CmPixelUtil.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. #include "CmPixelUtil.h"
  2. #include "CmBitwise.h"
  3. #include "CmColor.h"
  4. #include "CmException.h"
  5. namespace BansheeEngine {
  6. //-----------------------------------------------------------------------
  7. /**
  8. * Resamplers
  9. */
  10. // variable name hints:
  11. // sx_48 = 16/48-bit fixed-point x-position in source
  12. // stepx = difference between adjacent sx_48 values
  13. // sx1 = lower-bound integer x-position in source
  14. // sx2 = upper-bound integer x-position in source
  15. // sxf = fractional weight beween sx1 and sx2
  16. // x,y,z = location of output pixel in destination
  17. // nearest-neighbor resampler, does not convert formats.
  18. // templated on bytes-per-pixel to allow compiler optimizations, such
  19. // as simplifying memcpy() and replacing multiplies with bitshifts
  20. template<unsigned int elemsize> struct NearestResampler {
  21. static void scale(const PixelData& src, const PixelData& dst) {
  22. // assert(src.format == dst.format);
  23. // srcdata stays at beginning, pdst is a moving pointer
  24. UINT8* srcdata = (UINT8*)src.getData();
  25. UINT8* pdst = (UINT8*)dst.getData();
  26. // sx_48,sy_48,sz_48 represent current position in source
  27. // using 16/48-bit fixed precision, incremented by steps
  28. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  29. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  30. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  31. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  32. // for the center of the destination pixel, not the top-left corner
  33. UINT64 sz_48 = (stepz >> 1) - 1;
  34. for (size_t z = dst.getFront(); z < dst.getBack(); z++, sz_48 += stepz) {
  35. size_t srczoff = (size_t)(sz_48 >> 48) * src.getSlicePitch();
  36. UINT64 sy_48 = (stepy >> 1) - 1;
  37. for (size_t y = dst.getTop(); y < dst.getBottom(); y++, sy_48 += stepy) {
  38. size_t srcyoff = (size_t)(sy_48 >> 48) * src.getRowPitch();
  39. UINT64 sx_48 = (stepx >> 1) - 1;
  40. for (size_t x = dst.getLeft(); x < dst.getRight(); x++, sx_48 += stepx) {
  41. UINT8* psrc = srcdata +
  42. elemsize*((size_t)(sx_48 >> 48) + srcyoff + srczoff);
  43. memcpy(pdst, psrc, elemsize);
  44. pdst += elemsize;
  45. }
  46. pdst += elemsize*dst.getRowSkip();
  47. }
  48. pdst += elemsize*dst.getSliceSkip();
  49. }
  50. }
  51. };
  52. // default floating-point linear resampler, does format conversion
  53. struct LinearResampler {
  54. static void scale(const PixelData& src, const PixelData& dst) {
  55. size_t srcelemsize = PixelUtil::getNumElemBytes(src.getFormat());
  56. size_t dstelemsize = PixelUtil::getNumElemBytes(dst.getFormat());
  57. // srcdata stays at beginning, pdst is a moving pointer
  58. UINT8* srcdata = (UINT8*)src.getData();
  59. UINT8* pdst = (UINT8*)dst.getData();
  60. // sx_48,sy_48,sz_48 represent current position in source
  61. // using 16/48-bit fixed precision, incremented by steps
  62. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  63. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  64. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  65. // temp is 16/16 bit fixed precision, used to adjust a source
  66. // coordinate (x, y, or z) backwards by half a pixel so that the
  67. // integer bits represent the first sample (eg, sx1) and the
  68. // fractional bits are the blend weight of the second sample
  69. unsigned int temp;
  70. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  71. // for the center of the destination pixel, not the top-left corner
  72. UINT64 sz_48 = (stepz >> 1) - 1;
  73. for (size_t z = dst.getFront(); z < dst.getBack(); z++, sz_48+=stepz) {
  74. temp = static_cast<unsigned int>(sz_48 >> 32);
  75. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  76. size_t sz1 = temp >> 16; // src z, sample #1
  77. size_t sz2 = std::min(sz1+1,(size_t)src.getDepth()-1);// src z, sample #2
  78. float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
  79. UINT64 sy_48 = (stepy >> 1) - 1;
  80. for (size_t y = dst.getTop(); y < dst.getBottom(); y++, sy_48+=stepy) {
  81. temp = static_cast<unsigned int>(sy_48 >> 32);
  82. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  83. size_t sy1 = temp >> 16; // src y #1
  84. size_t sy2 = std::min(sy1+1,(size_t)src.getHeight()-1);// src y #2
  85. float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
  86. UINT64 sx_48 = (stepx >> 1) - 1;
  87. for (size_t x = dst.getLeft(); x < dst.getRight(); x++, sx_48+=stepx) {
  88. temp = static_cast<unsigned int>(sx_48 >> 32);
  89. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  90. size_t sx1 = temp >> 16; // src x #1
  91. size_t sx2 = std::min(sx1+1,(size_t)src.getWidth()-1);// src x #2
  92. float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
  93. Color x1y1z1, x2y1z1, x1y2z1, x2y2z1;
  94. Color x1y1z2, x2y1z2, x1y2z2, x2y2z2;
  95. #define UNPACK(dst,x,y,z) PixelUtil::unpackColour(&dst, src.getFormat(), \
  96. srcdata + srcelemsize*((x)+(y)*src.getRowPitch()+(z)*src.getSlicePitch()))
  97. UNPACK(x1y1z1,sx1,sy1,sz1); UNPACK(x2y1z1,sx2,sy1,sz1);
  98. UNPACK(x1y2z1,sx1,sy2,sz1); UNPACK(x2y2z1,sx2,sy2,sz1);
  99. UNPACK(x1y1z2,sx1,sy1,sz2); UNPACK(x2y1z2,sx2,sy1,sz2);
  100. UNPACK(x1y2z2,sx1,sy2,sz2); UNPACK(x2y2z2,sx2,sy2,sz2);
  101. #undef UNPACK
  102. Color accum =
  103. x1y1z1 * ((1.0f - sxf)*(1.0f - syf)*(1.0f - szf)) +
  104. x2y1z1 * ( sxf *(1.0f - syf)*(1.0f - szf)) +
  105. x1y2z1 * ((1.0f - sxf)* syf *(1.0f - szf)) +
  106. x2y2z1 * ( sxf * syf *(1.0f - szf)) +
  107. x1y1z2 * ((1.0f - sxf)*(1.0f - syf)* szf ) +
  108. x2y1z2 * ( sxf *(1.0f - syf)* szf ) +
  109. x1y2z2 * ((1.0f - sxf)* syf * szf ) +
  110. x2y2z2 * ( sxf * syf * szf );
  111. PixelUtil::packColour(accum, dst.getFormat(), pdst);
  112. pdst += dstelemsize;
  113. }
  114. pdst += dstelemsize*dst.getRowSkip();
  115. }
  116. pdst += dstelemsize*dst.getSliceSkip();
  117. }
  118. }
  119. };
  120. // float32 linear resampler, converts FLOAT32_RGB/FLOAT32_RGBA only.
  121. // avoids overhead of pixel unpack/repack function calls
  122. struct LinearResampler_Float32 {
  123. static void scale(const PixelData& src, const PixelData& dst) {
  124. size_t srcchannels = PixelUtil::getNumElemBytes(src.getFormat()) / sizeof(float);
  125. size_t dstchannels = PixelUtil::getNumElemBytes(dst.getFormat()) / sizeof(float);
  126. // assert(srcchannels == 3 || srcchannels == 4);
  127. // assert(dstchannels == 3 || dstchannels == 4);
  128. // srcdata stays at beginning, pdst is a moving pointer
  129. float* srcdata = (float*)src.getData();
  130. float* pdst = (float*)dst.getData();
  131. // sx_48,sy_48,sz_48 represent current position in source
  132. // using 16/48-bit fixed precision, incremented by steps
  133. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  134. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  135. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  136. // temp is 16/16 bit fixed precision, used to adjust a source
  137. // coordinate (x, y, or z) backwards by half a pixel so that the
  138. // integer bits represent the first sample (eg, sx1) and the
  139. // fractional bits are the blend weight of the second sample
  140. unsigned int temp;
  141. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  142. // for the center of the destination pixel, not the top-left corner
  143. UINT64 sz_48 = (stepz >> 1) - 1;
  144. for (size_t z = dst.getFront(); z < dst.getBack(); z++, sz_48+=stepz) {
  145. temp = static_cast<unsigned int>(sz_48 >> 32);
  146. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  147. size_t sz1 = temp >> 16; // src z, sample #1
  148. size_t sz2 = std::min(sz1+1,(size_t)src.getDepth()-1);// src z, sample #2
  149. float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
  150. UINT64 sy_48 = (stepy >> 1) - 1;
  151. for (size_t y = dst.getTop(); y < dst.getBottom(); y++, sy_48+=stepy) {
  152. temp = static_cast<unsigned int>(sy_48 >> 32);
  153. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  154. size_t sy1 = temp >> 16; // src y #1
  155. size_t sy2 = std::min(sy1+1,(size_t)src.getHeight()-1);// src y #2
  156. float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
  157. UINT64 sx_48 = (stepx >> 1) - 1;
  158. for (size_t x = dst.getLeft(); x < dst.getRight(); x++, sx_48+=stepx) {
  159. temp = static_cast<unsigned int>(sx_48 >> 32);
  160. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  161. size_t sx1 = temp >> 16; // src x #1
  162. size_t sx2 = std::min(sx1+1,(size_t)src.getWidth()-1);// src x #2
  163. float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
  164. // process R,G,B,A simultaneously for cache coherence?
  165. float accum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  166. #define ACCUM3(x,y,z,factor) \
  167. { float f = factor; \
  168. size_t off = (x+y*src.getRowPitch()+z*src.getSlicePitch())*srcchannels; \
  169. accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
  170. accum[2]+=srcdata[off+2]*f; }
  171. #define ACCUM4(x,y,z,factor) \
  172. { float f = factor; \
  173. size_t off = (x+y*src.getRowPitch()+z*src.getSlicePitch())*srcchannels; \
  174. accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
  175. accum[2]+=srcdata[off+2]*f; accum[3]+=srcdata[off+3]*f; }
  176. if (srcchannels == 3 || dstchannels == 3) {
  177. // RGB, no alpha
  178. ACCUM3(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
  179. ACCUM3(sx2,sy1,sz1, sxf *(1.0f-syf)*(1.0f-szf));
  180. ACCUM3(sx1,sy2,sz1,(1.0f-sxf)* syf *(1.0f-szf));
  181. ACCUM3(sx2,sy2,sz1, sxf * syf *(1.0f-szf));
  182. ACCUM3(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)* szf );
  183. ACCUM3(sx2,sy1,sz2, sxf *(1.0f-syf)* szf );
  184. ACCUM3(sx1,sy2,sz2,(1.0f-sxf)* syf * szf );
  185. ACCUM3(sx2,sy2,sz2, sxf * syf * szf );
  186. accum[3] = 1.0f;
  187. } else {
  188. // RGBA
  189. ACCUM4(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
  190. ACCUM4(sx2,sy1,sz1, sxf *(1.0f-syf)*(1.0f-szf));
  191. ACCUM4(sx1,sy2,sz1,(1.0f-sxf)* syf *(1.0f-szf));
  192. ACCUM4(sx2,sy2,sz1, sxf * syf *(1.0f-szf));
  193. ACCUM4(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)* szf );
  194. ACCUM4(sx2,sy1,sz2, sxf *(1.0f-syf)* szf );
  195. ACCUM4(sx1,sy2,sz2,(1.0f-sxf)* syf * szf );
  196. ACCUM4(sx2,sy2,sz2, sxf * syf * szf );
  197. }
  198. memcpy(pdst, accum, sizeof(float)*dstchannels);
  199. #undef ACCUM3
  200. #undef ACCUM4
  201. pdst += dstchannels;
  202. }
  203. pdst += dstchannels*dst.getRowSkip();
  204. }
  205. pdst += dstchannels*dst.getSliceSkip();
  206. }
  207. }
  208. };
  209. // byte linear resampler, does not do any format conversions.
  210. // only handles pixel formats that use 1 byte per color channel.
  211. // 2D only; punts 3D pixelboxes to default LinearResampler (slow).
  212. // templated on bytes-per-pixel to allow compiler optimizations, such
  213. // as unrolling loops and replacing multiplies with bitshifts
  214. template<unsigned int channels> struct LinearResampler_Byte {
  215. static void scale(const PixelData& src, const PixelData& dst) {
  216. // assert(src.format == dst.format);
  217. // only optimized for 2D
  218. if (src.getDepth() > 1 || dst.getDepth() > 1) {
  219. LinearResampler::scale(src, dst);
  220. return;
  221. }
  222. // srcdata stays at beginning of slice, pdst is a moving pointer
  223. UINT8* srcdata = (UINT8*)src.getData();
  224. UINT8* pdst = (UINT8*)dst.getData();
  225. // sx_48,sy_48 represent current position in source
  226. // using 16/48-bit fixed precision, incremented by steps
  227. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  228. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  229. // bottom 28 bits of temp are 16/12 bit fixed precision, used to
  230. // adjust a source coordinate backwards by half a pixel so that the
  231. // integer bits represent the first sample (eg, sx1) and the
  232. // fractional bits are the blend weight of the second sample
  233. unsigned int temp;
  234. UINT64 sy_48 = (stepy >> 1) - 1;
  235. for (size_t y = dst.getTop(); y < dst.getBottom(); y++, sy_48+=stepy) {
  236. temp = static_cast<unsigned int>(sy_48 >> 36);
  237. temp = (temp > 0x800)? temp - 0x800: 0;
  238. unsigned int syf = temp & 0xFFF;
  239. size_t sy1 = temp >> 12;
  240. size_t sy2 = std::min(sy1+1, (size_t)src.getBottom()-src.getTop()-1);
  241. size_t syoff1 = sy1 * src.getRowPitch();
  242. size_t syoff2 = sy2 * src.getRowPitch();
  243. UINT64 sx_48 = (stepx >> 1) - 1;
  244. for (size_t x = dst.getLeft(); x < dst.getRight(); x++, sx_48+=stepx) {
  245. temp = static_cast<unsigned int>(sx_48 >> 36);
  246. temp = (temp > 0x800)? temp - 0x800 : 0;
  247. unsigned int sxf = temp & 0xFFF;
  248. size_t sx1 = temp >> 12;
  249. size_t sx2 = std::min(sx1+1, (size_t)src.getRight()-src.getLeft()-1);
  250. unsigned int sxfsyf = sxf*syf;
  251. for (unsigned int k = 0; k < channels; k++) {
  252. unsigned int accum =
  253. srcdata[(sx1 + syoff1)*channels+k]*(0x1000000-(sxf<<12)-(syf<<12)+sxfsyf) +
  254. srcdata[(sx2 + syoff1)*channels+k]*((sxf<<12)-sxfsyf) +
  255. srcdata[(sx1 + syoff2)*channels+k]*((syf<<12)-sxfsyf) +
  256. srcdata[(sx2 + syoff2)*channels+k]*sxfsyf;
  257. // accum is computed using 8/24-bit fixed-point math
  258. // (maximum is 0xFF000000; rounding will not cause overflow)
  259. *pdst++ = static_cast<UINT8>((accum + 0x800000) >> 24);
  260. }
  261. }
  262. pdst += channels*dst.getRowSkip();
  263. }
  264. }
  265. };
  266. //-----------------------------------------------------------------------
  267. /**
  268. * A record that describes a pixel format in detail.
  269. */
  270. struct PixelFormatDescription {
  271. /* Name of the format, as in the enum */
  272. const char *name;
  273. /* Number of bytes one element (colour value) takes. */
  274. unsigned char elemBytes;
  275. /* Pixel format flags, see enum PixelFormatFlags for the bit field
  276. * definitions
  277. */
  278. UINT32 flags;
  279. /** Component type
  280. */
  281. PixelComponentType componentType;
  282. /** Component count
  283. */
  284. unsigned char componentCount;
  285. /* Number of bits for red(or luminance), green, blue, alpha
  286. */
  287. unsigned char rbits,gbits,bbits,abits; /*, ibits, dbits, ... */
  288. /* Masks and shifts as used by packers/unpackers */
  289. UINT32 rmask, gmask, bmask, amask;
  290. unsigned char rshift, gshift, bshift, ashift;
  291. };
  292. //-----------------------------------------------------------------------
  293. /** Pixel format database */
  294. PixelFormatDescription _pixelFormats[PF_COUNT] = {
  295. //-----------------------------------------------------------------------
  296. {"PF_UNKNOWN",
  297. /* Bytes per element */
  298. 0,
  299. /* Flags */
  300. 0,
  301. /* Component type and count */
  302. PCT_BYTE, 0,
  303. /* rbits, gbits, bbits, abits */
  304. 0, 0, 0, 0,
  305. /* Masks and shifts */
  306. 0, 0, 0, 0, 0, 0, 0, 0
  307. },
  308. //-----------------------------------------------------------------------
  309. {"PF_R8",
  310. /* Bytes per element */
  311. 1,
  312. /* Flags */
  313. 0,
  314. /* Component type and count */
  315. PCT_BYTE, 1,
  316. /* rbits, gbits, bbits, abits */
  317. 8, 0, 0, 0,
  318. /* Masks and shifts */
  319. 0x000000FF, 0, 0, 0,
  320. 0, 0, 0, 0
  321. },
  322. //-----------------------------------------------------------------------
  323. {"PF_R8G8",
  324. /* Bytes per element */
  325. 2,
  326. /* Flags */
  327. 0,
  328. /* Component type and count */
  329. PCT_BYTE, 2,
  330. /* rbits, gbits, bbits, abits */
  331. 8, 8, 0, 0,
  332. /* Masks and shifts */
  333. 0x000000FF, 0x0000FF00, 0, 0,
  334. 0, 8, 0, 0
  335. },
  336. //-----------------------------------------------------------------------
  337. {"PF_R8G8B8",
  338. /* Bytes per element */
  339. 3, // 24 bit integer -- special
  340. /* Flags */
  341. PFF_NATIVEENDIAN,
  342. /* Component type and count */
  343. PCT_BYTE, 3,
  344. /* rbits, gbits, bbits, abits */
  345. 8, 8, 8, 0,
  346. /* Masks and shifts */
  347. 0x000000FF, 0x0000FF00, 0x00FF0000, 0,
  348. 0, 8, 16, 0
  349. },
  350. //-----------------------------------------------------------------------
  351. {"PF_B8G8R8",
  352. /* Bytes per element */
  353. 3, // 24 bit integer -- special
  354. /* Flags */
  355. PFF_NATIVEENDIAN,
  356. /* Component type and count */
  357. PCT_BYTE, 3,
  358. /* rbits, gbits, bbits, abits */
  359. 8, 8, 8, 0,
  360. /* Masks and shifts */
  361. 0x00FF0000, 0x0000FF00, 0x000000FF, 0,
  362. 16, 8, 0, 0
  363. },
  364. //-----------------------------------------------------------------------
  365. {"PF_A8R8G8B8",
  366. /* Bytes per element */
  367. 4,
  368. /* Flags */
  369. PFF_HASALPHA | PFF_NATIVEENDIAN,
  370. /* Component type and count */
  371. PCT_BYTE, 4,
  372. /* rbits, gbits, bbits, abits */
  373. 8, 8, 8, 8,
  374. /* Masks and shifts */
  375. 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF,
  376. 8, 16, 24, 0
  377. },
  378. //-----------------------------------------------------------------------
  379. {"PF_A8B8G8R8",
  380. /* Bytes per element */
  381. 4,
  382. /* Flags */
  383. PFF_HASALPHA | PFF_NATIVEENDIAN,
  384. /* Component type and count */
  385. PCT_BYTE, 4,
  386. /* rbits, gbits, bbits, abits */
  387. 8, 8, 8, 8,
  388. /* Masks and shifts */
  389. 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
  390. 24, 16, 8, 0,
  391. },
  392. //-----------------------------------------------------------------------
  393. {"PF_B8G8R8A8",
  394. /* Bytes per element */
  395. 4,
  396. /* Flags */
  397. PFF_HASALPHA | PFF_NATIVEENDIAN,
  398. /* Component type and count */
  399. PCT_BYTE, 4,
  400. /* rbits, gbits, bbits, abits */
  401. 8, 8, 8, 8,
  402. /* Masks and shifts */
  403. 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
  404. 16, 8, 0, 24
  405. },
  406. //-----------------------------------------------------------------------
  407. {"PF_R8G8B8A8",
  408. /* Bytes per element */
  409. 4,
  410. /* Flags */
  411. PFF_HASALPHA | PFF_NATIVEENDIAN,
  412. /* Component type and count */
  413. PCT_BYTE, 4,
  414. /* rbits, gbits, bbits, abits */
  415. 8, 8, 8, 8,
  416. /* Masks and shifts */
  417. 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
  418. 0, 8, 16, 24
  419. },
  420. //-----------------------------------------------------------------------
  421. {"PF_X8R8G8B8",
  422. /* Bytes per element */
  423. 4,
  424. /* Flags */
  425. PFF_NATIVEENDIAN,
  426. /* Component type and count */
  427. PCT_BYTE, 3,
  428. /* rbits, gbits, bbits, abits */
  429. 8, 8, 8, 0,
  430. /* Masks and shifts */
  431. 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF,
  432. 8, 16, 24, 0
  433. },
  434. //-----------------------------------------------------------------------
  435. {"PF_X8B8G8R8",
  436. /* Bytes per element */
  437. 4,
  438. /* Flags */
  439. PFF_NATIVEENDIAN,
  440. /* Component type and count */
  441. PCT_BYTE, 3,
  442. /* rbits, gbits, bbits, abits */
  443. 8, 8, 8, 0,
  444. /* Masks and shifts */
  445. 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
  446. 24, 16, 8, 0
  447. },
  448. //-----------------------------------------------------------------------
  449. {"PF_R8G8B8X8",
  450. /* Bytes per element */
  451. 4,
  452. /* Flags */
  453. PFF_HASALPHA | PFF_NATIVEENDIAN,
  454. /* Component type and count */
  455. PCT_BYTE, 3,
  456. /* rbits, gbits, bbits, abits */
  457. 8, 8, 8, 0,
  458. /* Masks and shifts */
  459. 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
  460. 0, 8, 16, 0
  461. },
  462. //-----------------------------------------------------------------------
  463. {"PF_B8G8R8X8",
  464. /* Bytes per element */
  465. 4,
  466. /* Flags */
  467. PFF_HASALPHA | PFF_NATIVEENDIAN,
  468. /* Component type and count */
  469. PCT_BYTE, 3,
  470. /* rbits, gbits, bbits, abits */
  471. 8, 8, 8, 0,
  472. /* Masks and shifts */
  473. 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
  474. 16, 8, 0, 0
  475. },
  476. //-----------------------------------------------------------------------
  477. {"PF_DXT1",
  478. /* Bytes per element */
  479. 0,
  480. /* Flags */
  481. PFF_COMPRESSED | PFF_HASALPHA,
  482. /* Component type and count */
  483. PCT_BYTE, 3, // No alpha
  484. /* rbits, gbits, bbits, abits */
  485. 0, 0, 0, 0,
  486. /* Masks and shifts */
  487. 0, 0, 0, 0, 0, 0, 0, 0
  488. },
  489. //-----------------------------------------------------------------------
  490. {"PF_DXT2",
  491. /* Bytes per element */
  492. 0,
  493. /* Flags */
  494. PFF_COMPRESSED | PFF_HASALPHA,
  495. /* Component type and count */
  496. PCT_BYTE, 4,
  497. /* rbits, gbits, bbits, abits */
  498. 0, 0, 0, 0,
  499. /* Masks and shifts */
  500. 0, 0, 0, 0, 0, 0, 0, 0
  501. },
  502. //-----------------------------------------------------------------------
  503. {"PF_DXT3",
  504. /* Bytes per element */
  505. 0,
  506. /* Flags */
  507. PFF_COMPRESSED | PFF_HASALPHA,
  508. /* Component type and count */
  509. PCT_BYTE, 4,
  510. /* rbits, gbits, bbits, abits */
  511. 0, 0, 0, 0,
  512. /* Masks and shifts */
  513. 0, 0, 0, 0, 0, 0, 0, 0
  514. },
  515. //-----------------------------------------------------------------------
  516. {"PF_DXT4",
  517. /* Bytes per element */
  518. 0,
  519. /* Flags */
  520. PFF_COMPRESSED | PFF_HASALPHA,
  521. /* Component type and count */
  522. PCT_BYTE, 4,
  523. /* rbits, gbits, bbits, abits */
  524. 0, 0, 0, 0,
  525. /* Masks and shifts */
  526. 0, 0, 0, 0, 0, 0, 0, 0
  527. },
  528. //-----------------------------------------------------------------------
  529. {"PF_DXT5",
  530. /* Bytes per element */
  531. 0,
  532. /* Flags */
  533. PFF_COMPRESSED | PFF_HASALPHA,
  534. /* Component type and count */
  535. PCT_BYTE, 4,
  536. /* rbits, gbits, bbits, abits */
  537. 0, 0, 0, 0,
  538. /* Masks and shifts */
  539. 0, 0, 0, 0, 0, 0, 0, 0
  540. },
  541. //-----------------------------------------------------------------------
  542. {"PF_FLOAT16_R",
  543. /* Bytes per element */
  544. 2,
  545. /* Flags */
  546. PFF_FLOAT,
  547. /* Component type and count */
  548. PCT_FLOAT16, 1,
  549. /* rbits, gbits, bbits, abits */
  550. 16, 0, 0, 0,
  551. /* Masks and shifts */
  552. 0, 0, 0, 0, 0, 0, 0, 0
  553. },
  554. //-----------------------------------------------------------------------
  555. {"PF_FLOAT16_RG",
  556. /* Bytes per element */
  557. 4,
  558. /* Flags */
  559. PFF_FLOAT,
  560. /* Component type and count */
  561. PCT_FLOAT16, 2,
  562. /* rbits, gbits, bbits, abits */
  563. 16, 16, 0, 0,
  564. /* Masks and shifts */
  565. 0, 0, 0, 0, 0, 0, 0, 0
  566. },
  567. //-----------------------------------------------------------------------
  568. {"PF_FLOAT16_RGB",
  569. /* Bytes per element */
  570. 6,
  571. /* Flags */
  572. PFF_FLOAT,
  573. /* Component type and count */
  574. PCT_FLOAT16, 3,
  575. /* rbits, gbits, bbits, abits */
  576. 16, 16, 16, 0,
  577. /* Masks and shifts */
  578. 0, 0, 0, 0, 0, 0, 0, 0
  579. },
  580. //-----------------------------------------------------------------------
  581. {"PF_FLOAT16_RGBA",
  582. /* Bytes per element */
  583. 8,
  584. /* Flags */
  585. PFF_FLOAT | PFF_HASALPHA,
  586. /* Component type and count */
  587. PCT_FLOAT16, 4,
  588. /* rbits, gbits, bbits, abits */
  589. 16, 16, 16, 16,
  590. /* Masks and shifts */
  591. 0, 0, 0, 0, 0, 0, 0, 0
  592. },
  593. //-----------------------------------------------------------------------
  594. {"PF_FLOAT32_R",
  595. /* Bytes per element */
  596. 4,
  597. /* Flags */
  598. PFF_FLOAT,
  599. /* Component type and count */
  600. PCT_FLOAT32, 1,
  601. /* rbits, gbits, bbits, abits */
  602. 32, 0, 0, 0,
  603. /* Masks and shifts */
  604. 0, 0, 0, 0, 0, 0, 0, 0
  605. },
  606. //-----------------------------------------------------------------------
  607. {"PF_FLOAT32_RG",
  608. /* Bytes per element */
  609. 8,
  610. /* Flags */
  611. PFF_FLOAT,
  612. /* Component type and count */
  613. PCT_FLOAT32, 2,
  614. /* rbits, gbits, bbits, abits */
  615. 32, 32, 0, 0,
  616. /* Masks and shifts */
  617. 0, 0, 0, 0, 0, 0, 0, 0
  618. },
  619. //-----------------------------------------------------------------------
  620. {"PF_FLOAT32_RGB",
  621. /* Bytes per element */
  622. 12,
  623. /* Flags */
  624. PFF_FLOAT,
  625. /* Component type and count */
  626. PCT_FLOAT32, 3,
  627. /* rbits, gbits, bbits, abits */
  628. 32, 32, 32, 0,
  629. /* Masks and shifts */
  630. 0, 0, 0, 0, 0, 0, 0, 0
  631. },
  632. //-----------------------------------------------------------------------
  633. {"PF_FLOAT32_RGBA",
  634. /* Bytes per element */
  635. 16,
  636. /* Flags */
  637. PFF_FLOAT | PFF_HASALPHA,
  638. /* Component type and count */
  639. PCT_FLOAT32, 4,
  640. /* rbits, gbits, bbits, abits */
  641. 32, 32, 32, 32,
  642. /* Masks and shifts */
  643. 0, 0, 0, 0, 0, 0, 0, 0
  644. },
  645. //-----------------------------------------------------------------------
  646. {"PF_D32_S8X24",
  647. /* Bytes per element */
  648. 4,
  649. /* Flags */
  650. PFF_DEPTH | PFF_FLOAT,
  651. /* Component type and count */
  652. PCT_FLOAT32, 1,
  653. /* rbits, gbits, bbits, abits */
  654. 0, 0, 0, 0,
  655. /* Masks and shifts */
  656. 0, 0, 0, 0, 0, 0, 0, 0
  657. },
  658. //-----------------------------------------------------------------------
  659. {"PF_D24_S8",
  660. /* Bytes per element */
  661. 8,
  662. /* Flags */
  663. PFF_DEPTH | PFF_FLOAT,
  664. /* Component type and count */
  665. PCT_FLOAT32, 2,
  666. /* rbits, gbits, bbits, abits */
  667. 0, 0, 0, 0,
  668. /* Masks and shifts */
  669. 0, 0, 0, 0, 0, 0, 0, 0
  670. },
  671. //-----------------------------------------------------------------------
  672. {"PF_D32",
  673. /* Bytes per element */
  674. 4,
  675. /* Flags */
  676. PFF_DEPTH | PFF_FLOAT,
  677. /* Component type and count */
  678. PCT_FLOAT32, 1,
  679. /* rbits, gbits, bbits, abits */
  680. 0, 0, 0, 0,
  681. /* Masks and shifts */
  682. 0, 0, 0, 0, 0, 0, 0, 0
  683. },
  684. //-----------------------------------------------------------------------
  685. {"PF_D16",
  686. /* Bytes per element */
  687. 2,
  688. /* Flags */
  689. PFF_DEPTH | PFF_FLOAT,
  690. /* Component type and count */
  691. PCT_FLOAT16, 1,
  692. /* rbits, gbits, bbits, abits */
  693. 0, 0, 0, 0,
  694. /* Masks and shifts */
  695. 0, 0, 0, 0, 0, 0, 0, 0
  696. },
  697. };
  698. //-----------------------------------------------------------------------
  699. /**
  700. * Directly get the description record for provided pixel format. For debug builds,
  701. * this checks the bounds of fmt with an assertion.
  702. */
  703. static inline const PixelFormatDescription &getDescriptionFor(const PixelFormat fmt)
  704. {
  705. const int ord = (int)fmt;
  706. assert(ord>=0 && ord<PF_COUNT);
  707. return _pixelFormats[ord];
  708. }
  709. //-----------------------------------------------------------------------
  710. UINT32 PixelUtil::getNumElemBytes( PixelFormat format )
  711. {
  712. return getDescriptionFor(format).elemBytes;
  713. }
  714. //-----------------------------------------------------------------------
  715. UINT32 PixelUtil::getMemorySize(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
  716. {
  717. if(isCompressed(format))
  718. {
  719. switch(format)
  720. {
  721. // DXT formats work by dividing the image into 4x4 blocks, then encoding each
  722. // 4x4 block with a certain number of bytes.
  723. case PF_DXT1:
  724. return ((width+3)/4)*((height+3)/4)*8 * depth;
  725. case PF_DXT2:
  726. case PF_DXT3:
  727. case PF_DXT4:
  728. case PF_DXT5:
  729. return ((width+3)/4)*((height+3)/4)*16 * depth;
  730. default:
  731. CM_EXCEPT(InvalidParametersException, "Invalid compressed pixel format");
  732. }
  733. }
  734. else
  735. {
  736. return width*height*depth*getNumElemBytes(format);
  737. }
  738. }
  739. //-----------------------------------------------------------------------
  740. UINT32 PixelUtil::getNumElemBits( PixelFormat format )
  741. {
  742. return getDescriptionFor(format).elemBytes * 8;
  743. }
  744. //-----------------------------------------------------------------------
  745. unsigned int PixelUtil::getFlags( PixelFormat format )
  746. {
  747. return getDescriptionFor(format).flags;
  748. }
  749. //-----------------------------------------------------------------------
  750. bool PixelUtil::hasAlpha(PixelFormat format)
  751. {
  752. return (PixelUtil::getFlags(format) & PFF_HASALPHA) > 0;
  753. }
  754. //-----------------------------------------------------------------------
  755. bool PixelUtil::isFloatingPoint(PixelFormat format)
  756. {
  757. return (PixelUtil::getFlags(format) & PFF_FLOAT) > 0;
  758. }
  759. //-----------------------------------------------------------------------
  760. bool PixelUtil::isCompressed(PixelFormat format)
  761. {
  762. return (PixelUtil::getFlags(format) & PFF_COMPRESSED) > 0;
  763. }
  764. //-----------------------------------------------------------------------
  765. bool PixelUtil::isDepth(PixelFormat format)
  766. {
  767. return (PixelUtil::getFlags(format) & PFF_DEPTH) > 0;
  768. }
  769. //-----------------------------------------------------------------------
  770. bool PixelUtil::isNativeEndian(PixelFormat format)
  771. {
  772. return (PixelUtil::getFlags(format) & PFF_NATIVEENDIAN) > 0;
  773. }
  774. //-----------------------------------------------------------------------
  775. bool PixelUtil::isValidExtent(size_t width, size_t height, size_t depth, PixelFormat format)
  776. {
  777. if(isCompressed(format))
  778. {
  779. switch(format)
  780. {
  781. case PF_DXT1:
  782. case PF_DXT2:
  783. case PF_DXT3:
  784. case PF_DXT4:
  785. case PF_DXT5:
  786. return ((width&3)==0 && (height&3)==0 && depth==1);
  787. default:
  788. return true;
  789. }
  790. }
  791. else
  792. {
  793. return true;
  794. }
  795. }
  796. //-----------------------------------------------------------------------
  797. void PixelUtil::getBitDepths(PixelFormat format, int rgba[4])
  798. {
  799. const PixelFormatDescription &des = getDescriptionFor(format);
  800. rgba[0] = des.rbits;
  801. rgba[1] = des.gbits;
  802. rgba[2] = des.bbits;
  803. rgba[3] = des.abits;
  804. }
  805. //-----------------------------------------------------------------------
  806. void PixelUtil::getBitMasks(PixelFormat format, UINT32 rgba[4])
  807. {
  808. const PixelFormatDescription &des = getDescriptionFor(format);
  809. rgba[0] = des.rmask;
  810. rgba[1] = des.gmask;
  811. rgba[2] = des.bmask;
  812. rgba[3] = des.amask;
  813. }
  814. //---------------------------------------------------------------------
  815. void PixelUtil::getBitShifts(PixelFormat format, unsigned char rgba[4])
  816. {
  817. const PixelFormatDescription &des = getDescriptionFor(format);
  818. rgba[0] = des.rshift;
  819. rgba[1] = des.gshift;
  820. rgba[2] = des.bshift;
  821. rgba[3] = des.ashift;
  822. }
  823. //-----------------------------------------------------------------------
  824. String PixelUtil::getFormatName(PixelFormat srcformat)
  825. {
  826. return getDescriptionFor(srcformat).name;
  827. }
  828. //-----------------------------------------------------------------------
  829. bool PixelUtil::isAccessible(PixelFormat srcformat)
  830. {
  831. if (srcformat == PF_UNKNOWN)
  832. return false;
  833. unsigned int flags = getFlags(srcformat);
  834. return !((flags & PFF_COMPRESSED) || (flags & PFF_DEPTH));
  835. }
  836. //-----------------------------------------------------------------------
  837. PixelComponentType PixelUtil::getComponentType(PixelFormat fmt)
  838. {
  839. const PixelFormatDescription &des = getDescriptionFor(fmt);
  840. return des.componentType;
  841. }
  842. //-----------------------------------------------------------------------
  843. UINT32 PixelUtil::getComponentCount(PixelFormat fmt)
  844. {
  845. const PixelFormatDescription &des = getDescriptionFor(fmt);
  846. return des.componentCount;
  847. }
  848. //-----------------------------------------------------------------------
  849. PixelFormat PixelUtil::getFormatFromName(const String& name, bool accessibleOnly, bool caseSensitive)
  850. {
  851. String tmp = name;
  852. if (!caseSensitive)
  853. {
  854. // We are stored upper-case format names.
  855. StringUtil::toUpperCase(tmp);
  856. }
  857. for (int i = 0; i < PF_COUNT; ++i)
  858. {
  859. PixelFormat pf = static_cast<PixelFormat>(i);
  860. if (!accessibleOnly || isAccessible(pf))
  861. {
  862. if (tmp == getFormatName(pf))
  863. return pf;
  864. }
  865. }
  866. return PF_UNKNOWN;
  867. }
  868. //-----------------------------------------------------------------------
  869. String PixelUtil::getBNFExpressionOfPixelFormats(bool accessibleOnly)
  870. {
  871. // Collect format names sorted by length, it's required by BNF compiler
  872. // that similar tokens need longer ones comes first.
  873. typedef MultiMap<String::size_type, String> FormatNameMap;
  874. FormatNameMap formatNames;
  875. for (size_t i = 0; i < PF_COUNT; ++i)
  876. {
  877. PixelFormat pf = static_cast<PixelFormat>(i);
  878. if (!accessibleOnly || isAccessible(pf))
  879. {
  880. String formatName = getFormatName(pf);
  881. formatNames.insert(std::make_pair(formatName.length(), formatName));
  882. }
  883. }
  884. // Populate the BNF expression in reverse order
  885. String result;
  886. // Note: Stupid M$ VC7.1 can't dealing operator!= with FormatNameMap::const_reverse_iterator.
  887. for (FormatNameMap::reverse_iterator j = formatNames.rbegin(); j != formatNames.rend(); ++j)
  888. {
  889. if (!result.empty())
  890. result += " | ";
  891. result += "'" + j->second + "'";
  892. }
  893. return result;
  894. }
  895. UINT32 PixelUtil::getMaxMipmaps(UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
  896. {
  897. UINT32 count = 0;
  898. if((width > 0) && (height > 0))
  899. {
  900. do {
  901. if(width>1) width = width/2;
  902. if(height>1) height = height/2;
  903. if(depth>1) depth = depth/2;
  904. /*
  905. NOT needed, compressed formats will have mipmaps up to 1x1
  906. if(PixelUtil::isValidExtent(width, height, depth, format))
  907. count ++;
  908. else
  909. break;
  910. */
  911. count ++;
  912. } while(!(width == 1 && height == 1 && depth == 1));
  913. }
  914. return count;
  915. }
  916. //-----------------------------------------------------------------------
  917. /*************************************************************************
  918. * Pixel packing/unpacking utilities
  919. */
  920. void PixelUtil::packColour(const Color &colour, const PixelFormat pf, void* dest)
  921. {
  922. packColour(colour.r, colour.g, colour.b, colour.a, pf, dest);
  923. }
  924. //-----------------------------------------------------------------------
  925. void PixelUtil::packColour(const UINT8 r, const UINT8 g, const UINT8 b, const UINT8 a, const PixelFormat pf, void* dest)
  926. {
  927. const PixelFormatDescription &des = getDescriptionFor(pf);
  928. if(des.flags & PFF_NATIVEENDIAN) {
  929. // Shortcut for integer formats packing
  930. unsigned int value = ((Bitwise::fixedToFixed(r, 8, des.rbits)<<des.rshift) & des.rmask) |
  931. ((Bitwise::fixedToFixed(g, 8, des.gbits)<<des.gshift) & des.gmask) |
  932. ((Bitwise::fixedToFixed(b, 8, des.bbits)<<des.bshift) & des.bmask) |
  933. ((Bitwise::fixedToFixed(a, 8, des.abits)<<des.ashift) & des.amask);
  934. // And write to memory
  935. Bitwise::intWrite(dest, des.elemBytes, value);
  936. } else {
  937. // Convert to float
  938. packColour((float)r/255.0f,(float)g/255.0f,(float)b/255.0f,(float)a/255.0f, pf, dest);
  939. }
  940. }
  941. //-----------------------------------------------------------------------
  942. void PixelUtil::packColour(const float r, const float g, const float b, const float a, const PixelFormat pf, void* dest)
  943. {
  944. // Catch-it-all here
  945. const PixelFormatDescription &des = getDescriptionFor(pf);
  946. if(des.flags & PFF_NATIVEENDIAN) {
  947. // Do the packing
  948. //std::cerr << dest << " " << r << " " << g << " " << b << " " << a << std::endl;
  949. const unsigned int value = ((Bitwise::floatToFixed(r, des.rbits)<<des.rshift) & des.rmask) |
  950. ((Bitwise::floatToFixed(g, des.gbits)<<des.gshift) & des.gmask) |
  951. ((Bitwise::floatToFixed(b, des.bbits)<<des.bshift) & des.bmask) |
  952. ((Bitwise::floatToFixed(a, des.abits)<<des.ashift) & des.amask);
  953. // And write to memory
  954. Bitwise::intWrite(dest, des.elemBytes, value);
  955. } else {
  956. switch(pf)
  957. {
  958. case PF_FLOAT32_R:
  959. ((float*)dest)[0] = r;
  960. break;
  961. case PF_FLOAT32_RG:
  962. ((float*)dest)[0] = r;
  963. ((float*)dest)[1] = g;
  964. break;
  965. case PF_FLOAT32_RGB:
  966. ((float*)dest)[0] = r;
  967. ((float*)dest)[1] = g;
  968. ((float*)dest)[2] = b;
  969. break;
  970. case PF_FLOAT32_RGBA:
  971. ((float*)dest)[0] = r;
  972. ((float*)dest)[1] = g;
  973. ((float*)dest)[2] = b;
  974. ((float*)dest)[3] = a;
  975. break;
  976. case PF_FLOAT16_R:
  977. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  978. break;
  979. case PF_FLOAT16_RG:
  980. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  981. ((UINT16*)dest)[1] = Bitwise::floatToHalf(g);
  982. break;
  983. case PF_FLOAT16_RGB:
  984. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  985. ((UINT16*)dest)[1] = Bitwise::floatToHalf(g);
  986. ((UINT16*)dest)[2] = Bitwise::floatToHalf(b);
  987. break;
  988. case PF_FLOAT16_RGBA:
  989. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  990. ((UINT16*)dest)[1] = Bitwise::floatToHalf(g);
  991. ((UINT16*)dest)[2] = Bitwise::floatToHalf(b);
  992. ((UINT16*)dest)[3] = Bitwise::floatToHalf(a);
  993. break;
  994. case PF_R8G8:
  995. ((UINT8*)dest)[0] = (UINT8)Bitwise::floatToFixed(r, 8);
  996. ((UINT8*)dest)[1] = (UINT8)Bitwise::floatToFixed(g, 8);
  997. break;
  998. case PF_R8:
  999. ((UINT8*)dest)[0] = (UINT8)Bitwise::floatToFixed(r, 8);
  1000. break;
  1001. default:
  1002. // Not yet supported
  1003. CM_EXCEPT(NotImplementedException,
  1004. "pack to "+getFormatName(pf)+" not implemented");
  1005. break;
  1006. }
  1007. }
  1008. }
  1009. //-----------------------------------------------------------------------
  1010. void PixelUtil::unpackColour(Color *colour, PixelFormat pf, const void* src)
  1011. {
  1012. unpackColour(&colour->r, &colour->g, &colour->b, &colour->a, pf, src);
  1013. }
  1014. //-----------------------------------------------------------------------
  1015. void PixelUtil::unpackColour(UINT8 *r, UINT8 *g, UINT8 *b, UINT8 *a, PixelFormat pf, const void* src)
  1016. {
  1017. const PixelFormatDescription &des = getDescriptionFor(pf);
  1018. if(des.flags & PFF_NATIVEENDIAN) {
  1019. // Shortcut for integer formats unpacking
  1020. const unsigned int value = Bitwise::intRead(src, des.elemBytes);
  1021. *r = (UINT8)Bitwise::fixedToFixed((value & des.rmask)>>des.rshift, des.rbits, 8);
  1022. *g = (UINT8)Bitwise::fixedToFixed((value & des.gmask)>>des.gshift, des.gbits, 8);
  1023. *b = (UINT8)Bitwise::fixedToFixed((value & des.bmask)>>des.bshift, des.bbits, 8);
  1024. if(des.flags & PFF_HASALPHA)
  1025. {
  1026. *a = (UINT8)Bitwise::fixedToFixed((value & des.amask)>>des.ashift, des.abits, 8);
  1027. }
  1028. else
  1029. {
  1030. *a = 255; // No alpha, default a component to full
  1031. }
  1032. } else {
  1033. // Do the operation with the more generic floating point
  1034. float rr, gg, bb, aa;
  1035. unpackColour(&rr,&gg,&bb,&aa, pf, src);
  1036. *r = (UINT8)Bitwise::floatToFixed(rr, 8);
  1037. *g = (UINT8)Bitwise::floatToFixed(gg, 8);
  1038. *b = (UINT8)Bitwise::floatToFixed(bb, 8);
  1039. *a = (UINT8)Bitwise::floatToFixed(aa, 8);
  1040. }
  1041. }
  1042. //-----------------------------------------------------------------------
  1043. void PixelUtil::unpackColour(float *r, float *g, float *b, float *a,
  1044. PixelFormat pf, const void* src)
  1045. {
  1046. const PixelFormatDescription &des = getDescriptionFor(pf);
  1047. if(des.flags & PFF_NATIVEENDIAN) {
  1048. // Shortcut for integer formats unpacking
  1049. const unsigned int value = Bitwise::intRead(src, des.elemBytes);
  1050. *r = Bitwise::fixedToFloat((value & des.rmask)>>des.rshift, des.rbits);
  1051. *g = Bitwise::fixedToFloat((value & des.gmask)>>des.gshift, des.gbits);
  1052. *b = Bitwise::fixedToFloat((value & des.bmask)>>des.bshift, des.bbits);
  1053. if(des.flags & PFF_HASALPHA)
  1054. {
  1055. *a = Bitwise::fixedToFloat((value & des.amask)>>des.ashift, des.abits);
  1056. }
  1057. else
  1058. {
  1059. *a = 1.0f; // No alpha, default a component to full
  1060. }
  1061. } else {
  1062. switch(pf)
  1063. {
  1064. case PF_FLOAT32_R:
  1065. *r = *g = *b = ((float*)src)[0];
  1066. *a = 1.0f;
  1067. break;
  1068. case PF_FLOAT32_RG:
  1069. *r = ((float*)src)[0];
  1070. *g = *b = ((float*)src)[1];
  1071. *a = 1.0f;
  1072. break;
  1073. case PF_FLOAT32_RGB:
  1074. *r = ((float*)src)[0];
  1075. *g = ((float*)src)[1];
  1076. *b = ((float*)src)[2];
  1077. *a = 1.0f;
  1078. break;
  1079. case PF_FLOAT32_RGBA:
  1080. *r = ((float*)src)[0];
  1081. *g = ((float*)src)[1];
  1082. *b = ((float*)src)[2];
  1083. *a = ((float*)src)[3];
  1084. break;
  1085. case PF_FLOAT16_R:
  1086. *r = *g = *b = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1087. *a = 1.0f;
  1088. break;
  1089. case PF_FLOAT16_RG:
  1090. *r = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1091. *g = *b = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1092. *a = 1.0f;
  1093. break;
  1094. case PF_FLOAT16_RGB:
  1095. *r = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1096. *g = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1097. *b = Bitwise::halfToFloat(((UINT16*)src)[2]);
  1098. *a = 1.0f;
  1099. break;
  1100. case PF_FLOAT16_RGBA:
  1101. *r = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1102. *g = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1103. *b = Bitwise::halfToFloat(((UINT16*)src)[2]);
  1104. *a = Bitwise::halfToFloat(((UINT16*)src)[3]);
  1105. break;
  1106. case PF_R8G8:
  1107. *r = Bitwise::fixedToFloat(((UINT8*)src)[0], 8);
  1108. *g = Bitwise::fixedToFloat(((UINT8*)src)[1], 8);
  1109. *b = 0.0f;
  1110. *a = 1.0f;
  1111. break;
  1112. case PF_R8:
  1113. *r = Bitwise::fixedToFloat(((UINT8*)src)[0], 8);
  1114. *g = 0.0f;
  1115. *b = 0.0f;
  1116. *a = 1.0f;
  1117. break;
  1118. default:
  1119. // Not yet supported
  1120. CM_EXCEPT(NotImplementedException,
  1121. "unpack from "+getFormatName(pf)+" not implemented");
  1122. break;
  1123. }
  1124. }
  1125. }
  1126. //-----------------------------------------------------------------------
  1127. void PixelUtil::bulkPixelConversion(const PixelData &src, const PixelData &dst)
  1128. {
  1129. assert(src.getWidth() == dst.getWidth() &&
  1130. src.getHeight() == dst.getHeight() &&
  1131. src.getDepth() == dst.getDepth());
  1132. // Check for compressed formats, we don't support decompression, compression or recoding
  1133. if(PixelUtil::isCompressed(src.getFormat()) || PixelUtil::isCompressed(dst.getFormat()))
  1134. {
  1135. if(src.getFormat() == dst.getFormat())
  1136. {
  1137. memcpy(dst.getData(), src.getData(), src.getConsecutiveSize());
  1138. return;
  1139. }
  1140. else
  1141. {
  1142. CM_EXCEPT(NotImplementedException, "This method can not be used to compress or decompress images");
  1143. }
  1144. }
  1145. // The easy case
  1146. if(src.getFormat() == dst.getFormat()) {
  1147. // Everything consecutive?
  1148. if(src.isConsecutive() && dst.isConsecutive())
  1149. {
  1150. memcpy(dst.getData(), src.getData(), src.getConsecutiveSize());
  1151. return;
  1152. }
  1153. const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.getFormat());
  1154. const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.getFormat());
  1155. UINT8 *srcptr = static_cast<UINT8*>(src.getData())
  1156. + (src.getLeft() + src.getTop() * src.getRowPitch() + src.getFront() * src.getSlicePitch()) * srcPixelSize;
  1157. UINT8 *dstptr = static_cast<UINT8*>(dst.getData())
  1158. + (dst.getLeft() + dst.getTop() * dst.getRowPitch() + dst.getFront() * dst.getSlicePitch()) * dstPixelSize;
  1159. // Calculate pitches+skips in bytes
  1160. const size_t srcRowPitchBytes = src.getRowPitch()*srcPixelSize;
  1161. //const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
  1162. const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
  1163. const size_t dstRowPitchBytes = dst.getRowPitch()*dstPixelSize;
  1164. //const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
  1165. const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
  1166. // Otherwise, copy per row
  1167. const size_t rowSize = src.getWidth()*srcPixelSize;
  1168. for(size_t z=src.getFront(); z<src.getBack(); z++)
  1169. {
  1170. for(size_t y=src.getTop(); y<src.getBottom(); y++)
  1171. {
  1172. memcpy(dstptr, srcptr, rowSize);
  1173. srcptr += srcRowPitchBytes;
  1174. dstptr += dstRowPitchBytes;
  1175. }
  1176. srcptr += srcSliceSkipBytes;
  1177. dstptr += dstSliceSkipBytes;
  1178. }
  1179. return;
  1180. }
  1181. // Converting to PF_X8R8G8B8 is exactly the same as converting to
  1182. // PF_A8R8G8B8. (same with PF_X8B8G8R8 and PF_A8B8G8R8)
  1183. if(dst.getFormat() == PF_X8R8G8B8 || dst.getFormat() == PF_X8B8G8R8)
  1184. {
  1185. // Do the same conversion, with PF_A8R8G8B8, which has a lot of
  1186. // optimized conversions
  1187. PixelFormat tempFormat = dst.getFormat()==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
  1188. PixelData tempdst(dst.getWidth(), dst.getHeight(), dst.getDepth(), tempFormat);
  1189. bulkPixelConversion(src, tempdst);
  1190. return;
  1191. }
  1192. // Converting from PF_X8R8G8B8 is exactly the same as converting from
  1193. // PF_A8R8G8B8, given that the destination format does not have alpha.
  1194. if((src.getFormat() == PF_X8R8G8B8||src.getFormat() == PF_X8B8G8R8) && !hasAlpha(dst.getFormat()))
  1195. {
  1196. // Do the same conversion, with PF_A8R8G8B8, which has a lot of
  1197. // optimized conversions
  1198. PixelFormat tempFormat = src.getFormat()==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
  1199. PixelData tempsrc(src.getWidth(), src.getHeight(), src.getDepth(), tempFormat);
  1200. tempsrc.setExternalBuffer(src.getData());
  1201. bulkPixelConversion(tempsrc, dst);
  1202. return;
  1203. }
  1204. const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.getFormat());
  1205. const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.getFormat());
  1206. UINT8 *srcptr = static_cast<UINT8*>(src.getData())
  1207. + (src.getLeft() + src.getTop() * src.getRowPitch() + src.getFront() * src.getSlicePitch()) * srcPixelSize;
  1208. UINT8 *dstptr = static_cast<UINT8*>(dst.getData())
  1209. + (dst.getLeft() + dst.getTop() * dst.getRowPitch() + dst.getFront() * dst.getSlicePitch()) * dstPixelSize;
  1210. // Old way, not taking into account box dimensions
  1211. //UINT8 *srcptr = static_cast<UINT8*>(src.data), *dstptr = static_cast<UINT8*>(dst.data);
  1212. // Calculate pitches+skips in bytes
  1213. const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
  1214. const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
  1215. const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
  1216. const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
  1217. // The brute force fallback
  1218. float r,g,b,a;
  1219. for(size_t z=src.getFront(); z<src.getBack(); z++)
  1220. {
  1221. for(size_t y=src.getTop(); y<src.getBottom(); y++)
  1222. {
  1223. for(size_t x=src.getLeft(); x<src.getRight(); x++)
  1224. {
  1225. unpackColour(&r, &g, &b, &a, src.getFormat(), srcptr);
  1226. packColour(r, g, b, a, dst.getFormat(), dstptr);
  1227. srcptr += srcPixelSize;
  1228. dstptr += dstPixelSize;
  1229. }
  1230. srcptr += srcRowSkipBytes;
  1231. dstptr += dstRowSkipBytes;
  1232. }
  1233. srcptr += srcSliceSkipBytes;
  1234. dstptr += dstSliceSkipBytes;
  1235. }
  1236. }
  1237. void PixelUtil::scale(const PixelData &src, const PixelData &scaled, Filter filter)
  1238. {
  1239. assert(PixelUtil::isAccessible(src.getFormat()));
  1240. assert(PixelUtil::isAccessible(scaled.getFormat()));
  1241. PixelData temp;
  1242. switch (filter)
  1243. {
  1244. default:
  1245. case FILTER_NEAREST:
  1246. if(src.getFormat() == scaled.getFormat())
  1247. {
  1248. // No intermediate buffer needed
  1249. temp = scaled;
  1250. }
  1251. else
  1252. {
  1253. // Allocate temporary buffer of destination size in source format
  1254. temp = PixelData(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.getFormat());
  1255. temp.allocateInternalBuffer();
  1256. }
  1257. // super-optimized: no conversion
  1258. switch (PixelUtil::getNumElemBytes(src.getFormat()))
  1259. {
  1260. case 1: NearestResampler<1>::scale(src, temp); break;
  1261. case 2: NearestResampler<2>::scale(src, temp); break;
  1262. case 3: NearestResampler<3>::scale(src, temp); break;
  1263. case 4: NearestResampler<4>::scale(src, temp); break;
  1264. case 6: NearestResampler<6>::scale(src, temp); break;
  1265. case 8: NearestResampler<8>::scale(src, temp); break;
  1266. case 12: NearestResampler<12>::scale(src, temp); break;
  1267. case 16: NearestResampler<16>::scale(src, temp); break;
  1268. default:
  1269. // never reached
  1270. assert(false);
  1271. }
  1272. if(temp.getData() != scaled.getData())
  1273. {
  1274. // Blit temp buffer
  1275. PixelUtil::bulkPixelConversion(temp, scaled);
  1276. temp.freeInternalBuffer();
  1277. }
  1278. break;
  1279. case FILTER_LINEAR:
  1280. case FILTER_BILINEAR:
  1281. switch (src.getFormat())
  1282. {
  1283. case PF_R8G8:
  1284. case PF_R8G8B8: case PF_B8G8R8:
  1285. case PF_R8G8B8A8: case PF_B8G8R8A8:
  1286. case PF_A8B8G8R8: case PF_A8R8G8B8:
  1287. case PF_X8B8G8R8: case PF_X8R8G8B8:
  1288. if(src.getFormat() == scaled.getFormat())
  1289. {
  1290. // No intermediate buffer needed
  1291. temp = scaled;
  1292. }
  1293. else
  1294. {
  1295. // Allocate temp buffer of destination size in source format
  1296. temp = PixelData(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.getFormat());
  1297. temp.allocateInternalBuffer();
  1298. }
  1299. // super-optimized: byte-oriented math, no conversion
  1300. switch (PixelUtil::getNumElemBytes(src.getFormat()))
  1301. {
  1302. case 1: LinearResampler_Byte<1>::scale(src, temp); break;
  1303. case 2: LinearResampler_Byte<2>::scale(src, temp); break;
  1304. case 3: LinearResampler_Byte<3>::scale(src, temp); break;
  1305. case 4: LinearResampler_Byte<4>::scale(src, temp); break;
  1306. default:
  1307. // never reached
  1308. assert(false);
  1309. }
  1310. if(temp.getData() != scaled.getData())
  1311. {
  1312. // Blit temp buffer
  1313. PixelUtil::bulkPixelConversion(temp, scaled);
  1314. temp.freeInternalBuffer();
  1315. }
  1316. break;
  1317. case PF_FLOAT32_RGB:
  1318. case PF_FLOAT32_RGBA:
  1319. if (scaled.getFormat() == PF_FLOAT32_RGB || scaled.getFormat() == PF_FLOAT32_RGBA)
  1320. {
  1321. // float32 to float32, avoid unpack/repack overhead
  1322. LinearResampler_Float32::scale(src, scaled);
  1323. break;
  1324. }
  1325. // else, fall through
  1326. default:
  1327. // non-optimized: floating-point math, performs conversion but always works
  1328. LinearResampler::scale(src, scaled);
  1329. }
  1330. break;
  1331. }
  1332. }
  1333. //-----------------------------------------------------------------------------
  1334. void PixelUtil::applyGamma(UINT8 *buffer, float gamma, size_t size, UINT8 bpp)
  1335. {
  1336. if( gamma == 1.0f )
  1337. return;
  1338. //NB only 24/32-bit supported
  1339. if( bpp != 24 && bpp != 32 ) return;
  1340. UINT32 stride = bpp >> 3;
  1341. for( size_t i = 0, j = size / stride; i < j; i++, buffer += stride )
  1342. {
  1343. float r, g, b;
  1344. r = (float)buffer[0];
  1345. g = (float)buffer[1];
  1346. b = (float)buffer[2];
  1347. r = r * gamma;
  1348. g = g * gamma;
  1349. b = b * gamma;
  1350. float scale = 1.0f, tmp;
  1351. if( r > 255.0f && (tmp=(255.0f/r)) < scale )
  1352. scale = tmp;
  1353. if( g > 255.0f && (tmp=(255.0f/g)) < scale )
  1354. scale = tmp;
  1355. if( b > 255.0f && (tmp=(255.0f/b)) < scale )
  1356. scale = tmp;
  1357. r *= scale; g *= scale; b *= scale;
  1358. buffer[0] = (UINT8)r;
  1359. buffer[1] = (UINT8)g;
  1360. buffer[2] = (UINT8)b;
  1361. }
  1362. }
  1363. }