Create a System.Windows.Media.ImageSource From an Icon File in c#? - c#

I am programming in a WPF application in c#. I need to change the notifier icon sometimes;
I implemented the icon like this:
<tn:NotifyIcon x:Name="MyNotifyIcon"
Text="Title"
Icon="Resources/logo/Error.ico"/>
My solution is changing the Icon, the type of MyNotifyIcon.Icon is ImageSource, and I want to get by an icon file. I could find the way to do that.
Do somebody have some ideas how? Or have the any other solution?
Shortly, I have an address like /Resource/logo.icon, and I wanna get a System.Windows.Media.ImageSource

You can use the BitmapImage class:
// Create the source
BitmapImage img = new BitmapImage();
img.BeginInit();
img.UriSource = new Uri("./Resource/logo/logo.icon");
img.EndInit();
BitmapImage class inherits from ImageSource class which means you can pass the BitmapImage object to NotifyIcon.Icon as:
NI.Icon = img;

Are you using the NotifyIcon from the Hardcodet.Wpf.TaskbarNotification namespace created by Philipp Sumi? If so you have the option to either specify the icon as an ImageSource or an Icon.
TaskbarIcon notifyIcon = new TaskbarIcon();
// set using Icon
notifyIcon.Icon = some System.Drawing.Icon;
// set using ImageSource
notifyIcon.IconSource = some System.Windows.Media.ImageSource;
Note that internally setting IconSource sets Icon.
To set from a resource.
notifyIcon.Icon = MyNamespace.Properties.Resources.SomeIcon

