Guest User

Converting image to PVRTC using libPVRTC

a guest
Nov 26th, 2012
391
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "pvrtc.h" // libPVRTC
  2.  
  3. // Конвертируем изображение в формат PVRTC. Лучшее качество при quality = 4.
  4. Image ImageConvertArgbToPvrtc(const Image& img, unsigned int format, int quality)
  5. {
  6.     if ( !isPvrtcFormat(format) ) {
  7.         dbgfail("Not a PVRTC format: "+ utils::lexical_cast(format));
  8.         return Image();
  9.     }
  10.     // Конвертирование работает только из формата ARGB.
  11.     if ( img.GetPixelType() != PIXEL_TYPE_ARGB ) {
  12.         dbgfail("Not an ARGB image: "+ PixelTypeToString(img.GetPixelType()));
  13.         return Image();
  14.     }
  15.     // Изображение должно быть квадратное со сторонами, равными степени двойки.
  16.     if (img.w != Math::Pow2Ceil(img.w) || img.h != Math::Pow2Ceil(img.h) || img.w != img.h) {
  17.         dbgfail("Image sizes should be Pow2 and equal. Now w = "+ utils::lexical_cast(img.w) + ", h = " + utils::lexical_cast(img.h));
  18.         return Image();
  19.     }
  20.    
  21.     int bUse2bitFormat = (format == FORMAT_PVRTC2_RGB || format == FORMAT_PVRTC2_RGBA) ? 1 : 0;
  22.     int bMipMap = 0;
  23.     int w = img.w;
  24.     int h = img.h;
  25.     Assert(w == Math::Pow2Ceil(w) && h == Math::Pow2Ceil(h));
  26.    
  27.     int bin_sz = pvrtc_size(w, h, bMipMap, bUse2bitFormat);
  28.    
  29.     ImageData::Ref dst = ImageData::CreateRaw(w, h, bin_sz, format);
  30.     void * inputARGBData = img.Data();
  31.     void * outputCompressedData = dst->Data();
  32.    
  33.     int bAlphaOn = (format == FORMAT_PVRTC2_RGBA || format == FORMAT_PVRTC4_RGBA) ? 1 : 0;
  34.    
  35.     pvrtc_compress(inputARGBData, outputCompressedData, w, h, bMipMap, bAlphaOn, bUse2bitFormat, quality);
  36.    
  37.     return Image(dst);
  38. }
  39.  
  40. // Ну и вот так я записываю PVRTC в файл (возможно, не самый правильный способ).
  41.  
  42. void ImageData::WritePVRTC(const std::string& filename) const
  43. {
  44.     if (pixelType != PIXEL_TYPE_COMPRESSED) {
  45.         dbgfail("WritePVRTC: not a compressed data. pixelType = " + PixelTypeToString(pixelType));
  46.         return;
  47.     }
  48.  
  49.     struct {
  50.         uint32_t headerLength;
  51.         uint32_t height;
  52.         uint32_t width;
  53.         uint32_t mipmaps;
  54.         uint32_t flags;
  55.         uint32_t dataLength;
  56.         uint32_t bpp;
  57.         uint32_t bitmaskR;
  58.         uint32_t bitmaskG;
  59.         uint32_t bitmaskB;
  60.         uint32_t bitmaskA;
  61.         uint32_t PVR;
  62.         uint32_t surfaces;
  63.     } header;
  64.  
  65.     header.headerLength = sizeof(header);
  66.     header.height = h;
  67.     header.width = w;
  68.     header.mipmaps = 0;
  69.     header.flags = 0;
  70.     header.dataLength = dataSize;
  71.     header.bpp = 4;
  72.     header.bitmaskR = 1;
  73.     header.bitmaskG = 1;
  74.     header.bitmaskB = 1;
  75.     header.bitmaskA = 1;
  76.     header.PVR = 0x21525650;
  77.     header.surfaces = 1;
  78.  
  79.     switch (compressedFormat) {
  80.         case FORMAT_PVRTC2_RGB:
  81.             header.flags = 0x18; // OGL_PVRTC2
  82.             header.bitmaskA = 0;
  83.             break;
  84.         case FORMAT_PVRTC2_RGBA:
  85.             header.flags = 0x18; // OGL_PVRTC2
  86.             header.bitmaskA = 1;
  87.             break;
  88.         case FORMAT_PVRTC4_RGB:
  89.             header.flags = 0x19; // OGL_PVRTC4
  90.             header.bitmaskA = 0;
  91.             break;
  92.         case FORMAT_PVRTC4_RGBA:
  93.             header.flags = 0x19; // OGL_PVRTC4
  94.             header.bitmaskA = 1;
  95.             break;
  96.         default:
  97.             dbgfail("Unknown compressed format "+ utils::lexical_cast(compressedFormat));
  98.             return;
  99.     }
  100.  
  101.     header.flags |= 0x10000; // For PVRTexTool to know that image is flipped.
  102.  
  103.     File::c_file f;
  104.     f.open_to_write(filename);
  105.     if (!f.is_open()) { dbgfail("LoadPVRTC: Can't open file '"+ filename +"'."); }
  106.     f.write(&header, sizeof(header));
  107.     f.write(data, dataSize);
  108.     f.close();
  109. }
  110.  
  111. // Ну и немного определений, которые выше использовались.
  112.  
  113. #define FORMAT_PVRTC4_RGB  0x8c00
  114. #define FORMAT_PVRTC2_RGB  0x8C01
  115. #define FORMAT_PVRTC4_RGBA 0x8C02
  116. #define FORMAT_PVRTC2_RGBA 0x8C03
  117.  
  118. inline bool isPvrtcFormat(unsigned int format)
  119. {
  120.     return (   format == FORMAT_PVRTC4_RGB
  121.             || format == FORMAT_PVRTC2_RGB
  122.             || format == FORMAT_PVRTC4_RGBA
  123.             || format == FORMAT_PVRTC2_RGBA
  124.         );
  125. }
RAW Paste Data