/// <summary> /// Gets the number of images stored in a .ico file. /// </summary> /// <param name="path">The path to the file.</param> /// <returns>The number of images in the file, OR -1 if error.</returns> public static int GetImageCount(string path) { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return(-1); } try { using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] bytes = new byte[4]; fileStream.Read(bytes, 0, bytes.Length); if (!ByteHelper.StartsWith(bytes, IdentifierBytes_1)) { return(-1); } return(ByteHelper.ReadInt16LE(fileStream)); } } catch { return(-1); } }
/// <summary> /// Gets the image format from the leading byte identifiers. /// </summary> /// <param name="path">The path to the image file.</param> /// <returns>The image format.</returns> public static ImgFormat GetImageFormat(string path) { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return(ImgFormat.nil); } try { using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) using (BinaryReader binaryReader = new BinaryReader(fileStream)) { byte[] magicBytes = new byte[MAX_MAGIC_BYTE_LENGTH]; for (int i = 0; i < MAX_MAGIC_BYTE_LENGTH; i += 1) { magicBytes[i] = binaryReader.ReadByte(); foreach (KeyValuePair <byte[], ImgFormat> kvPair in Image_Byte_Identifiers) { if (ByteHelper.StartsWith(magicBytes, kvPair.Key)) { return(kvPair.Value); } } } return(ImgFormat.nil); } } catch { return(ImgFormat.nil); } }
/// <summary> /// Gets the width and height of the first image directory of a .ico file. /// </summary> /// <param name="path">The path to the file.</param> /// <returns>The <see cref="Size"/> of the first image directory, OR Size.Empty if error.</returns> public static Size GetDimensionOfFirstImageFromFile(string path) { if (string.IsNullOrEmpty(path) || !File.Exists(path)) { return(Size.Empty); } try { using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] bytes = new byte[6]; fileStream.Read(bytes, 0, bytes.Length); if (!ByteHelper.StartsWith(bytes, IdentifierBytes_1)) { return(Size.Empty); } byte[] wh = new byte[2]; fileStream.Read(wh, 0, wh.Length); int width = 0; int height = 0; if (wh[0] == 0x00) { width = 256; } else { width = (byte)wh[0]; } if (wh[1] == 0x00) { height = 256; } else { height = (byte)wh[0]; } return(new Size(width, height)); } } catch { return(Size.Empty); } }
/// <summary> /// Reads the first 5 bytes from the reader to identify a WORM image. /// </summary> /// <param name="binaryReader">The reader.</param> /// <returns>The format of a worm image. nil for invalid</returns> public static WormFormat GetWormFormat(BinaryReader binaryReader) { byte[] identifier = binaryReader.ReadBytes(5); if (ByteHelper.StartsWith(identifier, IdentifierBytes_1)) { return(WormFormat.wrm); } if (ByteHelper.StartsWith(identifier, IdentifierBytes_2)) { return(WormFormat.dwrm); } return(WormFormat.nil); }
/// <summary> /// Gets the dimensions of an image. /// </summary> /// <param name="path">The path of the image to get the dimensions of.</param> /// <returns>The dimensions of the specified image.</returns> /// <exception cref="ArgumentException">The image was of an unrecognised format.</exception> public static Size GetDimensions(BinaryReader binaryReader) { byte[] magicBytes = new byte[MAX_MAGIC_BYTE_LENGTH]; for (int i = 0; i < MAX_MAGIC_BYTE_LENGTH; i += 1) { magicBytes[i] = binaryReader.ReadByte(); foreach (KeyValuePair <byte[], Func <BinaryReader, Size> > kvPair in Image_Format_Decoders) { if (ByteHelper.StartsWith(magicBytes, kvPair.Key)) { return(kvPair.Value(binaryReader)); } } } return(Size.Empty); }
/// <summary> /// Checks if param 2 starts with param 1. /// </summary> /// <returns>True if param 2 starts with param 1.</returns> public static bool StartsWith(this byte[] thisBytes, byte[] thatBytes) { return(ByteHelper.StartsWith(thatBytes, thisBytes)); }
public override unsafe void Load(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentException("ICO.Load(string)\n\tPath cannot be null or empty"); } if (!File.Exists(path)) { throw new ArgumentException("ICO.Load(string)\n\tFile does not exist"); } this.Clear(); using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) { byte[] bytes = new byte[6]; fileStream.Read(bytes, 0, bytes.Length); if (!ByteHelper.StartsWith(bytes, IdentifierBytes_1)) { throw new Exception("ICO.Load(string)\n\tInvalid .ico file"); } int imageCount = ByteHelper.ReadInt16LE(bytes, 4); this.Images = new Bitmap[imageCount]; this.selectedImageIndex = 0; long streamPosition = -1; for (int i = 0; i < imageCount; i++) { try { byte[] imageDirectory = new byte[8]; fileStream.Read(imageDirectory, 0, imageDirectory.Length); int width = 0; int height = 0; // if the width is 256 its saved as 0x00 if (imageDirectory[0] == 0x00) { width = 256; } else { width = (byte)imageDirectory[0]; } // if the height is 256 its saved as 0x00 if (imageDirectory[1] == 0x00) { height = 256; } else { height = (byte)imageDirectory[1]; } // reserved should be 0 if (imageDirectory[3] != 0x00) { continue; } int colorPlanes = ByteHelper.ReadInt16LE(imageDirectory, 4); // should be 0 or 1 if (colorPlanes != 0 && colorPlanes != 1) { continue; } int bitsPerPixel = ByteHelper.ReadInt16LE(imageDirectory, 6); int imageDataSize = ByteHelper.ReadInt32LE(fileStream); int imageDataOffset = ByteHelper.ReadInt32LE(fileStream); streamPosition = fileStream.Position; // seek to the image data start fileStream.Seek(imageDataOffset, SeekOrigin.Begin); // get the image data byte[] imageData = new byte[imageDataSize]; fileStream.Read(imageData, 0, imageData.Length); // reset the position fileStream.Seek(streamPosition, SeekOrigin.Begin); // if the image is stored as a png, use a memory stream to read the image if (ByteHelper.StartsWith(imageData, PNG.IdentifierBytes_1)) { MemoryStream mem = new MemoryStream(); mem.Write(imageData, 0, imageData.Length); this.Images[i] = (Bitmap)System.Drawing.Image.FromStream(mem); continue; } int dipHeaderSize = ByteHelper.ReadInt32LE(imageData, 0); int index = dipHeaderSize; Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); this.Images[i] = bmp; BitmapData dstBD = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); byte *pDst = (byte *)(void *)dstBD.Scan0; for (int ii = 0; ii < bmp.Width * bmp.Height; ii++) { *pDst = (byte)(imageData[index]); // B pDst++; index++; *pDst = (byte)(imageData[index]); // G pDst++; index++; *pDst = (byte)(imageData[index]); // R pDst++; index++; if (bitsPerPixel == 32) { *pDst = (byte)(imageData[index]); // a index++; } else { *pDst = (byte)255; // a } pDst++; } bmp.UnlockBits(dstBD); // since the ico stores the bitmap data upside down // flip the image bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); } catch { // chances are the error was thrown when building the image // so at least try and get the others if (streamPosition != -1) { fileStream.Seek(streamPosition, SeekOrigin.Begin); } continue; } } } }