public void defilter(int xOffset, int yOffset, int xStep, int yStep, int passWidth, int passHeight, IPngImageOutput output) { if (passWidth == 0 || passHeight == 0) return; int bytesPerRow = (bitDepth * samples * passWidth + 7) / 8; bool isShort = bitDepth == 16; int rowSize = bytesPerRow + bpp; byte[] prev = new byte[rowSize]; byte[] cur = new byte[rowSize]; for (int srcY = 0, dstY = yOffset; srcY < passHeight; srcY++, dstY += yStep) { int filterType = stream.ReadByte(); if(filterType == -1) throw new EndOfStreamException(); fillBuffer(cur, bpp, bytesPerRow); defilter(cur, prev, bpp, filterType); output.writeLine(cur, bpp); byte[] tmp = cur; cur = prev; prev = tmp; } }
public void read(Stream stream, IPngImageOutput imageOutput) { this.imageOutput = imageOutput; CRCInputStream crcstream = new CRCInputStream(stream); BigEndianBinaryReader reader = new BigEndianBinaryReader(crcstream); //check signature if(!IsPng(stream)) throw new BadImageFormatException("signature invalid"); //sort of an inefficient way to do it, but at 3:30am itll do fine MemoryStream msIDAT = new MemoryStream(); int state = 0; for(; ; ) { bool skipChunk = false; int chunkLen = reader.ReadInt32(); crcstream.resetCrc(); int chunkType = reader.ReadInt32(); //expect an IHDR if(state == 0) { if(chunkType != type_IHDR) throw new BadImageFormatException("did not encounter initial IHDR"); ihdr.read(reader); //validate ihdr: do we support interlaced images for now? state = 1; } else if(state == 1) { switch(chunkType) { case type_IEND: //actually do the imagedata read now msIDAT.Position = 0; readImagedata(new BigEndianBinaryReader(msIDAT), (int)msIDAT.Length); state = 2; break; case type_IHDR: throw new BadImageFormatException("encountered supernumerary IHDR"); case type_IDAT: byte[] buf = new byte[chunkLen]; reader.BaseStream.Read(buf, 0, chunkLen); msIDAT.Write(buf, 0, chunkLen); break; case type_PLTE: readPLTE(reader, chunkLen); break; default: { skipChunk = true; byte[] bytes = System.BitConverter.GetBytes(chunkType); //debug: which chunk was skipped? //Console.WriteLine("{0}{1}{2}{3}", (char)bytes[3], (char)bytes[2], (char)bytes[1], (char)bytes[0]); } break; } } //if we skipped the chunk, skip the bytes. if(skipChunk) { reader.BaseStream.Position += chunkLen + 4; //+4 for the crc } else { //if we didnt skip it, do the crc validation if(!skipChunk) { int actualCrc = (int)crcstream.Value; int targetCrc = reader.ReadInt32(); if(actualCrc != targetCrc) throw new BadImageFormatException("Crc failure"); } } if(state == 2) break; } }