public static IconFile FromFile(string filename) { var instance = new IconFile(); var fileBytes = File.ReadAllBytes(filename); var pinnedBytes = GCHandle.Alloc(fileBytes, GCHandleType.Pinned); instance.iconDir = (ICONDIR)Marshal.PtrToStructure(pinnedBytes.AddrOfPinnedObject(), typeof(ICONDIR)); instance.iconEntry = new ICONDIRENTRY[instance.iconDir.Count]; instance.iconImage = new byte[instance.iconDir.Count][]; int offset = Marshal.SizeOf(instance.iconDir); var iconDirEntryType = typeof(ICONDIRENTRY); int size = Marshal.SizeOf(iconDirEntryType); for (int i = 0, loopTo = instance.iconDir.Count - 1; i <= loopTo; i++) { ICONDIRENTRY entry = (ICONDIRENTRY)Marshal.PtrToStructure(new IntPtr(pinnedBytes.AddrOfPinnedObject().ToInt64() + offset), iconDirEntryType); instance.iconEntry[i] = entry; instance.iconImage[i] = new byte[entry.BytesInRes]; Buffer.BlockCopy(fileBytes, entry.ImageOffset, instance.iconImage[i], 0, entry.BytesInRes); offset += size; } pinnedBytes.Free(); return(instance); }
public unsafe MultiIcon Load(Stream stream) { stream.Position = 0; SingleIcon singleIcon = new SingleIcon("Untitled"); ICONDIR iconDir = new ICONDIR(stream); if (iconDir.idReserved != 0) { throw new InvalidMultiIconFileException(); } if (iconDir.idType != 1) { throw new InvalidMultiIconFileException(); } int entryOffset = sizeof(ICONDIR); // Add Icon Images one by one to the new entry created for (int i = 0; i < iconDir.idCount; i++) { stream.Seek(entryOffset, SeekOrigin.Begin); ICONDIRENTRY entry = new ICONDIRENTRY(stream); // If there is missing information in the header... lets try to calculate it entry = CheckAndRepairEntry(entry); stream.Seek(entry.dwImageOffset, SeekOrigin.Begin); singleIcon.Add(new IconImage(stream, (int)(stream.Length - stream.Position))); entryOffset += sizeof(ICONDIRENTRY); } return(new MultiIcon(singleIcon)); }
public unsafe MultiIcon Load(Stream stream) { stream.Position = 0; SingleIcon singleIcon = new SingleIcon("Untitled"); ICONDIR iconDir = new ICONDIR(stream); if (iconDir.idReserved != 0) throw new InvalidMultiIconFileException(); if (iconDir.idType != 1) throw new InvalidMultiIconFileException(); int entryOffset = sizeof(ICONDIR); // Add Icon Images one by one to the new entry created for(int i=0; i<iconDir.idCount; i++) { stream.Seek(entryOffset, SeekOrigin.Begin); ICONDIRENTRY entry = new ICONDIRENTRY(stream); // If there is missing information in the header... lets try to calculate it entry = CheckAndRepairEntry(entry); stream.Seek(entry.dwImageOffset, SeekOrigin.Begin); singleIcon.Add(new IconImage(stream, (int) (stream.Length - stream.Position))); entryOffset += sizeof(ICONDIRENTRY); } return new MultiIcon(singleIcon); }
internal ICONDIR(RESOURCE_ICONDIR resdir) { idReserved = resdir.idReserved; idType = resdir.idType; idCount = resdir.idCount; uint offset = (uint)Marshal.SizeOf(typeof(ICONDIR)) + (uint)((idCount - 1) * Marshal.SizeOf(typeof(ICONDIRENTRY))); idEntries = new ICONDIRENTRY(resdir.idEntries, offset); }
public void Save(System.IO.Stream Stream) { _frames.SortAscending(); System.IO.BinaryWriter writer = new System.IO.BinaryWriter(Stream, System.Text.Encoding.UTF32); ushort FramesCount = Convert.ToUInt16(_frames.Count); ushort FileHeaderLength = 6; ushort FrameHeaderLength = 16; ICONDIR FileHeader = new ICONDIR(FramesCount); writer.Write(FileHeader.idReserved); writer.Write(FileHeader.idType); writer.Write(FileHeader.idCount); byte[][] data = new byte[FramesCount][]; foreach (BitmapFrame Frame in _frames) { int FrameIndex = _frames.IndexOf(Frame); if (Frame.PixelWidth == 256) { data[FrameIndex] = GetPNGData(Frame); } else { data[FrameIndex] = GetBMPData(Frame); } } uint FrameDataOffset = FileHeaderLength; FrameDataOffset += (uint)(FrameHeaderLength * FramesCount); foreach (BitmapFrame Frame in _frames) { int FrameIndex = _frames.IndexOf(Frame); if (FrameIndex > 0) { FrameDataOffset += Convert.ToUInt32(data[FrameIndex - 1].Length); } ICONDIRENTRY FrameHeader = new ICONDIRENTRY((ushort)Frame.PixelWidth, (ushort)Frame.PixelHeight, Convert.ToUInt16(Frame.Format.BitsPerPixel), Convert.ToUInt32(data[FrameIndex].Length), FrameDataOffset); writer.Write(FrameHeader.bWidth); writer.Write(FrameHeader.bHeight); writer.Write(FrameHeader.bColorCount); writer.Write(FrameHeader.bReserved); writer.Write(FrameHeader.wPlanes); writer.Write(FrameHeader.wBitCount); writer.Write(FrameHeader.dwBytesInRes); writer.Write(FrameHeader.dwImageOffset); } foreach (byte[] FrameData in data) { writer.Write(FrameData); } }
public short nID; // ID public void CopyFrom(ICONDIRENTRY other) { this.bWidth = other.bWidth; this.bHeight = other.bHeight; this.bColorCount = other.bColorCount; this.bReserved = other.bReserved; this.wPlanes = other.wPlanes; this.wBitCount = other.wBitCount; this.dwBytesInRes = other.dwBytesInRes; }
const ushort BitCount = 32; // (Because 32bppArgb) private static unsafe ICONDIRENTRY Make_ICONDIRENTRY(IconImage iconImage) { ICONDIRENTRY iconEntry = new ICONDIRENTRY(); iconEntry.bColorCount = NumColorsInPalette; iconEntry.bHeight = (byte)iconImage.ImageSize.Height; iconEntry.bReserved = 0; iconEntry.bWidth = (byte)iconImage.ImageSize.Width; iconEntry.dwBytesInRes = (uint)(sizeof(BITMAPINFOHEADER) + iconImage.XOR.Length /* + this.AND.Length*/); iconEntry.dwImageOffset = (uint)(sizeof(ICONDIR) + sizeof(ICONDIRENTRY)); iconEntry.wBitCount = BitCount; iconEntry.wPlanes = NumPlanes; return(iconEntry); }
public unsafe void Save(MultiIcon multiIcon, Stream stream) { if (multiIcon.SelectedIndex == -1) { return; } SingleIcon singleIcon = multiIcon[multiIcon.SelectedIndex]; // ICONDIR header ICONDIR iconDir = ICONDIR.Initalizated; iconDir.idCount = (ushort)singleIcon.Count; iconDir.Write(stream); // ICONENTRIES int entryPos = sizeof(ICONDIR); int imagesPos = sizeof(ICONDIR) + iconDir.idCount * sizeof(ICONDIRENTRY); foreach (IconImage iconImage in singleIcon) { // for some formats We don't know the size until we write, // so we have to write first the image then later the header // IconImage stream.Seek(imagesPos, SeekOrigin.Begin); iconImage.Write(stream); long bytesInRes = stream.Position - imagesPos; // IconDirHeader stream.Seek(entryPos, SeekOrigin.Begin); ICONDIRENTRY iconEntry = iconImage.ICONDIRENTRY; stream.Seek(entryPos, SeekOrigin.Begin); iconEntry.dwImageOffset = (uint)imagesPos; iconEntry.dwBytesInRes = (uint)bytesInRes; iconEntry.Write(stream); entryPos += sizeof(ICONDIRENTRY); imagesPos += (int)bytesInRes; } }
public unsafe void Save(Stream stream) { ICONDIR iconDir = ICONDIR.Initalizated; iconDir.idCount = (ushort)this.IconImages.Count; iconDir.Write(stream); int entryPos = sizeof(ICONDIR); // Placeholder for an array if ICONDIRENTRY here int imagesPos = entryPos + iconDir.idCount * sizeof(ICONDIRENTRY); foreach (IconImage iconImage in this.IconImages) { // IconImage stream.Seek(imagesPos, SeekOrigin.Begin); // Header BITMAPINFOHEADER header = Make_BITMAPINFOHEADER(iconImage); header.Write(stream); // Palette - (none) // XOR Image stream.Write(iconImage.XOR, 0, iconImage.XOR.Length); // AND Image - (not needed) long bytesInRes = stream.Position - imagesPos; // IconDirHeader stream.Seek(entryPos, SeekOrigin.Begin); ICONDIRENTRY iconEntry = Make_ICONDIRENTRY(iconImage); stream.Seek(entryPos, SeekOrigin.Begin); iconEntry.dwImageOffset = (uint)imagesPos; iconEntry.dwBytesInRes = (uint)bytesInRes; iconEntry.Write(stream); entryPos += sizeof(ICONDIRENTRY); imagesPos += (int)bytesInRes; } }
private static unsafe ICONDIRENTRY CheckAndRepairEntry(ICONDIRENTRY entry) { // If there is missing information in the header... lets try to calculate it if (entry.wBitCount == 0) { int stride, CLSSize, palette; int bmpSize = ((ushort)entry.dwBytesInRes - sizeof(BITMAPINFOHEADER)); int BWStride = ((entry.bWidth * 1 + 31) & ~31) >> 3; int BWSize = BWStride * entry.bHeight; bmpSize -= BWSize; // Lets find the value; byte[] bpp = { 1, 4, 8, 16, 24, 32 }; int j = 0; while (j <= 5) { stride = ((entry.bWidth * bpp[j] + 31) & ~31) >> 3; CLSSize = entry.bHeight * stride; palette = bpp[j] <= 8 ? ((int)(1 << bpp[j]) * 4) : 0; if (palette + CLSSize == bmpSize) { entry.wBitCount = bpp[j]; break; } j++; } } if (entry.wBitCount < 8 && entry.bColorCount == 0) { entry.bColorCount = (byte)(1 << entry.wBitCount); } if (entry.wPlanes == 0) { entry.wPlanes = 1; } return(entry); }
// Layout: ICONDIR, ICONDIRENTRY[], PngData[] static void WriteIcoFile(string fileName, IEnumerable <Bitmap> smallerBmps, Bitmap big256PxSource) { var dir = new ICONDIR { reserved = 0, imageType = 1, numImages = (UInt16)(1 + smallerBmps.Count()) }; var entries = new ICONDIRENTRY[dir.numImages]; var pngsToWrite = new Queue <MemoryStream>(); // Smaller entries go first var i = 0; var offset = Marshal.SizeOf(dir) + (Marshal.SizeOf(entries[0]) * entries.Length); foreach (var img in smallerBmps) { entries[i].imageWidth = (byte)img.Size.Width; entries[i].imageHeight = (byte)img.Size.Height; entries[i].numColors = 0; entries[i].reserved = 0; entries[i].colorPlanes = 0; entries[i].bitsPerPixel = 32; var stream = new MemoryStream(); img.Save(stream, ImageFormat.Png); pngsToWrite.Enqueue(stream); entries[i].imageDataSize = (UInt32)stream.Length; entries[i].imageDataOffset = (UInt32)offset; Debug.WriteLine($"Storing {img.Size.Width}x{img.Size.Height} image with size {stream.Length} at offset {offset}"); offset += (int)stream.Length; i++; } // 256x256 goes last entries[i].imageWidth = (byte)big256PxSource.Size.Width; entries[i].imageHeight = (byte)big256PxSource.Size.Height; entries[i].numColors = 0; entries[i].reserved = 0; entries[i].colorPlanes = 0; entries[i].bitsPerPixel = 32; var bigImageStream = new MemoryStream(); big256PxSource.Save(bigImageStream, ImageFormat.Png); pngsToWrite.Enqueue(bigImageStream); entries[i].imageDataSize = (UInt32)bigImageStream.Length; entries[i].imageDataOffset = (UInt32)offset; Debug.WriteLine($"Storing {big256PxSource.Size.Width}x{big256PxSource.Size.Height} image with size {bigImageStream.Length} at offset {offset}"); offset = 0; // Write all of the data out to the ICO file using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { var header = GetBytesForStruct(dir); fileStream.Write(header, 0, header.Length); Debug.WriteLine($"Wrote header ({header.Length} bytes, offset = {offset})"); offset += header.Length; i = 0; foreach (var entry in entries) { var entryBytes = GetBytesForStruct(entry); fileStream.Write(entryBytes, 0, entryBytes.Length); Debug.WriteLine($"Wrote directory entry {i++} ({entryBytes.Length} bytes, offset = {offset})"); offset += entryBytes.Length; } while (pngsToWrite.Count > 0) { var pngStream = pngsToWrite.Dequeue(); pngStream.Position = 0; pngStream.CopyTo(fileStream); Debug.WriteLine($"Wrote PNG ({pngStream.Length} bytes, offset = {offset})"); offset += (int)pngStream.Length; } } }
internal static void AppendIconToResourceStream(Stream resStream, Stream iconStream) { var iconReader = new BinaryReader(iconStream); //read magic reserved WORD var reserved = iconReader.ReadUInt16(); if (reserved != 0) { throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); } var type = iconReader.ReadUInt16(); if (type != 1) { throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); } var count = iconReader.ReadUInt16(); if (count == 0) { throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); } var iconDirEntries = new ICONDIRENTRY[count]; for (ushort i = 0; i < count; i++) { // Read the Icon header iconDirEntries[i].bWidth = iconReader.ReadByte(); iconDirEntries[i].bHeight = iconReader.ReadByte(); iconDirEntries[i].bColorCount = iconReader.ReadByte(); iconDirEntries[i].bReserved = iconReader.ReadByte(); iconDirEntries[i].wPlanes = iconReader.ReadUInt16(); iconDirEntries[i].wBitCount = iconReader.ReadUInt16(); iconDirEntries[i].dwBytesInRes = iconReader.ReadUInt32(); iconDirEntries[i].dwImageOffset = iconReader.ReadUInt32(); } // Because Icon files don't seem to record the actual w and BitCount in // the ICONDIRENTRY, get the info from the BITMAPINFOHEADER at the beginning // of the data here: //EDMAURER: PNG compressed icons must be treated differently. Do what has always //been done for uncompressed icons. Assume modern, compressed icons set the //ICONDIRENTRY fields correctly. //if (*(DWORD*)icoBuffer == sizeof(BITMAPINFOHEADER)) //{ // grp[i].Planes = ((BITMAPINFOHEADER*)icoBuffer)->biPlanes; // grp[i].BitCount = ((BITMAPINFOHEADER*)icoBuffer)->biBitCount; //} for (ushort i = 0; i < count; i++) { iconStream.Position = iconDirEntries[i].dwImageOffset; if (iconReader.ReadUInt32() == 40) { iconStream.Position += 8; iconDirEntries[i].wPlanes = iconReader.ReadUInt16(); iconDirEntries[i].wBitCount = iconReader.ReadUInt16(); } } //read everything and no exceptions. time to write. var resWriter = new BinaryWriter(resStream); //write all of the icon images as individual resources, then follow up with //a resource that groups them. const WORD RT_ICON = 3; for (ushort i = 0; i < count; i++) { /* write resource header. * struct RESOURCEHEADER * { * DWORD DataSize; * DWORD HeaderSize; * WORD Magic1; * WORD Type; * WORD Magic2; * WORD Name; * DWORD DataVersion; * WORD MemoryFlags; * WORD LanguageId; * DWORD Version; * DWORD Characteristics; * }; */ resStream.Position = (resStream.Position + 3) & ~3; //headers begin on 4-byte boundaries. resWriter.Write((DWORD)iconDirEntries[i].dwBytesInRes); resWriter.Write((DWORD)0x00000020); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)RT_ICON); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)(i + 1)); //EDMAURER this is not general. Implies you can only append one icon to the resources. //This icon ID would seem to be global among all of the icons not just this group. //Zero appears to not be an acceptable ID. Note that this ID is referred to below. resWriter.Write((DWORD)0x00000000); resWriter.Write((WORD)0x1010); resWriter.Write((WORD)0x0000); resWriter.Write((DWORD)0x00000000); resWriter.Write((DWORD)0x00000000); //write the data. iconStream.Position = iconDirEntries[i].dwImageOffset; resWriter.Write(iconReader.ReadBytes(checked ((int)iconDirEntries[i].dwBytesInRes))); } /* * * struct ICONDIR * { * WORD idReserved; // Reserved (must be 0) * WORD idType; // Resource Type (1 for icons) * WORD idCount; // How many images? * ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) * }/ * * struct ICONRESDIR * { * BYTE Width; // = ICONDIRENTRY.bWidth; * BYTE Height; // = ICONDIRENTRY.bHeight; * BYTE ColorCount; // = ICONDIRENTRY.bColorCount; * BYTE reserved; // = ICONDIRENTRY.bReserved; * WORD Planes; // = ICONDIRENTRY.wPlanes; * WORD BitCount; // = ICONDIRENTRY.wBitCount; * DWORD BytesInRes; // = ICONDIRENTRY.dwBytesInRes; * WORD IconId; // = RESOURCEHEADER.Name * }; */ const WORD RT_GROUP_ICON = RT_ICON + 11; resStream.Position = (resStream.Position + 3) & ~3; //align 4-byte boundary //write the icon group. first a RESOURCEHEADER. the data is the ICONDIR resWriter.Write((DWORD)(3 * sizeof(WORD) + count * /*sizeof(ICONRESDIR)*/ 14)); resWriter.Write((DWORD)0x00000020); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)RT_GROUP_ICON); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)0x7F00); //IDI_APPLICATION resWriter.Write((DWORD)0x00000000); resWriter.Write((WORD)0x1030); resWriter.Write((WORD)0x0000); resWriter.Write((DWORD)0x00000000); resWriter.Write((DWORD)0x00000000); //the ICONDIR resWriter.Write((WORD)0x0000); resWriter.Write((WORD)0x0001); resWriter.Write((WORD)count); for (ushort i = 0; i < count; i++) { resWriter.Write((BYTE)iconDirEntries[i].bWidth); resWriter.Write((BYTE)iconDirEntries[i].bHeight); resWriter.Write((BYTE)iconDirEntries[i].bColorCount); resWriter.Write((BYTE)iconDirEntries[i].bReserved); resWriter.Write((WORD)iconDirEntries[i].wPlanes); resWriter.Write((WORD)iconDirEntries[i].wBitCount); resWriter.Write((DWORD)iconDirEntries[i].dwBytesInRes); resWriter.Write((WORD)(i + 1)); //ID } }
private static unsafe ICONDIRENTRY CheckAndRepairEntry(ICONDIRENTRY entry) { // If there is missing information in the header... lets try to calculate it if (entry.wBitCount == 0) { int stride, CLSSize, palette; int bmpSize = ((ushort) entry.dwBytesInRes - sizeof(BITMAPINFOHEADER)); int BWStride = ((entry.bWidth * 1 + 31) & ~31) >> 3; int BWSize = BWStride * entry.bHeight; bmpSize -= BWSize; // Lets find the value; byte[] bpp = {1, 4, 8, 16, 24, 32}; int j=0; while(j<=5) { stride = ((entry.bWidth * bpp[j] + 31) & ~31) >> 3; CLSSize = entry.bHeight * stride ; palette = bpp[j]<=8 ? ((int) (1 << bpp[j]) * 4) : 0; if (palette + CLSSize == bmpSize) { entry.wBitCount = bpp[j]; break; } j++; } } if (entry.wBitCount < 8 && entry.bColorCount == 0) entry.bColorCount = (byte) (1 << entry.wBitCount); if (entry.wPlanes == 0) entry.wPlanes = 1; return entry; }
private void loadFromFile(string iconFile) { this.loadInitialise(); FileStream input = new FileStream(iconFile, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader br = new BinaryReader(input); try { int num = this.readIconFileHeader(br); ICONDIRENTRY[] icondirentryArray = new ICONDIRENTRY[num]; for (int i = 0; i < num; i++) { icondirentryArray[i] = new ICONDIRENTRY(br); } IcDvImg[] icons = new IcDvImg[num]; for (int j = 0; j < num; j++) { input.Seek((long)icondirentryArray[j].dwImageOffset, SeekOrigin.Begin); byte[] buffer = new byte[icondirentryArray[j].dwBytesInRes]; br.Read(buffer, 0, icondirentryArray[j].dwBytesInRes); icons[j] = new IcDvImg(buffer); } this.iconCollection = new IconDeviceImageCollection(icons); } catch (Exception exception) { if (exception is SystemException) { throw exception; } throw new IconExException("Failed to read icon file.", exception); } finally { br.Close(); } this.iconFile = iconFile; }
public void Save(string iconFile) { FileStream output = new FileStream(iconFile, FileMode.Create, FileAccess.Write, FileShare.Read); BinaryWriter bw = null; try { bw = new BinaryWriter(output); this.writeIconFileHeader(bw); int num = 6 + (0x10 * this.iconCollection.Count); foreach (IcDvImg image in this.iconCollection) { int num2 = image.IconImageDataBytes(); ICONDIRENTRY icondirentry = new ICONDIRENTRY(); icondirentry.width = (byte)image.IconSize.Width; icondirentry.height = (byte)image.IconSize.Height; switch (image.ColorDepth) { case ColorDepth.Depth16Bit: icondirentry.colorCount = 0; icondirentry.wBitCount = 0x10; break; case ColorDepth.Depth24Bit: icondirentry.colorCount = 0; icondirentry.wBitCount = 0x18; break; case ColorDepth.Depth32Bit: icondirentry.colorCount = 0; icondirentry.wBitCount = 0x20; break; case ColorDepth.Depth4Bit: icondirentry.colorCount = 0x10; icondirentry.wBitCount = 4; break; case ColorDepth.Depth8Bit: icondirentry.colorCount = 0xff; icondirentry.wBitCount = 8; break; } icondirentry.wPlanes = 1; icondirentry.dwBytesInRes = num2; icondirentry.dwImageOffset = num; icondirentry.Write(bw); num += num2; } foreach (IcDvImg image2 in this.iconCollection) { image2.SaveIconBitmapData(bw); } } catch (Exception exception) { if (exception is SystemException) { throw exception; } throw new IconExException(exception.Message, exception); } finally { if (bw != null) { bw.Close(); } } }
internal static string makeIconEx(string icon, int size, int depth, string icoFormat) { // Header of the whole file, the file may contain more than one Icon byte[] bytes = System.Convert.FromBase64String(icon); int colorsInPalette = depth > 8 ? 0 : 1 << depth; ICONDIR iconDir = ICONDIR.Initalizated; ICONDIRENTRY iconEntry = new ICONDIRENTRY(); BITMAPINFOHEADER bitMapHeader = new BITMAPINFOHEADER(); iconEntry.bWidth = (byte)size; iconEntry.bHeight = (byte)size; iconEntry.bColorCount = (byte)colorsInPalette; // 4 = 16 colors, 8 = 256 iconEntry.wBitCount = (ushort)depth; iconEntry.bReserved = 0; iconEntry.dwBytesInRes = (uint)(bytes.Length + Marshal.SizeOf(bitMapHeader) + colorsInPalette * 4); // Each color requires 4 bytes in the palette iconEntry.dwImageOffset = (uint)(Marshal.SizeOf(iconDir) + Marshal.SizeOf(iconEntry)); iconEntry.wPlanes = 1; bitMapHeader.biSize = (uint)Marshal.SizeOf(bitMapHeader); bitMapHeader.biWidth = (uint)size; bitMapHeader.biHeight = (uint)size * 2; bitMapHeader.biBitCount = (ushort)depth; bitMapHeader.biPlanes = 1; bitMapHeader.biCompression = IconImageFormat.BMP; bitMapHeader.biXPelsPerMeter = 0; bitMapHeader.biYPelsPerMeter = 0; bitMapHeader.biClrUsed = (uint)colorsInPalette; bitMapHeader.biClrImportant = 0; bitMapHeader.biSizeImage = (uint)bytes.Length; // // The icon is recieved flipped vertically, we need first to flip it before sending // it to the consumer // byte[] data = null; int len = 0, revIndex = 0, rowWidth = 0, ANDmapSize; len = bytes.Length; data = new byte[bytes.Length]; rowWidth = size * depth / 8; ANDmapSize = len - size * size * depth / 8; int step = 4; for (int k = len - rowWidth; k >= ANDmapSize; k -= rowWidth) { for (int r = 0; r < rowWidth; r++, revIndex++) { data[revIndex] = bytes[k + r]; } } for (int l = 0, m = ANDmapSize - step; l < ANDmapSize; l += step, m -= step) { for (int n = 0; n < step; n++, revIndex++) { data[revIndex] = bytes[m + n]; } } MemoryStream mStream = new MemoryStream(); // // Write the Icon directory // iconDir.Write(mStream); // // Write the icon directory entry // iconEntry.Write(mStream); // // Write the bitmap header // bitMapHeader.Write(mStream); // // Write the appropriate palette if required // if (depth == 4) { mStream.Write(palette_16, 0, palette_16.Length); } // // Write the icon data recieved from the CPS server // mStream.Write(data, 0, data.Length); byte[] outBytes; // // If the consumer requested an ico format return the stream as is without any conversion // if (icoFormat.ToLower() == "ico") { outBytes = mStream.GetBuffer(); mStream.Dispose(); return(Convert.ToBase64String(outBytes)); } // // Store the stream in an Icon object, this will solve the transparency problem // mStream.Position = 0; Icon iconStream = new Icon(mStream, depth, depth); // // Retrieve the icon as bitmap for conversion // Bitmap bitMap = iconStream.ToBitmap(); ImageFormat imgFormat = ImageFormat.Png; switch (icoFormat.ToLower()) { case "png": imgFormat = ImageFormat.Png; break; case "gif": imgFormat = ImageFormat.Gif; break; case "tiff": imgFormat = ImageFormat.Tiff; break; } // // Save the icon in the requested format to an icon to be sent to the consumer // MemoryStream oMStream = new MemoryStream(); bitMap.Save(oMStream, imgFormat); outBytes = oMStream.GetBuffer(); mStream.Dispose(); oMStream.Close(); oMStream.Dispose(); bitMap.Dispose(); // // Return the icon as base64 string // return(Convert.ToBase64String(outBytes)); }
private static Icon LoadIconFromResource(UIntPtr lpIconName) { HandleRef hmodule = new HandleRef(null, GetModuleHandle(null)); uint totalsize; RESOURCE_ICONDIRENTRY[] entries; SafeResourceBuffer[] entrybuffers; RESOURCE_ICONDIR dir; using (SafeResourceBuffer buffer = GetResourceBuffer(hmodule, lpIconName, MAKEINTRESOURCE(RT_GROUP_ICON))) { dir = buffer.Read <RESOURCE_ICONDIR>(0); if (dir.idReserved != 0 || dir.idType != IMAGE_ICON || dir.idCount == 0) { throw new InvalidDataException("There is no icon directory in resource data."); } entries = new RESOURCE_ICONDIRENTRY[dir.idCount]; entrybuffers = new SafeResourceBuffer[dir.idCount]; uint entrysize = (uint)Marshal.SizeOf(typeof(RESOURCE_ICONDIRENTRY)); ulong offset = (uint)Marshal.SizeOf(typeof(RESOURCE_ICONDIR)) - entrysize; totalsize = (uint)(Marshal.SizeOf(typeof(ICONDIR)) + (Marshal.SizeOf(typeof(ICONDIRENTRY)) * (dir.idCount - 1))); entries[0] = dir.idEntries; for (int i = 0; i < dir.idCount; i++, offset += entrysize) { if (i > 0) { entries[i] = buffer.Read <RESOURCE_ICONDIRENTRY>(offset); } uint iconsize = entries[i].dwBytesInRes; SafeResourceBuffer entrybuffer = GetResourceBuffer(hmodule, MAKEINTRESOURCE(entries[i].nID), MAKEINTRESOURCE(RT_ICON)); if (iconsize != entrybuffer.ByteLength) { throw new InvalidDataException("Reported resource size is not equal to the icon size."); } entrybuffers[i] = entrybuffer; totalsize += iconsize; } } using (SafeLocalAllocHandle iconbuffer = SafeLocalAlloc(LMEM_ZEROINIT | LMEM_FIXED, totalsize)) { using (UnmanagedMemoryStream outstream = iconbuffer.ToStream(FileAccess.ReadWrite)) { ICONDIR icondir = new ICONDIR(dir); iconbuffer.Write(0, icondir); uint iconoffset = icondir.idEntries.dwImageOffset; outstream.Position = iconoffset; uint entrysize = (uint)Marshal.SizeOf(typeof(ICONDIRENTRY)); ulong offset = (uint)Marshal.SizeOf(typeof(ICONDIR)); ICONDIRENTRY entry = icondir.idEntries; for (int i = 0; i < dir.idCount; i++, offset += entrysize) { if (i > 0) { entry = new ICONDIRENTRY(entries[i], iconoffset); iconbuffer.Write(offset, entry); } using (UnmanagedMemoryStream instream = entrybuffers[i].ToStream()) { instream.CopyTo(outstream); } if (outstream.Position != (iconoffset + entry.dwBytesInRes)) { throw new InvalidOperationException(); } iconoffset += entry.dwBytesInRes; } outstream.Position = 0; return(new Icon(outstream)); } } }
private void loadFromFile( string iconFile) { loadInitialise(); // Open the file FileStream fs = new FileStream( iconFile, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader br = new BinaryReader(fs); try { // read the header: int iconCount = readIconFileHeader(br); // read the directory: ICONDIRENTRY[] ide = new ICONDIRENTRY[iconCount]; for (int iconEntry = 0; iconEntry < iconCount; iconEntry++) { ide[iconEntry] = new ICONDIRENTRY(br); } IconDeviceImage[] icons = new IconDeviceImage[iconCount]; // read the actual icons: for (int iconEntry = 0; iconEntry < iconCount; iconEntry++) { fs.Seek(ide[iconEntry].dwImageOffset, SeekOrigin.Begin); byte[] b = new byte[ide[iconEntry].dwBytesInRes]; br.Read(b, 0, ide[iconEntry].dwBytesInRes); icons[iconEntry] = new IconDeviceImage(b); } // Add the icons to the collection: this.iconCollection = new IconDeviceImageCollection(icons); } catch (Exception ex) { if (ex is SystemException) { throw ex; } else { throw new IconExException("Failed to read icon file.", ex); } } finally { br.Close(); } this.iconFile = iconFile; }
/// <summary> /// Saves the icon to the specified file /// </summary> /// <param name="iconFile">File to save to</param> public void Save( string iconFile ) { // open the file for writing, truncate if exists FileStream fs = new FileStream( iconFile, FileMode.Create, FileAccess.Write, FileShare.Read); BinaryWriter bw = null; try { bw = new BinaryWriter(fs); // write out the icon header: writeIconFileHeader(bw); // write out the icon directory entries: int iconOffset = 6 + 16 * this.iconCollection.Count; foreach (IconDeviceImage idi in this.iconCollection) { int bytesInRes = idi.IconImageDataBytes(); ICONDIRENTRY ide = new ICONDIRENTRY(); ide.width = (byte)idi.IconSize.Width; ide.height = (byte)idi.IconSize.Height; switch (idi.ColorDepth) { case ColorDepth.Depth4Bit: ide.colorCount = 16; ide.wBitCount = 4; break; case ColorDepth.Depth8Bit: ide.colorCount = 0; //BUG CORRECTED, vasian, old was 255, based on http://www.daubnet.com/formats/ICO.html ide.wBitCount = 8; break; case ColorDepth.Depth16Bit: ide.colorCount = 0; ide.wBitCount = 16; break; case ColorDepth.Depth24Bit: ide.colorCount = 0; ide.wBitCount = 24; break; case ColorDepth.Depth32Bit: ide.colorCount = 0; ide.wBitCount = 32; break; } ide.wPlanes = 1; ide.dwBytesInRes = bytesInRes; ide.dwImageOffset = iconOffset; ide.Write(bw); iconOffset += bytesInRes; } // write out the icon data: foreach (IconDeviceImage idi in this.iconCollection) { idi.SaveIconBitmapData(bw); } } catch (Exception ex) { if (ex is SystemException) { throw ex; } else { throw new IconExException(ex.Message, ex); } } finally { if (bw != null) { bw.Close(); } } }
public ICONDIR(ICONDIRENTRY[] entries) { this.Reserved = 0; this.Type = 1; this.Count = (ushort)entries.Length; this.Entries = entries; }
/// <summary> /// Convert this IconEx to Icon /// </summary> /// <returns>icon</returns> public Icon GetIcon() { Icon icon = null; try { MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); // write out the icon header: writeIconFileHeader(bw); // write out the icon directory entries: int iconOffset = 6 + 16 * this.iconCollection.Count; foreach (IconDeviceImage idi in this.iconCollection) { int bytesInRes = idi.IconImageDataBytes(); ICONDIRENTRY ide = new ICONDIRENTRY(); ide.width = (byte)idi.IconSize.Width; ide.height = (byte)idi.IconSize.Height; switch (idi.ColorDepth) { case ColorDepth.Depth4Bit: ide.colorCount = 16; ide.wBitCount = 4; break; case ColorDepth.Depth8Bit: ide.colorCount = 255; ide.wBitCount = 8; break; case ColorDepth.Depth16Bit: ide.colorCount = 0; ide.wBitCount = 16; break; case ColorDepth.Depth24Bit: ide.colorCount = 0; ide.wBitCount = 24; break; case ColorDepth.Depth32Bit: ide.colorCount = 0; ide.wBitCount = 32; break; } ide.wPlanes = 1; ide.dwBytesInRes = bytesInRes; ide.dwImageOffset = iconOffset; ide.Write(bw); iconOffset += bytesInRes; } // write out the icon data: foreach (IconDeviceImage idi in this.iconCollection) { idi.SaveIconBitmapData(bw); } ms.Position = 0; icon = new Icon(ms); } catch (Exception ex) { if (ex is SystemException) { throw ex; } else { throw new IconExException(ex.Message, ex); } } return icon; }
public static void ChangeIcon(string exeFilePath, string icoFilePath) { int len = Marshal.SizeOf(typeof(GRPICONDIR)); using (FileStream fs = new FileStream(icoFilePath, FileMode.Open, FileAccess.Read)) { // 读取图标目录 ICONDIR iconDir = fs.Read <ICONDIR>(); // 读取图标头列表 List <ICONDIRENTRY> iconDirEntrys = new List <ICONDIRENTRY>(); for (int i = 0; i < iconDir.idCount; i++) { ICONDIRENTRY iconDirEntry = fs.Read <ICONDIRENTRY>(); iconDirEntrys.Add(iconDirEntry); } // 读取图标数据列表 List <byte[]> iconDatas = new List <byte[]>(); for (int i = 0; i < iconDir.idCount; i++) { byte[] iconData = new byte[iconDirEntrys[i].dwBytesInRes]; fs.Seek(iconDirEntrys[i].dwImageOffset, SeekOrigin.Begin); fs.Read(iconData, 0, iconData.Length); iconDatas.Add(iconData); } // 生成GRPICONDIR GRPICONDIR grpIconDir = new GRPICONDIR(); grpIconDir.idCount = iconDir.idCount; grpIconDir.idReserved = 0; grpIconDir.idType = 1; // 1代表图标 // 生成List<GRPICONDIRENTRY> List <GRPICONDIRENTRY> grpIconDirEntrys = new List <GRPICONDIRENTRY>(); for (int i = 0; i < iconDirEntrys.Count; i++) { GRPICONDIRENTRY grpIconDirEntry = new GRPICONDIRENTRY(); grpIconDirEntry.CopyFrom(iconDirEntrys[i]); grpIconDirEntry.nID = (short)(i + 1); grpIconDirEntrys.Add(grpIconDirEntry); } List <byte> grpData = new List <byte>(); grpData.AddRange(grpIconDir.ToByteArray()); for (int i = 0; i < grpIconDirEntrys.Count; i++) { grpData.AddRange(grpIconDirEntrys[i].ToByteArray()); } IntPtr grpDataPtr = grpData.ToArray().ToPtr(); bool ret = false; IntPtr pUpdateRes = BeginUpdateResource(exeFilePath, false); for (int i = 0; i < grpIconDirEntrys.Count; i++) { // 更新图标数据 int id = grpIconDirEntrys[i].nID; ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_ICON), new IntPtr(id), 0, iconDatas[i].ToPtr(), iconDatas[i].Length); } // 更新图标目录和图标头 // 32512为当前exe中Icon Group下id号 ret = UpdateResource(pUpdateRes, new IntPtr((int)eResourceTypes.RT_GROUP_ICON), new IntPtr(32512), 0, grpDataPtr, grpData.Count); ret = EndUpdateResource(pUpdateRes, false); } }
internal static void AppendIconToResourceStream(Stream resStream, Stream iconStream) { var iconReader = new BinaryReader(iconStream); //read magic reserved WORD var reserved = iconReader.ReadUInt16(); if (reserved != 0) throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); var type = iconReader.ReadUInt16(); if (type != 1) throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); var count = iconReader.ReadUInt16(); if (count == 0) throw new ResourceException(CodeAnalysisResources.IconStreamUnexpectedFormat); var iconDirEntries = new ICONDIRENTRY[count]; for (ushort i = 0; i < count; i++) { // Read the Icon header iconDirEntries[i].bWidth = iconReader.ReadByte(); iconDirEntries[i].bHeight = iconReader.ReadByte(); iconDirEntries[i].bColorCount = iconReader.ReadByte(); iconDirEntries[i].bReserved = iconReader.ReadByte(); iconDirEntries[i].wPlanes = iconReader.ReadUInt16(); iconDirEntries[i].wBitCount = iconReader.ReadUInt16(); iconDirEntries[i].dwBytesInRes = iconReader.ReadUInt32(); iconDirEntries[i].dwImageOffset = iconReader.ReadUInt32(); } // Because Icon files don't seem to record the actual w and BitCount in // the ICONDIRENTRY, get the info from the BITMAPINFOHEADER at the beginning // of the data here: //EDMAURER: PNG compressed icons must be treated differently. Do what has always //been done for uncompressed icons. Assume modern, compressed icons set the //ICONDIRENTRY fields correctly. //if (*(DWORD*)icoBuffer == sizeof(BITMAPINFOHEADER)) //{ // grp[i].Planes = ((BITMAPINFOHEADER*)icoBuffer)->biPlanes; // grp[i].BitCount = ((BITMAPINFOHEADER*)icoBuffer)->biBitCount; //} for (ushort i = 0; i < count; i++) { iconStream.Position = iconDirEntries[i].dwImageOffset; if (iconReader.ReadUInt32() == 40) { iconStream.Position += 8; iconDirEntries[i].wPlanes = iconReader.ReadUInt16(); iconDirEntries[i].wBitCount = iconReader.ReadUInt16(); } } //read everything and no exceptions. time to write. var resWriter = new BinaryWriter(resStream); //write all of the icon images as individual resources, then follow up with //a resource that groups them. const WORD RT_ICON = 3; for (ushort i = 0; i < count; i++) { /* write resource header. struct RESOURCEHEADER { DWORD DataSize; DWORD HeaderSize; WORD Magic1; WORD Type; WORD Magic2; WORD Name; DWORD DataVersion; WORD MemoryFlags; WORD LanguageId; DWORD Version; DWORD Characteristics; }; */ resStream.Position = (resStream.Position + 3) & ~3; //headers begin on 4-byte boundaries. resWriter.Write((DWORD)iconDirEntries[i].dwBytesInRes); resWriter.Write((DWORD)0x00000020); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)RT_ICON); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)(i + 1)); //EDMAURER this is not general. Implies you can only append one icon to the resources. //This icon ID would seem to be global among all of the icons not just this group. //Zero appears to not be an acceptable ID. Note that this ID is referred to below. resWriter.Write((DWORD)0x00000000); resWriter.Write((WORD)0x1010); resWriter.Write((WORD)0x0000); resWriter.Write((DWORD)0x00000000); resWriter.Write((DWORD)0x00000000); //write the data. iconStream.Position = iconDirEntries[i].dwImageOffset; resWriter.Write(iconReader.ReadBytes(checked((int)iconDirEntries[i].dwBytesInRes))); } /* struct ICONDIR { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource Type (1 for icons) WORD idCount; // How many images? ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em) }/ struct ICONRESDIR { BYTE Width; // = ICONDIRENTRY.bWidth; BYTE Height; // = ICONDIRENTRY.bHeight; BYTE ColorCount; // = ICONDIRENTRY.bColorCount; BYTE reserved; // = ICONDIRENTRY.bReserved; WORD Planes; // = ICONDIRENTRY.wPlanes; WORD BitCount; // = ICONDIRENTRY.wBitCount; DWORD BytesInRes; // = ICONDIRENTRY.dwBytesInRes; WORD IconId; // = RESOURCEHEADER.Name }; */ const WORD RT_GROUP_ICON = RT_ICON + 11; resStream.Position = (resStream.Position + 3) & ~3; //align 4-byte boundary //write the icon group. first a RESOURCEHEADER. the data is the ICONDIR resWriter.Write((DWORD)(3 * sizeof(WORD) + count * /*sizeof(ICONRESDIR)*/ 14)); resWriter.Write((DWORD)0x00000020); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)RT_GROUP_ICON); resWriter.Write((WORD)0xFFFF); resWriter.Write((WORD)0x7F00); //IDI_APPLICATION resWriter.Write((DWORD)0x00000000); resWriter.Write((WORD)0x1030); resWriter.Write((WORD)0x0000); resWriter.Write((DWORD)0x00000000); resWriter.Write((DWORD)0x00000000); //the ICONDIR resWriter.Write((WORD)0x0000); resWriter.Write((WORD)0x0001); resWriter.Write((WORD)count); for (ushort i = 0; i < count; i++) { resWriter.Write((BYTE)iconDirEntries[i].bWidth); resWriter.Write((BYTE)iconDirEntries[i].bHeight); resWriter.Write((BYTE)iconDirEntries[i].bColorCount); resWriter.Write((BYTE)iconDirEntries[i].bReserved); resWriter.Write((WORD)iconDirEntries[i].wPlanes); resWriter.Write((WORD)iconDirEntries[i].wBitCount); resWriter.Write((DWORD)iconDirEntries[i].dwBytesInRes); resWriter.Write((WORD)(i + 1)); //ID } }