public static IntPtr GenerateHICON(ImageSource image, Size dimensions) { if (image == null) { return(IntPtr.Zero); } // If we're getting this from a ".ico" resource, then it comes through as a BitmapFrame. // We can use leverage this as a shortcut to get the right 16x16 representation // because DrawImage doesn't do that for us. if (image is BitmapFrame bf) { bf = GetBestMatch(bf.Decoder.Frames, (int)dimensions.Width, (int)dimensions.Height); } else { // Constrain the dimensions based on the aspect ratio. var drawingDimensions = new Rect(0, 0, dimensions.Width, dimensions.Height); // There's no reason to assume that the requested image dimensions are square. var renderRatio = dimensions.Width / dimensions.Height; var aspectRatio = image.Width / image.Height; // If it's smaller than the requested size, then place it in the middle and pad the image. if (image.Width <= dimensions.Width && image.Height <= dimensions.Height) { drawingDimensions = new Rect((dimensions.Width - image.Width) / 2, (dimensions.Height - image.Height) / 2, image.Width, image.Height); } else if (renderRatio > aspectRatio) { var scaledRenderWidth = image.Width / image.Height * dimensions.Width; drawingDimensions = new Rect((dimensions.Width - scaledRenderWidth) / 2, 0, scaledRenderWidth, dimensions.Height); } else if (renderRatio < aspectRatio) { var scaledRenderHeight = image.Height / image.Width * dimensions.Height; drawingDimensions = new Rect(0, (dimensions.Height - scaledRenderHeight) / 2, dimensions.Width, scaledRenderHeight); } var dv = new DrawingVisual(); var dc = dv.RenderOpen(); dc.DrawImage(image, drawingDimensions); dc.Close(); var bmp = new RenderTargetBitmap((int)dimensions.Width, (int)dimensions.Height, 96, 96, PixelFormats.Pbgra32); bmp.Render(dv); bf = BitmapFrame.Create(bmp); } // Using GDI+ to convert to an HICON. // I'd rather not duplicate their code. using (var memstm = new MemoryStream()) { BitmapEncoder enc = new PngBitmapEncoder(); enc.Frames.Add(bf); enc.Save(memstm); using (var istm = new ManagedIStream(memstm)) { // We are not bubbling out GDI+ errors when creating the native image fails. var bitmap = IntPtr.Zero; try { var gpStatus = NativeMethods.GdipCreateBitmapFromStream(istm, out bitmap); if (Status.Ok != gpStatus) { return(IntPtr.Zero); } gpStatus = NativeMethods.GdipCreateHICONFromBitmap(bitmap, out var hicon); return(Status.Ok != gpStatus ? IntPtr.Zero : hicon); // Caller is responsible for freeing this. } finally { Utility.SafeDisposeImage(ref bitmap); } } } }
public static IntPtr GenerateHICON(ImageSource image, Size dimensions) { if (image == null) { return(IntPtr.Zero); } BitmapFrame bitmapFrame = image as BitmapFrame; if (bitmapFrame != null) { bitmapFrame = Utility.GetBestMatch(bitmapFrame.Decoder.Frames, (int)dimensions.Width, (int)dimensions.Height); } else { Rect rectangle = new Rect(0.0, 0.0, dimensions.Width, dimensions.Height); double num = dimensions.Width / dimensions.Height; double num2 = image.Width / image.Height; if (image.Width <= dimensions.Width && image.Height <= dimensions.Height) { rectangle = new Rect((dimensions.Width - image.Width) / 2.0, (dimensions.Height - image.Height) / 2.0, image.Width, image.Height); } else if (num > num2) { double num3 = image.Width / image.Height * dimensions.Width; rectangle = new Rect((dimensions.Width - num3) / 2.0, 0.0, num3, dimensions.Height); } else if (num < num2) { double num4 = image.Height / image.Width * dimensions.Height; rectangle = new Rect(0.0, (dimensions.Height - num4) / 2.0, dimensions.Width, num4); } DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); drawingContext.DrawImage(image, rectangle); drawingContext.Close(); RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((int)dimensions.Width, (int)dimensions.Height, 96.0, 96.0, PixelFormats.Pbgra32); renderTargetBitmap.Render(drawingVisual); bitmapFrame = BitmapFrame.Create(renderTargetBitmap); } IntPtr result; using (MemoryStream memoryStream = new MemoryStream()) { new PngBitmapEncoder { Frames = { bitmapFrame } }.Save(memoryStream); using (ManagedIStream managedIStream = new ManagedIStream(memoryStream)) { IntPtr zero = IntPtr.Zero; try { Status status = NativeMethods.GdipCreateBitmapFromStream(managedIStream, out zero); if (status != Status.Ok) { result = IntPtr.Zero; } else { IntPtr intPtr; status = NativeMethods.GdipCreateHICONFromBitmap(zero, out intPtr); if (status != Status.Ok) { result = IntPtr.Zero; } else { result = intPtr; } } } finally { Utility.SafeDisposeImage(ref zero); } } } return(result); }