예제 #1
0
        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));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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));
        }
예제 #4
0
        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));
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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);
                }
            }
        }