source-engine/utils/xbox/toollib/piclib.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

558 lines
13 KiB
C++

#include "toollib.h"
#include "piclib.h"
byte_t* g_tgabuffer;
byte_t* g_tgabuffptr;
/*****************************************************************************
TL_LoadPCX
*****************************************************************************/
void TL_LoadPCX(char* filename, byte_t** pic, byte_t** palette, int* width, int* height)
{
byte_t* raw;
pcx_t* pcx;
int x;
int y;
int len;
int databyte;
int runlength;
byte_t* out;
byte_t* pix;
// load the file
len = TL_LoadFile(filename,(void **)&raw);
// parse the PCX file
pcx = (pcx_t*)raw;
raw = &pcx->data;
pcx->xmin = TL_LittleShort(pcx->xmin);
pcx->ymin = TL_LittleShort(pcx->ymin);
pcx->xmax = TL_LittleShort(pcx->xmax);
pcx->ymax = TL_LittleShort(pcx->ymax);
pcx->hres = TL_LittleShort(pcx->hres);
pcx->vres = TL_LittleShort(pcx->vres);
pcx->bytes_per_line = TL_LittleShort(pcx->bytes_per_line);
pcx->palette_type = TL_LittleShort(pcx->palette_type);
if (pcx->manufacturer != 0x0a ||
pcx->version != 5 ||
pcx->encoding != 1 ||
pcx->bits_per_pixel != 8 ||
pcx->xmax >= 640 ||
pcx->ymax >= 480)
TL_Error("Bad pcx file %s",filename);
if (palette)
{
*palette = (byte_t*)TL_Malloc(768);
memcpy(*palette,(byte_t*)pcx + len - 768,768);
}
if (width)
*width = pcx->xmax+1;
if (height)
*height = pcx->ymax+1;
if (!pic)
return;
out = (byte_t*)TL_Malloc((pcx->ymax+1)*(pcx->xmax+1));
*pic = out;
pix = out;
for (y=0; y<=pcx->ymax; y++, pix += pcx->xmax+1)
{
for (x=0; x<=pcx->xmax; )
{
databyte = *raw++;
if((databyte & 0xC0) == 0xC0)
{
runlength = databyte & 0x3F;
databyte = *raw++;
}
else
runlength = 1;
while (runlength-- > 0)
pix[x++] = databyte;
}
}
if (raw - (byte_t *)pcx > len)
TL_Error("PCX file %s was malformed",filename);
TL_Free(pcx);
}
/*****************************************************************************
TL_SavePCX
*****************************************************************************/
void TL_SavePCX(char* filename, byte_t* data, int width, int height, byte_t* palette)
{
int i;
int j;
int length;
pcx_t* pcx;
byte_t* pack;
pcx = (pcx_t*)TL_Malloc(width*height*2+1000);
pcx->manufacturer = 0x0A; // PCX id
pcx->version = 5; // 256 color
pcx->encoding = 1; // uncompressed
pcx->bits_per_pixel = 8; // 256 color
pcx->xmin = 0;
pcx->ymin = 0;
pcx->xmax = TL_LittleShort((short)(width-1));
pcx->ymax = TL_LittleShort((short)(height-1));
pcx->hres = TL_LittleShort((short)width);
pcx->vres = TL_LittleShort((short)height);
pcx->color_planes = 1; // chunky image
pcx->bytes_per_line = TL_LittleShort((short)width);
pcx->palette_type = TL_LittleShort(2); // not a grey scale
// pack the image
pack = &pcx->data;
for (i=0; i<height; i++)
{
for (j=0; j<width; j++)
{
if ((*data & 0xc0) != 0xC0)
*pack++ = *data++;
else
{
*pack++ = 0xC1;
*pack++ = *data++;
}
}
}
// write the palette
*pack++ = 0x0C;
for (i=0; i<768; i++)
*pack++ = *palette++;
// write output file
length = pack - (byte_t*)pcx;
TL_SaveFile(filename,pcx,length);
TL_Free(pcx);
}
/*****************************************************************************
TGA_GetByte
*****************************************************************************/
byte_t TGA_GetByte(void)
{
return (*g_tgabuffptr++);
}
/*****************************************************************************
TGA_GetShort
*****************************************************************************/
short TGA_GetShort(void)
{
byte_t msb;
byte_t lsb;
lsb = g_tgabuffptr[0];
msb = g_tgabuffptr[1];
g_tgabuffptr += 2;
return ((msb<<8)|lsb);
}
/*****************************************************************************
TL_LoadTGA
*****************************************************************************/
void TL_LoadTGA(char* name, byte_t** pixels, int* width, int* height)
{
int columns;
int rows;
int numPixels;
byte_t* pixbuf;
int row;
int column;
byte_t* targa_rgba;
tga_t targa_header;
byte_t red;
byte_t green;
byte_t blue;
byte_t alphabyte;
byte_t packetHeader;
byte_t packetSize;
byte_t j;
TL_LoadFile(name,(void**)&g_tgabuffer);
g_tgabuffptr = g_tgabuffer;
/* load unaligned tga data */
targa_header.id_length = TGA_GetByte();
targa_header.colormap_type = TGA_GetByte();
targa_header.image_type = TGA_GetByte();
targa_header.colormap_index = TGA_GetShort();
targa_header.colormap_length = TGA_GetShort();
targa_header.colormap_size = TGA_GetByte();
targa_header.x_origin = TGA_GetShort();
targa_header.y_origin = TGA_GetShort();
targa_header.width = TGA_GetShort();
targa_header.height = TGA_GetShort();
targa_header.pixel_size = TGA_GetByte();
targa_header.attributes = TGA_GetByte();
if (targa_header.image_type != 2 && targa_header.image_type != 10)
TL_Error("TL_LoadTGA: %s - Only type 2 and 10 targa RGB images supported",name);
if ((targa_header.colormap_type != 0) || (targa_header.pixel_size != 32 && targa_header.pixel_size != 24))
TL_Error("TL_LoadTGA: %s - Only 32 or 24 bit images supported (no colormaps)",name);
columns = targa_header.width;
rows = targa_header.height;
numPixels = columns * rows;
if (width)
*width = columns;
if (height)
*height = rows;
targa_rgba = (byte_t*)TL_Malloc(numPixels*4);
*pixels = targa_rgba;
if (targa_header.id_length != 0)
{
// skip TARGA image comment
g_tgabuffptr += targa_header.id_length;
}
if (targa_header.image_type==2)
{
// Uncompressed, RGB images
for (row=rows-1; row>=0; row--)
{
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++)
{
switch (targa_header.pixel_size)
{
case 24:
blue = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = 255;
break;
case 32:
blue = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = TGA_GetByte();
break;
}
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
}
}
}
else if (targa_header.image_type==10)
{
// Runlength encoded RGB images
for (row=rows-1; row>=0; row--)
{
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; )
{
packetHeader = TGA_GetByte();
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80)
{
// run-length packet
switch (targa_header.pixel_size)
{
case 24:
blue = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = 255;
break;
case 32:
blue = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = TGA_GetByte();
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 = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = 255;
break;
case 32:
blue = TGA_GetByte();
green = TGA_GetByte();
red = TGA_GetByte();
alphabyte = TGA_GetByte();
break;
}
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
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:;
}
}
TL_Free(g_tgabuffer);
}
/*****************************************************************************
TL_SaveTGA
Saves TGA. Supports r/w 16/24/32 bpp.
*****************************************************************************/
void TL_SaveTGA(char* filename, byte_t* pixels, int width, int height, int sbpp, int tbpp)
{
int handle;
tga_t tga;
unsigned short rgba5551;
unsigned long rgba8888;
int r;
int g;
int b;
int x;
int y;
int a;
byte_t* tgabuffer;
byte_t* tgabufferptr;
byte_t* rawbufferptr;
byte_t* tempbuffer;
byte_t* tempbufferptr;
int bytesperpixel;
// all source is upsampled into easy 32 bit rgba8888
// and downsampled into tga buffer
tempbuffer = (byte_t*)TL_Malloc(width*height*4);
if (sbpp == 16)
{
/* source is 16 bit rgba */
rawbufferptr = pixels;
for (y=0; y<height; y++)
{
tempbufferptr = tempbuffer + y*width*4;
for (x=0; x<width; x++)
{
rgba5551 = *(unsigned short*)rawbufferptr;
r = (rgba5551 & 0xF800)>>11;
g = (rgba5551 & 0x07C0)>>6;
b = (rgba5551 & 0x003E)>>1;
a = (rgba5551 & 0x01);
tempbufferptr[0] = (byte_t)(b * (255.0/31.0));
tempbufferptr[1] = (byte_t)(g * (255.0/31.0));
tempbufferptr[2] = (byte_t)(r * (255.0/31.0));
tempbufferptr[3] = (byte_t)(a * 255.0);
rawbufferptr += sizeof(unsigned short);
tempbufferptr += 4;
}
}
}
else if (sbpp == 24)
{
/* source is 24 bit rgba */
rawbufferptr = pixels;
for (y=0; y<height; y++)
{
tempbufferptr = tempbuffer + y*width*4;
for (x=0; x<width; x++)
{
tempbufferptr[0] = rawbufferptr[0];
tempbufferptr[1] = rawbufferptr[1];
tempbufferptr[2] = rawbufferptr[2];
tempbufferptr[3] = 255;
rawbufferptr += 3;
tempbufferptr += 4;
}
}
}
else if (sbpp == 32)
{
/* source is 32 bit rgba */
memcpy(tempbuffer,pixels,width*height*4);
}
else
TL_Error("TL_SaveTGA: cannot handle source %d bits per pixel",sbpp);
if (tbpp == 16)
bytesperpixel = 2;
else if (tbpp == 24)
bytesperpixel = 3;
else if (tbpp == 32)
bytesperpixel = 4;
else
TL_Error("TL_SaveTGA: cannot handle target %d bits per pixel",tbpp);
handle = TL_SafeOpenWrite(filename);
/* write the targa header */
tga.id_length = 0;
tga.colormap_type = 0;
tga.image_type = 2;
tga.colormap_index = 0;
tga.colormap_length = 0;
tga.colormap_size = 0;
tga.x_origin = 0;
tga.y_origin = 0;
tga.width = width;
tga.height = height;
tga.pixel_size = tbpp;
tga.attributes = 0;
TL_SafeWrite(handle,&tga.id_length,sizeof(tga.id_length));
TL_SafeWrite(handle,&tga.colormap_type,sizeof(tga.colormap_type));
TL_SafeWrite(handle,&tga.image_type,sizeof(tga.image_type));
TL_SafeWrite(handle,&tga.colormap_index,sizeof(tga.colormap_index));
TL_SafeWrite(handle,&tga.colormap_length,sizeof(tga.colormap_length));
TL_SafeWrite(handle,&tga.colormap_size,sizeof(tga.colormap_size));
TL_SafeWrite(handle,&tga.x_origin,sizeof(tga.x_origin));
TL_SafeWrite(handle,&tga.y_origin,sizeof(tga.y_origin));
TL_SafeWrite(handle,&tga.width,sizeof(tga.width));
TL_SafeWrite(handle,&tga.height,sizeof(tga.height));
TL_SafeWrite(handle,&tga.pixel_size,sizeof(tga.pixel_size));
TL_SafeWrite(handle,&tga.attributes,sizeof(tga.attributes));
/* tga images are upside down left to right - !@#$% */
tgabuffer = (byte_t*)TL_Malloc(width*height*bytesperpixel);
/* source is 32 bit rgba */
rawbufferptr = tempbuffer;
for (y=height-1; y>=0; y--)
{
tgabufferptr = tgabuffer + y*width*bytesperpixel;
for (x=0; x<width; x++)
{
switch (bytesperpixel)
{
case 2:
break;
case 3:
rgba8888 = TL_BigLong(*(unsigned long*)rawbufferptr);
r = (rgba8888 & 0xFF000000)>>24;
g = (rgba8888 & 0x00FF0000)>>16;
b = (rgba8888 & 0x0000FF00)>>8;
tgabufferptr[0] = b;
tgabufferptr[1] = g;
tgabufferptr[2] = r;
break;
case 4:
rgba8888 = TL_BigLong(*(unsigned long*)rawbufferptr);
r = (rgba8888 & 0xFF000000)>>24;
g = (rgba8888 & 0x00FF0000)>>16;
b = (rgba8888 & 0x0000FF00)>>8;
a = rgba8888 & 0xFF;
tgabufferptr[0] = b;
tgabufferptr[1] = g;
tgabufferptr[2] = r;
tgabufferptr[3] = a;
break;
}
rawbufferptr += 4;
tgabufferptr += bytesperpixel;
}
}
TL_SafeWrite(handle,tgabuffer,width*height*bytesperpixel);
close(handle);
TL_Free(tempbuffer);
TL_Free(tgabuffer);
}
/*****************************************************************************
TL_LoadImage
Loads an image based on extension.
*****************************************************************************/
void TL_LoadImage(char* name, byte_t** pixels, byte_t** palette, int* width, int* height)
{
char ext[16];
TL_GetExtension(name,ext);
if (!stricmp(ext,"pcx"))
TL_LoadPCX(name,pixels,palette,width,height);
else if (!stricmp(ext,"tga"))
{
TL_LoadTGA(name,pixels,width,height);
*palette = NULL;
}
else
TL_Error("TL_LoadImage: unknown image extension %s",ext);
}