Last active
July 5, 2023 03:32
-
-
Save ktwrd/b0f47d8ee535e747d785f1850b6d9491 to your computer and use it in GitHub Desktop.
Extract ICO from Exe File
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[string] | |
$Path | |
) | |
#Adopted from https://gist.github.com/darkfall/1656050 | |
$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.Primitives','System.Drawing.Common','System.Drawing','System.IO','System.Collections' | |
Function ConvertTo-Icon | |
{ | |
# [CmdletBinding()] | |
param( | |
# The file | |
[Parameter(Mandatory=$true, Position=0,ValueFromPipelineByPropertyName=$true)] | |
[string]$Path, | |
# If provided, will output the icon to a location | |
[Parameter(Position=1, ValueFromPipelineByPropertyName=$true)] | |
[string]$Dest | |
) | |
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,$Dest) | |
} | |
End | |
{ | |
} | |
} | |
$inputImage="$PSScriptRoot\icon.png" | |
$outputImage="$PSScriptRoot\icon.ico" | |
Add-Type -AssemblyName System.Drawing | |
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$(Resolve-Path -Path $Path)") | |
$icon.ToBitmap().Save($inputImage) | |
ConvertTo-Icon -Path $inputImage -Dest $outputImage |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment