EtcBlock4x4Encoding_RGB8.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731
  1. /*
  2. * Copyright 2015 The Etc2Comp Authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. EtcBlock4x4Encoding_RGB8.cpp
  18. Block4x4Encoding_RGB8 is the encoder to use for the ETC2 extensions when targetting file format RGB8.
  19. This encoder is also used for the ETC2 subset of file format RGBA8.
  20. Block4x4Encoding_ETC1 encodes the ETC1 subset of RGB8.
  21. */
  22. #include "EtcConfig.h"
  23. #include "EtcBlock4x4Encoding_RGB8.h"
  24. #include "EtcBlock4x4EncodingBits.h"
  25. #include "EtcBlock4x4.h"
  26. #include "EtcMath.h"
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <float.h>
  31. #include <limits>
  32. namespace Etc
  33. {
  34. float Block4x4Encoding_RGB8::s_afTHDistanceTable[TH_DISTANCES] =
  35. {
  36. 3.0f / 255.0f,
  37. 6.0f / 255.0f,
  38. 11.0f / 255.0f,
  39. 16.0f / 255.0f,
  40. 23.0f / 255.0f,
  41. 32.0f / 255.0f,
  42. 41.0f / 255.0f,
  43. 64.0f / 255.0f
  44. };
  45. // ----------------------------------------------------------------------------------------------------
  46. //
  47. Block4x4Encoding_RGB8::Block4x4Encoding_RGB8(void)
  48. {
  49. m_pencodingbitsRGB8 = nullptr;
  50. }
  51. Block4x4Encoding_RGB8::~Block4x4Encoding_RGB8(void) {}
  52. // ----------------------------------------------------------------------------------------------------
  53. // initialization from the encoding bits of a previous encoding
  54. // a_pblockParent points to the block associated with this encoding
  55. // a_errormetric is used to choose the best encoding
  56. // a_pafrgbaSource points to a 4x4 block subset of the source image
  57. // a_paucEncodingBits points to the final encoding bits of a previous encoding
  58. //
  59. void Block4x4Encoding_RGB8::InitFromEncodingBits(Block4x4 *a_pblockParent,
  60. unsigned char *a_paucEncodingBits,
  61. ColorFloatRGBA *a_pafrgbaSource,
  62. ErrorMetric a_errormetric)
  63. {
  64. // handle ETC1 modes
  65. Block4x4Encoding_ETC1::InitFromEncodingBits(a_pblockParent,
  66. a_paucEncodingBits, a_pafrgbaSource,a_errormetric);
  67. m_pencodingbitsRGB8 = (Block4x4EncodingBits_RGB8 *)a_paucEncodingBits;
  68. // detect if there is a T, H or Planar mode present
  69. if (m_pencodingbitsRGB8->differential.diff)
  70. {
  71. int iRed1 = (int)m_pencodingbitsRGB8->differential.red1;
  72. int iDRed2 = m_pencodingbitsRGB8->differential.dred2;
  73. int iRed2 = iRed1 + iDRed2;
  74. int iGreen1 = (int)m_pencodingbitsRGB8->differential.green1;
  75. int iDGreen2 = m_pencodingbitsRGB8->differential.dgreen2;
  76. int iGreen2 = iGreen1 + iDGreen2;
  77. int iBlue1 = (int)m_pencodingbitsRGB8->differential.blue1;
  78. int iDBlue2 = m_pencodingbitsRGB8->differential.dblue2;
  79. int iBlue2 = iBlue1 + iDBlue2;
  80. if (iRed2 < 0 || iRed2 > 31)
  81. {
  82. InitFromEncodingBits_T();
  83. }
  84. else if (iGreen2 < 0 || iGreen2 > 31)
  85. {
  86. InitFromEncodingBits_H();
  87. }
  88. else if (iBlue2 < 0 || iBlue2 > 31)
  89. {
  90. InitFromEncodingBits_Planar();
  91. }
  92. }
  93. }
  94. // ----------------------------------------------------------------------------------------------------
  95. // initialization from the encoding bits of a previous encoding if T mode is detected
  96. //
  97. void Block4x4Encoding_RGB8::InitFromEncodingBits_T(void)
  98. {
  99. m_mode = MODE_T;
  100. unsigned char ucRed1 = (unsigned char)((m_pencodingbitsRGB8->t.red1a << 2) +
  101. m_pencodingbitsRGB8->t.red1b);
  102. unsigned char ucGreen1 = m_pencodingbitsRGB8->t.green1;
  103. unsigned char ucBlue1 = m_pencodingbitsRGB8->t.blue1;
  104. unsigned char ucRed2 = m_pencodingbitsRGB8->t.red2;
  105. unsigned char ucGreen2 = m_pencodingbitsRGB8->t.green2;
  106. unsigned char ucBlue2 = m_pencodingbitsRGB8->t.blue2;
  107. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4(ucRed1, ucGreen1, ucBlue1);
  108. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4(ucRed2, ucGreen2, ucBlue2);
  109. m_uiCW1 = (m_pencodingbitsRGB8->t.da << 1) + m_pencodingbitsRGB8->t.db;
  110. Block4x4Encoding_ETC1::InitFromEncodingBits_Selectors();
  111. DecodePixels_T();
  112. CalcBlockError();
  113. }
  114. // ----------------------------------------------------------------------------------------------------
  115. // initialization from the encoding bits of a previous encoding if H mode is detected
  116. //
  117. void Block4x4Encoding_RGB8::InitFromEncodingBits_H(void)
  118. {
  119. m_mode = MODE_H;
  120. unsigned char ucRed1 = m_pencodingbitsRGB8->h.red1;
  121. unsigned char ucGreen1 = (unsigned char)((m_pencodingbitsRGB8->h.green1a << 1) +
  122. m_pencodingbitsRGB8->h.green1b);
  123. unsigned char ucBlue1 = (unsigned char)((m_pencodingbitsRGB8->h.blue1a << 3) +
  124. (m_pencodingbitsRGB8->h.blue1b << 1) +
  125. m_pencodingbitsRGB8->h.blue1c);
  126. unsigned char ucRed2 = m_pencodingbitsRGB8->h.red2;
  127. unsigned char ucGreen2 = (unsigned char)((m_pencodingbitsRGB8->h.green2a << 1) +
  128. m_pencodingbitsRGB8->h.green2b);
  129. unsigned char ucBlue2 = m_pencodingbitsRGB8->h.blue2;
  130. m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4(ucRed1, ucGreen1, ucBlue1);
  131. m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4(ucRed2, ucGreen2, ucBlue2);
  132. // used to determine the LSB of the CW
  133. unsigned int uiRGB1 = (unsigned int)(((int)ucRed1 << 16) + ((int)ucGreen1 << 8) + (int)ucBlue1);
  134. unsigned int uiRGB2 = (unsigned int)(((int)ucRed2 << 16) + ((int)ucGreen2 << 8) + (int)ucBlue2);
  135. m_uiCW1 = (m_pencodingbitsRGB8->h.da << 2) + (m_pencodingbitsRGB8->h.db << 1);
  136. if (uiRGB1 >= uiRGB2)
  137. {
  138. m_uiCW1++;
  139. }
  140. Block4x4Encoding_ETC1::InitFromEncodingBits_Selectors();
  141. DecodePixels_H();
  142. CalcBlockError();
  143. }
  144. // ----------------------------------------------------------------------------------------------------
  145. // initialization from the encoding bits of a previous encoding if Planar mode is detected
  146. //
  147. void Block4x4Encoding_RGB8::InitFromEncodingBits_Planar(void)
  148. {
  149. m_mode = MODE_PLANAR;
  150. unsigned char ucOriginRed = m_pencodingbitsRGB8->planar.originRed;
  151. unsigned char ucOriginGreen = (unsigned char)((m_pencodingbitsRGB8->planar.originGreen1 << 6) +
  152. m_pencodingbitsRGB8->planar.originGreen2);
  153. unsigned char ucOriginBlue = (unsigned char)((m_pencodingbitsRGB8->planar.originBlue1 << 5) +
  154. (m_pencodingbitsRGB8->planar.originBlue2 << 3) +
  155. (m_pencodingbitsRGB8->planar.originBlue3 << 1) +
  156. m_pencodingbitsRGB8->planar.originBlue4);
  157. unsigned char ucHorizRed = (unsigned char)((m_pencodingbitsRGB8->planar.horizRed1 << 1) +
  158. m_pencodingbitsRGB8->planar.horizRed2);
  159. unsigned char ucHorizGreen = m_pencodingbitsRGB8->planar.horizGreen;
  160. unsigned char ucHorizBlue = (unsigned char)((m_pencodingbitsRGB8->planar.horizBlue1 << 5) +
  161. m_pencodingbitsRGB8->planar.horizBlue2);
  162. unsigned char ucVertRed = (unsigned char)((m_pencodingbitsRGB8->planar.vertRed1 << 3) +
  163. m_pencodingbitsRGB8->planar.vertRed2);
  164. unsigned char ucVertGreen = (unsigned char)((m_pencodingbitsRGB8->planar.vertGreen1 << 2) +
  165. m_pencodingbitsRGB8->planar.vertGreen2);
  166. unsigned char ucVertBlue = m_pencodingbitsRGB8->planar.vertBlue;
  167. m_frgbaColor1 = ColorFloatRGBA::ConvertFromR6G7B6(ucOriginRed, ucOriginGreen, ucOriginBlue);
  168. m_frgbaColor2 = ColorFloatRGBA::ConvertFromR6G7B6(ucHorizRed, ucHorizGreen, ucHorizBlue);
  169. m_frgbaColor3 = ColorFloatRGBA::ConvertFromR6G7B6(ucVertRed, ucVertGreen, ucVertBlue);
  170. DecodePixels_Planar();
  171. CalcBlockError();
  172. }
  173. // ----------------------------------------------------------------------------------------------------
  174. // perform a single encoding iteration
  175. // replace the encoding if a better encoding was found
  176. // subsequent iterations generally take longer for each iteration
  177. // set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
  178. //
  179. void Block4x4Encoding_RGB8::PerformIteration(float a_fEffort)
  180. {
  181. assert(!m_boolDone);
  182. switch (m_uiEncodingIterations)
  183. {
  184. case 0:
  185. Block4x4Encoding_ETC1::PerformFirstIteration();
  186. if (m_boolDone)
  187. {
  188. break;
  189. }
  190. TryPlanar(0);
  191. SetDoneIfPerfect();
  192. if (m_boolDone)
  193. {
  194. break;
  195. }
  196. TryTAndH(0);
  197. break;
  198. case 1:
  199. Block4x4Encoding_ETC1::TryDifferential(m_boolMostLikelyFlip, 1, 0, 0);
  200. break;
  201. case 2:
  202. Block4x4Encoding_ETC1::TryIndividual(m_boolMostLikelyFlip, 1);
  203. break;
  204. case 3:
  205. Block4x4Encoding_ETC1::TryDifferential(!m_boolMostLikelyFlip, 1, 0, 0);
  206. break;
  207. case 4:
  208. Block4x4Encoding_ETC1::TryIndividual(!m_boolMostLikelyFlip, 1);
  209. break;
  210. case 5:
  211. TryPlanar(1);
  212. if (a_fEffort <= 49.5f)
  213. {
  214. m_boolDone = true;
  215. }
  216. break;
  217. case 6:
  218. TryTAndH(1);
  219. if (a_fEffort <= 59.5f)
  220. {
  221. m_boolDone = true;
  222. }
  223. break;
  224. case 7:
  225. Block4x4Encoding_ETC1::TryDegenerates1();
  226. if (a_fEffort <= 69.5f)
  227. {
  228. m_boolDone = true;
  229. }
  230. break;
  231. case 8:
  232. Block4x4Encoding_ETC1::TryDegenerates2();
  233. if (a_fEffort <= 79.5f)
  234. {
  235. m_boolDone = true;
  236. }
  237. break;
  238. case 9:
  239. Block4x4Encoding_ETC1::TryDegenerates3();
  240. if (a_fEffort <= 89.5f)
  241. {
  242. m_boolDone = true;
  243. }
  244. break;
  245. case 10:
  246. Block4x4Encoding_ETC1::TryDegenerates4();
  247. m_boolDone = true;
  248. break;
  249. default:
  250. assert(0);
  251. break;
  252. }
  253. m_uiEncodingIterations++;
  254. SetDoneIfPerfect();
  255. }
  256. // ----------------------------------------------------------------------------------------------------
  257. // try encoding in Planar mode
  258. // save this encoding if it improves the error
  259. //
  260. void Block4x4Encoding_RGB8::TryPlanar(unsigned int a_uiRadius)
  261. {
  262. Block4x4Encoding_RGB8 encodingTry = *this;
  263. // init "try"
  264. {
  265. encodingTry.m_mode = MODE_PLANAR;
  266. encodingTry.m_boolDiff = true;
  267. encodingTry.m_boolFlip = false;
  268. }
  269. encodingTry.CalculatePlanarCornerColors();
  270. encodingTry.DecodePixels_Planar();
  271. encodingTry.CalcBlockError();
  272. if (a_uiRadius > 0)
  273. {
  274. encodingTry.TwiddlePlanar();
  275. }
  276. if (encodingTry.m_fError < m_fError)
  277. {
  278. m_mode = MODE_PLANAR;
  279. m_boolDiff = true;
  280. m_boolFlip = false;
  281. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  282. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  283. m_frgbaColor3 = encodingTry.m_frgbaColor3;
  284. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  285. {
  286. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  287. }
  288. m_fError = encodingTry.m_fError;
  289. }
  290. }
  291. // ----------------------------------------------------------------------------------------------------
  292. // try encoding in T mode or H mode
  293. // save this encoding if it improves the error
  294. //
  295. void Block4x4Encoding_RGB8::TryTAndH(unsigned int a_uiRadius)
  296. {
  297. CalculateBaseColorsForTAndH();
  298. TryT(a_uiRadius);
  299. TryH(a_uiRadius);
  300. }
  301. // ----------------------------------------------------------------------------------------------------
  302. // calculate original values for base colors
  303. // store them in m_frgbaOriginalColor1 and m_frgbaOriginalColor2
  304. //
  305. void Block4x4Encoding_RGB8::CalculateBaseColorsForTAndH(void)
  306. {
  307. bool boolRGBX = m_pblockParent->GetImageSource()->GetErrorMetric() == ErrorMetric::RGBX;
  308. ColorFloatRGBA frgbaBlockAverage = (m_frgbaSourceAverageLeft + m_frgbaSourceAverageRight) * 0.5f;
  309. // find pixel farthest from average gray line
  310. unsigned int uiFarthestPixel = 0;
  311. float fFarthestGrayDistance2 = 0.0f;
  312. unsigned int uiTransparentPixels = 0;
  313. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  314. {
  315. // don't count transparent
  316. if (m_pafrgbaSource[uiPixel].fA == 0.0f && !boolRGBX)
  317. {
  318. uiTransparentPixels++;
  319. }
  320. else
  321. {
  322. float fGrayDistance2 = CalcGrayDistance2(m_pafrgbaSource[uiPixel], frgbaBlockAverage);
  323. if (fGrayDistance2 > fFarthestGrayDistance2)
  324. {
  325. uiFarthestPixel = uiPixel;
  326. fFarthestGrayDistance2 = fGrayDistance2;
  327. }
  328. }
  329. }
  330. // a transparent block should not reach this method
  331. assert(uiTransparentPixels < PIXELS);
  332. // set the original base colors to:
  333. // half way to the farthest pixel and
  334. // the mirror color on the other side of the average
  335. ColorFloatRGBA frgbaOffset = (m_pafrgbaSource[uiFarthestPixel] - frgbaBlockAverage) * 0.5f;
  336. m_frgbaOriginalColor1_TAndH = (frgbaBlockAverage + frgbaOffset).QuantizeR4G4B4();
  337. m_frgbaOriginalColor2_TAndH = (frgbaBlockAverage - frgbaOffset).ClampRGB().QuantizeR4G4B4(); // the "other side" might be out of range
  338. // move base colors to find best fit
  339. for (unsigned int uiIteration = 0; uiIteration < 10; uiIteration++)
  340. {
  341. // find the center of pixels closest to each color
  342. float fPixelsCloserToColor1 = 0.0f;
  343. ColorFloatRGBA frgbSumPixelsCloserToColor1;
  344. float fPixelsCloserToColor2 = 0.0f;
  345. ColorFloatRGBA frgbSumPixelsCloserToColor2;
  346. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  347. {
  348. // don't count transparent pixels
  349. if (m_pafrgbaSource[uiPixel].fA == 0.0f)
  350. {
  351. continue;
  352. }
  353. float fGrayDistance2ToColor1 = CalcGrayDistance2(m_pafrgbaSource[uiPixel], m_frgbaOriginalColor1_TAndH);
  354. float fGrayDistance2ToColor2 = CalcGrayDistance2(m_pafrgbaSource[uiPixel], m_frgbaOriginalColor2_TAndH);
  355. ColorFloatRGBA frgbaAlphaWeightedSource = m_pafrgbaSource[uiPixel] * m_pafrgbaSource[uiPixel].fA;
  356. if (fGrayDistance2ToColor1 <= fGrayDistance2ToColor2)
  357. {
  358. fPixelsCloserToColor1 += m_pafrgbaSource[uiPixel].fA;
  359. frgbSumPixelsCloserToColor1 = frgbSumPixelsCloserToColor1 + frgbaAlphaWeightedSource;
  360. }
  361. else
  362. {
  363. fPixelsCloserToColor2 += m_pafrgbaSource[uiPixel].fA;
  364. frgbSumPixelsCloserToColor2 = frgbSumPixelsCloserToColor2 + frgbaAlphaWeightedSource;
  365. }
  366. }
  367. if (fPixelsCloserToColor1 == 0.0f || fPixelsCloserToColor2 == 0.0f)
  368. {
  369. break;
  370. }
  371. ColorFloatRGBA frgbAvgColor1Pixels = (frgbSumPixelsCloserToColor1 * (1.0f / fPixelsCloserToColor1)).QuantizeR4G4B4();
  372. ColorFloatRGBA frgbAvgColor2Pixels = (frgbSumPixelsCloserToColor2 * (1.0f / fPixelsCloserToColor2)).QuantizeR4G4B4();
  373. if (frgbAvgColor1Pixels.fR == m_frgbaOriginalColor1_TAndH.fR &&
  374. frgbAvgColor1Pixels.fG == m_frgbaOriginalColor1_TAndH.fG &&
  375. frgbAvgColor1Pixels.fB == m_frgbaOriginalColor1_TAndH.fB &&
  376. frgbAvgColor2Pixels.fR == m_frgbaOriginalColor2_TAndH.fR &&
  377. frgbAvgColor2Pixels.fG == m_frgbaOriginalColor2_TAndH.fG &&
  378. frgbAvgColor2Pixels.fB == m_frgbaOriginalColor2_TAndH.fB)
  379. {
  380. break;
  381. }
  382. m_frgbaOriginalColor1_TAndH = frgbAvgColor1Pixels;
  383. m_frgbaOriginalColor2_TAndH = frgbAvgColor2Pixels;
  384. }
  385. }
  386. // ----------------------------------------------------------------------------------------------------
  387. // try encoding in T mode
  388. // save this encoding if it improves the error
  389. //
  390. // since pixels that use base color1 don't use the distance table, color1 and color2 can be twiddled independently
  391. // better encoding can be found if TWIDDLE_RADIUS is set to 2, but it will be much slower
  392. //
  393. void Block4x4Encoding_RGB8::TryT(unsigned int a_uiRadius)
  394. {
  395. Block4x4Encoding_RGB8 encodingTry = *this;
  396. // init "try"
  397. {
  398. encodingTry.m_mode = MODE_T;
  399. encodingTry.m_boolDiff = true;
  400. encodingTry.m_boolFlip = false;
  401. encodingTry.m_fError = FLT_MAX;
  402. }
  403. int iColor1Red = m_frgbaOriginalColor1_TAndH.IntRed(15.0f);
  404. int iColor1Green = m_frgbaOriginalColor1_TAndH.IntGreen(15.0f);
  405. int iColor1Blue = m_frgbaOriginalColor1_TAndH.IntBlue(15.0f);
  406. int iMinRed1 = iColor1Red - (int)a_uiRadius;
  407. if (iMinRed1 < 0)
  408. {
  409. iMinRed1 = 0;
  410. }
  411. int iMaxRed1 = iColor1Red + (int)a_uiRadius;
  412. if (iMaxRed1 > 15)
  413. {
  414. iMaxRed1 = 15;
  415. }
  416. int iMinGreen1 = iColor1Green - (int)a_uiRadius;
  417. if (iMinGreen1 < 0)
  418. {
  419. iMinGreen1 = 0;
  420. }
  421. int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
  422. if (iMaxGreen1 > 15)
  423. {
  424. iMaxGreen1 = 15;
  425. }
  426. int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
  427. if (iMinBlue1 < 0)
  428. {
  429. iMinBlue1 = 0;
  430. }
  431. int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
  432. if (iMaxBlue1 > 15)
  433. {
  434. iMaxBlue1 = 15;
  435. }
  436. int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
  437. int iColor2Green = m_frgbaOriginalColor2_TAndH.IntGreen(15.0f);
  438. int iColor2Blue = m_frgbaOriginalColor2_TAndH.IntBlue(15.0f);
  439. int iMinRed2 = iColor2Red - (int)a_uiRadius;
  440. if (iMinRed2 < 0)
  441. {
  442. iMinRed2 = 0;
  443. }
  444. int iMaxRed2 = iColor2Red + (int)a_uiRadius;
  445. if (iMaxRed2 > 15)
  446. {
  447. iMaxRed2 = 15;
  448. }
  449. int iMinGreen2 = iColor2Green - (int)a_uiRadius;
  450. if (iMinGreen2 < 0)
  451. {
  452. iMinGreen2 = 0;
  453. }
  454. int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
  455. if (iMaxGreen2 > 15)
  456. {
  457. iMaxGreen2 = 15;
  458. }
  459. int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
  460. if (iMinBlue2 < 0)
  461. {
  462. iMinBlue2 = 0;
  463. }
  464. int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
  465. if (iMaxBlue2 > 15)
  466. {
  467. iMaxBlue2 = 15;
  468. }
  469. for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
  470. {
  471. encodingTry.m_uiCW1 = uiDistance;
  472. // twiddle m_frgbaOriginalColor2_TAndH
  473. // twiddle color2 first, since it affects 3 selectors, while color1 only affects one selector
  474. //
  475. for (int iRed2 = iMinRed2; iRed2 <= iMaxRed2; iRed2++)
  476. {
  477. for (int iGreen2 = iMinGreen2; iGreen2 <= iMaxGreen2; iGreen2++)
  478. {
  479. for (int iBlue2 = iMinBlue2; iBlue2 <= iMaxBlue2; iBlue2++)
  480. {
  481. for (unsigned int uiBaseColorSwaps = 0; uiBaseColorSwaps < 2; uiBaseColorSwaps++)
  482. {
  483. if (uiBaseColorSwaps == 0)
  484. {
  485. encodingTry.m_frgbaColor1 = m_frgbaOriginalColor1_TAndH;
  486. encodingTry.m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed2, (unsigned char)iGreen2, (unsigned char)iBlue2);
  487. }
  488. else
  489. {
  490. encodingTry.m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed2, (unsigned char)iGreen2, (unsigned char)iBlue2);
  491. encodingTry.m_frgbaColor2 = m_frgbaOriginalColor1_TAndH;
  492. }
  493. encodingTry.TryT_BestSelectorCombination();
  494. if (encodingTry.m_fError < m_fError)
  495. {
  496. m_mode = encodingTry.m_mode;
  497. m_boolDiff = encodingTry.m_boolDiff;
  498. m_boolFlip = encodingTry.m_boolFlip;
  499. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  500. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  501. m_uiCW1 = encodingTry.m_uiCW1;
  502. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  503. {
  504. m_auiSelectors[uiPixel] = encodingTry.m_auiSelectors[uiPixel];
  505. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  506. }
  507. m_fError = encodingTry.m_fError;
  508. }
  509. }
  510. }
  511. }
  512. }
  513. // twiddle m_frgbaOriginalColor1_TAndH
  514. for (int iRed1 = iMinRed1; iRed1 <= iMaxRed1; iRed1++)
  515. {
  516. for (int iGreen1 = iMinGreen1; iGreen1 <= iMaxGreen1; iGreen1++)
  517. {
  518. for (int iBlue1 = iMinBlue1; iBlue1 <= iMaxBlue1; iBlue1++)
  519. {
  520. for (unsigned int uiBaseColorSwaps = 0; uiBaseColorSwaps < 2; uiBaseColorSwaps++)
  521. {
  522. if (uiBaseColorSwaps == 0)
  523. {
  524. encodingTry.m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed1, (unsigned char)iGreen1, (unsigned char)iBlue1);
  525. encodingTry.m_frgbaColor2 = m_frgbaOriginalColor2_TAndH;
  526. }
  527. else
  528. {
  529. encodingTry.m_frgbaColor1 = m_frgbaOriginalColor2_TAndH;
  530. encodingTry.m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed1, (unsigned char)iGreen1, (unsigned char)iBlue1);
  531. }
  532. encodingTry.TryT_BestSelectorCombination();
  533. if (encodingTry.m_fError < m_fError)
  534. {
  535. m_mode = encodingTry.m_mode;
  536. m_boolDiff = encodingTry.m_boolDiff;
  537. m_boolFlip = encodingTry.m_boolFlip;
  538. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  539. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  540. m_uiCW1 = encodingTry.m_uiCW1;
  541. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  542. {
  543. m_auiSelectors[uiPixel] = encodingTry.m_auiSelectors[uiPixel];
  544. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  545. }
  546. m_fError = encodingTry.m_fError;
  547. }
  548. }
  549. }
  550. }
  551. }
  552. }
  553. }
  554. // ----------------------------------------------------------------------------------------------------
  555. // find best selector combination for TryT
  556. // called on an encodingTry
  557. //
  558. void Block4x4Encoding_RGB8::TryT_BestSelectorCombination(void)
  559. {
  560. float fDistance = s_afTHDistanceTable[m_uiCW1];
  561. unsigned int auiBestPixelSelectors[PIXELS];
  562. float afBestPixelErrors[PIXELS] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX,
  563. FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  564. ColorFloatRGBA afrgbaBestDecodedPixels[PIXELS];
  565. ColorFloatRGBA afrgbaDecodedPixel[SELECTORS];
  566. assert(SELECTORS == 4);
  567. afrgbaDecodedPixel[0] = m_frgbaColor1;
  568. afrgbaDecodedPixel[1] = (m_frgbaColor2 + fDistance).ClampRGB();
  569. afrgbaDecodedPixel[2] = m_frgbaColor2;
  570. afrgbaDecodedPixel[3] = (m_frgbaColor2 - fDistance).ClampRGB();
  571. // try each selector
  572. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  573. {
  574. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  575. {
  576. float fPixelError = CalcPixelError(afrgbaDecodedPixel[uiSelector], m_afDecodedAlphas[uiPixel],
  577. m_pafrgbaSource[uiPixel]);
  578. if (fPixelError < afBestPixelErrors[uiPixel])
  579. {
  580. afBestPixelErrors[uiPixel] = fPixelError;
  581. auiBestPixelSelectors[uiPixel] = uiSelector;
  582. afrgbaBestDecodedPixels[uiPixel] = afrgbaDecodedPixel[uiSelector];
  583. }
  584. }
  585. }
  586. // add up all of the pixel errors
  587. float fBlockError = 0.0f;
  588. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  589. {
  590. fBlockError += afBestPixelErrors[uiPixel];
  591. }
  592. if (fBlockError < m_fError)
  593. {
  594. m_fError = fBlockError;
  595. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  596. {
  597. m_auiSelectors[uiPixel] = auiBestPixelSelectors[uiPixel];
  598. m_afrgbaDecodedColors[uiPixel] = afrgbaBestDecodedPixels[uiPixel];
  599. }
  600. }
  601. }
  602. // ----------------------------------------------------------------------------------------------------
  603. // try encoding in T mode
  604. // save this encoding if it improves the error
  605. //
  606. // since all pixels use the distance table, color1 and color2 can NOT be twiddled independently
  607. // TWIDDLE_RADIUS of 2 is WAY too slow
  608. //
  609. void Block4x4Encoding_RGB8::TryH(unsigned int a_uiRadius)
  610. {
  611. Block4x4Encoding_RGB8 encodingTry = *this;
  612. // init "try"
  613. {
  614. encodingTry.m_mode = MODE_H;
  615. encodingTry.m_boolDiff = true;
  616. encodingTry.m_boolFlip = false;
  617. encodingTry.m_fError = FLT_MAX;
  618. }
  619. int iColor1Red = m_frgbaOriginalColor1_TAndH.IntRed(15.0f);
  620. int iColor1Green = m_frgbaOriginalColor1_TAndH.IntGreen(15.0f);
  621. int iColor1Blue = m_frgbaOriginalColor1_TAndH.IntBlue(15.0f);
  622. int iMinRed1 = iColor1Red - (int)a_uiRadius;
  623. if (iMinRed1 < 0)
  624. {
  625. iMinRed1 = 0;
  626. }
  627. int iMaxRed1 = iColor1Red + (int)a_uiRadius;
  628. if (iMaxRed1 > 15)
  629. {
  630. iMaxRed1 = 15;
  631. }
  632. int iMinGreen1 = iColor1Green - (int)a_uiRadius;
  633. if (iMinGreen1 < 0)
  634. {
  635. iMinGreen1 = 0;
  636. }
  637. int iMaxGreen1 = iColor1Green + (int)a_uiRadius;
  638. if (iMaxGreen1 > 15)
  639. {
  640. iMaxGreen1 = 15;
  641. }
  642. int iMinBlue1 = iColor1Blue - (int)a_uiRadius;
  643. if (iMinBlue1 < 0)
  644. {
  645. iMinBlue1 = 0;
  646. }
  647. int iMaxBlue1 = iColor1Blue + (int)a_uiRadius;
  648. if (iMaxBlue1 > 15)
  649. {
  650. iMaxBlue1 = 15;
  651. }
  652. int iColor2Red = m_frgbaOriginalColor2_TAndH.IntRed(15.0f);
  653. int iColor2Green = m_frgbaOriginalColor2_TAndH.IntGreen(15.0f);
  654. int iColor2Blue = m_frgbaOriginalColor2_TAndH.IntBlue(15.0f);
  655. int iMinRed2 = iColor2Red - (int)a_uiRadius;
  656. if (iMinRed2 < 0)
  657. {
  658. iMinRed2 = 0;
  659. }
  660. int iMaxRed2 = iColor2Red + (int)a_uiRadius;
  661. if (iMaxRed2 > 15)
  662. {
  663. iMaxRed2 = 15;
  664. }
  665. int iMinGreen2 = iColor2Green - (int)a_uiRadius;
  666. if (iMinGreen2 < 0)
  667. {
  668. iMinGreen2 = 0;
  669. }
  670. int iMaxGreen2 = iColor2Green + (int)a_uiRadius;
  671. if (iMaxGreen2 > 15)
  672. {
  673. iMaxGreen2 = 15;
  674. }
  675. int iMinBlue2 = iColor2Blue - (int)a_uiRadius;
  676. if (iMinBlue2 < 0)
  677. {
  678. iMinBlue2 = 0;
  679. }
  680. int iMaxBlue2 = iColor2Blue + (int)a_uiRadius;
  681. if (iMaxBlue2 > 15)
  682. {
  683. iMaxBlue2 = 15;
  684. }
  685. for (unsigned int uiDistance = 0; uiDistance < TH_DISTANCES; uiDistance++)
  686. {
  687. encodingTry.m_uiCW1 = uiDistance;
  688. // twiddle m_frgbaOriginalColor1_TAndH
  689. for (int iRed1 = iMinRed1; iRed1 <= iMaxRed1; iRed1++)
  690. {
  691. for (int iGreen1 = iMinGreen1; iGreen1 <= iMaxGreen1; iGreen1++)
  692. {
  693. for (int iBlue1 = iMinBlue1; iBlue1 <= iMaxBlue1; iBlue1++)
  694. {
  695. encodingTry.m_frgbaColor1 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed1, (unsigned char)iGreen1, (unsigned char)iBlue1);
  696. encodingTry.m_frgbaColor2 = m_frgbaOriginalColor2_TAndH;
  697. // if color1 == color2, H encoding issues can pop up, so abort
  698. if (iRed1 == iColor2Red && iGreen1 == iColor2Green && iBlue1 == iColor2Blue)
  699. {
  700. continue;
  701. }
  702. encodingTry.TryH_BestSelectorCombination();
  703. if (encodingTry.m_fError < m_fError)
  704. {
  705. m_mode = encodingTry.m_mode;
  706. m_boolDiff = encodingTry.m_boolDiff;
  707. m_boolFlip = encodingTry.m_boolFlip;
  708. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  709. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  710. m_uiCW1 = encodingTry.m_uiCW1;
  711. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  712. {
  713. m_auiSelectors[uiPixel] = encodingTry.m_auiSelectors[uiPixel];
  714. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  715. }
  716. m_fError = encodingTry.m_fError;
  717. }
  718. }
  719. }
  720. }
  721. // twiddle m_frgbaOriginalColor2_TAndH
  722. for (int iRed2 = iMinRed2; iRed2 <= iMaxRed2; iRed2++)
  723. {
  724. for (int iGreen2 = iMinGreen2; iGreen2 <= iMaxGreen2; iGreen2++)
  725. {
  726. for (int iBlue2 = iMinBlue2; iBlue2 <= iMaxBlue2; iBlue2++)
  727. {
  728. encodingTry.m_frgbaColor1 = m_frgbaOriginalColor1_TAndH;
  729. encodingTry.m_frgbaColor2 = ColorFloatRGBA::ConvertFromRGB4((unsigned char)iRed2, (unsigned char)iGreen2, (unsigned char)iBlue2);
  730. // if color1 == color2, H encoding issues can pop up, so abort
  731. if (iRed2 == iColor1Red && iGreen2 == iColor1Green && iBlue2 == iColor1Blue)
  732. {
  733. continue;
  734. }
  735. encodingTry.TryH_BestSelectorCombination();
  736. if (encodingTry.m_fError < m_fError)
  737. {
  738. m_mode = encodingTry.m_mode;
  739. m_boolDiff = encodingTry.m_boolDiff;
  740. m_boolFlip = encodingTry.m_boolFlip;
  741. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  742. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  743. m_uiCW1 = encodingTry.m_uiCW1;
  744. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  745. {
  746. m_auiSelectors[uiPixel] = encodingTry.m_auiSelectors[uiPixel];
  747. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  748. }
  749. m_fError = encodingTry.m_fError;
  750. }
  751. }
  752. }
  753. }
  754. }
  755. }
  756. // ----------------------------------------------------------------------------------------------------
  757. // find best selector combination for TryH
  758. // called on an encodingTry
  759. //
  760. void Block4x4Encoding_RGB8::TryH_BestSelectorCombination(void)
  761. {
  762. float fDistance = s_afTHDistanceTable[m_uiCW1];
  763. unsigned int auiBestPixelSelectors[PIXELS];
  764. float afBestPixelErrors[PIXELS] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX,
  765. FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX };
  766. ColorFloatRGBA afrgbaBestDecodedPixels[PIXELS];
  767. ColorFloatRGBA afrgbaDecodedPixel[SELECTORS];
  768. assert(SELECTORS == 4);
  769. afrgbaDecodedPixel[0] = (m_frgbaColor1 + fDistance).ClampRGB();
  770. afrgbaDecodedPixel[1] = (m_frgbaColor1 - fDistance).ClampRGB();
  771. afrgbaDecodedPixel[2] = (m_frgbaColor2 + fDistance).ClampRGB();
  772. afrgbaDecodedPixel[3] = (m_frgbaColor2 - fDistance).ClampRGB();
  773. // try each selector
  774. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  775. {
  776. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  777. {
  778. float fPixelError = CalcPixelError(afrgbaDecodedPixel[uiSelector], m_afDecodedAlphas[uiPixel],
  779. m_pafrgbaSource[uiPixel]);
  780. if (fPixelError < afBestPixelErrors[uiPixel])
  781. {
  782. afBestPixelErrors[uiPixel] = fPixelError;
  783. auiBestPixelSelectors[uiPixel] = uiSelector;
  784. afrgbaBestDecodedPixels[uiPixel] = afrgbaDecodedPixel[uiSelector];
  785. }
  786. }
  787. }
  788. // add up all of the pixel errors
  789. float fBlockError = 0.0f;
  790. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  791. {
  792. fBlockError += afBestPixelErrors[uiPixel];
  793. }
  794. if (fBlockError < m_fError)
  795. {
  796. m_fError = fBlockError;
  797. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  798. {
  799. m_auiSelectors[uiPixel] = auiBestPixelSelectors[uiPixel];
  800. m_afrgbaDecodedColors[uiPixel] = afrgbaBestDecodedPixels[uiPixel];
  801. }
  802. }
  803. }
  804. // ----------------------------------------------------------------------------------------------------
  805. // use linear regression to find the best fit for colors along the edges of the 4x4 block
  806. //
  807. void Block4x4Encoding_RGB8::CalculatePlanarCornerColors(void)
  808. {
  809. ColorFloatRGBA afrgbaRegression[MAX_PLANAR_REGRESSION_SIZE];
  810. ColorFloatRGBA frgbaSlope;
  811. ColorFloatRGBA frgbaOffset;
  812. // top edge
  813. afrgbaRegression[0] = m_pafrgbaSource[0];
  814. afrgbaRegression[1] = m_pafrgbaSource[4];
  815. afrgbaRegression[2] = m_pafrgbaSource[8];
  816. afrgbaRegression[3] = m_pafrgbaSource[12];
  817. ColorRegression(afrgbaRegression, 4, &frgbaSlope, &frgbaOffset);
  818. m_frgbaColor1 = frgbaOffset;
  819. m_frgbaColor2 = (frgbaSlope * 4.0f) + frgbaOffset;
  820. // left edge
  821. afrgbaRegression[0] = m_pafrgbaSource[0];
  822. afrgbaRegression[1] = m_pafrgbaSource[1];
  823. afrgbaRegression[2] = m_pafrgbaSource[2];
  824. afrgbaRegression[3] = m_pafrgbaSource[3];
  825. ColorRegression(afrgbaRegression, 4, &frgbaSlope, &frgbaOffset);
  826. m_frgbaColor1 = (m_frgbaColor1 + frgbaOffset) * 0.5f; // average with top edge
  827. m_frgbaColor3 = (frgbaSlope * 4.0f) + frgbaOffset;
  828. // right edge
  829. afrgbaRegression[0] = m_pafrgbaSource[12];
  830. afrgbaRegression[1] = m_pafrgbaSource[13];
  831. afrgbaRegression[2] = m_pafrgbaSource[14];
  832. afrgbaRegression[3] = m_pafrgbaSource[15];
  833. ColorRegression(afrgbaRegression, 4, &frgbaSlope, &frgbaOffset);
  834. m_frgbaColor2 = (m_frgbaColor2 + frgbaOffset) * 0.5f; // average with top edge
  835. // bottom edge
  836. afrgbaRegression[0] = m_pafrgbaSource[3];
  837. afrgbaRegression[1] = m_pafrgbaSource[7];
  838. afrgbaRegression[2] = m_pafrgbaSource[11];
  839. afrgbaRegression[3] = m_pafrgbaSource[15];
  840. ColorRegression(afrgbaRegression, 4, &frgbaSlope, &frgbaOffset);
  841. m_frgbaColor3 = (m_frgbaColor3 + frgbaOffset) * 0.5f; // average with left edge
  842. // quantize corner colors to 6/7/6
  843. m_frgbaColor1 = m_frgbaColor1.QuantizeR6G7B6();
  844. m_frgbaColor2 = m_frgbaColor2.QuantizeR6G7B6();
  845. m_frgbaColor3 = m_frgbaColor3.QuantizeR6G7B6();
  846. }
  847. // ----------------------------------------------------------------------------------------------------
  848. // try different corner colors by slightly changing R, G and B independently
  849. //
  850. // R, G and B decoding and errors are independent, so R, G and B twiddles can be independent
  851. //
  852. // return true if improvement
  853. //
  854. bool Block4x4Encoding_RGB8::TwiddlePlanar(void)
  855. {
  856. bool boolImprovement = false;
  857. while (TwiddlePlanarR())
  858. {
  859. boolImprovement = true;
  860. }
  861. while (TwiddlePlanarG())
  862. {
  863. boolImprovement = true;
  864. }
  865. while (TwiddlePlanarB())
  866. {
  867. boolImprovement = true;
  868. }
  869. return boolImprovement;
  870. }
  871. // ----------------------------------------------------------------------------------------------------
  872. // try different corner colors by slightly changing R
  873. //
  874. bool Block4x4Encoding_RGB8::TwiddlePlanarR()
  875. {
  876. bool boolImprovement = false;
  877. Block4x4Encoding_RGB8 encodingTry = *this;
  878. // init "try"
  879. {
  880. encodingTry.m_mode = MODE_PLANAR;
  881. encodingTry.m_boolDiff = true;
  882. encodingTry.m_boolFlip = false;
  883. }
  884. int iOriginRed = encodingTry.m_frgbaColor1.IntRed(63.0f);
  885. int iHorizRed = encodingTry.m_frgbaColor2.IntRed(63.0f);
  886. int iVertRed = encodingTry.m_frgbaColor3.IntRed(63.0f);
  887. for (int iTryOriginRed = iOriginRed - 1; iTryOriginRed <= iOriginRed + 1; iTryOriginRed++)
  888. {
  889. // check for out of range
  890. if (iTryOriginRed < 0 || iTryOriginRed > 63)
  891. {
  892. continue;
  893. }
  894. encodingTry.m_frgbaColor1.fR = ((iTryOriginRed << 2) + (iTryOriginRed >> 4)) / 255.0f;
  895. for (int iTryHorizRed = iHorizRed - 1; iTryHorizRed <= iHorizRed + 1; iTryHorizRed++)
  896. {
  897. // check for out of range
  898. if (iTryHorizRed < 0 || iTryHorizRed > 63)
  899. {
  900. continue;
  901. }
  902. encodingTry.m_frgbaColor2.fR = ((iTryHorizRed << 2) + (iTryHorizRed >> 4)) / 255.0f;
  903. for (int iTryVertRed = iVertRed - 1; iTryVertRed <= iVertRed + 1; iTryVertRed++)
  904. {
  905. // check for out of range
  906. if (iTryVertRed < 0 || iTryVertRed > 63)
  907. {
  908. continue;
  909. }
  910. // don't bother with null twiddle
  911. if (iTryOriginRed == iOriginRed && iTryHorizRed == iHorizRed && iTryVertRed == iVertRed)
  912. {
  913. continue;
  914. }
  915. encodingTry.m_frgbaColor3.fR = ((iTryVertRed << 2) + (iTryVertRed >> 4)) / 255.0f;
  916. encodingTry.DecodePixels_Planar();
  917. encodingTry.CalcBlockError();
  918. if (encodingTry.m_fError < m_fError)
  919. {
  920. m_mode = MODE_PLANAR;
  921. m_boolDiff = true;
  922. m_boolFlip = false;
  923. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  924. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  925. m_frgbaColor3 = encodingTry.m_frgbaColor3;
  926. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  927. {
  928. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  929. }
  930. m_fError = encodingTry.m_fError;
  931. boolImprovement = true;
  932. }
  933. }
  934. }
  935. }
  936. return boolImprovement;
  937. }
  938. // ----------------------------------------------------------------------------------------------------
  939. // try different corner colors by slightly changing G
  940. //
  941. bool Block4x4Encoding_RGB8::TwiddlePlanarG()
  942. {
  943. bool boolImprovement = false;
  944. Block4x4Encoding_RGB8 encodingTry = *this;
  945. // init "try"
  946. {
  947. encodingTry.m_mode = MODE_PLANAR;
  948. encodingTry.m_boolDiff = true;
  949. encodingTry.m_boolFlip = false;
  950. }
  951. int iOriginGreen = encodingTry.m_frgbaColor1.IntGreen(127.0f);
  952. int iHorizGreen = encodingTry.m_frgbaColor2.IntGreen(127.0f);
  953. int iVertGreen = encodingTry.m_frgbaColor3.IntGreen(127.0f);
  954. for (int iTryOriginGreen = iOriginGreen - 1; iTryOriginGreen <= iOriginGreen + 1; iTryOriginGreen++)
  955. {
  956. // check for out of range
  957. if (iTryOriginGreen < 0 || iTryOriginGreen > 127)
  958. {
  959. continue;
  960. }
  961. encodingTry.m_frgbaColor1.fG = ((iTryOriginGreen << 1) + (iTryOriginGreen >> 6)) / 255.0f;
  962. for (int iTryHorizGreen = iHorizGreen - 1; iTryHorizGreen <= iHorizGreen + 1; iTryHorizGreen++)
  963. {
  964. // check for out of range
  965. if (iTryHorizGreen < 0 || iTryHorizGreen > 127)
  966. {
  967. continue;
  968. }
  969. encodingTry.m_frgbaColor2.fG = ((iTryHorizGreen << 1) + (iTryHorizGreen >> 6)) / 255.0f;
  970. for (int iTryVertGreen = iVertGreen - 1; iTryVertGreen <= iVertGreen + 1; iTryVertGreen++)
  971. {
  972. // check for out of range
  973. if (iTryVertGreen < 0 || iTryVertGreen > 127)
  974. {
  975. continue;
  976. }
  977. // don't bother with null twiddle
  978. if (iTryOriginGreen == iOriginGreen &&
  979. iTryHorizGreen == iHorizGreen &&
  980. iTryVertGreen == iVertGreen)
  981. {
  982. continue;
  983. }
  984. encodingTry.m_frgbaColor3.fG = ((iTryVertGreen << 1) + (iTryVertGreen >> 6)) / 255.0f;
  985. encodingTry.DecodePixels_Planar();
  986. encodingTry.CalcBlockError();
  987. if (encodingTry.m_fError < m_fError)
  988. {
  989. m_mode = MODE_PLANAR;
  990. m_boolDiff = true;
  991. m_boolFlip = false;
  992. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  993. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  994. m_frgbaColor3 = encodingTry.m_frgbaColor3;
  995. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  996. {
  997. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  998. }
  999. m_fError = encodingTry.m_fError;
  1000. boolImprovement = true;
  1001. }
  1002. }
  1003. }
  1004. }
  1005. return boolImprovement;
  1006. }
  1007. // ----------------------------------------------------------------------------------------------------
  1008. // try different corner colors by slightly changing B
  1009. //
  1010. bool Block4x4Encoding_RGB8::TwiddlePlanarB()
  1011. {
  1012. bool boolImprovement = false;
  1013. Block4x4Encoding_RGB8 encodingTry = *this;
  1014. // init "try"
  1015. {
  1016. encodingTry.m_mode = MODE_PLANAR;
  1017. encodingTry.m_boolDiff = true;
  1018. encodingTry.m_boolFlip = false;
  1019. }
  1020. int iOriginBlue = encodingTry.m_frgbaColor1.IntBlue(63.0f);
  1021. int iHorizBlue = encodingTry.m_frgbaColor2.IntBlue(63.0f);
  1022. int iVertBlue = encodingTry.m_frgbaColor3.IntBlue(63.0f);
  1023. for (int iTryOriginBlue = iOriginBlue - 1; iTryOriginBlue <= iOriginBlue + 1; iTryOriginBlue++)
  1024. {
  1025. // check for out of range
  1026. if (iTryOriginBlue < 0 || iTryOriginBlue > 63)
  1027. {
  1028. continue;
  1029. }
  1030. encodingTry.m_frgbaColor1.fB = ((iTryOriginBlue << 2) + (iTryOriginBlue >> 4)) / 255.0f;
  1031. for (int iTryHorizBlue = iHorizBlue - 1; iTryHorizBlue <= iHorizBlue + 1; iTryHorizBlue++)
  1032. {
  1033. // check for out of range
  1034. if (iTryHorizBlue < 0 || iTryHorizBlue > 63)
  1035. {
  1036. continue;
  1037. }
  1038. encodingTry.m_frgbaColor2.fB = ((iTryHorizBlue << 2) + (iTryHorizBlue >> 4)) / 255.0f;
  1039. for (int iTryVertBlue = iVertBlue - 1; iTryVertBlue <= iVertBlue + 1; iTryVertBlue++)
  1040. {
  1041. // check for out of range
  1042. if (iTryVertBlue < 0 || iTryVertBlue > 63)
  1043. {
  1044. continue;
  1045. }
  1046. // don't bother with null twiddle
  1047. if (iTryOriginBlue == iOriginBlue && iTryHorizBlue == iHorizBlue && iTryVertBlue == iVertBlue)
  1048. {
  1049. continue;
  1050. }
  1051. encodingTry.m_frgbaColor3.fB = ((iTryVertBlue << 2) + (iTryVertBlue >> 4)) / 255.0f;
  1052. encodingTry.DecodePixels_Planar();
  1053. encodingTry.CalcBlockError();
  1054. if (encodingTry.m_fError < m_fError)
  1055. {
  1056. m_mode = MODE_PLANAR;
  1057. m_boolDiff = true;
  1058. m_boolFlip = false;
  1059. m_frgbaColor1 = encodingTry.m_frgbaColor1;
  1060. m_frgbaColor2 = encodingTry.m_frgbaColor2;
  1061. m_frgbaColor3 = encodingTry.m_frgbaColor3;
  1062. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  1063. {
  1064. m_afrgbaDecodedColors[uiPixel] = encodingTry.m_afrgbaDecodedColors[uiPixel];
  1065. }
  1066. m_fError = encodingTry.m_fError;
  1067. boolImprovement = true;
  1068. }
  1069. }
  1070. }
  1071. }
  1072. return boolImprovement;
  1073. }
  1074. // ----------------------------------------------------------------------------------------------------
  1075. // set the encoding bits based on encoding state
  1076. //
  1077. void Block4x4Encoding_RGB8::SetEncodingBits(void)
  1078. {
  1079. switch (m_mode)
  1080. {
  1081. case MODE_ETC1:
  1082. Block4x4Encoding_ETC1::SetEncodingBits();
  1083. break;
  1084. case MODE_T:
  1085. SetEncodingBits_T();
  1086. break;
  1087. case MODE_H:
  1088. SetEncodingBits_H();
  1089. break;
  1090. case MODE_PLANAR:
  1091. SetEncodingBits_Planar();
  1092. break;
  1093. default:
  1094. assert(false);
  1095. }
  1096. }
  1097. // ----------------------------------------------------------------------------------------------------
  1098. // set the encoding bits based on encoding state for T mode
  1099. //
  1100. void Block4x4Encoding_RGB8::SetEncodingBits_T(void)
  1101. {
  1102. static const bool SANITY_CHECK = true;
  1103. assert(m_mode == MODE_T);
  1104. assert(m_boolDiff == true);
  1105. unsigned int uiRed1 = (unsigned int)m_frgbaColor1.IntRed(15.0f);
  1106. unsigned int uiGreen1 = (unsigned int)m_frgbaColor1.IntGreen(15.0f);
  1107. unsigned int uiBlue1 = (unsigned int)m_frgbaColor1.IntBlue(15.0f);
  1108. unsigned int uiRed2 = (unsigned int)m_frgbaColor2.IntRed(15.0f);
  1109. unsigned int uiGreen2 = (unsigned int)m_frgbaColor2.IntGreen(15.0f);
  1110. unsigned int uiBlue2 = (unsigned int)m_frgbaColor2.IntBlue(15.0f);
  1111. m_pencodingbitsRGB8->t.red1a = uiRed1 >> 2;
  1112. m_pencodingbitsRGB8->t.red1b = uiRed1;
  1113. m_pencodingbitsRGB8->t.green1 = uiGreen1;
  1114. m_pencodingbitsRGB8->t.blue1 = uiBlue1;
  1115. m_pencodingbitsRGB8->t.red2 = uiRed2;
  1116. m_pencodingbitsRGB8->t.green2 = uiGreen2;
  1117. m_pencodingbitsRGB8->t.blue2 = uiBlue2;
  1118. m_pencodingbitsRGB8->t.da = m_uiCW1 >> 1;
  1119. m_pencodingbitsRGB8->t.db = m_uiCW1;
  1120. m_pencodingbitsRGB8->t.diff = 1;
  1121. Block4x4Encoding_ETC1::SetEncodingBits_Selectors();
  1122. // create an invalid R differential to trigger T mode
  1123. m_pencodingbitsRGB8->t.detect1 = 0;
  1124. m_pencodingbitsRGB8->t.detect2 = 0;
  1125. int iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1126. if (iRed2 >= 4)
  1127. {
  1128. m_pencodingbitsRGB8->t.detect1 = 7;
  1129. m_pencodingbitsRGB8->t.detect2 = 0;
  1130. }
  1131. else
  1132. {
  1133. m_pencodingbitsRGB8->t.detect1 = 0;
  1134. m_pencodingbitsRGB8->t.detect2 = 1;
  1135. }
  1136. if (SANITY_CHECK)
  1137. {
  1138. iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1139. // make sure red overflows
  1140. assert(iRed2 < 0 || iRed2 > 31);
  1141. }
  1142. }
  1143. // ----------------------------------------------------------------------------------------------------
  1144. // set the encoding bits based on encoding state for H mode
  1145. //
  1146. // colors and selectors may need to swap in order to generate lsb of distance index
  1147. //
  1148. void Block4x4Encoding_RGB8::SetEncodingBits_H(void)
  1149. {
  1150. static const bool SANITY_CHECK = true;
  1151. assert(m_mode == MODE_H);
  1152. assert(m_boolDiff == true);
  1153. unsigned int uiRed1 = (unsigned int)m_frgbaColor1.IntRed(15.0f);
  1154. unsigned int uiGreen1 = (unsigned int)m_frgbaColor1.IntGreen(15.0f);
  1155. unsigned int uiBlue1 = (unsigned int)m_frgbaColor1.IntBlue(15.0f);
  1156. unsigned int uiRed2 = (unsigned int)m_frgbaColor2.IntRed(15.0f);
  1157. unsigned int uiGreen2 = (unsigned int)m_frgbaColor2.IntGreen(15.0f);
  1158. unsigned int uiBlue2 = (unsigned int)m_frgbaColor2.IntBlue(15.0f);
  1159. unsigned int uiColor1 = (uiRed1 << 16) + (uiGreen1 << 8) + uiBlue1;
  1160. unsigned int uiColor2 = (uiRed2 << 16) + (uiGreen2 << 8) + uiBlue2;
  1161. bool boolOddDistance = m_uiCW1 & 1;
  1162. bool boolSwapColors = (uiColor1 < uiColor2) ^ !boolOddDistance;
  1163. if (boolSwapColors)
  1164. {
  1165. m_pencodingbitsRGB8->h.red1 = uiRed2;
  1166. m_pencodingbitsRGB8->h.green1a = uiGreen2 >> 1;
  1167. m_pencodingbitsRGB8->h.green1b = uiGreen2;
  1168. m_pencodingbitsRGB8->h.blue1a = uiBlue2 >> 3;
  1169. m_pencodingbitsRGB8->h.blue1b = uiBlue2 >> 1;
  1170. m_pencodingbitsRGB8->h.blue1c = uiBlue2;
  1171. m_pencodingbitsRGB8->h.red2 = uiRed1;
  1172. m_pencodingbitsRGB8->h.green2a = uiGreen1 >> 1;
  1173. m_pencodingbitsRGB8->h.green2b = uiGreen1;
  1174. m_pencodingbitsRGB8->h.blue2 = uiBlue1;
  1175. m_pencodingbitsRGB8->h.da = m_uiCW1 >> 2;
  1176. m_pencodingbitsRGB8->h.db = m_uiCW1 >> 1;
  1177. }
  1178. else
  1179. {
  1180. m_pencodingbitsRGB8->h.red1 = uiRed1;
  1181. m_pencodingbitsRGB8->h.green1a = uiGreen1 >> 1;
  1182. m_pencodingbitsRGB8->h.green1b = uiGreen1;
  1183. m_pencodingbitsRGB8->h.blue1a = uiBlue1 >> 3;
  1184. m_pencodingbitsRGB8->h.blue1b = uiBlue1 >> 1;
  1185. m_pencodingbitsRGB8->h.blue1c = uiBlue1;
  1186. m_pencodingbitsRGB8->h.red2 = uiRed2;
  1187. m_pencodingbitsRGB8->h.green2a = uiGreen2 >> 1;
  1188. m_pencodingbitsRGB8->h.green2b = uiGreen2;
  1189. m_pencodingbitsRGB8->h.blue2 = uiBlue2;
  1190. m_pencodingbitsRGB8->h.da = m_uiCW1 >> 2;
  1191. m_pencodingbitsRGB8->h.db = m_uiCW1 >> 1;
  1192. }
  1193. m_pencodingbitsRGB8->h.diff = 1;
  1194. Block4x4Encoding_ETC1::SetEncodingBits_Selectors();
  1195. if (boolSwapColors)
  1196. {
  1197. m_pencodingbitsRGB8->h.selectors ^= 0x0000FFFF;
  1198. }
  1199. // create an invalid R differential to trigger T mode
  1200. m_pencodingbitsRGB8->h.detect1 = 0;
  1201. m_pencodingbitsRGB8->h.detect2 = 0;
  1202. m_pencodingbitsRGB8->h.detect3 = 0;
  1203. int iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1204. int iGreen2 = (int)m_pencodingbitsRGB8->differential.green1 + (int)m_pencodingbitsRGB8->differential.dgreen2;
  1205. if (iRed2 < 0 || iRed2 > 31)
  1206. {
  1207. m_pencodingbitsRGB8->h.detect1 = 1;
  1208. }
  1209. if (iGreen2 >= 4)
  1210. {
  1211. m_pencodingbitsRGB8->h.detect2 = 7;
  1212. m_pencodingbitsRGB8->h.detect3 = 0;
  1213. }
  1214. else
  1215. {
  1216. m_pencodingbitsRGB8->h.detect2 = 0;
  1217. m_pencodingbitsRGB8->h.detect3 = 1;
  1218. }
  1219. if (SANITY_CHECK)
  1220. {
  1221. iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1222. iGreen2 = (int)m_pencodingbitsRGB8->differential.green1 + (int)m_pencodingbitsRGB8->differential.dgreen2;
  1223. // make sure red doesn't overflow and green does
  1224. assert(iRed2 >= 0 && iRed2 <= 31);
  1225. assert(iGreen2 < 0 || iGreen2 > 31);
  1226. }
  1227. }
  1228. // ----------------------------------------------------------------------------------------------------
  1229. // set the encoding bits based on encoding state for Planar mode
  1230. //
  1231. void Block4x4Encoding_RGB8::SetEncodingBits_Planar(void)
  1232. {
  1233. static const bool SANITY_CHECK = true;
  1234. assert(m_mode == MODE_PLANAR);
  1235. assert(m_boolDiff == true);
  1236. unsigned int uiOriginRed = (unsigned int)m_frgbaColor1.IntRed(63.0f);
  1237. unsigned int uiOriginGreen = (unsigned int)m_frgbaColor1.IntGreen(127.0f);
  1238. unsigned int uiOriginBlue = (unsigned int)m_frgbaColor1.IntBlue(63.0f);
  1239. unsigned int uiHorizRed = (unsigned int)m_frgbaColor2.IntRed(63.0f);
  1240. unsigned int uiHorizGreen = (unsigned int)m_frgbaColor2.IntGreen(127.0f);
  1241. unsigned int uiHorizBlue = (unsigned int)m_frgbaColor2.IntBlue(63.0f);
  1242. unsigned int uiVertRed = (unsigned int)m_frgbaColor3.IntRed(63.0f);
  1243. unsigned int uiVertGreen = (unsigned int)m_frgbaColor3.IntGreen(127.0f);
  1244. unsigned int uiVertBlue = (unsigned int)m_frgbaColor3.IntBlue(63.0f);
  1245. m_pencodingbitsRGB8->planar.originRed = uiOriginRed;
  1246. m_pencodingbitsRGB8->planar.originGreen1 = uiOriginGreen >> 6;
  1247. m_pencodingbitsRGB8->planar.originGreen2 = uiOriginGreen;
  1248. m_pencodingbitsRGB8->planar.originBlue1 = uiOriginBlue >> 5;
  1249. m_pencodingbitsRGB8->planar.originBlue2 = uiOriginBlue >> 3;
  1250. m_pencodingbitsRGB8->planar.originBlue3 = uiOriginBlue >> 1;
  1251. m_pencodingbitsRGB8->planar.originBlue4 = uiOriginBlue;
  1252. m_pencodingbitsRGB8->planar.horizRed1 = uiHorizRed >> 1;
  1253. m_pencodingbitsRGB8->planar.horizRed2 = uiHorizRed;
  1254. m_pencodingbitsRGB8->planar.horizGreen = uiHorizGreen;
  1255. m_pencodingbitsRGB8->planar.horizBlue1 = uiHorizBlue >> 5;
  1256. m_pencodingbitsRGB8->planar.horizBlue2 = uiHorizBlue;
  1257. m_pencodingbitsRGB8->planar.vertRed1 = uiVertRed >> 3;
  1258. m_pencodingbitsRGB8->planar.vertRed2 = uiVertRed;
  1259. m_pencodingbitsRGB8->planar.vertGreen1 = uiVertGreen >> 2;
  1260. m_pencodingbitsRGB8->planar.vertGreen2 = uiVertGreen;
  1261. m_pencodingbitsRGB8->planar.vertBlue = uiVertBlue;
  1262. m_pencodingbitsRGB8->planar.diff = 1;
  1263. // create valid RG differentials and an invalid B differential to trigger planar mode
  1264. m_pencodingbitsRGB8->planar.detect1 = 0;
  1265. m_pencodingbitsRGB8->planar.detect2 = 0;
  1266. m_pencodingbitsRGB8->planar.detect3 = 0;
  1267. m_pencodingbitsRGB8->planar.detect4 = 0;
  1268. int iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1269. int iGreen2 = (int)m_pencodingbitsRGB8->differential.green1 + (int)m_pencodingbitsRGB8->differential.dgreen2;
  1270. int iBlue2 = (int)m_pencodingbitsRGB8->differential.blue1 + (int)m_pencodingbitsRGB8->differential.dblue2;
  1271. if (iRed2 < 0 || iRed2 > 31)
  1272. {
  1273. m_pencodingbitsRGB8->planar.detect1 = 1;
  1274. }
  1275. if (iGreen2 < 0 || iGreen2 > 31)
  1276. {
  1277. m_pencodingbitsRGB8->planar.detect2 = 1;
  1278. }
  1279. if (iBlue2 >= 4)
  1280. {
  1281. m_pencodingbitsRGB8->planar.detect3 = 7;
  1282. m_pencodingbitsRGB8->planar.detect4 = 0;
  1283. }
  1284. else
  1285. {
  1286. m_pencodingbitsRGB8->planar.detect3 = 0;
  1287. m_pencodingbitsRGB8->planar.detect4 = 1;
  1288. }
  1289. if (SANITY_CHECK)
  1290. {
  1291. iRed2 = (int)m_pencodingbitsRGB8->differential.red1 + (int)m_pencodingbitsRGB8->differential.dred2;
  1292. iGreen2 = (int)m_pencodingbitsRGB8->differential.green1 + (int)m_pencodingbitsRGB8->differential.dgreen2;
  1293. iBlue2 = (int)m_pencodingbitsRGB8->differential.blue1 + (int)m_pencodingbitsRGB8->differential.dblue2;
  1294. // make sure red and green don't overflow and blue does
  1295. assert(iRed2 >= 0 && iRed2 <= 31);
  1296. assert(iGreen2 >= 0 && iGreen2 <= 31);
  1297. assert(iBlue2 < 0 || iBlue2 > 31);
  1298. }
  1299. }
  1300. // ----------------------------------------------------------------------------------------------------
  1301. // set the decoded colors and decoded alpha based on the encoding state for T mode
  1302. //
  1303. void Block4x4Encoding_RGB8::DecodePixels_T(void)
  1304. {
  1305. float fDistance = s_afTHDistanceTable[m_uiCW1];
  1306. ColorFloatRGBA frgbaDistance(fDistance, fDistance, fDistance, 0.0f);
  1307. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  1308. {
  1309. switch (m_auiSelectors[uiPixel])
  1310. {
  1311. case 0:
  1312. m_afrgbaDecodedColors[uiPixel] = m_frgbaColor1;
  1313. break;
  1314. case 1:
  1315. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor2 + frgbaDistance).ClampRGB();
  1316. break;
  1317. case 2:
  1318. m_afrgbaDecodedColors[uiPixel] = m_frgbaColor2;
  1319. break;
  1320. case 3:
  1321. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor2 - frgbaDistance).ClampRGB();
  1322. break;
  1323. }
  1324. }
  1325. }
  1326. // ----------------------------------------------------------------------------------------------------
  1327. // set the decoded colors and decoded alpha based on the encoding state for H mode
  1328. //
  1329. void Block4x4Encoding_RGB8::DecodePixels_H(void)
  1330. {
  1331. float fDistance = s_afTHDistanceTable[m_uiCW1];
  1332. ColorFloatRGBA frgbaDistance(fDistance, fDistance, fDistance, 0.0f);
  1333. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  1334. {
  1335. switch (m_auiSelectors[uiPixel])
  1336. {
  1337. case 0:
  1338. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor1 + frgbaDistance).ClampRGB();
  1339. break;
  1340. case 1:
  1341. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor1 - frgbaDistance).ClampRGB();
  1342. break;
  1343. case 2:
  1344. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor2 + frgbaDistance).ClampRGB();
  1345. break;
  1346. case 3:
  1347. m_afrgbaDecodedColors[uiPixel] = (m_frgbaColor2 - frgbaDistance).ClampRGB();
  1348. break;
  1349. }
  1350. }
  1351. }
  1352. // ----------------------------------------------------------------------------------------------------
  1353. // set the decoded colors and decoded alpha based on the encoding state for Planar mode
  1354. //
  1355. void Block4x4Encoding_RGB8::DecodePixels_Planar(void)
  1356. {
  1357. int iRO = (int)roundf(m_frgbaColor1.fR * 255.0f);
  1358. int iGO = (int)roundf(m_frgbaColor1.fG * 255.0f);
  1359. int iBO = (int)roundf(m_frgbaColor1.fB * 255.0f);
  1360. int iRH = (int)roundf(m_frgbaColor2.fR * 255.0f);
  1361. int iGH = (int)roundf(m_frgbaColor2.fG * 255.0f);
  1362. int iBH = (int)roundf(m_frgbaColor2.fB * 255.0f);
  1363. int iRV = (int)roundf(m_frgbaColor3.fR * 255.0f);
  1364. int iGV = (int)roundf(m_frgbaColor3.fG * 255.0f);
  1365. int iBV = (int)roundf(m_frgbaColor3.fB * 255.0f);
  1366. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  1367. {
  1368. int iX = (int)(uiPixel >> 2);
  1369. int iY = (int)(uiPixel & 3);
  1370. int iR = (iX*(iRH - iRO) + iY*(iRV - iRO) + 4*iRO + 2) >> 2;
  1371. int iG = (iX*(iGH - iGO) + iY*(iGV - iGO) + 4*iGO + 2) >> 2;
  1372. int iB = (iX*(iBH - iBO) + iY*(iBV - iBO) + 4*iBO + 2) >> 2;
  1373. ColorFloatRGBA frgba;
  1374. frgba.fR = (float)iR / 255.0f;
  1375. frgba.fG = (float)iG / 255.0f;
  1376. frgba.fB = (float)iB / 255.0f;
  1377. frgba.fA = 1.0f;
  1378. m_afrgbaDecodedColors[uiPixel] = frgba.ClampRGB();
  1379. }
  1380. }
  1381. // ----------------------------------------------------------------------------------------------------
  1382. // perform a linear regression for the a_uiPixels in a_pafrgbaPixels[]
  1383. //
  1384. // output the closest color line using a_pfrgbaSlope and a_pfrgbaOffset
  1385. //
  1386. void Block4x4Encoding_RGB8::ColorRegression(ColorFloatRGBA *a_pafrgbaPixels, unsigned int a_uiPixels,
  1387. ColorFloatRGBA *a_pfrgbaSlope, ColorFloatRGBA *a_pfrgbaOffset)
  1388. {
  1389. typedef struct
  1390. {
  1391. float f[4];
  1392. } Float4;
  1393. Float4 *paf4Pixels = (Float4 *)(a_pafrgbaPixels);
  1394. Float4 *pf4Slope = (Float4 *)(a_pfrgbaSlope);
  1395. Float4 *pf4Offset = (Float4 *)(a_pfrgbaOffset);
  1396. float afX[MAX_PLANAR_REGRESSION_SIZE];
  1397. float afY[MAX_PLANAR_REGRESSION_SIZE];
  1398. // handle r, g and b separately. don't bother with a
  1399. for (unsigned int uiComponent = 0; uiComponent < 3; uiComponent++)
  1400. {
  1401. for (unsigned int uiPixel = 0; uiPixel < a_uiPixels; uiPixel++)
  1402. {
  1403. afX[uiPixel] = (float)uiPixel;
  1404. afY[uiPixel] = paf4Pixels[uiPixel].f[uiComponent];
  1405. }
  1406. Etc::Regression(afX, afY, a_uiPixels,
  1407. &(pf4Slope->f[uiComponent]), &(pf4Offset->f[uiComponent]));
  1408. }
  1409. }
  1410. // ----------------------------------------------------------------------------------------------------
  1411. //
  1412. }