📄 imagelib.c
字号:
LOAD BMP
============================================================================
*/
/*
// we can't just use these structures, because
// compiler structure alignment will not be portable
// on this unaligned stuff
typedef struct tagBITMAPFILEHEADER { // bmfh
WORD bfType; // BM
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{ // bmih
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
typedef struct tagBITMAPINFO { // bmi
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
typedef struct tagBITMAPCOREHEADER { // bmch
DWORD bcSize;
WORD bcWidth;
WORD bcHeight;
WORD bcPlanes;
WORD bcBitCount;
} BITMAPCOREHEADER;
typedef struct _BITMAPCOREINFO { // bmci
BITMAPCOREHEADER bmciHeader;
RGBTRIPLE bmciColors[1];
} BITMAPCOREINFO;
*/
/*
==============
LoadBMP
==============
*/
void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
{
byte *out;
FILE *fin;
int i;
int bfSize;
int bfOffBits;
int structSize;
int bcWidth;
int bcHeight;
int bcPlanes;
int bcBitCount;
byte bcPalette[1024];
qboolean flipped;
fin = fopen (filename, "rb");
if (!fin) {
Error ("Couldn't read %s", filename);
}
i = fgetLittleShort (fin);
if (i != 'B' + ('M'<<8) ) {
Error ("%s is not a bmp file", filename);
}
bfSize = fgetLittleLong (fin);
fgetLittleShort(fin);
fgetLittleShort(fin);
bfOffBits = fgetLittleLong (fin);
// the size will tell us if it is a
// bitmapinfo or a bitmapcore
structSize = fgetLittleLong (fin);
if (structSize == 40) {
// bitmapinfo
bcWidth = fgetLittleLong(fin);
bcHeight= fgetLittleLong(fin);
bcPlanes = fgetLittleShort(fin);
bcBitCount = fgetLittleShort(fin);
fseek (fin, 24, SEEK_CUR);
if (palette) {
fread (bcPalette, 1, 1024, fin);
*palette = malloc(768);
for (i = 0 ; i < 256 ; i++) {
(*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
(*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
(*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
}
}
} else if (structSize == 12) {
// bitmapcore
bcWidth = fgetLittleShort(fin);
bcHeight= fgetLittleShort(fin);
bcPlanes = fgetLittleShort(fin);
bcBitCount = fgetLittleShort(fin);
if (palette) {
fread (bcPalette, 1, 768, fin);
*palette = malloc(768);
for (i = 0 ; i < 256 ; i++) {
(*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
(*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
(*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
}
}
} else {
Error ("%s had strange struct size", filename);
}
if (bcPlanes != 1) {
Error ("%s was not a single plane image", filename);
}
if (bcBitCount != 8) {
Error ("%s was not an 8 bit image", filename);
}
if (bcHeight < 0) {
bcHeight = -bcHeight;
flipped = qtrue;
} else {
flipped = qfalse;
}
if (width)
*width = bcWidth;
if (height)
*height = bcHeight;
if (!pic) {
fclose (fin);
return;
}
out = malloc ( bcWidth * bcHeight );
*pic = out;
fseek (fin, bfOffBits, SEEK_SET);
if (flipped) {
for (i = 0 ; i < bcHeight ; i++) {
fread (out + bcWidth * (bcHeight - 1 - i), 1, bcWidth, fin);
}
} else {
fread (out, 1, bcWidth*bcHeight, fin);
}
fclose (fin);
}
/*
============================================================================
LOAD IMAGE
============================================================================
*/
/*
==============
Load256Image
Will load either an lbm or pcx, depending on extension.
Any of the return pointers can be NULL if you don't want them.
==============
*/
void Load256Image (const char *name, byte **pixels, byte **palette,
int *width, int *height)
{
char ext[128];
ExtractFileExtension (name, ext);
if (!Q_stricmp (ext, "lbm"))
{
LoadLBM (name, pixels, palette);
if (width)
*width = bmhd.w;
if (height)
*height = bmhd.h;
}
else if (!Q_stricmp (ext, "pcx"))
{
LoadPCX (name, pixels, palette, width, height);
}
else if (!Q_stricmp (ext, "bmp"))
{
LoadBMP (name, pixels, palette, width, height);
}
else
Error ("%s doesn't have a known image extension", name);
}
/*
==============
Save256Image
Will save either an lbm or pcx, depending on extension.
==============
*/
void Save256Image (const char *name, byte *pixels, byte *palette,
int width, int height)
{
char ext[128];
ExtractFileExtension (name, ext);
if (!Q_stricmp (ext, "lbm"))
{
WriteLBMfile (name, pixels, width, height, palette);
}
else if (!Q_stricmp (ext, "pcx"))
{
WritePCXfile (name, pixels, width, height, palette);
}
else
Error ("%s doesn't have a known image extension", name);
}
/*
============================================================================
TARGA IMAGE
============================================================================
*/
typedef struct _TargaHeader {
unsigned char id_length, colormap_type, image_type;
unsigned short colormap_index, colormap_length;
unsigned char colormap_size;
unsigned short x_origin, y_origin, width, height;
unsigned char pixel_size, attributes;
} TargaHeader;
/*
=============
LoadTGABuffer
=============
*/
void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
byte *buf_p;
TargaHeader targa_header;
byte *targa_rgba;
*pic = NULL;
buf_p = buffer;
targa_header.id_length = *buf_p++;
targa_header.colormap_type = *buf_p++;
targa_header.image_type = *buf_p++;
targa_header.colormap_index = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.colormap_length = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.colormap_size = *buf_p++;
targa_header.x_origin = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.y_origin = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.width = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.height = LittleShort ( *(short *)buf_p );
buf_p += 2;
targa_header.pixel_size = *buf_p++;
targa_header.attributes = *buf_p++;
if (targa_header.image_type!=2
&& targa_header.image_type!=10
&& targa_header.image_type != 3 )
{
Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
}
if ( targa_header.colormap_type != 0 )
{
Error("LoadTGA: colormaps not supported\n" );
}
if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
{
Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
}
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
if (width)
*width = columns;
if (height)
*height = rows;
targa_rgba = malloc (numPixels*4);
*pic = targa_rgba;
if (targa_header.id_length != 0)
buf_p += targa_header.id_length; // skip TARGA image comment
if ( targa_header.image_type==2 || targa_header.image_type == 3 )
{
// Uncompressed RGB or gray scale image
for(row=rows-1; row>=0; row--)
{
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++)
{
unsigned char red,green,blue,alphabyte;
switch (targa_header.pixel_size)
{
case 8:
blue = *buf_p++;
green = blue;
red = blue;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
default:
//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
red = 0;
green = 0;
blue = 0;
alphabyte = 0xff;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader= *buf_p++;
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
break;
default:
//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
break;
}
for(j=0;j<packetSize;j++) {
*pixbuf++=red;
*pixbuf++=green;
*pixbuf++=blue;
*pixbuf++=alphabyte;
column++;
if (column==columns) { // run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
else { // non run-length packet
for(j=0;j<packetSize;j++) {
switch (targa_header.pixel_size) {
case 24:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = *buf_p++;
green = *buf_p++;
red = *buf_p++;
alphabyte = *buf_p++;
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
default:
//Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
break;
}
column++;
if (column==columns) { // pixel packet run spans across rows
column=0;
if (row>0)
row--;
else
goto breakOut;
pixbuf = targa_rgba + row*columns*4;
}
}
}
}
breakOut:;
}
}
//free(buffer);
}
/*
=============
LoadTGA
=============
*/
void LoadTGA (const char *name, byte **pixels, int *width, int *height)
{
byte *buffer;
int nLen;
//
// load the file
//
nLen = LoadFile ( ( char * ) name, (void **)&buffer);
if (nLen == -1)
{
Error ("Couldn't read %s", name);
}
LoadTGABuffer(buffer, pixels, width, height);
}
/*
================
WriteTGA
================
*/
void WriteTGA (const char *filename, byte *data, int width, int height) {
byte *buffer;
int i;
int c;
FILE *f;
buffer = malloc(width*height*4 + 18);
memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = width&255;
buffer[13] = width>>8;
buffer[14] = height&255;
buffer[15] = height>>8;
buffer[16] = 32; // pixel size
// swap rgb to bgr
c = 18 + width * height * 4;
for (i=18 ; i<c ; i+=4)
{
buffer[i] = data[i-18+2]; // blue
buffer[i+1] = data[i-18+1]; // green
buffer[i+2] = data[i-18+0]; // red
buffer[i+3] = data[i-18+3]; // alpha
}
f = fopen (filename, "wb");
fwrite (buffer, 1, c, f);
fclose (f);
free (buffer);
}
/*
============================================================================
LOAD32BITIMAGE
============================================================================
*/
/*
==============
Load32BitImage
Any of the return pointers can be NULL if you don't want them.
==============
*/
void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height)
{
char ext[128];
byte *palette;
byte *pixels8;
byte *pixels32;
int size;
int i;
int v;
ExtractFileExtension (name, ext);
if (!Q_stricmp (ext, "tga")) {
LoadTGA (name, (byte **)pixels, width, height);
} else {
Load256Image (name, &pixels8, &palette, width, height);
if (!pixels) {
return;
}
size = *width * *height;
pixels32 = malloc(size * 4);
*pixels = (unsigned *)pixels32;
for (i = 0 ; i < size ; i++) {
v = pixels8[i];
pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
pixels32[i*4 + 3] = 0xff;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -