Diff of /bmp.c [000000] .. [2a97a8] Maximize Restore

  Switch to side-by-side view

--- a
+++ b/bmp.c
@@ -0,0 +1,380 @@
+#include "filter.h"
+#include "sys_win.h"
+
+static int readBMPFileHeader(Image *im, file_spec input);
+
+
+#pragma pack(push, 1) 
+// Bitmap file header
+typedef struct tagwin3xHead{
+	short ImageFileType;						// Always 4D42h ("BM")
+	long  FileSize;								// Physical size of file in bytes
+	short Reserved1;							// Always 0
+	short Reserved2;							// Always 0
+	long  ImageDataOffset;						// Start of image data offset in bytes
+} win3xHead;
+
+typedef struct tagwin3xBitmapInfoHeader{
+	long  HeaderSize;							// Size of this header
+	long  ImageWidth;							// Image width in pixels
+	long  ImageHeight;							// Image height in pixels
+	short NumberOfImagePlanes;					// Number of planes (Always 1)
+	short BitsPerPixel;							// Bits per pixel (1,4, 8 or 24)
+	long  CompressionMethod;					// Compression method (0, 1 or 2)
+
+	long  SizeOfBitmap;							// Size of bitmap in bytes
+	long  HorzResolution;						// Horizontal resolution in pixels / meter
+	long  VertResolution;						// Vertical resolution in pixels / meter
+	long  NumColorsUsed;						// Number of colors in image
+	long  NumSignificantColors;					// Number of important colors in palette
+} win3xBitmapInfoHeader;
+#pragma pack(pop)
+
+
+
+int writeBMP( Image *im, fullPath *sfile )
+{
+	file_spec  output;
+	unsigned char *buf, *data;
+	long count;
+	int scanLength;
+	int y;
+	win3xHead head;							// First part of bitmap header
+	win3xBitmapInfoHeader ihead;			// Second part of bitmap header
+
+		
+	scanLength = (im->width * 3 + 1)/2;
+	scanLength *= 2;
+
+	// Build header structures
+
+	head.ImageFileType=0x4D42;				// Always 4D42h ("BM")
+	head.FileSize = scanLength * im->height+54;		// Physical size of file in bytes
+	head.Reserved1=0;						// Always 0
+	head.Reserved2=0;						// Always 0
+	head.ImageDataOffset= 54;				// Start of image data offset in bytes
+
+	ihead.HeaderSize=40;					// Size of this header
+	ihead.ImageWidth=im->width;				// Image width in pixels
+	ihead.ImageHeight=im->height;			// Image height in pixels
+	ihead.NumberOfImagePlanes=1;			// Number of planes (Always 1)
+	ihead.BitsPerPixel=24;					// Bits per pixel (24 bit color)
+	ihead.CompressionMethod=0;				// Compression method (0=uncompressed)
+
+	ihead.SizeOfBitmap = head.FileSize-54;	// Size of bitmap in bytes
+	ihead.HorzResolution=7085;				// Horizontal resolution in pixels / meter
+	ihead.VertResolution=7085;				// Vertical resolution in pixels / meter
+	ihead.NumColorsUsed =0;					// Number of colors in image
+	ihead.NumSignificantColors=0;			// Number of important colors in palette
+
+	if( myopen( sfile, write_bin, output )	)
+	{
+		PrintError("writeBMP, could not open file"); 
+		return -1;
+	}
+	
+	count = sizeof( head );
+	mywrite( output, count, &head );
+	if( count != sizeof( head ) )
+	{
+		PrintError("writeBMP, could not write header"); 
+		return -1;
+	}
+	
+
+	count = sizeof( ihead );
+	mywrite( output, count, &ihead );
+	if( count != sizeof( ihead ) )
+	{
+		PrintError("writeBMP, could not write header"); 
+		return -1;
+	}
+
+	buf = (unsigned char*)malloc( im->bytesPerLine + 1); // Worst case
+	if( buf == NULL )
+	{
+		PrintError( "Not enough memory" );
+		return -1;
+	}
+
+	// Write image in reverse order, also change rgb->bgr	
+	
+	data = *(im->data) + ((im->height-1) * im->bytesPerLine);
+	for(y=0; y<im->height; y++)
+	{
+		if( im->bitsPerPixel == 32 )	// Convert 4->3 samples
+		{
+			int x;
+			unsigned char *c1=buf, *c2=data;
+			for(x=0; x < im->width; x++)
+			{
+				*c1++ = c2[3];
+				*c1++ = c2[2];
+				*c1++ = c2[1];
+				c2 += 4;
+			}
+		}
+		else
+		{
+			int x;
+			unsigned char *c1=buf, *c2=buf;
+			for(x=0; x < im->width; x++)
+			{
+				*c1++ = c2[2];
+				*c1++ = c2[1];
+				*c1++ = c2[0];
+				c2 += 3;
+			}
+		}
+		
+
+
+		count = scanLength;
+		mywrite( output, count, buf );
+		if( count != scanLength )
+		{
+			PrintError("writeBMP, could not write image data");
+			free( buf );
+			return -1;
+		}
+		data -= im->bytesPerLine;
+	}
+	myclose( output );
+	free( buf );
+	
+	return 0;
+}
+
+
+// Read bitmap file
+static int readBMP( Image *im, fullPath *sfile )
+{
+	file_spec input;
+	unsigned char *data, *buf;
+	int y;
+	int scanLength;
+	long count;
+	
+	// Bitmap file open
+	if( myopen( sfile, read_bin, input )	)
+	{
+		PrintError("readBMP, could not open file"); 
+		return -1;
+	}
+
+
+	// Read bitmap file header
+
+	if( readBMPFileHeader(im, input)  )
+	{
+		PrintError("readBMP, error reading bitmap file header");
+		return -1;
+	}
+
+	scanLength = (im->width * 3 + 1)/2;
+	scanLength *= 2;
+
+	
+	im->data = (unsigned char**) mymalloc( im->dataSize );
+	if( im->data == NULL )
+	{
+		PrintError("Not enough memory");
+		return -1;
+	}
+
+	buf = (unsigned char*)malloc( im->bytesPerLine + 1); // Worst case
+	if( buf == NULL )
+	{
+		PrintError( "Not enough memory" );
+		return -1;
+	}
+	
+	data = *(im->data) + ((im->height-1) * im->bytesPerLine);
+	for(y=0; y<im->height; y++)
+	{
+		count = scanLength;
+		myread(  input, count, buf );
+		if( count != scanLength )
+		{
+			PrintError("Error reading image data");
+			return -1;
+		}
+		// Convert 3->4 samples; bgr->rgb
+		{
+			int x;
+			unsigned char *c1=buf, *c2=data;
+			for(x=0; x < im->width; x++)
+			{
+				*c2++ = UCHAR_MAX;
+				*c2++ = c1[2];
+				*c2++ = c1[1];
+				*c2++ = c1[0];
+				c1+=3;
+			}
+		}
+		data -= im->bytesPerLine;
+	}
+	
+	myclose(input);
+	free( buf );
+	return 0;
+}
+
+
+// Read bitmap file header
+static int readBMPFileHeader(Image *im, file_spec input)
+{
+	win3xHead header;						// First part of bitmap header
+	win3xBitmapInfoHeader iheader;			// Second part of bitmap header
+	long count;
+	
+	count = sizeof(header);
+	myread(  input, count, &header );
+	if( count != sizeof(header) )
+	{
+		PrintError("Error reading first BMP header segment");
+		return -1;
+	}
+
+	if(header.ImageFileType != 0x4D42)
+	{
+		PrintError("readBMPFileHeader, BMP bad magic No");
+		return -1;
+	}
+
+
+	count = sizeof(iheader);
+	myread(  input, count, &iheader );
+	if( count != sizeof(iheader) )
+	{
+		PrintError("Error reading second BMP header segment");
+		return -1;
+	}
+
+	if(iheader.HeaderSize != 40)
+	{			// Size of this header
+		PrintError("readBMPFileHeader, secondary header length wrong -- Not MS version 3 compatible");
+		return -1;
+	}
+
+	if(iheader.NumberOfImagePlanes != 1){	// Number of planes (Always 1)
+		PrintError("readBMPFileHeader, should be 1 image plane");
+		return -1;
+	}
+
+	if(iheader.BitsPerPixel != 24){			// Bits per pixel (1,4, 8 or 24)
+		PrintError("readBMPFileHeader, only 24 bit color supported");
+		return -1;
+	}
+	
+	if(iheader.CompressionMethod != 0)
+	{		// Compression method (0, 1 or 2)
+		PrintError("readBMPFileHeader, only uncompressed BMP supported");
+		return -1;
+	}
+	
+	SetImageDefaults( im );
+	
+	// Setup height and width
+	im->height = iheader.ImageHeight;
+	im->width  = iheader.ImageWidth;
+	
+	im->bitsPerPixel = 32;
+	im->bytesPerLine = im->width * 4;
+	im->dataSize = im->bytesPerLine * im->height;
+	
+	// Advance file pointer to start of image data
+	fseek( input, header.ImageDataOffset, SEEK_SET );
+	
+	return 0;							// Header ok -- no error
+}
+
+
+
+int makeTempPath( fullPath *path )
+{
+	file_spec fnum;
+	char *dir;
+	static int try = 0;
+	int i;
+	char fname[24];
+
+
+	dir = strrchr( path->name, '\\' );
+	if( dir == NULL )
+	{
+		dir = path->name;
+	}
+	else
+	{
+		dir++;
+	}
+
+	
+#define MAX_TEMP_TRY	1000
+	
+	try++;
+	
+	for(i=0; i < MAX_TEMP_TRY; try++,i++)
+	{
+		sprintf( fname, "_PTStitcher_tmp_%d", try );
+		if( strlen( fname ) + 2 < sizeof(path->name) - (strlen(path->name)-strlen(dir)) )
+		{
+			sprintf( dir, "%s", fname );
+			if( myopen( path, read_bin, fnum ))
+				break;
+			myclose( fnum );
+		}
+		else
+		{
+			PrintError("Path too long");
+			return -1;
+		}
+	}
+	if( try < MAX_TEMP_TRY )
+		return 0;
+	else
+		return -1;
+	
+}
+
+
+int readImage( Image *im, fullPath *sfile )
+{
+	char *ext,extension[4];
+	int i;
+	
+	ext = strrchr( sfile->name, '.' );
+	if( ext == NULL || strlen(ext) != 4 )
+	{
+		PrintError("File must have extension JPG, PNG, TIF or BMP");
+		return -1;
+	}
+	ext++;
+	strcpy( extension, ext );
+	for(i=0; i<3; i++)
+		extension[i] = tolower(extension[i]);
+
+	
+	if( strcmp( extension, "bmp" ) == 0 )
+		return readBMP(  im, sfile );
+	else if( strcmp( extension, "jpg" ) == 0 )
+		return readJPEG(im, sfile );
+	else if( strcmp( extension, "tif" ) == 0 )
+		return readTIFF(im, sfile );
+	else if( strcmp( extension, "png" ) == 0 )
+		return readPNG(im, sfile );
+	else
+	{
+		PrintError("Unsupported File Format: Must be JPEG, PNG, TIFF or BMP");
+		return -1;
+	}
+}
+		
+
+int writeImage( Image *im, fullPath *sfile )
+{
+	return writeBMP( im, sfile );
+}
+
+