private void SaveIconDump(BinaryWriter writer, IconDump id) { writer.Write(id.data !); }
private void InitFromStreamWithSize(Stream stream, int width, int height) { //read the icon header if (stream == null || stream.Length == 0) { throw new System.ArgumentException("The argument 'stream' must be a picture that can be used as a Icon", "stream"); } BinaryReader reader = new BinaryReader(stream); //iconDir = new IconDir (); iconDir.idReserved = reader.ReadUInt16(); if (iconDir.idReserved != 0) //must be 0 { throw new System.ArgumentException("Invalid Argument", "stream"); } iconDir.idType = reader.ReadUInt16(); if (iconDir.idType != 1) //must be 1 { throw new System.ArgumentException("Invalid Argument", "stream"); } ushort dirEntryCount = reader.ReadUInt16(); imageData = new ImageData [dirEntryCount]; iconDir.idCount = dirEntryCount; iconDir.idEntries = new IconDirEntry [dirEntryCount]; bool sizeObtained = false; // now read in the IconDirEntry structures for (int i = 0; i < dirEntryCount; i++) { IconDirEntry ide; ide.width = reader.ReadByte(); ide.height = reader.ReadByte(); ide.colorCount = reader.ReadByte(); ide.reserved = reader.ReadByte(); ide.planes = reader.ReadUInt16(); ide.bitCount = reader.ReadUInt16(); ide.bytesInRes = reader.ReadUInt32(); ide.imageOffset = reader.ReadUInt32(); #if false Console.WriteLine("Entry: {0}", i); Console.WriteLine("\tide.width: {0}", ide.width); Console.WriteLine("\tide.height: {0}", ide.height); Console.WriteLine("\tide.colorCount: {0}", ide.colorCount); Console.WriteLine("\tide.reserved: {0}", ide.reserved); Console.WriteLine("\tide.planes: {0}", ide.planes); Console.WriteLine("\tide.bitCount: {0}", ide.bitCount); Console.WriteLine("\tide.bytesInRes: {0}", ide.bytesInRes); Console.WriteLine("\tide.imageOffset: {0}", ide.imageOffset); #endif // Vista 256x256 icons points directly to a PNG bitmap // 256x256 icons are decoded as 0x0 (width and height are encoded as BYTE) // and we ignore them just like MS does (at least up to fx 2.0) // Added: storing data so it can be saved back if ((ide.width == 0) && (ide.height == 0)) { ide.ignore = true; } else { ide.ignore = false; } iconDir.idEntries [i] = ide; //is this is the best fit?? if (!sizeObtained) { if (((ide.height == height) || (ide.width == width)) && !ide.ignore) { this.id = (ushort)i; sizeObtained = true; this.iconSize.Height = ide.height; this.iconSize.Width = ide.width; } } } // throw error if no valid entries found int valid = 0; for (int i = 0; i < dirEntryCount; i++) { if (!(iconDir.idEntries [i].ignore)) { valid++; } } if (valid == 0) { throw new Win32Exception(0, "No valid icon entry were found."); } // if we havent found the best match, return the one with the // largest size. Is this approach correct?? if (!sizeObtained) { uint largestSize = 0; for (int j = 0; j < dirEntryCount; j++) { if (iconDir.idEntries [j].bytesInRes >= largestSize && !iconDir.idEntries [j].ignore) { largestSize = iconDir.idEntries [j].bytesInRes; this.id = (ushort)j; this.iconSize.Height = iconDir.idEntries [j].height; this.iconSize.Width = iconDir.idEntries [j].width; } } } //now read in the icon data for (int j = 0; j < dirEntryCount; j++) { // process ignored into IconDump if (iconDir.idEntries [j].ignore) { IconDump id = new IconDump(); stream.Seek(iconDir.idEntries [j].imageOffset, SeekOrigin.Begin); id.data = new byte [iconDir.idEntries [j].bytesInRes]; stream.Read(id.data, 0, id.data.Length); imageData [j] = id; continue; } // standard image IconImage iidata = new IconImage(); BitmapInfoHeader bih = new BitmapInfoHeader(); stream.Seek(iconDir.idEntries [j].imageOffset, SeekOrigin.Begin); byte [] buffer = new byte [iconDir.idEntries [j].bytesInRes]; stream.Read(buffer, 0, buffer.Length); BinaryReader bihReader = new BinaryReader(new MemoryStream(buffer)); bih.biSize = bihReader.ReadUInt32(); bih.biWidth = bihReader.ReadInt32(); bih.biHeight = bihReader.ReadInt32(); bih.biPlanes = bihReader.ReadUInt16(); bih.biBitCount = bihReader.ReadUInt16(); bih.biCompression = bihReader.ReadUInt32(); bih.biSizeImage = bihReader.ReadUInt32(); bih.biXPelsPerMeter = bihReader.ReadInt32(); bih.biYPelsPerMeter = bihReader.ReadInt32(); bih.biClrUsed = bihReader.ReadUInt32(); bih.biClrImportant = bihReader.ReadUInt32(); #if false Console.WriteLine("Entry: {0}", j); Console.WriteLine("\tbih.biSize: {0}", bih.biSize); Console.WriteLine("\tbih.biWidth: {0}", bih.biWidth); Console.WriteLine("\tbih.biHeight: {0}", bih.biHeight); Console.WriteLine("\tbih.biPlanes: {0}", bih.biPlanes); Console.WriteLine("\tbih.biBitCount: {0}", bih.biBitCount); Console.WriteLine("\tbih.biCompression: {0}", bih.biCompression); Console.WriteLine("\tbih.biSizeImage: {0}", bih.biSizeImage); Console.WriteLine("\tbih.biXPelsPerMeter: {0}", bih.biXPelsPerMeter); Console.WriteLine("\tbih.biYPelsPerMeter: {0}", bih.biYPelsPerMeter); Console.WriteLine("\tbih.biClrUsed: {0}", bih.biClrUsed); Console.WriteLine("\tbih.biClrImportant: {0}", bih.biClrImportant); #endif iidata.iconHeader = bih; //Read the number of colors used and corresponding memory occupied by //color table. Fill this memory chunk into rgbquad[] int numColors; switch (bih.biBitCount) { case 1: numColors = 2; break; case 4: numColors = 16; break; case 8: numColors = 256; break; default: numColors = 0; break; } iidata.iconColors = new uint [numColors]; for (int i = 0; i < numColors; i++) { iidata.iconColors [i] = bihReader.ReadUInt32(); } //XOR mask is immediately after ColorTable and its size is //icon height* no. of bytes per line //icon height is half of BITMAPINFOHEADER.biHeight, since it contains //both XOR as well as AND mask bytes int iconHeight = bih.biHeight / 2; //bytes per line should should be uint aligned int numBytesPerLine = ((((bih.biWidth * bih.biPlanes * bih.biBitCount) + 31) >> 5) << 2); //Determine the XOR array Size int xorSize = numBytesPerLine * iconHeight; iidata.iconXOR = new byte [xorSize]; int nread = bihReader.Read(iidata.iconXOR, 0, xorSize); if (nread != xorSize) { string msg = Locale.GetText("{0} data length expected {1}, read {2}", "XOR", xorSize, nread); throw new ArgumentException(msg, "stream"); } //Determine the AND array size numBytesPerLine = (int)((((bih.biWidth) + 31) & ~31) >> 3); int andSize = numBytesPerLine * iconHeight; iidata.iconAND = new byte [andSize]; nread = bihReader.Read(iidata.iconAND, 0, andSize); if (nread != andSize) { string msg = Locale.GetText("{0} data length expected {1}, read {2}", "AND", andSize, nread); throw new ArgumentException(msg, "stream"); } imageData [j] = iidata; bihReader.Dispose(); } reader.Dispose(); }
private void InitFromStreamWithSize (Stream stream, int width, int height) { //read the icon header if (stream == null || stream.Length == 0) throw new ArgumentException ("The argument 'stream' must be a picture that can be used as a Icon", "stream"); BinaryReader reader = new BinaryReader (stream); //iconDir = new IconDir (); iconDir.idReserved = reader.ReadUInt16(); if (iconDir.idReserved != 0) //must be 0 throw new ArgumentException ("Invalid Argument", "stream"); iconDir.idType = reader.ReadUInt16(); if (iconDir.idType != 1) //must be 1 throw new ArgumentException ("Invalid Argument", "stream"); ushort dirEntryCount = reader.ReadUInt16(); imageData = new ImageData [dirEntryCount]; iconDir.idCount = dirEntryCount; iconDir.idEntries = new IconDirEntry [dirEntryCount]; bool sizeObtained = false; // now read in the IconDirEntry structures for (int i = 0; i < dirEntryCount; i++) { IconDirEntry ide; ide.width = reader.ReadByte (); ide.height = reader.ReadByte (); ide.colorCount = reader.ReadByte (); ide.reserved = reader.ReadByte (); ide.planes = reader.ReadUInt16 (); ide.bitCount = reader.ReadUInt16 (); ide.bytesInRes = reader.ReadUInt32 (); ide.imageOffset = reader.ReadUInt32 (); #if false Console.WriteLine ("Entry: {0}", i); Console.WriteLine ("\tide.width: {0}", ide.width); Console.WriteLine ("\tide.height: {0}", ide.height); Console.WriteLine ("\tide.colorCount: {0}", ide.colorCount); Console.WriteLine ("\tide.reserved: {0}", ide.reserved); Console.WriteLine ("\tide.planes: {0}", ide.planes); Console.WriteLine ("\tide.bitCount: {0}", ide.bitCount); Console.WriteLine ("\tide.bytesInRes: {0}", ide.bytesInRes); Console.WriteLine ("\tide.imageOffset: {0}", ide.imageOffset); #endif // Vista 256x256 icons points directly to a PNG bitmap // 256x256 icons are decoded as 0x0 (width and height are encoded as BYTE) // and we ignore them just like MS does (at least up to fx 2.0) // Added: storing data so it can be saved back if ((ide.width == 0) && (ide.height == 0)) ide.ignore = true; else ide.ignore = false; iconDir.idEntries [i] = ide; //is this is the best fit?? if (!sizeObtained) { if (((ide.height == height) || (ide.width == width)) && !ide.ignore) { this.id = (ushort) i; sizeObtained = true; this.iconSize.Height = ide.height; this.iconSize.Width = ide.width; } } } // throw error if no valid entries found int valid = 0; for (int i = 0; i < dirEntryCount; i++) { if (!(iconDir.idEntries [i].ignore)) valid++; } if (valid == 0) throw new Win32Exception (0, "No valid icon entry were found."); // if we havent found the best match, return the one with the // largest size. Is this approach correct?? if (!sizeObtained){ uint largestSize = 0; for (int j=0; j<dirEntryCount; j++){ if (iconDir.idEntries [j].bytesInRes >= largestSize && !iconDir.idEntries [j].ignore) { largestSize = iconDir.idEntries [j].bytesInRes; this.id = (ushort) j; this.iconSize.Height = iconDir.idEntries [j].height; this.iconSize.Width = iconDir.idEntries [j].width; } } } //now read in the icon data for (int j = 0; j<dirEntryCount; j++) { // process ignored into IconDump if (iconDir.idEntries [j].ignore) { IconDump id = new IconDump (); stream.Seek (iconDir.idEntries [j].imageOffset, SeekOrigin.Begin); id.data = new byte [iconDir.idEntries [j].bytesInRes]; stream.Read (id.data, 0, id.data.Length); imageData [j] = id; continue; } // standard image IconImage iidata = new IconImage(); BitmapInfoHeader bih = new BitmapInfoHeader(); stream.Seek (iconDir.idEntries [j].imageOffset, SeekOrigin.Begin); byte [] buffer = new byte [iconDir.idEntries [j].bytesInRes]; stream.Read (buffer, 0, buffer.Length); BinaryReader bihReader = new BinaryReader (new MemoryStream(buffer)); bih.biSize = bihReader.ReadUInt32 (); bih.biWidth = bihReader.ReadInt32 (); bih.biHeight = bihReader.ReadInt32 (); bih.biPlanes = bihReader.ReadUInt16 (); bih.biBitCount = bihReader.ReadUInt16 (); bih.biCompression = bihReader.ReadUInt32 (); bih.biSizeImage = bihReader.ReadUInt32 (); bih.biXPelsPerMeter = bihReader.ReadInt32 (); bih.biYPelsPerMeter = bihReader.ReadInt32 (); bih.biClrUsed = bihReader.ReadUInt32 (); bih.biClrImportant = bihReader.ReadUInt32 (); #if false Console.WriteLine ("Entry: {0}", j); Console.WriteLine ("\tbih.biSize: {0}", bih.biSize); Console.WriteLine ("\tbih.biWidth: {0}", bih.biWidth); Console.WriteLine ("\tbih.biHeight: {0}", bih.biHeight); Console.WriteLine ("\tbih.biPlanes: {0}", bih.biPlanes); Console.WriteLine ("\tbih.biBitCount: {0}", bih.biBitCount); Console.WriteLine ("\tbih.biCompression: {0}", bih.biCompression); Console.WriteLine ("\tbih.biSizeImage: {0}", bih.biSizeImage); Console.WriteLine ("\tbih.biXPelsPerMeter: {0}", bih.biXPelsPerMeter); Console.WriteLine ("\tbih.biYPelsPerMeter: {0}", bih.biYPelsPerMeter); Console.WriteLine ("\tbih.biClrUsed: {0}", bih.biClrUsed); Console.WriteLine ("\tbih.biClrImportant: {0}", bih.biClrImportant); #endif iidata.iconHeader = bih; //Read the number of colors used and corresponding memory occupied by //color table. Fill this memory chunk into rgbquad[] int numColors; switch (bih.biBitCount){ case 1: numColors = 2; break; case 4: numColors = 16; break; case 8: numColors = 256; break; default: numColors = 0; break; } iidata.iconColors = new uint [numColors]; for (int i=0; i<numColors; i++) iidata.iconColors [i] = bihReader.ReadUInt32 (); //XOR mask is immediately after ColorTable and its size is //icon height* no. of bytes per line //icon height is half of BITMAPINFOHEADER.biHeight, since it contains //both XOR as well as AND mask bytes int iconHeight = bih.biHeight/2; //bytes per line should should be uint aligned int numBytesPerLine = ((((bih.biWidth * bih.biPlanes * bih.biBitCount)+ 31)>>5)<<2); //Determine the XOR array Size int xorSize = numBytesPerLine * iconHeight; iidata.iconXOR = new byte [xorSize]; int nread = bihReader.Read (iidata.iconXOR, 0, xorSize); if (nread != xorSize) { string msg = string.Format("{0} data length expected {1}, read {2}", "XOR", xorSize, nread); throw new ArgumentException (msg, "stream"); } //Determine the AND array size numBytesPerLine = (int)((((bih.biWidth) + 31) & ~31) >> 3); int andSize = numBytesPerLine * iconHeight; iidata.iconAND = new byte [andSize]; nread = bihReader.Read (iidata.iconAND, 0, andSize); if (nread != andSize) { string msg = string.Format("{0} data length expected {1}, read {2}", "AND", andSize, nread); throw new ArgumentException (msg, "stream"); } imageData [j] = iidata; bihReader.Close(); } reader.Close(); }
private void InitFromStreamWithSize(Stream stream, int width, int height) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } if (stream.Length == 0) { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream))); } bool sizeObtained = false; ushort dirEntryCount; // Read the icon header using (var reader = new BinaryReader(stream)) { iconDir.idReserved = reader.ReadUInt16(); if (iconDir.idReserved != 0) //must be 0 { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream))); } iconDir.idType = reader.ReadUInt16(); if (iconDir.idType != 1) //must be 1 { throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(stream))); } dirEntryCount = reader.ReadUInt16(); imageData = new ImageData[dirEntryCount]; iconDir.idCount = dirEntryCount; iconDir.idEntries = new IconDirEntry[dirEntryCount]; // Now read in the IconDirEntry structures for (int i = 0; i < dirEntryCount; i++) { var ide = new IconDirEntry { width = reader.ReadByte(), height = reader.ReadByte(), colorCount = reader.ReadByte(), reserved = reader.ReadByte(), planes = reader.ReadUInt16(), bitCount = reader.ReadUInt16(), bytesInRes = reader.ReadUInt32(), imageOffset = reader.ReadUInt32() }; // Vista 256x256 icons points directly to a PNG bitmap // 256x256 icons are decoded as 0x0 (width and height are encoded as BYTE) // We mark them as png and later on we just store the raw bytes to be able to save to a file. ide.png = (ide.width == 0) && (ide.height == 0); iconDir.idEntries[i] = ide; if (!sizeObtained) { if (((ide.height == height) || (ide.width == width)) && !ide.png) { this.id = (ushort)i; sizeObtained = true; this.iconSize.Height = ide.height; this.iconSize.Width = ide.width; } } } // If we havent found the best match, return the one with the largest size. if (!sizeObtained) { uint largestSize = 0; for (int j = 0; j < dirEntryCount; j++) { if (iconDir.idEntries[j].bytesInRes >= largestSize && !iconDir.idEntries[j].png) { largestSize = iconDir.idEntries[j].bytesInRes; this.id = (ushort)j; this.iconSize.Height = iconDir.idEntries[j].height; this.iconSize.Width = iconDir.idEntries[j].width; } } } // Now read in the icon data bool valid = false; for (int j = 0; j < dirEntryCount; j++) { stream.Seek(iconDir.idEntries[j].imageOffset, SeekOrigin.Begin); byte[] buffer = new byte[iconDir.idEntries[j].bytesInRes]; stream.Read(buffer, 0, buffer.Length); using (var bihReader = new BinaryReader(new MemoryStream(buffer))) { uint headerSize = bihReader.ReadUInt32(); int headerWidth = bihReader.ReadInt32(); // Process PNG images into IconDump if (iconDir.idEntries[j].png || (headerSize == PNGSignature1 && headerWidth == (int)PNGSignature2)) { IconDump id = new IconDump(); id.data = buffer; imageData[j] = id; iconDir.idEntries[j].png = true; continue; } // We found a valid icon BMP entry. valid = true; var bih = new BitmapInfoHeader { biSize = headerSize, biWidth = headerWidth, biHeight = bihReader.ReadInt32(), biPlanes = bihReader.ReadUInt16(), biBitCount = bihReader.ReadUInt16(), biCompression = bihReader.ReadUInt32(), biSizeImage = bihReader.ReadUInt32(), biXPelsPerMeter = bihReader.ReadInt32(), biYPelsPerMeter = bihReader.ReadInt32(), biClrUsed = bihReader.ReadUInt32(), biClrImportant = bihReader.ReadUInt32() }; var iidata = new IconImage { iconHeader = bih }; // Read the number of colors used and corresponding memory occupied by // color table. Fill this memory chunk into rgbquad[] int numColors; switch (bih.biBitCount) { case 1: numColors = 2; break; case 4: numColors = 16; break; case 8: numColors = 256; break; default: numColors = 0; break; } iidata.iconColors = new uint[numColors]; for (int i = 0; i < numColors; i++) { iidata.iconColors[i] = bihReader.ReadUInt32(); } //XOR mask is immediately after ColorTable and its size is //icon height* no. of bytes per line //icon height is half of BITMAPINFOHEADER.biHeight, since it contains //both XOR as well as AND mask bytes int iconHeight = bih.biHeight / 2; //bytes per line should be uint aligned int numBytesPerLine = checked ((((bih.biWidth * bih.biPlanes * bih.biBitCount) + 31) >> 5) << 2); //Determine the XOR array Size int xorSize = checked (numBytesPerLine * iconHeight); iidata.iconXOR = new byte[xorSize]; int nread = bihReader.Read(iidata.iconXOR, 0, xorSize); if (nread != xorSize) { throw new ArgumentException(SR.Format(SR.IconInvalidMaskLength, "XOR", xorSize, nread), nameof(stream)); } //Determine the AND array size numBytesPerLine = checked ((((bih.biWidth) + 31) & ~31) >> 3); int andSize = checked (numBytesPerLine * iconHeight); iidata.iconAND = new byte[andSize]; nread = bihReader.Read(iidata.iconAND, 0, andSize); if (nread != andSize) { throw new ArgumentException(SR.Format(SR.IconInvalidMaskLength, "AND", andSize, nread), nameof(stream)); } imageData[j] = iidata; } } // Throw error if no valid entries found if (!valid) { throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER, SR.Format(SR.InvalidPictureType, "picture", nameof(stream))); } } }
private void SaveIconDump (BinaryWriter writer, IconDump id) { writer.Write (id.data); }