Beispiel #1
0
 internal ImageLine( ImageInfo imgInfo, ESampleType stype, bool unpackedMode, int [] sci, byte [] scb )
 {
     this.ImgInfo = imgInfo;
     channels = imgInfo.Channels;
     this.bitDepth = imgInfo.BitDepth;
     this.FilterUsed = FilterType.FILTER_UNKNOWN;
     this.SampleType = stype;
     this.SamplesUnpacked = unpackedMode || !imgInfo.Packed;
     ElementsPerRow = this.SamplesUnpacked ? imgInfo.SamplesPerRow
         : imgInfo.SamplesPerRowPacked;
     if ( stype == ESampleType.INT )
     {
         Scanline = sci != null ? sci : new int [ ElementsPerRow ];
         ScanlineB = null;
         maxSampleVal = bitDepth == 16 ? 0xFFFF : GetMaskForPackedFormatsLs ( bitDepth );
     }
     else if ( stype == ESampleType.BYTE )
     {
         ScanlineB = scb != null ? scb : new byte [ ElementsPerRow ];
         Scanline = null;
         maxSampleVal = bitDepth == 16 ? 0xFF : GetMaskForPackedFormatsLs ( bitDepth );
     }
     else
         throw new PngjExceptionInternal ( "bad ImageLine initialization" );
     this.Rown = -1;
 }
        /// <summary>
        /// Encodes a raw file buffer of image data into a PNG image.
        /// </summary>
        /// <param name="outputStream">Png bytes.</param>
        public ImageLines Translate(ImageData image, IProgress prog = null)
        {
            if (image is null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            var imageInfo = new Hjg.Pngcs.ImageInfo(
                image.Info.Dimensions.Width,
                image.Info.Dimensions.Height,
                image.Info.BitsPerSample / image.Info.Components,
                image.Info.Components == 4);

            var imageLines = new ImageLines(
                imageInfo,
                ImageLine.ESampleType.BYTE,
                true,
                0,
                image.Info.Dimensions.Height,
                image.Info.Stride);

            for (var y = 0; y < image.Info.Dimensions.Height; ++y)
            {
                prog.Report(y, image.Info.Dimensions.Height);
                var dataIndex = y * image.Info.Stride;
                var line      = imageLines.ScanlinesB[y];
                Array.Copy(image.GetData(), dataIndex, line, 0, image.Info.Stride);
                prog.Report(y + 1, image.Info.Dimensions.Height);
            }

            return(imageLines);
        }
Beispiel #3
0
 public static ImageLine generateNoiseLine(ImageInfo imi)
 {
     // byte format!
     ImageLine line = new ImageLine(imi, ImageLine.ESampleType.BYTE, true);
     Random r = new Random();
     r.NextBytes(line.ScanlineB);
     return line;
 }
Beispiel #4
0
 public static byte[] Pack( ImageInfo imgInfo, byte [] src, byte [] dst, bool scale )
 {
     int len0 = imgInfo.SamplesPerRowPacked;
     if ( dst == null || dst.Length < len0 )
         dst = new byte [ len0 ];
     if ( imgInfo.Packed )
         ImageLine.packInplaceByte ( imgInfo, src, dst, scale );
     else
         Array.Copy ( src, 0, dst, 0, len0 );
     return dst;
 }
Beispiel #5
0
 private static void mirrorLineInt(ImageInfo imgInfo, int[] line)
 {
     // unpacked line
     int channels = imgInfo.Channels;
     for (int c1 = 0, c2 = imgInfo.Cols - 1; c1 < c2; c1++, c2--) { // swap pixels (not samples!)
         for (int i = 0; i < channels; i++) {
             int aux = line[c1 * channels + i];
             line[c1 * channels + i] = line[c2 * channels + i];
             line[c2 * channels + i] = aux;
         }
     }
 }
Beispiel #6
0
 public PngReader( Stream inputStream, String filename )
 {
     this.filename = ( filename == null ) ? "" : filename;
     this.inputStream = inputStream;
     this.chunksList = new ChunksList ( null );
     this.metadata = new PngMetadata ( chunksList );
     this.offset = 0;
     this.CurrentChunkGroup = -1;
     this.ShouldCloseStream = true;
     this.MaxBytesMetadata = 5 * 1024 * 1024;
     this.MaxTotalBytesRead = 200 * 1024 * 1024;
     this.SkipChunkMaxSize = 2 * 1024 * 1024;
     this.SkipChunkIds = new string [] { "fdAT" };
     this.ChunkLoadBehaviour = Hjg.Pngcs.Chunks.ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS;
     byte [] pngid = new byte [ 8 ];
     PngHelperInternal.ReadBytes ( inputStream, pngid, 0, pngid.Length );
     offset += pngid.Length;
     if ( !PngCsUtils.arraysEqual ( pngid, PngHelperInternal.PNG_ID_SIGNATURE ) )
         throw new PngjInputException ( "Bad PNG signature" );
     CurrentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
     int clen = PngHelperInternal.ReadInt4 ( inputStream );
     offset += 4;
     if ( clen != 13 )
         throw new Exception ( "IDHR chunk len != 13 ?? " + clen );
     byte [] chunkid = new byte [ 4 ];
     PngHelperInternal.ReadBytes ( inputStream, chunkid, 0, 4 );
     if ( !PngCsUtils.arraysEqual4 ( chunkid, ChunkHelper.b_IHDR ) )
         throw new PngjInputException ( "IHDR not found as first chunk??? ["
                 + ChunkHelper.ToString ( chunkid ) + "]" );
     offset += 4;
     PngChunkIHDR ihdr = ( PngChunkIHDR ) ReadChunk ( chunkid, clen, false );
     bool alpha = ( ihdr.Colormodel & 0x04 ) != 0;
     bool palette = ( ihdr.Colormodel & 0x01 ) != 0;
     bool grayscale = ( ihdr.Colormodel == 0 || ihdr.Colormodel == 4 );
     ImgInfo = new ImageInfo ( ihdr.Cols, ihdr.Rows, ihdr.Bitspc, alpha, grayscale, palette );
     rowb = new byte [ ImgInfo.BytesPerRow + 1 ];
     rowbprev = new byte [ rowb.Length ];
     rowbfilter = new byte [ rowb.Length ];
     interlaced = ihdr.Interlaced == 1;
     deinterlacer = interlaced ? new PngDeinterlacer ( ImgInfo ) : null;
     if ( ihdr.Filmeth != 0 || ihdr.Compmeth != 0 || ( ihdr.Interlaced & 0xFFFE ) != 0 )
         throw new PngjInputException ( "compmethod or filtermethod or interlaced unrecognized" );
     if ( ihdr.Colormodel < 0 || ihdr.Colormodel > 6 || ihdr.Colormodel == 1
             || ihdr.Colormodel == 5 )
         throw new PngjInputException ( "Invalid colormodel " + ihdr.Colormodel );
     if ( ihdr.Bitspc != 1 && ihdr.Bitspc != 2 && ihdr.Bitspc != 4 && ihdr.Bitspc != 8
             && ihdr.Bitspc != 16 )
         throw new PngjInputException ( "Invalid bit depth " + ihdr.Bitspc );
 }
Beispiel #7
0
        public ImageLines Concatenate(ImageLines[,] images, IProgress prog = null)
        {
            if (images is null)
            {
                throw new ArgumentNullException(nameof(images));
            }

            this.ValidateImages(images, prog,
                                out var rows, out var columns, out var components,
                                out var tileWidth,
                                out var tileHeight);

            var combinedInfo = new Hjg.Pngcs.ImageInfo(
                columns * tileWidth,
                rows * tileHeight,
                Units.Bits.PER_BYTE,
                components == 4);

            var combinedLines = new ImageLines(
                combinedInfo,
                ImageLine.ESampleType.BYTE,
                true,
                0,
                rows * tileHeight,
                rows * tileHeight * components);

            for (var y = 0; y < rows; ++y)
            {
                for (var x = 0; x < columns; ++x)
                {
                    var tile = images[y, x];
                    if (tile is object)
                    {
                        for (var i = 0; i < tileHeight; ++i)
                        {
                            var bufferY    = (y * tileHeight) + i;
                            var bufferX    = x * tileWidth;
                            var bufferLine = combinedLines.ScanlinesB[bufferY];
                            var tileLine   = tile.ScanlinesB[i];
                            Array.Copy(tileLine, 0, bufferLine, bufferX, tileLine.Length);
                        }
                    }
                }
            }

            return(combinedLines);
        }
        private double[] preference = new double[] { 1.1, 1.1, 1.1, 1.1, 1.2 }; // a priori preference (NONE SUB UP AVERAGE PAETH)

        #endregion Fields

        #region Constructors

        internal FilterWriteStrategy(ImageInfo imgInfo, FilterType configuredType)
        {
            this.imgInfo = imgInfo;
            this.configuredType = configuredType;
            if (configuredType < 0) { // first guess
                if ((imgInfo.Rows < 8 && imgInfo.Cols < 8) || imgInfo.Indexed
                        || imgInfo.BitDepth < 8)
                    currentType = FilterType.FILTER_NONE;
                else
                    currentType = FilterType.FILTER_PAETH;
            } else {
                currentType = configuredType;
            }
            if (configuredType == FilterType.FILTER_AGGRESSIVE)
                discoverEachLines = COMPUTE_STATS_EVERY_N_LINES;
            if (configuredType == FilterType.FILTER_VERYAGGRESSIVE)
                discoverEachLines = 1;
        }
        private int rows, cols, dY, dX, oY, oX, oXsamples, dXsamples; // at current pass

        #endregion Fields

        #region Constructors

        internal PngDeinterlacer(ImageInfo iminfo)
        {
            this.imi = iminfo;
            pass = 0;
            if (imi.Packed) {
                packedValsPerPixel = 8 / imi.BitDepth;
                packedShift = imi.BitDepth;
                if (imi.BitDepth == 1)
                    packedMask = 0x80;
                else if (imi.BitDepth == 2)
                    packedMask = 0xc0;
                else
                    packedMask = 0xf0;
            } else {
                packedMask = packedShift = packedValsPerPixel = 1;// dont care
            }
            setPass(1);
            setRow(0);
        }
Beispiel #10
0
        public PngWriter( Stream outputStream, ImageInfo imgInfo,
				String filename )
        {
            this.filename = ( filename == null ) ? "" : filename;
            this.outputStream = outputStream;
            this.ImgInfo = imgInfo;
            this.CompLevel = 6;
            this.ShouldCloseStream = true;
            this.IdatMaxSize = 0;
            this.CompressionStrategy = EDeflateCompressStrategy.Filtered;
            rowb = new byte [ imgInfo.BytesPerRow + 1 ];
            rowbprev = new byte [ rowb.Length ];
            rowbfilter = new byte [ rowb.Length ];
            chunksList = new ChunksListForWrite ( ImgInfo );
            metadata = new PngMetadata ( chunksList );
            filterStrat = new FilterWriteStrategy ( ImgInfo, FilterType.FILTER_DEFAULT );
            unpackedMode = false;
            needsPack = unpackedMode && imgInfo.Packed;
        }
 public static void Create(string filename, int cols, int rows)
 {
     ImageInfo imi = new ImageInfo(cols, rows, 8, false); // 8 bits per channel, no alpha
     // open image for writing
     PngWriter png = FileHelper.CreatePngWriter(filename, imi, true);
     // add some optional metadata (chunks)
     png.GetMetadata().SetDpi(100.0);
     png.GetMetadata().SetTimeNow(0); // 0 seconds fron now = now
     png.GetMetadata().SetText(PngChunkTextVar.KEY_Title, "Just a text image");
     PngChunk chunk = png.GetMetadata().SetText("my key", "my text .. bla bla");
     chunk.Priority = true; // this chunk will be written as soon as possible
     ImageLine iline = new ImageLine(imi);
     for (int col = 0; col < imi.Cols; col++) { // this line will be written to all rows
         int r = 255;
         int g = 127;
         int b = 255 * col / imi.Cols;
         ImageLineHelper.SetPixel(iline , col, r, g, b); // orange-ish gradient
     }
     for (int row = 0; row < png.ImgInfo.Rows; row++) {
         png.WriteRow(iline, row);
     }
     png.End();
 }
Beispiel #12
0
 public static string createWaves(String suffix, double scale, ImageInfo imi)
 {
     string f = getTmpFile(suffix);
     // open image for writing to a output stream
     PngWriter png = FileHelper.CreatePngWriter(f, imi, true);
     png.GetMetadata().SetText("key1", "val1");
     ImageLine iline = new ImageLine(imi, ImageLine.ESampleType.BYTE, true);
     for (int row = 0; row < png.ImgInfo.Rows; row++) {
         for (int x = 0; x < imi.Cols; x++) {
             int r = (int)((Math.Sin((row + x) * 0.073 * scale) + 1) * 128);
             int g = (int)((Math.Sin((row + x * 0.22) * 0.08 * scale) + 1) * 128);
             int b = (int)((Math.Sin((row * 0.52 - x * 0.2) * 0.21 * scale) + 1) * 128);
             iline.ScanlineB[x * imi.Channels] = (byte)r;
             iline.ScanlineB[x * imi.Channels + 1] = (byte)g;
             iline.ScanlineB[x * imi.Channels + 2] = (byte)b;
             if (imi.Channels == 4)
                 iline.ScanlineB[x * imi.Channels + 3] = (byte)((b + g) / 2);
         }
         png.WriteRow(iline, row);
     }
     png.End();
     return f;
 }
        public static void doit(String orig)
        {
            string copy= TestsHelper.addSuffixToName(orig, "_tc");

            PngReader pngr = FileHelper.CreatePngReader(orig);
            if (!pngr.ImgInfo.Indexed)
                throw new Exception("Not indexed image");
            PngChunkPLTE plte = pngr.GetMetadata().GetPLTE();
            PngChunkTRNS trns = pngr.GetMetadata().GetTRNS(); // transparency metadata, can be null
            bool alpha = trns != null;
            ImageInfo im2 = new ImageInfo(pngr.ImgInfo.Cols, pngr.ImgInfo.Rows, 8, alpha);
            PngWriter pngw = FileHelper.CreatePngWriter(copy, im2, true);
            pngw.CopyChunksFirst(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE);
            int[] buf = null;
            for (int row = 0; row < pngr.ImgInfo.Rows; row++) {
                ImageLine line = pngr.ReadRowInt(row);
                buf = ImageLineHelper.Palette2rgb(line, plte, trns, buf);
                pngw.WriteRowInt(buf, row);
            }
            pngw.CopyChunksLast(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE);
            pngr.End();
            pngw.End();
            Console.WriteLine("True color: " + copy);
        }
Beispiel #14
0
 public ImageLine(ImageInfo imgInfo)
     : this(imgInfo, ESampleType.INT, false)
 {
 }
Beispiel #15
0
 public ImageLine(ImageInfo imgInfo, ESampleType stype)
     : this(imgInfo, stype, false)
 {
 }
Beispiel #16
0
 public PngChunkSRGB( ImageInfo info )
     : base(ID, info)
 {
 }
Beispiel #17
0
 public PngChunkIHDR(ImageInfo info)
     : base(ID, info)
 {
 }
Beispiel #18
0
 /// <summary>
 /// Constructs an ImageLine
 /// </summary>
 /// <param name="imgInfo">Inmutable copy of PNG ImageInfo</param>
 /// <param name="stype">Storage for samples:INT (default) or BYTE</param>
 /// <param name="unpackedMode">If true and bitdepth less than 8, samples are unpacked. This has no effect if biddepth 8 or 16</param>
 public ImageLine(ImageInfo imgInfo, ESampleType stype, bool unpackedMode)
     : this(imgInfo, stype, unpackedMode, null, null)
 {
 }
Beispiel #19
0
 private static void additionalTestPalette(string orig, string truecolor)
 {
     // covnert to true color 8 bits and check equality
     PngReader pngr = FileHelper.CreatePngReader(orig);
     PngChunkPLTE plte = pngr.GetMetadata().GetPLTE();
     PngChunkTRNS trns = pngr.GetMetadata().GetTRNS();
     string copy = TestsHelper.addSuffixToName(orig, "_tccopy");
     bool alpha = trns != null;
     ImageInfo im2 = new ImageInfo(pngr.ImgInfo.Cols, pngr.ImgInfo.Rows, 8, alpha);
     PngWriter pngw = FileHelper.CreatePngWriter(copy, im2, true);
     pngw.CopyChunksFirst(pngr, ChunkCopyBehaviour.COPY_ALL_SAFE);
     int[] buf = null;
     for (int row = 0; row < pngr.ImgInfo.Rows; row++) {
         ImageLine line = pngr.ReadRowInt(row);
         buf = ImageLineHelper.Palette2rgb(line, plte, trns, buf);
         pngw.WriteRowInt(buf, row);
     }
     pngr.End();
     pngw.End();
     TestsHelper.testEqual(copy, truecolor);
     System.IO.File.Delete(copy);
 }
Beispiel #20
0
 public PngChunkGAMA(ImageInfo info)
     : base(ID, info)
 {
 }
Beispiel #21
0
 public PngWriter( Stream outputStream, ImageInfo imgInfo )
     : this(outputStream, imgInfo, "[NO FILENAME AVAILABLE]")
 {
 }
Beispiel #22
0
 internal static void unpackInplaceInt(ImageInfo iminfo, int[] src, int[] dst,
     bool Scale)
 {
     int bitDepth = iminfo.BitDepth;
     if (bitDepth >= 8)
         return; // nothing to do
     int mask0 = GetMaskForPackedFormatsLs(bitDepth);
     int scalefactor = 8 - bitDepth;
     int offset0 = 8 * iminfo.SamplesPerRowPacked - bitDepth * iminfo.SamplesPerRow;
     int mask, offset, v;
     if (offset0 != 8) {
         mask = mask0 << offset0;
         offset = offset0; // how many bits to shift the mask to the right to recover mask0
     } else {
         mask = mask0;
         offset = 0;
     }
     for (int j = iminfo.SamplesPerRow - 1, i = iminfo.SamplesPerRowPacked - 1; j >= 0; j--) {
         v = (src[i] & mask) >> offset;
         if (Scale)
             v <<= scalefactor;
         dst[j] = v;
         mask <<= bitDepth;
         offset += bitDepth;
         if (offset == 8) {
             mask = mask0;
             offset = 0;
             i--;
         }
     }
 }
Beispiel #23
0
 internal static void packInplaceInt(ImageInfo iminfo, int[] src, int[] dst,
     bool scaled)
 {
     int bitDepth = iminfo.BitDepth;
     if (bitDepth >= 8)
         return; // nothing to do
     int mask0 = GetMaskForPackedFormatsLs(bitDepth);
     int scalefactor = 8 - bitDepth;
     int offset0 = 8 - bitDepth;
     int v, v0;
     int offset = 8 - bitDepth;
     v0 = src[0]; // first value is special for in place
     dst[0] = 0;
     if (scaled)
         v0 >>= scalefactor;
     v0 = ((v0 & mask0) << offset);
     for (int i = 0, j = 0; j < iminfo.SamplesPerRow; j++) {
         v = src[j];
         if (scaled)
             v >>= scalefactor;
         dst[i] |= ((v & mask0) << offset);
         offset -= bitDepth;
         if (offset < 0) {
             offset = offset0;
             i++;
             dst[i] = 0;
         }
     }
     dst[0] |= v0;
 }
Beispiel #24
0
 public static int[] Unpack( ImageInfo imgInfo, int [] src, int [] dst, bool scale )
 {
     int len1 = imgInfo.SamplesPerRow;
     int len0 = imgInfo.SamplesPerRowPacked;
     if ( dst == null || dst.Length < len1 )
         dst = new int [ len1 ];
     if ( imgInfo.Packed )
         ImageLine.unpackInplaceInt ( imgInfo, src, dst, scale );
     else
         Array.Copy ( src, 0, dst, 0, len0 );
     return dst;
 }
Beispiel #25
0
 public PngChunkPHYS( ImageInfo info )
     : base(ID, info)
 {
 }
Beispiel #26
0
        internal readonly int channels; // copied from imgInfo, more handy

        #endregion Fields

        #region Constructors

        public ImageLine(ImageInfo imgInfo)
            : this(imgInfo, ESampleType.INT, false)
        {
        }
Beispiel #27
0
 public PngWriter(Stream outputStream, ImageInfo imgInfo)
     : this(outputStream, imgInfo, "[NO FILENAME AVAILABLE]")
 {
 }
Beispiel #28
0
 public ImageLine(ImageInfo imgInfo, ESampleType stype)
     : this(imgInfo, stype, false)
 {
 }
Beispiel #29
0
 protected internal PngChunkTextVar(String id, ImageInfo info)
     : base(id, info)
 {
 }
Beispiel #30
0
 /// <summary>
 /// Constructs an ImageLine
 /// </summary>
 /// <param name="imgInfo">Inmutable copy of PNG ImageInfo</param>
 /// <param name="stype">Storage for samples:INT (default) or BYTE</param>
 /// <param name="unpackedMode">If true and bitdepth less than 8, samples are unpacked. This has no effect if biddepth 8 or 16</param>
 public ImageLine(ImageInfo imgInfo, ESampleType stype, bool unpackedMode)
     : this(imgInfo, stype, unpackedMode, null, null)
 {
 }
Beispiel #31
0
 public PngChunkSBIT(ImageInfo info)
     : base(ID, info)
 {
 }
Beispiel #32
0
        private int[] hist = new int[0]; // should have same lenght as palette

        #endregion Fields

        #region Constructors

        public PngChunkHIST(ImageInfo info)
            : base(ID, info)
        {
        }
Beispiel #33
0
 public PngChunkCHRM(ImageInfo info)
     : base(ID, info)
 {
 }
 public PngChunkUNKNOWN(String id, ImageInfo info)
     : base(id, info)
 {
 }
 private PngChunkUNKNOWN(PngChunkUNKNOWN c, ImageInfo info)
     : base(c.Id, info)
 {
     System.Array.Copy(c.data, 0, data, 0, c.data.Length);
 }
Beispiel #36
0
 public PngChunkZTXT(ImageInfo info)
     : base(ID, info)
 {
 }
Beispiel #37
0
        /// <summary>
        /// Constructs a PNGReader objet from a opened Stream
        /// </summary>
        /// <remarks>The constructor reads the signature and first chunk (IDHR)<seealso cref="FileHelper.CreatePngReader(string)"/>
        /// </remarks>
        ///
        /// <param name="inputStream"></param>
        /// <param name="filename">Optional, can be the filename or a description.</param>
        public PngReader(Stream inputStream, String filename)
        {
            this.filename    = (filename == null) ? "" : filename;
            this.inputStream = inputStream;
            this.chunksList  = new ChunksList(null);
            this.metadata    = new PngMetadata(chunksList);
            this.offset      = 0;
            // set default options
            this.CurrentChunkGroup  = -1;
            this.ShouldCloseStream  = true;
            this.MaxBytesMetadata   = 5 * 1024 * 1024;
            this.MaxTotalBytesRead  = 200 * 1024 * 1024; // 200MB
            this.SkipChunkMaxSize   = 2 * 1024 * 1024;
            this.SkipChunkIds       = new string[] { "fdAT" };
            this.ChunkLoadBehaviour = Hjg.Pngcs.Chunks.ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS;
            // starts reading: signature
            byte[] pngid = new byte[8];
            PngHelperInternal.ReadBytes(inputStream, pngid, 0, pngid.Length);
            offset += pngid.Length;
            if (!PngCsUtils.arraysEqual(pngid, PngHelperInternal.PNG_ID_SIGNATURE))
            {
                throw new PngjInputException("Bad PNG signature");
            }
            CurrentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
            // reads first chunk IDHR
            int clen = PngHelperInternal.ReadInt4(inputStream);

            offset += 4;
            if (clen != 13)
            {
                throw new Exception("IDHR chunk len != 13 ?? " + clen);
            }
            byte[] chunkid = new byte[4];
            PngHelperInternal.ReadBytes(inputStream, chunkid, 0, 4);
            if (!PngCsUtils.arraysEqual4(chunkid, ChunkHelper.b_IHDR))
            {
                throw new PngjInputException("IHDR not found as first chunk??? ["
                                             + ChunkHelper.ToString(chunkid) + "]");
            }
            offset += 4;
            PngChunkIHDR ihdr      = (PngChunkIHDR)ReadChunk(chunkid, clen, false);
            bool         alpha     = (ihdr.Colormodel & 0x04) != 0;
            bool         palette   = (ihdr.Colormodel & 0x01) != 0;
            bool         grayscale = (ihdr.Colormodel == 0 || ihdr.Colormodel == 4);

            // creates ImgInfo and imgLine, and allocates buffers
            ImgInfo      = new ImageInfo(ihdr.Cols, ihdr.Rows, ihdr.Bitspc, alpha, grayscale, palette);
            rowb         = new byte[ImgInfo.BytesPerRow + 1];
            rowbprev     = new byte[rowb.Length];
            rowbfilter   = new byte[rowb.Length];
            interlaced   = ihdr.Interlaced == 1;
            deinterlacer = interlaced ? new PngDeinterlacer(ImgInfo) : null;
            // some checks
            if (ihdr.Filmeth != 0 || ihdr.Compmeth != 0 || (ihdr.Interlaced & 0xFFFE) != 0)
            {
                throw new PngjInputException("compmethod or filtermethod or interlaced unrecognized");
            }
            if (ihdr.Colormodel < 0 || ihdr.Colormodel > 6 || ihdr.Colormodel == 1 ||
                ihdr.Colormodel == 5)
            {
                throw new PngjInputException("Invalid colormodel " + ihdr.Colormodel);
            }
            if (ihdr.Bitspc != 1 && ihdr.Bitspc != 2 && ihdr.Bitspc != 4 && ihdr.Bitspc != 8 &&
                ihdr.Bitspc != 16)
            {
                throw new PngjInputException("Invalid bit depth " + ihdr.Bitspc);
            }
        }