
// WRdBmp6.c

/*
 * rdbmp.c
 *
 * Copyright (C) 1994-1996, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains routines to read input images in Microsoft "BMP"
 * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
 * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
 * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
 * Also, we don't support RLE-compressed files.
 *
 * These routines may need modification for non-Unix environments or
 * specialized applications.  As they stand, they assume input from
 * an ordinary stdio stream.  They further assume that reading begins
 * at the start of the file; start_input may need work if the
 * user interface has already read some data (e.g., to determine that
 * the file is indeed BMP format).
 *
 * This code contributed by James Arthur Boucher.
 */

// Feb 98 - Added support for monochrome and 16-color BITMAPS
// ==========================================================

#include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */

#ifdef BMP_SUPPORTED


/* Macros to deal with unsigned chars as efficiently as compiler allows */

#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char U_CHAR;
#define UCH(x)	((int) (x))
#else /* !HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char U_CHAR;
#define UCH(x)	((int) (x))
#else
typedef char U_CHAR;
#define UCH(x)	((int) (x) & 0xFF)
#endif
#endif /* HAVE_UNSIGNED_CHAR */

extern	void	ExtDebugStop( int code );

//#define	ReadOK(file,buffer,len)	(JFREAD(file,buffer,len) == ((size_t) (len)))

/* Private version of data source object */

typedef struct _bmp_source_struct MLPTR bmp_source_ptr;

typedef struct _bmp_source_struct {

	struct cjpeg_source_struct pub; /* public fields */

	j_compress_ptr cinfo;		/* back link saves passing separate parm */

	JSAMPARRAY colormap;		/* BMP colormap (converted to my format) */

	jvirt_sarray_ptr whole_image;	/* Needed to reverse row order */

	JDIMENSION source_row;	/* Current source row number */

	JDIMENSION row_width;		/* Physical width of scanlines in file */
	int bits_per_pixel;		/* remembers 8- or 24-bit format */
	// NOTE: The above row_width and bits_per_pixel continue
	// to reflect only either 8 or 24,
	// but the truth is per the below
	int		iBPP;			// Remembers 1, 4, 8 or 24 format
	DWORD	dw_srccols;		// Source DIB columns
	
	HGLOBAL	hg_input;		// Input DATA handle
	DWORD	dw_insize;		// Input DATA size
	DWORD	dw_inused;		// Input BYTES used
	LPSTR	lp_input;		// Input data POINTER

} bmp_source_struct;

#define		WNO_DATA		-1

void	chkendd( void )
{
	int	i;
	i = 0;
}

LOCAL(int)
wingetc( bmp_source_ptr sinfo )
{
	int		c;

	c = (int)WNO_DATA;
	if( sinfo->hg_input && sinfo->lp_input &&
		(sinfo->dw_inused < sinfo->dw_insize ) )
	{
		c = (sinfo->lp_input[sinfo->dw_inused++] & 0xff);
	}
	else
	{
		chkendd();
	}
	return c;
}

LOCAL(int)
read_byte (bmp_source_ptr sinfo)
/* Read next byte from BMP file */
{
	HGLOBAL infile = sinfo->pub.input_file;
	int c;

//	if ((c = getc(infile)) == EOF)
	if ((c = wingetc( sinfo )) == WNO_DATA)
		ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
	return c;
}

BOOL	ReadOK( bmp_source_ptr sinfo, LPSTR buffer, int len)
{
	BOOL	flg;
	LPSTR	lpb;
	int		b, i, rd;

	flg = FALSE;
	i = len + 1;
	if( ( lpb = buffer ) && ( rd = len ) )
	{
		for( i = 0; i < rd; i++ )
		{
			b = read_byte( sinfo );
			if( b == WNO_DATA )
				break;
			lpb[i] = b;
		}
	}
	if( i == rd )
		flg = TRUE;
	return flg;
}


// Read the colormap from a BMP file
// For some reason I get a CRASH when I try to implement
// a 2-color MONOCHROME BMP support!!!
// So try allocating 256 even if less, and fill will 0's
// Add an ALLOCATED length to parameters
// Of course we can NOT alter the READ of the TRUTH
//
LOCAL(void)
read_colormap( bmp_source_ptr sinfo, int cmaplen, int mapentrysize,
			  int calloclen )
{
	int i;

	switch( mapentrysize )
	{
	case 3:
		/* BGR format (occurs in OS/2 files) */
		for( i = 0; i < cmaplen; i++ )
		{
			sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
			sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
			sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
			
		}
		break;

	case 4:
		/* BGR0 format (occurs in MS Windows files) */
		for( i = 0; i < cmaplen; i++ )
		{
			// read and store 3 colors
			sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
			sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
			sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
			// read and dump 4th byte of RGBQUAD
			(void) read_byte(sinfo);
		}
		break;

	default:
		ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
		break;

	}
	if( i < calloclen )
	{
		// continue to fill will zero's
		for( ; i < calloclen; i++ )
		{
			sinfo->colormap[2][i] = 0;
			sinfo->colormap[1][i] = 0;
			sinfo->colormap[0][i] = 0;
		}
	}
}


/*
 * Read one row of pixels.
 * The image has been read into the whole_image array, but is otherwise
 * unprocessed.  We must read it out in top-to-bottom row order, and if
 * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
 */

/* This version is for reading 8-bit colormap indexes */
METHODDEF(JDIMENSION)
get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
	bmp_source_ptr source = (bmp_source_ptr) sinfo;
	JSAMPARRAY colormap = source->colormap;
	JSAMPARRAY image_ptr;
	int t;
	JSAMPROW inptr, outptr;
	JDIMENSION col;

	/* Fetch next row from virtual array */
	source->source_row--;
	image_ptr = (*cinfo->mem->access_virt_sarray)
		((j_common_ptr) cinfo,
		source->whole_image,
		source->source_row,
		(JDIMENSION) 1,
		FALSE );

	/* Expand the colormap indexes to real data */
	// This sort of expands the input to like 24-bit data
	// ==================================================
	inptr = image_ptr[0];

	outptr = source->pub.buffer[0];

	for( col = cinfo->image_width; col > 0; col-- )
	{
		t = GETJSAMPLE(*inptr++);
		*outptr++ = colormap[0][t];	/* can omit GETJSAMPLE() safely */
		*outptr++ = colormap[1][t];
		*outptr++ = colormap[2][t];
	}

	return 1;
}


/* This version is for reading 24-bit pixels */
METHODDEF(JDIMENSION)
get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
	bmp_source_ptr source = (bmp_source_ptr) sinfo;
	JSAMPARRAY image_ptr;
	JSAMPROW inptr, outptr;
	JDIMENSION col;


	/* Fetch next row from virtual array */
	source->source_row--;
	image_ptr = (*cinfo->mem->access_virt_sarray)
		((j_common_ptr) cinfo,
		source->whole_image,
		source->source_row,
		(JDIMENSION) 1,
		FALSE );

	/* Transfer data.
	 *	Note source values are in BGR order
	 * (even though Microsoft's own documents say the opposite).
	 */

	inptr = image_ptr[0];
	outptr = source->pub.buffer[0];

	for( col = cinfo->image_width; col > 0; col-- )
	{
		outptr[2] = *inptr++;	/* can omit GETJSAMPLE() safely */
		outptr[1] = *inptr++;
		outptr[0] = *inptr++;
		outptr += 3;
	}

	return 1;
}

void	chkovr( void )
{
	int	i;
	ExtDebugStop( 1 );
	i = 0;
}

/*
 * This method loads the image into whole_image during the first call on
 * get_pixel_rows.  The get_pixel_rows pointer is then adjusted to call
 * get_8bit_row or get_24bit_row on subsequent calls.
 */