have you thought in do it with resources?
To get from resources:
MainNameSpace.Properties.Resources.NameOfIconFileInResources;
Put the icons in resources, if you have the image file (not icon) i have a method to change it:
public static Icon toIcon(Bitmap b)
{
Bitmap cb = (Bitmap) b.Clone();
cb.MakeTransparent(Color.White);
System.IntPtr p = cb.GetHicon();
Icon ico = Icon.FromHandle(p);
return ico;
}
And programmatically change it with the known attribute .Icon;
Don't worry about ImageSource type.
Extracting image from icon (.ico) file:
Stream iconStream = new FileStream (MainNameSpace.Properties.Resources.NameOfIconFileINResources, FileMode.Open );
IconBitmapDecoder decoder = new IconBitmapDecoder (
iconStream,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.None );
// loop through images inside the file
foreach ( var item in decoder.Frames )
{
//Do whatever you want to do with the single images inside the file
this.panel.Children.Add ( new Image () { Source = item } );
}
// or just get exactly the 4th image:
var frame = decoder.Frames[3];
// save file as PNG
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(frame);
using ( Stream saveStream = new FileStream ( #"C:\target.png", FileMode.Create ))
{
encoder.Save( saveStream );
}
But you must put the .ico file in resources, or take it with relative path...
Taken from How can you access icons from a Multi-Icon (.ico) file using index in C#

Related

Deleting a file with File.Delete throws System.IO.IOException [duplicate]

I'm trying create a user perfil edit window, in this window has a Image control
When I selected a image file, it will show in this Image control and copy this file at my image folder, first time is all right, but second time, it show a error
"The process cannot access the file 'C:\1.jpg' because it is being used by another process."
I think it is because my Image control is using this file, so, I don't know what can I do
private void Select_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog od = new OpenFileDialog();
if (od.ShowDialog() == true)
{
string imageLocal = #"C:/1.jpg";
File.Copy(od.FileName, imageLocal, true);
image1.Source = new BitmapImage(new Uri(imageLocal));
}
}
If you want to load and display an image, and keep the file amenable to operations in the file system (like reloading it or moving it to another directory), the Uri constructor will not work because (as you point out), the BitmapImage class hangs on to the file handle.
Instead, use a method like this...
private static BitmapImage ByStream(FileInfo info)
{ //http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/dee7cb68-aca3-402b-b159-2de933f933f1
try
{
if (info.Exists)
{
// do this so that the image file can be moved in the file system
BitmapImage result = new BitmapImage();
// Create new BitmapImage
Stream stream = new MemoryStream(); // Create new MemoryStream
Bitmap bitmap = new Bitmap(info.FullName);
// Create new Bitmap (System.Drawing.Bitmap) from the existing image file
(albumArtSource set to its path name)
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
// Save the loaded Bitmap into the MemoryStream - Png format was the only one I
tried that didn't cause an error (tried Jpg, Bmp, MemoryBmp)
bitmap.Dispose(); // Dispose bitmap so it releases the source image file
result.BeginInit(); // Begin the BitmapImage's initialisation
result.StreamSource = stream;
// Set the BitmapImage's StreamSource to the MemoryStream containing the image
result.EndInit(); // End the BitmapImage's initialisation
return result; // Finally, set the WPF Image component's source to the
BitmapImage
}
return null;
}
catch
{
return null;
}
}
This method takes a FileInfo and returns a BitmapImage which you can display and simultaneously move it to another directory or display it again.
A much simpler method, copied from another answer below, is this:
public static BitmapImage LoadBitmapImage(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
The method shown below loads a BitmapImage from file and immediately closes the file after loading. Note that it is necessary to set the BitmapCacheOption.OnLoad flag when the source stream is closed right after EndInit.
public static BitmapImage LoadBitmapImage(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze(); // just in case you want to load the image in another thread
return bitmapImage;
}
}
This code will work for any image format that is supported by WPF. When passing the image file content as stream to the StreamSource property, WPF will automatically create the appropriate decoder.
Very simple solution:
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
File.Copy(od.FileName, imageLocal, true);

Image file copy, is being used by another process

I'm trying create a user perfil edit window, in this window has a Image control
When I selected a image file, it will show in this Image control and copy this file at my image folder, first time is all right, but second time, it show a error
"The process cannot access the file 'C:\1.jpg' because it is being used by another process."
I think it is because my Image control is using this file, so, I don't know what can I do
private void Select_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog od = new OpenFileDialog();
if (od.ShowDialog() == true)
{
string imageLocal = #"C:/1.jpg";
File.Copy(od.FileName, imageLocal, true);
image1.Source = new BitmapImage(new Uri(imageLocal));
}
}
If you want to load and display an image, and keep the file amenable to operations in the file system (like reloading it or moving it to another directory), the Uri constructor will not work because (as you point out), the BitmapImage class hangs on to the file handle.
Instead, use a method like this...
private static BitmapImage ByStream(FileInfo info)
{ //http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/dee7cb68-aca3-402b-b159-2de933f933f1
try
{
if (info.Exists)
{
// do this so that the image file can be moved in the file system
BitmapImage result = new BitmapImage();
// Create new BitmapImage
Stream stream = new MemoryStream(); // Create new MemoryStream
Bitmap bitmap = new Bitmap(info.FullName);
// Create new Bitmap (System.Drawing.Bitmap) from the existing image file
(albumArtSource set to its path name)
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
// Save the loaded Bitmap into the MemoryStream - Png format was the only one I
tried that didn't cause an error (tried Jpg, Bmp, MemoryBmp)
bitmap.Dispose(); // Dispose bitmap so it releases the source image file
result.BeginInit(); // Begin the BitmapImage's initialisation
result.StreamSource = stream;
// Set the BitmapImage's StreamSource to the MemoryStream containing the image
result.EndInit(); // End the BitmapImage's initialisation
return result; // Finally, set the WPF Image component's source to the
BitmapImage
}
return null;
}
catch
{
return null;
}
}
This method takes a FileInfo and returns a BitmapImage which you can display and simultaneously move it to another directory or display it again.
A much simpler method, copied from another answer below, is this:
public static BitmapImage LoadBitmapImage(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
The method shown below loads a BitmapImage from file and immediately closes the file after loading. Note that it is necessary to set the BitmapCacheOption.OnLoad flag when the source stream is closed right after EndInit.
public static BitmapImage LoadBitmapImage(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze(); // just in case you want to load the image in another thread
return bitmapImage;
}
}
This code will work for any image format that is supported by WPF. When passing the image file content as stream to the StreamSource property, WPF will automatically create the appropriate decoder.
Very simple solution:
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
File.Copy(od.FileName, imageLocal, true);

How do I fill a rectangle with an ImageBrush using a file from the hard drive

I am trying to fill a rectangle with a file that I have saved to the hard drive. I know that I have to use a ImageBrush and I think I know how to do that if the image is an included resource. In this case the file is created and setting on the hard drive but when I try to use it with the code below the rectangle changes but it changes to show the form back color not the image as I had expected (almost as if the image is invisible).
using (dynamic CommonDialog = AutomationFactory.CreateObject("WIA.CommonDialog"))
{
dynamic imageFile = CommonDialog.ShowAcquireImage();
if (imageFile != null)
{
string filePath = string.Format("d:\\{0}.jpg", Guid.NewGuid());
imageFile.SaveFile(filePath);
rectangle2.Fill = new ImageBrush()
{
ImageSource = new BitmapImage(new Uri(filePath, UriKind.Absolute))
};
}
}
Update: I was able to get this to work by replacing the code block inside the If Then with the following:
{
string filePath = string.Format("d:\\{0}.jpg", Guid.NewGuid());
imageFile.SaveFile(filePath);
BitmapImage bitmapBase = new BitmapImage();
dynamic fileData = imageFile.FileData;
byte[] imageData = fileData.BinaryData;
MemoryStream ms = new MemoryStream(imageData);
bitmapBase.SetSource(ms);
WriteableBitmap writableBitmap = new WriteableBitmap(bitmapBase);
rectangle2.Fill = new ImageBrush() { ImageSource = (writableBitmap) };
}
When using Silverlight 4 you can create an out-of-browser application thatt can access (part of) the local disk.
See here how
You cannot access images, or any files, from a local drive (except for Isolated storage or a stream from a file open dialog). These are all security measures.
As you did not mention Out Of Browser I assume this is just a web/client app.

Find type of image in clipboard

I have an image copied to the clicpboard from the word using "Comment.Scope.CopyAsPicture()"
How can i find the type of this image in the clipboard, so that i can write the image with proper extension in local file system?
In DataFromats we have only Bitmap member...
normally you choose the format to store
IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(DataFormats.Bitmap))
{
Bitmap bitmap = (data.GetData(DataFormats.Bitmap,true) as Bitmap);
bitmap.Save("image.bmp",System.Drawing.Imaging.ImageFormat.Bmp);
bitmap.Save("image.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
}
but You can create Your own format and use it
DataFormats.Format jepgFormat = DataFormats.GetFormat("jpgFormat");
Image image = new Image();
DataObject myDataObject = new DataObject(jpegFormat.Name, image );
// Copies myObject into the clipboard.
Clipboard.SetDataObject(myDataObject);
Using DataFormats.Bitmap you can get this as a bitmap and use the framework functions to save it.
if (iData.GetDataPresent(DataFormats.Bitmap))
Bitmap bImg = (Bitmap)iData.GetData();

How to Clear an image control in WPF (C#)

I have an image control with a source image located in my c drive. I get a message that the image is being used by another process whenever I try to delete the original image to change it with another one dynamically. How do I release the image from the image control to be able to delete it.
I tried this variants:
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.SetValue(System.Windows.Controls.Image.SourceProperty, null);
File.Delete(path);
And:
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.Source = null;
File.Delete(path)
But it's not work...
Try setting the bitmap image through the stream source property. That way the app won't put a lock on the file since you loaded it through a stream.
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.streamsource(VS.85).aspx
//this function allows you to load an image from a file and release it
BitmapImage loadPhoto(string path)
{
BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.CacheOption = BitmapCacheOption.OnLoad;
bmi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bmi.UriSource = new Uri(path);
bmi.EndInit();
return bmi;
}

Categories

Resources