Example #1
0
        /// <summary>
        /// Gets the PLTE chunk of the parent image and throws an exception if it is not present.
        /// </summary>
        /// <returns>The PLTE chunk of the parent image.</returns>
        /// <exception cref="ChunkNotFoundException" />
        protected PLTEChunk GetAssertPLTEChunk()
        {
            PLTEChunk chunk = _image.Chunks["PLTE"] as PLTEChunk;

            if (chunk == null)
            {
                throw new ChunkNotFoundException("PLTE chunk not found.");
            }

            return(chunk);
        }
Example #2
0
        public Color GetEffectiveBackgroundColor()
        {
            IHDRChunk hdr = this.GetAssertIHDRChunk();

            switch (hdr.ColorType)
            {
            case ColorType.Grayscale:
            case ColorType.GrayscaleWithAlpha:
                if (hdr.BitDepth == 1)
                {
                    return(Utils.MakeGray((_backgroundColor.Gray & 0x1) * 255));
                }
                else if (hdr.BitDepth == 2)
                {
                    return(Utils.MakeGray((_backgroundColor.Gray & 0x3) * 255 / 3));
                }
                else if (hdr.BitDepth == 4)
                {
                    return(Utils.MakeGray((_backgroundColor.Gray & 0xf) * 255 / 15));
                }
                else if (hdr.BitDepth == 8)
                {
                    return(Utils.MakeGray(_backgroundColor.Gray & 0xff));
                }
                else if (hdr.BitDepth == 16)
                {
                    return(Utils.MakeGray(_backgroundColor.Gray * 255 / 65535));
                }
                else
                {
                    throw new InvalidChunkDataException("Invalid bit depth.");
                }

            case ColorType.Truecolor:
            case ColorType.TruecolorWithAlpha:
                if (hdr.BitDepth == 8)
                {
                    return(Color.FromArgb(
                               _backgroundColor.Red & 0xff,
                               _backgroundColor.Green & 0xff,
                               _backgroundColor.Blue & 0xff));
                }
                else if (hdr.BitDepth == 16)
                {
                    return(Color.FromArgb(
                               _backgroundColor.Red * 255 / 65535,
                               _backgroundColor.Green * 255 / 65535,
                               _backgroundColor.Blue * 255 / 65535));
                }
                else
                {
                    throw new InvalidChunkDataException("Invalid bit depth.");
                }

            case ColorType.IndexedColor:
                PLTEChunk plte = this.GetAssertPLTEChunk();

                return(plte.Entries[_backgroundColor.Index]);

            default:
                throw new InvalidChunkDataException("Invalid color type.");
            }
        }
