/* * $Logfile: /DescentIII/Main/bitmap/pcx.cpp $ * $Revision: 8 $ * $Date: 3/30/99 12:36a $ * $Author: Jeff $ * * Code to read PCX files * * $Log: /DescentIII/Main/bitmap/pcx.cpp $ * * 8 3/30/99 12:36a Jeff * added support for 24bit pcx's * * 7 2/16/99 5:50p Jason * made pcx stuff only work with 8 bit files * * 6 10/20/98 1:41a Jeff * fixed a mem_malloc/free bug * * 5 10/08/98 4:23p Kevin * Changed code to comply with memory library usage. Always use mem_malloc * , mem_free and mem_strdup * * 4 4/23/98 6:38p Jason * made bitmaps use 1555 format * * 3 12/22/97 7:34p Samir * Removed instances of gr.h include. Replaced with grdefs.h * * 2 10/15/97 5:20p Jason * did a HUGE overhaul of the bitmap system * * 4 3/03/97 6:20p Matt * Changed cfile functions to use D3 naming convention * * $NoKeywords: $ */ #include "mem.h" #include "bitmap.h" #include "pserror.h" #include "pstypes.h" #include "grdefs.h" #include // load an 8bit pcx image int bm_pcx_8bit_alloc_file(CFILE *infile); // load a 24bit pcx image int bm_pcx_24bit_alloc_file(CFILE *infile); // Loads a pcx file and converts it to 16 bit. Returns bitmap handle or -1 on error int bm_pcx_alloc_file(CFILE *infile) { ubyte temp[128]; cf_ReadBytes(temp, 128, infile); cfseek(infile, 0, SEEK_SET); switch (temp[65]) { case 1: // one plane, sounds like an 8bit pcx return bm_pcx_8bit_alloc_file(infile); break; case 3: // three planes, sounds like a 24bit pcx return bm_pcx_24bit_alloc_file(infile); break; } return -1; // Must be 8 bit only } // load an 8bit pcx image int bm_pcx_8bit_alloc_file(CFILE *infile) { int xmin, ymin, xmax, ymax; int width, height; int total, run = 0; int i, t; int src_bm; ubyte pred[256], pgreen[256], pblue[256]; ubyte buf; ubyte temp[128]; cf_ReadBytes(temp, 4, infile); if (temp[3] != 8) return -1; // nope...bail xmin = cf_ReadShort(infile); ymin = cf_ReadShort(infile); xmax = cf_ReadShort(infile); ymax = cf_ReadShort(infile); cf_ReadBytes(temp, 116, infile); if (temp[65 - 12] != 1) return -1; // Must be 8 bit only width = 1 + xmax - xmin; height = 1 + ymax - ymin; total = width * height; ubyte *rawdata = (ubyte *)mem_malloc(width * height); if (!rawdata) return -1; // no memory! run = 0; while (run < total) { buf = cf_ReadByte(infile); if (buf >= 192) { ubyte tb; tb = cf_ReadByte(infile); for (i = 0; i < (buf - 192); i++, run++) rawdata[run] = tb; } else { rawdata[run] = buf; run++; } } cf_ReadByte(infile); // ignore pad // Read palette for (i = 0; i < 256; i++) { pred[i] = cf_ReadByte(infile); pgreen[i] = cf_ReadByte(infile); pblue[i] = cf_ReadByte(infile); pred[i] >>= 3; pgreen[i] >>= 3; pblue[i] >>= 3; } src_bm = bm_AllocBitmap(width, height, 0); if (src_bm < 0) return -1; // probably out of memory ushort *data = bm_data(src_bm, 0); for (i = 0; i < height; i++) { for (t = 0; t < width; t++) { ushort pixel; ubyte c = rawdata[i * width + t]; int r = pred[c]; int g = pgreen[c]; int b = pblue[c]; pixel = OPAQUE_FLAG | (r << 10) | (g << 5) | b; if (c == 0) pixel = NEW_TRANSPARENT_COLOR; data[i * width + t] = pixel; } } mem_free(rawdata); return src_bm; // success! } // load a 24bit pcx image int bm_pcx_24bit_alloc_file(CFILE *infile) { int xmin, ymin, xmax, ymax; int width, height; int total, run = 0; int i, t; int src_bm; ubyte buf; ubyte temp[128]; cf_ReadBytes(temp, 4, infile); if (temp[1] < 5) { // need at least version 5.0f mprintf((0, "PCXLoad: PCX Not version 5.0 or greater\n")); return -1; } if (temp[3] != 8) { // need 8 bits per pixel mprintf((0, "PCXLoad: PCX Not 8 bpp\n")); return -1; // nope...bail } xmin = cf_ReadShort(infile); ymin = cf_ReadShort(infile); xmax = cf_ReadShort(infile); ymax = cf_ReadShort(infile); cf_ReadBytes(temp, 116, infile); #define PCXHEADER_OFFSET 12 if (temp[65 - PCXHEADER_OFFSET] != 3) { // Must have 3 planes mprintf((0, "PCXLoad: PCX Not 3 Planes for 24bit encoding\n")); return -1; } width = 1 + xmax - xmin; height = 1 + ymax - ymin; // Determine BytesPerLine cfseek(infile, 66, SEEK_SET); int BytesPerLine = cf_ReadShort(infile); cfseek(infile, 128, SEEK_SET); // scanline length total = 3 * BytesPerLine; ubyte *rawdata = (ubyte *)mem_malloc(total * height); if (!rawdata) { mprintf((0, "PCXLoad: Out of memory\n")); return -1; // no memory! } // Load in the data // the data is divided into scanlines // the first scanline is line 0's red // the second scanline is line 0's green // the third scanline is line 0's blue // the fourth scanline is line 1's red // etc. int data_index = 0; for (int line = 0; line < height; line++) { // Read red scanline run = 0; while (run < BytesPerLine) { buf = cf_ReadByte(infile); if (buf >= 192) { ubyte tb; tb = cf_ReadByte(infile); for (i = 0; i < (buf - 192); i++, run++, data_index++) rawdata[data_index] = tb; } else { rawdata[data_index] = buf; run++; data_index++; } } // Read green scanline run = 0; while (run < BytesPerLine) { buf = cf_ReadByte(infile); if (buf >= 192) { ubyte tb; tb = cf_ReadByte(infile); for (i = 0; i < (buf - 192); i++, run++, data_index++) rawdata[data_index] = tb; } else { rawdata[data_index] = buf; run++; data_index++; } } // Read blue scanline run = 0; while (run < BytesPerLine) { buf = cf_ReadByte(infile); if (buf >= 192) { ubyte tb; tb = cf_ReadByte(infile); for (i = 0; i < (buf - 192); i++, run++, data_index++) rawdata[data_index] = tb; } else { rawdata[data_index] = buf; run++; data_index++; } } } src_bm = bm_AllocBitmap(width, height, 0); if (src_bm < 0) return -1; // probably out of memory ushort *data = bm_data(src_bm, 0); for (i = 0; i < height; i++) { for (t = 0; t < width; t++) { int r, g, b; ushort pixel; r = rawdata[(i * total) + (0 * BytesPerLine) + t]; g = rawdata[(i * total) + (1 * BytesPerLine) + t]; b = rawdata[(i * total) + (2 * BytesPerLine) + t]; pixel = OPAQUE_FLAG | GR_RGB16(r, g, b); data[i * width + t] = pixel; } } mem_free(rawdata); return src_bm; // success! }