METHODDEF(JDIMENSION)
preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
	bmp_source_ptr source = (bmp_source_ptr) sinfo;
	HGLOBAL infile = source->pub.input_file;
	int c, iBPP, j, mask;
	JSAMPROW out_ptr;
	JSAMPARRAY image_ptr;
	JDIMENSION row, col, colc;
	cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;

	iBPP = source->iBPP;	// For WINDOWS BMP fix
	if( ( iBPP == 0 ) ||
		( iBPP == 8 ) ||
		( iBPP == 24) )
	{
		iBPP = 0;	// Nothing to do here
	}
	else if( ( iBPP == 1 ) ||
		( iBPP == 4 ) )
	{
		// NEED to adjust READ-IN
		chkovr();
	}
	else
	{
		ERREXIT(cinfo, JERR_BMP_BADCMAP);
	}

	/* Set up to read from the virtual array
	   in top-to-bottom order */
	// NOTE: Presently ONLY supports 8 and 24 BPP color depth
	switch( source->bits_per_pixel )
	{
		case 8:
			source->pub.get_pixel_rows = get_8bit_row;
			break;
		case 24:
			source->pub.get_pixel_rows = get_24bit_row;
			break;
		default:
			ERREXIT(cinfo, JERR_BMP_BADDEPTH);
	}

	/* Read the data into a virtual array
	   in input-file row order. */
	for( row = 0; row < cinfo->image_height; row++ )
	{
		if( progress != NULL )
		{
			progress->pub.pass_counter = (long) row;
			progress->pub.pass_limit = (long) cinfo->image_height;
			(*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
		}
		image_ptr = (*cinfo->mem->access_virt_sarray)
			((j_common_ptr) cinfo,
			source->whole_image,
			row,
			(JDIMENSION) 1,
			TRUE );
		out_ptr = image_ptr[0];

		if( iBPP )
		{
			colc = 0;
			for( col = source->dw_srccols; col > 0; col-- )
			{
				if( ( c = wingetc( source ) ) == WNO_DATA )
					ERREXIT(cinfo, JERR_INPUT_EOF);
				if( iBPP == 1 )
				{
					// EXPAND to EIGHT BYTES
					mask = 0x80;
					for( j = 0; j < 8; j++ )
					{
						if( colc < source->row_width )
						{
							if( c & mask )
								*out_ptr++ = (JSAMPLE) 1;
							else
								*out_ptr++ = (JSAMPLE) 0;
							colc++;
						}
						mask = (mask >> 1);
					}
				}
				else	// if( iBPP == 4 )
				{
					// Expand to TWO BYTES
					if( colc < source->row_width )
					{
						mask = (( c & 0xf0 ) >> 4 );
						*out_ptr++ = (JSAMPLE) mask;
						colc++;
						if( colc < source->row_width )
						{
							mask = (c & 0x0f);
							*out_ptr++ = (JSAMPLE) mask;
							colc++;
						}
					}
				}
//				if( colc >= source->row_width )
//				{
//					chkovr();
//				}
			}	// for the SOURCE rows
		}
		else
		{
		// NOTE: Original ONLY supported 8 and 24 BPP color depth
		// This source->row_width is either
		// biWidth * 3 for 24-bit samples, or
		// biWidth     for  8-bit samples,
		// padded to DWORD boundary
			for( col = source->row_width; col > 0; col-- )
			{
				/* inline copy of read_byte() for speed */
				// if ((c = getc(infile)) == EOF)
				if( ( c = wingetc( source ) ) == WNO_DATA )
					ERREXIT(cinfo, JERR_INPUT_EOF);
				*out_ptr++ = (JSAMPLE) c;
			}
		}
	}	// for each row

	if( progress != NULL )
		progress->completed_extra_passes++;

	source->source_row = cinfo->image_height;

	/* And read the first row */
	return (*source->pub.get_pixel_rows) (cinfo, sinfo);

}

#define GET_2B(array,offset)  ((unsigned int) UCH(array[offset]) + \
			       (((unsigned int) UCH(array[offset+1])) << 8))
#define GET_4B(array,offset)  ((INT32) UCH(array[offset]) + \
			       (((INT32) UCH(array[offset+1])) << 8) + \
			       (((INT32) UCH(array[offset+2])) << 16) + \
			       (((INT32) UCH(array[offset+3])) << 24))


/*
 * Read the file header; return image size and component count.
 */

