#include <stdio.h> #include <stdlib.h> #include <string.h> #include "pic_private.h" #include "pic.h" // ---------------------------------------------------------------------------------------------------------------------------------- #pragma pack(1) typedef struct BMP_HEADER { unsigned short bfType; unsigned long bfSize; unsigned short Res1; unsigned short Res2; unsigned long bfOffBits; unsigned long biSize; unsigned long biWidth; unsigned long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } BMP_HEADER; #pragma pack() // ---------------------------------------------------------------------------------------------------------------------------------- unsigned long Pic_BMP_Write( const char *FileName, char *pPal, char *pDatas, unsigned long w, unsigned long h, unsigned long d) { FILE *file; BMP_HEADER bmph; unsigned long slsize; unsigned char *scanline; unsigned long i; long x,y,rest; unsigned char r,g,b; file=fopen(FileName,"wb"); if (!file) { return(0); } memset(&bmph,0,sizeof(BMP_HEADER)); bmph.bfType=19778; bmph.bfSize=sizeof(BMP_HEADER); bmph.bfSize+=w*h*d/8; if (pPal) { bmph.bfSize+=(256*4); } bmph.bfOffBits=sizeof(BMP_HEADER); if (pPal) { bmph.bfOffBits+=(256*4); } bmph.biSize=40;//sizeof(BMP_HEADER); bmph.biWidth=w; bmph.biHeight=h; bmph.biPlanes=1; bmph.biBitCount=(unsigned short)d; bmph.biCompression=0; bmph.biSizeImage=w*h*d/8; fwrite(&bmph,1,sizeof(BMP_HEADER),file); if (pPal) { for(i=0 ; i<256 ; i++) { fwrite(&pPal[i*3+0],1,1,file); fwrite(&pPal[i*3+1],1,1,file); fwrite(&pPal[i*3+2],1,1,file); fwrite(&pPal[i*3+2],1,1,file); } } slsize=w*d/8; scanline=(unsigned char*)Pic_calloc(1,slsize); if (!scanline) { Pic_SetError("BMP_Write, not enough memory for scanline"); return(0); } for(rest=0 ; ((w*d/8)+rest)%4!=0 ; rest++); for(y=0 ; y<(long)h ; y++) { memcpy(scanline,&pDatas[(h-y-1)*slsize],slsize); if (d==24) { for(x=0 ; x<(long)w ; x++) { b=scanline[x*3+0]; g=scanline[x*3+1]; r=scanline[x*3+2]; scanline[x*3+0]=b; scanline[x*3+1]=g; scanline[x*3+2]=r; } } fwrite(scanline,1,slsize,file); if (rest) { fwrite(scanline,1,rest,file); } } Pic_free(scanline); fclose(file); return(1); } // ---------------------------------------------------------------------------------------------------------------------------------- unsigned long Pic_BMP_Read( const char *FileName, char **ppPal, char **ppDatas, unsigned long *pWidth, unsigned long *pHeight, unsigned long *pDepth) { FILE *file; BMP_HEADER bmph; char *pPal; char *pDatas; unsigned char *scanline; long w,h,d; long i,x,y,rest; unsigned char r,g,b; unsigned char pad[4]; pPal=NULL; pDatas=NULL; file=fopen(FileName,"rb"); if (!file) { Pic_SetError("BMP_Read, unable to open %s",FileName); return(0); } fread(&bmph,1,sizeof(BMP_HEADER),file); *pWidth=w=bmph.biWidth; *pHeight=h=bmph.biHeight; *pDepth=d=bmph.biBitCount; if (d!=8 && d!=24) { Pic_SetError("BMP_Read, number of bits per pixel unsupported"); return(0); } if (*pDepth==8) { pPal=(char*)Pic_calloc(1,256*3); if (!pPal) { Pic_SetError("BMP_Read, not enough memory for palette"); return(0); } for(i=0 ; i<256 ; i++) { fread(&pPal[i*3+2],1,1,file); fread(&pPal[i*3+1],1,1,file); fread(&pPal[i*3+0],1,1,file); fread(&pad[0],1,1,file); } } pDatas=(char*)Pic_calloc(1,w*h*d/8); if (!pDatas) { if (pPal) { Pic_free(pPal); } Pic_SetError("BMP_Read, not enough memory for datas"); return(0); } scanline=(unsigned char*)Pic_calloc(1,w*h*d/8); if (!scanline) { if (pPal) { Pic_free(pPal); } Pic_free(pDatas); Pic_SetError("BMP_Read, not enough memory for scanline"); return(0); } for(rest=0 ; (w+rest)%4!=0 ; rest++); for(y=0 ; y<h ; y++) { fread(scanline,w,d/8,file); if (d==24) { for(x=0 ; x<w ; x++) { r=scanline[x*3+0]; g=scanline[x*3+1]; b=scanline[x*3+2]; scanline[x*3+0]=b; scanline[x*3+1]=g; scanline[x*3+2]=r; } } memcpy(&pDatas[(h-y-1)*w*d/8],scanline,w*d/8); fread(pad,rest,d/8,file); } fclose(file); Pic_free(scanline); *ppPal=pPal; *ppDatas=pDatas; return(1); } // ----------------------------------------------------------------------------------------------------------------------------------