void ProcessStream(Stream data)
{
if (data.CanTimeout) throw new PNGMaskException("Stream must not be able to time-out");
if (!data.CanRead) throw new PNGMaskException("Stream must be readable");
if (!data.CanSeek) throw new PNGMaskException("Stream must be seekable");
if (data.Length < MAGIC_NUMBER.Length) throw new PNGMaskException("File is smaller than magic number");
byte[] buffer = new byte[MAGIC_NUMBER.Length];
if (data.Read(buffer, 0, buffer.Length) < buffer.Length) throw new PNGMaskException("Could not read magic number");
for (int i = 0; i < buffer.Length; i++)
if (buffer[i] != MAGIC_NUMBER[i]) throw new PNGMaskException("Incorrect magic number, this file is not a PNG.");
Chunks = new List<PNGChunk>();
buffer = new byte[4];
bool first = true;
string name;
do
{
ReadData(data, ref buffer);
SwapEndianness(ref buffer);
uint length = BitConverter.ToUInt32(buffer, 0);
ReadData(data, ref buffer);
byte[] nameb = (byte[])buffer.Clone();
name = Encoding.ASCII.GetString(buffer);
if (first)
{
if (name != "IHDR") throw new PNGMaskException("First chunk must be IHDR, PNG is corrupt.");
if (length < 8) throw new PNGMaskException("IHDR chunk is too small, PNG is corrupt");
first = false;
}
byte[] chunkdata = new byte[length];
ReadData(data, ref chunkdata);
ReadData(data, ref buffer);
byte[] crcb = (byte[])buffer.Clone();
SwapEndianness(ref buffer);
uint CRC = BitConverter.ToUInt32(buffer, 0);
uint[] crcTable = null;
uint CRC2 = CRC32(nameb, 0, nameb.Length, 0, ref crcTable);
CRC2 = CRC32(chunkdata, 0, chunkdata.Length, CRC2, ref crcTable);
bool standard = false;
foreach (string s in STANDARD_CHUNKS)
if (name == s) { standard = true; break; }
bool critical = false;
if (standard)
foreach (string s in CRITICAL_CHUNKS)
if (name == s) { critical = true; break; }
Chunks.Add(new PNGChunk()
{
Name = name,
Standard = standard,
Critical = critical,
Data = chunkdata,
CRC = CRC,
CRCBytes = crcb,
ValidCRC = (CRC == CRC2)
});
} while (name != "IEND");
long EOF = data.Length - data.Position;
if (EOF > 0)
{
buffer = new byte[EOF];
ReadData(data, ref buffer);
Chunks.Add(new PNGChunk()
{
Name = "_EOF",
Standard = false,
Critical = false,
Data = buffer,
CRC = 0,
CRCBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 },
ValidCRC = false
});
}
PNGChunk IHDR = Chunks[0];
Width = BitConverter.ToUInt32(new byte[4] { IHDR.Data[3], IHDR.Data[2], IHDR.Data[1], IHDR.Data[0] }, 0);
Height = BitConverter.ToUInt32(new byte[4] { IHDR.Data[7], IHDR.Data[6], IHDR.Data[5], IHDR.Data[4] }, 0);
}