private unsafe Bitmap ReadImageFrame( Stream stream, FITSImageInfo imageInfo )
{
int width = imageInfo.Width;
int height = imageInfo.Height;
// create new bitmap
Bitmap image = ( imageInfo.BitsPerPixel == 8 ) ?
Tools.CreateGrayscaleImage( width, height ) :
new Bitmap( width, height, PixelFormat.Format16bppGrayScale );
// lock it
BitmapData imageData = image.LockBits( new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadWrite, image.PixelFormat );
int originalBitsPerPixel = imageInfo.OriginalBitsPerPixl;
int stride = imageData.Stride;
byte* ptr = (byte*) imageData.Scan0.ToPointer( );
double min = imageInfo.MinDataValue;
double max = imageInfo.MaxDataValue;
// check number of bits per pixel and load image appropriately
if ( imageInfo.BitsPerPixel == 16 )
{
// 16 bpp grayscale image
double coef = 65535.0 / ( max - min );
// prepare a buffer for one line
int lineSize = width * Math.Abs( originalBitsPerPixel ) / 8;
byte[] line = new byte[lineSize];
byte[] temp = new byte[8];
// load all rows
for ( int y = height - 1; y >= 0; y-- )
{
// load next line
if ( Tools.ReadStream( stream, line, 0, lineSize ) < lineSize )
throw new ArgumentException( "The stream does not contain valid FITS image." );
// fill next image row
ushort* row = (ushort*) ( ptr + stride * y );
for ( int x = 0, i = 0; x < width; x++, row++ )
{
double value = 0;
switch ( originalBitsPerPixel )
{
case 16: // 16 bit signed integer
{
short tempValue = 0;
unchecked
{
tempValue = (short) ( ( line[i++] << 8 ) + line[i++] );
}
value = tempValue;
break;
}
case 32: // 32 bit signed integer
{
temp[3] = line[i++];
temp[2] = line[i++];
temp[1] = line[i++];
temp[0] = line[i++];
value = BitConverter.ToInt32( temp, 0 );
break;
}
case -32: // 32 bit float
{
temp[3] = line[i++];
temp[2] = line[i++];
temp[1] = line[i++];
temp[0] = line[i++];
value = BitConverter.ToSingle( temp, 0 );
break;
}
case -64: // 64 bit double
{
temp[7] = line[i++];
temp[6] = line[i++];
temp[5] = line[i++];
temp[4] = line[i++];
temp[3] = line[i++];
temp[2] = line[i++];
temp[1] = line[i++];
temp[0] = line[i++];
value = BitConverter.ToDouble( temp, 0 );
break;
}
}
*row = (ushort) ( ( value - min ) * coef );
}
}
}
else
{
// 8 bpp grayscale image
double coef = 255.0 / ( max - min );
// prepare a buffer for one line
byte[] line = new byte[width];
// load all rows
for ( int y = height - 1; y >= 0; y-- )
{
// load next line
if ( Tools.ReadStream( stream, line, 0, width ) < width )
throw new ArgumentException( "The stream does not contain valid FITS image." );
// fill next image row
byte* row = ptr + stride * y;
for ( int x = 0; x < width; x++, row++ )
{
*row = (byte) ( ( (double) line[x] - min ) * coef );
}
}
}
// unlock image and return it
image.UnlockBits( imageData );
return image;
}