woof/toolsrc/bmp2c.c
Fabian Greffrath f70d372907
fix all cppcheck 2.9 warnings (#771)
* fix most cppcheck 2.9 warnings

* simplify matters

* simplify a bit more

* simplify

* more/better fixes

* whitespace cosmetic

* use I_Realloc() in u_mapinfo.c
2022-11-23 07:51:01 +01:00

300 lines
7.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h> // [FG] tolower()
#include "doomtype.h"
#define XPARENT (0xf7) /* palette index representing transparent in BMP */
typedef struct stPicData
{
short pwid;
short phgt;
short pxoff;
short pyoff;
long *coloffs;
unsigned char *posts;
long postlen;
} PicData;
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
typedef unsigned short UINT;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned char BYTE;
typedef unsigned char UBYTE;
#if defined(_MSC_VER)
#pragma pack(push, 1)
#endif
typedef PACKED_PREFIX struct tagBITMAPFILEHEADER
{
UINT bfType; // 2
DWORD bfSize; // 4
UINT bfReserved1; // 2
UINT bfReserved2; // 2
DWORD bfOffBits; // 4
} PACKED_SUFFIX BITMAPFILEHEADER; // 14
typedef PACKED_PREFIX struct tagBITMAPINFOHEADER
{
DWORD biSize; // 4
LONG biWidth; // 4
LONG biHeight; // 4
WORD biPlanes; // 2
WORD biBitCount; // 2
DWORD biCompression; // 4
DWORD biSizeImage; // 4
LONG biXPelsPerMeter; // 4
LONG biYPelsPerMeter; // 4
DWORD biClrUsed; // 4
DWORD biClrImportant; // 4
} PACKED_SUFFIX BITMAPINFOHEADER; // 40
typedef PACKED_PREFIX struct tagRGBQUAD
{
UBYTE rgbBlue;
UBYTE rgbGreen;
UBYTE rgbRed;
UBYTE rgbReserved;
} PACKED_SUFFIX RGBQUAD;
#if defined(_MSC_VER)
#pragma pack(pop)
#endif
// Convert a rectangular array of numbers to a DOOM format picture
// bytes 0-255 represent palette colors as usual, XPARENT is transparency.
//
// memory is allocated on p->coloffs and p->posts
// max: 256k+rwid actual: postlen+4*(1+rwid)
void ConvertToPicture(BYTE *bytes,int logw,int rwid,int logh,PicData *p,int pf)
{
int i,j,n;
int pixcnt;
int postlen;
p->pwid = rwid;
p->phgt = logh;
p->pxoff = pf? rwid/2 - 1 : 0;
p->pyoff = pf? logh - 5 : 0;
p->coloffs = (long *)malloc(logw*sizeof(int));
p->posts = (unsigned char *)malloc(1024*256*sizeof(unsigned char));
n=postlen=0;
for (j=0;j<rwid;j++) // do each column
{
p->coloffs[j] = 4*sizeof(short) + p->pwid*sizeof(int) + postlen;
pixcnt = 0;
for (i=0;i<logh;i++)
{
if (bytes[logw*i+j]==XPARENT)
{
if (pixcnt>0)
{
p->posts[postlen++]=0; // add fill byte at end
pixcnt=0;
}
}
else
{
if (pixcnt==0) // start a post
{
p->posts[postlen++] = i;
n = postlen++;
p->posts[n] = 1;
p->posts[postlen++] = 0; // add fill byte at start
}
else p->posts[n]++;
// add pixel to current post
p->posts[postlen++] = bytes[logw*i+j];
pixcnt++;
}
}
if (pixcnt>0) // terminate last post
p->posts[postlen++]=0;
p->posts[postlen++]=255; // terminate column
}
p->posts = (unsigned char *)realloc(p->posts,postlen);
p->postlen = postlen;
}
// Reads BMP file
// Header is read for real width, and logical height
// Logical width is next multiple of 4 greater than or equal to real width
// Bitmap is written to short array *out, allocated to fit
// *out is allocated and read as logical width by logical height
//
// memory is allocated on *out
// max: logw*logh*sizeof(short)
void ReadBMP(BYTE **out,int *logw,int *realw,int *logh,char *bmpname)
{
int i,n;
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
FILE *st;
char *buffer=NULL;
RGBQUAD pal[256];
*logw = *logh = *realw = 0;
st = fopen(bmpname,"rb");
if (st!=NULL)
{
#define fread2(a,b,c,d) if(!fread(a,b,c,d)){fprintf(stderr,"ERROR: invalid bitmap file %s\n",bmpname);fclose(st);if(buffer)free(buffer);return;}
fread2(&bmfh.bfType,sizeof(bmfh.bfType),1,st);
fread2(&bmfh.bfSize,sizeof(bmfh.bfSize),1,st);
fread2(&bmfh.bfReserved1,sizeof(bmfh.bfReserved1),1,st);
fread2(&bmfh.bfReserved2,sizeof(bmfh.bfReserved2),1,st);
fread2(&bmfh.bfOffBits,sizeof(bmfh.bfOffBits),1,st);
fread2(&bmih.biSize,sizeof(bmih.biSize),1,st);
fread2(&bmih.biWidth,sizeof(bmih.biWidth),1,st);
fread2(&bmih.biHeight,sizeof(bmih.biHeight),1,st);
fread2(&bmih.biPlanes,sizeof(bmih.biPlanes),1,st);
fread2(&bmih.biBitCount,sizeof(bmih.biBitCount),1,st);
fread2(&bmih.biCompression,sizeof(bmih.biCompression),1,st);
fread2(&bmih.biSizeImage,sizeof(bmih.biSizeImage),1,st);
fread2(&bmih.biXPelsPerMeter,sizeof(bmih.biXPelsPerMeter),1,st);
fread2(&bmih.biYPelsPerMeter,sizeof(bmih.biYPelsPerMeter),1,st);
fread2(&bmih.biClrUsed,sizeof(bmih.biClrUsed),1,st);
fread2(&bmih.biClrImportant,sizeof(bmih.biClrImportant),1,st);
fread2(pal,sizeof(RGBQUAD),256,st);
*realw = bmih.biWidth;
*logw = 4*((bmih.biWidth+3)/4);
*logh = bmih.biHeight;
n = (*logw)*(*logh);
buffer = malloc(n);
fseek(st,bmfh.bfOffBits,SEEK_SET);
fread2(buffer,n,1,st);
*out = (BYTE *)malloc(n);
for (i=(*logh)-1;i>=0;i--)
memmove((*out)+((*logh)-1-i)*(*logw),buffer+(*logw)*i,*logw);
fclose(st);
free(buffer);
}
else fprintf(stderr,"ERROR: bitmap file %s not found\n",bmpname);
}
// Read a .BMP file and embed in a wad as a DOOM picture
// memory balanced except directory extension
void WritePic(char *path,FILE *st,int pf)
{
int n,t;
BYTE *out = NULL;
int logw=0,logh=0,rwid=0;
PicData pic;
char name[256],*p;
BYTE *q;
if (path && *path)
{
ReadBMP(&out,&logw,&rwid,&logh,path); // allocs out
if (logw>0)
{
ConvertToPicture(out,logw,rwid,logh,&pic,pf);
strcpy(name,path[1]==':'? path+2 : path); // strip drive, if any
p = strrchr(name,'\\'); // strip dirs, if any
if (p) strcpy(name,p+1);
p = strrchr(name,'.'); // strip ext, if any
if (p) *p='\0';
// code to write pic as C data here
fprintf(st,"static const char %s[]=\n{\n\t",name);
q = (BYTE *)&pic.pwid;
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,",*q++);
fprintf(st,"%3d,\n\t",*q++);
q = (BYTE *)pic.coloffs;
t = pic.pwid*sizeof(long);
for (n=0;n<t;n++)
{
fprintf(st,"%3d,",*q++);
if ((n&15)==15)
fprintf(st,"\n\t");
}
q = pic.posts;
for (;n<pic.postlen+t;n++)
{
fprintf(st,"%3d,",*q++);
if (n==t+pic.postlen-1)
fprintf(st,"\n};\n\n");
else if ((n&15)==15)
fprintf(st,"\n\t");
}
free(pic.coloffs);
free(pic.posts);
}
else
{
fprintf(stderr,"ERROR: Can't open file: %s\n",path);
}
free(out);
}
}
// write all .BMP files specified as input (possibly wildcarded)
// as a collection of C arrays
int main(int argc,char **argv)
{
int i;
char name[256];
FILE *st;
int pf;
if (argc<2)
{
printf("Usage: BMP2C [/p] name1.bmp...\n");
printf("name may contain wildcards\n");
printf("/p will insert patch style offsets, else 0\n");
exit(1);
}
st = fopen("cdata.c","w");
if (st)
{
pf = 0;
if (argv[1][0] == '-' || (argv[1][0]=='/' && tolower(argv[1][1])=='p'))
pf = 1;
for (i=1+pf;i<argc;i++)
{
strcpy(name,argv[i]);
WritePic(name,st,pf);
}
fclose(st);
}
else
fprintf(stderr,"Cannot open CDATA.C for output\n");
return 0;
}