ImfTiledRgbaFile.cpp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163
  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. // class TiledRgbaOutputFile
  37. // class TiledRgbaInputFile
  38. //
  39. //-----------------------------------------------------------------------------
  40. #include <ImfTiledRgbaFile.h>
  41. #include <ImfRgbaFile.h>
  42. #include <ImfTiledOutputFile.h>
  43. #include <ImfTiledInputFile.h>
  44. #include <ImfChannelList.h>
  45. #include <ImfTileDescriptionAttribute.h>
  46. #include <ImfStandardAttributes.h>
  47. #include <ImfRgbaYca.h>
  48. #include <ImfArray.h>
  49. #include "IlmThreadMutex.h"
  50. #include "Iex.h"
  51. #include "ImfNamespace.h"
  52. OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
  53. using namespace std;
  54. using namespace IMATH_NAMESPACE;
  55. using namespace RgbaYca;
  56. using namespace ILMTHREAD_NAMESPACE;
  57. namespace {
  58. void
  59. insertChannels (Header &header,
  60. RgbaChannels rgbaChannels,
  61. const char fileName[])
  62. {
  63. ChannelList ch;
  64. if (rgbaChannels & (WRITE_Y | WRITE_C))
  65. {
  66. if (rgbaChannels & WRITE_Y)
  67. {
  68. ch.insert ("Y", Channel (HALF, 1, 1));
  69. }
  70. if (rgbaChannels & WRITE_C)
  71. {
  72. THROW (IEX_NAMESPACE::ArgExc, "Cannot open file \"" << fileName << "\" "
  73. "for writing. Tiled image files do not "
  74. "support subsampled chroma channels.");
  75. }
  76. }
  77. else
  78. {
  79. if (rgbaChannels & WRITE_R)
  80. ch.insert ("R", Channel (HALF, 1, 1));
  81. if (rgbaChannels & WRITE_G)
  82. ch.insert ("G", Channel (HALF, 1, 1));
  83. if (rgbaChannels & WRITE_B)
  84. ch.insert ("B", Channel (HALF, 1, 1));
  85. }
  86. if (rgbaChannels & WRITE_A)
  87. ch.insert ("A", Channel (HALF, 1, 1));
  88. header.channels() = ch;
  89. }
  90. RgbaChannels
  91. rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "")
  92. {
  93. int i = 0;
  94. if (ch.findChannel (channelNamePrefix + "R"))
  95. i |= WRITE_R;
  96. if (ch.findChannel (channelNamePrefix + "G"))
  97. i |= WRITE_G;
  98. if (ch.findChannel (channelNamePrefix + "B"))
  99. i |= WRITE_B;
  100. if (ch.findChannel (channelNamePrefix + "A"))
  101. i |= WRITE_A;
  102. if (ch.findChannel (channelNamePrefix + "Y"))
  103. i |= WRITE_Y;
  104. return RgbaChannels (i);
  105. }
  106. string
  107. prefixFromLayerName (const string &layerName, const Header &header)
  108. {
  109. if (layerName.empty())
  110. return "";
  111. if (hasMultiView (header) && multiView(header)[0] == layerName)
  112. return "";
  113. return layerName + ".";
  114. }
  115. V3f
  116. ywFromHeader (const Header &header)
  117. {
  118. Chromaticities cr;
  119. if (hasChromaticities (header))
  120. cr = chromaticities (header);
  121. return computeYw (cr);
  122. }
  123. } // namespace
  124. class TiledRgbaOutputFile::ToYa: public Mutex
  125. {
  126. public:
  127. ToYa (TiledOutputFile &outputFile, RgbaChannels rgbaChannels);
  128. void setFrameBuffer (const Rgba *base,
  129. size_t xStride,
  130. size_t yStride);
  131. void writeTile (int dx, int dy, int lx, int ly);
  132. private:
  133. TiledOutputFile & _outputFile;
  134. bool _writeA;
  135. unsigned int _tileXSize;
  136. unsigned int _tileYSize;
  137. V3f _yw;
  138. Array2D <Rgba> _buf;
  139. const Rgba * _fbBase;
  140. size_t _fbXStride;
  141. size_t _fbYStride;
  142. };
  143. TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile,
  144. RgbaChannels rgbaChannels)
  145. :
  146. _outputFile (outputFile)
  147. {
  148. _writeA = (rgbaChannels & WRITE_A)? true: false;
  149. const TileDescription &td = outputFile.header().tileDescription();
  150. _tileXSize = td.xSize;
  151. _tileYSize = td.ySize;
  152. _yw = ywFromHeader (_outputFile.header());
  153. _buf.resizeErase (_tileYSize, _tileXSize);
  154. _fbBase = 0;
  155. _fbXStride = 0;
  156. _fbYStride = 0;
  157. }
  158. void
  159. TiledRgbaOutputFile::ToYa::setFrameBuffer (const Rgba *base,
  160. size_t xStride,
  161. size_t yStride)
  162. {
  163. _fbBase = base;
  164. _fbXStride = xStride;
  165. _fbYStride = yStride;
  166. }
  167. void
  168. TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly)
  169. {
  170. if (_fbBase == 0)
  171. {
  172. THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the "
  173. "pixel data source for image file "
  174. "\"" << _outputFile.fileName() << "\".");
  175. }
  176. //
  177. // Copy the tile's RGBA pixels into _buf and convert
  178. // them to luminance/alpha format
  179. //
  180. Box2i dw = _outputFile.dataWindowForTile (dx, dy, lx, ly);
  181. int width = dw.max.x - dw.min.x + 1;
  182. for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
  183. {
  184. for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
  185. _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride];
  186. RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]);
  187. }
  188. //
  189. // Store the contents of _buf in the output file
  190. //
  191. FrameBuffer fb;
  192. fb.insert ("Y", Slice (HALF, // type
  193. (char *) &_buf[-dw.min.y][-dw.min.x].g, // base
  194. sizeof (Rgba), // xStride
  195. sizeof (Rgba) * _tileXSize)); // yStride
  196. fb.insert ("A", Slice (HALF, // type
  197. (char *) &_buf[-dw.min.y][-dw.min.x].a, // base
  198. sizeof (Rgba), // xStride
  199. sizeof (Rgba) * _tileXSize)); // yStride
  200. _outputFile.setFrameBuffer (fb);
  201. _outputFile.writeTile (dx, dy, lx, ly);
  202. }
  203. TiledRgbaOutputFile::TiledRgbaOutputFile
  204. (const char name[],
  205. const Header &header,
  206. RgbaChannels rgbaChannels,
  207. int tileXSize,
  208. int tileYSize,
  209. LevelMode mode,
  210. LevelRoundingMode rmode,
  211. int numThreads)
  212. :
  213. _outputFile (0),
  214. _toYa (0)
  215. {
  216. Header hd (header);
  217. insertChannels (hd, rgbaChannels, name);
  218. hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
  219. _outputFile = new TiledOutputFile (name, hd, numThreads);
  220. if (rgbaChannels & WRITE_Y)
  221. _toYa = new ToYa (*_outputFile, rgbaChannels);
  222. }
  223. TiledRgbaOutputFile::TiledRgbaOutputFile
  224. (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os,
  225. const Header &header,
  226. RgbaChannels rgbaChannels,
  227. int tileXSize,
  228. int tileYSize,
  229. LevelMode mode,
  230. LevelRoundingMode rmode,
  231. int numThreads)
  232. :
  233. _outputFile (0),
  234. _toYa (0)
  235. {
  236. Header hd (header);
  237. insertChannels (hd, rgbaChannels, os.fileName());
  238. hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
  239. _outputFile = new TiledOutputFile (os, hd, numThreads);
  240. if (rgbaChannels & WRITE_Y)
  241. _toYa = new ToYa (*_outputFile, rgbaChannels);
  242. }
  243. TiledRgbaOutputFile::TiledRgbaOutputFile
  244. (const char name[],
  245. int tileXSize,
  246. int tileYSize,
  247. LevelMode mode,
  248. LevelRoundingMode rmode,
  249. const IMATH_NAMESPACE::Box2i &displayWindow,
  250. const IMATH_NAMESPACE::Box2i &dataWindow,
  251. RgbaChannels rgbaChannels,
  252. float pixelAspectRatio,
  253. const IMATH_NAMESPACE::V2f screenWindowCenter,
  254. float screenWindowWidth,
  255. LineOrder lineOrder,
  256. Compression compression,
  257. int numThreads)
  258. :
  259. _outputFile (0),
  260. _toYa (0)
  261. {
  262. Header hd (displayWindow,
  263. dataWindow.isEmpty()? displayWindow: dataWindow,
  264. pixelAspectRatio,
  265. screenWindowCenter,
  266. screenWindowWidth,
  267. lineOrder,
  268. compression);
  269. insertChannels (hd, rgbaChannels, name);
  270. hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
  271. _outputFile = new TiledOutputFile (name, hd, numThreads);
  272. if (rgbaChannels & WRITE_Y)
  273. _toYa = new ToYa (*_outputFile, rgbaChannels);
  274. }
  275. TiledRgbaOutputFile::TiledRgbaOutputFile
  276. (const char name[],
  277. int width,
  278. int height,
  279. int tileXSize,
  280. int tileYSize,
  281. LevelMode mode,
  282. LevelRoundingMode rmode,
  283. RgbaChannels rgbaChannels,
  284. float pixelAspectRatio,
  285. const IMATH_NAMESPACE::V2f screenWindowCenter,
  286. float screenWindowWidth,
  287. LineOrder lineOrder,
  288. Compression compression,
  289. int numThreads)
  290. :
  291. _outputFile (0),
  292. _toYa (0)
  293. {
  294. Header hd (width,
  295. height,
  296. pixelAspectRatio,
  297. screenWindowCenter,
  298. screenWindowWidth,
  299. lineOrder,
  300. compression);
  301. insertChannels (hd, rgbaChannels, name);
  302. hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
  303. _outputFile = new TiledOutputFile (name, hd, numThreads);
  304. if (rgbaChannels & WRITE_Y)
  305. _toYa = new ToYa (*_outputFile, rgbaChannels);
  306. }
  307. TiledRgbaOutputFile::~TiledRgbaOutputFile ()
  308. {
  309. delete _outputFile;
  310. delete _toYa;
  311. }
  312. void
  313. TiledRgbaOutputFile::setFrameBuffer (const Rgba *base,
  314. size_t xStride,
  315. size_t yStride)
  316. {
  317. if (_toYa)
  318. {
  319. Lock lock (*_toYa);
  320. _toYa->setFrameBuffer (base, xStride, yStride);
  321. }
  322. else
  323. {
  324. size_t xs = xStride * sizeof (Rgba);
  325. size_t ys = yStride * sizeof (Rgba);
  326. FrameBuffer fb;
  327. fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));
  328. fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));
  329. fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));
  330. fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));
  331. _outputFile->setFrameBuffer (fb);
  332. }
  333. }
  334. const Header &
  335. TiledRgbaOutputFile::header () const
  336. {
  337. return _outputFile->header();
  338. }
  339. const FrameBuffer &
  340. TiledRgbaOutputFile::frameBuffer () const
  341. {
  342. return _outputFile->frameBuffer();
  343. }
  344. const IMATH_NAMESPACE::Box2i &
  345. TiledRgbaOutputFile::displayWindow () const
  346. {
  347. return _outputFile->header().displayWindow();
  348. }
  349. const IMATH_NAMESPACE::Box2i &
  350. TiledRgbaOutputFile::dataWindow () const
  351. {
  352. return _outputFile->header().dataWindow();
  353. }
  354. float
  355. TiledRgbaOutputFile::pixelAspectRatio () const
  356. {
  357. return _outputFile->header().pixelAspectRatio();
  358. }
  359. const IMATH_NAMESPACE::V2f
  360. TiledRgbaOutputFile::screenWindowCenter () const
  361. {
  362. return _outputFile->header().screenWindowCenter();
  363. }
  364. float
  365. TiledRgbaOutputFile::screenWindowWidth () const
  366. {
  367. return _outputFile->header().screenWindowWidth();
  368. }
  369. LineOrder
  370. TiledRgbaOutputFile::lineOrder () const
  371. {
  372. return _outputFile->header().lineOrder();
  373. }
  374. Compression
  375. TiledRgbaOutputFile::compression () const
  376. {
  377. return _outputFile->header().compression();
  378. }
  379. RgbaChannels
  380. TiledRgbaOutputFile::channels () const
  381. {
  382. return rgbaChannels (_outputFile->header().channels());
  383. }
  384. unsigned int
  385. TiledRgbaOutputFile::tileXSize () const
  386. {
  387. return _outputFile->tileXSize();
  388. }
  389. unsigned int
  390. TiledRgbaOutputFile::tileYSize () const
  391. {
  392. return _outputFile->tileYSize();
  393. }
  394. LevelMode
  395. TiledRgbaOutputFile::levelMode () const
  396. {
  397. return _outputFile->levelMode();
  398. }
  399. LevelRoundingMode
  400. TiledRgbaOutputFile::levelRoundingMode () const
  401. {
  402. return _outputFile->levelRoundingMode();
  403. }
  404. int
  405. TiledRgbaOutputFile::numLevels () const
  406. {
  407. return _outputFile->numLevels();
  408. }
  409. int
  410. TiledRgbaOutputFile::numXLevels () const
  411. {
  412. return _outputFile->numXLevels();
  413. }
  414. int
  415. TiledRgbaOutputFile::numYLevels () const
  416. {
  417. return _outputFile->numYLevels();
  418. }
  419. bool
  420. TiledRgbaOutputFile::isValidLevel (int lx, int ly) const
  421. {
  422. return _outputFile->isValidLevel (lx, ly);
  423. }
  424. int
  425. TiledRgbaOutputFile::levelWidth (int lx) const
  426. {
  427. return _outputFile->levelWidth (lx);
  428. }
  429. int
  430. TiledRgbaOutputFile::levelHeight (int ly) const
  431. {
  432. return _outputFile->levelHeight (ly);
  433. }
  434. int
  435. TiledRgbaOutputFile::numXTiles (int lx) const
  436. {
  437. return _outputFile->numXTiles (lx);
  438. }
  439. int
  440. TiledRgbaOutputFile::numYTiles (int ly) const
  441. {
  442. return _outputFile->numYTiles (ly);
  443. }
  444. IMATH_NAMESPACE::Box2i
  445. TiledRgbaOutputFile::dataWindowForLevel (int l) const
  446. {
  447. return _outputFile->dataWindowForLevel (l);
  448. }
  449. IMATH_NAMESPACE::Box2i
  450. TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const
  451. {
  452. return _outputFile->dataWindowForLevel (lx, ly);
  453. }
  454. IMATH_NAMESPACE::Box2i
  455. TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const
  456. {
  457. return _outputFile->dataWindowForTile (dx, dy, l);
  458. }
  459. IMATH_NAMESPACE::Box2i
  460. TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
  461. {
  462. return _outputFile->dataWindowForTile (dx, dy, lx, ly);
  463. }
  464. void
  465. TiledRgbaOutputFile::writeTile (int dx, int dy, int l)
  466. {
  467. if (_toYa)
  468. {
  469. Lock lock (*_toYa);
  470. _toYa->writeTile (dx, dy, l, l);
  471. }
  472. else
  473. {
  474. _outputFile->writeTile (dx, dy, l);
  475. }
  476. }
  477. void
  478. TiledRgbaOutputFile::writeTile (int dx, int dy, int lx, int ly)
  479. {
  480. if (_toYa)
  481. {
  482. Lock lock (*_toYa);
  483. _toYa->writeTile (dx, dy, lx, ly);
  484. }
  485. else
  486. {
  487. _outputFile->writeTile (dx, dy, lx, ly);
  488. }
  489. }
  490. void
  491. TiledRgbaOutputFile::writeTiles
  492. (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly)
  493. {
  494. if (_toYa)
  495. {
  496. Lock lock (*_toYa);
  497. for (int dy = dyMin; dy <= dyMax; dy++)
  498. for (int dx = dxMin; dx <= dxMax; dx++)
  499. _toYa->writeTile (dx, dy, lx, ly);
  500. }
  501. else
  502. {
  503. _outputFile->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
  504. }
  505. }
  506. void
  507. TiledRgbaOutputFile::writeTiles
  508. (int dxMin, int dxMax, int dyMin, int dyMax, int l)
  509. {
  510. writeTiles (dxMin, dxMax, dyMin, dyMax, l, l);
  511. }
  512. class TiledRgbaInputFile::FromYa: public Mutex
  513. {
  514. public:
  515. FromYa (TiledInputFile &inputFile);
  516. void setFrameBuffer (Rgba *base,
  517. size_t xStride,
  518. size_t yStride,
  519. const string &channelNamePrefix);
  520. void readTile (int dx, int dy, int lx, int ly);
  521. private:
  522. TiledInputFile & _inputFile;
  523. unsigned int _tileXSize;
  524. unsigned int _tileYSize;
  525. V3f _yw;
  526. Array2D <Rgba> _buf;
  527. Rgba * _fbBase;
  528. size_t _fbXStride;
  529. size_t _fbYStride;
  530. };
  531. TiledRgbaInputFile::FromYa::FromYa (TiledInputFile &inputFile)
  532. :
  533. _inputFile (inputFile)
  534. {
  535. const TileDescription &td = inputFile.header().tileDescription();
  536. _tileXSize = td.xSize;
  537. _tileYSize = td.ySize;
  538. _yw = ywFromHeader (_inputFile.header());
  539. _buf.resizeErase (_tileYSize, _tileXSize);
  540. _fbBase = 0;
  541. _fbXStride = 0;
  542. _fbYStride = 0;
  543. }
  544. void
  545. TiledRgbaInputFile::FromYa::setFrameBuffer (Rgba *base,
  546. size_t xStride,
  547. size_t yStride,
  548. const string &channelNamePrefix)
  549. {
  550. if (_fbBase == 0)
  551. {
  552. FrameBuffer fb;
  553. fb.insert (channelNamePrefix + "Y",
  554. Slice (HALF, // type
  555. (char *) &_buf[0][0].g, // base
  556. sizeof (Rgba), // xStride
  557. sizeof (Rgba) * _tileXSize, // yStride
  558. 1, 1, // sampling
  559. 0.0, // fillValue
  560. true, true)); // tileCoordinates
  561. fb.insert (channelNamePrefix + "A",
  562. Slice (HALF, // type
  563. (char *) &_buf[0][0].a, // base
  564. sizeof (Rgba), // xStride
  565. sizeof (Rgba) * _tileXSize, // yStride
  566. 1, 1, // sampling
  567. 1.0, // fillValue
  568. true, true)); // tileCoordinates
  569. _inputFile.setFrameBuffer (fb);
  570. }
  571. _fbBase = base;
  572. _fbXStride = xStride;
  573. _fbYStride = yStride;
  574. }
  575. void
  576. TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly)
  577. {
  578. if (_fbBase == 0)
  579. {
  580. THROW (IEX_NAMESPACE::ArgExc, "No frame buffer was specified as the "
  581. "pixel data destination for image file "
  582. "\"" << _inputFile.fileName() << "\".");
  583. }
  584. //
  585. // Read the tile requested by the caller into _buf.
  586. //
  587. _inputFile.readTile (dx, dy, lx, ly);
  588. //
  589. // Convert the luminance/alpha pixels to RGBA
  590. // and copy them into the caller's frame buffer.
  591. //
  592. Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly);
  593. int width = dw.max.x - dw.min.x + 1;
  594. for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
  595. {
  596. for (int x1 = 0; x1 < width; ++x1)
  597. {
  598. _buf[y1][x1].r = 0;
  599. _buf[y1][x1].b = 0;
  600. }
  601. YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]);
  602. for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
  603. {
  604. _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1];
  605. }
  606. }
  607. }
  608. TiledRgbaInputFile::TiledRgbaInputFile (const char name[], int numThreads):
  609. _inputFile (new TiledInputFile (name, numThreads)),
  610. _fromYa (0),
  611. _channelNamePrefix ("")
  612. {
  613. if (channels() & WRITE_Y)
  614. _fromYa = new FromYa (*_inputFile);
  615. }
  616. TiledRgbaInputFile::TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads):
  617. _inputFile (new TiledInputFile (is, numThreads)),
  618. _fromYa (0),
  619. _channelNamePrefix ("")
  620. {
  621. if (channels() & WRITE_Y)
  622. _fromYa = new FromYa (*_inputFile);
  623. }
  624. TiledRgbaInputFile::TiledRgbaInputFile (const char name[],
  625. const string &layerName,
  626. int numThreads)
  627. :
  628. _inputFile (new TiledInputFile (name, numThreads)),
  629. _fromYa (0),
  630. _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
  631. {
  632. if (channels() & WRITE_Y)
  633. _fromYa = new FromYa (*_inputFile);
  634. }
  635. TiledRgbaInputFile::TiledRgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
  636. const string &layerName,
  637. int numThreads)
  638. :
  639. _inputFile (new TiledInputFile (is, numThreads)),
  640. _fromYa (0),
  641. _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
  642. {
  643. if (channels() & WRITE_Y)
  644. _fromYa = new FromYa (*_inputFile);
  645. }
  646. TiledRgbaInputFile::~TiledRgbaInputFile ()
  647. {
  648. delete _inputFile;
  649. delete _fromYa;
  650. }
  651. void
  652. TiledRgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
  653. {
  654. if (_fromYa)
  655. {
  656. Lock lock (*_fromYa);
  657. _fromYa->setFrameBuffer (base, xStride, yStride, _channelNamePrefix);
  658. }
  659. else
  660. {
  661. size_t xs = xStride * sizeof (Rgba);
  662. size_t ys = yStride * sizeof (Rgba);
  663. FrameBuffer fb;
  664. fb.insert (_channelNamePrefix + "R",
  665. Slice (HALF,
  666. (char *) &base[0].r,
  667. xs, ys,
  668. 1, 1, // xSampling, ySampling
  669. 0.0)); // fillValue
  670. fb.insert (_channelNamePrefix + "G",
  671. Slice (HALF,
  672. (char *) &base[0].g,
  673. xs, ys,
  674. 1, 1, // xSampling, ySampling
  675. 0.0)); // fillValue
  676. fb.insert (_channelNamePrefix + "B",
  677. Slice (HALF,
  678. (char *) &base[0].b,
  679. xs, ys,
  680. 1, 1, // xSampling, ySampling
  681. 0.0)); // fillValue
  682. fb.insert (_channelNamePrefix + "A",
  683. Slice (HALF,
  684. (char *) &base[0].a,
  685. xs, ys,
  686. 1, 1, // xSampling, ySampling
  687. 1.0)); // fillValue
  688. _inputFile->setFrameBuffer (fb);
  689. }
  690. }
  691. void
  692. TiledRgbaInputFile::setLayerName (const std::string &layerName)
  693. {
  694. delete _fromYa;
  695. _fromYa = 0;
  696. _channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header());
  697. if (channels() & WRITE_Y)
  698. _fromYa = new FromYa (*_inputFile);
  699. FrameBuffer fb;
  700. _inputFile->setFrameBuffer (fb);
  701. }
  702. const Header &
  703. TiledRgbaInputFile::header () const
  704. {
  705. return _inputFile->header();
  706. }
  707. const char *
  708. TiledRgbaInputFile::fileName () const
  709. {
  710. return _inputFile->fileName();
  711. }
  712. const FrameBuffer &
  713. TiledRgbaInputFile::frameBuffer () const
  714. {
  715. return _inputFile->frameBuffer();
  716. }
  717. const IMATH_NAMESPACE::Box2i &
  718. TiledRgbaInputFile::displayWindow () const
  719. {
  720. return _inputFile->header().displayWindow();
  721. }
  722. const IMATH_NAMESPACE::Box2i &
  723. TiledRgbaInputFile::dataWindow () const
  724. {
  725. return _inputFile->header().dataWindow();
  726. }
  727. float
  728. TiledRgbaInputFile::pixelAspectRatio () const
  729. {
  730. return _inputFile->header().pixelAspectRatio();
  731. }
  732. const IMATH_NAMESPACE::V2f
  733. TiledRgbaInputFile::screenWindowCenter () const
  734. {
  735. return _inputFile->header().screenWindowCenter();
  736. }
  737. float
  738. TiledRgbaInputFile::screenWindowWidth () const
  739. {
  740. return _inputFile->header().screenWindowWidth();
  741. }
  742. LineOrder
  743. TiledRgbaInputFile::lineOrder () const
  744. {
  745. return _inputFile->header().lineOrder();
  746. }
  747. Compression
  748. TiledRgbaInputFile::compression () const
  749. {
  750. return _inputFile->header().compression();
  751. }
  752. RgbaChannels
  753. TiledRgbaInputFile::channels () const
  754. {
  755. return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
  756. }
  757. int
  758. TiledRgbaInputFile::version () const
  759. {
  760. return _inputFile->version();
  761. }
  762. bool
  763. TiledRgbaInputFile::isComplete () const
  764. {
  765. return _inputFile->isComplete();
  766. }
  767. unsigned int
  768. TiledRgbaInputFile::tileXSize () const
  769. {
  770. return _inputFile->tileXSize();
  771. }
  772. unsigned int
  773. TiledRgbaInputFile::tileYSize () const
  774. {
  775. return _inputFile->tileYSize();
  776. }
  777. LevelMode
  778. TiledRgbaInputFile::levelMode () const
  779. {
  780. return _inputFile->levelMode();
  781. }
  782. LevelRoundingMode
  783. TiledRgbaInputFile::levelRoundingMode () const
  784. {
  785. return _inputFile->levelRoundingMode();
  786. }
  787. int
  788. TiledRgbaInputFile::numLevels () const
  789. {
  790. return _inputFile->numLevels();
  791. }
  792. int
  793. TiledRgbaInputFile::numXLevels () const
  794. {
  795. return _inputFile->numXLevels();
  796. }
  797. int
  798. TiledRgbaInputFile::numYLevels () const
  799. {
  800. return _inputFile->numYLevels();
  801. }
  802. bool
  803. TiledRgbaInputFile::isValidLevel (int lx, int ly) const
  804. {
  805. return _inputFile->isValidLevel (lx, ly);
  806. }
  807. int
  808. TiledRgbaInputFile::levelWidth (int lx) const
  809. {
  810. return _inputFile->levelWidth (lx);
  811. }
  812. int
  813. TiledRgbaInputFile::levelHeight (int ly) const
  814. {
  815. return _inputFile->levelHeight (ly);
  816. }
  817. int
  818. TiledRgbaInputFile::numXTiles (int lx) const
  819. {
  820. return _inputFile->numXTiles(lx);
  821. }
  822. int
  823. TiledRgbaInputFile::numYTiles (int ly) const
  824. {
  825. return _inputFile->numYTiles(ly);
  826. }
  827. IMATH_NAMESPACE::Box2i
  828. TiledRgbaInputFile::dataWindowForLevel (int l) const
  829. {
  830. return _inputFile->dataWindowForLevel (l);
  831. }
  832. IMATH_NAMESPACE::Box2i
  833. TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const
  834. {
  835. return _inputFile->dataWindowForLevel (lx, ly);
  836. }
  837. IMATH_NAMESPACE::Box2i
  838. TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const
  839. {
  840. return _inputFile->dataWindowForTile (dx, dy, l);
  841. }
  842. IMATH_NAMESPACE::Box2i
  843. TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
  844. {
  845. return _inputFile->dataWindowForTile (dx, dy, lx, ly);
  846. }
  847. void
  848. TiledRgbaInputFile::readTile (int dx, int dy, int l)
  849. {
  850. if (_fromYa)
  851. {
  852. Lock lock (*_fromYa);
  853. _fromYa->readTile (dx, dy, l, l);
  854. }
  855. else
  856. {
  857. _inputFile->readTile (dx, dy, l);
  858. }
  859. }
  860. void
  861. TiledRgbaInputFile::readTile (int dx, int dy, int lx, int ly)
  862. {
  863. if (_fromYa)
  864. {
  865. Lock lock (*_fromYa);
  866. _fromYa->readTile (dx, dy, lx, ly);
  867. }
  868. else
  869. {
  870. _inputFile->readTile (dx, dy, lx, ly);
  871. }
  872. }
  873. void
  874. TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
  875. int lx, int ly)
  876. {
  877. if (_fromYa)
  878. {
  879. Lock lock (*_fromYa);
  880. for (int dy = dyMin; dy <= dyMax; dy++)
  881. for (int dx = dxMin; dx <= dxMax; dx++)
  882. _fromYa->readTile (dx, dy, lx, ly);
  883. }
  884. else
  885. {
  886. _inputFile->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
  887. }
  888. }
  889. void
  890. TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
  891. int l)
  892. {
  893. readTiles (dxMin, dxMax, dyMin, dyMax, l, l);
  894. }
  895. void
  896. TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
  897. {
  898. _outputFile->updatePreviewImage (newPixels);
  899. }
  900. void
  901. TiledRgbaOutputFile::breakTile (int dx, int dy, int lx, int ly,
  902. int offset, int length, char c)
  903. {
  904. _outputFile->breakTile (dx, dy, lx, ly, offset, length, c);
  905. }
  906. OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT