private void PrepareBuffer(int width, int height)
{
uint widthLength = (uint)(width * 4) + 1;
_rowLength = (int)widthLength;
uint dcSize = widthLength * (uint)height;
uint rowsPerBlock = _MAXBLOCK / widthLength;
uint blockSize = rowsPerBlock * widthLength;
_blockSize = (int)blockSize;
uint blockCount;
ushort length;
uint remainder = dcSize;
if ((dcSize % blockSize) == 0)
{
blockCount = dcSize / blockSize;
}
else
{
blockCount = (dcSize / blockSize) + 1;
}
uint totalSize = 51 + (dcSize + 12 + 4 + blockCount * 5) + 12; // header, (data), end
_buffer = new byte[totalSize];
int currIndex = 0;
// ********************************
// ******* write png header *******
_HEADER.CopyTo(_buffer, (int)currIndex);
currIndex += _HEADER.Length;
// ********************************
// ******* Write IHDR *******
// Width: 4 bytes
// Height: 4 bytes
// Bit depth: 1 byte
// Color type: 1 byte
// Compression method: 1 byte
// Filter method: 1 byte
// Interlace method: 1 byte
byte[] size;
size = BitConverter.GetBytes((uint)13); // sizeof(data(IHDR))
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
// "IHDR"
_IHDR.CopyTo(_buffer, (int)currIndex);
currIndex += _IHDR.Length;
size = BitConverter.GetBytes(width);
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
size = BitConverter.GetBytes(height);
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
_buffer[currIndex] = 8; currIndex++; // 8 bits
_buffer[currIndex] = 6; currIndex++; // RGBA format
currIndex += 3; // skip to end of IHDR
currIndex += 4; // skip CRC, assume 0
// ********************************
// ******* Write gAMA chunk *******
size = BitConverter.GetBytes((uint)4); // sizeof(data(gAMA))
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
// "GAMA"
_GAMA.CopyTo(_buffer, (int)currIndex);
currIndex += _GAMA.Length;
// Set gamma = 1
size = BitConverter.GetBytes(1 * 100000);
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
currIndex += 4; // skip CRC, assume 0
// ***************************************
// ******* Write IDAT (data) chunk *******
size = BitConverter.GetBytes(dcSize + 2 + 4 + blockCount * 5); // image data size + 2 bytes for compression header + 4 bytes for adler checksum + blocks overhead
_buffer[currIndex] = size[3]; currIndex++;
_buffer[currIndex] = size[2]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
_buffer[currIndex] = size[0]; currIndex++;
// "IDAT"
_IDAT.CopyTo(_buffer, (int)currIndex);
currIndex += _IDAT.Length;
// write compression header
_buffer[currIndex] = 0x78; currIndex++;
_buffer[currIndex] = 0xDA; currIndex++;
_dataStart = currIndex;
// write image data
//currIndex += (int)dcSize; // !!!
for (uint blocks = 0; blocks < blockCount; blocks++)
{
// Write LEN
length = (ushort)((remainder < blockSize) ? remainder : blockSize);
if (length == remainder)
{
_buffer[currIndex] = 1;
}
else
{
_buffer[currIndex] = 0;
}
currIndex++;
size = BitConverter.GetBytes(length);
_buffer[currIndex] = size[0]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
// Write one's compliment of LEN
size = BitConverter.GetBytes((ushort)~length);
_buffer[currIndex] = size[0]; currIndex++;
_buffer[currIndex] = size[1]; currIndex++;
// Write blocks
//for (int i = currIndex; i < currIndex + length; i++)
//{
// _buffer[i] = 200;
//}
currIndex += length;
// Next block
remainder -= blockSize;
}
currIndex += 4; // skip adler32 checksum, assume 0
currIndex += 4; // skip CRC, assume 0
// ********************************
// ******* Write IEND chunk *******
currIndex += 4; // sizeof(data(IEND)) is 0
// "IEND"
_IEND.CopyTo(_buffer, (int)currIndex);
currIndex += _IEND.Length;
_buffer[currIndex] = 81; currIndex++; // CRC
_buffer[currIndex] = 189; currIndex++; // CRC
_buffer[currIndex] = 159; currIndex++; // CRC
_buffer[currIndex] = 125; currIndex++; // CRC
}