Пример #1
0
        private static Size DecodeTiffLE(BinaryReader binaryReader)
        {
            if (binaryReader.ReadByte() != 0)
            {
                return(Size.Empty);
            }

            int idfStart = ByteHelper.ReadInt32LE(binaryReader);

            binaryReader.BaseStream.Seek(idfStart, SeekOrigin.Begin);

            int numberOfIDF = ByteHelper.ReadInt16LE(binaryReader);

            int width  = -1;
            int height = -1;

            for (int i = 0; i < numberOfIDF; i++)
            {
                short field = ByteHelper.ReadInt16LE(binaryReader);

                switch (field)
                {
                // https://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
                default:
                    binaryReader.ReadBytes(10);
                    break;

                case 256:     // image width
                    binaryReader.ReadBytes(6);
                    width = ByteHelper.ReadInt32LE(binaryReader);
                    break;

                case 257:     // image length
                    binaryReader.ReadBytes(6);
                    height = ByteHelper.ReadInt32LE(binaryReader);
                    break;
                }
                if (width != -1 && height != -1)
                {
                    return(new Size(width, height));
                }
            }
            return(Size.Empty);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
 /// <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));
 }
Пример #4
0
        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;
                    }
                }
            }
        }
Пример #5
0
        // https://www.cyotek.com/blog/reading-photoshop-color-swatch-aco-files-using-csharp
        private static List <Color> ReadSwatches(Stream stream, FileVersion version)
        {
            int          colorCount;
            List <Color> results;

            results = new List <Color>();

            // read the number of colors, which also occupies two bytes
            colorCount = ByteHelper.ReadInt16BE(stream);

            for (int i = 0; i < colorCount; i++)
            {
                ColorSpace colorSpace;
                int        value1;
                int        value2;
                int        value3;
                int        value4;

                // again, two bytes for the color space
                colorSpace = (ColorSpace)(ByteHelper.ReadInt16BE(stream));

                value1 = ByteHelper.ReadInt16BE(stream);
                value2 = ByteHelper.ReadInt16BE(stream);
                value3 = ByteHelper.ReadInt16BE(stream);
                value4 = ByteHelper.ReadInt16BE(stream);

                if (version == FileVersion.Version2)
                {
                    int length;

                    // need to read the name even though currently our colour collection doesn't support names
                    length = ByteHelper.ReadInt32BE(stream);
                    Helper.ReadString(stream, length);
                }

                switch (colorSpace)
                {
                case ColorSpace.Rgb:
                    int red;
                    int green;
                    int blue;

                    // RGB.
                    // The first three values in the color data are red , green , and blue . They are full unsigned
                    //  16-bit values as in Apple's RGBColor data structure. Pure red = 65535, 0, 0.

                    red   = value1 / 256;   // 0-255
                    green = value2 / 256;   // 0-255
                    blue  = value3 / 256;   // 0-255

                    results.Add(ARGB.FromARGB(red.ToByte(), green.ToByte(), blue.ToByte()));
                    break;

                case ColorSpace.Hsb:
                    float hue;
                    float saturation;
                    float brightness;

                    // HSB.
                    // The first three values in the color data are hue , saturation , and brightness . They are full
                    // unsigned 16-bit values as in Apple's HSVColor data structure. Pure red = 0,65535, 65535.

                    hue        = value1 / 182.04f; // 0-359
                    saturation = value2 / 655.35f; // 0-100
                    brightness = value3 / 655.35f; // 0-100

                    results.Add(new HSB(hue, saturation, brightness).ToColor());
                    break;

                case ColorSpace.Grayscale:

                    int gray;

                    // Grayscale.
                    // The first value in the color data is the gray value, from 0...10000.

                    gray = (int)(value1 / 39.0625);     // 0-255

                    results.Add(ARGB.FromARGB(gray.ToByte(), gray.ToByte(), gray.ToByte()));
                    break;

                default:
                    throw new InvalidDataException(string.Format("Color space '{0}' not supported.", colorSpace));
                }
            }

            return(results);
        }
Пример #6
0
        // https://www.cyotek.com/blog/loading-the-color-palette-from-a-bbm-lbm-image-file-using-csharp#files
        public static List <Color> ReadColorMap(string fileName)
        {
            List <Color> colorPalette;

            colorPalette = new List <Color>();

            using (FileStream stream = File.OpenRead(fileName))
            {
                byte[] buffer;
                string header;

                // read the FORM header that identifies the document as an IFF file
                buffer = new byte[4];
                stream.Read(buffer, 0, buffer.Length);
                if (Encoding.ASCII.GetString(buffer) != "FORM")
                {
                    throw new InvalidDataException("Form header not found.");
                }

                // the next value is the size of all the data in the FORM chunk
                // We don't actually need this value, but we have to read it
                // regardless to advance the stream
                ByteHelper.ReadInt32BE(stream);

                // read either the PBM or ILBM header that identifies this document as an image file
                stream.Read(buffer, 0, buffer.Length);
                header = Encoding.ASCII.GetString(buffer);
                if (header != "PBM " && header != "ILBM")
                {
                    throw new InvalidDataException("Bitmap header not found.");
                }

                while (stream.Read(buffer, 0, buffer.Length) == buffer.Length)
                {
                    int chunkLength;

                    chunkLength = ByteHelper.ReadInt32BE(stream);

                    if (Encoding.ASCII.GetString(buffer) != "CMAP")
                    {
                        // some other LBM chunk, skip it
                        if (stream.CanSeek)
                        {
                            stream.Seek(chunkLength, SeekOrigin.Current);
                        }
                        else
                        {
                            for (int i = 0; i < chunkLength; i++)
                            {
                                stream.ReadByte();
                            }
                        }
                    }
                    else
                    {
                        // color map chunk!
                        for (int i = 0; i < chunkLength / 3; i++)
                        {
                            int r;
                            int g;
                            int b;

                            r = stream.ReadByte();
                            g = stream.ReadByte();
                            b = stream.ReadByte();

                            colorPalette.Add(ARGB.FromARGB(255, r.ToByte(), g.ToByte(), b.ToByte()));
                        }

                        // all done so stop reading the rest of the file
                        break;
                    }

                    // chunks always contain an even number of bytes even if the recorded length is odd
                    // if the length is odd, then there's a padding byte in the file - just read and discard
                    if (chunkLength % 2 != 0)
                    {
                        stream.ReadByte();
                    }
                }
            }

            return(colorPalette);
        }