Example #3
0
        /// <summary>
        /// Reads the image pixels and stores them in Bitmap.
        /// </summary>
        /// <param name="data">The image bytes.</param>
        private void Read(byte[] data)
        {
            // optimized for speed (it's very slow already)

            IHDRChunk hdr      = _image.Chunks["IHDR"] as IHDRChunk;
            int       width    = (int)hdr.Width;
            int       height   = (int)hdr.Height;
            byte      bitDepth = hdr.BitDepth;

            _bitmap         = CreateBitmap(hdr.ColorType, hdr.BitDepth, width, height);
            _scanlineLength = Utils.IntCeilDiv(Utils.GetBitsPerPixel(hdr.ColorType, hdr.BitDepth) * width, 8) + 1;
            _bpp            = Utils.GetBytesPerPixel(hdr.ColorType, hdr.BitDepth); // bytes per pixel

            byte[] decoded = null;

            // palette
            PLTEChunk palette = _image.Chunks["PLTE"] as PLTEChunk;

            #region tRNS Chunk

            tRNSChunk trns     = _image.Chunks["tRNS"] as tRNSChunk;
            int       tGray1   = -1;
            int       tGray2   = -1;
            int       tGray4   = -1;
            int       tGray8   = -1;
            int       tGray16  = -1;
            Color     tRgb8    = Color.FromArgb(0, 0, 0, 0);
            Color     tRgb16   = Color.FromArgb(0, 0, 0, 0);
            int[]     tPalette = null;

            if (trns != null)
            {
                tGray1  = trns.Gray & 0x1;
                tGray2  = trns.Gray & 0x3;
                tGray4  = trns.Gray & 0xf;
                tGray8  = trns.Gray & 0xff;
                tGray16 = trns.Gray;
                tRgb8   = Color.FromArgb(trns.Red & 0xff, trns.Green & 0xff, trns.Blue & 0xff);
                tRgb16  = Color.FromArgb(trns.Red * 255 / 65535, trns.Green * 255 / 65535, trns.Blue * 255 / 65535);

                if (palette != null)
                {
                    tPalette = new int[palette.Entries.Length];

                    for (int i = 0; i < tPalette.Length; i++)
                    {
                        if (i < trns.PaletteAlpha.Length)
                        {
                            tPalette[i] = trns.PaletteAlpha[i];
                        }
                        else
                        {
                            tPalette[i] = 255;
                        }
                    }
                }
            }
            else
            {
                if (palette != null)
                {
                    tPalette = new int[palette.Entries.Length];

                    for (int i = 0; i < tPalette.Length; i++)
                    {
                        tPalette[i] = 255;
                    }
                }
            }

            #endregion

            if (hdr.InterlaceMethod == InterlaceMethod.Adam7)
            {
                #region Adam7

                for (int pass = 0; pass < _adam7.Length; pass++)
                {
                }

                #endregion
            }
            else
            {
                #region Normal

                for (int line = 0; line < data.Length / _scanlineLength; line++)
                {
                    decoded = this.Defilter(data, line, decoded);

                    switch (hdr.ColorType)
                    {
                    case ColorType.Grayscale:
                        if (bitDepth == 1)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 8); i++)
                            {
                                int[] pixels = new int[8];

                                for (int j = 0; j < 8; j++)
                                {
                                    pixels[j] = (decoded[i] >> (7 - j)) & 0x1;
                                }

                                for (int j = 0; j < 8; j++)
                                {
                                    if (i * 8 + j < hdr.Width)
                                    {
                                        _bitmap.SetPixel(i * 8 + j, line,
                                                         Utils.MakeGray(pixels[j] == tGray1 ? 0 : 255, pixels[j] * 255));
                                    }
                                }
                            }
                        }
                        else if (bitDepth == 2)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 4); i++)
                            {
                                int[] pixels = new int[4];

                                for (int j = 0; j < 4; j++)
                                {
                                    pixels[j] = (decoded[i] >> ((3 - j) * 2)) & 0x3;
                                }

                                for (int j = 0; j < 4; j++)
                                {
                                    if (i * 4 + j < hdr.Width)
                                    {
                                        _bitmap.SetPixel(i * 4 + j, line,
                                                         Utils.MakeGray(pixels[j] == tGray2 ? 0 : 255, pixels[j] * 255 / 3));
                                    }
                                }
                            }
                        }
                        else if (bitDepth == 4)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 2); i++)
                            {
                                int pixel1 = decoded[i] >> 4;     // upper four bits
                                int pixel2 = decoded[i] & 0xf;    // lower two bits

                                _bitmap.SetPixel(i * 2, line, Utils.MakeGray(
                                                     pixel1 == tGray4 ? 0 : 255, pixel1 * 255 / 15));

                                if (i * 2 + 1 < hdr.Width)
                                {
                                    _bitmap.SetPixel(i * 2 + 1, line, Utils.MakeGray(
                                                         pixel2 == tGray4 ? 0 : 255, pixel2 * 255 / 15));
                                }
                            }
                        }
                        else if (bitDepth == 8)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line,
                                                 Utils.MakeGray(decoded[i] == tGray8 ? 0 : 255, decoded[i]));
                            }
                        }
                        else if (bitDepth == 16)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                int value = Utils.BytesToUShort(decoded, i * 2, Utils.Endianness.Big);

                                _bitmap.SetPixel(i, line, Utils.MakeGray(
                                                     value == tGray16 ? 0 : 255, value * 255 / 65535));
                            }
                        }

                        break;

                    case ColorType.GrayscaleWithAlpha:
                        if (bitDepth == 8)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     decoded[i * 2 + 1],
                                                     decoded[i * 2], decoded[i * 2], decoded[i * 2]
                                                     ));
                            }
                        }
                        else if (bitDepth == 16)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     Utils.BytesToUShort(decoded, i * 4 + 2, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 4, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 4, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 4, Utils.Endianness.Big) * 255 / 65535
                                                     ));
                            }
                        }

                        break;

                    case ColorType.IndexedColor:
                        if (bitDepth == 1)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 8); i++)
                            {
                                int[] pixels = new int[8];

                                for (int j = 0; j < 8; j++)
                                {
                                    pixels[j] = (decoded[i] >> (7 - j)) & 0x1;
                                }

                                for (int j = 0; j < 8; j++)
                                {
                                    if (i * 8 + j < hdr.Width)
                                    {
                                        _bitmap.SetPixel(i * 8 + j, line,
                                                         Color.FromArgb(tPalette[pixels[j]], palette.Entries[pixels[j]]));
                                    }
                                }
                            }
                        }
                        else if (bitDepth == 2)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 4); i++)
                            {
                                int[] pixels = new int[4];

                                for (int j = 0; j < 4; j++)
                                {
                                    pixels[j] = (decoded[i] >> ((3 - j) * 2)) & 0x3;
                                }

                                for (int j = 0; j < 4; j++)
                                {
                                    if (i * 4 + j < hdr.Width)
                                    {
                                        _bitmap.SetPixel(i * 4 + j, line,
                                                         Color.FromArgb(tPalette[pixels[j]], palette.Entries[pixels[j]]));
                                    }
                                }
                            }
                        }
                        else if (bitDepth == 4)
                        {
                            for (int i = 0; i < Utils.IntCeilDiv(width, 2); i++)
                            {
                                int pixel1 = decoded[i] >> 4;     // upper four bits
                                int pixel2 = decoded[i] & 0xf;    // lower two bits

                                _bitmap.SetPixel(i * 2, line,
                                                 Color.FromArgb(tPalette[pixel1], palette.Entries[pixel1]));

                                if (i * 2 + 1 < hdr.Width)
                                {
                                    _bitmap.SetPixel(i * 2 + 1, line,
                                                     Color.FromArgb(tPalette[pixel2], palette.Entries[pixel2]));
                                }
                            }
                        }
                        else if (bitDepth == 8)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line,
                                                 Color.FromArgb(tPalette[decoded[i]], palette.Entries[decoded[i]]));
                            }
                        }

                        break;

                    case ColorType.Truecolor:
                        if (bitDepth == 8)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                Color c = Color.FromArgb(
                                    decoded[i * 3],
                                    decoded[i * 3 + 1],
                                    decoded[i * 3 + 2]
                                    );

                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     Utils.ColorsEqual(c, tRgb8) ? 0 : 255, c));
                            }
                        }
                        else if (bitDepth == 16)
                        {
                            // .NET doesn't support 16-bit bit depths
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                Color c = Color.FromArgb(
                                    Utils.BytesToUShort(decoded, i * 6, Utils.Endianness.Big) * 255 / 65535,
                                    Utils.BytesToUShort(decoded, i * 6 + 2, Utils.Endianness.Big) * 255 / 65535,
                                    Utils.BytesToUShort(decoded, i * 6 + 4, Utils.Endianness.Big) * 255 / 65535
                                    );

                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     Utils.ColorsEqual(c, tRgb16) ? 0 : 255, c));
                            }
                        }

                        break;

                    case ColorType.TruecolorWithAlpha:
                        if (bitDepth == 8)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     decoded[i * 4 + 3],
                                                     decoded[i * 4],
                                                     decoded[i * 4 + 1],
                                                     decoded[i * 4 + 2]));
                            }
                        }
                        else if (bitDepth == 16)
                        {
                            for (int i = 0; i < hdr.Width; i++)
                            {
                                _bitmap.SetPixel(i, line, Color.FromArgb(
                                                     Utils.BytesToUShort(decoded, i * 8 + 6, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 8, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 8 + 2, Utils.Endianness.Big) * 255 / 65535,
                                                     Utils.BytesToUShort(decoded, i * 8 + 4, Utils.Endianness.Big) * 255 / 65535
                                                     ));
                            }
                        }

                        break;

                    default:
                        throw new Exception("Invalid color type.");
                    }
                }

                #endregion
            }
        }