ImfB44Compressor.cpp 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
  4. // Digital Ltd. LLC
  5. //
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Industrial Light & Magic nor the names of
  18. // its contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. //-----------------------------------------------------------------------------
  35. //
  36. // class B44Compressor
  37. //
  38. // This compressor is lossy for HALF channels; the compression rate
  39. // is fixed at 32/14 (approximately 2.28). FLOAT and UINT channels
  40. // are not compressed; their data are preserved exactly.
  41. //
  42. // Each HALF channel is split into blocks of 4 by 4 pixels. An
  43. // uncompressed block occupies 32 bytes, which are re-interpreted
  44. // as sixteen 16-bit unsigned integers, t[0] ... t[15]. Compression
  45. // shrinks the block to 14 bytes. The compressed 14-byte block
  46. // contains
  47. //
  48. // - t[0]
  49. //
  50. // - a 6-bit shift value
  51. //
  52. // - 15 densely packed 6-bit values, r[0] ... r[14], which are
  53. // computed by subtracting adjacent pixel values and right-
  54. // shifting the differences according to the stored shift value.
  55. //
  56. // Differences between adjacent pixels are computed according
  57. // to the following diagram:
  58. //
  59. // 0 --------> 1 --------> 2 --------> 3
  60. // | 3 7 11
  61. // |
  62. // | 0
  63. // |
  64. // v
  65. // 4 --------> 5 --------> 6 --------> 7
  66. // | 4 8 12
  67. // |
  68. // | 1
  69. // |
  70. // v
  71. // 8 --------> 9 --------> 10 --------> 11
  72. // | 5 9 13
  73. // |
  74. // | 2
  75. // |
  76. // v
  77. // 12 --------> 13 --------> 14 --------> 15
  78. // 6 10 14
  79. //
  80. // Here
  81. //
  82. // 5 ---------> 6
  83. // 8
  84. //
  85. // means that r[8] is the difference between t[5] and t[6].
  86. //
  87. // - optionally, a 4-by-4 pixel block where all pixels have the
  88. // same value can be treated as a special case, where the
  89. // compressed block contains only 3 instead of 14 bytes:
  90. // t[0], followed by an "impossible" 6-bit shift value and
  91. // two padding bits.
  92. //
  93. // This compressor can handle positive and negative pixel values.
  94. // NaNs and infinities are replaced with zeroes before compression.
  95. //
  96. //-----------------------------------------------------------------------------
  97. #include "ImfB44Compressor.h"
  98. #include "ImfHeader.h"
  99. #include "ImfChannelList.h"
  100. #include "ImfMisc.h"
  101. #include "ImfCheckedArithmetic.h"
  102. #include <ImathFun.h>
  103. #include <ImathBox.h>
  104. #include <Iex.h>
  105. #include <ImfIO.h>
  106. #include <ImfXdr.h>
  107. #include <string.h>
  108. #include <assert.h>
  109. #include <algorithm>
  110. #include "ImfNamespace.h"
  111. OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
  112. using IMATH_NAMESPACE::divp;
  113. using IMATH_NAMESPACE::modp;
  114. using IMATH_NAMESPACE::Box2i;
  115. using IMATH_NAMESPACE::V2i;
  116. using std::min;
  117. namespace {
  118. //
  119. // Lookup tables for
  120. // y = exp (x / 8)
  121. // and
  122. // x = 8 * log (y)
  123. //
  124. #include "b44ExpLogTable.h"
  125. inline void
  126. convertFromLinear (unsigned short s[16])
  127. {
  128. for (int i = 0; i < 16; ++i)
  129. s[i] = expTable[s[i]];
  130. }
  131. inline void
  132. convertToLinear (unsigned short s[16])
  133. {
  134. for (int i = 0; i < 16; ++i)
  135. s[i] = logTable[s[i]];
  136. }
  137. inline int
  138. shiftAndRound (int x, int shift)
  139. {
  140. //
  141. // Compute
  142. //
  143. // y = x * pow (2, -shift),
  144. //
  145. // then round y to the nearest integer.
  146. // In case of a tie, where y is exactly
  147. // halfway between two integers, round
  148. // to the even one.
  149. //
  150. x <<= 1;
  151. int a = (1 << shift) - 1;
  152. shift += 1;
  153. int b = (x >> shift) & 1;
  154. return (x + a + b) >> shift;
  155. }
  156. int
  157. pack (const unsigned short s[16],
  158. unsigned char b[14],
  159. bool optFlatFields,
  160. bool exactMax)
  161. {
  162. //
  163. // Pack a block of 4 by 4 16-bit pixels (32 bytes) into
  164. // either 14 or 3 bytes.
  165. //
  166. //
  167. // Integers s[0] ... s[15] represent floating-point numbers
  168. // in what is essentially a sign-magnitude format. Convert
  169. // s[0] .. s[15] into a new set of integers, t[0] ... t[15],
  170. // such that if t[i] is greater than t[j], the floating-point
  171. // number that corresponds to s[i] is always greater than
  172. // the floating-point number that corresponds to s[j].
  173. //
  174. // Also, replace any bit patterns that represent NaNs or
  175. // infinities with bit patterns that represent floating-point
  176. // zeroes.
  177. //
  178. // bit pattern floating-point bit pattern
  179. // in s[i] value in t[i]
  180. //
  181. // 0x7fff NAN 0x8000
  182. // 0x7ffe NAN 0x8000
  183. // ... ...
  184. // 0x7c01 NAN 0x8000
  185. // 0x7c00 +infinity 0x8000
  186. // 0x7bff +HALF_MAX 0xfbff
  187. // 0x7bfe 0xfbfe
  188. // 0x7bfd 0xfbfd
  189. // ... ...
  190. // 0x0002 +2 * HALF_MIN 0x8002
  191. // 0x0001 +HALF_MIN 0x8001
  192. // 0x0000 +0.0 0x8000
  193. // 0x8000 -0.0 0x7fff
  194. // 0x8001 -HALF_MIN 0x7ffe
  195. // 0x8002 -2 * HALF_MIN 0x7ffd
  196. // ... ...
  197. // 0xfbfd 0x0f02
  198. // 0xfbfe 0x0401
  199. // 0xfbff -HALF_MAX 0x0400
  200. // 0xfc00 -infinity 0x8000
  201. // 0xfc01 NAN 0x8000
  202. // ... ...
  203. // 0xfffe NAN 0x8000
  204. // 0xffff NAN 0x8000
  205. //
  206. unsigned short t[16];
  207. for (int i = 0; i < 16; ++i)
  208. {
  209. if ((s[i] & 0x7c00) == 0x7c00)
  210. t[i] = 0x8000;
  211. else if (s[i] & 0x8000)
  212. t[i] = ~s[i];
  213. else
  214. t[i] = s[i] | 0x8000;
  215. }
  216. //
  217. // Find the maximum, tMax, of t[0] ... t[15].
  218. //
  219. unsigned short tMax = 0;
  220. for (int i = 0; i < 16; ++i)
  221. if (tMax < t[i])
  222. tMax = t[i];
  223. //
  224. // Compute a set of running differences, r[0] ... r[14]:
  225. // Find a shift value such that after rounding off the
  226. // rightmost bits and shifting all differenes are between
  227. // -32 and +31. Then bias the differences so that they
  228. // end up between 0 and 63.
  229. //
  230. int shift = -1;
  231. int d[16];
  232. int r[15];
  233. int rMin;
  234. int rMax;
  235. const int bias = 0x20;
  236. do
  237. {
  238. shift += 1;
  239. //
  240. // Compute absolute differences, d[0] ... d[15],
  241. // between tMax and t[0] ... t[15].
  242. //
  243. // Shift and round the absolute differences.
  244. //
  245. for (int i = 0; i < 16; ++i)
  246. d[i] = shiftAndRound (tMax - t[i], shift);
  247. //
  248. // Convert d[0] .. d[15] into running differences
  249. //
  250. r[ 0] = d[ 0] - d[ 4] + bias;
  251. r[ 1] = d[ 4] - d[ 8] + bias;
  252. r[ 2] = d[ 8] - d[12] + bias;
  253. r[ 3] = d[ 0] - d[ 1] + bias;
  254. r[ 4] = d[ 4] - d[ 5] + bias;
  255. r[ 5] = d[ 8] - d[ 9] + bias;
  256. r[ 6] = d[12] - d[13] + bias;
  257. r[ 7] = d[ 1] - d[ 2] + bias;
  258. r[ 8] = d[ 5] - d[ 6] + bias;
  259. r[ 9] = d[ 9] - d[10] + bias;
  260. r[10] = d[13] - d[14] + bias;
  261. r[11] = d[ 2] - d[ 3] + bias;
  262. r[12] = d[ 6] - d[ 7] + bias;
  263. r[13] = d[10] - d[11] + bias;
  264. r[14] = d[14] - d[15] + bias;
  265. rMin = r[0];
  266. rMax = r[0];
  267. for (int i = 1; i < 15; ++i)
  268. {
  269. if (rMin > r[i])
  270. rMin = r[i];
  271. if (rMax < r[i])
  272. rMax = r[i];
  273. }
  274. }
  275. while (rMin < 0 || rMax > 0x3f);
  276. if (rMin == bias && rMax == bias && optFlatFields)
  277. {
  278. //
  279. // Special case - all pixels have the same value.
  280. // We encode this in 3 instead of 14 bytes by
  281. // storing the value 0xfc in the third output byte,
  282. // which cannot occur in the 14-byte encoding.
  283. //
  284. b[0] = (t[0] >> 8);
  285. b[1] = (unsigned char) t[0];
  286. b[2] = 0xfc;
  287. return 3;
  288. }
  289. if (exactMax)
  290. {
  291. //
  292. // Adjust t[0] so that the pixel whose value is equal
  293. // to tMax gets represented as accurately as possible.
  294. //
  295. t[0] = tMax - (d[0] << shift);
  296. }
  297. //
  298. // Pack t[0], shift and r[0] ... r[14] into 14 bytes:
  299. //
  300. b[ 0] = (t[0] >> 8);
  301. b[ 1] = (unsigned char) t[0];
  302. b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4));
  303. b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2));
  304. b[ 4] = (unsigned char) ((r[ 1] << 6) | r[ 2] );
  305. b[ 5] = (unsigned char) ((r[ 3] << 2) | (r[ 4] >> 4));
  306. b[ 6] = (unsigned char) ((r[ 4] << 4) | (r[ 5] >> 2));
  307. b[ 7] = (unsigned char) ((r[ 5] << 6) | r[ 6] );
  308. b[ 8] = (unsigned char) ((r[ 7] << 2) | (r[ 8] >> 4));
  309. b[ 9] = (unsigned char) ((r[ 8] << 4) | (r[ 9] >> 2));
  310. b[10] = (unsigned char) ((r[ 9] << 6) | r[10] );
  311. b[11] = (unsigned char) ((r[11] << 2) | (r[12] >> 4));
  312. b[12] = (unsigned char) ((r[12] << 4) | (r[13] >> 2));
  313. b[13] = (unsigned char) ((r[13] << 6) | r[14] );
  314. return 14;
  315. }
  316. inline
  317. void
  318. unpack14 (const unsigned char b[14], unsigned short s[16])
  319. {
  320. //
  321. // Unpack a 14-byte block into 4 by 4 16-bit pixels.
  322. //
  323. #if defined (DEBUG)
  324. assert (b[2] != 0xfc);
  325. #endif
  326. s[ 0] = (b[0] << 8) | b[1];
  327. unsigned short shift = (b[ 2] >> 2);
  328. unsigned short bias = (0x20 << shift);
  329. s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
  330. s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
  331. s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) - bias;
  332. s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) - bias;
  333. s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
  334. s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
  335. s[13] = s[12] + ((b[ 7] & 0x3f) << shift) - bias;
  336. s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) - bias;
  337. s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
  338. s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
  339. s[14] = s[13] + ((b[10] & 0x3f) << shift) - bias;
  340. s[ 3] = s[ 2] + ((b[11] >> 2) << shift) - bias;
  341. s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
  342. s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
  343. s[15] = s[14] + ((b[13] & 0x3f) << shift) - bias;
  344. for (int i = 0; i < 16; ++i)
  345. {
  346. if (s[i] & 0x8000)
  347. s[i] &= 0x7fff;
  348. else
  349. s[i] = ~s[i];
  350. }
  351. }
  352. inline
  353. void
  354. unpack3 (const unsigned char b[3], unsigned short s[16])
  355. {
  356. //
  357. // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
  358. //
  359. #if defined (DEBUG)
  360. assert (b[2] == 0xfc);
  361. #endif
  362. s[0] = (b[0] << 8) | b[1];
  363. if (s[0] & 0x8000)
  364. s[0] &= 0x7fff;
  365. else
  366. s[0] = ~s[0];
  367. for (int i = 1; i < 16; ++i)
  368. s[i] = s[0];
  369. }
  370. void
  371. notEnoughData ()
  372. {
  373. throw IEX_NAMESPACE::InputExc ("Error decompressing data "
  374. "(input data are shorter than expected).");
  375. }
  376. void
  377. tooMuchData ()
  378. {
  379. throw IEX_NAMESPACE::InputExc ("Error decompressing data "
  380. "(input data are longer than expected).");
  381. }
  382. } // namespace
  383. struct B44Compressor::ChannelData
  384. {
  385. unsigned short * start;
  386. unsigned short * end;
  387. int nx;
  388. int ny;
  389. int ys;
  390. PixelType type;
  391. bool pLinear;
  392. int size;
  393. };
  394. B44Compressor::B44Compressor
  395. (const Header &hdr,
  396. size_t maxScanLineSize,
  397. size_t numScanLines,
  398. bool optFlatFields)
  399. :
  400. Compressor (hdr),
  401. _maxScanLineSize (maxScanLineSize),
  402. _optFlatFields (optFlatFields),
  403. _format (XDR),
  404. _numScanLines (numScanLines),
  405. _tmpBuffer (0),
  406. _outBuffer (0),
  407. _numChans (0),
  408. _channels (hdr.channels()),
  409. _channelData (0)
  410. {
  411. //
  412. // Allocate buffers for compressed an uncompressed pixel data,
  413. // allocate a set of ChannelData structs to help speed up the
  414. // compress() and uncompress() functions, below, and determine
  415. // if uncompressed pixel data should be in native or Xdr format.
  416. //
  417. _tmpBuffer = new unsigned short
  418. [checkArraySize (uiMult (maxScanLineSize, numScanLines),
  419. sizeof (unsigned short))];
  420. const ChannelList &channels = header().channels();
  421. int numHalfChans = 0;
  422. for (ChannelList::ConstIterator c = channels.begin();
  423. c != channels.end();
  424. ++c)
  425. {
  426. assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);
  427. ++_numChans;
  428. if (c.channel().type == HALF)
  429. ++numHalfChans;
  430. }
  431. //
  432. // Compressed data may be larger than the input data
  433. //
  434. size_t padding = 12 * numHalfChans * (numScanLines + 3) / 4;
  435. _outBuffer = new char
  436. [uiAdd (uiMult (maxScanLineSize, numScanLines), padding)];
  437. _channelData = new ChannelData[_numChans];
  438. int i = 0;
  439. for (ChannelList::ConstIterator c = channels.begin();
  440. c != channels.end();
  441. ++c, ++i)
  442. {
  443. _channelData[i].ys = c.channel().ySampling;
  444. _channelData[i].type = c.channel().type;
  445. _channelData[i].pLinear = c.channel().pLinear;
  446. _channelData[i].size =
  447. pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
  448. }
  449. const Box2i &dataWindow = hdr.dataWindow();
  450. _minX = dataWindow.min.x;
  451. _maxX = dataWindow.max.x;
  452. _maxY = dataWindow.max.y;
  453. //
  454. // We can support uncompressed data in the machine's native
  455. // format only if all image channels are of type HALF.
  456. //
  457. assert (sizeof (unsigned short) == pixelTypeSize (HALF));
  458. if (_numChans == numHalfChans)
  459. _format = NATIVE;
  460. }
  461. B44Compressor::~B44Compressor ()
  462. {
  463. delete [] _tmpBuffer;
  464. delete [] _outBuffer;
  465. delete [] _channelData;
  466. }
  467. int
  468. B44Compressor::numScanLines () const
  469. {
  470. return _numScanLines;
  471. }
  472. Compressor::Format
  473. B44Compressor::format () const
  474. {
  475. return _format;
  476. }
  477. int
  478. B44Compressor::compress (const char *inPtr,
  479. int inSize,
  480. int minY,
  481. const char *&outPtr)
  482. {
  483. return compress (inPtr,
  484. inSize,
  485. Box2i (V2i (_minX, minY),
  486. V2i (_maxX, minY + numScanLines() - 1)),
  487. outPtr);
  488. }
  489. int
  490. B44Compressor::compressTile (const char *inPtr,
  491. int inSize,
  492. IMATH_NAMESPACE::Box2i range,
  493. const char *&outPtr)
  494. {
  495. return compress (inPtr, inSize, range, outPtr);
  496. }
  497. int
  498. B44Compressor::uncompress (const char *inPtr,
  499. int inSize,
  500. int minY,
  501. const char *&outPtr)
  502. {
  503. return uncompress (inPtr,
  504. inSize,
  505. Box2i (V2i (_minX, minY),
  506. V2i (_maxX, minY + numScanLines() - 1)),
  507. outPtr);
  508. }
  509. int
  510. B44Compressor::uncompressTile (const char *inPtr,
  511. int inSize,
  512. IMATH_NAMESPACE::Box2i range,
  513. const char *&outPtr)
  514. {
  515. return uncompress (inPtr, inSize, range, outPtr);
  516. }
  517. int
  518. B44Compressor::compress (const char *inPtr,
  519. int inSize,
  520. IMATH_NAMESPACE::Box2i range,
  521. const char *&outPtr)
  522. {
  523. //
  524. // Compress a block of pixel data: First copy the input pixels
  525. // from the input buffer into _tmpBuffer, rearranging them such
  526. // that blocks of 4x4 pixels of a single channel can be accessed
  527. // conveniently. Then compress each 4x4 block of HALF pixel data
  528. // and append the result to the output buffer. Copy UINT and
  529. // FLOAT data to the output buffer without compressing them.
  530. //
  531. outPtr = _outBuffer;
  532. if (inSize == 0)
  533. {
  534. //
  535. // Special case - empty input buffer.
  536. //
  537. return 0;
  538. }
  539. //
  540. // For each channel, detemine how many pixels are stored
  541. // in the input buffer, and where those pixels will be
  542. // placed in _tmpBuffer.
  543. //
  544. int minX = range.min.x;
  545. int maxX = min (range.max.x, _maxX);
  546. int minY = range.min.y;
  547. int maxY = min (range.max.y, _maxY);
  548. unsigned short *tmpBufferEnd = _tmpBuffer;
  549. int i = 0;
  550. for (ChannelList::ConstIterator c = _channels.begin();
  551. c != _channels.end();
  552. ++c, ++i)
  553. {
  554. ChannelData &cd = _channelData[i];
  555. cd.start = tmpBufferEnd;
  556. cd.end = cd.start;
  557. cd.nx = numSamples (c.channel().xSampling, minX, maxX);
  558. cd.ny = numSamples (c.channel().ySampling, minY, maxY);
  559. tmpBufferEnd += cd.nx * cd.ny * cd.size;
  560. }
  561. if (_format == XDR)
  562. {
  563. //
  564. // The data in the input buffer are in the machine-independent
  565. // Xdr format. Copy the HALF channels into _tmpBuffer and
  566. // convert them back into native format for compression.
  567. // Copy UINT and FLOAT channels verbatim into _tmpBuffer.
  568. //
  569. for (int y = minY; y <= maxY; ++y)
  570. {
  571. for (int i = 0; i < _numChans; ++i)
  572. {
  573. ChannelData &cd = _channelData[i];
  574. if (modp (y, cd.ys) != 0)
  575. continue;
  576. if (cd.type == HALF)
  577. {
  578. for (int x = cd.nx; x > 0; --x)
  579. {
  580. Xdr::read <CharPtrIO> (inPtr, *cd.end);
  581. ++cd.end;
  582. }
  583. }
  584. else
  585. {
  586. int n = cd.nx * cd.size;
  587. memcpy (cd.end, inPtr, n * sizeof (unsigned short));
  588. inPtr += n * sizeof (unsigned short);
  589. cd.end += n;
  590. }
  591. }
  592. }
  593. }
  594. else
  595. {
  596. //
  597. // The input buffer contains only HALF channels, and they
  598. // are in native, machine-dependent format. Copy the pixels
  599. // into _tmpBuffer.
  600. //
  601. for (int y = minY; y <= maxY; ++y)
  602. {
  603. for (int i = 0; i < _numChans; ++i)
  604. {
  605. ChannelData &cd = _channelData[i];
  606. #if defined (DEBUG)
  607. assert (cd.type == HALF);
  608. #endif
  609. if (modp (y, cd.ys) != 0)
  610. continue;
  611. int n = cd.nx * cd.size;
  612. memcpy (cd.end, inPtr, n * sizeof (unsigned short));
  613. inPtr += n * sizeof (unsigned short);
  614. cd.end += n;
  615. }
  616. }
  617. }
  618. //
  619. // The pixels for each channel have been packed into a contiguous
  620. // block in _tmpBuffer. HALF channels are in native format; UINT
  621. // and FLOAT channels are in Xdr format.
  622. //
  623. #if defined (DEBUG)
  624. for (int i = 1; i < _numChans; ++i)
  625. assert (_channelData[i-1].end == _channelData[i].start);
  626. assert (_channelData[_numChans-1].end == tmpBufferEnd);
  627. #endif
  628. //
  629. // For each HALF channel, split the data in _tmpBuffer into 4x4
  630. // pixel blocks. Compress each block and append the compressed
  631. // data to the output buffer.
  632. //
  633. // UINT and FLOAT channels are copied from _tmpBuffer into the
  634. // output buffer without further processing.
  635. //
  636. char *outEnd = _outBuffer;
  637. for (int i = 0; i < _numChans; ++i)
  638. {
  639. ChannelData &cd = _channelData[i];
  640. if (cd.type != HALF)
  641. {
  642. //
  643. // UINT or FLOAT channel.
  644. //
  645. int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
  646. memcpy (outEnd, cd.start, n);
  647. outEnd += n;
  648. continue;
  649. }
  650. //
  651. // HALF channel
  652. //
  653. for (int y = 0; y < cd.ny; y += 4)
  654. {
  655. //
  656. // Copy the next 4x4 pixel block into array s.
  657. // If the width, cd.nx, or the height, cd.ny, of
  658. // the pixel data in _tmpBuffer is not divisible
  659. // by 4, then pad the data by repeating the
  660. // rightmost column and the bottom row.
  661. //
  662. unsigned short *row0 = cd.start + y * cd.nx;
  663. unsigned short *row1 = row0 + cd.nx;
  664. unsigned short *row2 = row1 + cd.nx;
  665. unsigned short *row3 = row2 + cd.nx;
  666. if (y + 3 >= cd.ny)
  667. {
  668. if (y + 1 >= cd.ny)
  669. row1 = row0;
  670. if (y + 2 >= cd.ny)
  671. row2 = row1;
  672. row3 = row2;
  673. }
  674. for (int x = 0; x < cd.nx; x += 4)
  675. {
  676. unsigned short s[16];
  677. if (x + 3 >= cd.nx)
  678. {
  679. int n = cd.nx - x;
  680. for (int i = 0; i < 4; ++i)
  681. {
  682. int j = min (i, n - 1);
  683. s[i + 0] = row0[j];
  684. s[i + 4] = row1[j];
  685. s[i + 8] = row2[j];
  686. s[i + 12] = row3[j];
  687. }
  688. }
  689. else
  690. {
  691. memcpy (&s[ 0], row0, 4 * sizeof (unsigned short));
  692. memcpy (&s[ 4], row1, 4 * sizeof (unsigned short));
  693. memcpy (&s[ 8], row2, 4 * sizeof (unsigned short));
  694. memcpy (&s[12], row3, 4 * sizeof (unsigned short));
  695. }
  696. row0 += 4;
  697. row1 += 4;
  698. row2 += 4;
  699. row3 += 4;
  700. //
  701. // Compress the contents of array s and append the
  702. // results to the output buffer.
  703. //
  704. if (cd.pLinear)
  705. convertFromLinear (s);
  706. outEnd += pack (s, (unsigned char *) outEnd,
  707. _optFlatFields, !cd.pLinear);
  708. }
  709. }
  710. }
  711. return outEnd - _outBuffer;
  712. }
  713. int
  714. B44Compressor::uncompress (const char *inPtr,
  715. int inSize,
  716. IMATH_NAMESPACE::Box2i range,
  717. const char *&outPtr)
  718. {
  719. //
  720. // This function is the reverse of the compress() function,
  721. // above. First all pixels are moved from the input buffer
  722. // into _tmpBuffer. UINT and FLOAT channels are copied
  723. // verbatim; HALF channels are uncompressed in blocks of
  724. // 4x4 pixels. Then the pixels in _tmpBuffer are copied
  725. // into the output buffer and rearranged such that the data
  726. // for for each scan line form a contiguous block.
  727. //
  728. outPtr = _outBuffer;
  729. if (inSize == 0)
  730. {
  731. return 0;
  732. }
  733. int minX = range.min.x;
  734. int maxX = min (range.max.x, _maxX);
  735. int minY = range.min.y;
  736. int maxY = min (range.max.y, _maxY);
  737. unsigned short *tmpBufferEnd = _tmpBuffer;
  738. int i = 0;
  739. for (ChannelList::ConstIterator c = _channels.begin();
  740. c != _channels.end();
  741. ++c, ++i)
  742. {
  743. ChannelData &cd = _channelData[i];
  744. cd.start = tmpBufferEnd;
  745. cd.end = cd.start;
  746. cd.nx = numSamples (c.channel().xSampling, minX, maxX);
  747. cd.ny = numSamples (c.channel().ySampling, minY, maxY);
  748. tmpBufferEnd += cd.nx * cd.ny * cd.size;
  749. }
  750. for (int i = 0; i < _numChans; ++i)
  751. {
  752. ChannelData &cd = _channelData[i];
  753. if (cd.type != HALF)
  754. {
  755. //
  756. // UINT or FLOAT channel.
  757. //
  758. int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
  759. if (inSize < n)
  760. notEnoughData();
  761. memcpy (cd.start, inPtr, n);
  762. inPtr += n;
  763. inSize -= n;
  764. continue;
  765. }
  766. //
  767. // HALF channel
  768. //
  769. for (int y = 0; y < cd.ny; y += 4)
  770. {
  771. unsigned short *row0 = cd.start + y * cd.nx;
  772. unsigned short *row1 = row0 + cd.nx;
  773. unsigned short *row2 = row1 + cd.nx;
  774. unsigned short *row3 = row2 + cd.nx;
  775. for (int x = 0; x < cd.nx; x += 4)
  776. {
  777. unsigned short s[16];
  778. if (inSize < 3)
  779. notEnoughData();
  780. if (((const unsigned char *)inPtr)[2] == 0xfc)
  781. {
  782. unpack3 ((const unsigned char *)inPtr, s);
  783. inPtr += 3;
  784. inSize -= 3;
  785. }
  786. else
  787. {
  788. if (inSize < 14)
  789. notEnoughData();
  790. unpack14 ((const unsigned char *)inPtr, s);
  791. inPtr += 14;
  792. inSize -= 14;
  793. }
  794. if (cd.pLinear)
  795. convertToLinear (s);
  796. int n = (x + 3 < cd.nx)?
  797. 4 * sizeof (unsigned short) :
  798. (cd.nx - x) * sizeof (unsigned short);
  799. if (y + 3 < cd.ny)
  800. {
  801. memcpy (row0, &s[ 0], n);
  802. memcpy (row1, &s[ 4], n);
  803. memcpy (row2, &s[ 8], n);
  804. memcpy (row3, &s[12], n);
  805. }
  806. else
  807. {
  808. memcpy (row0, &s[ 0], n);
  809. if (y + 1 < cd.ny)
  810. memcpy (row1, &s[ 4], n);
  811. if (y + 2 < cd.ny)
  812. memcpy (row2, &s[ 8], n);
  813. }
  814. row0 += 4;
  815. row1 += 4;
  816. row2 += 4;
  817. row3 += 4;
  818. }
  819. }
  820. }
  821. char *outEnd = _outBuffer;
  822. if (_format == XDR)
  823. {
  824. for (int y = minY; y <= maxY; ++y)
  825. {
  826. for (int i = 0; i < _numChans; ++i)
  827. {
  828. ChannelData &cd = _channelData[i];
  829. if (modp (y, cd.ys) != 0)
  830. continue;
  831. if (cd.type == HALF)
  832. {
  833. for (int x = cd.nx; x > 0; --x)
  834. {
  835. Xdr::write <CharPtrIO> (outEnd, *cd.end);
  836. ++cd.end;
  837. }
  838. }
  839. else
  840. {
  841. int n = cd.nx * cd.size;
  842. memcpy (outEnd, cd.end, n * sizeof (unsigned short));
  843. outEnd += n * sizeof (unsigned short);
  844. cd.end += n;
  845. }
  846. }
  847. }
  848. }
  849. else
  850. {
  851. for (int y = minY; y <= maxY; ++y)
  852. {
  853. for (int i = 0; i < _numChans; ++i)
  854. {
  855. ChannelData &cd = _channelData[i];
  856. #if defined (DEBUG)
  857. assert (cd.type == HALF);
  858. #endif
  859. if (modp (y, cd.ys) != 0)
  860. continue;
  861. int n = cd.nx * cd.size;
  862. memcpy (outEnd, cd.end, n * sizeof (unsigned short));
  863. outEnd += n * sizeof (unsigned short);
  864. cd.end += n;
  865. }
  866. }
  867. }
  868. #if defined (DEBUG)
  869. for (int i = 1; i < _numChans; ++i)
  870. assert (_channelData[i-1].end == _channelData[i].start);
  871. assert (_channelData[_numChans-1].end == tmpBufferEnd);
  872. #endif
  873. if (inSize > 0)
  874. tooMuchData();
  875. outPtr = _outBuffer;
  876. return outEnd - _outBuffer;
  877. }
  878. OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT