Blame test/bmp.c

Packit Service b05338
/* Copyright (C)2004 Landmark Graphics Corporation
Packit Service b05338
 * Copyright (C)2005 Sun Microsystems, Inc.
Packit Service b05338
 * Copyright (C)2010, 2012 D. R. Commander
Packit Service b05338
 *
Packit Service b05338
 * This library is free software and may be redistributed and/or modified under
Packit Service b05338
 * the terms of the wxWindows Library License, Version 3.1 or (at your option)
Packit Service b05338
 * any later version.  The full license is in the LICENSE.txt file included
Packit Service b05338
 * with this distribution.
Packit Service b05338
 *
Packit Service b05338
 * This library is distributed in the hope that it will be useful,
Packit Service b05338
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service b05338
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service b05338
 * wxWindows Library License for more details.
Packit Service b05338
*/
Packit Service b05338
Packit Service b05338
#include <fcntl.h>
Packit Service b05338
#include <sys/types.h>
Packit Service b05338
#include <sys/stat.h>
Packit Service b05338
#include <errno.h>
Packit Service b05338
#include <stdlib.h>
Packit Service b05338
#include <stdio.h>
Packit Service b05338
#include <string.h>
Packit Service b05338
#ifdef _WIN32
Packit Service b05338
 #include <io.h>
Packit Service b05338
#else
Packit Service b05338
 #include <unistd.h>
Packit Service b05338
#endif
Packit Service b05338
#include "./tjutil.h"
Packit Service b05338
#include "./bmp.h"
Packit Service b05338
Packit Service b05338
#define byteswap(i) ( \
Packit Service b05338
	(((i) & 0xff000000) >> 24) | \
Packit Service b05338
	(((i) & 0x00ff0000) >>  8) | \
Packit Service b05338
	(((i) & 0x0000ff00) <<  8) | \
Packit Service b05338
	(((i) & 0x000000ff) << 24) )
Packit Service b05338
Packit Service b05338
#define byteswap16(i) ( \
Packit Service b05338
	(((i) & 0xff00) >> 8) | \
Packit Service b05338
	(((i) & 0x00ff) << 8) )
