private 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 Exception( );
}
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;
}