private static Size DecodeBitmap(SequentialBinaryReader reader) { var magicNumber = reader.ReadUInt16(); // skip past the rest of the file header reader.Skip(4 + 2 + 2 + 4); int headerSize = reader.ReadInt32(); int width, height; // We expect the header size to be either 40 (BITMAPINFOHEADER) or 12 (BITMAPCOREHEADER) if (headerSize == 40) { // BITMAPINFOHEADER width = reader.ReadInt32(); height = Math.Abs(reader.ReadInt32()); } else if (headerSize == 12) { width = reader.ReadInt16(); height = reader.ReadInt16(); } else { // Unexpected DIB header size return(Size.Empty); } return(new Size(width, height)); }
private static Size DecodeEmf(SequentialBinaryReader reader) { // EMR_HEADER: Type + Size + Bounds reader.Skip(4 + 4 + 16); // Frame: specify the rectangular inclusive-inclusive dimensions, // in .01 millimeter units, of a rectangle that surrounds the image stored in the metafile. int left = reader.ReadInt32(); int top = reader.ReadInt32(); int right = reader.ReadInt32(); int bottom = reader.ReadInt32(); // Skip other headers: // Signature (4) + Version (4) + Size (4) + Records (4) + Handles (2) // + nReserved (2) + nDescription (4) + offDescription (4) + PalEntries (4) reader.Skip(32); // Next 8 bytes specify the size of the reference device, in pixels int deviceSizeInPixelX = reader.ReadInt32(); int deviceSizeInPixelY = reader.ReadInt32(); // Then 8 more to specify the size of the reference device, in millimeters int deviceSizeInMlmX = reader.ReadInt32(); int deviceSizeInMlmY = reader.ReadInt32(); int widthInPixel = (int)Math.Round(0.5 + ((right - left + 1.0) * deviceSizeInPixelX / deviceSizeInMlmX) / 100.0); int heightInPixel = (int)Math.Round(0.5 + ((bottom - top + 1.0) * deviceSizeInPixelY / deviceSizeInMlmY) / 100.0); return(new Size(widthInPixel, heightInPixel)); }
private static Size DecodePng(SequentialBinaryReader reader) { reader.IsBigEndian = true; reader.ReadBytes(pngSignatureBytes.Length); reader.Skip(8); int width = reader.ReadInt32(); int height = reader.ReadInt32(); return(new Size(width, height)); }
private static Size DecodeGif(SequentialBinaryReader reader) { // 3 - signature: "GIF" // 3 - version: either "87a" or "89a" reader.Skip(6); int width = reader.ReadInt16(); int height = reader.ReadInt16(); return(new Size(width, height)); }
/// <summary> /// Examines the a file's first bytes and estimates the file's type. /// </summary> private static FileType DetectFileType(SequentialBinaryReader reader) { byte[] magicBytes = new byte[MaxMagicBytesLength]; for (int i = 0; i < MaxMagicBytesLength; i += 1) { magicBytes[i] = reader.ReadByte(); foreach (var kvPair in imageFormatDecoders) { if (StartsWith(magicBytes, kvPair.Key)) { return(kvPair.Value); } } } return(FileType.Unrecognized); }
private static Size DecodeJfif(SequentialBinaryReader reader) { reader.IsBigEndian = true; var magicNumber = reader.ReadUInt16(); // first two bytes should be JPEG magic number do { // Find next segment marker. Markers are zero or more 0xFF bytes, followed // by a 0xFF and then a byte not equal to 0x00 or 0xFF. byte segmentIdentifier = reader.ReadByte(); byte segmentType = reader.ReadByte(); // Read until we have a 0xFF byte followed by a byte that is not 0xFF or 0x00 while (segmentIdentifier != 0xFF || segmentType == 0xFF || segmentType == 0) { segmentIdentifier = segmentType; segmentType = reader.ReadByte(); } if (segmentType == 0xD9) // EOF? { return(Size.Empty); } // next 2-bytes are <segment-size>: [high-byte] [low-byte] var segmentLength = (int)reader.ReadUInt16(); // segment length includes size bytes, so subtract two segmentLength -= 2; if (segmentType == 0xC0 || segmentType == 0xC2) { reader.ReadByte(); // bits/sample, usually 8 int height = (int)reader.ReadUInt16(); int width = (int)reader.ReadUInt16(); return(new Size(width, height)); } else { // skip this segment reader.Skip(segmentLength); } }while (true); }
/// <summary> /// Gets the dimensions of an image. /// </summary> /// <param name="stream">The content of the image.</param> /// <returns>The dimensions of the specified image.</returns> /// <exception cref="ArgumentException">The image was of an unrecognised format.</exception> public static Size GetDimensions(Stream stream) { using (SequentialBinaryReader reader = new SequentialBinaryReader(stream)) { FileType type = DetectFileType(reader); stream.Seek(0L, SeekOrigin.Begin); switch (type) { case FileType.Bitmap: return(DecodeBitmap(reader)); case FileType.Gif: return(DecodeGif(reader)); case FileType.Jpeg: return(DecodeJfif(reader)); case FileType.Png: return(DecodePng(reader)); default: return(Size.Empty); } } }