TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

exr.cpp 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
  2. /**
  3. * KImageIO Routines to read (and perhaps in the future, write) images
  4. * in the high dynamic range EXR format.
  5. * Copyright (c) 2003, Brad Hards <bradh@frogmouth.net>
  6. *
  7. * This library is distributed under the conditions of the GNU LGPL.
  8. *
  9. * $Id$
  10. */
  11. #include "config.h"
  12. #ifdef HAVE_EXR
  13. #include <ImfRgbaFile.h>
  14. #include <ImfStandardAttributes.h>
  15. #include <ImathBox.h>
  16. #include <ImfInputFile.h>
  17. #include <ImfBoxAttribute.h>
  18. #include <ImfChannelListAttribute.h>
  19. #include <ImfCompressionAttribute.h>
  20. #include <ImfFloatAttribute.h>
  21. #include <ImfIntAttribute.h>
  22. #include <ImfLineOrderAttribute.h>
  23. #include <ImfStringAttribute.h>
  24. #include <ImfVecAttribute.h>
  25. #include <ImfArray.h>
  26. #include <ImfConvert.h>
  27. #include <iostream>
  28. #include <stdlib.h>
  29. #include <kurl.h>
  30. #include <kprocess.h>
  31. #include <tdelocale.h>
  32. #include <kgenericfactory.h>
  33. #include <kdebug.h>
  34. #include <tqimage.h>
  35. #include <tqcstring.h>
  36. #include <tqfile.h>
  37. #include <tqdatetime.h>
  38. #include <tqdict.h>
  39. #include <tqvalidator.h>
  40. #include <tqcolor.h>
  41. #include "exr.h"
  42. using namespace Imf;
  43. /* this does a conversion from the ILM Half (equal to Nvidia Half)
  44. * format into the normal 32 bit pixel format. Process is from the
  45. * ILM code.
  46. */
  47. QRgb RgbaToQrgba(struct Rgba imagePixel)
  48. {
  49. float r,g,b,a;
  50. // 1) Compensate for fogging by subtracting defog
  51. // from the raw pixel values.
  52. // Response: We work with defog of 0.0, so this is a no-op
  53. // 2) Multiply the defogged pixel values by
  54. // 2^(exposure + 2.47393).
  55. // Response: We work with exposure of 0.0.
  56. // (2^2.47393) is 5.55555
  57. r = imagePixel.r * 5.55555;
  58. g = imagePixel.g * 5.55555;
  59. b = imagePixel.b * 5.55555;
  60. a = imagePixel.a * 5.55555;
  61. // 3) Values, which are now 1.0, are called "middle gray".
  62. // If defog and exposure are both set to 0.0, then
  63. // middle gray corresponds to a raw pixel value of 0.18.
  64. // In step 6, middle gray values will be mapped to an
  65. // intensity 3.5 f-stops below the display's maximum
  66. // intensity.
  67. // Response: no apparent content.
  68. // 4) Apply a knee function. The knee function has two
  69. // parameters, kneeLow and kneeHigh. Pixel values
  70. // below 2^kneeLow are not changed by the knee
  71. // function. Pixel values above kneeLow are lowered
  72. // according to a logarithmic curve, such that the
  73. // value 2^kneeHigh is mapped to 2^3.5 (in step 6,
  74. // this value will be mapped to the the display's
  75. // maximum intensity).
  76. // Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
  77. if (r > 1.0)
  78. r = 1.0 + Imath::Math<float>::log ((r-1.0) * 0.184874 + 1) / 0.184874;
  79. if (g > 1.0)
  80. g = 1.0 + Imath::Math<float>::log ((g-1.0) * 0.184874 + 1) / 0.184874;
  81. if (b > 1.0)
  82. b = 1.0 + Imath::Math<float>::log ((b-1.0) * 0.184874 + 1) / 0.184874;
  83. if (a > 1.0)
  84. a = 1.0 + Imath::Math<float>::log ((a-1.0) * 0.184874 + 1) / 0.184874;
  85. //
  86. // 5) Gamma-correct the pixel values, assuming that the
  87. // screen's gamma is 0.4545 (or 1/2.2).
  88. r = Imath::Math<float>::pow (r, 0.4545);
  89. g = Imath::Math<float>::pow (g, 0.4545);
  90. b = Imath::Math<float>::pow (b, 0.4545);
  91. a = Imath::Math<float>::pow (a, 0.4545);
  92. // 6) Scale the values such that pixels middle gray
  93. // pixels are mapped to 84.66 (or 3.5 f-stops below
  94. // the display's maximum intensity).
  95. //
  96. // 7) Clamp the values to [0, 255].
  97. return tqRgba( char (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ),
  98. char (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ),
  99. char (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ),
  100. char (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) );
  101. }
  102. KDE_EXPORT void kimgio_exr_read( TQImageIO *io )
  103. {
  104. try
  105. {
  106. int width, height;
  107. // This won't work if io is not TQFile !
  108. RgbaInputFile file (TQFile::encodeName(io->fileName()));
  109. Imath::Box2i dw = file.dataWindow();
  110. width = dw.max.x - dw.min.x + 1;
  111. height = dw.max.y - dw.min.y + 1;
  112. Array2D<Rgba> pixels;
  113. pixels.resizeErase (height, width);
  114. file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
  115. file.readPixels (dw.min.y, dw.max.y);
  116. TQImage image(width, height, 32, 0, TQImage::BigEndian);
  117. if( image.isNull())
  118. return;
  119. // somehow copy pixels into image
  120. for ( int y=0; y < height; y++ ) {
  121. for ( int x=0; x < width; x++ ) {
  122. // copy pixels(x,y) into image(x,y)
  123. image.setPixel( x, y, RgbaToQrgba( pixels[y][x] ) );
  124. }
  125. }
  126. io->setImage( image );
  127. io->setStatus( 0 );
  128. }
  129. catch (const std::exception &exc)
  130. {
  131. kdDebug(399) << exc.what() << endl;
  132. return;
  133. }
  134. }
  135. KDE_EXPORT void kimgio_exr_write(TQImageIO *)
  136. {
  137. // TODO: stub
  138. }
  139. #endif