EtcBlock4x4Encoding_R11.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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_R11.cpp
  18. Block4x4Encoding_R11 is the encoder to use when targetting file format R11 and SR11 (signed R11).
  19. */
  20. #include "EtcConfig.h"
  21. #include "EtcBlock4x4Encoding_R11.h"
  22. #include "EtcBlock4x4EncodingBits.h"
  23. #include "EtcBlock4x4.h"
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <assert.h>
  27. #include <float.h>
  28. #include <limits>
  29. namespace Etc
  30. {
  31. // modifier values to use for R11, SR11, RG11 and SRG11
  32. float Block4x4Encoding_R11::s_aafModifierTable[MODIFIER_TABLE_ENTRYS][SELECTORS]
  33. {
  34. { -3.0f / 255.0f, -6.0f / 255.0f, -9.0f / 255.0f, -15.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 8.0f / 255.0f, 14.0f / 255.0f },
  35. { -3.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, -13.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f, 12.0f / 255.0f },
  36. { -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 12.0f / 255.0f },
  37. { -2.0f / 255.0f, -4.0f / 255.0f, -6.0f / 255.0f, -13.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 12.0f / 255.0f },
  38. { -3.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -12.0f / 255.0f, 2.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 11.0f / 255.0f },
  39. { -3.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f, 10.0f / 255.0f },
  40. { -4.0f / 255.0f, -7.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
  41. { -3.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -11.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 10.0f / 255.0f },
  42. { -2.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
  43. { -2.0f / 255.0f, -5.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
  44. { -2.0f / 255.0f, -4.0f / 255.0f, -8.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 3.0f / 255.0f, 7.0f / 255.0f, 9.0f / 255.0f },
  45. { -2.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 1.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
  46. { -3.0f / 255.0f, -4.0f / 255.0f, -7.0f / 255.0f, -10.0f / 255.0f, 2.0f / 255.0f, 3.0f / 255.0f, 6.0f / 255.0f, 9.0f / 255.0f },
  47. { -1.0f / 255.0f, -2.0f / 255.0f, -3.0f / 255.0f, -10.0f / 255.0f, 0.0f / 255.0f, 1.0f / 255.0f, 2.0f / 255.0f, 9.0f / 255.0f },
  48. { -4.0f / 255.0f, -6.0f / 255.0f, -8.0f / 255.0f, -9.0f / 255.0f, 3.0f / 255.0f, 5.0f / 255.0f, 7.0f / 255.0f, 8.0f / 255.0f },
  49. { -3.0f / 255.0f, -5.0f / 255.0f, -7.0f / 255.0f, -9.0f / 255.0f, 2.0f / 255.0f, 4.0f / 255.0f, 6.0f / 255.0f, 8.0f / 255.0f }
  50. };
  51. // ----------------------------------------------------------------------------------------------------
  52. //
  53. Block4x4Encoding_R11::Block4x4Encoding_R11(void)
  54. {
  55. m_pencodingbitsR11 = nullptr;
  56. }
  57. Block4x4Encoding_R11::~Block4x4Encoding_R11(void) {}
  58. // ----------------------------------------------------------------------------------------------------
  59. // initialization prior to encoding
  60. // a_pblockParent points to the block associated with this encoding
  61. // a_errormetric is used to choose the best encoding
  62. // a_pafrgbaSource points to a 4x4 block subset of the source image
  63. // a_paucEncodingBits points to the final encoding bits
  64. //
  65. void Block4x4Encoding_R11::InitFromSource(Block4x4 *a_pblockParent,
  66. ColorFloatRGBA *a_pafrgbaSource,
  67. unsigned char *a_paucEncodingBits, ErrorMetric a_errormetric)
  68. {
  69. Block4x4Encoding::Init(a_pblockParent, a_pafrgbaSource,a_errormetric);
  70. m_pencodingbitsR11 = (Block4x4EncodingBits_R11 *)a_paucEncodingBits;
  71. }
  72. // ----------------------------------------------------------------------------------------------------
  73. // initialization from the encoding bits of a previous encoding
  74. // a_pblockParent points to the block associated with this encoding
  75. // a_errormetric is used to choose the best encoding
  76. // a_pafrgbaSource points to a 4x4 block subset of the source image
  77. // a_paucEncodingBits points to the final encoding bits of a previous encoding
  78. //
  79. void Block4x4Encoding_R11::InitFromEncodingBits(Block4x4 *a_pblockParent,
  80. unsigned char *a_paucEncodingBits,
  81. ColorFloatRGBA *a_pafrgbaSource,
  82. ErrorMetric a_errormetric)
  83. {
  84. m_pencodingbitsR11 = (Block4x4EncodingBits_R11 *)a_paucEncodingBits;
  85. // init RGB portion
  86. Block4x4Encoding_RGB8::InitFromEncodingBits(a_pblockParent,
  87. (unsigned char *)m_pencodingbitsR11,
  88. a_pafrgbaSource,
  89. a_errormetric);
  90. // init R11 portion
  91. {
  92. m_mode = MODE_R11;
  93. if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
  94. {
  95. m_fRedBase = (float)(signed char)m_pencodingbitsR11->data.base;
  96. }
  97. else
  98. {
  99. m_fRedBase = (float)(unsigned char)m_pencodingbitsR11->data.base;
  100. }
  101. m_fRedMultiplier = (float)m_pencodingbitsR11->data.multiplier;
  102. m_uiRedModifierTableIndex = m_pencodingbitsR11->data.table;
  103. unsigned long long int ulliSelectorBits = 0;
  104. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors0 << 40;
  105. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors1 << 32;
  106. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors2 << 24;
  107. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors3 << 16;
  108. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors4 << 8;
  109. ulliSelectorBits |= (unsigned long long int)m_pencodingbitsR11->data.selectors5;
  110. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  111. {
  112. unsigned int uiShift = 45 - (3 * uiPixel);
  113. m_auiRedSelectors[uiPixel] = (ulliSelectorBits >> uiShift) & (SELECTORS - 1);
  114. }
  115. // decode the red channel
  116. // calc red error
  117. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  118. {
  119. float fDecodedPixelData = 0.0f;
  120. if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
  121. {
  122. fDecodedPixelData = DecodePixelRed(m_fRedBase, m_fRedMultiplier,
  123. m_uiRedModifierTableIndex,
  124. m_auiRedSelectors[uiPixel]);
  125. }
  126. else if (a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || a_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
  127. {
  128. fDecodedPixelData = DecodePixelRed(m_fRedBase + 128, m_fRedMultiplier,
  129. m_uiRedModifierTableIndex,
  130. m_auiRedSelectors[uiPixel]);
  131. }
  132. else
  133. {
  134. assert(0);
  135. }
  136. m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(fDecodedPixelData, 0.0f, 0.0f, 1.0f);
  137. }
  138. CalcBlockError();
  139. }
  140. }
  141. // ----------------------------------------------------------------------------------------------------
  142. // perform a single encoding iteration
  143. // replace the encoding if a better encoding was found
  144. // subsequent iterations generally take longer for each iteration
  145. // set m_boolDone if encoding is perfect or encoding is finished based on a_fEffort
  146. //
  147. void Block4x4Encoding_R11::PerformIteration(float a_fEffort)
  148. {
  149. assert(!m_boolDone);
  150. m_mode = MODE_R11;
  151. switch (m_uiEncodingIterations)
  152. {
  153. case 0:
  154. m_fError = FLT_MAX;
  155. m_fRedBlockError = FLT_MAX; // artificially high value
  156. CalculateR11(8, 0.0f, 0.0f);
  157. m_fError = m_fRedBlockError;
  158. break;
  159. case 1:
  160. CalculateR11(8, 2.0f, 1.0f);
  161. m_fError = m_fRedBlockError;
  162. if (a_fEffort <= 24.5f)
  163. {
  164. m_boolDone = true;
  165. }
  166. break;
  167. case 2:
  168. CalculateR11(8, 12.0f, 1.0f);
  169. m_fError = m_fRedBlockError;
  170. if (a_fEffort <= 49.5f)
  171. {
  172. m_boolDone = true;
  173. }
  174. break;
  175. case 3:
  176. CalculateR11(7, 6.0f, 1.0f);
  177. m_fError = m_fRedBlockError;
  178. break;
  179. case 4:
  180. CalculateR11(6, 3.0f, 1.0f);
  181. m_fError = m_fRedBlockError;
  182. break;
  183. case 5:
  184. CalculateR11(5, 1.0f, 0.0f);
  185. m_fError = m_fRedBlockError;
  186. m_boolDone = true;
  187. break;
  188. default:
  189. assert(0);
  190. break;
  191. }
  192. m_uiEncodingIterations++;
  193. SetDoneIfPerfect();
  194. }
  195. // ----------------------------------------------------------------------------------------------------
  196. // find the best combination of base color, multiplier and selectors
  197. //
  198. // a_uiSelectorsUsed limits the number of selector combinations to try
  199. // a_fBaseRadius limits the range of base colors to try
  200. // a_fMultiplierRadius limits the range of multipliers to try
  201. //
  202. void Block4x4Encoding_R11::CalculateR11(unsigned int a_uiSelectorsUsed,
  203. float a_fBaseRadius, float a_fMultiplierRadius)
  204. {
  205. // maps from virtual (monotonic) selector to ETC selector
  206. static const unsigned int auiVirtualSelectorMap[8] = {3, 2, 1, 0, 4, 5, 6, 7};
  207. // find min/max red
  208. float fMinRed = 1.0f;
  209. float fMaxRed = 0.0f;
  210. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  211. {
  212. // ignore border pixels
  213. float fAlpha = m_pafrgbaSource[uiPixel].fA;
  214. if (isnan(fAlpha))
  215. {
  216. continue;
  217. }
  218. float fRed = m_pafrgbaSource[uiPixel].fR;
  219. if (fRed < fMinRed)
  220. {
  221. fMinRed = fRed;
  222. }
  223. if (fRed > fMaxRed)
  224. {
  225. fMaxRed = fRed;
  226. }
  227. }
  228. assert(fMinRed <= fMaxRed);
  229. float fRedRange = (fMaxRed - fMinRed);
  230. // try each modifier table entry
  231. for (unsigned int uiTableEntry = 0; uiTableEntry < MODIFIER_TABLE_ENTRYS; uiTableEntry++)
  232. {
  233. for (unsigned int uiMinVirtualSelector = 0;
  234. uiMinVirtualSelector <= (8- a_uiSelectorsUsed);
  235. uiMinVirtualSelector++)
  236. {
  237. unsigned int uiMaxVirtualSelector = uiMinVirtualSelector + a_uiSelectorsUsed - 1;
  238. unsigned int uiMinSelector = auiVirtualSelectorMap[uiMinVirtualSelector];
  239. unsigned int uiMaxSelector = auiVirtualSelectorMap[uiMaxVirtualSelector];
  240. float fTableEntryCenter = -s_aafModifierTable[uiTableEntry][uiMinSelector];
  241. float fTableEntryRange = s_aafModifierTable[uiTableEntry][uiMaxSelector] -
  242. s_aafModifierTable[uiTableEntry][uiMinSelector];
  243. float fCenterRatio = fTableEntryCenter / fTableEntryRange;
  244. float fCenter = fMinRed + fCenterRatio*fRedRange;
  245. fCenter = roundf(255.0f * fCenter) / 255.0f;
  246. float fMinBase = fCenter - (a_fBaseRadius / 255.0f);
  247. if (fMinBase < 0.0f)
  248. {
  249. fMinBase = 0.0f;
  250. }
  251. float fMaxBase = fCenter + (a_fBaseRadius / 255.0f);
  252. if (fMaxBase > 1.0f)
  253. {
  254. fMaxBase = 1.0f;
  255. }
  256. for (float fBase = fMinBase; fBase <= fMaxBase; fBase += (0.999999f / 255.0f))
  257. {
  258. float fRangeMultiplier = roundf(fRedRange / fTableEntryRange);
  259. float fMinMultiplier = fRangeMultiplier - a_fMultiplierRadius;
  260. if (fMinMultiplier < 1.0f)
  261. {
  262. fMinMultiplier = 0.0f;
  263. }
  264. else if (fMinMultiplier > 15.0f)
  265. {
  266. fMinMultiplier = 15.0f;
  267. }
  268. float fMaxMultiplier = fRangeMultiplier + a_fMultiplierRadius;
  269. if (fMaxMultiplier < 1.0f)
  270. {
  271. fMaxMultiplier = 1.0f;
  272. }
  273. else if (fMaxMultiplier > 15.0f)
  274. {
  275. fMaxMultiplier = 15.0f;
  276. }
  277. for (float fMultiplier = fMinMultiplier; fMultiplier <= fMaxMultiplier; fMultiplier += 1.0f)
  278. {
  279. // find best selector for each pixel
  280. unsigned int auiBestSelectors[PIXELS];
  281. float afBestRedError[PIXELS];
  282. float afBestPixelRed[PIXELS];
  283. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  284. {
  285. float fBestPixelRedError = FLT_MAX;
  286. for (unsigned int uiSelector = 0; uiSelector < SELECTORS; uiSelector++)
  287. {
  288. float fPixelRed = DecodePixelRed(fBase * 255.0f, fMultiplier, uiTableEntry, uiSelector);
  289. ColorFloatRGBA frgba(fPixelRed, m_pafrgbaSource[uiPixel].fG,0.0f,1.0f);
  290. float fPixelRedError = CalcPixelError(frgba, 1.0f, m_pafrgbaSource[uiPixel]);
  291. if (fPixelRedError < fBestPixelRedError)
  292. {
  293. fBestPixelRedError = fPixelRedError;
  294. auiBestSelectors[uiPixel] = uiSelector;
  295. afBestRedError[uiPixel] = fBestPixelRedError;
  296. afBestPixelRed[uiPixel] = fPixelRed;
  297. }
  298. }
  299. }
  300. float fBlockError = 0.0f;
  301. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  302. {
  303. fBlockError += afBestRedError[uiPixel];
  304. }
  305. if (fBlockError < m_fRedBlockError)
  306. {
  307. m_fRedBlockError = fBlockError;
  308. if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
  309. {
  310. m_fRedBase = 255.0f * fBase;
  311. }
  312. else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
  313. {
  314. m_fRedBase = (fBase * 255) - 128;
  315. }
  316. else
  317. {
  318. assert(0);
  319. }
  320. m_fRedMultiplier = fMultiplier;
  321. m_uiRedModifierTableIndex = uiTableEntry;
  322. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  323. {
  324. m_auiRedSelectors[uiPixel] = auiBestSelectors[uiPixel];
  325. float fBestPixelRed = afBestPixelRed[uiPixel];
  326. m_afrgbaDecodedColors[uiPixel] = ColorFloatRGBA(fBestPixelRed, 0.0f, 0.0f, 1.0f);
  327. m_afDecodedAlphas[uiPixel] = 1.0f;
  328. }
  329. }
  330. }
  331. }
  332. }
  333. }
  334. }
  335. // ----------------------------------------------------------------------------------------------------
  336. // set the encoding bits based on encoding state
  337. //
  338. void Block4x4Encoding_R11::SetEncodingBits(void)
  339. {
  340. if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::RG11)
  341. {
  342. m_pencodingbitsR11->data.base = (unsigned char)roundf(m_fRedBase);
  343. }
  344. else if (m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_R11 || m_pblockParent->GetImageSource()->GetFormat() == Image::Format::SIGNED_RG11)
  345. {
  346. m_pencodingbitsR11->data.base = (signed char)roundf(m_fRedBase);
  347. }
  348. else
  349. {
  350. assert(0);
  351. }
  352. m_pencodingbitsR11->data.table = m_uiRedModifierTableIndex;
  353. m_pencodingbitsR11->data.multiplier = (unsigned char)roundf(m_fRedMultiplier);
  354. unsigned long long int ulliSelectorBits = 0;
  355. for (unsigned int uiPixel = 0; uiPixel < PIXELS; uiPixel++)
  356. {
  357. unsigned int uiShift = 45 - (3 * uiPixel);
  358. ulliSelectorBits |= ((unsigned long long int)m_auiRedSelectors[uiPixel]) << uiShift;
  359. }
  360. m_pencodingbitsR11->data.selectors0 = ulliSelectorBits >> 40;
  361. m_pencodingbitsR11->data.selectors1 = ulliSelectorBits >> 32;
  362. m_pencodingbitsR11->data.selectors2 = ulliSelectorBits >> 24;
  363. m_pencodingbitsR11->data.selectors3 = ulliSelectorBits >> 16;
  364. m_pencodingbitsR11->data.selectors4 = ulliSelectorBits >> 8;
  365. m_pencodingbitsR11->data.selectors5 = ulliSelectorBits;
  366. }
  367. // ----------------------------------------------------------------------------------------------------
  368. //
  369. }