CmPixelUtil.cpp 46 KB

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