Skip to content

Instantly share code, notes, and snippets.

@darkfall
Created January 22, 2012 07:15
Show Gist options
  • Save darkfall/1656050 to your computer and use it in GitHub Desktop.
Save darkfall/1656050 to your computer and use it in GitHub Desktop.
A simple class that converts a image to a icon in c# without losing image color data, unlike System.Drawing.Icon; ico with png data requires Windows Vista or above
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;
}
}
@Amerigoware1
Copy link

@EvertKuijpers Your VB.NET version works excellently; however (with Option Strick On), I had to fix three errors and several naming rule violations.
Added "As Boolean" to the last function.
Changed "offset += imageStreams(index:=i).Length" to "offset += CInt(imageStreams(index:=i).Length)".
Changed "Dim inputBitmap As Drawing.Bitmap = Drawing.Bitmap.FromStream(stream:=input)" to "Dim inputBitmap As Drawing.Bitmap = CType(Drawing.Bitmap.FromStream(stream:=input), Drawing.Bitmap)".

@EvertKuijpers
Copy link

@Amerigoware1 The missing "As Boolean" is an error for sure. Thank you for finding this. Greetz from Tilburg in The Netherlands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment