Creating Images from an Embedded Resource - c#

This has been driving me crazy for the past 2 days, and anything close that I find just does not seem to work in my situation, perhaps someone can point out what I'm doing wrong.
I have a WPF project to which I've include a fairly large number of images(80ish). I've added them to the project into a folder called "Images". They are currently set to be embedded resources(though I've tried regular resources as well) but nothing seems to work.
I am attempting to create and load an ArrayList of type Image using these files as the source, but I'm failing pretty bad.
private void addPicture(string name)
{
string filePath = "pack://MyApp_WPF:,,,/Images/" + name + ".png";
Stream imageStream = assembly.GetManifestResourceStream(filePath);
Image curImage = new Image();
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = new Uri(filePath, UriKind.Relative);
bmpImage.EndInit();
curImage.Height = 60;
curImage.Stretch = Stretch.Uniform;
curImage.Source = bmpImage;
curImage.Margin = new Thickness(5);
imageList.Add(curImage);
}
It was much easier to do in my windows form application, but I just cant figure it out with WPF... Any help besides links to resources would be nice, because chances are at this point I've already read them.

First thing to note is that there is an DownloadError event that you ought to subscribe to, this might explain what is happening and why (though sometimes the error message is rather generic); the next is that you might not need the pack:// URI construct with images build actions of Resource:
var bmpImage = new BitmapImage(new Uri(
string.Format("/Images/{0}.png", name", UriKind.Relative));

The Pack URI is wrong, where you name your assembly you should place an authority, in this case application, i.e.
string filePath = "pack://application:,,,/Images/" + name + ".png";

Related

C# - How can I have a dynamic Image / BitmapSource accessible from XAML?

In my C# project I have a list of images which are resources compiled in the exe:
/Pics/Image1.png
/Pics/Image2.png
/Pics/Image3.png
...
In my code I process the images to match them to the theme of the application. The issue I am having is that I am trying to figure out an easy way to access these processed images in the XAML syntax.
This is how I typically access a resource image (pre-processed):
<Image Source="/Pics/Image1.png" />
So I would really like to access these processed images a similar way.
I tried a static dictionary like this:
<Image Source="{x:Static local:Theme.Images.ImageDictionary[/Pics/Image1.png]}" />
But this threw an error because it doesn't like the ".png", I haven't been able to get this working with dictionary keys. Not to mention this looks really ugly.
Ideally I would love to be able to "replace" the resource references, or create a resource at runtime (e.g. PicsProcessed/Image1.png) but haven't been able to figure a way to add or modify resources in a running C# application programmatically.
Any suggestions are really appreciated - thank you!
Have you tried creating a Bitmap then setting it as the image source? I think this should be easy. Give your image a name, say theImage. You can't possibly reference the image without giving it a name.
Try the following:
string path="/Pics/Image3.png";//path to the image
var bitmapImage=new Bitmap(new Uri(path));
theImage.source=bitmapImage;//set the bitmap as the source.
There are other ways you can achieve this though. Hope this helps?
It took a couple of days but I figured out a solution!
I moved all my images into another C# Project in the same solution, set to compile as a Class Libary DLL file called DynamicResources.dll (assembly name in the Project settings is "DynamicResources"). This project is added as a reference to the main project. As such I can access images in the XAML - clean and tidy:
<Image Source="/DynamicResources;component/pics/image1.png" />
Then in the post-build event for the main project, I rename the compiled .dll so it doesn't get loaded by the main .exe binary at launch:
copy "$(TargetDir)DynamicResources.dll" "$(TargetDir)DynamicResources.temp"
del "$(TargetDir)DynamicResources.dll"
Then I used a third-party library called Mono.Cecil to load the DynamicResources.temp file (DLL format), replace the resources, write it back to memory, then tell the application to load it:
public static void UpdateAssembly()
{
string dllFile = "DynamicResources.temp";
string dllNamespace = "DynamicResources";
var asm = AssemblyDefinition.ReadAssembly(dllFile);
var module = asm.Modules.FirstOrDefault();
var resources = module.Resources;
var dllResource = (EmbeddedResource)(resources.FirstOrDefault());
var dllResourceReader = new ResourceReader(dllResource.GetResourceStream());
var newResourceOutputStream = new MemoryStream();
var newResourceWriter = new ResourceWriter(newResourceOutputStream);
foreach (DictionaryEntry dllResourceEntry in dllResourceReader)
{
var image = (BitmapSource)new ImageSourceConverter().ConvertFrom(dllResourceEntry.Value);
Color foreground = (Color)ColorConverter.ConvertFromString("#FFFFFF");
var processed = (WriteableBitmap)ColorizeImage(image, foreground); // Your image processing function ?
newResourceWriter.AddResource(dllResourceEntry.Key.ToString(), BitmapToByte(processed));
}
newResourceWriter.Close();
var newResource = new EmbeddedResource(dllResource.Name, dllResource.Attributes, newResourceOutputStream.ToArray());
module.Resources.Remove(dllResource);
module.Resources.Add(newResource);
var woutput = new MemoryStream();
asm.Write(woutput);
var doutput = woutput.ToArray();
Assembly assembly = Assembly.Load(doutput);
}
public static MemoryStream BitmapToByte(BitmapSource bitmapSource)
{
var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
var frame = System.Windows.Media.Imaging.BitmapFrame.Create(bitmapSource);
encoder.Frames.Add(frame);
var stream = new MemoryStream();
encoder.Save(stream);
return stream;
}
public static void AttachAssembly(string myAsmFileName)
{
Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + myAsmFileName); // LoadFrom
AppDomain.CurrentDomain.Load(assembly.GetName());
}
Important note: When iterating through resources, they become lowercase, so you must use lowercase file and folder names.

How to get a System.Drawing.Image object from image which build action is marked as Resource?

I have a wpf app,and got a image useful for codebehind which's location in the project is something like "projectName\images\pp.png" and its build action is "Resource"(Node:not Embedded Resource).
I need a System.Drawing.Image object in the codebehind.
I tried these methods:
1.
var img = new BitmapImage(new Uri(#"\images\pp.png", UriKind.Relative));
var stream = img.StreamSource;
System.Drawing.Image needObj = Image.FromStream(stream);
i got a null stream,so it's not work.
2.
private static System.IO.Stream getResource(string name)
{
var assembly = Assembly.GetExecutingAssembly();
string resName = assembly.GetName().Name + ".g.resources";
return assembly.GetManifestResourceStream(resName);
}
var stream = getResource(#"\images\pp.png");
System.Drawing.Image needObj = Image.FromStream(stream);
i got an UnmanagedMemoryStream object,and an InvalidArgument exception occurred while calling "Image.FromStream(stream)" .
Could anyone tell me why the two methods above not working or how to achieve it ?
WPF - Get an Image Resource and Convert to System.Drawing.Image
var bitmapImage = new BitmapImage(new Uri(#"pack://application:,,,/"
+ Assembly.GetExecutingAssembly().GetName().Name
+ ";component/"
+ "images/pp.png", UriKind.Absolute));
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapImage)bitmapImage));
var stream = new MemoryStream();
encoder.Save(stream);
stream.Flush();
var image = new System.Drawing.Bitmap(stream);
Note:
Use "/" instead of "\"
Consider reading Pack URIs in WPF (important part: Resource File Pack URIs)
Add reference to system.drawing.dll
Local Assembly Resource File
The pack URI for a resource file that is compiled into the local
assembly uses the following authority and path:
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.Ext
Windows Forms - Get an image embedded resource:
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var stream= assembly.GetManifestResourceStream("YourAssemblyName.images.pp.png");
var image = Image.FromStream(stream);
Note:
"YourAssemblyName.images.pp.png" is case sensitive
Instead of YourAssemblyName put your assembly name, for example for my project, it is my project name and also my default namespace.
If you are not sure what exactly pass to GetManifestResourceStram use the code below:
Find embedded resource names:
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
assembly.GetManifestResourceNames()
.Where(x => x.EndsWith("pp.png")) //Comment this line to find all resource names
.ToList()
.ForEach(resource =>
{
MessageBox.Show(resource);
});

How to make the Bitmap Constructor take a string

I know this question has been asked before, but i couldnt find an answer for my specific situation. Im trying to create new bitmap from a resource image.
private void button1_Click(object sender, EventArgs e)
{
string test = "meridian_am";
string resources = "Resources.Properties.Resources." + test;
var master = new Bitmap(Resources.Properties.Resources.master);
var meridian_am = new Bitmap(resources);
using (Graphics g = Graphics.FromImage(master))
{
g.DrawImageUnscaled(meridian_am, 114, 332);
}
}
for some reason, for the *var meridian_am = new Bitmap(resources)* im getting an invalid parameter error.. Ultimately, i would rather do a string concatenation on the fly, as in var meridian_am = new Bitmap(Resources.Properties.Resources. + test), but for some reason that wont work... Any ideas?
I'm no expert in C#, but... for var master = ... you're passing a resource that might well be an Image or something like that, while for var meridian = ... you're passing a string as the parameter, which should be the path to an accessible file.
Hope that helps.
EDIT:
I'm talking this constructor versus this one.
Does Resources.Properties.Resources.master contain image bytes or string (path to file name)? In any case you can't pass raw string "Resources.Properties.Resources.meridian_am" to Bitmap constructor. It treats it as path to file, not your resource.
You should load data from resources by this name before. Something like that (if your resource contain image bytes):
var assembly = System.Reflection.Assembly.GetEntryAssembly();
var resources = assembly.GetManifestResourceStream("Resources.Properties.Resources." + test);

Get IsolatedStorage path for ShareMediaTask in WP8

I have been attempting to use a saved image in IsolatedStorage within the new ShareMediaTask in Windows Phone 8. I am having issues getting an image path from IsolatedStorage. I have successfully used the ShareMediaTask from the result of CameraCaptureTask as exampled in http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207027(v=vs.105).aspx but I am unsure of how to get the path from IsolatedStorage in wp8.
I was attempting to retrieved an image path using something of the following:
//Combine the directory and file name
filePath = Path.Combine(IsolatedStoragePath, fileName);
Uri uri = new Uri(#"isostore:" + filePath, UriKind.Absolute);
_shareTask = new ShareMediaTask();
//_shareTask.FilePath = #"isostore:" + filePath;
_shareTask.FilePath = uri.ToString();
_shareTask.Show();
Not sure if I'm headed in the right direction or not with this, any advice, assistance, or references would be greatly appreciated! The only similiar link I've found uses xna which I must avoid for this application http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/56c91aa1-26ea-41f7-b5ac-035537419faf/ .
I think the best you can do is to save the photo do MediaLibrary, share it and the delete it immediately after sharing.
your idea i working But after save image we are not able delete image because WP OS not give permission to delete other app item
var mediaLibrary = new Microsoft.Xna.Framework.Media.MediaLibrary();
var location = mediaLibrary.SavePicture(tempJpeg + ".jpg", e.Result);
string Path = location.GetPath();
ShareMediaTask SMT = new ShareMediaTask();
SMT.FilePath = Path;
SMT.Show();

Path to an embedded resource file

I have an icon in my resource file , which I want to reference.
This is the code that needs that path to an icon file:
IWshRuntimeLibrary.IWshShortcut MyShortcut ;
MyShortcut = (IWshRuntimeLibrary.IWshShortcut)WshShell.CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + #"\PerfectUpload.lnk");
MyShortcut.IconLocation = //path to icons path . Works if set to #"c:/icon.ico"
Instead of having an external icon file I want it to find an embedded icon file.
Something like
MyShortcut.IconLocation = Path.GetFullPath(global::perfectupload.Properties.Resources.finish_perfect1.ToString()) ;
is this possible ? if so how ?
Thanks
I think this should work, but I can't remember exactly (not at work to double check).
MyShortcut.IconLocation = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("YourNamespace.IconFilename.ico");
Just expanding on SharpUrBrain's answer, which didn't work for me, instead of:
if (null != stream)
{
//Fetch image from stream.
MyShortcut.IconLocation = System.Drawing.Image.FromStream(stream);
}
It should be something like:
if (null != stream)
{
string temp = Path.GetTempFileName();
System.Drawing.Image.FromStream(stream).Save(temp);
shortcut.IconLocation = temp;
}
I think it will help you in some what...
//Get the assembly.
System.Reflection.Assembly CurrAssembly = System.Reflection.Assembly.LoadFrom(System.Windows.Forms.Application.ExecutablePath);
//Gets the image from Images Folder.
System.IO.Stream stream = CurrAssembly.GetManifestResourceStream("ImageURL");
if (null != stream)
{
//Fetch image from stream.
MyShortcut.IconLocation = System.Drawing.Image.FromStream(stream);
}
The res protocol may be able to help you with this: http://msdn.microsoft.com/en-us/library/aa767740(v=vs.85).aspx
In WPF I have done this before:
Uri TweetyUri = new Uri(#"/Resources/MyIco.ico", UriKind.Relative);
System.IO.Stream IconStream = Application.GetResourceStream(TweetyUri).Stream;
NotifyIcon.Icon = new System.Drawing.Icon(IconStream);
The resource it is embedded, so incapsulated in a DLL assembly. So you cannot get its real path, you have to change your approach.
You would probably want to load the resource in memory and write it down to a temp file, then link it from there. Once the icon is is changed on the destination file, you can delete the icon file itself.

Categories

Resources