/src/FreeImage/Source/OpenEXR/IlmImf/ImfMisc.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 787 lines · 542 code · 172 blank · 73 comment · 80 complexity · aaf31256e57e679a4e004ddebf282ddf MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2004, 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. // Miscellaneous helper functions for OpenEXR image file I/O
  37. //
  38. //-----------------------------------------------------------------------------
  39. #include <ImfMisc.h>
  40. #include <ImfHeader.h>
  41. #include <ImfCompressor.h>
  42. #include <ImfChannelList.h>
  43. #include <ImfXdr.h>
  44. #include <ImathFun.h>
  45. #include <Iex.h>
  46. #include <ImfStdIO.h>
  47. #include <ImfConvert.h>
  48. namespace Imf {
  49. using Imath::Box2i;
  50. using Imath::divp;
  51. using Imath::modp;
  52. using std::vector;
  53. int
  54. pixelTypeSize (PixelType type)
  55. {
  56. int size;
  57. switch (type)
  58. {
  59. case UINT:
  60. size = Xdr::size <unsigned int> ();
  61. break;
  62. case HALF:
  63. size = Xdr::size <half> ();
  64. break;
  65. case FLOAT:
  66. size = Xdr::size <float> ();
  67. break;
  68. default:
  69. throw Iex::ArgExc ("Unknown pixel type.");
  70. }
  71. return size;
  72. }
  73. int
  74. numSamples (int s, int a, int b)
  75. {
  76. int a1 = divp (a, s);
  77. int b1 = divp (b, s);
  78. return b1 - a1 + ((a1 * s < a)? 0: 1);
  79. }
  80. size_t
  81. bytesPerLineTable (const Header &header,
  82. vector<size_t> &bytesPerLine)
  83. {
  84. const Box2i &dataWindow = header.dataWindow();
  85. const ChannelList &channels = header.channels();
  86. bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1);
  87. for (ChannelList::ConstIterator c = channels.begin();
  88. c != channels.end();
  89. ++c)
  90. {
  91. int nBytes = pixelTypeSize (c.channel().type) *
  92. (dataWindow.max.x - dataWindow.min.x + 1) /
  93. c.channel().xSampling;
  94. for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
  95. if (modp (y, c.channel().ySampling) == 0)
  96. bytesPerLine[i] += nBytes;
  97. }
  98. size_t maxBytesPerLine = 0;
  99. for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
  100. if (maxBytesPerLine < bytesPerLine[i])
  101. maxBytesPerLine = bytesPerLine[i];
  102. return maxBytesPerLine;
  103. }
  104. void
  105. offsetInLineBufferTable (const vector<size_t> &bytesPerLine,
  106. int linesInLineBuffer,
  107. vector<size_t> &offsetInLineBuffer)
  108. {
  109. offsetInLineBuffer.resize (bytesPerLine.size());
  110. size_t offset = 0;
  111. for (int i = 0; i < bytesPerLine.size(); ++i)
  112. {
  113. if (i % linesInLineBuffer == 0)
  114. offset = 0;
  115. offsetInLineBuffer[i] = offset;
  116. offset += bytesPerLine[i];
  117. }
  118. }
  119. int
  120. lineBufferMinY (int y, int minY, int linesInLineBuffer)
  121. {
  122. return ((y - minY) / linesInLineBuffer) * linesInLineBuffer + minY;
  123. }
  124. int
  125. lineBufferMaxY (int y, int minY, int linesInLineBuffer)
  126. {
  127. return lineBufferMinY (y, minY, linesInLineBuffer) + linesInLineBuffer - 1;
  128. }
  129. Compressor::Format
  130. defaultFormat (Compressor * compressor)
  131. {
  132. return compressor? compressor->format(): Compressor::XDR;
  133. }
  134. int
  135. numLinesInBuffer (Compressor * compressor)
  136. {
  137. return compressor? compressor->numScanLines(): 1;
  138. }
  139. void
  140. copyIntoFrameBuffer (const char *& readPtr,
  141. char * writePtr,
  142. char * endPtr,
  143. size_t xStride,
  144. bool fill,
  145. double fillValue,
  146. Compressor::Format format,
  147. PixelType typeInFrameBuffer,
  148. PixelType typeInFile)
  149. {
  150. //
  151. // Copy a horizontal row of pixels from an input
  152. // file's line or tile buffer to a frame buffer.
  153. //
  154. if (fill)
  155. {
  156. //
  157. // The file contains no data for this channel.
  158. // Store a default value in the frame buffer.
  159. //
  160. switch (typeInFrameBuffer)
  161. {
  162. case UINT:
  163. {
  164. unsigned int fillVal = (unsigned int) (fillValue);
  165. while (writePtr <= endPtr)
  166. {
  167. *(unsigned int *) writePtr = fillVal;
  168. writePtr += xStride;
  169. }
  170. }
  171. break;
  172. case HALF:
  173. {
  174. half fillVal = half (fillValue);
  175. while (writePtr <= endPtr)
  176. {
  177. *(half *) writePtr = fillVal;
  178. writePtr += xStride;
  179. }
  180. }
  181. break;
  182. case FLOAT:
  183. {
  184. float fillVal = float (fillValue);
  185. while (writePtr <= endPtr)
  186. {
  187. *(float *) writePtr = fillVal;
  188. writePtr += xStride;
  189. }
  190. }
  191. break;
  192. default:
  193. throw Iex::ArgExc ("Unknown pixel data type.");
  194. }
  195. }
  196. else if (format == Compressor::XDR)
  197. {
  198. //
  199. // The the line or tile buffer is in XDR format.
  200. //
  201. // Convert the pixels from the file's machine-
  202. // independent representation, and store the
  203. // results in the frame buffer.
  204. //
  205. switch (typeInFrameBuffer)
  206. {
  207. case UINT:
  208. switch (typeInFile)
  209. {
  210. case UINT:
  211. while (writePtr <= endPtr)
  212. {
  213. Xdr::read <CharPtrIO> (readPtr, *(unsigned int *) writePtr);
  214. writePtr += xStride;
  215. }
  216. break;
  217. case HALF:
  218. while (writePtr <= endPtr)
  219. {
  220. half h;
  221. Xdr::read <CharPtrIO> (readPtr, h);
  222. *(unsigned int *) writePtr = halfToUint (h);
  223. writePtr += xStride;
  224. }
  225. break;
  226. case FLOAT:
  227. while (writePtr <= endPtr)
  228. {
  229. float f;
  230. Xdr::read <CharPtrIO> (readPtr, f);
  231. *(unsigned int *)writePtr = floatToUint (f);
  232. writePtr += xStride;
  233. }
  234. break;
  235. }
  236. break;
  237. case HALF:
  238. switch (typeInFile)
  239. {
  240. case UINT:
  241. while (writePtr <= endPtr)
  242. {
  243. unsigned int ui;
  244. Xdr::read <CharPtrIO> (readPtr, ui);
  245. *(half *) writePtr = uintToHalf (ui);
  246. writePtr += xStride;
  247. }
  248. break;
  249. case HALF:
  250. while (writePtr <= endPtr)
  251. {
  252. Xdr::read <CharPtrIO> (readPtr, *(half *) writePtr);
  253. writePtr += xStride;
  254. }
  255. break;
  256. case FLOAT:
  257. while (writePtr <= endPtr)
  258. {
  259. float f;
  260. Xdr::read <CharPtrIO> (readPtr, f);
  261. *(half *) writePtr = floatToHalf (f);
  262. writePtr += xStride;
  263. }
  264. break;
  265. }
  266. break;
  267. case FLOAT:
  268. switch (typeInFile)
  269. {
  270. case UINT:
  271. while (writePtr <= endPtr)
  272. {
  273. unsigned int ui;
  274. Xdr::read <CharPtrIO> (readPtr, ui);
  275. *(float *) writePtr = float (ui);
  276. writePtr += xStride;
  277. }
  278. break;
  279. case HALF:
  280. while (writePtr <= endPtr)
  281. {
  282. half h;
  283. Xdr::read <CharPtrIO> (readPtr, h);
  284. *(float *) writePtr = float (h);
  285. writePtr += xStride;
  286. }
  287. break;
  288. case FLOAT:
  289. while (writePtr <= endPtr)
  290. {
  291. Xdr::read <CharPtrIO> (readPtr, *(float *) writePtr);
  292. writePtr += xStride;
  293. }
  294. break;
  295. }
  296. break;
  297. default:
  298. throw Iex::ArgExc ("Unknown pixel data type.");
  299. }
  300. }
  301. else
  302. {
  303. //
  304. // The the line or tile buffer is in NATIVE format.
  305. // Copy the results into the frame buffer.
  306. //
  307. switch (typeInFrameBuffer)
  308. {
  309. case UINT:
  310. switch (typeInFile)
  311. {
  312. case UINT:
  313. while (writePtr <= endPtr)
  314. {
  315. for (size_t i = 0; i < sizeof (unsigned int); ++i)
  316. writePtr[i] = readPtr[i];
  317. readPtr += sizeof (unsigned int);
  318. writePtr += xStride;
  319. }
  320. break;
  321. case HALF:
  322. while (writePtr <= endPtr)
  323. {
  324. half h = *(half *) readPtr;
  325. *(unsigned int *) writePtr = halfToUint (h);
  326. readPtr += sizeof (half);
  327. writePtr += xStride;
  328. }
  329. break;
  330. case FLOAT:
  331. while (writePtr <= endPtr)
  332. {
  333. float f;
  334. for (size_t i = 0; i < sizeof (float); ++i)
  335. ((char *)&f)[i] = readPtr[i];
  336. *(unsigned int *)writePtr = floatToUint (f);
  337. readPtr += sizeof (float);
  338. writePtr += xStride;
  339. }
  340. break;
  341. }
  342. break;
  343. case HALF:
  344. switch (typeInFile)
  345. {
  346. case UINT:
  347. while (writePtr <= endPtr)
  348. {
  349. unsigned int ui;
  350. for (size_t i = 0; i < sizeof (unsigned int); ++i)
  351. ((char *)&ui)[i] = readPtr[i];
  352. *(half *) writePtr = uintToHalf (ui);
  353. readPtr += sizeof (unsigned int);
  354. writePtr += xStride;
  355. }
  356. break;
  357. case HALF:
  358. while (writePtr <= endPtr)
  359. {
  360. *(half *) writePtr = *(half *)readPtr;
  361. readPtr += sizeof (half);
  362. writePtr += xStride;
  363. }
  364. break;
  365. case FLOAT:
  366. while (writePtr <= endPtr)
  367. {
  368. float f;
  369. for (size_t i = 0; i < sizeof (float); ++i)
  370. ((char *)&f)[i] = readPtr[i];
  371. *(half *) writePtr = floatToHalf (f);
  372. readPtr += sizeof (float);
  373. writePtr += xStride;
  374. }
  375. break;
  376. }
  377. break;
  378. case FLOAT:
  379. switch (typeInFile)
  380. {
  381. case UINT:
  382. while (writePtr <= endPtr)
  383. {
  384. unsigned int ui;
  385. for (size_t i = 0; i < sizeof (unsigned int); ++i)
  386. ((char *)&ui)[i] = readPtr[i];
  387. *(float *) writePtr = float (ui);
  388. readPtr += sizeof (unsigned int);
  389. writePtr += xStride;
  390. }
  391. break;
  392. case HALF:
  393. while (writePtr <= endPtr)
  394. {
  395. half h = *(half *) readPtr;
  396. *(float *) writePtr = float (h);
  397. readPtr += sizeof (half);
  398. writePtr += xStride;
  399. }
  400. break;
  401. case FLOAT:
  402. while (writePtr <= endPtr)
  403. {
  404. for (size_t i = 0; i < sizeof (float); ++i)
  405. writePtr[i] = readPtr[i];
  406. readPtr += sizeof (float);
  407. writePtr += xStride;
  408. }
  409. break;
  410. }
  411. break;
  412. default:
  413. throw Iex::ArgExc ("Unknown pixel data type.");
  414. }
  415. }
  416. }
  417. void
  418. skipChannel (const char *& readPtr,
  419. PixelType typeInFile,
  420. size_t xSize)
  421. {
  422. switch (typeInFile)
  423. {
  424. case UINT:
  425. Xdr::skip <CharPtrIO> (readPtr, Xdr::size <unsigned int> () * xSize);
  426. break;
  427. case HALF:
  428. Xdr::skip <CharPtrIO> (readPtr, Xdr::size <half> () * xSize);
  429. break;
  430. case FLOAT:
  431. Xdr::skip <CharPtrIO> (readPtr, Xdr::size <float> () * xSize);
  432. break;
  433. default:
  434. throw Iex::ArgExc ("Unknown pixel data type.");
  435. }
  436. }
  437. void
  438. convertInPlace (char *& writePtr,
  439. const char *& readPtr,
  440. PixelType type,
  441. size_t numPixels)
  442. {
  443. switch (type)
  444. {
  445. case UINT:
  446. for (int j = 0; j < numPixels; ++j)
  447. {
  448. Xdr::write <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
  449. readPtr += sizeof(unsigned int);
  450. }
  451. break;
  452. case HALF:
  453. for (int j = 0; j < numPixels; ++j)
  454. {
  455. Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
  456. readPtr += sizeof(half);
  457. }
  458. break;
  459. case FLOAT:
  460. for (int j = 0; j < numPixels; ++j)
  461. {
  462. Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
  463. readPtr += sizeof(float);
  464. }
  465. break;
  466. default:
  467. throw Iex::ArgExc ("Unknown pixel data type.");
  468. }
  469. }
  470. void
  471. copyFromFrameBuffer (char *& writePtr,
  472. const char *& readPtr,
  473. const char * endPtr,
  474. size_t xStride,
  475. Compressor::Format format,
  476. PixelType type)
  477. {
  478. //
  479. // Copy a horizontal row of pixels from a frame
  480. // buffer to an output file's line or tile buffer.
  481. //
  482. if (format == Compressor::XDR)
  483. {
  484. //
  485. // The the line or tile buffer is in XDR format.
  486. //
  487. switch (type)
  488. {
  489. case UINT:
  490. while (readPtr <= endPtr)
  491. {
  492. Xdr::write <CharPtrIO> (writePtr,
  493. *(const unsigned int *) readPtr);
  494. readPtr += xStride;
  495. }
  496. break;
  497. case HALF:
  498. while (readPtr <= endPtr)
  499. {
  500. Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
  501. readPtr += xStride;
  502. }
  503. break;
  504. case FLOAT:
  505. while (readPtr <= endPtr)
  506. {
  507. Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
  508. readPtr += xStride;
  509. }
  510. break;
  511. default:
  512. throw Iex::ArgExc ("Unknown pixel data type.");
  513. }
  514. }
  515. else
  516. {
  517. //
  518. // The the line or tile buffer is in NATIVE format.
  519. //
  520. switch (type)
  521. {
  522. case UINT:
  523. while (readPtr <= endPtr)
  524. {
  525. for (size_t i = 0; i < sizeof (unsigned int); ++i)
  526. *writePtr++ = readPtr[i];
  527. readPtr += xStride;
  528. }
  529. break;
  530. case HALF:
  531. while (readPtr <= endPtr)
  532. {
  533. *(half *) writePtr = *(const half *) readPtr;
  534. writePtr += sizeof (half);
  535. readPtr += xStride;
  536. }
  537. break;
  538. case FLOAT:
  539. while (readPtr <= endPtr)
  540. {
  541. for (size_t i = 0; i < sizeof (float); ++i)
  542. *writePtr++ = readPtr[i];
  543. readPtr += xStride;
  544. }
  545. break;
  546. default:
  547. throw Iex::ArgExc ("Unknown pixel data type.");
  548. }
  549. }
  550. }
  551. void
  552. fillChannelWithZeroes (char *& writePtr,
  553. Compressor::Format format,
  554. PixelType type,
  555. size_t xSize)
  556. {
  557. if (format == Compressor::XDR)
  558. {
  559. //
  560. // Fill with data in XDR format.
  561. //
  562. switch (type)
  563. {
  564. case UINT:
  565. for (int j = 0; j < xSize; ++j)
  566. Xdr::write <CharPtrIO> (writePtr, (unsigned int) 0);
  567. break;
  568. case HALF:
  569. for (int j = 0; j < xSize; ++j)
  570. Xdr::write <CharPtrIO> (writePtr, (half) 0);
  571. break;
  572. case FLOAT:
  573. for (int j = 0; j < xSize; ++j)
  574. Xdr::write <CharPtrIO> (writePtr, (float) 0);
  575. break;
  576. default:
  577. throw Iex::ArgExc ("Unknown pixel data type.");
  578. }
  579. }
  580. else
  581. {
  582. //
  583. // Fill with data in NATIVE format.
  584. //
  585. switch (type)
  586. {
  587. case UINT:
  588. for (int j = 0; j < xSize; ++j)
  589. {
  590. static const unsigned int ui = 0;
  591. for (size_t i = 0; i < sizeof (ui); ++i)
  592. *writePtr++ = ((char *) &ui)[i];
  593. }
  594. break;
  595. case HALF:
  596. for (int j = 0; j < xSize; ++j)
  597. {
  598. *(half *) writePtr = half (0);
  599. writePtr += sizeof (half);
  600. }
  601. break;
  602. case FLOAT:
  603. for (int j = 0; j < xSize; ++j)
  604. {
  605. static const float f = 0;
  606. for (size_t i = 0; i < sizeof (f); ++i)
  607. *writePtr++ = ((char *) &f)[i];
  608. }
  609. break;
  610. default:
  611. throw Iex::ArgExc ("Unknown pixel data type.");
  612. }
  613. }
  614. }
  615. } // namespace Imf