METHODDEF(void)
start_input_bmp( j_compress_ptr cinfo, cjpeg_source_ptr sinfo )
{
	bmp_source_ptr	source;
	//  U_CHAR bmpfileheader[14];
	U_CHAR			bmpinfoheader[64];
	INT32			bfOffBits;
	INT32			headerSize;
	INT32			biWidth;
	INT32			biHeight;
	unsigned int	biPlanes;
	INT32			biCompression;
	INT32			biXPelsPerMeter,biYPelsPerMeter;
	INT32			biClrUsed;
	int				mapentrysize;	/* 0 indicates no colormap */
	INT32			bPad;
	JDIMENSION		row_width;
	int				nBPP;	// now source->iBPP;

//	source->hg_input = 0;
//	source->dw_insize = 0;
//	source->dw_inused = 0;
//	source->lp_input = 0;

	source = (bmp_source_ptr) sinfo;
	biWidth = 0;		/* initialize to avoid compiler warning */
	biHeight = 0;
	mapentrysize = 0;		/* 0 indicates no colormap */
	source->colormap = 0;	// No MEMORY allocation for COLOR MAP YET
	biClrUsed = 0;
	bPad = 0;	// Padding after HEADER (BITMAPINFOHEADER for Windows)
	source->iBPP = 0;	// If WINDOWS BMP contains ACTUAL BPP

	// plus COLOR Map.
	if( ( source->hg_input ) &&
		( source->dw_insize ) &&
		( source->lp_input = GlobalLock( source->hg_input ) ) &&
		( source->dw_insize <= GlobalSize( source->hg_input ) ) )
	{
		// start used counter
		source->dw_inused = 0;
	}
	else
	{
		// errant INPUT parameters
		if( source->hg_input && source->lp_input )
		{
			GlobalUnlock( source->hg_input );
		}
		source->hg_input = 0;
		source->lp_input = 0;
		ERREXIT(cinfo, JERR_INPUT_EOF);
	}


	/* Read and verify the bitmap file header */
//  if (! ReadOK( source, bmpfileheader, 14))
//    ERREXIT(cinfo, JERR_INPUT_EOF);
//  if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
//    ERREXIT(cinfo, JERR_BMP_NOT);
//  bfOffBits = (INT32) GET_4B(bmpfileheader,10);
  /* We ignore the remaining fileheader fields */

  /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
   * or 64 bytes (OS/2 2.x).  Check the first 4 bytes to find out which.
   */

	// Now using DIB (Device Independent Bitmap) (ie NO file header)
	// Read first 4 BYTES
	if( !ReadOK( source, bmpinfoheader, 4 ) )
		ERREXIT(cinfo, JERR_INPUT_EOF);

	//   DWORD  biSize; for Windows ( = sizeof(BITMAPINFOHEADER) ) 
	headerSize = (INT32) GET_4B(bmpinfoheader,0);

	// If a NON-Supported SIZE is in first 4 bytes
	if( ( headerSize < 12 ) || ( headerSize > 64 ) )
		ERREXIT(cinfo, JERR_BMP_BADHEADER);

	// Read BALANCE of stated HEADER size (less already read)
	if( !ReadOK( source, bmpinfoheader+4, headerSize-4 ) )
		ERREXIT(cinfo, JERR_INPUT_EOF);

	switch( (int)headerSize )
	{

	case 12:
		/* Decode OS/2 1.x header (per Microsoft
			this is a BITMAPCOREHEADER) */
		biWidth = (INT32) GET_2B(bmpinfoheader,4);
		biHeight = (INT32) GET_2B(bmpinfoheader,6);
		biPlanes = GET_2B(bmpinfoheader,8);
		source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
		switch( source->bits_per_pixel )
		{
		case 8:		/* colormapped image */
			mapentrysize = 3;		/* OS/2 uses RGBTRIPLE colormap */
			TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
			break;

		case 24:	/* RGB image */
			TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
			break;

		default:
			ERREXIT(cinfo, JERR_BMP_BADDEPTH);
			break;
		}
		if( biPlanes != 1 )
			ERREXIT(cinfo, JERR_BMP_BADPLANES);
		break;

	case 40:
	case 64:
//typedef struct tagBITMAPINFOHEADER{ // bmih 
//   DWORD  biSize; 
//   LONG   biWidth; 
//   LONG   biHeight; 
//   WORD   biPlanes; 
//   WORD   biBitCount 
//   DWORD  biCompression; 
//   DWORD  biSizeImage; 
//   LONG   biXPelsPerMeter; 
//   LONG   biYPelsPerMeter; 
//   DWORD  biClrUsed; 
//   DWORD  biClrImportant; 
////} BITMAPINFOHEADER; 

		/* Decode Windows 3.x header
			(Microsoft calls this a BITMAPINFOHEADER) */

		/* or OS/2 2.x header, which has additional fields
			that we ignore */
		biWidth = GET_4B(bmpinfoheader,4);
		biHeight = GET_4B(bmpinfoheader,8);
		biPlanes = GET_2B(bmpinfoheader,12);
		nBPP = (int) GET_2B(bmpinfoheader,14);
		source->bits_per_pixel = nBPP;
		biCompression = GET_4B(bmpinfoheader,16);
		biXPelsPerMeter = GET_4B(bmpinfoheader,24);
		biYPelsPerMeter = GET_4B(bmpinfoheader,28);
		// *** IS THIS ANYTHING OTHER THAN AN INDICATION ***
		biClrUsed = GET_4B(bmpinfoheader,32);

		/* biSizeImage, biClrImportant fields are ignored,
			but have been read */
		// *** WINDOWS SPECIFIC ***
		if( headerSize == sizeof(BITMAPINFOHEADER) )
		{
			int	iTrace;
			//TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
			// We can calculate bPad
		    // Fix Bits per Pixel
			if( nBPP <= 1 )
				source->iBPP = 1;
			else if( nBPP <= 4 )
				source->iBPP = 4;
			else if( nBPP <= 8 )
				source->iBPP = 8;
			else
				source->iBPP = 24;
			// NOTE: For the present this code
			//	ORG ONLY SUPPORTED 256 and 24-bit COLOR
			// ===================================
			switch( source->iBPP )
			{
			case 1:		// Monochrome
				mapentrysize = 4;	// Windows uses RGBQUAD colormap
				biClrUsed = 2;
//				ERREXIT(cinfo, JERR_BMP_BADDEPTH);
				source->bits_per_pixel = 8;	// input read will do fixup
				source->dw_srccols = biWidth / 8;
				if( biWidth % 8 )
					source->dw_srccols++;
				iTrace = JTRC_BMP_1BPP;
				break;
			case 4:
				mapentrysize = 4;	// Windows uses RGBQUAD colormap
				biClrUsed = 16;
//				ERREXIT(cinfo, JERR_BMP_BADDEPTH);
				source->bits_per_pixel = 8;	// input read will do fixup
				source->dw_srccols = biWidth / 2;
				if( biWidth % 2 )
					source->dw_srccols++;
				iTrace = JTRC_BMP_4BPP;
				break;
			case 8:
				mapentrysize = 4;	// Windows uses RGBQUAD colormap
				biClrUsed = 256;
				source->bits_per_pixel = 8;	// input read will do fixup
				source->dw_srccols = biWidth;
				iTrace = JTRC_BMP_8BPP;
				break;
			default:	// Default to 24-bit DIB
				mapentrysize = 0;	// NOTHING
				biClrUsed = 0;		// Each 3 Bytes is a COLOR
				source->bits_per_pixel = 24;	// input read will do fixup
				source->dw_srccols = biWidth * 3;
				iTrace = JTRC_BMP_24BPP;
				break;
			}
			while( (source->dw_srccols & 3) != 0 )
				source->dw_srccols++;
			TRACEMS3(cinfo, 1, iTrace,
				(int) biWidth, (int) biHeight,
				(int) source->dw_srccols );
			bPad = biClrUsed * mapentrysize;
			// *** End WINDOWS SPECIFIC ***
		}
		else
		{
			switch( source->bits_per_pixel )
			{
			case 8:		/* colormapped image */
				mapentrysize = 4;		/* Windows uses RGBQUAD colormap */
				TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
				break;

			case 24:	/* RGB image */
				TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
				break;

			default:
				ERREXIT(cinfo, JERR_BMP_BADDEPTH);
				break;

			}
			if( biClrUsed <= 0 )
				biClrUsed = 256;		/* assume it's 256 */
			else if( biClrUsed > 256 )
				ERREXIT(cinfo, JERR_BMP_BADCMAP);
			bPad = biClrUsed * mapentrysize;
		}

		if( biPlanes != 1 )
			ERREXIT(cinfo, JERR_BMP_BADPLANES);
		if( biCompression != 0 )
			ERREXIT(cinfo, JERR_BMP_COMPRESSED);

		if( ( biXPelsPerMeter > 0 ) &&
			( biYPelsPerMeter > 0 ) )
		{
			/* Set JFIF density parameters from the BMP data */
			cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
			cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
			cinfo->density_unit = 2;	/* dots/cm */
		}
		break;

	default:
		ERREXIT(cinfo, JERR_BMP_BADHEADER);
		break;

	}

	/* Compute distance to bitmap data.
	   will adjust for colormap below */
	bfOffBits = headerSize;
	//bPad = bfOffBits - (headerSize + 14);
	//  bPad = 0;

	/* Read the colormap, if any */
	if( mapentrysize > 0 )
	{
		int	iClrAlloc;
//		if( biClrUsed <= 0 )
//			biClrUsed = 256;		/* assume it's 256 */
//		else if( biClrUsed > 256 )
//			ERREXIT(cinfo, JERR_BMP_BADCMAP);
		if( biClrUsed <= 256 )
			iClrAlloc = 256;
		else if( biClrUsed > 256 )
			ERREXIT(cinfo, JERR_BMP_BADCMAP);

		/* Allocate space to store the colormap */
		source->colormap = (*cinfo->mem->alloc_sarray)
			((j_common_ptr) cinfo,
			JPOOL_IMAGE,
			(JDIMENSION) iClrAlloc,		// biClrUsed,
			(JDIMENSION) 3);

		/* and read it from the file */
		read_colormap( source, (int)biClrUsed, mapentrysize,
			iClrAlloc );

		bfOffBits += (biClrUsed * mapentrysize);

		/* account for size of colormap */
		bPad -= biClrUsed * mapentrysize;
		
	}

	/* Skip any remaining pad bytes */
	if( bPad < 0 )	/* incorrect bfOffBits value? */
		ERREXIT(cinfo, JERR_BMP_BADHEADER);

	while( --bPad >= 0 )
	{
		(void) read_byte(source);
	}

	/* Compute row width in file,
		including padding to 4-byte boundary */
	//	ONLY SUPPORTS 256 and 24-bit COLOR
	if( source->bits_per_pixel == 24 )
		row_width = (JDIMENSION) (biWidth * 3);
	else
		row_width = (JDIMENSION) biWidth;

	while( (row_width & 3) != 0 ) row_width++;

	source->row_width = row_width;
	if( source->iBPP )
	{
		// We have a WINDOWS BMP
	}
	/* Allocate space for inversion array,
		prepare for preload pass */
	source->whole_image = (*cinfo->mem->request_virt_sarray)
		((j_common_ptr) cinfo,
		JPOOL_IMAGE,
		FALSE,
		row_width,
		(JDIMENSION)biHeight,
		(JDIMENSION) 1 );

	source->pub.get_pixel_rows = preload_image;

	if( cinfo->progress != NULL )
	{
		cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;

		progress->total_extra_passes++; /* count file input as separate pass */
	}

	/* Allocate one-row buffer for returned data */
	source->pub.buffer = (*cinfo->mem->alloc_sarray)
		((j_common_ptr) cinfo,
		JPOOL_IMAGE,
		(JDIMENSION) (biWidth * 3),		// NOTE: Always expanded to 24-bit
		(JDIMENSION) 1 );

	source->pub.buffer_height = 1;

	cinfo->in_color_space = JCS_RGB;
	cinfo->input_components = 3;
	cinfo->data_precision = 8;
	cinfo->image_width = (JDIMENSION) biWidth;
	cinfo->image_height = (JDIMENSION) biHeight;

}


