khanat-opennel-code/code/nel/tools/3d/tile_edit/PIC/Pic_BMP.cpp
2014-09-24 16:20:25 +02:00

215 lines
4.5 KiB
C++

#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);
}
// ----------------------------------------------------------------------------------------------------------------------------------