#include #include #include "d3_image.hpp" #include "platform.h" // define = 1 if you dont have pre-quantized images to load into palettized D3D texture surfaces #define QUANTISE_ON_LOAD 0 #if debug #define DEBUG_TRANSPARENCY 1 #else #define DEBUG_TRANSPARENCY 0 #endif // image loader stuff #if OUTPUT_LOG #include "debuglog.hpp" LogFile CL_LogFile("DB_IMLD.LOG"); #endif #if TIME_LOADS unsigned int OpenTime; unsigned int CloseTime; unsigned int ReadTime; #endif static inline unsigned long read_le_dword(D3I_FILE * f) { unsigned char d1,d2,d3,d4; d3i_fread(&d1,1,1,f); d3i_fread(&d2,1,1,f); d3i_fread(&d3,1,1,f); d3i_fread(&d4,1,1,f); return (unsigned long)d1 | (unsigned long)d2<<8 | (unsigned long)d3<<16 | (unsigned long)d4<<24; } static inline unsigned short read_le_word(D3I_FILE * f) { unsigned char d1,d2; d3i_fread(&d1,1,1,f); d3i_fread(&d2,1,1,f); return (unsigned short)d1 | (unsigned short)((unsigned short)d2<<8); } // some default globals CL_ImageMode CL_Image::imode = CLM_GLOBALPALETTE; CL_ImageMode CL_Image::imode_d3d = CLM_ATTACHEDPALETTE; CL_ImageMode CL_Image::imode_ddraw = CLM_GLOBALPALETTE; LPDDSURFACEDESC CL_Image::format = 0; unsigned int CL_Image::bitsperpixel; unsigned int CL_Image::bitsperpixel_d3d; unsigned int CL_Image::bitsperpixel_ddraw; CL_LoadMode CL_Image::lmode = CLL_DDSURFACE; CL_DX_Format CL_Pixel_32::f; CL_DX_Format CL_Pixel_32::f_d3d; CL_DX_Format CL_Pixel_32::f_ddraw; CL_DX_Format CL_Pixel_16::f; CL_DX_Format CL_Pixel_16::f_d3d; CL_DX_Format CL_Pixel_16::f_ddraw; void CL_Image::DeleteNotMips(void) { if (im24) { delete[] *im24; delete[] im24; im24 = 0; } if (im16) { delete[] *im16; delete[] im16; im16 = 0; } if (im8) { delete[] *im8; delete[] im8; im8 = 0; } if (palette) { delete[] palette; palette = 0; palette_size = 0; } flags.loaded = 0; flags.raw16bit = 0; } void CL_Image::Delete(void) { DeleteNotMips(); while (mipmaps.size()) { delete mipmaps.last_entry(); mipmaps.delete_last_entry(); } } void CL_Image::Copy(CL_Image const & i2) { if (i2.im24) { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; CL_Pixel_24 const * sptr = *i2.im24; CL_Pixel_24 * dptr = *im24; for (int i=size; i; --i) { *dptr++ = *sptr++; } CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 const * aptr = *im24; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } if (i2.im16) { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 const * sptr = *i2.im16; CL_Pixel_16 * dptr = *im16; for (int i=size; i; --i) { *dptr++ = *sptr++; } CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } if (i2.im8) { im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; unsigned char const * sptr = *i2.im8; unsigned char * dptr = *im8; for (int i=size; i; --i) { *dptr++ = *sptr++; } unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char const * aptr = *im8; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } if (i2.palette) { palette = new CL_Pixel_24 [palette_size]; CL_Pixel_24 const * sptr = i2.palette; CL_Pixel_24 * dptr = palette; for (int i=palette_size; i; --i) { *dptr++ = *sptr; } } if (i2.name) { name = new char [strlen(i2.name)+1]; strcpy(name,i2.name); } if (i2.fname) { fname = new char [strlen(i2.fname)+1]; strcpy(fname,i2.fname); } for (CLIF i_mip(&i2.mipmaps); !i_mip.done(); i_mip.next()) { mipmaps.add_entry_end(new CL_Image(*i_mip())); } } CL_Image::~CL_Image() { Delete(); if (fname) delete[] fname; if (name) delete[] name; } CL_Image::CL_Image(CL_Image const & i2) : width(i2.width) , height(i2.height) , size(i2.size) , im24(0) , im16(0) , im8(0) , palette(0) , palette_size(i2.palette_size) , fname(0) , name(0) , flags(i2.flags) { Copy(i2); } CL_Image & CL_Image::operator = (CL_Image const & i2) { if (&i2 != this) { Delete(); if (fname) delete[] fname; if (name) delete[] name; width = i2.width; height = i2.height; size = i2.size; palette_size = i2.palette_size; fname = 0; name = 0; flags = i2.flags; Copy(i2); } return *this; } CL_Error CL_Image::Make(int const _width, int const _height) { Delete(); width = _width; height = _height; palette_size = 0; size = width*height; switch (imode) { case CLM_ATTACHEDPALETTE: { palette_size = 256; palette = new CL_Pixel_24 [palette_size]; } case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: { im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char * dptr = *im8; for (int i=height; i; --i, dptr+=width) { *dptrptr++ = dptr; } break; } case CLM_24BIT: { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 const * aptr = *im24; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } break; } case CLM_16BIT: { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } break; } case CLM_32BIT: { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 const * aptr = *im32; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } break; } default: return CLE_INVALIDDXMODE; } flags.loaded = 1; return CLE_OK; } CL_Error CL_Image::MakeRandom(int const _width, int const _height, int const seed) { Delete(); if (-1!=seed) srand((unsigned int)seed); width = _width; height = _height; size = width*height; palette_size = 0; switch (imode) { case CLM_ATTACHEDPALETTE: { palette_size = 256; palette = new CL_Pixel_24 [palette_size]; CL_Pixel_24 * palP = palette; for (int i=palette_size; i; --i, ++palP) { *palP = CL_Pixel_24(rand()&255,rand()&255,rand()&255); } } case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: { im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char * dptr = *im8; for (int i=height; i; --i) { *dptrptr++ = dptr; for (int j=width; j; --j, ++dptr) *dptr = (unsigned char)(rand()&(palette_size-1)); } break; } case CLM_24BIT: { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 * aptr = *im24; for (int i=height; i; --i) { *dptrptr++ = aptr; for (int j=width; j; --j, ++aptr) *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255); } break; } case CLM_16BIT: { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 * aptr = *im16; for (int i=height; i; --i) { *dptrptr++ = aptr; for (int j=width; j; --j, ++aptr) *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255); } break; } case CLM_32BIT: { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 * aptr = *im32; for (int i=height; i; --i) { *dptrptr++ = aptr; for (int j=width; j; --j, ++aptr) *aptr = CL_Pixel_24(rand()&255,rand()&255,rand()&255); } break; } default: return CLE_INVALIDDXMODE; } flags.loaded = 1; return CLE_OK; } CL_Error CL_Image::Load_BMP(D3I_FILE * f) { if (!f) return CLE_OPENERROR; DeleteNotMips(); switch (imode) { case CLM_ATTACHEDPALETTE: case CLM_24BIT: case CLM_16BIT: case CLM_32BIT: break; default: return CLE_INVALIDDXMODE; } d3i_fseek(f,0,SEEK_SET); unsigned short magic; d3i_fread(&magic,2,1,f); if (magic != *(unsigned short const *)"BM") return CLE_LOADERROR; size_t filesize = read_le_dword(f); d3i_fseek(f,4,SEEK_CUR); size_t offset = read_le_dword(f); size_t headsize = read_le_dword(f); unsigned short bitdepth; if (12 == headsize) // OS/2 1.x { width = read_le_word(f); height = read_le_word(f); size = width * height; if (!width || !height) return CLE_LOADERROR; unsigned short planes = read_le_word(f); if (1 != planes) return CLE_LOADERROR; bitdepth = read_le_word(f); if (bitdepth != 24) { palette_size = 1<Read(f,CLF_BGR); } } } else if (40 == headsize || 64 == headsize) // Windows 3.x || OS/2 2.x { width = read_le_dword(f); height = read_le_dword(f); unsigned short planes = read_le_word(f); if (1 != planes) return CLE_LOADERROR; bitdepth = read_le_word(f); if (read_le_dword(f)) return CLE_LOADERROR; // compressed bmps not supported size = read_le_dword(f); d3i_fseek(f,8,SEEK_CUR); palette_size = read_le_dword(f); if (!palette_size && bitdepth != 24) palette_size = 1<Read(f,CLF_BGRX); } } } else return CLE_LOADERROR; d3i_fseek(f,offset,SEEK_SET); if (palette_size) { if (bitdepth < 4) { delete[] palette; palette_size = 0; return CLE_LOADERROR; } im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char * dptr = *im8; for (int i=height; i; --i, dptr+=width) { *dptrptr++ = dptr; } #if DEBUG_TRANSPARENCY int num_tps=0; #endif for (i=height-1; i>=0; --i) { dptr = im8[i]; if (4==bitdepth) { for (int i=width>>1; i; --i) { unsigned char byte; d3i_fread(&byte,1,1,f); #if DEBUG_TRANSPARENCY *dptr = (unsigned char)(byte >> 4 & 0xf); if (!*dptr) num_tps++; *++dptr = (unsigned char)(byte & 0xf); if (!*dptr) num_tps++; ++dptr; #else *dptr++ = (unsigned char)(byte >> 4 & 0xf); *dptr++ = (unsigned char)(byte & 0xf); #endif } if (width & 1) { d3i_fread(dptr,1,1,f); *dptr &= 0xf; #if DEBUG_TRANSPARENCY if (!*dptr) num_tps++; #endif } d3i_fseek(f,(~(width-1) & 7)>>1,SEEK_CUR); } else { for (int i=width; i; --i) { #if DEBUG_TRANSPARENCY d3i_fread(dptr,1,1,f); if (!*dptr) num_tps++; dptr++; #else d3i_fread(dptr++,1,1,f); #endif } d3i_fseek(f,~(width-1) & 3,SEEK_CUR); } } #if DEBUG_TRANSPARENCY if (num_tps) CL_LogFile.lprintf("-- %d TRANSPARENT PIXELS FOUND\n",num_tps); #endif } else if (CLM_16BIT == imode) { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (i=height-1; i>=0; --i) { CL_Pixel_16 * dptr = im16[i]; for (int i=width; i; --i) { dptr++->Read(f,CLF_BGR); } d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR); } } else if (CLM_32BIT == imode) { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 const * aptr = *im32; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (i=height-1; i>=0; --i) { CL_Pixel_32 * dptr = im32[i]; for (int i=width; i; --i) { dptr++->Read(f,CLF_BGR); } d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR); } } else if (CLM_24BIT == imode) { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 const * aptr = *im24; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (i=height-1; i>=0; --i) { CL_Pixel_24 * dptr = im24[i]; for (int i=width; i; --i) { dptr++->Read(f,CLF_BGR); } d3i_fseek(f,~(width*3-1) & 3,SEEK_CUR); } } else return CLE_INVALIDDXMODE; if (palette_size && CLM_ATTACHEDPALETTE != imode) { if (CLM_16BIT == imode) { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; unsigned char const * sptr = *im8; CL_Pixel_16 * dptr = *im16; for (int i=size; i; --i, ++dptr,++sptr) { if (*sptr && !palette[*sptr]) *dptr = dptr->f.dx_black; else *dptr = palette[*sptr]; } CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } else if (CLM_32BIT == imode) { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; unsigned char const * sptr = *im8; CL_Pixel_32 * dptr = *im32; for (int i=size; i; --i, ++dptr,++sptr) { if (*sptr && !palette[*sptr]) *dptr = dptr->f.dx_black; else *dptr = palette[*sptr]; } CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 const * aptr = *im32; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } else { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; unsigned char const * sptr = *im8; CL_Pixel_24 * dptr = *im24; for (int i=size; i; --i, ++dptr,++sptr) { if (*sptr && !palette[*sptr]) *dptr = CL_Pixel_24(0,1,0); else *dptr = palette[*sptr]; } CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 const * aptr = *im24; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } delete[] palette; palette = 0; palette_size = 0; delete[] *im8; delete[] im8; im8 = 0; } if (d3i_ferror(f) || d3i_feof(f)) { DeleteNotMips(); return CLE_LOADERROR; } flags.loaded = 1; return CLE_OK; } CL_Error CL_Image::Load_PPM(D3I_FILE * f) { if (!f) return CLE_OPENERROR; DeleteNotMips(); switch (imode) { case CLM_24BIT: case CLM_16BIT: case CLM_32BIT: break; default: return CLE_INVALIDDXMODE; } d3i_fseek(f,0,SEEK_SET); unsigned short magic; d3i_fread(&magic,2,1,f); if (magic != *(unsigned short const *)"P6") return CLE_LOADERROR; d3i_fseek(f,1,SEEK_CUR); char buf[256]; char * bufptr = buf; unsigned int fields[5]; unsigned int fields_read = 0; while (fields_read < 3 && bufptr) { do bufptr = d3i_fgets(buf, sizeof buf, f); while ('#'==buf[0] && bufptr); int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]); if (EOF != num_fields_read) fields_read += num_fields_read; } if (fields_read < 3) return CLE_LOADERROR; width = fields[0]; height = fields[1]; unsigned int maxval = fields[2]; if (maxval > 255) return CLE_LOADERROR; size = width * height; if (CLM_16BIT == imode) { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 * rptr = *im16; for (int i=size; i; --i) { rptr++->Read(f,CLF_RGB,maxval); } CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } else if (CLM_32BIT == imode) { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; CL_Pixel_32 * rptr = *im32; for (int i=size; i; --i) { rptr++->Read(f,CLF_RGB,maxval); } CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 const * aptr = *im32; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } else { im24 = new CL_Pixel_24 * [height]; *im24 = new CL_Pixel_24 [size]; CL_Pixel_24 * rptr = *im24; for (int i=size; i; --i) { rptr++->Read(f,CLF_RGB,maxval); } CL_Pixel_24 const * * dptrptr = (CL_Pixel_24 const * *) im24; CL_Pixel_24 const * aptr = *im24; for (i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } } if (d3i_ferror(f) || d3i_feof(f)) { DeleteNotMips(); return CLE_LOADERROR; } flags.loaded = 1; return CLE_OK; } CL_Error CL_Image::Load_PGM(D3I_FILE * f) { if (!f) return CLE_OPENERROR; DeleteNotMips(); switch (imode) { case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: break; default: return CLE_INVALIDDXMODE; } d3i_fseek(f,0,SEEK_SET); unsigned short magic; d3i_fread(&magic,2,1,f); if (magic != *(unsigned short const *)"P5") return CLE_LOADERROR; d3i_fseek(f,1,SEEK_CUR); char buf[256]; char * bufptr = buf; unsigned int fields[5]; unsigned int fields_read = 0; while (fields_read < 3 && bufptr) { do bufptr = d3i_fgets(buf, sizeof buf, f); while ('#'==buf[0] && bufptr); int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]); if (EOF != num_fields_read) fields_read += num_fields_read; } if (fields_read < 3) return CLE_LOADERROR; width = fields[0]; height = fields[1]; unsigned int maxval = fields[2]; if (maxval > 255) return CLE_LOADERROR; size = width * height; im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; d3i_fread(*im8,1,size,f); unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char const * aptr = *im8; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } if (d3i_ferror(f) || d3i_feof(f)) { DeleteNotMips(); return CLE_LOADERROR; } flags.loaded = 1; return CLE_OK; } CL_Error CL_Image::Load_PWM(D3I_FILE * f) { if (!f) return CLE_OPENERROR; DeleteNotMips(); switch (imode) { case CLM_TLTPALETTE: break; default: return CLE_INVALIDDXMODE; } d3i_fseek(f,0,SEEK_SET); unsigned short magic; d3i_fread(&magic,2,1,f); if (magic != *(unsigned short const *)"P8") return CLE_LOADERROR; d3i_fseek(f,1,SEEK_CUR); char buf[256]; char * bufptr = buf; unsigned int fields[5]; unsigned int fields_read = 0; while (fields_read < 3 && bufptr) { do bufptr = d3i_fgets(buf, sizeof buf, f); while ('#'==buf[0] && bufptr); int num_fields_read = sscanf(buf,"%u %u %u",&fields[fields_read],&fields[fields_read+1],&fields[fields_read+2]); if (EOF != num_fields_read) fields_read += num_fields_read; } if (fields_read < 3) return CLE_LOADERROR; width = fields[0]; height = fields[1]; unsigned int maxval = fields[2]; if (maxval > 65535) return CLE_LOADERROR; size = width * height; im16raw = new unsigned short * [height]; *im16raw = new unsigned short [size]; d3i_fread(*im16raw,2,size,f); unsigned short const * * dptrptr = (unsigned short const * *) im16raw; unsigned short const * aptr = *im16raw; for (int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } if (d3i_ferror(f) || d3i_feof(f)) { DeleteNotMips(); return CLE_LOADERROR; } flags.loaded = 1; flags.raw16bit = 1; return CLE_OK; } CL_Error CL_Image::GetBitsPerPixel(unsigned int* bpp) { *bpp = bitsperpixel; return CLE_OK; } CL_Error CL_Image::Load_Image(D3I_FILE * f) { if (!f) return CLE_OPENERROR; CL_Error retval = CLE_LOADERROR; START_TIMER d3i_fseek(f,0,SEEK_SET); unsigned short magic; d3i_fread(&magic,2,1,f); if ( *(unsigned short const *)"BM" == magic) retval = Load_BMP(f); else if ( *(unsigned short const *)"P6" == magic) retval = Load_PPM(f); else if ( *(unsigned short const *)"P5" == magic) retval = Load_PGM(f); else if ( *(unsigned short const *)"P8" == magic) retval = Load_PWM(f); #if OUTPUT_LOG else CL_LogFile.lputs("** ERROR: Not a recognized file format\n"); #endif END_TIMER(ReadTime) #if OUTPUT_LOG #if TIME_LOADS CL_LogFile.lprintf("-- Timer Stats (ms): Open %d Read %d Close %d\n",OpenTime,ReadTime,CloseTime); #endif #endif return retval; } void CL_Image::PadTo(int const width_unit,int const height_unit) { if (!flags.loaded) return; unsigned int const owidth = width; unsigned int const oheight = height; width += width_unit-1; width &= ~(width_unit-1); height += height_unit-1; height &= ~(height_unit-1); if (width == owidth && height == oheight) return; // already in spec size = width * height; CL_Pixel_32 * * const oim32 = im32; CL_Pixel_16 * * const oim16 = im16; unsigned char * * const oim8 = im8; if (oim32) { im32 = new CL_Pixel_32 * [height]; *im32 = new CL_Pixel_32 [size]; CL_Pixel_32 const * * dptrptr = (CL_Pixel_32 const * *) im32; CL_Pixel_32 const * aptr = *im32; for (unsigned int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (unsigned int y = 0; y < oheight; ++y) { CL_Pixel_32 const * sptr = oim32[y]; CL_Pixel_32 * dptr = im32[y]; for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr) *dptr = *sptr; for (; x < width; ++x, ++dptr) *dptr = CL_Pixel_24(0,0,0); } for (; y < height; ++y) { CL_Pixel_32 * dptr = im32[y]; for (unsigned int x = 0; x < width; ++x, ++dptr) *dptr = CL_Pixel_24(0,0,0); } delete[] *oim32; delete[] oim32; } if (oim16) { im16 = new CL_Pixel_16 * [height]; *im16 = new CL_Pixel_16 [size]; CL_Pixel_16 const * * dptrptr = (CL_Pixel_16 const * *) im16; CL_Pixel_16 const * aptr = *im16; for (unsigned int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (unsigned int y = 0; y < oheight; ++y) { CL_Pixel_16 const * sptr = oim16[y]; CL_Pixel_16 * dptr = im16[y]; for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr) *dptr = *sptr; for (; x < width; ++x, ++dptr) *dptr = CL_Pixel_24(0,0,0); } for (; y < height; ++y) { CL_Pixel_16 * dptr = im16[y]; for (unsigned int x = 0; x < width; ++x, ++dptr) *dptr = CL_Pixel_24(0,0,0); } delete[] *oim16; delete[] oim16; } if (oim8) { im8 = new unsigned char * [height]; *im8 = new unsigned char [size]; unsigned char const * * dptrptr = (unsigned char const * *) im8; unsigned char const * aptr = *im8; for (unsigned int i=height; i; --i, aptr+=width) { *dptrptr++ = aptr; } for (unsigned int y = 0; y < oheight; ++y) { unsigned char const * sptr = oim8[y]; unsigned char * dptr = im8[y]; for (unsigned int x = 0; x < owidth; ++x, ++dptr, ++sptr) *dptr = *sptr; for (; x < width; ++x, ++dptr) *dptr = 0; } for (; y < height; ++y) { unsigned char * dptr = im8[y]; for (unsigned int x = 0; x < width; ++x, ++dptr) *dptr = 0; } delete[] *oim8; delete[] oim8; } } // implementation of the 'popularity algorithm' for reducing palette unsigned int CL_Pixel_24::FVD_Distance(CL_Pixel_24 const & p2) const { unsigned int dg = g > p2.g ? g - p2.g : p2.g - g; unsigned int db = b > p2.b ? b - p2.b : p2.b - b; unsigned int dgb = dg + db + ((dg > db ? dg : db)<<1); unsigned int dr = r > p2.r ? r - p2.r : p2.r - r; dr += dr<<1; // *= 3 return dr + dgb + ((dr > dgb ? dr : dgb)<<1); } struct _CL_palpixcnt { unsigned int cnt; unsigned int palpos; }; int _CL_cmp_palpixcnt(void const * e1, void const * e2) { return ((_CL_palpixcnt *)e2)->cnt - ((_CL_palpixcnt *)e1)->cnt; } CL_Error CL_Image::ReducePalette(unsigned int const num_colours) { if (!flags.loaded) return CLE_LOADERROR; if (!palette) return CLE_INVALIDDXMODE; if (!im8) return CLE_INVALIDDXMODE; if (palette_size <= num_colours) return CLE_OK; _CL_palpixcnt * const sortarray = new _CL_palpixcnt[palette_size]; for (unsigned int i=0; iname = new char[strlen(name)+1]; mip_n->fname = new char[strlen(fname)+1]; strcpy(mip_n->name,name); strcpy(mip_n->fname,fname); char * dotpos = strrchr(mip_n->fname,'.'); if (!dotpos) { delete mip_n; break; } sprintf(dotpos+3,"%1d",mip_idx); mip_n->flags.located = 1; if (CLE_OK!=mip_n->Load()) { delete mip_n; break; } if (mip_n->width << mip_idx < width || mip_n->height << mip_idx < height) { delete mip_n; #if OUTPUT_LOG CL_LogFile.lputs("** Warning: less than half size\n"); #endif break; } mipmaps.add_entry_end(mip_n); } return CLE_OK; } void CL_Select_Mode(CL_LoadMode const lmode) { switch (lmode) { case CLL_D3DTEXTURE: CL_Image::imode = CL_Image::imode_d3d; CL_Image::bitsperpixel = CL_Image::bitsperpixel_d3d; CL_Pixel_16::f = CL_Pixel_16::f_d3d; CL_Pixel_32::f = CL_Pixel_32::f_d3d; break; case CLL_DDSURFACE: CL_Image::imode = CL_Image::imode_ddraw; CL_Image::bitsperpixel = CL_Image::bitsperpixel_ddraw; CL_Pixel_16::f = CL_Pixel_16::f_ddraw; CL_Pixel_32::f = CL_Pixel_32::f_ddraw; break; } CL_Image::lmode = lmode; } // 3DC interface void CL_Init_DirectDrawMode(CL_VideoMode const vmode) { switch (vmode) { case CLV_8: CL_Image::bitsperpixel_ddraw = 8; CL_Image::imode_ddraw = CLM_GLOBALPALETTE; break; case CLV_8TLT: CL_Image::bitsperpixel_ddraw = 8; CL_Image::imode_ddraw = CLM_TLTPALETTE; break; case CLV_15: CL_Image::bitsperpixel_ddraw = 16; CL_Image::imode_ddraw = CLM_16BIT; CL_Pixel_16::f_ddraw.Init ( DisplayPixelFormat.dwRBitMask, DisplayPixelFormat.dwGBitMask, DisplayPixelFormat.dwBBitMask ); break; case CLV_24: CL_Image::bitsperpixel_ddraw = DisplayPixelFormat.dwRGBBitCount; if (24 == CL_Image::bitsperpixel_ddraw) CL_Image::imode_ddraw = CLM_24BIT; else { CL_Image::imode_ddraw = CLM_32BIT; CL_Pixel_32::f_ddraw.Init ( DisplayPixelFormat.dwRBitMask, DisplayPixelFormat.dwGBitMask, DisplayPixelFormat.dwBBitMask ); } break; case CLV_8T: CL_Image::bitsperpixel_ddraw = 8; CL_Image::imode_ddraw = CLM_16BIT; CL_Pixel_16::f_ddraw.Init(7<<5,7<<2,3); break; } CL_Select_Mode(CLL_DDSURFACE); } CL_Error CL_Image::CopyToScanDrawTexture(unsigned char * * const ImagePtrA [], unsigned int n_mips_max) { if (!flags.loaded) return CLE_LOADERROR; if (CLL_DDSURFACE != lmode) CL_Select_Mode(CLL_DDSURFACE); if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1; if (!*ImagePtrA[0]) { if (flags.raw16bit) { if (n_mips_max>1) *ImagePtrA[0] = (unsigned char *) AllocateMem((2*width+1)*(2*height+1)*2/3+(n_mips_max-3)*2); // slightly more than 4/3 w*h*bytedepth else *ImagePtrA[0] = (unsigned char *) AllocateMem(width*height*2); } else { if (n_mips_max>1) *ImagePtrA[0] = (unsigned char *) AllocateMem((2*width+1)*(2*height+1)*bitsperpixel/24+(n_mips_max-3)*(bitsperpixel/8)); // slightly more than 4/3 w*h*bytedepth else *ImagePtrA[0] = (unsigned char *) AllocateMem(width*height*(bitsperpixel>>3)); } } if (!*ImagePtrA[0]) return CLE_ALLOCFAIL; unsigned int my_bitsperpixel = bitsperpixel; switch (imode) { unsigned char * tptr; unsigned short * tSptr; unsigned long * tLptr; case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: if (flags.raw16bit) { my_bitsperpixel = 16; tSptr = (unsigned short *)*ImagePtrA[0]; if (tSptr) { for (int i=0; ib; *tptr++ = i24ptr->g; *tptr++ = i24ptr->r; i24ptr++; } } } break; case 32: tLptr = (unsigned long *)*ImagePtrA[0]; if (tLptr) { for (int i=0; i i_mip(&mipmaps); for (int i=1; iwidth*last_mipP->height*(my_bitsperpixel>>3); CL_Error thismipmaperror = i_mip()->CopyToScanDrawTexture(&ImagePtrA[i],1); if (CLE_OK != thismipmaperror) return thismipmaperror; last_mipP = i_mip(); } return CLE_OK; } // Direct X interface void CL_Init_D3DMode(LPDDSURFACEDESC const format) { CL_Image::format = format; if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { #if QUANTISE_ON_LOAD CL_Image::imode_d3d = CLM_24BIT; #else CL_Image::imode_d3d = CLM_ATTACHEDPALETTE; #endif CL_Image::bitsperpixel_d3d = 8; } else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) { #if QUANTISE_ON_LOAD CL_Image::imode_d3d = CLM_24BIT; #else CL_Image::imode_d3d = CLM_ATTACHEDPALETTE; #endif CL_Image::bitsperpixel_d3d = 4; } else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2) { #if QUANTISE_ON_LOAD CL_Image::imode_d3d = CLM_24BIT; #else CL_Image::imode_d3d = CLM_ATTACHEDPALETTE; #endif CL_Image::bitsperpixel_d3d = 2; } else if (format->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1) { #if QUANTISE_ON_LOAD CL_Image::imode_d3d = CLM_24BIT; #else CL_Image::imode_d3d = CLM_ATTACHEDPALETTE; #endif CL_Image::bitsperpixel_d3d = 1; } else { CL_Image::bitsperpixel_d3d = format->ddpfPixelFormat.dwRGBBitCount; if (format->ddpfPixelFormat.dwRGBBitCount > 16) { CL_Image::imode_d3d = CLM_32BIT; CL_Pixel_32::f_d3d.Init ( format->ddpfPixelFormat.dwRBitMask, format->ddpfPixelFormat.dwGBitMask, format->ddpfPixelFormat.dwBBitMask ); } else { CL_Image::imode_d3d = CLM_16BIT; CL_Pixel_16::f_d3d.Init ( format->ddpfPixelFormat.dwRBitMask, format->ddpfPixelFormat.dwGBitMask, format->ddpfPixelFormat.dwBBitMask ); } } CL_Select_Mode(CLL_D3DTEXTURE); } CL_Error CL_Image::CopyToD3DTexture(LPDIRECTDRAWSURFACE * const DDPtrA [], LPVOID * const DDSurfaceA [], int const MemoryType, unsigned int n_mips_max) { if (!flags.loaded) return CLE_LOADERROR; WaitForVRamReady(VWS_D3DTEXCREATE); if (CLL_D3DTEXTURE != lmode) CL_Select_Mode(CLL_D3DTEXTURE); LPDIRECTDRAWSURFACE lpDDS; DDSURFACEDESC ddsd; HRESULT ddrval; // Check for image being 4 byte aligned // and fail if it is not if (width & 3 || height & 3) { // return error code return CLE_DXERROR; } // Set up the surface description. starting // with the passed texture format and then // incorporating the information read from the // ppm. memcpy(&ddsd, format, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT); ddsd.ddsCaps.dwCaps = (DDSCAPS_TEXTURE | MemoryType); ddsd.dwHeight = height; ddsd.dwWidth = width; if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1; if (n_mips_max>1) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; ddsd.dwMipMapCount = n_mips_max; } // Create the surface ddrval = lpDD->CreateSurface(&ddsd, &lpDDS, NULL); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return CLE_DXERROR; #endif } // now do mipmaps if avail if (n_mips_max>1) { // We must now traverse the mip-map chain from highest to lowest // resolutions, For each surface AFTER the first one, we must // load a new file, using a name obtained from the mip map number int MipMapNum = 0; LPDIRECTDRAWSURFACE lpThisMipMap, lpNextMipMap; DDSCAPS ddsCaps; lpThisMipMap = lpDDS; // Component Object Model, increase reference count on // mip-map surface by one. lpThisMipMap->AddRef(); ddsCaps.dwCaps = (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP); ddrval = DD_OK; LIF i_mip(&mipmaps); CL_Image * last_mipP = this; while ((ddrval == DD_OK) && (MipMapNum < n_mips_max)) // both tests in case... { // Call LoadPPMIntoDDSurface with lpThisMipMap, new file name, and // other values. *DDSurfaceA[MipMapNum] = last_mipP->CopyToDDSurface(lpThisMipMap); // Death trap if (!*DDSurfaceA[MipMapNum]) { return CLE_DXERROR; } *DDPtrA[MipMapNum] = lpThisMipMap; // Proceed to the next level. // Collect bonus rings. ddrval = lpThisMipMap->GetAttachedSurface(&ddsCaps, &lpNextMipMap); // Necessary to match the manual increment of the reference count on the // COM texture. I think. lpThisMipMap->Release(); // ?? lpNextMipMap = lpThisMipMap; lpThisMipMap = lpNextMipMap; MipMapNum++; if (!i_mip.done()) { last_mipP = i_mip(); i_mip.next(); } } } else { *DDSurfaceA[0] = CopyToDDSurface(lpDDS); if (!*DDSurfaceA[0]) return CLE_DXERROR; *DDPtrA[0] = lpDDS; } return CLE_OK; } CL_Error CL_Image::CopyToDirectDrawSurface(LPDIRECTDRAWSURFACE * const DDPtrA [], LPVOID * const DDSurfaceA [], int const MemoryType, unsigned int n_mips_max) { if (!flags.loaded) return CLE_LOADERROR; WaitForVRamReady(VWS_DDCREATE); if (CLL_DDSURFACE != lmode) CL_Select_Mode(CLL_DDSURFACE); LPDIRECTDRAWSURFACE lpDDS; DDSURFACEDESC ddsd; HRESULT ddrval; // Check for image being 4 byte aligned // and fail if it is not if (width & 3 || height & 3) { // return error code return CLE_DXERROR; } if (n_mips_max > mipmaps.size()+1) n_mips_max = mipmaps.size()+1; // Set up the surface description. starting // with the passed texture format and then // incorporating the information read from the // ppm. memset(&ddsd, 0, sizeof ddsd); ddsd.dwSize = sizeof ddsd; ddsd.dwFlags = (DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT); // Ensure that created surface has same pixel desription // as primary memcpy(&ddsd.ddpfPixelFormat, &DisplayPixelFormat, sizeof(DDPIXELFORMAT)); ddsd.ddsCaps.dwCaps = (DDSCAPS_OFFSCREENPLAIN | MemoryType); ddsd.dwHeight = height; ddsd.dwWidth = width; if (n_mips_max>1) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; ddsd.ddsCaps.dwCaps |= DDSCAPS_MIPMAP | DDSCAPS_COMPLEX; ddsd.dwMipMapCount = n_mips_max; } // Create the surface ddrval = lpDD->CreateSurface(&ddsd, &lpDDS, NULL); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return CLE_DXERROR; #endif } DDCOLORKEY set_zero = {0,0}; ddrval = lpDDS->SetColorKey(DDCKEY_SRCBLT, &set_zero); LOGDXERR(ddrval); if(ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return CLE_DXERROR; #endif } // now do mipmaps if avail if (n_mips_max>1) { // We must now traverse the mip-map chain from highest to lowest // resolutions, For each surface AFTER the first one, we must // load a new file, using a name obtained from the mip map number int MipMapNum = 0; LPDIRECTDRAWSURFACE lpThisMipMap, lpNextMipMap; DDSCAPS ddsCaps; lpThisMipMap = lpDDS; // Component Object Model, increase reference count on // mip-map surface by one. lpThisMipMap->AddRef(); ddsCaps.dwCaps = (DDSCAPS_TEXTURE | DDSCAPS_MIPMAP); ddrval = DD_OK; LIF i_mip(&mipmaps); CL_Image * last_mipP = this; while ((ddrval == DD_OK) && (MipMapNum < n_mips_max)) // both tests in case... { // Call LoadPPMIntoDDSurface with lpThisMipMap, new file name, and // other values. *DDSurfaceA[MipMapNum] = last_mipP->CopyToDDSurface(lpThisMipMap); // Death trap if (!*DDSurfaceA[MipMapNum]) { return CLE_DXERROR; } *DDPtrA[MipMapNum] = lpThisMipMap; // Proceed to the next level. // Collect bonus rings. ddrval = lpThisMipMap->GetAttachedSurface(&ddsCaps, &lpNextMipMap); // Necessary to match the manual increment of the reference count on the // COM texture. I think. lpThisMipMap->Release(); // ?? lpNextMipMap = lpThisMipMap; lpThisMipMap = lpNextMipMap; MipMapNum++; if (!i_mip.done()) { last_mipP = i_mip(); i_mip.next(); } } } else { *DDSurfaceA[0] = CopyToDDSurface(lpDDS); if (!*DDSurfaceA[0]) return CLE_DXERROR; *DDPtrA[0] = lpDDS; } return CLE_OK; } LPVOID CL_Image::CopyToDDSurface(LPDIRECTDRAWSURFACE lpDDS) { if (!flags.loaded) return 0; LPDIRECTDRAWPALETTE lpDDPPMPal; PALETTEENTRY ppe[256]; DDSURFACEDESC ddsd; #if QUANTISE_ON_LOAD D3DCOLOR colors[256]; D3DCOLOR c; int color_count; #endif int psize; char *lpC; HRESULT ddrval; unsigned int i, j; unsigned int pcaps; // Lock the surface so it can be filled with the PPM file memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddrval = lpDDS->Lock(NULL, &ddsd, 0, NULL); if (!ddsd.lpSurface) { lpDDS->Unlock(NULL); lpDDS->Release(); LOGDXSTR("No surface"); return 0; } LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return 0; #endif } // The method of loading depends on the pixel format of the dest surface switch (imode) { case CLM_32BIT: switch (bitsperpixel) { case 32: for (j = 0; j < height; j++) { // Point to next row in texture surface unsigned long * lpLP = (unsigned long*)((char*)ddsd.lpSurface + ddsd.lPitch * j); CL_Pixel_32 * lpP32 = im32[j]; for (i = width; i; --i) { *lpLP++ = *lpP32++; } } break; case 24: for (j = 0; j < height; j++) { // Point to next row in texture surface unsigned char * lpCP = (unsigned char*)ddsd.lpSurface + ddsd.lPitch * j; CL_Pixel_32 * lpP32 = im32[j]; for (i = width; i; --i) { unsigned long lv = *lpP32++; unsigned char const * lpSrcCP = (unsigned char const *)&lv; // dodgy - makes assumtions about 24-bit values... *lpCP++ = *lpSrcCP++; *lpCP++ = *lpSrcCP++; *lpCP++ = *lpSrcCP++; } } break; default: #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Unlock(NULL); lpDDS->Release(); return 0; #endif } lpDDS->Unlock(NULL); break; case CLM_16BIT: switch (bitsperpixel) { case 16: for (j = 0; j < height; j++) { // Point to next row in texture surface unsigned short * lpSP = (unsigned short*)((char*)ddsd.lpSurface + ddsd.lPitch * j); CL_Pixel_16 * lpP16 = im16[j]; for (i = width; i; --i) { *lpSP++ = *lpP16++; } } break; case 8: for (j = 0; j < height; j++) { // Point to next row in texture surface unsigned char * lpCP = (unsigned char*)ddsd.lpSurface + ddsd.lPitch * j; CL_Pixel_16 * lpP16 = im16[j]; for (i = width; i; --i) { *lpCP++ = *lpP16++; } } break; default: // Everything's gone pear-shaped... #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Unlock(NULL); lpDDS->Release(); return 0; #endif } lpDDS->Unlock(NULL); break; case CLM_24BIT: if (24==bitsperpixel) { for (j = 0; j < height; j++) { // Point to next row in surface unsigned char * lpCP = ((unsigned char*)ddsd.lpSurface) + ddsd.lPitch * j; CL_Pixel_24 * lpP24 = im24[j]; for (i = 0; i < width; i++) { // making an assumption about the ordering of r,g,b on the video card *lpCP++ = lpP24->b; *lpCP++ = lpP24->g; *lpCP++ = lpP24->r; lpP24++; } } lpDDS->Unlock(NULL); } else { #if QUANTISE_ON_LOAD // Neal's quantize on load stuff // Paletted target texture surface psize = 1<r, lpP24->g, lpP24->b); // Search for this color in a table of colors in this texture for (k = 0; k < color_count; k++) if (c == colors[k]) break; if (k == color_count) { // This is a new color, so add it to the list color_count++; // More than 256 and we fail (8-bit) if (color_count > psize) { color_count--; k = color_count - 1; } colors[k] = c; } // Set the "pixel" value on the surface to be the index into the // color table if (psize<256) { unsigned int bitmask; switch (psize) { default: bitmask = 1; break; case 4: bitmask = 3; break; case 2: bitmask = 7; break; } if ((i & bitmask) == 0) *lpC = (char)(k & (psize-1)); else *lpC |= (char)((k & (psize-1)) << (i & (psize-1))); if ((~i & bitmask) == 0) lpC++; } else { *lpC = (char)k; lpC++; } } } // Close the file and unlock the surface lpDDS->Unlock(NULL); if (color_count > psize) { // If there are more than 256 colors, we overran our palette #if debug ReleaseDirect3D(); exit(0x321123); #else lpDDS->Release(); return 0; #endif } // Create a palette with the colors in our color table memset(ppe, 0, sizeof(PALETTEENTRY) * 256); for (i = 0; i < color_count; i++) { ppe[i].peRed = (unsigned char)RGB_GETRED(colors[i]); ppe[i].peGreen = (unsigned char)RGB_GETGREEN(colors[i]); ppe[i].peBlue = (unsigned char)RGB_GETBLUE(colors[i]); } // Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by // the renderer. for (; i < 256; i++) ppe[i].peFlags = D3DPAL_RESERVED; // Create the palette with the DDPCAPS_ALLOW256 flag because we want to // have access to all entries. switch (bitsperpixel) { default: pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256; break; case 4: pcaps = DDPCAPS_4BIT; break; case 2: pcaps = DDPCAPS_2BIT; break; case 1: pcaps = DDPCAPS_1BIT; break; } ddrval = lpDD->CreatePalette (DDPCAPS_INITIALIZE | pcaps, ppe, &lpDDPPMPal, NULL); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return 0; #endif } // Finally, bind the palette to the surface ddrval = lpDDS->SetPalette(lpDDPPMPal); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); lpDDPPMPal->Release(); return 0; #endif } lpDDPPMPal->Release(); } break; #else // Everything's gone pear-shaped... #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Unlock(NULL); lpDDS->Release(); return 0; #endif } break; case CLM_ATTACHEDPALETTE: #endif case CLM_GLOBALPALETTE: case CLM_TLTPALETTE: // Paletted target texture surface psize = 1<> nextpixelshift; for (i = 0; i < width; i++) { unsigned char k = *lpP8++; // Set the "pixel" value on the surface to be the index into the // color table if ((i & bitmask) == 0) *lpC = (char) (k & (psize-1)); else *lpC |= (char) ((k & (psize-1)) << ((i & bitmask)<Unlock(NULL); // Create a palette with the colors in our color table memset(ppe, 0, sizeof(PALETTEENTRY) * 256); for (i = 0; i < palette_size; i++) { ppe[i].peRed = palette[i].r; ppe[i].peGreen = palette[i].g; ppe[i].peBlue = palette[i].b; } // Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by // the renderer. for (; i < 256; i++) ppe[i].peFlags = D3DPAL_RESERVED; // Create the palette with the DDPCAPS_ALLOW256 flag because we want to // have access to all entries. switch (bitsperpixel) { default: pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256; break; case 4: pcaps = DDPCAPS_4BIT; break; case 2: pcaps = DDPCAPS_2BIT; break; case 1: pcaps = DDPCAPS_1BIT; break; } ddrval = lpDD->CreatePalette (DDPCAPS_INITIALIZE | pcaps, ppe, &lpDDPPMPal, NULL); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); return 0; #endif } // Finally, bind the palette to the surface ddrval = lpDDS->SetPalette(lpDDPPMPal); LOGDXERR(ddrval); if (ddrval != DD_OK) { #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Release(); lpDDPPMPal->Release(); return 0; #endif } lpDDPPMPal->Release(); break; default: // Everything's gone pear-shaped... #if debug ReleaseDirect3D(); exit(ddrval); #else lpDDS->Unlock(NULL); lpDDS->Release(); return 0; #endif } return ddsd.lpSurface; }