Some utility static methods for internal use.
예제 #1
0
 private void FilterRowPaeth() {
       int i, j, imax;
       imax = ImgInfo.BytesPerRow;
       for (j = 1 - ImgInfo.BytesPixel, i = 1; i <= imax; i++, j++)
         rowbfilter[i] = (byte)(rowb[i] - PngHelperInternal.FilterPaethPredictor(j > 0 ? rowb[j] : 0,
                                                                                 rowbprev[i], j > 0 ? rowbprev[j] : 0));
 }
예제 #2
0
        /// <summary>
        /// Write id signature and also "IHDR" chunk
        /// </summary>
        ///
        private void WriteSignatureAndIHDR()
        {
            CurrentChunkGroup = ChunksList.CHUNK_GROUP_0_IDHR;
            PngHelperInternal.WriteBytes(outputStream, Hjg.Pngcs.PngHelperInternal.PNG_ID_SIGNATURE); // signature
            PngChunkIHDR ihdr = new PngChunkIHDR(ImgInfo);

            // http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
            ihdr.Cols   = ImgInfo.Cols;
            ihdr.Rows   = ImgInfo.Rows;
            ihdr.Bitspc = ImgInfo.BitDepth;
            int colormodel = 0;

            if (ImgInfo.Alpha)
            {
                colormodel += 0x04;
            }
            if (ImgInfo.Indexed)
            {
                colormodel += 0x01;
            }
            if (!ImgInfo.Greyscale)
            {
                colormodel += 0x02;
            }
            ihdr.Colormodel = colormodel;
            ihdr.Compmeth   = 0; // compression method 0=deflate
            ihdr.Filmeth    = 0; // filter method (0)
            ihdr.Interlaced = 0; // never interlace
            ihdr.CreateRawChunk().WriteChunk(outputStream);
        }
예제 #3
0
        public void WriteSignatureAndIHDR()
        {
            CurrentChunkGroup = 0;
            PngHelperInternal.WriteBytes(outputStream, PngHelperInternal.PNG_ID_SIGNATURE);
            PngChunkIHDR obj = new PngChunkIHDR(ImgInfo)
            {
                Cols   = ImgInfo.Cols,
                Rows   = ImgInfo.Rows,
                Bitspc = ImgInfo.BitDepth
            };
            int num = 0;

            if (ImgInfo.Alpha)
            {
                num += 4;
            }
            if (ImgInfo.Indexed)
            {
                num++;
            }
            if (!ImgInfo.Greyscale)
            {
                num += 2;
            }
            obj.Colormodel = num;
            obj.Compmeth   = 0;
            obj.Filmeth    = 0;
            obj.Interlaced = 0;
            obj.CreateRawChunk().WriteChunk(outputStream);
        }
예제 #4
0
        /// <summary>
        /// Reads chunkd from input stream, adds to ChunksList, and returns it.
        /// If it's skipped, a PngChunkSkipped object is created
        /// </summary>
        /// <returns></returns>
        private AbstractPngChunk ReadChunk(byte[] chunkid, int clen, bool skipforced)
        {
            if (clen < 0)
            {
                throw new PngjInputException("invalid chunk lenght: " + clen);
            }
            // skipChunksByIdSet is created lazyly, if fist IHDR has already been read
            if (skipChunkIdsSet is null && CurrentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR)
            {
                skipChunkIdsSet = new Dictionary <string, int>();
                if (SkipChunkIds is object)
                {
                    foreach (var id in SkipChunkIds)
                    {
                        skipChunkIdsSet.Add(id, 1);
                    }
                }
            }

            var chunkidstr = ChunkHelper.ToString(chunkid);
            var critical   = ChunkHelper.IsCritical(chunkidstr);
            var skip       = skipforced;

            if (MaxTotalBytesRead > 0 && clen + offset > MaxTotalBytesRead)
            {
                throw new PngjInputException("Maximum total bytes to read exceeeded: " + MaxTotalBytesRead + " offset:"
                                             + offset + " clen=" + clen);
            }
            // an ancillary chunks can be skipped because of several reasons:
            if (CurrentChunkGroup > ChunksList.CHUNK_GROUP_0_IDHR && !ChunkHelper.IsCritical(chunkidstr))
            {
                skip = skip || (SkipChunkMaxSize > 0 && clen >= SkipChunkMaxSize) || skipChunkIdsSet.ContainsKey(chunkidstr) ||
                       (MaxBytesMetadata > 0 && clen > MaxBytesMetadata - bytesChunksLoaded) ||
                       !ChunkHelper.ShouldLoad(chunkidstr, ChunkLoadBehaviour);
            }

            AbstractPngChunk pngChunk;

            if (skip)
            {
                PngHelperInternal.SkipBytes(inputStream, clen);
                PngHelperInternal.ReadInt4(inputStream); // skip - we dont call PngHelperInternal.skipBytes(inputStream, clen + 4) for risk of overflow
                pngChunk = new PngChunkSkipped(chunkidstr, ImgInfo, clen);
            }
            else
            {
                var chunk = new ChunkRaw(clen, chunkid, true);
                _        = chunk.ReadChunkData(inputStream, critical);
                pngChunk = AbstractPngChunk.Factory(chunk, ImgInfo);
                if (!pngChunk.Crit)
                {
                    bytesChunksLoaded += chunk.Len;
                }
            }

            pngChunk.Offset = offset - 8L;
            chunksList.AppendReadChunk(pngChunk, CurrentChunkGroup);
            offset += clen + 4L;
            return(pngChunk);
        }
예제 #5
0
        private int ReadRowRaw(int nrow)
        {
            //
            if (nrow == 0 && FirstChunksNotYetRead())
            {
                ReadFirstChunks();
            }
            if (nrow == 0 && interlaced)
            {
                Array.Clear(rowb, 0, rowb.Length); // new subimage: reset filters: this is enough, see the swap that happens lines
            }
            // below
            int bytesRead = ImgInfo.BytesPerRow; // NOT including the filter byte

            if (interlaced)
            {
                if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
                {
                    throw new PngjInputException("invalid row in interlaced mode: " + nrow);
                }
                deinterlacer.setRow(nrow);
                bytesRead = (ImgInfo.BitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
                if (bytesRead < 1)
                {
                    throw new PngjExceptionInternal("wtf??");
                }
            }
            else     // check for non interlaced
            {
                if (nrow < 0 || nrow >= ImgInfo.Rows || nrow != rowNum + 1)
                {
                    throw new PngjInputException("invalid row: " + nrow);
                }
            }
            rowNum = nrow;
            // swap buffers
            byte[] tmp = rowb;
            rowb     = rowbprev;
            rowbprev = tmp;
            // loads in rowbfilter "raw" bytes, with filter
            PngHelperInternal.ReadBytes(idatIstream, rowbfilter, 0, bytesRead + 1);
            offset = iIdatCstream.GetOffset();
            if (offset < 0)
            {
                throw new PngjExceptionInternal("bad offset ??" + offset);
            }
            if (MaxTotalBytesRead > 0 && offset >= MaxTotalBytesRead)
            {
                throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + MaxTotalBytesRead
                                             + " offset:" + offset);
            }
            rowb[0] = 0;
            UnfilterRow(bytesRead);
            rowb[0] = rowbfilter[0];
            if ((rowNum == ImgInfo.Rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
            {
                ReadLastAndClose();
            }
            return(bytesRead);
        }
예제 #6
0
        /// <summary>
        /// Reads chunks before first IDAT. Position before: after IDHR (crc included)
        /// Position after: just after the first IDAT chunk id Returns length of first
        /// IDAT chunk , -1 if not found
        /// </summary>
        ///
        private void ReadFirstChunks()
        {
            if (!FirstChunksNotYetRead())
            {
                return;
            }

            var clen    = 0;
            var found   = false;
            var chunkid = new byte[4]; // it's important to reallocate in each

            CurrentChunkGroup = ChunksList.CHUNK_GROUP_1_AFTERIDHR;
            while (!found)
            {
                clen    = PngHelperInternal.ReadInt4(inputStream);
                offset += 4;
                if (clen < 0)
                {
                    break;
                }

                PngHelperInternal.ReadBytes(inputStream, chunkid, 0, 4);
                offset += 4;
                if (PngCsUtils.arraysEqual4(chunkid, Hjg.Pngcs.Chunks.ChunkHelper.b_IDAT))
                {
                    found             = true;
                    CurrentChunkGroup = ChunksList.CHUNK_GROUP_4_IDAT;
                    // add dummy idat chunk to list
                    chunksList.AppendReadChunk(new PngChunkIDAT(ImgInfo, clen, offset - 8), CurrentChunkGroup);
                    break;
                }
                else if (PngCsUtils.arraysEqual4(chunkid, Hjg.Pngcs.Chunks.ChunkHelper.b_IEND))
                {
                    throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset);
                }
                var chunkids = ChunkHelper.ToString(chunkid);
                if (chunkids.Equals(ChunkHelper.PLTE, System.StringComparison.Ordinal))
                {
                    CurrentChunkGroup = ChunksList.CHUNK_GROUP_2_PLTE;
                }

                ReadChunk(chunkid, clen, false);
                if (chunkids.Equals(ChunkHelper.PLTE, System.StringComparison.Ordinal))
                {
                    CurrentChunkGroup = ChunksList.CHUNK_GROUP_3_AFTERPLTE;
                }
            }

            var idatLen = found ? clen : -1;

            if (idatLen < 0)
            {
                throw new PngjInputException("first idat chunk not found!");
            }

            iIdatCstream = new PngIDatChunkInputStream(inputStream, idatLen, offset);
            idatIstream  = new ZlibInputStream(iIdatCstream, true);
        }
예제 #7
0
        public void ReadFirstChunks()
        {
            if (!FirstChunksNotYetRead())
            {
                return;
            }
            int  num  = 0;
            bool flag = false;

            byte[] array = new byte[4];
            CurrentChunkGroup = 1;
            while (!flag)
            {
                num     = PngHelperInternal.ReadInt4(inputStream);
                offset += 4L;
                if (num < 0)
                {
                    break;
                }
                PngHelperInternal.ReadBytes(inputStream, array, 0, 4);
                offset += 4L;
                if (PngCsUtils.arraysEqual4(array, ChunkHelper.b_IDAT))
                {
                    flag = true;
                    CurrentChunkGroup = 4;
                    chunksList.AppendReadChunk(new PngChunkIDAT(ImgInfo, num, offset - 8), CurrentChunkGroup);
                    break;
                }
                if (PngCsUtils.arraysEqual4(array, ChunkHelper.b_IEND))
                {
                    throw new PngjInputException("END chunk found before image data (IDAT) at offset=" + offset.ToString());
                }
                string text = ChunkHelper.ToString(array);
                if (text.Equals("PLTE"))
                {
                    CurrentChunkGroup = 2;
                }
                ReadChunk(array, num, skipforced: false);
                if (text.Equals("PLTE"))
                {
                    CurrentChunkGroup = 3;
                }
            }
            int num2 = flag ? num : (-1);

            if (num2 < 0)
            {
                throw new PngjInputException("first idat chunk not found!");
            }
            iIdatCstream = new PngIDatChunkInputStream(inputStream, num2, offset);
            idatIstream  = ZlibStreamFactory.createZlibInputStream(iIdatCstream, leaveOpen: true);
            if (!crcEnabled)
            {
                iIdatCstream.DisableCrcCheck();
            }
        }
예제 #8
0
        private void UnfilterRowPaeth(int nbytes)
        {
            int i, j, x, y;

            for (j = 1 - ImgInfo.BytesPixel, i = 1; i <= nbytes; i++, j++)
            {
                x       = (j > 0) ? rowb[j] : 0;
                y       = (j > 0) ? rowbprev[j] : 0;
                rowb[i] = (byte)(rowbfilter[i] + PngHelperInternal.FilterPaethPredictor(x, rowbprev[i], y));
            }
        }
예제 #9
0
        public int ReadRowRaw(int nrow)
        {
            if (nrow == 0 && FirstChunksNotYetRead())
            {
                ReadFirstChunks();
            }
            if (nrow == 0 && interlaced)
            {
                Array.Clear(rowb, 0, rowb.Length);
            }
            int num = ImgInfo.BytesPerRow;

            if (interlaced)
            {
                if (nrow < 0 || nrow > deinterlacer.getRows() || (nrow != 0 && nrow != deinterlacer.getCurrRowSubimg() + 1))
                {
                    throw new PngjInputException("invalid row in interlaced mode: " + nrow.ToString());
                }
                deinterlacer.setRow(nrow);
                num = (ImgInfo.BitspPixel * deinterlacer.getPixelsToRead() + 7) / 8;
                if (num < 1)
                {
                    throw new PngjExceptionInternal("wtf??");
                }
            }
            else if (nrow < 0 || nrow >= ImgInfo.Rows || nrow != rowNum + 1)
            {
                throw new PngjInputException("invalid row: " + nrow.ToString());
            }
            rowNum = nrow;
            byte[] array = rowb;
            rowb     = rowbprev;
            rowbprev = array;
            PngHelperInternal.ReadBytes(idatIstream, rowbfilter, 0, num + 1);
            offset = iIdatCstream.GetOffset();
            if (offset < 0)
            {
                throw new PngjExceptionInternal("bad offset ??" + offset.ToString());
            }
            if (MaxTotalBytesRead > 0 && offset >= MaxTotalBytesRead)
            {
                throw new PngjInputException("Reading IDAT: Maximum total bytes to read exceeeded: " + MaxTotalBytesRead.ToString() + " offset:" + offset.ToString());
            }
            rowb[0] = 0;
            UnfilterRow(num);
            rowb[0] = rowbfilter[0];
            if ((rowNum == ImgInfo.Rows - 1 && !interlaced) || (interlaced && deinterlacer.isAtLastRow()))
            {
                ReadLastAndClose();
            }
            return(num);
        }
예제 #10
0
        public PngChunk ReadChunk(byte[] chunkid, int clen, bool skipforced)
        {
            if (clen < 0)
            {
                throw new PngjInputException("invalid chunk lenght: " + clen.ToString());
            }
            if (skipChunkIdsSet == null && CurrentChunkGroup > 0)
            {
                skipChunkIdsSet = new Dictionary <string, int>();
                if (SkipChunkIds != null)
                {
                    string[] skipChunkIds = SkipChunkIds;
                    foreach (string key in skipChunkIds)
                    {
                        skipChunkIdsSet.Add(key, 1);
                    }
                }
            }
            string   text     = ChunkHelper.ToString(chunkid);
            PngChunk pngChunk = null;
            bool     flag     = ChunkHelper.IsCritical(text);
            bool     flag2    = skipforced;

            if (MaxTotalBytesRead > 0 && clen + offset > MaxTotalBytesRead)
            {
                throw new PngjInputException("Maximum total bytes to read exceeeded: " + MaxTotalBytesRead.ToString() + " offset:" + offset.ToString() + " clen=" + clen.ToString());
            }
            if (CurrentChunkGroup > 0 && !ChunkHelper.IsCritical(text))
            {
                flag2 = (flag2 || (SkipChunkMaxSize > 0 && clen >= SkipChunkMaxSize) || skipChunkIdsSet.ContainsKey(text) || (MaxBytesMetadata > 0 && clen > MaxBytesMetadata - bytesChunksLoaded) || !ChunkHelper.ShouldLoad(text, ChunkLoadBehaviour));
            }
            if (flag2)
            {
                PngHelperInternal.SkipBytes(inputStream, clen);
                PngHelperInternal.ReadInt4(inputStream);
                pngChunk = new PngChunkSkipped(text, ImgInfo, clen);
            }
            else
            {
                ChunkRaw chunkRaw = new ChunkRaw(clen, chunkid, alloc: true);
                chunkRaw.ReadChunkData(inputStream, crcEnabled | flag);
                pngChunk = PngChunk.Factory(chunkRaw, ImgInfo);
                if (!pngChunk.Crit)
                {
                    bytesChunksLoaded += chunkRaw.Length;
                }
            }
            pngChunk.Offset = offset - 8;
            chunksList.AppendReadChunk(pngChunk, CurrentChunkGroup);
            offset += (long)clen + 4L;
            return(pngChunk);
        }
 public void ForceChunkEnd()
 {
     if (!ended)
     {
         byte[] array = new byte[toReadThisChunk];
         PngHelperInternal.ReadBytes(inputStream, array, 0, toReadThisChunk);
         if (checkCrc)
         {
             crcEngine.Update(array, 0, toReadThisChunk);
         }
         EndChunkGoForNext();
     }
 }
예제 #12
0
        public void FilterRowPaeth()
        {
            int bytesPerRow = ImgInfo.BytesPerRow;
            int num         = 1 - ImgInfo.BytesPixel;
            int num2        = 1;

            while (num2 <= bytesPerRow)
            {
                rowbfilter[num2] = (byte)(rowb[num2] - PngHelperInternal.FilterPaethPredictor((num > 0) ? rowb[num] : 0, rowbprev[num2], (num > 0) ? rowbprev[num] : 0));
                num2++;
                num++;
            }
        }
예제 #13
0
        public void UnfilterRowPaeth(int nbytes)
        {
            int num  = 1 - ImgInfo.BytesPixel;
            int num2 = 1;

            while (num2 <= nbytes)
            {
                int a = (num > 0) ? rowb[num] : 0;
                int c = (num > 0) ? rowbprev[num] : 0;
                rowb[num2] = (byte)(rowbfilter[num2] + PngHelperInternal.FilterPaethPredictor(a, rowbprev[num2], c));
                num2++;
                num++;
            }
        }
예제 #14
0
        /// <summary>
        /// Reads (and processes ... up to a point) chunks after last IDAT.
        /// </summary>
        ///
        private void ReadLastChunks()
        {
            CurrentChunkGroup = ChunksList.CHUNK_GROUP_5_AFTERIDAT;
            // PngHelper.logdebug("idat ended? " + iIdatCstream.isEnded());
            if (!iIdatCstream.IsEnded())
            {
                iIdatCstream.ForceChunkEnd();
            }

            var clen     = iIdatCstream.GetLenLastChunk();
            var chunkid  = iIdatCstream.GetIdLastChunk();
            var endfound = false;
            var first    = true;

            while (!endfound)
            {
                var skip = false;
                if (!first)
                {
                    clen    = PngHelperInternal.ReadInt4(inputStream);
                    offset += 4;
                    if (clen < 0)
                    {
                        throw new PngjInputException("bad len " + clen);
                    }

                    PngHelperInternal.ReadBytes(inputStream, chunkid, 0, 4);
                    offset += 4;
                }

                first = false;
                if (PngCsUtils.arraysEqual4(chunkid, ChunkHelper.b_IDAT))
                {
                    skip = true; // extra dummy (empty?) idat chunk, it can happen, ignore it
                }
                else if (PngCsUtils.arraysEqual4(chunkid, ChunkHelper.b_IEND))
                {
                    CurrentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
                    endfound          = true;
                }
                ReadChunk(chunkid, clen, skip);
            }

            if (!endfound)
            {
                throw new PngjInputException("end chunk not found - offset=" + offset);
            }
            // PngHelper.logdebug("end chunk found ok offset=" + offset);
        }
예제 #15
0
        public void ReadLastChunks()
        {
            CurrentChunkGroup = 5;
            if (!iIdatCstream.IsEnded())
            {
                iIdatCstream.ForceChunkEnd();
            }
            int num = iIdatCstream.GetLenLastChunk();

            byte[] idLastChunk = iIdatCstream.GetIdLastChunk();
            bool   flag        = false;
            bool   flag2       = true;
            bool   flag3       = false;

            while (!flag)
            {
                flag3 = false;
                if (!flag2)
                {
                    num     = PngHelperInternal.ReadInt4(inputStream);
                    offset += 4L;
                    if (num < 0)
                    {
                        throw new PngjInputException("bad len " + num.ToString());
                    }
                    PngHelperInternal.ReadBytes(inputStream, idLastChunk, 0, 4);
                    offset += 4L;
                }
                flag2 = false;
                if (PngCsUtils.arraysEqual4(idLastChunk, ChunkHelper.b_IDAT))
                {
                    flag3 = true;
                }
                else if (PngCsUtils.arraysEqual4(idLastChunk, ChunkHelper.b_IEND))
                {
                    CurrentChunkGroup = 6;
                    flag = true;
                }
                ReadChunk(idLastChunk, num, flag3);
            }
            if (!flag)
            {
                throw new PngjInputException("end chunk not found - offset=" + offset.ToString());
            }
        }
예제 #16
0
        private void EndChunkGoForNext()
        {
            // Called after readging the last byte of chunk
            // Checks CRC, and read ID from next CHUNK
            // Those values are left in idLastChunk / lenLastChunk
            // Skips empty IDATS
            do
            {
                var crc = PngHelperInternal.ReadInt4(inputStream);
                offset += 4;
                if (checkCrc)
                {
                    var crccalc = (int)crcEngine.GetValue();
                    if (lenLastChunk > 0 && crc != crccalc)
                    {
                        throw new PngjBadCrcException("error reading idat; offset: " + offset.ToString(CultureInfo.CurrentCulture));
                    }

                    crcEngine.Reset();
                }

                lenLastChunk = PngHelperInternal.ReadInt4(inputStream);
                if (lenLastChunk < 0)
                {
                    throw new PngjInputException("invalid len for chunk: " + lenLastChunk.ToString(CultureInfo.CurrentCulture));
                }

                toReadThisChunk = lenLastChunk;
                PngHelperInternal.ReadBytes(inputStream, idLastChunk, 0, 4);
                offset += 8;

                ended = !PngCsUtils.arraysEqual4(idLastChunk, Chunks.ChunkHelper.b_IDAT);
                if (!ended)
                {
                    foundChunksInfo.Add(new IdatChunkInfo(lenLastChunk, offset - 8));
                    if (checkCrc)
                    {
                        crcEngine.Update(idLastChunk, 0, 4);
                    }
                }
            } while (lenLastChunk == 0 && !ended);
            // rarely condition is true (empty IDAT ??)
        }
 public void EndChunkGoForNext()
 {
     while (true)
     {
         int num = PngHelperInternal.ReadInt4(inputStream);
         offset += 4L;
         if (checkCrc)
         {
             int value = (int)crcEngine.GetValue();
             if (lenLastChunk > 0 && num != value)
             {
                 throw new PngjBadCrcException("error reading idat; offset: " + offset.ToString());
             }
             crcEngine.Reset();
         }
         lenLastChunk = PngHelperInternal.ReadInt4(inputStream);
         if (lenLastChunk < 0)
         {
             break;
         }
         toReadThisChunk = lenLastChunk;
         PngHelperInternal.ReadBytes(inputStream, idLastChunk, 0, 4);
         offset += 8L;
         ended   = !PngCsUtils.arraysEqual4(idLastChunk, ChunkHelper.b_IDAT);
         if (!ended)
         {
             foundChunksInfo.Add(new IdatChunkInfo(lenLastChunk, offset - 8));
             if (checkCrc)
             {
                 crcEngine.Update(idLastChunk, 0, 4);
             }
         }
         if (lenLastChunk != 0 || ended)
         {
             return;
         }
     }
     throw new PngjInputException("invalid len for chunk: " + lenLastChunk.ToString());
 }
예제 #18
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);
            }
        }
예제 #19
0
        public PngReader(Stream inputStream, string filename)
        {
            this.filename     = ((filename == null) ? "" : filename);
            this.inputStream  = inputStream;
            chunksList        = new ChunksList(null);
            metadata          = new PngMetadata(chunksList);
            offset            = 0L;
            CurrentChunkGroup = -1;
            ShouldCloseStream = true;
            MaxBytesMetadata  = 5242880L;
            MaxTotalBytesRead = 209715200L;
            SkipChunkMaxSize  = 2097152;
            SkipChunkIds      = new string[1]
            {
                "fdAT"
            };
            ChunkLoadBehaviour = ChunkLoadBehaviour.LOAD_CHUNK_ALWAYS;
            byte[] array = new byte[8];
            PngHelperInternal.ReadBytes(inputStream, array, 0, array.Length);
            offset += array.Length;
            if (!PngCsUtils.arraysEqual(array, PngHelperInternal.PNG_ID_SIGNATURE))
            {
                throw new PngjInputException("Bad PNG signature");
            }
            CurrentChunkGroup = 0;
            int num = PngHelperInternal.ReadInt4(inputStream);

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

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