Packit Service b05338
Packit Service b05338
static __inline int littleendian(void)
Packit Service b05338
{
Packit Service b05338
	unsigned int value=1;
Packit Service b05338
	unsigned char *ptr=(unsigned char *)(&value);
Packit Service b05338
	if(ptr[0]==1 && ptr[3]==0) return 1;
Packit Service b05338
	else return 0;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
#ifndef BI_BITFIELDS
Packit Service b05338
#define BI_BITFIELDS 3L
Packit Service b05338
#endif
Packit Service b05338
#ifndef BI_RGB
Packit Service b05338
#define BI_RGB 0L
Packit Service b05338
#endif
Packit Service b05338
Packit Service b05338
#define BMPHDRSIZE 54
Packit Service b05338
typedef struct _bmphdr
Packit Service b05338
{
Packit Service b05338
	unsigned short bfType;
Packit Service b05338
	unsigned int bfSize;
Packit Service b05338
	unsigned short bfReserved1, bfReserved2;
Packit Service b05338
	unsigned int bfOffBits;
Packit Service b05338
Packit Service b05338
	unsigned int biSize;
Packit Service b05338
	int biWidth, biHeight;
Packit Service b05338
	unsigned short biPlanes, biBitCount;
Packit Service b05338
	unsigned int biCompression, biSizeImage;
Packit Service b05338
	int biXPelsPerMeter, biYPelsPerMeter;
Packit Service b05338
	unsigned int biClrUsed, biClrImportant;
Packit Service b05338
} bmphdr;
Packit Service b05338
Packit Service b05338
static const char *__bmperr="No error";
Packit Service b05338
Packit Service b05338
static const int ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
Packit Service b05338
static const int roffset[BMPPIXELFORMATS]={0, 0, 2, 2, 3, 1};
Packit Service b05338
static const int goffset[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
Packit Service b05338
static const int boffset[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
Packit Service b05338
Packit Service b05338
#define _throw(m) {__bmperr=m;  retcode=-1;  goto finally;}
Packit Service b05338
#define _unix(f) {if((f)==-1) _throw(strerror(errno));}
Packit Service b05338
#define _catch(f) {if((f)==-1) {retcode=-1;  goto finally;}}
Packit Service b05338
Packit Service b05338
#define readme(fd, addr, size) \
Packit Service b05338
	if((bytesread=read(fd, addr, (size)))==-1) _throw(strerror(errno)); \
Packit Service b05338
	if(bytesread!=(size)) _throw("Read error");
Packit Service b05338
Packit Service b05338
void pixelconvert(unsigned char *srcbuf, enum BMPPIXELFORMAT srcformat,
Packit Service b05338
	int srcpitch, unsigned char *dstbuf, enum BMPPIXELFORMAT dstformat, int dstpitch,
Packit Service b05338
	int w, int h, int flip)
Packit Service b05338
{
Packit Service b05338
	unsigned char *srcptr, *srcptr0, *dstptr, *dstptr0;
Packit Service b05338
	int i, j;
Packit Service b05338
Packit Service b05338
	srcptr=flip? &srcbuf[srcpitch*(h-1)]:srcbuf;
Packit Service b05338
	for(j=0, dstptr=dstbuf; j
Packit Service b05338
		srcptr+=flip? -srcpitch:srcpitch, dstptr+=dstpitch)
Packit Service b05338
	{
Packit Service b05338
		for(i=0, srcptr0=srcptr, dstptr0=dstptr; i
Packit Service b05338
			srcptr0+=ps[srcformat], dstptr0+=ps[dstformat])
Packit Service b05338
		{
Packit Service b05338
			dstptr0[roffset[dstformat]]=srcptr0[roffset[srcformat]];
Packit Service b05338
			dstptr0[goffset[dstformat]]=srcptr0[goffset[srcformat]];
Packit Service b05338
			dstptr0[boffset[dstformat]]=srcptr0[boffset[srcformat]];
Packit Service b05338
		}
Packit Service b05338
	}
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
int loadppm(int *fd, unsigned char **buf, int *w, int *h,
Packit Service b05338
	enum BMPPIXELFORMAT f, int align, int dstbottomup, int ascii)
Packit Service b05338
{
Packit Service b05338
	FILE *fs=NULL;  int retcode=0, scalefactor, dstpitch;
Packit Service b05338
	unsigned char *tempbuf=NULL;  char temps[255], temps2[255];
Packit Service b05338
	int numread=0, totalread=0, pixel[3], i, j;
Packit Service b05338
Packit Service b05338
	if((fs=fdopen(*fd, "r"))==NULL) _throw(strerror(errno));
Packit Service b05338
Packit Service b05338
	do
Packit Service b05338
	{
Packit Service b05338
		if(!fgets(temps, 255, fs)) _throw("Read error");
Packit Service b05338
		if(strlen(temps)==0 || temps[0]=='\n') continue;
Packit Service b05338
		if(sscanf(temps, "%s", temps2)==1 && temps2[1]=='#') continue;
Packit Service b05338
		switch(totalread)
Packit Service b05338
		{
Packit Service b05338
			case 0:
Packit Service b05338
				if((numread=sscanf(temps, "%d %d %d", w, h, &scalefactor))==EOF)
Packit Service b05338
					_throw("Read error");
Packit Service b05338
				break;
Packit Service b05338
			case 1:
Packit Service b05338
				if((numread=sscanf(temps, "%d %d", h, &scalefactor))==EOF)
Packit Service b05338
					_throw("Read error");
Packit Service b05338
				break;
Packit Service b05338
			case 2:
Packit Service b05338
				if((numread=sscanf(temps, "%d", &scalefactor))==EOF)
Packit Service b05338
					_throw("Read error");
Packit Service b05338
				break;
Packit Service b05338
		}
Packit Service b05338
		totalread+=numread;
Packit Service b05338
	} while(totalread<3);
Packit Service b05338
	if((*w)<1 || (*h)<1 || scalefactor<1) _throw("Corrupt PPM header");
Packit Service b05338
Packit Service b05338
	dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
Packit Service b05338
	if((*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
Packit Service b05338
		_throw("Memory allocation error");
Packit Service b05338
	if(ascii)
Packit Service b05338
	{
Packit Service b05338
		for(j=0; j<*h; j++)
Packit Service b05338
		{
Packit Service b05338
			for(i=0; i<*w; i++)
Packit Service b05338
			{
Packit Service b05338
				if(fscanf(fs, "%d%d%d", &pixel[0], &pixel[1], &pixel[2])!=3)
Packit Service b05338
					_throw("Read error");
Packit Service b05338
				(*buf)[j*dstpitch+i*ps[f]+roffset[f]]=(unsigned char)(pixel[0]*255/scalefactor);
Packit Service b05338
				(*buf)[j*dstpitch+i*ps[f]+goffset[f]]=(unsigned char)(pixel[1]*255/scalefactor);
Packit Service b05338
				(*buf)[j*dstpitch+i*ps[f]+boffset[f]]=(unsigned char)(pixel[2]*255/scalefactor);
Packit Service b05338
			}
Packit Service b05338
		}
Packit Service b05338
	}
Packit Service b05338
	else
Packit Service b05338
	{
Packit Service b05338
		if(scalefactor!=255)
Packit Service b05338
			_throw("Binary PPMs must have 8-bit components");
Packit Service b05338
		if((tempbuf=(unsigned char *)malloc((*w)*(*h)*3))==NULL)
Packit Service b05338
			_throw("Memory allocation error");
Packit Service b05338
		if(fread(tempbuf, (*w)*(*h)*3, 1, fs)!=1) _throw("Read error");
Packit Service b05338
		pixelconvert(tempbuf, BMP_RGB, (*w)*3, *buf, f, dstpitch, *w, *h, dstbottomup);
Packit Service b05338
	}
Packit Service b05338
Packit Service b05338
	finally:
Packit Service b05338
	if(fs) {fclose(fs);  *fd=-1;}
Packit Service b05338
	if(tempbuf) free(tempbuf);
Packit Service b05338
	return retcode;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
Packit Service b05338
int loadbmp(char *filename, unsigned char **buf, int *w, int *h, 
Packit Service b05338
	enum BMPPIXELFORMAT f, int align, int dstbottomup)
Packit Service b05338
{
Packit Service b05338
	int fd=-1, bytesread, srcpitch, srcbottomup=1, srcps, dstpitch,
Packit Service b05338
		retcode=0;
Packit Service b05338
	unsigned char *tempbuf=NULL;
Packit Service b05338
	bmphdr bh;  int flags=O_RDONLY;
Packit Service b05338
Packit Service b05338
	dstbottomup=dstbottomup? 1:0;
Packit Service b05338
	#ifdef _WIN32
Packit Service b05338
	flags|=O_BINARY;
Packit Service b05338
	#endif
Packit Service b05338
	if(!filename || !buf || !w || !h || f<0 || f>BMPPIXELFORMATS-1 || align<1)
Packit Service b05338
		_throw("invalid argument to loadbmp()");
Packit Service b05338
	if((align&(align-1))!=0)
Packit Service b05338
		_throw("Alignment must be a power of 2");
Packit Service b05338
	_unix(fd=open(filename, flags));
Packit Service b05338
Packit Service b05338
	readme(fd, &bh.bfType, sizeof(unsigned short));
Packit Service b05338
	if(!littleendian())	bh.bfType=byteswap16(bh.bfType);
Packit Service b05338
Packit Service b05338
	if(bh.bfType==0x3650)
Packit Service b05338
	{
Packit Service b05338
		_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 0));
Packit Service b05338
		goto finally;
Packit Service b05338
	}
Packit Service b05338
	if(bh.bfType==0x3350)
Packit Service b05338
	{
Packit Service b05338
		_catch(loadppm(&fd, buf, w, h, f, align, dstbottomup, 1));
Packit Service b05338
		goto finally;
Packit Service b05338
	}
Packit Service b05338
Packit Service b05338
	readme(fd, &bh.bfSize, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.bfReserved1, sizeof(unsigned short));
Packit Service b05338
	readme(fd, &bh.bfReserved2, sizeof(unsigned short));
Packit Service b05338
	readme(fd, &bh.bfOffBits, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.biSize, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.biWidth, sizeof(int));
Packit Service b05338
	readme(fd, &bh.biHeight, sizeof(int));
Packit Service b05338
	readme(fd, &bh.biPlanes, sizeof(unsigned short));
Packit Service b05338
	readme(fd, &bh.biBitCount, sizeof(unsigned short));
Packit Service b05338
	readme(fd, &bh.biCompression, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.biSizeImage, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.biXPelsPerMeter, sizeof(int));
Packit Service b05338
	readme(fd, &bh.biYPelsPerMeter, sizeof(int));
Packit Service b05338
	readme(fd, &bh.biClrUsed, sizeof(unsigned int));
Packit Service b05338
	readme(fd, &bh.biClrImportant, sizeof(unsigned int));
Packit Service b05338
Packit Service b05338
	if(!littleendian())
Packit Service b05338
	{
Packit Service b05338
		bh.bfSize=byteswap(bh.bfSize);
Packit Service b05338
		bh.bfOffBits=byteswap(bh.bfOffBits);
Packit Service b05338
		bh.biSize=byteswap(bh.biSize);
Packit Service b05338
		bh.biWidth=byteswap(bh.biWidth);
Packit Service b05338
		bh.biHeight=byteswap(bh.biHeight);
Packit Service b05338
		bh.biPlanes=byteswap16(bh.biPlanes);
Packit Service b05338
		bh.biBitCount=byteswap16(bh.biBitCount);
Packit Service b05338
		bh.biCompression=byteswap(bh.biCompression);
Packit Service b05338
		bh.biSizeImage=byteswap(bh.biSizeImage);
Packit Service b05338
		bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
Packit Service b05338
		bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
Packit Service b05338
		bh.biClrUsed=byteswap(bh.biClrUsed);
Packit Service b05338
		bh.biClrImportant=byteswap(bh.biClrImportant);
Packit Service b05338
	}
Packit Service b05338
Packit Service b05338
	if(bh.bfType!=0x4d42 || bh.bfOffBits
Packit Service b05338
	|| bh.biWidth<1 || bh.biHeight==0)
Packit Service b05338
		_throw("Corrupt bitmap header");
Packit Service b05338
	if((bh.biBitCount!=24 && bh.biBitCount!=32) || bh.biCompression!=BI_RGB)
Packit Service b05338
		_throw("Only uncompessed RGB bitmaps are supported");
Packit Service b05338
Packit Service b05338
	*w=bh.biWidth;  *h=bh.biHeight;  srcps=bh.biBitCount/8;
Packit Service b05338
	if(*h<0) {*h=-(*h);  srcbottomup=0;}
Packit Service b05338
	srcpitch=(((*w)*srcps)+3)&(~3);
Packit Service b05338
	dstpitch=(((*w)*ps[f])+(align-1))&(~(align-1));
Packit Service b05338
Packit Service b05338
	if(srcpitch*(*h)+bh.bfOffBits!=bh.bfSize) _throw("Corrupt bitmap header");
Packit Service b05338
	if((tempbuf=(unsigned char *)malloc(srcpitch*(*h)))==NULL
Packit Service b05338
	|| (*buf=(unsigned char *)malloc(dstpitch*(*h)))==NULL)
Packit Service b05338
		_throw("Memory allocation error");
Packit Service b05338
	if(lseek(fd, (long)bh.bfOffBits, SEEK_SET)!=(long)bh.bfOffBits)
Packit Service b05338
		_throw(strerror(errno));
Packit Service b05338
	_unix(bytesread=read(fd, tempbuf, srcpitch*(*h)));
Packit Service b05338
	if(bytesread!=srcpitch*(*h)) _throw("Read error");
Packit Service b05338
Packit Service b05338
	pixelconvert(tempbuf, BMP_BGR, srcpitch, *buf, f, dstpitch, *w, *h, 
Packit Service b05338
		srcbottomup!=dstbottomup);
Packit Service b05338
Packit Service b05338
	finally:
Packit Service b05338
	if(tempbuf) free(tempbuf);
Packit Service b05338
	if(fd!=-1) close(fd);
Packit Service b05338
	return retcode;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
#define writeme(fd, addr, size) \
Packit Service b05338
	if((byteswritten=write(fd, addr, (size)))==-1) _throw(strerror(errno)); \
Packit Service b05338
	if(byteswritten!=(size)) _throw("Write error");
Packit Service b05338
Packit Service b05338
int saveppm(char *filename, unsigned char *buf, int w, int h,
Packit Service b05338
	enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
Packit Service b05338
{
Packit Service b05338
	FILE *fs=NULL;  int retcode=0;
Packit Service b05338
	unsigned char *tempbuf=NULL;
Packit Service b05338
Packit Service b05338
	if((fs=fopen(filename, "wb"))==NULL) _throw(strerror(errno));
Packit Service b05338
	if(fprintf(fs, "P6\n")<1) _throw("Write error");
Packit Service b05338
	if(fprintf(fs, "%d %d\n", w, h)<1) _throw("Write error");
Packit Service b05338
	if(fprintf(fs, "255\n")<1) _throw("Write error");
Packit Service b05338
Packit Service b05338
	if((tempbuf=(unsigned char *)malloc(w*h*3))==NULL)
Packit Service b05338
		_throw("Memory allocation error");
Packit Service b05338
Packit Service b05338
	pixelconvert(buf, f, srcpitch, tempbuf, BMP_RGB, w*3, w, h, 
Packit Service b05338
		srcbottomup);
Packit Service b05338
Packit Service b05338
	if((fwrite(tempbuf, w*h*3, 1, fs))!=1) _throw("Write error");
Packit Service b05338
Packit Service b05338
	finally:
Packit Service b05338
	if(tempbuf) free(tempbuf);
Packit Service b05338
	if(fs) fclose(fs);
Packit Service b05338
	return retcode;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
int savebmp(char *filename, unsigned char *buf, int w, int h,
Packit Service b05338
	enum BMPPIXELFORMAT f, int srcpitch, int srcbottomup)
Packit Service b05338
{
Packit Service b05338
	int fd=-1, byteswritten, dstpitch, retcode=0;
Packit Service b05338
	int flags=O_RDWR|O_CREAT|O_TRUNC;
Packit Service b05338
	unsigned char *tempbuf=NULL;  char *temp;
Packit Service b05338
	bmphdr bh;  int mode;
Packit Service b05338
Packit Service b05338
	#ifdef _WIN32
Packit Service b05338
	flags|=O_BINARY;  mode=_S_IREAD|_S_IWRITE;
Packit Service b05338
	#else
Packit Service b05338
	mode=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
Packit Service b05338
	#endif
Packit Service b05338
	if(!filename || !buf || w<1 || h<1 || f<0 || f>BMPPIXELFORMATS-1 || srcpitch<0)
Packit Service b05338
		_throw("bad argument to savebmp()");
Packit Service b05338
Packit Service b05338
	if(srcpitch==0) srcpitch=w*ps[f];
Packit Service b05338
Packit Service b05338
	if((temp=strrchr(filename, '.'))!=NULL)
Packit Service b05338
	{
Packit Service b05338
		if(!strcasecmp(temp, ".ppm"))
Packit Service b05338
			return saveppm(filename, buf, w, h, f, srcpitch, srcbottomup);
Packit Service b05338
	}
Packit Service b05338
Packit Service b05338
	_unix(fd=open(filename, flags, mode));
Packit Service b05338
	dstpitch=((w*3)+3)&(~3);
Packit Service b05338
Packit Service b05338
	bh.bfType=0x4d42;
Packit Service b05338
	bh.bfSize=BMPHDRSIZE+dstpitch*h;
Packit Service b05338
	bh.bfReserved1=0;  bh.bfReserved2=0;
Packit Service b05338
	bh.bfOffBits=BMPHDRSIZE;
Packit Service b05338
	bh.biSize=40;
Packit Service b05338
	bh.biWidth=w;  bh.biHeight=h;
Packit Service b05338
	bh.biPlanes=0;  bh.biBitCount=24;
Packit Service b05338
	bh.biCompression=BI_RGB;  bh.biSizeImage=0;
Packit Service b05338
	bh.biXPelsPerMeter=0;  bh.biYPelsPerMeter=0;
Packit Service b05338
	bh.biClrUsed=0;  bh.biClrImportant=0;
Packit Service b05338
Packit Service b05338
	if(!littleendian())
Packit Service b05338
	{
Packit Service b05338
		bh.bfType=byteswap16(bh.bfType);
Packit Service b05338
		bh.bfSize=byteswap(bh.bfSize);
Packit Service b05338
		bh.bfOffBits=byteswap(bh.bfOffBits);
Packit Service b05338
		bh.biSize=byteswap(bh.biSize);
Packit Service b05338
		bh.biWidth=byteswap(bh.biWidth);
Packit Service b05338
		bh.biHeight=byteswap(bh.biHeight);
Packit Service b05338
		bh.biPlanes=byteswap16(bh.biPlanes);
Packit Service b05338
		bh.biBitCount=byteswap16(bh.biBitCount);
Packit Service b05338
		bh.biCompression=byteswap(bh.biCompression);
Packit Service b05338
		bh.biSizeImage=byteswap(bh.biSizeImage);
Packit Service b05338
		bh.biXPelsPerMeter=byteswap(bh.biXPelsPerMeter);
Packit Service b05338
		bh.biYPelsPerMeter=byteswap(bh.biYPelsPerMeter);
Packit Service b05338
		bh.biClrUsed=byteswap(bh.biClrUsed);
Packit Service b05338
		bh.biClrImportant=byteswap(bh.biClrImportant);
Packit Service b05338
	}
Packit Service b05338
Packit Service b05338
	writeme(fd, &bh.bfType, sizeof(unsigned short));
Packit Service b05338
	writeme(fd, &bh.bfSize, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.bfReserved1, sizeof(unsigned short));
Packit Service b05338
	writeme(fd, &bh.bfReserved2, sizeof(unsigned short));
Packit Service b05338
	writeme(fd, &bh.bfOffBits, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.biSize, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.biWidth, sizeof(int));
Packit Service b05338
	writeme(fd, &bh.biHeight, sizeof(int));
Packit Service b05338
	writeme(fd, &bh.biPlanes, sizeof(unsigned short));
Packit Service b05338
	writeme(fd, &bh.biBitCount, sizeof(unsigned short));
Packit Service b05338
	writeme(fd, &bh.biCompression, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.biSizeImage, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.biXPelsPerMeter, sizeof(int));
Packit Service b05338
	writeme(fd, &bh.biYPelsPerMeter, sizeof(int));
Packit Service b05338
	writeme(fd, &bh.biClrUsed, sizeof(unsigned int));
Packit Service b05338
	writeme(fd, &bh.biClrImportant, sizeof(unsigned int));
Packit Service b05338
Packit Service b05338
	if((tempbuf=(unsigned char *)malloc(dstpitch*h))==NULL)
Packit Service b05338
		_throw("Memory allocation error");
Packit Service b05338
Packit Service b05338
	pixelconvert(buf, f, srcpitch, tempbuf, BMP_BGR, dstpitch, w, h, 
Packit Service b05338
		!srcbottomup);
Packit Service b05338
Packit Service b05338
	if((byteswritten=write(fd, tempbuf, dstpitch*h))!=dstpitch*h)
Packit Service b05338
		_throw(strerror(errno));
Packit Service b05338
Packit Service b05338
	finally:
Packit Service b05338
	if(tempbuf) free(tempbuf);
Packit Service b05338
	if(fd!=-1) close(fd);
Packit Service b05338
	return retcode;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
const char *bmpgeterr(void)
Packit Service b05338
{
Packit Service b05338
	return __bmperr;
Packit Service b05338
}