00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043 #include <assert.h>
00044
00045 #include "OSGConfig.h"
00046
00047 #include <string>
00048 #include <vector>
00049
00050 #include <iostream>
00051 #include <fstream>
00052
00053 #include <OSGLog.h>
00054
00055 #include <OSGImage.h>
00056
00057 #include "OSGDDSImageFileType.h"
00058
00059 #ifdef OSG_SGI_STL
00060
00061
00062 #ifndef INT_MAX
00063 #define INT_MAX numeric_limits<int>::max()
00064 #endif
00065 #else
00066 #include <limits.h>
00067 #endif
00068 OSG_USING_NAMESPACE
00069
00070
00083
00084
00085
00086
00087 static const Char8 *suffixArray[] =
00088 {
00089 "dds"
00090 };
00091
00092
00093 DDSImageFileType DDSImageFileType::_the("dds",
00094 suffixArray, sizeof(suffixArray),
00095 OSG_READ_SUPPORTED |
00096 OSG_WRITE_SUPPORTED);
00097
00098
00099
00100
00101
00102
00103
00104
00105 #ifdef WIN32
00106 # include <windows.h>
00107 #endif
00108
00109 const unsigned long DDS_FOURCC = 0x00000004;
00110 const unsigned long DDS_RGB = 0x00000040;
00111 const unsigned long DDS_RGBA = 0x00000041;
00112 const unsigned long DDS_DEPTH = 0x00800000;
00113
00114 const unsigned long DDS_COMPLEX = 0x00000008;
00115 const unsigned long DDS_CUBEMAP = 0x00000200;
00116 const unsigned long DDS_VOLUME = 0x00200000;
00117
00118 const unsigned long FOURCC_DXT1 = 0x31545844;
00119 const unsigned long FOURCC_DXT3 = 0x33545844;
00120 const unsigned long FOURCC_DXT5 = 0x35545844;
00121
00122 struct DDS_PIXELFORMAT {
00123 unsigned long dwSize;
00124 unsigned long dwFlags;
00125 unsigned long dwFourCC;
00126 unsigned long dwRGBBitCount;
00127 unsigned long dwRBitMask;
00128 unsigned long dwGBitMask;
00129 unsigned long dwBBitMask;
00130 unsigned long dwABitMask;
00131 };
00132
00133 struct DXTColBlock {
00134 unsigned short col0;
00135 unsigned short col1;
00136
00137 unsigned char row[4];
00138 };
00139
00140 struct DXT3AlphaBlock {
00141 unsigned short row[4];
00142 };
00143
00144 struct DXT5AlphaBlock
00145 {
00146 unsigned char alpha0;
00147 unsigned char alpha1;
00148
00149 unsigned char row[6];
00150 };
00151
00152 struct DDS_HEADER {
00153 unsigned long dwSize;
00154 unsigned long dwFlags;
00155 unsigned long dwHeight;
00156 unsigned long dwWidth;
00157 unsigned long dwPitchOrLinearSize;
00158 unsigned long dwDepth;
00159 unsigned long dwMipMapCount;
00160 unsigned long dwReserved1[11];
00161 DDS_PIXELFORMAT ddspf;
00162 unsigned long dwCaps1;
00163 unsigned long dwCaps2;
00164 unsigned long dwReserved2[3];
00165 };
00166
00167 class CSurface
00168 {
00169 friend class CTexture;
00170 friend class CDDSImage;
00171
00172 public:
00173 CSurface();
00174 CSurface(int w, int h, int d, int imgsize);
00175 CSurface(const CSurface ©);
00176 CSurface &operator= (const CSurface &rhs);
00177 virtual ~CSurface();
00178
00179 operator char*();
00180
00181 void create(int w, int h, int d, int imgsize);
00182 void clear();
00183
00184 inline int get_width() { return width; }
00185 inline int get_height() { return height; }
00186 inline int get_depth() { return depth; }
00187 inline int get_size() { return size; }
00188 inline char* get_pixels() { return pixels; }
00189
00190 protected:
00191 int width;
00192 int height;
00193 int depth;
00194 int size;
00195
00196 char *pixels;
00197 };
00198
00199 class CTexture : public CSurface
00200 {
00201 friend class CDDSImage;
00202
00203 public:
00204 CTexture();
00205 CTexture(int w, int h, int d, int imgSize);
00206 CTexture(const CTexture ©);
00207 CTexture &operator= (const CTexture &rhs);
00208 ~CTexture();
00209
00210 inline CSurface &get_mipmap(int index)
00211 {
00212 assert(index < (int)mipmaps.size());
00213 return mipmaps[index];
00214 }
00215
00216 inline int get_num_mipmaps() { return (int)mipmaps.size(); }
00217 protected:
00218 std::vector<CSurface> mipmaps;
00219 };
00220
00221 class CDDSImage
00222 {
00223 public:
00224 CDDSImage();
00225 ~CDDSImage();
00226
00227 bool load(std::string filename, bool flipImage = true);
00228 void clear();
00229
00230 operator char*();
00231 CTexture &operator[](int index);
00232
00233 inline int get_num_images(void) { return (int)images.size(); }
00234 inline CTexture &get_image(int index)
00235 {
00236 assert(index < (int)images.size());
00237 return images[index];
00238 }
00239
00240 inline int get_components() { return components; }
00241 inline int get_format() { return format; }
00242
00243 inline bool is_compressed() { return compressed; }
00244 inline bool is_cubemap() { return cubemap; }
00245 inline bool is_volume() { return volume; }
00246 inline bool is_valid() { return valid; }
00247
00248 private:
00249 int clamp_size(int size);
00250 int get_line_width(int width, int bpp);
00251 int size_dxtc(int width, int height);
00252 int size_rgb(int width, int height);
00253 inline void swap_endian(void *val);
00254 void align_memory(CTexture *surface);
00255
00256 void flip(char *image, int width, int height, int depth, int size);
00257
00258 void swap(void *byte1, void *byte2, int size);
00259 void flip_blocks_dxtc1(DXTColBlock *line, int numBlocks);
00260 void flip_blocks_dxtc3(DXTColBlock *line, int numBlocks);
00261 void flip_blocks_dxtc5(DXTColBlock *line, int numBlocks);
00262 void flip_dxt5_alpha(DXT5AlphaBlock *block);
00263
00264 int format;
00265 int components;
00266 bool compressed;
00267 bool cubemap;
00268 bool volume;
00269 bool valid;
00270
00271 std::vector<CTexture> images;
00272
00273 };
00274
00275
00276
00277
00278
00279
00280
00284 DDSImageFileType& DDSImageFileType::the (void)
00285 {
00286 return _the;
00287 }
00288
00289
00290
00291
00292
00293
00298 bool DDSImageFileType::read(ImagePtr &image, const Char8 *fileName)
00299 {
00300 bool validImage = false;
00301 CDDSImage ddsImage;
00302 int i,j,w,h,d, mm = 0, components, format,size;
00303 int width = 0, height = 0, depth = 0, numMipMaps = 0;
00304 bool isCompressed, isCubeMap, isVolume;
00305 unsigned char *data;
00306 unsigned dataSize = 0;
00307
00308 SINFO << "DDS File Info: " << fileName << ": ";
00309
00310 if (ddsImage.load(fileName) && (validImage = ddsImage.is_valid())) {
00311 components = ddsImage.get_components();
00312 format = ddsImage.get_format();
00313 isCompressed = ddsImage.is_compressed();
00314 isCubeMap = ddsImage.is_cubemap();
00315 isVolume = ddsImage.is_volume();
00316 SINFO << "cs: " << components
00317 << ", f: " << format
00318 << ", cd: " << isCompressed
00319 << ", cm: " << isCubeMap
00320 << ", vo: " << isVolume
00321 << endLog;
00322 for (i = 0; i < ddsImage.get_num_images(); ++i) {
00323 w = ddsImage[i].get_width();
00324 h = ddsImage[i].get_height();
00325 d = ddsImage[i].get_depth();
00326 size = ddsImage[i].get_size();
00327 dataSize += size;
00328 mm = ddsImage[i].get_num_mipmaps();
00329 if (i) {
00330 if ( (w != width) || (h != height) || (d != depth) &&
00331 (mm != numMipMaps) )
00332 validImage = false;
00333 }
00334 else {
00335 width = w;
00336 height = h;
00337 depth = d;
00338 numMipMaps = mm;
00339 }
00340 SINFO << " " << i
00341 << ", " << w << "x" << h << "x" << d
00342 << ", size: " << size
00343 << ", mm: " << mm
00344 << endLog;
00345 for (j = 0; j < mm; ++j) {
00346 w = ddsImage[i].get_mipmap(j).get_width();
00347 h = ddsImage[i].get_mipmap(j).get_height();
00348 d = ddsImage[i].get_mipmap(j).get_depth();
00349 size = ddsImage[i].get_mipmap(j).get_size();
00350 dataSize += size;
00351 SINFO << " " << j
00352 << ", " << w << "x" << h << "x" << d
00353 << ", size: " << size
00354 << ", mm: " << mm
00355 << endLog;
00356
00357 }
00358 }
00359 if (validImage) {
00360 image->set( osg::Image::PixelFormat(format),
00361 width, height, depth,
00362 numMipMaps + 1,
00363 1, 0.0, 0, osg::Image::OSG_UINT8_IMAGEDATA,
00364 true,
00365 ddsImage.get_num_images() );
00366
00367 if (dataSize == image->getSize()) {
00368 data = image->getData();
00369
00370
00371 for (i = 0; i < ddsImage.get_num_images(); ++i) {
00372 size = ddsImage[i].get_size();
00373 memcpy (data, ddsImage[i].get_pixels(), size);
00374 data += size;
00375 for (j = 0; j < mm; ++j) {
00376 size = ddsImage[i].get_mipmap(j).get_size();
00377 memcpy (data, ddsImage[i].get_mipmap(j).get_pixels(), size);
00378 data += size;
00379 }
00380 }
00381 }
00382 else {
00383 SWARNING << "ERROR: Invalid data size; cannot cp dds data"
00384 << endLog;
00385
00386 }
00387 }
00388 }
00389 else
00390 SWARNING << "DDS Load Failed !" << endLog;
00391
00392 return validImage;;
00393 }
00394
00395
00400 bool DDSImageFileType::write(const ImagePtr &image, const Char8 *fileName)
00401 {
00402 SWARNING << getMimeType()
00403 << " write is not implemented "
00404 << endLog;
00405
00406 return false;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00427
00431 DDSImageFileType::DDSImageFileType(const Char8 *mimeType,
00432 const Char8 *suffixArray[],
00433 UInt16 suffixByteCount,
00434 UInt32 flags) :
00435 ImageFileType(mimeType,suffixArray, suffixByteCount, flags)
00436 {
00437 return;
00438 }
00439
00440
00444 DDSImageFileType::DDSImageFileType(const DDSImageFileType &obj) :
00445 ImageFileType(obj)
00446 {
00447 return;
00448 }
00449
00450
00454 DDSImageFileType::~DDSImageFileType(void)
00455 {
00456 return;
00457 }
00458
00459
00461
00462
00464
00465 CDDSImage::CDDSImage()
00466 : format(0),
00467 components(0),
00468 compressed(false),
00469 cubemap(false),
00470 volume(false),
00471 valid(false)
00472 {
00473 }
00474
00475 CDDSImage::~CDDSImage()
00476 {
00477 }
00478
00480
00481
00482
00483
00484 bool CDDSImage::load(std::string filename, bool flipImage)
00485 {
00486 DDS_HEADER ddsh;
00487 char filecode[4];
00488 FILE *fp;
00489 int width, height, depth;
00490 int (CDDSImage::*sizefunc)(int, int);
00491
00492
00493 clear();
00494
00495
00496 fp = fopen(filename.data(), "rb");
00497 if (fp == NULL)
00498 return false;
00499
00500
00501 fread(filecode, 1, 4, fp);
00502 if (strncmp(filecode, "DDS ", 4) != 0)
00503 {
00504 fclose(fp);
00505 return false;
00506 }
00507
00508
00509 fread(&ddsh, sizeof(ddsh), 1, fp);
00510
00511 swap_endian(&ddsh.dwSize);
00512 swap_endian(&ddsh.dwFlags);
00513 swap_endian(&ddsh.dwHeight);
00514 swap_endian(&ddsh.dwWidth);
00515 swap_endian(&ddsh.dwPitchOrLinearSize);
00516 swap_endian(&ddsh.dwMipMapCount);
00517 swap_endian(&ddsh.ddspf.dwSize);
00518 swap_endian(&ddsh.ddspf.dwFlags);
00519 swap_endian(&ddsh.ddspf.dwFourCC);
00520 swap_endian(&ddsh.ddspf.dwRGBBitCount);
00521 swap_endian(&ddsh.dwCaps1);
00522 swap_endian(&ddsh.dwCaps2);
00523
00524
00525 if (ddsh.dwCaps2 & DDS_CUBEMAP)
00526 cubemap = true;
00527
00528
00529 if ((ddsh.dwCaps2 & DDS_VOLUME) && (ddsh.dwDepth > 0))
00530 volume = true;
00531
00532
00533 if (ddsh.ddspf.dwFlags & DDS_FOURCC)
00534 {
00535 switch(ddsh.ddspf.dwFourCC)
00536 {
00537 case FOURCC_DXT1:
00538 format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
00539 components = 3;
00540 compressed = true;
00541 break;
00542 case FOURCC_DXT3:
00543 format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
00544 components = 4;
00545 compressed = true;
00546 break;
00547 case FOURCC_DXT5:
00548 format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
00549 components = 4;
00550 compressed = true;
00551 break;
00552 default:
00553 fclose(fp);
00554 return false;
00555 }
00556 }
00557 else if (ddsh.ddspf.dwFlags == DDS_RGBA && ddsh.ddspf.dwRGBBitCount == 32)
00558 {
00559 format = Image::OSG_BGRA_PF;
00560 compressed = false;
00561 components = 4;
00562 }
00563 else if (ddsh.ddspf.dwFlags == DDS_RGB && ddsh.ddspf.dwRGBBitCount == 32)
00564 {
00565 format = Image::OSG_BGRA_PF;
00566 compressed = false;
00567 components = 4;
00568 }
00569 else if (ddsh.ddspf.dwFlags == DDS_RGB && ddsh.ddspf.dwRGBBitCount == 24)
00570 {
00571 format = Image::OSG_BGR_PF;
00572 compressed = false;
00573 components = 3;
00574 }
00575 else if ( ddsh.ddspf.dwRGBBitCount == 8)
00576 {
00577 format = Image::OSG_L_PF;
00578 compressed = false;
00579 components = 1;
00580 }
00581 else
00582 {
00583 SWARNING << "ERROR: unknown image format!" << endLog;
00584 fclose(fp);
00585 return false;
00586 }
00587
00588
00589 width = ddsh.dwWidth;
00590 height = ddsh.dwHeight;
00591 depth = clamp_size(ddsh.dwDepth);
00592
00593
00594
00595 sizefunc = (compressed ? &CDDSImage::size_dxtc : &CDDSImage::size_rgb);
00596
00597
00598 for (int n = 0; n < (cubemap ? 6 : 1); n++)
00599 {
00600 int size;
00601
00602
00603 size = (this->*sizefunc)(width, height)*depth;
00604
00605
00606 CTexture img(width, height, depth, size);
00607 fread(img, 1, img.size, fp);
00608
00609 align_memory(&img);
00610
00611 if (flipImage && !cubemap)
00612 flip(img, img.width, img.height, img.depth, img.size);
00613
00614 int w = clamp_size(width >> 1);
00615 int h = clamp_size(height >> 1);
00616 int d = clamp_size(depth >> 1);
00617
00618
00619 int numMipmaps = ddsh.dwMipMapCount;
00620
00621
00622
00623 if (numMipmaps != 0)
00624 numMipmaps--;
00625
00626
00627 for (int i = 0; i < numMipmaps && (w || h); i++)
00628 {
00629
00630 size = (this->*sizefunc)(w, h)*d;
00631
00632 CSurface mipmap(w, h, d, size);
00633 fread(mipmap, 1, mipmap.size, fp);
00634
00635 if (flipImage && !cubemap)
00636 {
00637 flip(mipmap, mipmap.width, mipmap.height, mipmap.depth,
00638 mipmap.size);
00639 }
00640
00641 img.mipmaps.push_back(mipmap);
00642
00643
00644 w = clamp_size(w >> 1);
00645 h = clamp_size(h >> 1);
00646 d = clamp_size(d >> 1);
00647 }
00648
00649 images.push_back(img);
00650 }
00651
00652 #if 0
00653
00654 if (cubemap && flipImage)
00655 {
00656 CTexture tmp;
00657 tmp = images[3];
00658 images[3] = images[2];
00659 images[2] = tmp;
00660 }
00661 #endif
00662
00663 fclose(fp);
00664
00665 valid = true;
00666
00667 return true;
00668 }
00669
00671
00672 void CDDSImage::clear()
00673 {
00674 components = 0;
00675 format = 0;
00676 compressed = false;
00677 cubemap = false;
00678 volume = false;
00679 valid = false;
00680
00681 images.clear();
00682 }
00683
00685
00686
00687 CTexture &CDDSImage::operator[](int index)
00688 {
00689
00690 assert(valid);
00691 assert(index < (int)images.size());
00692
00693 return images[index];
00694 }
00695
00697
00698 CDDSImage::operator char*()
00699 {
00700 assert(valid);
00701
00702 return images[0];
00703 }
00704
00705
00707
00708 inline int CDDSImage::clamp_size(int size)
00709 {
00710 if (size <= 0)
00711 size = 1;
00712
00713 return size;
00714 }
00715
00717
00719
00721
00722 inline int CDDSImage::get_line_width(int width, int bpp)
00723 {
00724 return ((width * bpp + 31) & -32) >> 3;
00725 }
00726
00728
00729 inline int CDDSImage::size_dxtc(int width, int height)
00730 {
00731 return ((width+3)/4)*((height+3)/4)*
00732 (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 8 : 16);
00733 }
00734
00736
00737 inline int CDDSImage::size_rgb(int width, int height)
00738 {
00739 return width*height*components;
00740 }
00741
00743
00744 inline void CDDSImage::swap_endian(void *val)
00745 {
00746 #ifdef MACOS
00747 unsigned int *ival = (unsigned int *)val;
00748
00749 *ival = ((*ival >> 24) & 0x000000ff) |
00750 ((*ival >> 8) & 0x0000ff00) |
00751 ((*ival << 8) & 0x00ff0000) |
00752 ((*ival << 24) & 0xff000000);
00753 #endif
00754 }
00755
00757
00758 void CDDSImage::align_memory(CTexture *surface)
00759 {
00760
00761 if (compressed || volume || cubemap)
00762 return;
00763
00764
00765 int linesize = get_line_width(surface->width, components*8);
00766 int imagesize = linesize*surface->height;
00767
00768
00769 if (surface->size == imagesize)
00770 return;
00771
00772
00773 CTexture newSurface(surface->width, surface->height, surface->depth,
00774 imagesize);
00775
00776
00777 char *srcimage = (char*)*surface;
00778 char *dstimage = (char*)newSurface;
00779 for (int n = 0; n < surface->depth; n++)
00780 {
00781 char *curline = srcimage;
00782 char *newline = dstimage;
00783
00784 int imsize = surface->size / surface->depth;
00785 int lnsize = imsize / surface->height;
00786
00787 for (int i = 0; i < surface->height; i++)
00788 {
00789 memcpy(newline, curline, lnsize);
00790 newline += linesize;
00791 curline += lnsize;
00792 }
00793 }
00794
00795
00796 *surface = newSurface;
00797 }
00798
00800
00801 void CDDSImage::flip(char *image, int width, int height, int depth, int size)
00802 {
00803 int linesize;
00804 int offset;
00805
00806 if (!compressed)
00807 {
00808 assert(depth > 0);
00809
00810 int imagesize = size/depth;
00811 linesize = imagesize / height;
00812
00813 for (int n = 0; n < depth; n++)
00814 {
00815 offset = imagesize*n;
00816 char *top = image + offset;
00817 char *bottom = top + (imagesize-linesize);
00818
00819 for (int i = 0; i < (height >> 1); i++)
00820 {
00821 swap(bottom, top, linesize);
00822
00823 top += linesize;
00824 bottom -= linesize;
00825 }
00826 }
00827 }
00828 else
00829 {
00830 void (CDDSImage::*flipblocks)(DXTColBlock*, int);
00831 int xblocks = width / 4;
00832 int yblocks = height / 4;
00833 int blocksize;
00834
00835 switch (format)
00836 {
00837 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
00838 blocksize = 8;
00839 flipblocks = &CDDSImage::flip_blocks_dxtc1;
00840 break;
00841 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
00842 blocksize = 16;
00843 flipblocks = &CDDSImage::flip_blocks_dxtc3;
00844 break;
00845 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
00846 blocksize = 16;
00847 flipblocks = &CDDSImage::flip_blocks_dxtc5;
00848 break;
00849 default:
00850 return;
00851 }
00852
00853 linesize = xblocks * blocksize;
00854
00855 DXTColBlock *top;
00856 DXTColBlock *bottom;
00857
00858 for (int j = 0; j < (yblocks >> 1); j++)
00859 {
00860 top = (DXTColBlock*)(image + j * linesize);
00861 bottom = (DXTColBlock*)(image + (((yblocks-j)-1) * linesize));
00862
00863 (this->*flipblocks)(top, xblocks);
00864 (this->*flipblocks)(bottom, xblocks);
00865
00866 swap(bottom, top, linesize);
00867 }
00868 }
00869 }
00870
00872
00873 void CDDSImage::swap(void *byte1, void *byte2, int size)
00874 {
00875 unsigned char *tmp = new unsigned char[size];
00876
00877 memcpy(tmp, byte1, size);
00878 memcpy(byte1, byte2, size);
00879 memcpy(byte2, tmp, size);
00880
00881 delete [] tmp;
00882 }
00883
00885
00886 void CDDSImage::flip_blocks_dxtc1(DXTColBlock *line, int numBlocks)
00887 {
00888 DXTColBlock *curblock = line;
00889
00890 for (int i = 0; i < numBlocks; i++)
00891 {
00892 swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
00893 swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
00894
00895 curblock++;
00896 }
00897 }
00898
00900
00901 void CDDSImage::flip_blocks_dxtc3(DXTColBlock *line, int numBlocks)
00902 {
00903 DXTColBlock *curblock = line;
00904 DXT3AlphaBlock *alphablock;
00905
00906 for (int i = 0; i < numBlocks; i++)
00907 {
00908 alphablock = (DXT3AlphaBlock*)curblock;
00909
00910 swap(&alphablock->row[0], &alphablock->row[3], sizeof(unsigned short));
00911 swap(&alphablock->row[1], &alphablock->row[2], sizeof(unsigned short));
00912
00913 curblock++;
00914
00915 swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
00916 swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
00917
00918 curblock++;
00919 }
00920 }
00921
00923
00924 void CDDSImage::flip_dxt5_alpha(DXT5AlphaBlock *block)
00925 {
00926 unsigned char gBits[4][4];
00927
00928 const unsigned long mask = 0x00000007;
00929 unsigned long bits = 0;
00930 memcpy(&bits, &block->row[0], sizeof(unsigned char) * 3);
00931
00932 gBits[0][0] = (unsigned char)(bits & mask);
00933 bits >>= 3;
00934 gBits[0][1] = (unsigned char)(bits & mask);
00935 bits >>= 3;
00936 gBits[0][2] = (unsigned char)(bits & mask);
00937 bits >>= 3;
00938 gBits[0][3] = (unsigned char)(bits & mask);
00939 bits >>= 3;
00940 gBits[1][0] = (unsigned char)(bits & mask);
00941 bits >>= 3;
00942 gBits[1][1] = (unsigned char)(bits & mask);
00943 bits >>= 3;
00944 gBits[1][2] = (unsigned char)(bits & mask);
00945 bits >>= 3;
00946 gBits[1][3] = (unsigned char)(bits & mask);
00947
00948 bits = 0;
00949 memcpy(&bits, &block->row[3], sizeof(unsigned char) * 3);
00950
00951 gBits[2][0] = (unsigned char)(bits & mask);
00952 bits >>= 3;
00953 gBits[2][1] = (unsigned char)(bits & mask);
00954 bits >>= 3;
00955 gBits[2][2] = (unsigned char)(bits & mask);
00956 bits >>= 3;
00957 gBits[2][3] = (unsigned char)(bits & mask);
00958 bits >>= 3;
00959 gBits[3][0] = (unsigned char)(bits & mask);
00960 bits >>= 3;
00961 gBits[3][1] = (unsigned char)(bits & mask);
00962 bits >>= 3;
00963 gBits[3][2] = (unsigned char)(bits & mask);
00964 bits >>= 3;
00965 gBits[3][3] = (unsigned char)(bits & mask);
00966
00967 unsigned long *pBits = ((unsigned long*) &(block->row[0]));
00968
00969 *pBits = *pBits | (gBits[3][0] << 0);
00970 *pBits = *pBits | (gBits[3][1] << 3);
00971 *pBits = *pBits | (gBits[3][2] << 6);
00972 *pBits = *pBits | (gBits[3][3] << 9);
00973
00974 *pBits = *pBits | (gBits[2][0] << 12);
00975 *pBits = *pBits | (gBits[2][1] << 15);
00976 *pBits = *pBits | (gBits[2][2] << 18);
00977 *pBits = *pBits | (gBits[2][3] << 21);
00978
00979 pBits = ((unsigned long*) &(block->row[3]));
00980
00981 #ifdef MACOS
00982 *pBits &= 0x000000ff;
00983 #else
00984 *pBits &= 0xff000000;
00985 #endif
00986
00987 *pBits = *pBits | (gBits[1][0] << 0);
00988 *pBits = *pBits | (gBits[1][1] << 3);
00989 *pBits = *pBits | (gBits[1][2] << 6);
00990 *pBits = *pBits | (gBits[1][3] << 9);
00991
00992 *pBits = *pBits | (gBits[0][0] << 12);
00993 *pBits = *pBits | (gBits[0][1] << 15);
00994 *pBits = *pBits | (gBits[0][2] << 18);
00995 *pBits = *pBits | (gBits[0][3] << 21);
00996 }
00997
00999
01000 void CDDSImage::flip_blocks_dxtc5(DXTColBlock *line, int numBlocks)
01001 {
01002 DXTColBlock *curblock = line;
01003 DXT5AlphaBlock *alphablock;
01004
01005 for (int i = 0; i < numBlocks; i++)
01006 {
01007 alphablock = (DXT5AlphaBlock*)curblock;
01008
01009 flip_dxt5_alpha(alphablock);
01010
01011 curblock++;
01012
01013 swap(&curblock->row[0], &curblock->row[3], sizeof(unsigned char));
01014 swap(&curblock->row[1], &curblock->row[2], sizeof(unsigned char));
01015
01016 curblock++;
01017 }
01018 }
01019
01021
01023
01025
01026 CTexture::CTexture()
01027 : CSurface()
01028 {
01029 }
01030
01032
01033 CTexture::CTexture(int w, int h, int d, int imgSize)
01034 : CSurface(w, h, d, imgSize)
01035 {
01036 }
01037
01039
01040 CTexture::CTexture(const CTexture ©)
01041 : CSurface(copy)
01042 {
01043 for (unsigned int i = 0; i < copy.mipmaps.size(); i++)
01044 mipmaps.push_back(copy.mipmaps[i]);
01045 }
01046
01048
01049 CTexture &CTexture::operator= (const CTexture &rhs)
01050 {
01051 if (this != &rhs)
01052 {
01053 CSurface::operator = (rhs);
01054
01055 mipmaps.clear();
01056 for (unsigned int i = 0; i < rhs.mipmaps.size(); i++)
01057 {
01058 mipmaps.push_back(rhs.mipmaps[i]);
01059 }
01060 }
01061
01062 return *this;
01063 }
01064
01066
01067 CTexture::~CTexture()
01068 {
01069 mipmaps.clear();
01070 }
01071
01073
01075
01077
01078 CSurface::CSurface()
01079 : width(0),
01080 height(0),
01081 depth(0),
01082 size(0),
01083 pixels(NULL)
01084 {
01085 }
01086
01088
01089 CSurface::CSurface(int w, int h, int d, int imgsize)
01090 {
01091 pixels = NULL;
01092 create(w, h, d, imgsize);
01093 }
01094
01096
01097 CSurface::CSurface(const CSurface ©)
01098 : width(0),
01099 height(0),
01100 depth(0),
01101 size(0),
01102 pixels(NULL)
01103 {
01104
01105 if (copy.pixels)
01106 {
01107 size = copy.size;
01108 width = copy.width;
01109 height = copy.height;
01110 depth = copy.depth;
01111 pixels = new char[size];
01112 memcpy(pixels, copy.pixels, copy.size);
01113 }
01114 }
01115
01117
01118 CSurface &CSurface::operator= (const CSurface &rhs)
01119 {
01120 if (this != &rhs)
01121 {
01122 clear();
01123
01124 if (rhs.pixels)
01125 {
01126 size = rhs.size;
01127 width = rhs.width;
01128 height = rhs.height;
01129 depth = rhs.depth;
01130
01131 pixels = new char[size];
01132 memcpy(pixels, rhs.pixels, size);
01133 }
01134 }
01135
01136 return *this;
01137 }
01138
01140
01141 CSurface::~CSurface()
01142 {
01143 clear();
01144 }
01145
01147
01148 CSurface::operator char*()
01149 {
01150 return pixels;
01151 }
01152
01154
01155 void CSurface::create(int w, int h, int d, int imgsize)
01156 {
01157 clear();
01158
01159 width = w;
01160 height = h;
01161 depth = d;
01162 size = imgsize;
01163 pixels = new char[imgsize];
01164 }
01165
01167
01168 void CSurface::clear()
01169 {
01170 delete [] pixels;
01171 pixels = NULL;
01172 }