-
-
Save darkfall/1656050 to your computer and use it in GitHub Desktop.
class PngIconConverter | |
{ | |
/* input image with width = height is suggested to get the best result */ | |
/* png support in icon was introduced in Windows Vista */ | |
public static bool Convert(System.IO.Stream input_stream, System.IO.Stream output_stream, int size, bool keep_aspect_ratio = false) | |
{ | |
System.Drawing.Bitmap input_bit = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromStream(input_stream); | |
if (input_bit != null) | |
{ | |
int width, height; | |
if (keep_aspect_ratio) | |
{ | |
width = size; | |
height = input_bit.Height / input_bit.Width * size; | |
} | |
else | |
{ | |
width = height = size; | |
} | |
System.Drawing.Bitmap new_bit = new System.Drawing.Bitmap(input_bit, new System.Drawing.Size(width, height)); | |
if (new_bit != null) | |
{ | |
// save the resized png into a memory stream for future use | |
System.IO.MemoryStream mem_data = new System.IO.MemoryStream(); | |
new_bit.Save(mem_data, System.Drawing.Imaging.ImageFormat.Png); | |
System.IO.BinaryWriter icon_writer = new System.IO.BinaryWriter(output_stream); | |
if (output_stream != null && icon_writer != null) | |
{ | |
// 0-1 reserved, 0 | |
icon_writer.Write((byte)0); | |
icon_writer.Write((byte)0); | |
// 2-3 image type, 1 = icon, 2 = cursor | |
icon_writer.Write((short)1); | |
// 4-5 number of images | |
icon_writer.Write((short)1); | |
// image entry 1 | |
// 0 image width | |
icon_writer.Write((byte)width); | |
// 1 image height | |
icon_writer.Write((byte)height); | |
// 2 number of colors | |
icon_writer.Write((byte)0); | |
// 3 reserved | |
icon_writer.Write((byte)0); | |
// 4-5 color planes | |
icon_writer.Write((short)0); | |
// 6-7 bits per pixel | |
icon_writer.Write((short)32); | |
// 8-11 size of image data | |
icon_writer.Write((int)mem_data.Length); | |
// 12-15 offset of image data | |
icon_writer.Write((int)(6 + 16)); | |
// write image data | |
// png data must contain the whole png data file | |
icon_writer.Write(mem_data.ToArray()); | |
icon_writer.Flush(); | |
return true; | |
} | |
} | |
return false; | |
} | |
return false; | |
} | |
public static bool Convert(string input_image, string output_icon, int size, bool keep_aspect_ratio = false) | |
{ | |
System.IO.FileStream input_stream = new System.IO.FileStream(input_image, System.IO.FileMode.Open); | |
System.IO.FileStream output_stream = new System.IO.FileStream(output_icon, System.IO.FileMode.OpenOrCreate); | |
bool result = Convert(input_stream, output_stream, size, keep_aspect_ratio); | |
input_stream.Close(); | |
output_stream.Close(); | |
return result; | |
} | |
} |
thank you very much dude , it's working well on converting , png to ico
Fail fast, less indentation.
public static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="input">The input stream</param>
/// <param name="output">The output stream</param>
/// <param name="size">The size (16x16 px by default)</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon( Stream input, Stream output, int size = 16, bool preserveAspectRatio = false )
{
var inputBitmap = (Bitmap)Bitmap.FromStream( input );
if( inputBitmap == null )
return false;
int width = size, height = size;
if( preserveAspectRatio )
{
width = size;
height = inputBitmap.Height / inputBitmap.Width * size;
}
var newBitmap = new Bitmap( inputBitmap, new Size( width, height ) );
if( newBitmap == null )
return false;
// save the resized png into a memory stream for future use
using( MemoryStream memoryStream = new MemoryStream() )
{
newBitmap.Save( memoryStream, ImageFormat.Png );
var iconWriter = new BinaryWriter( output );
if( output == null || iconWriter == null )
return false;
// 0-1 reserved, 0
iconWriter.Write( (byte)0 );
iconWriter.Write( (byte)0 );
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write( (short)1 );
// 4-5 number of images
iconWriter.Write( (short)1 );
// image entry 1
// 0 image width
iconWriter.Write( (byte)width );
// 1 image height
iconWriter.Write( (byte)height );
// 2 number of colors
iconWriter.Write( (byte)0 );
// 3 reserved
iconWriter.Write( (byte)0 );
// 4-5 color planes
iconWriter.Write( (short)0 );
// 6-7 bits per pixel
iconWriter.Write( (short)32 );
// 8-11 size of image data
iconWriter.Write( (int)memoryStream.Length );
// 12-15 offset of image data
iconWriter.Write( (int)(6 + 16) );
// write image data
// png data must contain the whole png data file
iconWriter.Write( memoryStream.ToArray() );
iconWriter.Flush();
}
return true;
}
}
Thanks.
Thanks
Preserve Aspect Ratio fixed.
Thanks so much for this code, it works amazing!
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
/// <summary>
/// Provides helper methods for imaging
/// </summary>
public static class IconHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="input">The input stream</param>
/// <param name="output">The output stream</param>
/// <param name="size">Needs to be a factor of 2 (16x16 px by default)</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false)
{
var inputBitmap = (Bitmap)Bitmap.FromStream(input);
if (inputBitmap == null)
return false;
float width = size, height = size;
if (preserveAspectRatio)
{
if (inputBitmap.Width > inputBitmap.Height)
height = ((float)inputBitmap.Height / inputBitmap.Width) * size;
else
width = ((float)inputBitmap.Width / inputBitmap.Height) * size;
}
var newBitmap = new Bitmap(inputBitmap, new Size((int)width, (int)height));
if (newBitmap == null)
return false;
// save the resized png into a memory stream for future use
using (MemoryStream memoryStream = new MemoryStream())
{
newBitmap.Save(memoryStream, ImageFormat.Png);
var iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write((int)(6 + 16));
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
}
return true;
}
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="inputPath">The input path</param>
/// <param name="outputPath">The output path</param>
/// <param name="size">Needs to be a factor of 2 (16x16 px by default)</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false)
{
using (FileStream inputStream = new FileStream(inputPath, FileMode.Open))
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
}
}
}
thank you so much
Thank you!
Wrapper added: converting Image object to Ico byte array.
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
/// <summary>
/// Provides helper methods for imaging
/// </summary>
public static class IconHelper
{
/// <summary>
/// Converts a PNG image to an icon (ico)
/// </summary>
/// <param name="input">The input stream</param>
/// <param name="output">The output stream</param>
/// <param name="size">Needs to be a factor of 2 (16x16 px by default)</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false)
{
var inputBitmap = (Bitmap)Bitmap.FromStream(input);
if (inputBitmap == null)
return false;
float width = size, height = size;
if (preserveAspectRatio)
{
if (inputBitmap.Width > inputBitmap.Height)
height = ((float)inputBitmap.Height / inputBitmap.Width) * size;
else
width = ((float)inputBitmap.Width / inputBitmap.Height) * size;
}
var newBitmap = new Bitmap(inputBitmap, new Size((int)width, (int)height));
if (newBitmap == null)
return false;
// save the resized png into a memory stream for future use
using (MemoryStream memoryStream = new MemoryStream())
{
newBitmap.Save(memoryStream, ImageFormat.Png);
var iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)1);
// image entry 1
// 0 image width
iconWriter.Write((byte)width);
// 1 image height
iconWriter.Write((byte)height);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)memoryStream.Length);
// 12-15 offset of image data
iconWriter.Write((int)(6 + 16));
// write image data
// png data must contain the whole png data file
iconWriter.Write(memoryStream.ToArray());
iconWriter.Flush();
}
return true;
}
/// <summary>
/// Converts a PNG image to an icon (ico)
/// </summary>
/// <param name="inputPath">The input path</param>
/// <param name="outputPath">The output path</param>
/// <param name="size">Needs to be a factor of 2 (16x16 px by default)</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false)
{
using (FileStream inputStream = new FileStream(inputPath, FileMode.Open))
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio);
}
}
/// <summary>
/// Converts a PNG image to an icon (ico)
/// </summary>
/// <param name="inputPath">Image object</param>
/// <param name="preserveAspectRatio">Preserve the aspect ratio</param>
/// <returns>ico byte array / null for error</returns>
public static byte[] ConvertToIcon(Image image, bool preserveAspectRatio = false)
{
MemoryStream inputStream = new MemoryStream();
image.Save(inputStream, ImageFormat.Png);
inputStream.Seek(0, SeekOrigin.Begin);
MemoryStream outputStream = new MemoryStream();
int size = image.Size.Width;
if (!ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio))
{
return null;
}
return outputStream.ToArray();
}
}
This was super useful to me. I modified it to create multiple images in one ico of varying sizes.
/// <summary>
/// Adapted from this gist: https://gist.github.com/darkfall/1656050
/// Provides helper methods for imaging
/// </summary>
public static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico) with all the sizes windows likes
/// </summary>
/// <param name="inputBitmap">The input bitmap</param>
/// <param name="output">The output stream</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Bitmap inputBitmap, Stream output)
{
if (inputBitmap == null)
return false;
int[] sizes = new int[] { 256, 48, 32, 16 };
// Generate bitmaps for all the sizes and toss them in streams
List<MemoryStream> imageStreams = new List<MemoryStream>();
foreach (int size in sizes)
{
Bitmap newBitmap = ResizeImage(inputBitmap, size, size);
if (newBitmap == null)
return false;
MemoryStream memoryStream = new MemoryStream();
newBitmap.Save(memoryStream, ImageFormat.Png);
imageStreams.Add(memoryStream);
}
BinaryWriter iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;
int offset = 0;
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)sizes.Length);
offset += 6 + (16 * sizes.Length);
for (int i = 0; i < sizes.Length; i++)
{
// image entry 1
// 0 image width
iconWriter.Write((byte)sizes[i]);
// 1 image height
iconWriter.Write((byte)sizes[i]);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)imageStreams[i].Length);
// 12-15 offset of image data
iconWriter.Write((int)offset);
offset += (int)imageStreams[i].Length;
}
for (int i = 0; i < sizes.Length; i++)
{
// write image data
// png data must contain the whole png data file
iconWriter.Write(imageStreams[i].ToArray());
imageStreams[i].Close();
}
iconWriter.Flush();
return true;
}
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="input">The input stream</param>
/// <param name="output">The output stream</param
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Stream input, Stream output)
{
Bitmap inputBitmap = (Bitmap)Bitmap.FromStream(input);
return ConvertToIcon(inputBitmap, output);
}
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="inputPath">The input path</param>
/// <param name="outputPath">The output path</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(string inputPath, string outputPath)
{
using (FileStream inputStream = new FileStream(inputPath, FileMode.Open))
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(inputStream, outputStream);
}
}
/// <summary>
/// Converts an image to a icon (ico)
/// </summary>
/// <param name="inputImage">The input image</param>
/// <param name="outputPath">The output path</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Image inputImage, string outputPath)
{
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(new Bitmap(inputImage), outputStream);
}
}
/// <summary>
/// Resize the image to the specified width and height.
/// Found on stackoverflow: https://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
}
Thank you 👍
This was super useful to me. I modified it to create multiple images in one ico of varying sizes.
/// <summary> /// Adapted from this gist: https://gist.github.com/darkfall/1656050 /// Provides helper methods for imaging /// </summary> public static class ImagingHelper { /// <summary> /// Converts a PNG image to a icon (ico) with all the sizes windows likes /// </summary> /// <param name="inputBitmap">The input bitmap</param> /// <param name="output">The output stream</param> /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(Bitmap inputBitmap, Stream output) { if (inputBitmap == null) return false; int[] sizes = new int[] { 256, 48, 32, 16 }; // Generate bitmaps for all the sizes and toss them in streams List<MemoryStream> imageStreams = new List<MemoryStream>(); foreach (int size in sizes) { Bitmap newBitmap = ResizeImage(inputBitmap, size, size); if (newBitmap == null) return false; MemoryStream memoryStream = new MemoryStream(); newBitmap.Save(memoryStream, ImageFormat.Png); imageStreams.Add(memoryStream); } BinaryWriter iconWriter = new BinaryWriter(output); if (output == null || iconWriter == null) return false; int offset = 0; // 0-1 reserved, 0 iconWriter.Write((byte)0); iconWriter.Write((byte)0); // 2-3 image type, 1 = icon, 2 = cursor iconWriter.Write((short)1); // 4-5 number of images iconWriter.Write((short)sizes.Length); offset += 6 + (16 * sizes.Length); for (int i = 0; i < sizes.Length; i++) { // image entry 1 // 0 image width iconWriter.Write((byte)sizes[i]); // 1 image height iconWriter.Write((byte)sizes[i]); // 2 number of colors iconWriter.Write((byte)0); // 3 reserved iconWriter.Write((byte)0); // 4-5 color planes iconWriter.Write((short)0); // 6-7 bits per pixel iconWriter.Write((short)32); // 8-11 size of image data iconWriter.Write((int)imageStreams[i].Length); // 12-15 offset of image data iconWriter.Write((int)offset); offset += (int)imageStreams[i].Length; } for (int i = 0; i < sizes.Length; i++) { // write image data // png data must contain the whole png data file iconWriter.Write(imageStreams[i].ToArray()); imageStreams[i].Close(); } iconWriter.Flush(); return true; } /// <summary> /// Converts a PNG image to a icon (ico) /// </summary> /// <param name="input">The input stream</param> /// <param name="output">The output stream</param /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(Stream input, Stream output) { Bitmap inputBitmap = (Bitmap)Bitmap.FromStream(input); return ConvertToIcon(inputBitmap, output); } /// <summary> /// Converts a PNG image to a icon (ico) /// </summary> /// <param name="inputPath">The input path</param> /// <param name="outputPath">The output path</param> /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(string inputPath, string outputPath) { using (FileStream inputStream = new FileStream(inputPath, FileMode.Open)) using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate)) { return ConvertToIcon(inputStream, outputStream); } } /// <summary> /// Converts an image to a icon (ico) /// </summary> /// <param name="inputImage">The input image</param> /// <param name="outputPath">The output path</param> /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(Image inputImage, string outputPath) { using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate)) { return ConvertToIcon(new Bitmap(inputImage), outputStream); } } /// <summary> /// Resize the image to the specified width and height. /// Found on stackoverflow: https://stackoverflow.com/questions/1922040/resize-an-image-c-sharp /// </summary> /// <param name="image">The image to resize.</param> /// <param name="width">The width to resize to.</param> /// <param name="height">The height to resize to.</param> /// <returns>The resized image.</returns> public static Bitmap ResizeImage(Image image, int width, int height) { var destRect = new Rectangle(0, 0, width, height); var destImage = new Bitmap(width, height); destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); using (var graphics = Graphics.FromImage(destImage)) { graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; using (var wrapMode = new ImageAttributes()) { wrapMode.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode); } } return destImage; } }
I use your code to create a icon including some sizes like 3232, 4848, 256*256. But if I use var bmp = (Bitmap)Image.FromFile(iconFilePath).Clone()
, it failed, shows"GDI+ error". So how to open the icon file correctly?
This is absolutely perfect!
Converted the logic to PowerShell,
function ConvertTo-Icon
{
<#
.Synopsis
Converts image to icons
.Description
Converts an image to an icon
.Example
ConvertTo-Icon -File .\Logo.png -OutputFile .\Favicon.ico
#>
[CmdletBinding()]
param(
# The file
[Parameter(Mandatory=$true, Position=0,ValueFromPipelineByPropertyName=$true)]
[Alias('Fullname')]
[string]$File,
# If provided, will output the icon to a location
[Parameter(Position=1, ValueFromPipelineByPropertyName=$true)]
[string]$OutputFile
)
begin {
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
}
process {
#region Load Icon
$resolvedFile = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($file)
if (-not $resolvedFile) { return }
$inputBitmap = [Drawing.Image]::FromFile($resolvedFile)
$width = $inputBitmap.Width
$height = $inputBitmap.Height
$size = New-Object Drawing.Size $width, $height
$newBitmap = New-Object Drawing.Bitmap $inputBitmap, $size
#endregion Load Icon
#region Save Icon
$memoryStream = New-Object System.IO.MemoryStream
$newBitmap.Save($memoryStream, [System.Drawing.Imaging.ImageFormat]::Png)
$resolvedOutputFile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($outputFile)
$output = [IO.File]::Create("$resolvedOutputFile")
$iconWriter = New-Object System.IO.BinaryWriter($output)
# 0-1 reserved, 0
$iconWriter.Write([byte]0)
$iconWriter.Write([byte]0)
# 2-3 image type, 1 = icon, 2 = cursor
$iconWriter.Write([short]1);
# 4-5 number of images
$iconWriter.Write([short]1);
# image entry 1
# 0 image width
$iconWriter.Write([byte]$width);
# 1 image height
$iconWriter.Write([byte]$height);
# 2 number of colors
$iconWriter.Write([byte]0);
# 3 reserved
$iconWriter.Write([byte]0);
# 4-5 color planes
$iconWriter.Write([short]0);
# 6-7 bits per pixel
$iconWriter.Write([short]32);
# 8-11 size of image data
$iconWriter.Write([int]$memoryStream.Length);
# 12-15 offset of image data
$iconWriter.Write([int](6 + 16));
# write image data
# png data must contain the whole png data file
$iconWriter.Write($memoryStream.ToArray());
$iconWriter.Flush();
$output.Close()
#endregion Save Icon
#region Cleanup
$memoryStream.Dispose()
$newBitmap.Dispose()
$inputBitmap.Dispose()
#endregion Cleanup
}
}
/// <summary> /// Provides helper methods for imaging /// </summary> public static class ImagingHelper { /// <summary> /// Converts a PNG image to a icon (ico) /// </summary> /// <param name="input">The input stream</param> /// <param name="output">The output stream</param> /// <param name="size">The size (16x16 px by default)</param> /// <param name="preserveAspectRatio">Preserve the aspect ratio</param> /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(Stream input, Stream output, int size = 16, bool preserveAspectRatio = false) { Bitmap inputBitmap = (Bitmap)Bitmap.FromStream(input); if (inputBitmap != null) { int width, height; if (preserveAspectRatio) { width = size; height = inputBitmap.Height / inputBitmap.Width * size; } else { width = height = size; } Bitmap newBitmap = new Bitmap(inputBitmap, new Size(width, height)); if (newBitmap != null) { // save the resized png into a memory stream for future use using (MemoryStream memoryStream = new MemoryStream()) { newBitmap.Save(memoryStream, ImageFormat.Png); BinaryWriter iconWriter = new BinaryWriter(output); if (output != null && iconWriter != null) { // 0-1 reserved, 0 iconWriter.Write((byte)0); iconWriter.Write((byte)0); // 2-3 image type, 1 = icon, 2 = cursor iconWriter.Write((short)1); // 4-5 number of images iconWriter.Write((short)1); // image entry 1 // 0 image width iconWriter.Write((byte)width); // 1 image height iconWriter.Write((byte)height); // 2 number of colors iconWriter.Write((byte)0); // 3 reserved iconWriter.Write((byte)0); // 4-5 color planes iconWriter.Write((short)0); // 6-7 bits per pixel iconWriter.Write((short)32); // 8-11 size of image data iconWriter.Write((int)memoryStream.Length); // 12-15 offset of image data iconWriter.Write((int)(6 + 16)); // write image data // png data must contain the whole png data file iconWriter.Write(memoryStream.ToArray()); iconWriter.Flush(); return true; } } } return false; } return false; } /// <summary> /// Converts a PNG image to a icon (ico) /// </summary> /// <param name="inputPath">The input path</param> /// <param name="outputPath">The output path</param> /// <param name="size">The size (16x16 px by default)</param> /// <param name="preserveAspectRatio">Preserve the aspect ratio</param> /// <returns>Wether or not the icon was succesfully generated</returns> public static bool ConvertToIcon(string inputPath, string outputPath, int size = 16, bool preserveAspectRatio = false) { using (FileStream inputStream = new FileStream(inputPath, FileMode.Open)) using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate)) { return ConvertToIcon(inputStream, outputStream, size, preserveAspectRatio); } } }
Thank You
this is great TY
PowerShell Compatible Version
Although @lextm ported the code to PowerShell (many props, Sir), they did not include all the functionality added later by other contributors such as @kipusoep, @bananbl, and @mdiller.
Here is a usable version with the additional modifications and adapted to work with PowerShell.
I didn't have time to convert all the code to PowerShell syntax like @lextm did, so I added it as a custom type and included the required dependencies and command syntax that can be difficult to figure out with PowerShell. After adding the custom type, I wrapped it in a PowerShell function inspired by @lextm.
Parameters/Parameter Sets should be added later to take full advantage of all the constructors and for adjusting other things like size, etc.
The Preserve Aspect Ratio from @ChuckSavage wasn't included in the other C# code (possibly they accounted for it in another way), so I didn't end up adding it here yet, but maybe later; or someone else could do it.
Compatibility
OS Version | PowerShell Version | .NET Version | ❔ ✔️ ❌ |
---|---|---|---|
Windows 10, ver. 2004, build 19041.572 | Windows PowerShell 5.1 | 4.8 | ✔️ |
License
As per @darkfall, this work is licensed under CC BY-SA 4.0
Code
$TypeDefinition = @'
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
/// <summary>
/// Adapted from this gist: https://gist.github.com/darkfall/1656050
/// Provides helper methods for imaging
/// </summary>
public static class ImagingHelper
{
/// <summary>
/// Converts a PNG image to a icon (ico) with all the sizes windows likes
/// </summary>
/// <param name="inputBitmap">The input bitmap</param>
/// <param name="output">The output stream</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Bitmap inputBitmap, Stream output)
{
if (inputBitmap == null)
return false;
int[] sizes = new int[] { 256, 48, 32, 16 };
// Generate bitmaps for all the sizes and toss them in streams
List<MemoryStream> imageStreams = new List<MemoryStream>();
foreach (int size in sizes)
{
Bitmap newBitmap = ResizeImage(inputBitmap, size, size);
if (newBitmap == null)
return false;
MemoryStream memoryStream = new MemoryStream();
newBitmap.Save(memoryStream, ImageFormat.Png);
imageStreams.Add(memoryStream);
}
BinaryWriter iconWriter = new BinaryWriter(output);
if (output == null || iconWriter == null)
return false;
int offset = 0;
// 0-1 reserved, 0
iconWriter.Write((byte)0);
iconWriter.Write((byte)0);
// 2-3 image type, 1 = icon, 2 = cursor
iconWriter.Write((short)1);
// 4-5 number of images
iconWriter.Write((short)sizes.Length);
offset += 6 + (16 * sizes.Length);
for (int i = 0; i < sizes.Length; i++)
{
// image entry 1
// 0 image width
iconWriter.Write((byte)sizes[i]);
// 1 image height
iconWriter.Write((byte)sizes[i]);
// 2 number of colors
iconWriter.Write((byte)0);
// 3 reserved
iconWriter.Write((byte)0);
// 4-5 color planes
iconWriter.Write((short)0);
// 6-7 bits per pixel
iconWriter.Write((short)32);
// 8-11 size of image data
iconWriter.Write((int)imageStreams[i].Length);
// 12-15 offset of image data
iconWriter.Write((int)offset);
offset += (int)imageStreams[i].Length;
}
for (int i = 0; i < sizes.Length; i++)
{
// write image data
// png data must contain the whole png data file
iconWriter.Write(imageStreams[i].ToArray());
imageStreams[i].Close();
}
iconWriter.Flush();
return true;
}
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="input">The input stream</param>
/// <param name="output">The output stream</param
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Stream input, Stream output)
{
Bitmap inputBitmap = (Bitmap)Bitmap.FromStream(input);
return ConvertToIcon(inputBitmap, output);
}
/// <summary>
/// Converts a PNG image to a icon (ico)
/// </summary>
/// <param name="inputPath">The input path</param>
/// <param name="outputPath">The output path</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(string inputPath, string outputPath)
{
using (FileStream inputStream = new FileStream(inputPath, FileMode.Open))
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(inputStream, outputStream);
}
}
/// <summary>
/// Converts an image to a icon (ico)
/// </summary>
/// <param name="inputImage">The input image</param>
/// <param name="outputPath">The output path</param>
/// <returns>Wether or not the icon was succesfully generated</returns>
public static bool ConvertToIcon(Image inputImage, string outputPath)
{
using (FileStream outputStream = new FileStream(outputPath, FileMode.OpenOrCreate))
{
return ConvertToIcon(new Bitmap(inputImage), outputStream);
}
}
/// <summary>
/// Resize the image to the specified width and height.
/// Found on stackoverflow: https://stackoverflow.com/questions/1922040/resize-an-image-c-sharp
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(Image image, int width, int height)
{
var destRect = new Rectangle(0, 0, width, height);
var destImage = new Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
}
'@
Add-Type -TypeDefinition $TypeDefinition -ReferencedAssemblies 'System.Drawing','System.IO','System.Collections'
<#
.Synopsis
Converts .PNG images to icons
.Description
Converts a .PNG image to an icon
.Example
ConvertTo-Icon -Path .\Logo.png -Destination .\Favicon.ico
#>
Function ConvertTo-Icon
{
[CmdletBinding()]
param(
# The file
[Parameter(Mandatory=$true, Position=0,ValueFromPipelineByPropertyName=$true)]
[Alias('Fullname','File')]
[string]$Path,
# If provided, will output the icon to a location
[Parameter(Position=1, ValueFromPipelineByPropertyName=$true)]
[Alias('OutputFile')]
[string]$Destination
)
Begin
{
If (-Not 'ImagingHelper' -as [Type])
{
Throw 'The custom "ImagingHelper" type is not loaded'
}
}
Process
{
#region Resolve Path
$ResolvedFile = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($Path)
If (-not $ResolvedFile)
{
return
}
#endregion
[ImagingHelper]::ConvertToIcon($ResolvedFile[0].Path,$Destination)
}
End
{
}
}
Sure!
great, thx, here is btw the respondity for the DLL: CSBeginnerHelp
Thanks for this!
If you get EndOfStreamException
when using the Stream output
do this before using it:
output.Position = 0;
Unfortunately this cannot be used on Powershell Core, System.Drawing.Bitmap
is not available.
Very nice, thanks!
I've added some documentation and renamed variables to comply with Microsoft standards: