diff options
Diffstat (limited to 'utils/xbox/toollib/piclib.cpp')
| -rw-r--r-- | utils/xbox/toollib/piclib.cpp | 557 |
1 files changed, 557 insertions, 0 deletions
diff --git a/utils/xbox/toollib/piclib.cpp b/utils/xbox/toollib/piclib.cpp new file mode 100644 index 0000000..fc0101a --- /dev/null +++ b/utils/xbox/toollib/piclib.cpp @@ -0,0 +1,557 @@ +#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); +} + |