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)); }
/// <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); }
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); }
/// <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); }
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); }
/// <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); }
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(); } }
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)); } }
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); }
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(); } }
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++; } }
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++; } }
/// <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); }
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()); } }
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()); }
/// <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); } }
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()); } }