/*
 * Finish up at the end of the file.
 */

METHODDEF(void)
finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
	/* well, nearly no work */
	bmp_source_ptr source = (bmp_source_ptr) sinfo;
	if( source->hg_input && source->lp_input )
		GlobalUnlock( source->hg_input );
	source->hg_input = 0;
	source->lp_input = 0;
	source->dw_inused = source->dw_insize;

}


/*
 * The module selection routine for BMP format input.
 */

GLOBAL(cjpeg_source_ptr)
jinit_read_bmp( j_compress_ptr cinfo, HGLOBAL hgIn, DWORD dwSz )
{
	bmp_source_ptr source;

	/* Create module interface object */
	source = (bmp_source_ptr) (*cinfo->mem->alloc_small)
		((j_common_ptr) cinfo,
		JPOOL_IMAGE,
		SIZEOF(bmp_source_struct) );

	source->cinfo = cinfo;	/* make back link for subroutines */

	/* Fill in method ptrs,
		except get_pixel_rows which start_input sets */
	source->pub.start_input = start_input_bmp;
	source->pub.finish_input = finish_input_bmp;

	source->hg_input = hgIn;
	source->dw_insize = dwSz;
	source->dw_inused = 0;
	source->lp_input = 0;

	return (cjpeg_source_ptr) source;
}

#endif /* BMP_SUPPORTED */

// eof - WRdBmp6.c
