CmPixelUtil.cpp 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmPixelUtil.h"
  25. #include "CmBitwise.h"
  26. #include "CmColor.h"
  27. #include "CmException.h"
  28. namespace CamelotEngine {
  29. //-----------------------------------------------------------------------
  30. /**
  31. * Resamplers
  32. */
  33. // variable name hints:
  34. // sx_48 = 16/48-bit fixed-point x-position in source
  35. // stepx = difference between adjacent sx_48 values
  36. // sx1 = lower-bound integer x-position in source
  37. // sx2 = upper-bound integer x-position in source
  38. // sxf = fractional weight beween sx1 and sx2
  39. // x,y,z = location of output pixel in destination
  40. // nearest-neighbor resampler, does not convert formats.
  41. // templated on bytes-per-pixel to allow compiler optimizations, such
  42. // as simplifying memcpy() and replacing multiplies with bitshifts
  43. template<unsigned int elemsize> struct NearestResampler {
  44. static void scale(const PixelData& src, const PixelData& dst) {
  45. // assert(src.format == dst.format);
  46. // srcdata stays at beginning, pdst is a moving pointer
  47. UINT8* srcdata = (UINT8*)src.data;
  48. UINT8* pdst = (UINT8*)dst.data;
  49. // sx_48,sy_48,sz_48 represent current position in source
  50. // using 16/48-bit fixed precision, incremented by steps
  51. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  52. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  53. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  54. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  55. // for the center of the destination pixel, not the top-left corner
  56. UINT64 sz_48 = (stepz >> 1) - 1;
  57. for (size_t z = dst.front; z < dst.back; z++, sz_48 += stepz) {
  58. size_t srczoff = (size_t)(sz_48 >> 48) * src.slicePitch;
  59. UINT64 sy_48 = (stepy >> 1) - 1;
  60. for (size_t y = dst.top; y < dst.bottom; y++, sy_48 += stepy) {
  61. size_t srcyoff = (size_t)(sy_48 >> 48) * src.rowPitch;
  62. UINT64 sx_48 = (stepx >> 1) - 1;
  63. for (size_t x = dst.left; x < dst.right; x++, sx_48 += stepx) {
  64. UINT8* psrc = srcdata +
  65. elemsize*((size_t)(sx_48 >> 48) + srcyoff + srczoff);
  66. memcpy(pdst, psrc, elemsize);
  67. pdst += elemsize;
  68. }
  69. pdst += elemsize*dst.getRowSkip();
  70. }
  71. pdst += elemsize*dst.getSliceSkip();
  72. }
  73. }
  74. };
  75. // default floating-point linear resampler, does format conversion
  76. struct LinearResampler {
  77. static void scale(const PixelData& src, const PixelData& dst) {
  78. size_t srcelemsize = PixelUtil::getNumElemBytes(src.format);
  79. size_t dstelemsize = PixelUtil::getNumElemBytes(dst.format);
  80. // srcdata stays at beginning, pdst is a moving pointer
  81. UINT8* srcdata = (UINT8*)src.data;
  82. UINT8* pdst = (UINT8*)dst.data;
  83. // sx_48,sy_48,sz_48 represent current position in source
  84. // using 16/48-bit fixed precision, incremented by steps
  85. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  86. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  87. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  88. // temp is 16/16 bit fixed precision, used to adjust a source
  89. // coordinate (x, y, or z) backwards by half a pixel so that the
  90. // integer bits represent the first sample (eg, sx1) and the
  91. // fractional bits are the blend weight of the second sample
  92. unsigned int temp;
  93. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  94. // for the center of the destination pixel, not the top-left corner
  95. UINT64 sz_48 = (stepz >> 1) - 1;
  96. for (size_t z = dst.front; z < dst.back; z++, sz_48+=stepz) {
  97. temp = static_cast<unsigned int>(sz_48 >> 32);
  98. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  99. size_t sz1 = temp >> 16; // src z, sample #1
  100. size_t sz2 = std::min(sz1+1,src.getDepth()-1);// src z, sample #2
  101. float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
  102. UINT64 sy_48 = (stepy >> 1) - 1;
  103. for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
  104. temp = static_cast<unsigned int>(sy_48 >> 32);
  105. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  106. size_t sy1 = temp >> 16; // src y #1
  107. size_t sy2 = std::min(sy1+1,src.getHeight()-1);// src y #2
  108. float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
  109. UINT64 sx_48 = (stepx >> 1) - 1;
  110. for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
  111. temp = static_cast<unsigned int>(sx_48 >> 32);
  112. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  113. size_t sx1 = temp >> 16; // src x #1
  114. size_t sx2 = std::min(sx1+1,src.getWidth()-1);// src x #2
  115. float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
  116. Color x1y1z1, x2y1z1, x1y2z1, x2y2z1;
  117. Color x1y1z2, x2y1z2, x1y2z2, x2y2z2;
  118. #define UNPACK(dst,x,y,z) PixelUtil::unpackColour(&dst, src.format, \
  119. srcdata + srcelemsize*((x)+(y)*src.rowPitch+(z)*src.slicePitch))
  120. UNPACK(x1y1z1,sx1,sy1,sz1); UNPACK(x2y1z1,sx2,sy1,sz1);
  121. UNPACK(x1y2z1,sx1,sy2,sz1); UNPACK(x2y2z1,sx2,sy2,sz1);
  122. UNPACK(x1y1z2,sx1,sy1,sz2); UNPACK(x2y1z2,sx2,sy1,sz2);
  123. UNPACK(x1y2z2,sx1,sy2,sz2); UNPACK(x2y2z2,sx2,sy2,sz2);
  124. #undef UNPACK
  125. Color accum =
  126. x1y1z1 * ((1.0f - sxf)*(1.0f - syf)*(1.0f - szf)) +
  127. x2y1z1 * ( sxf *(1.0f - syf)*(1.0f - szf)) +
  128. x1y2z1 * ((1.0f - sxf)* syf *(1.0f - szf)) +
  129. x2y2z1 * ( sxf * syf *(1.0f - szf)) +
  130. x1y1z2 * ((1.0f - sxf)*(1.0f - syf)* szf ) +
  131. x2y1z2 * ( sxf *(1.0f - syf)* szf ) +
  132. x1y2z2 * ((1.0f - sxf)* syf * szf ) +
  133. x2y2z2 * ( sxf * syf * szf );
  134. PixelUtil::packColour(accum, dst.format, pdst);
  135. pdst += dstelemsize;
  136. }
  137. pdst += dstelemsize*dst.getRowSkip();
  138. }
  139. pdst += dstelemsize*dst.getSliceSkip();
  140. }
  141. }
  142. };
  143. // float32 linear resampler, converts FLOAT32_RGB/FLOAT32_RGBA only.
  144. // avoids overhead of pixel unpack/repack function calls
  145. struct LinearResampler_Float32 {
  146. static void scale(const PixelData& src, const PixelData& dst) {
  147. size_t srcchannels = PixelUtil::getNumElemBytes(src.format) / sizeof(float);
  148. size_t dstchannels = PixelUtil::getNumElemBytes(dst.format) / sizeof(float);
  149. // assert(srcchannels == 3 || srcchannels == 4);
  150. // assert(dstchannels == 3 || dstchannels == 4);
  151. // srcdata stays at beginning, pdst is a moving pointer
  152. float* srcdata = (float*)src.data;
  153. float* pdst = (float*)dst.data;
  154. // sx_48,sy_48,sz_48 represent current position in source
  155. // using 16/48-bit fixed precision, incremented by steps
  156. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  157. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  158. UINT64 stepz = ((UINT64)src.getDepth() << 48) / dst.getDepth();
  159. // temp is 16/16 bit fixed precision, used to adjust a source
  160. // coordinate (x, y, or z) backwards by half a pixel so that the
  161. // integer bits represent the first sample (eg, sx1) and the
  162. // fractional bits are the blend weight of the second sample
  163. unsigned int temp;
  164. // note: ((stepz>>1) - 1) is an extra half-step increment to adjust
  165. // for the center of the destination pixel, not the top-left corner
  166. UINT64 sz_48 = (stepz >> 1) - 1;
  167. for (size_t z = dst.front; z < dst.back; z++, sz_48+=stepz) {
  168. temp = static_cast<unsigned int>(sz_48 >> 32);
  169. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  170. size_t sz1 = temp >> 16; // src z, sample #1
  171. size_t sz2 = std::min(sz1+1,src.getDepth()-1);// src z, sample #2
  172. float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
  173. UINT64 sy_48 = (stepy >> 1) - 1;
  174. for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
  175. temp = static_cast<unsigned int>(sy_48 >> 32);
  176. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  177. size_t sy1 = temp >> 16; // src y #1
  178. size_t sy2 = std::min(sy1+1,src.getHeight()-1);// src y #2
  179. float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
  180. UINT64 sx_48 = (stepx >> 1) - 1;
  181. for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
  182. temp = static_cast<unsigned int>(sx_48 >> 32);
  183. temp = (temp > 0x8000)? temp - 0x8000 : 0;
  184. size_t sx1 = temp >> 16; // src x #1
  185. size_t sx2 = std::min(sx1+1,src.getWidth()-1);// src x #2
  186. float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
  187. // process R,G,B,A simultaneously for cache coherence?
  188. float accum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  189. #define ACCUM3(x,y,z,factor) \
  190. { float f = factor; \
  191. size_t off = (x+y*src.rowPitch+z*src.slicePitch)*srcchannels; \
  192. accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
  193. accum[2]+=srcdata[off+2]*f; }
  194. #define ACCUM4(x,y,z,factor) \
  195. { float f = factor; \
  196. size_t off = (x+y*src.rowPitch+z*src.slicePitch)*srcchannels; \
  197. accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
  198. accum[2]+=srcdata[off+2]*f; accum[3]+=srcdata[off+3]*f; }
  199. if (srcchannels == 3 || dstchannels == 3) {
  200. // RGB, no alpha
  201. ACCUM3(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
  202. ACCUM3(sx2,sy1,sz1, sxf *(1.0f-syf)*(1.0f-szf));
  203. ACCUM3(sx1,sy2,sz1,(1.0f-sxf)* syf *(1.0f-szf));
  204. ACCUM3(sx2,sy2,sz1, sxf * syf *(1.0f-szf));
  205. ACCUM3(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)* szf );
  206. ACCUM3(sx2,sy1,sz2, sxf *(1.0f-syf)* szf );
  207. ACCUM3(sx1,sy2,sz2,(1.0f-sxf)* syf * szf );
  208. ACCUM3(sx2,sy2,sz2, sxf * syf * szf );
  209. accum[3] = 1.0f;
  210. } else {
  211. // RGBA
  212. ACCUM4(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
  213. ACCUM4(sx2,sy1,sz1, sxf *(1.0f-syf)*(1.0f-szf));
  214. ACCUM4(sx1,sy2,sz1,(1.0f-sxf)* syf *(1.0f-szf));
  215. ACCUM4(sx2,sy2,sz1, sxf * syf *(1.0f-szf));
  216. ACCUM4(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)* szf );
  217. ACCUM4(sx2,sy1,sz2, sxf *(1.0f-syf)* szf );
  218. ACCUM4(sx1,sy2,sz2,(1.0f-sxf)* syf * szf );
  219. ACCUM4(sx2,sy2,sz2, sxf * syf * szf );
  220. }
  221. memcpy(pdst, accum, sizeof(float)*dstchannels);
  222. #undef ACCUM3
  223. #undef ACCUM4
  224. pdst += dstchannels;
  225. }
  226. pdst += dstchannels*dst.getRowSkip();
  227. }
  228. pdst += dstchannels*dst.getSliceSkip();
  229. }
  230. }
  231. };
  232. // byte linear resampler, does not do any format conversions.
  233. // only handles pixel formats that use 1 byte per color channel.
  234. // 2D only; punts 3D pixelboxes to default LinearResampler (slow).
  235. // templated on bytes-per-pixel to allow compiler optimizations, such
  236. // as unrolling loops and replacing multiplies with bitshifts
  237. template<unsigned int channels> struct LinearResampler_Byte {
  238. static void scale(const PixelData& src, const PixelData& dst) {
  239. // assert(src.format == dst.format);
  240. // only optimized for 2D
  241. if (src.getDepth() > 1 || dst.getDepth() > 1) {
  242. LinearResampler::scale(src, dst);
  243. return;
  244. }
  245. // srcdata stays at beginning of slice, pdst is a moving pointer
  246. UINT8* srcdata = (UINT8*)src.data;
  247. UINT8* pdst = (UINT8*)dst.data;
  248. // sx_48,sy_48 represent current position in source
  249. // using 16/48-bit fixed precision, incremented by steps
  250. UINT64 stepx = ((UINT64)src.getWidth() << 48) / dst.getWidth();
  251. UINT64 stepy = ((UINT64)src.getHeight() << 48) / dst.getHeight();
  252. // bottom 28 bits of temp are 16/12 bit fixed precision, used to
  253. // adjust a source coordinate backwards by half a pixel so that the
  254. // integer bits represent the first sample (eg, sx1) and the
  255. // fractional bits are the blend weight of the second sample
  256. unsigned int temp;
  257. UINT64 sy_48 = (stepy >> 1) - 1;
  258. for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
  259. temp = static_cast<unsigned int>(sy_48 >> 36);
  260. temp = (temp > 0x800)? temp - 0x800: 0;
  261. unsigned int syf = temp & 0xFFF;
  262. size_t sy1 = temp >> 12;
  263. size_t sy2 = std::min(sy1+1, src.bottom-src.top-1);
  264. size_t syoff1 = sy1 * src.rowPitch;
  265. size_t syoff2 = sy2 * src.rowPitch;
  266. UINT64 sx_48 = (stepx >> 1) - 1;
  267. for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
  268. temp = static_cast<unsigned int>(sx_48 >> 36);
  269. temp = (temp > 0x800)? temp - 0x800 : 0;
  270. unsigned int sxf = temp & 0xFFF;
  271. size_t sx1 = temp >> 12;
  272. size_t sx2 = std::min(sx1+1, src.right-src.left-1);
  273. unsigned int sxfsyf = sxf*syf;
  274. for (unsigned int k = 0; k < channels; k++) {
  275. unsigned int accum =
  276. srcdata[(sx1 + syoff1)*channels+k]*(0x1000000-(sxf<<12)-(syf<<12)+sxfsyf) +
  277. srcdata[(sx2 + syoff1)*channels+k]*((sxf<<12)-sxfsyf) +
  278. srcdata[(sx1 + syoff2)*channels+k]*((syf<<12)-sxfsyf) +
  279. srcdata[(sx2 + syoff2)*channels+k]*sxfsyf;
  280. // accum is computed using 8/24-bit fixed-point math
  281. // (maximum is 0xFF000000; rounding will not cause overflow)
  282. *pdst++ = static_cast<UINT8>((accum + 0x800000) >> 24);
  283. }
  284. }
  285. pdst += channels*dst.getRowSkip();
  286. }
  287. }
  288. };
  289. //-----------------------------------------------------------------------
  290. /**
  291. * A record that describes a pixel format in detail.
  292. */
  293. struct PixelFormatDescription {
  294. /* Name of the format, as in the enum */
  295. const char *name;
  296. /* Number of bytes one element (colour value) takes. */
  297. unsigned char elemBytes;
  298. /* Pixel format flags, see enum PixelFormatFlags for the bit field
  299. * definitions
  300. */
  301. UINT32 flags;
  302. /** Component type
  303. */
  304. PixelComponentType componentType;
  305. /** Component count
  306. */
  307. unsigned char componentCount;
  308. /* Number of bits for red(or luminance), green, blue, alpha
  309. */
  310. unsigned char rbits,gbits,bbits,abits; /*, ibits, dbits, ... */
  311. /* Masks and shifts as used by packers/unpackers */
  312. UINT32 rmask, gmask, bmask, amask;
  313. unsigned char rshift, gshift, bshift, ashift;
  314. };
  315. //-----------------------------------------------------------------------
  316. /** Pixel format database */
  317. PixelFormatDescription _pixelFormats[PF_COUNT] = {
  318. //-----------------------------------------------------------------------
  319. {"PF_UNKNOWN",
  320. /* Bytes per element */
  321. 0,
  322. /* Flags */
  323. 0,
  324. /* Component type and count */
  325. PCT_BYTE, 0,
  326. /* rbits, gbits, bbits, abits */
  327. 0, 0, 0, 0,
  328. /* Masks and shifts */
  329. 0, 0, 0, 0, 0, 0, 0, 0
  330. },
  331. //-----------------------------------------------------------------------
  332. {"PF_L8",
  333. /* Bytes per element */
  334. 1,
  335. /* Flags */
  336. PFF_LUMINANCE | PFF_NATIVEENDIAN,
  337. /* Component type and count */
  338. PCT_BYTE, 1,
  339. /* rbits, gbits, bbits, abits */
  340. 8, 0, 0, 0,
  341. /* Masks and shifts */
  342. 0xFF, 0, 0, 0, 0, 0, 0, 0
  343. },
  344. //-----------------------------------------------------------------------
  345. {"PF_L16",
  346. /* Bytes per element */
  347. 2,
  348. /* Flags */
  349. PFF_LUMINANCE | PFF_NATIVEENDIAN,
  350. /* Component type and count */
  351. PCT_SHORT, 1,
  352. /* rbits, gbits, bbits, abits */
  353. 16, 0, 0, 0,
  354. /* Masks and shifts */
  355. 0xFFFF, 0, 0, 0, 0, 0, 0, 0
  356. },
  357. //-----------------------------------------------------------------------
  358. {"PF_A8",
  359. /* Bytes per element */
  360. 1,
  361. /* Flags */
  362. PFF_HASALPHA | PFF_NATIVEENDIAN,
  363. /* Component type and count */
  364. PCT_BYTE, 1,
  365. /* rbits, gbits, bbits, abits */
  366. 0, 0, 0, 8,
  367. /* Masks and shifts */
  368. 0, 0, 0, 0xFF, 0, 0, 0, 0
  369. },
  370. //-----------------------------------------------------------------------
  371. {"PF_A4L4",
  372. /* Bytes per element */
  373. 1,
  374. /* Flags */
  375. PFF_HASALPHA | PFF_LUMINANCE | PFF_NATIVEENDIAN,
  376. /* Component type and count */
  377. PCT_BYTE, 2,
  378. /* rbits, gbits, bbits, abits */
  379. 4, 0, 0, 4,
  380. /* Masks and shifts */
  381. 0x0F, 0, 0, 0xF0, 0, 0, 0, 4
  382. },
  383. //-----------------------------------------------------------------------
  384. {"PF_BYTE_LA",
  385. /* Bytes per element */
  386. 2,
  387. /* Flags */
  388. PFF_HASALPHA | PFF_LUMINANCE,
  389. /* Component type and count */
  390. PCT_BYTE, 2,
  391. /* rbits, gbits, bbits, abits */
  392. 8, 0, 0, 8,
  393. /* Masks and shifts */
  394. 0,0,0,0,0,0,0,0
  395. },
  396. //-----------------------------------------------------------------------
  397. {"PF_R5G6B5",
  398. /* Bytes per element */
  399. 2,
  400. /* Flags */
  401. PFF_NATIVEENDIAN,
  402. /* Component type and count */
  403. PCT_BYTE, 3,
  404. /* rbits, gbits, bbits, abits */
  405. 5, 6, 5, 0,
  406. /* Masks and shifts */
  407. 0xF800, 0x07E0, 0x001F, 0,
  408. 11, 5, 0, 0
  409. },
  410. //-----------------------------------------------------------------------
  411. {"PF_B5G6R5",
  412. /* Bytes per element */
  413. 2,
  414. /* Flags */
  415. PFF_NATIVEENDIAN,
  416. /* Component type and count */
  417. PCT_BYTE, 3,
  418. /* rbits, gbits, bbits, abits */
  419. 5, 6, 5, 0,
  420. /* Masks and shifts */
  421. 0x001F, 0x07E0, 0xF800, 0,
  422. 0, 5, 11, 0
  423. },
  424. //-----------------------------------------------------------------------
  425. {"PF_A4R4G4B4",
  426. /* Bytes per element */
  427. 2,
  428. /* Flags */
  429. PFF_HASALPHA | PFF_NATIVEENDIAN,
  430. /* Component type and count */
  431. PCT_BYTE, 4,
  432. /* rbits, gbits, bbits, abits */
  433. 4, 4, 4, 4,
  434. /* Masks and shifts */
  435. 0x0F00, 0x00F0, 0x000F, 0xF000,
  436. 8, 4, 0, 12
  437. },
  438. //-----------------------------------------------------------------------
  439. {"PF_A1R5G5B5",
  440. /* Bytes per element */
  441. 2,
  442. /* Flags */
  443. PFF_HASALPHA | PFF_NATIVEENDIAN,
  444. /* Component type and count */
  445. PCT_BYTE, 4,
  446. /* rbits, gbits, bbits, abits */
  447. 5, 5, 5, 1,
  448. /* Masks and shifts */
  449. 0x7C00, 0x03E0, 0x001F, 0x8000,
  450. 10, 5, 0, 15,
  451. },
  452. //-----------------------------------------------------------------------
  453. {"PF_R8G8B8",
  454. /* Bytes per element */
  455. 3, // 24 bit integer -- special
  456. /* Flags */
  457. PFF_NATIVEENDIAN,
  458. /* Component type and count */
  459. PCT_BYTE, 3,
  460. /* rbits, gbits, bbits, abits */
  461. 8, 8, 8, 0,
  462. /* Masks and shifts */
  463. 0xFF0000, 0x00FF00, 0x0000FF, 0,
  464. 16, 8, 0, 0
  465. },
  466. //-----------------------------------------------------------------------
  467. {"PF_B8G8R8",
  468. /* Bytes per element */
  469. 3, // 24 bit integer -- special
  470. /* Flags */
  471. PFF_NATIVEENDIAN,
  472. /* Component type and count */
  473. PCT_BYTE, 3,
  474. /* rbits, gbits, bbits, abits */
  475. 8, 8, 8, 0,
  476. /* Masks and shifts */
  477. 0x0000FF, 0x00FF00, 0xFF0000, 0,
  478. 0, 8, 16, 0
  479. },
  480. //-----------------------------------------------------------------------
  481. {"PF_A8R8G8B8",
  482. /* Bytes per element */
  483. 4,
  484. /* Flags */
  485. PFF_HASALPHA | PFF_NATIVEENDIAN,
  486. /* Component type and count */
  487. PCT_BYTE, 4,
  488. /* rbits, gbits, bbits, abits */
  489. 8, 8, 8, 8,
  490. /* Masks and shifts */
  491. 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
  492. 16, 8, 0, 24
  493. },
  494. //-----------------------------------------------------------------------
  495. {"PF_A8B8G8R8",
  496. /* Bytes per element */
  497. 4,
  498. /* Flags */
  499. PFF_HASALPHA | PFF_NATIVEENDIAN,
  500. /* Component type and count */
  501. PCT_BYTE, 4,
  502. /* rbits, gbits, bbits, abits */
  503. 8, 8, 8, 8,
  504. /* Masks and shifts */
  505. 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
  506. 0, 8, 16, 24,
  507. },
  508. //-----------------------------------------------------------------------
  509. {"PF_B8G8R8A8",
  510. /* Bytes per element */
  511. 4,
  512. /* Flags */
  513. PFF_HASALPHA | PFF_NATIVEENDIAN,
  514. /* Component type and count */
  515. PCT_BYTE, 4,
  516. /* rbits, gbits, bbits, abits */
  517. 8, 8, 8, 8,
  518. /* Masks and shifts */
  519. 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF,
  520. 8, 16, 24, 0
  521. },
  522. //-----------------------------------------------------------------------
  523. {"PF_A2R10G10B10",
  524. /* Bytes per element */
  525. 4,
  526. /* Flags */
  527. PFF_HASALPHA | PFF_NATIVEENDIAN,
  528. /* Component type and count */
  529. PCT_BYTE, 4,
  530. /* rbits, gbits, bbits, abits */
  531. 10, 10, 10, 2,
  532. /* Masks and shifts */
  533. 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000,
  534. 20, 10, 0, 30
  535. },
  536. //-----------------------------------------------------------------------
  537. {"PF_A2B10G10R10",
  538. /* Bytes per element */
  539. 4,
  540. /* Flags */
  541. PFF_HASALPHA | PFF_NATIVEENDIAN,
  542. /* Component type and count */
  543. PCT_BYTE, 4,
  544. /* rbits, gbits, bbits, abits */
  545. 10, 10, 10, 2,
  546. /* Masks and shifts */
  547. 0x000003FF, 0x000FFC00, 0x3FF00000, 0xC0000000,
  548. 0, 10, 20, 30
  549. },
  550. //-----------------------------------------------------------------------
  551. {"PF_DXT1",
  552. /* Bytes per element */
  553. 0,
  554. /* Flags */
  555. PFF_COMPRESSED | PFF_HASALPHA,
  556. /* Component type and count */
  557. PCT_BYTE, 3, // No alpha
  558. /* rbits, gbits, bbits, abits */
  559. 0, 0, 0, 0,
  560. /* Masks and shifts */
  561. 0, 0, 0, 0, 0, 0, 0, 0
  562. },
  563. //-----------------------------------------------------------------------
  564. {"PF_DXT2",
  565. /* Bytes per element */
  566. 0,
  567. /* Flags */
  568. PFF_COMPRESSED | PFF_HASALPHA,
  569. /* Component type and count */
  570. PCT_BYTE, 4,
  571. /* rbits, gbits, bbits, abits */
  572. 0, 0, 0, 0,
  573. /* Masks and shifts */
  574. 0, 0, 0, 0, 0, 0, 0, 0
  575. },
  576. //-----------------------------------------------------------------------
  577. {"PF_DXT3",
  578. /* Bytes per element */
  579. 0,
  580. /* Flags */
  581. PFF_COMPRESSED | PFF_HASALPHA,
  582. /* Component type and count */
  583. PCT_BYTE, 4,
  584. /* rbits, gbits, bbits, abits */
  585. 0, 0, 0, 0,
  586. /* Masks and shifts */
  587. 0, 0, 0, 0, 0, 0, 0, 0
  588. },
  589. //-----------------------------------------------------------------------
  590. {"PF_DXT4",
  591. /* Bytes per element */
  592. 0,
  593. /* Flags */
  594. PFF_COMPRESSED | PFF_HASALPHA,
  595. /* Component type and count */
  596. PCT_BYTE, 4,
  597. /* rbits, gbits, bbits, abits */
  598. 0, 0, 0, 0,
  599. /* Masks and shifts */
  600. 0, 0, 0, 0, 0, 0, 0, 0
  601. },
  602. //-----------------------------------------------------------------------
  603. {"PF_DXT5",
  604. /* Bytes per element */
  605. 0,
  606. /* Flags */
  607. PFF_COMPRESSED | PFF_HASALPHA,
  608. /* Component type and count */
  609. PCT_BYTE, 4,
  610. /* rbits, gbits, bbits, abits */
  611. 0, 0, 0, 0,
  612. /* Masks and shifts */
  613. 0, 0, 0, 0, 0, 0, 0, 0
  614. },
  615. //-----------------------------------------------------------------------
  616. {"PF_FLOAT16_RGB",
  617. /* Bytes per element */
  618. 6,
  619. /* Flags */
  620. PFF_FLOAT,
  621. /* Component type and count */
  622. PCT_FLOAT16, 3,
  623. /* rbits, gbits, bbits, abits */
  624. 16, 16, 16, 0,
  625. /* Masks and shifts */
  626. 0, 0, 0, 0, 0, 0, 0, 0
  627. },
  628. //-----------------------------------------------------------------------
  629. {"PF_FLOAT16_RGBA",
  630. /* Bytes per element */
  631. 8,
  632. /* Flags */
  633. PFF_FLOAT | PFF_HASALPHA,
  634. /* Component type and count */
  635. PCT_FLOAT16, 4,
  636. /* rbits, gbits, bbits, abits */
  637. 16, 16, 16, 16,
  638. /* Masks and shifts */
  639. 0, 0, 0, 0, 0, 0, 0, 0
  640. },
  641. //-----------------------------------------------------------------------
  642. {"PF_FLOAT32_RGB",
  643. /* Bytes per element */
  644. 12,
  645. /* Flags */
  646. PFF_FLOAT,
  647. /* Component type and count */
  648. PCT_FLOAT32, 3,
  649. /* rbits, gbits, bbits, abits */
  650. 32, 32, 32, 0,
  651. /* Masks and shifts */
  652. 0, 0, 0, 0, 0, 0, 0, 0
  653. },
  654. //-----------------------------------------------------------------------
  655. {"PF_FLOAT32_RGBA",
  656. /* Bytes per element */
  657. 16,
  658. /* Flags */
  659. PFF_FLOAT | PFF_HASALPHA,
  660. /* Component type and count */
  661. PCT_FLOAT32, 4,
  662. /* rbits, gbits, bbits, abits */
  663. 32, 32, 32, 32,
  664. /* Masks and shifts */
  665. 0, 0, 0, 0, 0, 0, 0, 0
  666. },
  667. //-----------------------------------------------------------------------
  668. {"PF_X8R8G8B8",
  669. /* Bytes per element */
  670. 4,
  671. /* Flags */
  672. PFF_NATIVEENDIAN,
  673. /* Component type and count */
  674. PCT_BYTE, 3,
  675. /* rbits, gbits, bbits, abits */
  676. 8, 8, 8, 0,
  677. /* Masks and shifts */
  678. 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
  679. 16, 8, 0, 24
  680. },
  681. //-----------------------------------------------------------------------
  682. {"PF_X8B8G8R8",
  683. /* Bytes per element */
  684. 4,
  685. /* Flags */
  686. PFF_NATIVEENDIAN,
  687. /* Component type and count */
  688. PCT_BYTE, 3,
  689. /* rbits, gbits, bbits, abits */
  690. 8, 8, 8, 0,
  691. /* Masks and shifts */
  692. 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
  693. 0, 8, 16, 24
  694. },
  695. //-----------------------------------------------------------------------
  696. {"PF_R8G8B8A8",
  697. /* Bytes per element */
  698. 4,
  699. /* Flags */
  700. PFF_HASALPHA | PFF_NATIVEENDIAN,
  701. /* Component type and count */
  702. PCT_BYTE, 4,
  703. /* rbits, gbits, bbits, abits */
  704. 8, 8, 8, 8,
  705. /* Masks and shifts */
  706. 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
  707. 24, 16, 8, 0
  708. },
  709. //-----------------------------------------------------------------------
  710. {"PF_DEPTH",
  711. /* Bytes per element */
  712. 4,
  713. /* Flags */
  714. PFF_DEPTH,
  715. /* Component type and count */
  716. PCT_FLOAT32, 1, // ?
  717. /* rbits, gbits, bbits, abits */
  718. 0, 0, 0, 0,
  719. /* Masks and shifts */
  720. 0, 0, 0, 0, 0, 0, 0, 0
  721. },
  722. //-----------------------------------------------------------------------
  723. {"PF_SHORT_RGBA",
  724. /* Bytes per element */
  725. 8,
  726. /* Flags */
  727. PFF_HASALPHA,
  728. /* Component type and count */
  729. PCT_SHORT, 4,
  730. /* rbits, gbits, bbits, abits */
  731. 16, 16, 16, 16,
  732. /* Masks and shifts */
  733. 0, 0, 0, 0, 0, 0, 0, 0
  734. },
  735. //-----------------------------------------------------------------------
  736. {"PF_R3G3B2",
  737. /* Bytes per element */
  738. 1,
  739. /* Flags */
  740. PFF_NATIVEENDIAN,
  741. /* Component type and count */
  742. PCT_BYTE, 3,
  743. /* rbits, gbits, bbits, abits */
  744. 3, 3, 2, 0,
  745. /* Masks and shifts */
  746. 0xE0, 0x1C, 0x03, 0,
  747. 5, 2, 0, 0
  748. },
  749. //-----------------------------------------------------------------------
  750. {"PF_FLOAT16_R",
  751. /* Bytes per element */
  752. 2,
  753. /* Flags */
  754. PFF_FLOAT,
  755. /* Component type and count */
  756. PCT_FLOAT16, 1,
  757. /* rbits, gbits, bbits, abits */
  758. 16, 0, 0, 0,
  759. /* Masks and shifts */
  760. 0, 0, 0, 0, 0, 0, 0, 0
  761. },
  762. //-----------------------------------------------------------------------
  763. {"PF_FLOAT32_R",
  764. /* Bytes per element */
  765. 4,
  766. /* Flags */
  767. PFF_FLOAT,
  768. /* Component type and count */
  769. PCT_FLOAT32, 1,
  770. /* rbits, gbits, bbits, abits */
  771. 32, 0, 0, 0,
  772. /* Masks and shifts */
  773. 0, 0, 0, 0, 0, 0, 0, 0
  774. },
  775. //-----------------------------------------------------------------------
  776. {"PF_SHORT_GR",
  777. /* Bytes per element */
  778. 4,
  779. /* Flags */
  780. PFF_NATIVEENDIAN,
  781. /* Component type and count */
  782. PCT_SHORT, 2,
  783. /* rbits, gbits, bbits, abits */
  784. 16, 16, 0, 0,
  785. /* Masks and shifts */
  786. 0x0000FFFF, 0xFFFF0000, 0, 0,
  787. 0, 16, 0, 0
  788. },
  789. //-----------------------------------------------------------------------
  790. {"PF_FLOAT16_GR",
  791. /* Bytes per element */
  792. 4,
  793. /* Flags */
  794. PFF_FLOAT,
  795. /* Component type and count */
  796. PCT_FLOAT16, 2,
  797. /* rbits, gbits, bbits, abits */
  798. 16, 16, 0, 0,
  799. /* Masks and shifts */
  800. 0, 0, 0, 0, 0, 0, 0, 0
  801. },
  802. //-----------------------------------------------------------------------
  803. {"PF_FLOAT32_GR",
  804. /* Bytes per element */
  805. 8,
  806. /* Flags */
  807. PFF_FLOAT,
  808. /* Component type and count */
  809. PCT_FLOAT32, 2,
  810. /* rbits, gbits, bbits, abits */
  811. 32, 32, 0, 0,
  812. /* Masks and shifts */
  813. 0, 0, 0, 0, 0, 0, 0, 0
  814. },
  815. //-----------------------------------------------------------------------
  816. {"PF_SHORT_RGB",
  817. /* Bytes per element */
  818. 6,
  819. /* Flags */
  820. 0,
  821. /* Component type and count */
  822. PCT_SHORT, 3,
  823. /* rbits, gbits, bbits, abits */
  824. 16, 16, 16, 0,
  825. /* Masks and shifts */
  826. 0, 0, 0, 0, 0, 0, 0, 0
  827. },
  828. //-----------------------------------------------------------------------
  829. {"PF_PVRTC_RGB2",
  830. /* Bytes per element */
  831. 0,
  832. /* Flags */
  833. PFF_COMPRESSED,
  834. /* Component type and count */
  835. PCT_BYTE, 3,
  836. /* rbits, gbits, bbits, abits */
  837. 0, 0, 0, 0,
  838. /* Masks and shifts */
  839. 0, 0, 0, 0, 0, 0, 0, 0
  840. },
  841. //-----------------------------------------------------------------------
  842. {"PF_PVRTC_RGBA2",
  843. /* Bytes per element */
  844. 0,
  845. /* Flags */
  846. PFF_COMPRESSED | PFF_HASALPHA,
  847. /* Component type and count */
  848. PCT_BYTE, 4,
  849. /* rbits, gbits, bbits, abits */
  850. 0, 0, 0, 0,
  851. /* Masks and shifts */
  852. 0, 0, 0, 0, 0, 0, 0, 0
  853. },
  854. //-----------------------------------------------------------------------
  855. {"PF_PVRTC_RGB4",
  856. /* Bytes per element */
  857. 0,
  858. /* Flags */
  859. PFF_COMPRESSED,
  860. /* Component type and count */
  861. PCT_BYTE, 3,
  862. /* rbits, gbits, bbits, abits */
  863. 0, 0, 0, 0,
  864. /* Masks and shifts */
  865. 0, 0, 0, 0, 0, 0, 0, 0
  866. },
  867. //-----------------------------------------------------------------------
  868. {"PF_PVRTC_RGBA4",
  869. /* Bytes per element */
  870. 0,
  871. /* Flags */
  872. PFF_COMPRESSED | PFF_HASALPHA,
  873. /* Component type and count */
  874. PCT_BYTE, 4,
  875. /* rbits, gbits, bbits, abits */
  876. 0, 0, 0, 0,
  877. /* Masks and shifts */
  878. 0, 0, 0, 0, 0, 0, 0, 0
  879. },
  880. };
  881. //-----------------------------------------------------------------------
  882. size_t PixelData::getConsecutiveSize() const
  883. {
  884. return PixelUtil::getMemorySize(getWidth(), getHeight(), getDepth(), format);
  885. }
  886. PixelData PixelData::getSubVolume(const Box &def) const
  887. {
  888. if(PixelUtil::isCompressed(format))
  889. {
  890. if(def.left == left && def.top == top && def.front == front &&
  891. def.right == right && def.bottom == bottom && def.back == back)
  892. {
  893. // Entire buffer is being queried
  894. return *this;
  895. }
  896. CM_EXCEPT(InvalidParametersException, "Cannot return subvolume of compressed PixelBuffer");
  897. }
  898. if(!contains(def))
  899. {
  900. CM_EXCEPT(InvalidParametersException, "Bounds out of range");
  901. }
  902. const size_t elemSize = PixelUtil::getNumElemBytes(format);
  903. // Calculate new data origin
  904. // Notice how we do not propagate left/top/front from the incoming box, since
  905. // the returned pointer is already offset
  906. PixelData rval(def.getWidth(), def.getHeight(), def.getDepth(), format,
  907. ((UINT8*)data) + ((def.left-left)*elemSize)
  908. + ((def.top-top)*rowPitch*elemSize)
  909. + ((def.front-front)*slicePitch*elemSize)
  910. );
  911. rval.rowPitch = rowPitch;
  912. rval.slicePitch = slicePitch;
  913. rval.format = format;
  914. return rval;
  915. }
  916. //-----------------------------------------------------------------------
  917. /**
  918. * Directly get the description record for provided pixel format. For debug builds,
  919. * this checks the bounds of fmt with an assertion.
  920. */
  921. static inline const PixelFormatDescription &getDescriptionFor(const PixelFormat fmt)
  922. {
  923. const int ord = (int)fmt;
  924. assert(ord>=0 && ord<PF_COUNT);
  925. return _pixelFormats[ord];
  926. }
  927. //-----------------------------------------------------------------------
  928. size_t PixelUtil::getNumElemBytes( PixelFormat format )
  929. {
  930. return getDescriptionFor(format).elemBytes;
  931. }
  932. //-----------------------------------------------------------------------
  933. size_t PixelUtil::getMemorySize(size_t width, size_t height, size_t depth, PixelFormat format)
  934. {
  935. if(isCompressed(format))
  936. {
  937. switch(format)
  938. {
  939. // DXT formats work by dividing the image into 4x4 blocks, then encoding each
  940. // 4x4 block with a certain number of bytes.
  941. case PF_DXT1:
  942. return ((width+3)/4)*((height+3)/4)*8 * depth;
  943. case PF_DXT2:
  944. case PF_DXT3:
  945. case PF_DXT4:
  946. case PF_DXT5:
  947. return ((width+3)/4)*((height+3)/4)*16 * depth;
  948. // Size calculations from the PVRTC OpenGL extension spec
  949. // http://www.khronos.org/registry/gles/extensions/IMG/IMG_texture_compression_pvrtc.txt
  950. // Basically, 32 bytes is the minimum texture size. Smaller textures are padded up to 32 bytes
  951. case PF_PVRTC_RGB2:
  952. case PF_PVRTC_RGBA2:
  953. assert(depth == 1);
  954. return (std::max((int)width, 16) * std::max((int)height, 8) * 2 + 7) / 8;
  955. case PF_PVRTC_RGB4:
  956. case PF_PVRTC_RGBA4:
  957. assert(depth == 1);
  958. return (std::max((int)width, 8) * std::max((int)height, 8) * 4 + 7) / 8;
  959. default:
  960. CM_EXCEPT(InvalidParametersException, "Invalid compressed pixel format");
  961. }
  962. }
  963. else
  964. {
  965. return width*height*depth*getNumElemBytes(format);
  966. }
  967. }
  968. //-----------------------------------------------------------------------
  969. size_t PixelUtil::getNumElemBits( PixelFormat format )
  970. {
  971. return getDescriptionFor(format).elemBytes * 8;
  972. }
  973. //-----------------------------------------------------------------------
  974. unsigned int PixelUtil::getFlags( PixelFormat format )
  975. {
  976. return getDescriptionFor(format).flags;
  977. }
  978. //-----------------------------------------------------------------------
  979. bool PixelUtil::hasAlpha(PixelFormat format)
  980. {
  981. return (PixelUtil::getFlags(format) & PFF_HASALPHA) > 0;
  982. }
  983. //-----------------------------------------------------------------------
  984. bool PixelUtil::isFloatingPoint(PixelFormat format)
  985. {
  986. return (PixelUtil::getFlags(format) & PFF_FLOAT) > 0;
  987. }
  988. //-----------------------------------------------------------------------
  989. bool PixelUtil::isCompressed(PixelFormat format)
  990. {
  991. return (PixelUtil::getFlags(format) & PFF_COMPRESSED) > 0;
  992. }
  993. //-----------------------------------------------------------------------
  994. bool PixelUtil::isDepth(PixelFormat format)
  995. {
  996. return (PixelUtil::getFlags(format) & PFF_DEPTH) > 0;
  997. }
  998. //-----------------------------------------------------------------------
  999. bool PixelUtil::isNativeEndian(PixelFormat format)
  1000. {
  1001. return (PixelUtil::getFlags(format) & PFF_NATIVEENDIAN) > 0;
  1002. }
  1003. //-----------------------------------------------------------------------
  1004. bool PixelUtil::isLuminance(PixelFormat format)
  1005. {
  1006. return (PixelUtil::getFlags(format) & PFF_LUMINANCE) > 0;
  1007. }
  1008. //-----------------------------------------------------------------------
  1009. bool PixelUtil::isValidExtent(size_t width, size_t height, size_t depth, PixelFormat format)
  1010. {
  1011. if(isCompressed(format))
  1012. {
  1013. switch(format)
  1014. {
  1015. case PF_DXT1:
  1016. case PF_DXT2:
  1017. case PF_DXT3:
  1018. case PF_DXT4:
  1019. case PF_DXT5:
  1020. return ((width&3)==0 && (height&3)==0 && depth==1);
  1021. default:
  1022. return true;
  1023. }
  1024. }
  1025. else
  1026. {
  1027. return true;
  1028. }
  1029. }
  1030. //-----------------------------------------------------------------------
  1031. void PixelUtil::getBitDepths(PixelFormat format, int rgba[4])
  1032. {
  1033. const PixelFormatDescription &des = getDescriptionFor(format);
  1034. rgba[0] = des.rbits;
  1035. rgba[1] = des.gbits;
  1036. rgba[2] = des.bbits;
  1037. rgba[3] = des.abits;
  1038. }
  1039. //-----------------------------------------------------------------------
  1040. void PixelUtil::getBitMasks(PixelFormat format, UINT32 rgba[4])
  1041. {
  1042. const PixelFormatDescription &des = getDescriptionFor(format);
  1043. rgba[0] = des.rmask;
  1044. rgba[1] = des.gmask;
  1045. rgba[2] = des.bmask;
  1046. rgba[3] = des.amask;
  1047. }
  1048. //---------------------------------------------------------------------
  1049. void PixelUtil::getBitShifts(PixelFormat format, unsigned char rgba[4])
  1050. {
  1051. const PixelFormatDescription &des = getDescriptionFor(format);
  1052. rgba[0] = des.rshift;
  1053. rgba[1] = des.gshift;
  1054. rgba[2] = des.bshift;
  1055. rgba[3] = des.ashift;
  1056. }
  1057. //-----------------------------------------------------------------------
  1058. String PixelUtil::getFormatName(PixelFormat srcformat)
  1059. {
  1060. return getDescriptionFor(srcformat).name;
  1061. }
  1062. //-----------------------------------------------------------------------
  1063. bool PixelUtil::isAccessible(PixelFormat srcformat)
  1064. {
  1065. if (srcformat == PF_UNKNOWN)
  1066. return false;
  1067. unsigned int flags = getFlags(srcformat);
  1068. return !((flags & PFF_COMPRESSED) || (flags & PFF_DEPTH));
  1069. }
  1070. //-----------------------------------------------------------------------
  1071. PixelComponentType PixelUtil::getComponentType(PixelFormat fmt)
  1072. {
  1073. const PixelFormatDescription &des = getDescriptionFor(fmt);
  1074. return des.componentType;
  1075. }
  1076. //-----------------------------------------------------------------------
  1077. size_t PixelUtil::getComponentCount(PixelFormat fmt)
  1078. {
  1079. const PixelFormatDescription &des = getDescriptionFor(fmt);
  1080. return des.componentCount;
  1081. }
  1082. //-----------------------------------------------------------------------
  1083. PixelFormat PixelUtil::getFormatFromName(const String& name, bool accessibleOnly, bool caseSensitive)
  1084. {
  1085. String tmp = name;
  1086. if (!caseSensitive)
  1087. {
  1088. // We are stored upper-case format names.
  1089. StringUtil::toUpperCase(tmp);
  1090. }
  1091. for (int i = 0; i < PF_COUNT; ++i)
  1092. {
  1093. PixelFormat pf = static_cast<PixelFormat>(i);
  1094. if (!accessibleOnly || isAccessible(pf))
  1095. {
  1096. if (tmp == getFormatName(pf))
  1097. return pf;
  1098. }
  1099. }
  1100. return PF_UNKNOWN;
  1101. }
  1102. //-----------------------------------------------------------------------
  1103. String PixelUtil::getBNFExpressionOfPixelFormats(bool accessibleOnly)
  1104. {
  1105. // Collect format names sorted by length, it's required by BNF compiler
  1106. // that similar tokens need longer ones comes first.
  1107. typedef multimap<String::size_type, String>::type FormatNameMap;
  1108. FormatNameMap formatNames;
  1109. for (size_t i = 0; i < PF_COUNT; ++i)
  1110. {
  1111. PixelFormat pf = static_cast<PixelFormat>(i);
  1112. if (!accessibleOnly || isAccessible(pf))
  1113. {
  1114. String formatName = getFormatName(pf);
  1115. formatNames.insert(std::make_pair(formatName.length(), formatName));
  1116. }
  1117. }
  1118. // Populate the BNF expression in reverse order
  1119. String result;
  1120. // Note: Stupid M$ VC7.1 can't dealing operator!= with FormatNameMap::const_reverse_iterator.
  1121. for (FormatNameMap::reverse_iterator j = formatNames.rbegin(); j != formatNames.rend(); ++j)
  1122. {
  1123. if (!result.empty())
  1124. result += " | ";
  1125. result += "'" + j->second + "'";
  1126. }
  1127. return result;
  1128. }
  1129. //-----------------------------------------------------------------------
  1130. PixelFormat PixelUtil::getFormatForBitDepths(PixelFormat fmt, UINT16 integerBits, UINT16 floatBits)
  1131. {
  1132. switch (integerBits)
  1133. {
  1134. case 16:
  1135. switch (fmt)
  1136. {
  1137. case PF_R8G8B8:
  1138. case PF_X8R8G8B8:
  1139. return PF_R5G6B5;
  1140. case PF_B8G8R8:
  1141. case PF_X8B8G8R8:
  1142. return PF_B5G6R5;
  1143. case PF_A8R8G8B8:
  1144. case PF_R8G8B8A8:
  1145. case PF_A8B8G8R8:
  1146. case PF_B8G8R8A8:
  1147. return PF_A4R4G4B4;
  1148. case PF_A2R10G10B10:
  1149. case PF_A2B10G10R10:
  1150. return PF_A1R5G5B5;
  1151. default:
  1152. // use original image format
  1153. break;
  1154. }
  1155. break;
  1156. case 32:
  1157. switch (fmt)
  1158. {
  1159. case PF_R5G6B5:
  1160. return PF_X8R8G8B8;
  1161. case PF_B5G6R5:
  1162. return PF_X8B8G8R8;
  1163. case PF_A4R4G4B4:
  1164. return PF_A8R8G8B8;
  1165. case PF_A1R5G5B5:
  1166. return PF_A2R10G10B10;
  1167. default:
  1168. // use original image format
  1169. break;
  1170. }
  1171. break;
  1172. default:
  1173. // use original image format
  1174. break;
  1175. }
  1176. switch (floatBits)
  1177. {
  1178. case 16:
  1179. switch (fmt)
  1180. {
  1181. case PF_FLOAT32_R:
  1182. return PF_FLOAT16_R;
  1183. case PF_FLOAT32_RGB:
  1184. return PF_FLOAT16_RGB;
  1185. case PF_FLOAT32_RGBA:
  1186. return PF_FLOAT16_RGBA;
  1187. default:
  1188. // use original image format
  1189. break;
  1190. }
  1191. break;
  1192. case 32:
  1193. switch (fmt)
  1194. {
  1195. case PF_FLOAT16_R:
  1196. return PF_FLOAT32_R;
  1197. case PF_FLOAT16_RGB:
  1198. return PF_FLOAT32_RGB;
  1199. case PF_FLOAT16_RGBA:
  1200. return PF_FLOAT32_RGBA;
  1201. default:
  1202. // use original image format
  1203. break;
  1204. }
  1205. break;
  1206. default:
  1207. // use original image format
  1208. break;
  1209. }
  1210. return fmt;
  1211. }
  1212. //-----------------------------------------------------------------------
  1213. /*************************************************************************
  1214. * Pixel packing/unpacking utilities
  1215. */
  1216. void PixelUtil::packColour(const Color &colour, const PixelFormat pf, void* dest)
  1217. {
  1218. packColour(colour.r, colour.g, colour.b, colour.a, pf, dest);
  1219. }
  1220. //-----------------------------------------------------------------------
  1221. void PixelUtil::packColour(const UINT8 r, const UINT8 g, const UINT8 b, const UINT8 a, const PixelFormat pf, void* dest)
  1222. {
  1223. const PixelFormatDescription &des = getDescriptionFor(pf);
  1224. if(des.flags & PFF_NATIVEENDIAN) {
  1225. // Shortcut for integer formats packing
  1226. unsigned int value = ((Bitwise::fixedToFixed(r, 8, des.rbits)<<des.rshift) & des.rmask) |
  1227. ((Bitwise::fixedToFixed(g, 8, des.gbits)<<des.gshift) & des.gmask) |
  1228. ((Bitwise::fixedToFixed(b, 8, des.bbits)<<des.bshift) & des.bmask) |
  1229. ((Bitwise::fixedToFixed(a, 8, des.abits)<<des.ashift) & des.amask);
  1230. // And write to memory
  1231. Bitwise::intWrite(dest, des.elemBytes, value);
  1232. } else {
  1233. // Convert to float
  1234. packColour((float)r/255.0f,(float)g/255.0f,(float)b/255.0f,(float)a/255.0f, pf, dest);
  1235. }
  1236. }
  1237. //-----------------------------------------------------------------------
  1238. void PixelUtil::packColour(const float r, const float g, const float b, const float a, const PixelFormat pf, void* dest)
  1239. {
  1240. // Catch-it-all here
  1241. const PixelFormatDescription &des = getDescriptionFor(pf);
  1242. if(des.flags & PFF_NATIVEENDIAN) {
  1243. // Do the packing
  1244. //std::cerr << dest << " " << r << " " << g << " " << b << " " << a << std::endl;
  1245. const unsigned int value = ((Bitwise::floatToFixed(r, des.rbits)<<des.rshift) & des.rmask) |
  1246. ((Bitwise::floatToFixed(g, des.gbits)<<des.gshift) & des.gmask) |
  1247. ((Bitwise::floatToFixed(b, des.bbits)<<des.bshift) & des.bmask) |
  1248. ((Bitwise::floatToFixed(a, des.abits)<<des.ashift) & des.amask);
  1249. // And write to memory
  1250. Bitwise::intWrite(dest, des.elemBytes, value);
  1251. } else {
  1252. switch(pf)
  1253. {
  1254. case PF_FLOAT32_R:
  1255. ((float*)dest)[0] = r;
  1256. break;
  1257. case PF_FLOAT32_GR:
  1258. ((float*)dest)[0] = g;
  1259. ((float*)dest)[1] = r;
  1260. break;
  1261. case PF_FLOAT32_RGB:
  1262. ((float*)dest)[0] = r;
  1263. ((float*)dest)[1] = g;
  1264. ((float*)dest)[2] = b;
  1265. break;
  1266. case PF_FLOAT32_RGBA:
  1267. ((float*)dest)[0] = r;
  1268. ((float*)dest)[1] = g;
  1269. ((float*)dest)[2] = b;
  1270. ((float*)dest)[3] = a;
  1271. break;
  1272. case PF_FLOAT16_R:
  1273. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  1274. break;
  1275. case PF_FLOAT16_GR:
  1276. ((UINT16*)dest)[0] = Bitwise::floatToHalf(g);
  1277. ((UINT16*)dest)[1] = Bitwise::floatToHalf(r);
  1278. break;
  1279. case PF_FLOAT16_RGB:
  1280. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  1281. ((UINT16*)dest)[1] = Bitwise::floatToHalf(g);
  1282. ((UINT16*)dest)[2] = Bitwise::floatToHalf(b);
  1283. break;
  1284. case PF_FLOAT16_RGBA:
  1285. ((UINT16*)dest)[0] = Bitwise::floatToHalf(r);
  1286. ((UINT16*)dest)[1] = Bitwise::floatToHalf(g);
  1287. ((UINT16*)dest)[2] = Bitwise::floatToHalf(b);
  1288. ((UINT16*)dest)[3] = Bitwise::floatToHalf(a);
  1289. break;
  1290. case PF_SHORT_RGB:
  1291. ((UINT16*)dest)[0] = (UINT16)Bitwise::floatToFixed(r, 16);
  1292. ((UINT16*)dest)[1] = (UINT16)Bitwise::floatToFixed(g, 16);
  1293. ((UINT16*)dest)[2] = (UINT16)Bitwise::floatToFixed(b, 16);
  1294. break;
  1295. case PF_SHORT_RGBA:
  1296. ((UINT16*)dest)[0] = (UINT16)Bitwise::floatToFixed(r, 16);
  1297. ((UINT16*)dest)[1] = (UINT16)Bitwise::floatToFixed(g, 16);
  1298. ((UINT16*)dest)[2] = (UINT16)Bitwise::floatToFixed(b, 16);
  1299. ((UINT16*)dest)[3] = (UINT16)Bitwise::floatToFixed(a, 16);
  1300. break;
  1301. case PF_BYTE_LA:
  1302. ((UINT8*)dest)[0] = (UINT8)Bitwise::floatToFixed(r, 8);
  1303. ((UINT8*)dest)[1] = (UINT8)Bitwise::floatToFixed(a, 8);
  1304. break;
  1305. default:
  1306. // Not yet supported
  1307. CM_EXCEPT(NotImplementedException,
  1308. "pack to "+getFormatName(pf)+" not implemented");
  1309. break;
  1310. }
  1311. }
  1312. }
  1313. //-----------------------------------------------------------------------
  1314. void PixelUtil::unpackColour(Color *colour, PixelFormat pf, const void* src)
  1315. {
  1316. unpackColour(&colour->r, &colour->g, &colour->b, &colour->a, pf, src);
  1317. }
  1318. //-----------------------------------------------------------------------
  1319. void PixelUtil::unpackColour(UINT8 *r, UINT8 *g, UINT8 *b, UINT8 *a, PixelFormat pf, const void* src)
  1320. {
  1321. const PixelFormatDescription &des = getDescriptionFor(pf);
  1322. if(des.flags & PFF_NATIVEENDIAN) {
  1323. // Shortcut for integer formats unpacking
  1324. const unsigned int value = Bitwise::intRead(src, des.elemBytes);
  1325. if(des.flags & PFF_LUMINANCE)
  1326. {
  1327. // Luminance format -- only rbits used
  1328. *r = *g = *b = (UINT8)Bitwise::fixedToFixed(
  1329. (value & des.rmask)>>des.rshift, des.rbits, 8);
  1330. }
  1331. else
  1332. {
  1333. *r = (UINT8)Bitwise::fixedToFixed((value & des.rmask)>>des.rshift, des.rbits, 8);
  1334. *g = (UINT8)Bitwise::fixedToFixed((value & des.gmask)>>des.gshift, des.gbits, 8);
  1335. *b = (UINT8)Bitwise::fixedToFixed((value & des.bmask)>>des.bshift, des.bbits, 8);
  1336. }
  1337. if(des.flags & PFF_HASALPHA)
  1338. {
  1339. *a = (UINT8)Bitwise::fixedToFixed((value & des.amask)>>des.ashift, des.abits, 8);
  1340. }
  1341. else
  1342. {
  1343. *a = 255; // No alpha, default a component to full
  1344. }
  1345. } else {
  1346. // Do the operation with the more generic floating point
  1347. float rr, gg, bb, aa;
  1348. unpackColour(&rr,&gg,&bb,&aa, pf, src);
  1349. *r = (UINT8)Bitwise::floatToFixed(rr, 8);
  1350. *g = (UINT8)Bitwise::floatToFixed(gg, 8);
  1351. *b = (UINT8)Bitwise::floatToFixed(bb, 8);
  1352. *a = (UINT8)Bitwise::floatToFixed(aa, 8);
  1353. }
  1354. }
  1355. //-----------------------------------------------------------------------
  1356. void PixelUtil::unpackColour(float *r, float *g, float *b, float *a,
  1357. PixelFormat pf, const void* src)
  1358. {
  1359. const PixelFormatDescription &des = getDescriptionFor(pf);
  1360. if(des.flags & PFF_NATIVEENDIAN) {
  1361. // Shortcut for integer formats unpacking
  1362. const unsigned int value = Bitwise::intRead(src, des.elemBytes);
  1363. if(des.flags & PFF_LUMINANCE)
  1364. {
  1365. // Luminance format -- only rbits used
  1366. *r = *g = *b = Bitwise::fixedToFloat(
  1367. (value & des.rmask)>>des.rshift, des.rbits);
  1368. }
  1369. else
  1370. {
  1371. *r = Bitwise::fixedToFloat((value & des.rmask)>>des.rshift, des.rbits);
  1372. *g = Bitwise::fixedToFloat((value & des.gmask)>>des.gshift, des.gbits);
  1373. *b = Bitwise::fixedToFloat((value & des.bmask)>>des.bshift, des.bbits);
  1374. }
  1375. if(des.flags & PFF_HASALPHA)
  1376. {
  1377. *a = Bitwise::fixedToFloat((value & des.amask)>>des.ashift, des.abits);
  1378. }
  1379. else
  1380. {
  1381. *a = 1.0f; // No alpha, default a component to full
  1382. }
  1383. } else {
  1384. switch(pf)
  1385. {
  1386. case PF_FLOAT32_R:
  1387. *r = *g = *b = ((float*)src)[0];
  1388. *a = 1.0f;
  1389. break;
  1390. case PF_FLOAT32_GR:
  1391. *g = ((float*)src)[0];
  1392. *r = *b = ((float*)src)[1];
  1393. *a = 1.0f;
  1394. break;
  1395. case PF_FLOAT32_RGB:
  1396. *r = ((float*)src)[0];
  1397. *g = ((float*)src)[1];
  1398. *b = ((float*)src)[2];
  1399. *a = 1.0f;
  1400. break;
  1401. case PF_FLOAT32_RGBA:
  1402. *r = ((float*)src)[0];
  1403. *g = ((float*)src)[1];
  1404. *b = ((float*)src)[2];
  1405. *a = ((float*)src)[3];
  1406. break;
  1407. case PF_FLOAT16_R:
  1408. *r = *g = *b = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1409. *a = 1.0f;
  1410. break;
  1411. case PF_FLOAT16_GR:
  1412. *g = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1413. *r = *b = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1414. *a = 1.0f;
  1415. break;
  1416. case PF_FLOAT16_RGB:
  1417. *r = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1418. *g = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1419. *b = Bitwise::halfToFloat(((UINT16*)src)[2]);
  1420. *a = 1.0f;
  1421. break;
  1422. case PF_FLOAT16_RGBA:
  1423. *r = Bitwise::halfToFloat(((UINT16*)src)[0]);
  1424. *g = Bitwise::halfToFloat(((UINT16*)src)[1]);
  1425. *b = Bitwise::halfToFloat(((UINT16*)src)[2]);
  1426. *a = Bitwise::halfToFloat(((UINT16*)src)[3]);
  1427. break;
  1428. case PF_SHORT_RGB:
  1429. *r = Bitwise::fixedToFloat(((UINT16*)src)[0], 16);
  1430. *g = Bitwise::fixedToFloat(((UINT16*)src)[1], 16);
  1431. *b = Bitwise::fixedToFloat(((UINT16*)src)[2], 16);
  1432. *a = 1.0f;
  1433. break;
  1434. case PF_SHORT_RGBA:
  1435. *r = Bitwise::fixedToFloat(((UINT16*)src)[0], 16);
  1436. *g = Bitwise::fixedToFloat(((UINT16*)src)[1], 16);
  1437. *b = Bitwise::fixedToFloat(((UINT16*)src)[2], 16);
  1438. *a = Bitwise::fixedToFloat(((UINT16*)src)[3], 16);
  1439. break;
  1440. case PF_BYTE_LA:
  1441. *r = *g = *b = Bitwise::fixedToFloat(((UINT8*)src)[0], 8);
  1442. *a = Bitwise::fixedToFloat(((UINT8*)src)[1], 8);
  1443. break;
  1444. default:
  1445. // Not yet supported
  1446. CM_EXCEPT(NotImplementedException,
  1447. "unpack from "+getFormatName(pf)+" not implemented");
  1448. break;
  1449. }
  1450. }
  1451. }
  1452. //-----------------------------------------------------------------------
  1453. /* Convert pixels from one format to another */
  1454. void PixelUtil::bulkPixelConversion(void *srcp, PixelFormat srcFormat,
  1455. void *destp, PixelFormat dstFormat, unsigned int count)
  1456. {
  1457. PixelData src(count, 1, 1, srcFormat, srcp),
  1458. dst(count, 1, 1, dstFormat, destp);
  1459. bulkPixelConversion(src, dst);
  1460. }
  1461. //-----------------------------------------------------------------------
  1462. void PixelUtil::bulkPixelConversion(const PixelData &src, const PixelData &dst)
  1463. {
  1464. assert(src.getWidth() == dst.getWidth() &&
  1465. src.getHeight() == dst.getHeight() &&
  1466. src.getDepth() == dst.getDepth());
  1467. // Check for compressed formats, we don't support decompression, compression or recoding
  1468. if(PixelUtil::isCompressed(src.format) || PixelUtil::isCompressed(dst.format))
  1469. {
  1470. if(src.format == dst.format)
  1471. {
  1472. memcpy(dst.data, src.data, src.getConsecutiveSize());
  1473. return;
  1474. }
  1475. else
  1476. {
  1477. CM_EXCEPT(NotImplementedException, "This method can not be used to compress or decompress images");
  1478. }
  1479. }
  1480. // The easy case
  1481. if(src.format == dst.format) {
  1482. // Everything consecutive?
  1483. if(src.isConsecutive() && dst.isConsecutive())
  1484. {
  1485. memcpy(dst.data, src.data, src.getConsecutiveSize());
  1486. return;
  1487. }
  1488. const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.format);
  1489. const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.format);
  1490. UINT8 *srcptr = static_cast<UINT8*>(src.data)
  1491. + (src.left + src.top * src.rowPitch + src.front * src.slicePitch) * srcPixelSize;
  1492. UINT8 *dstptr = static_cast<UINT8*>(dst.data)
  1493. + (dst.left + dst.top * dst.rowPitch + dst.front * dst.slicePitch) * dstPixelSize;
  1494. // Calculate pitches+skips in bytes
  1495. const size_t srcRowPitchBytes = src.rowPitch*srcPixelSize;
  1496. //const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
  1497. const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
  1498. const size_t dstRowPitchBytes = dst.rowPitch*dstPixelSize;
  1499. //const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
  1500. const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
  1501. // Otherwise, copy per row
  1502. const size_t rowSize = src.getWidth()*srcPixelSize;
  1503. for(size_t z=src.front; z<src.back; z++)
  1504. {
  1505. for(size_t y=src.top; y<src.bottom; y++)
  1506. {
  1507. memcpy(dstptr, srcptr, rowSize);
  1508. srcptr += srcRowPitchBytes;
  1509. dstptr += dstRowPitchBytes;
  1510. }
  1511. srcptr += srcSliceSkipBytes;
  1512. dstptr += dstSliceSkipBytes;
  1513. }
  1514. return;
  1515. }
  1516. // Converting to PF_X8R8G8B8 is exactly the same as converting to
  1517. // PF_A8R8G8B8. (same with PF_X8B8G8R8 and PF_A8B8G8R8)
  1518. if(dst.format == PF_X8R8G8B8 || dst.format == PF_X8B8G8R8)
  1519. {
  1520. // Do the same conversion, with PF_A8R8G8B8, which has a lot of
  1521. // optimized conversions
  1522. PixelData tempdst = dst;
  1523. tempdst.format = dst.format==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
  1524. bulkPixelConversion(src, tempdst);
  1525. return;
  1526. }
  1527. // Converting from PF_X8R8G8B8 is exactly the same as converting from
  1528. // PF_A8R8G8B8, given that the destination format does not have alpha.
  1529. if((src.format == PF_X8R8G8B8||src.format == PF_X8B8G8R8) && !hasAlpha(dst.format))
  1530. {
  1531. // Do the same conversion, with PF_A8R8G8B8, which has a lot of
  1532. // optimized conversions
  1533. PixelData tempsrc = src;
  1534. tempsrc.format = src.format==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
  1535. bulkPixelConversion(tempsrc, dst);
  1536. return;
  1537. }
  1538. const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.format);
  1539. const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.format);
  1540. UINT8 *srcptr = static_cast<UINT8*>(src.data)
  1541. + (src.left + src.top * src.rowPitch + src.front * src.slicePitch) * srcPixelSize;
  1542. UINT8 *dstptr = static_cast<UINT8*>(dst.data)
  1543. + (dst.left + dst.top * dst.rowPitch + dst.front * dst.slicePitch) * dstPixelSize;
  1544. // Old way, not taking into account box dimensions
  1545. //UINT8 *srcptr = static_cast<UINT8*>(src.data), *dstptr = static_cast<UINT8*>(dst.data);
  1546. // Calculate pitches+skips in bytes
  1547. const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
  1548. const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
  1549. const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
  1550. const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
  1551. // The brute force fallback
  1552. float r,g,b,a;
  1553. for(size_t z=src.front; z<src.back; z++)
  1554. {
  1555. for(size_t y=src.top; y<src.bottom; y++)
  1556. {
  1557. for(size_t x=src.left; x<src.right; x++)
  1558. {
  1559. unpackColour(&r, &g, &b, &a, src.format, srcptr);
  1560. packColour(r, g, b, a, dst.format, dstptr);
  1561. srcptr += srcPixelSize;
  1562. dstptr += dstPixelSize;
  1563. }
  1564. srcptr += srcRowSkipBytes;
  1565. dstptr += dstRowSkipBytes;
  1566. }
  1567. srcptr += srcSliceSkipBytes;
  1568. dstptr += dstSliceSkipBytes;
  1569. }
  1570. }
  1571. void PixelUtil::scale(const PixelData &src, const PixelData &scaled, Filter filter)
  1572. {
  1573. assert(PixelUtil::isAccessible(src.format));
  1574. assert(PixelUtil::isAccessible(scaled.format));
  1575. PixelData temp;
  1576. switch (filter)
  1577. {
  1578. default:
  1579. case FILTER_NEAREST:
  1580. if(src.format == scaled.format)
  1581. {
  1582. // No intermediate buffer needed
  1583. temp = scaled;
  1584. }
  1585. else
  1586. {
  1587. // Allocate temporary buffer of destination size in source format
  1588. temp = PixelData(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
  1589. temp.data = malloc(temp.getConsecutiveSize());
  1590. }
  1591. // super-optimized: no conversion
  1592. switch (PixelUtil::getNumElemBytes(src.format))
  1593. {
  1594. case 1: NearestResampler<1>::scale(src, temp); break;
  1595. case 2: NearestResampler<2>::scale(src, temp); break;
  1596. case 3: NearestResampler<3>::scale(src, temp); break;
  1597. case 4: NearestResampler<4>::scale(src, temp); break;
  1598. case 6: NearestResampler<6>::scale(src, temp); break;
  1599. case 8: NearestResampler<8>::scale(src, temp); break;
  1600. case 12: NearestResampler<12>::scale(src, temp); break;
  1601. case 16: NearestResampler<16>::scale(src, temp); break;
  1602. default:
  1603. // never reached
  1604. assert(false);
  1605. }
  1606. if(temp.data != scaled.data)
  1607. {
  1608. // Blit temp buffer
  1609. PixelUtil::bulkPixelConversion(temp, scaled);
  1610. free(temp.data);
  1611. }
  1612. break;
  1613. case FILTER_LINEAR:
  1614. case FILTER_BILINEAR:
  1615. switch (src.format)
  1616. {
  1617. case PF_L8: case PF_A8: case PF_BYTE_LA:
  1618. case PF_R8G8B8: case PF_B8G8R8:
  1619. case PF_R8G8B8A8: case PF_B8G8R8A8:
  1620. case PF_A8B8G8R8: case PF_A8R8G8B8:
  1621. case PF_X8B8G8R8: case PF_X8R8G8B8:
  1622. if(src.format == scaled.format)
  1623. {
  1624. // No intermediate buffer needed
  1625. temp = scaled;
  1626. }
  1627. else
  1628. {
  1629. // Allocate temp buffer of destination size in source format
  1630. temp = PixelData(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
  1631. temp.data = malloc(temp.getConsecutiveSize());
  1632. }
  1633. // super-optimized: byte-oriented math, no conversion
  1634. switch (PixelUtil::getNumElemBytes(src.format))
  1635. {
  1636. case 1: LinearResampler_Byte<1>::scale(src, temp); break;
  1637. case 2: LinearResampler_Byte<2>::scale(src, temp); break;
  1638. case 3: LinearResampler_Byte<3>::scale(src, temp); break;
  1639. case 4: LinearResampler_Byte<4>::scale(src, temp); break;
  1640. default:
  1641. // never reached
  1642. assert(false);
  1643. }
  1644. if(temp.data != scaled.data)
  1645. {
  1646. // Blit temp buffer
  1647. PixelUtil::bulkPixelConversion(temp, scaled);
  1648. free(temp.data);
  1649. }
  1650. break;
  1651. case PF_FLOAT32_RGB:
  1652. case PF_FLOAT32_RGBA:
  1653. if (scaled.format == PF_FLOAT32_RGB || scaled.format == PF_FLOAT32_RGBA)
  1654. {
  1655. // float32 to float32, avoid unpack/repack overhead
  1656. LinearResampler_Float32::scale(src, scaled);
  1657. break;
  1658. }
  1659. // else, fall through
  1660. default:
  1661. // non-optimized: floating-point math, performs conversion but always works
  1662. LinearResampler::scale(src, scaled);
  1663. }
  1664. break;
  1665. }
  1666. }
  1667. Color PixelData::getColourAt(size_t x, size_t y, size_t z)
  1668. {
  1669. Color cv;
  1670. unsigned char pixelSize = PixelUtil::getNumElemBytes(format);
  1671. size_t pixelOffset = pixelSize * (z * slicePitch + y * rowPitch + x);
  1672. PixelUtil::unpackColour(&cv, format, (unsigned char *)data + pixelOffset);
  1673. return cv;
  1674. }
  1675. void PixelData::setColourAt(Color const &cv, size_t x, size_t y, size_t z)
  1676. {
  1677. unsigned char pixelSize = PixelUtil::getNumElemBytes(format);
  1678. size_t pixelOffset = pixelSize * (z * slicePitch + y * rowPitch + x);
  1679. PixelUtil::packColour(cv, format, (unsigned char *)data + pixelOffset);
  1680. }
  1681. }