private static unsafe Bitmap ReadP6Image(Stream stream, int width, int height, int maxValue)
{
double scalingFactor = (double)255 / maxValue;
// create new bitmap and lock it
Bitmap image = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData imageData = image.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = imageData.Stride;
byte* ptr = (byte*)imageData.Scan0.ToPointer();
// prepare a buffer for one line
int lineSize = width * 3;
byte[] line = new byte[lineSize];
int totalBytesRead = 0, bytesRead = 0;
// load all rows
for (int y = 0; y < height; y++)
{
totalBytesRead = 0;
bytesRead = 0;
// load next line
while (totalBytesRead != lineSize)
{
bytesRead = stream.Read(line, totalBytesRead, lineSize - totalBytesRead);
if (bytesRead == 0)
{
// if we've reached the end before complete image is loaded, then there should
// be something wrong
throw new InvalidOperationException("Execution should not reach here.");
}
totalBytesRead += bytesRead;
}
// fill next image row
byte* row = ptr + stride * y;
for (int x = 0, i = 0; x < width; x++, i += 3, row += 3)
{
row[2] = (byte)(scalingFactor * line[i]); // red
row[1] = (byte)(scalingFactor * line[i + 1]); // green
row[0] = (byte)(scalingFactor * line[i + 2]); // blue
}
}
// unlock image and return it
image.UnlockBits(imageData);
return image;
}