• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KImgIO

  • sources
  • kde-4.14
  • kdelibs
  • kimgio
exr.cpp
Go to the documentation of this file.
1 // -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
2 
11 #include "exr.h"
12 
13 #include <config.h>
14 
15 #include <ImfRgbaFile.h>
16 #include <ImfStandardAttributes.h>
17 #include <ImathBox.h>
18 #include <ImfInputFile.h>
19 #include <ImfBoxAttribute.h>
20 #include <ImfChannelListAttribute.h>
21 #include <ImfCompressionAttribute.h>
22 #include <ImfFloatAttribute.h>
23 #include <ImfIntAttribute.h>
24 #include <ImfLineOrderAttribute.h>
25 #include <ImfStringAttribute.h>
26 #include <ImfVecAttribute.h>
27 #include <ImfArray.h>
28 #include <ImfConvert.h>
29 #include <ImfVersion.h>
30 #include <IexThrowErrnoExc.h>
31 
32 #include <iostream>
33 
34 #include <kdebug.h>
35 
36 
37 #include <QImage>
38 #include <QDataStream>
39 #include <QImageIOPlugin>
40 
41 class K_IStream: public Imf::IStream
42 {
43 public:
44  K_IStream( QIODevice *dev, const QByteArray& fileName ):
45  IStream( fileName.data() ), m_dev ( dev )
46  {}
47 
48  virtual bool read( char c[], int n );
49  virtual Imf::Int64 tellg( );
50  virtual void seekg( Imf::Int64 pos );
51  virtual void clear( );
52 
53 private:
54  QIODevice *m_dev;
55 };
56 
57 bool K_IStream::read( char c[], int n )
58 {
59  qint64 result = m_dev->read( c, n );
60  if ( result > 0 ) {
61  return true;
62  } else if ( result == 0 ) {
63  throw Iex::InputExc( "Unexpected end of file" );
64  } else // negative value {
65  Iex::throwErrnoExc( "Error in read", result );
66  return false;
67 }
68 
69 Imf::Int64 K_IStream::tellg( )
70 {
71  return m_dev->pos();
72 }
73 
74 void K_IStream::seekg( Imf::Int64 pos )
75 {
76  m_dev->seek( pos );
77 }
78 
79 void K_IStream::clear( )
80 {
81  // TODO
82 }
83 
84 /* this does a conversion from the ILM Half (equal to Nvidia Half)
85  * format into the normal 32 bit pixel format. Process is from the
86  * ILM code.
87  */
88 QRgb RgbaToQrgba(struct Imf::Rgba imagePixel)
89 {
90  float r,g,b,a;
91 
92  // 1) Compensate for fogging by subtracting defog
93  // from the raw pixel values.
94  // Response: We work with defog of 0.0, so this is a no-op
95 
96  // 2) Multiply the defogged pixel values by
97  // 2^(exposure + 2.47393).
98  // Response: We work with exposure of 0.0.
99  // (2^2.47393) is 5.55555
100  r = imagePixel.r * 5.55555;
101  g = imagePixel.g * 5.55555;
102  b = imagePixel.b * 5.55555;
103  a = imagePixel.a * 5.55555;
104 
105  // 3) Values, which are now 1.0, are called "middle gray".
106  // If defog and exposure are both set to 0.0, then
107  // middle gray corresponds to a raw pixel value of 0.18.
108  // In step 6, middle gray values will be mapped to an
109  // intensity 3.5 f-stops below the display's maximum
110  // intensity.
111  // Response: no apparent content.
112 
113  // 4) Apply a knee function. The knee function has two
114  // parameters, kneeLow and kneeHigh. Pixel values
115  // below 2^kneeLow are not changed by the knee
116  // function. Pixel values above kneeLow are lowered
117  // according to a logarithmic curve, such that the
118  // value 2^kneeHigh is mapped to 2^3.5 (in step 6,
119  // this value will be mapped to the display's
120  // maximum intensity).
121  // Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
122  if (r > 1.0)
123  r = 1.0 + Imath::Math<float>::log ((r-1.0) * 0.184874 + 1) / 0.184874;
124  if (g > 1.0)
125  g = 1.0 + Imath::Math<float>::log ((g-1.0) * 0.184874 + 1) / 0.184874;
126  if (b > 1.0)
127  b = 1.0 + Imath::Math<float>::log ((b-1.0) * 0.184874 + 1) / 0.184874;
128  if (a > 1.0)
129  a = 1.0 + Imath::Math<float>::log ((a-1.0) * 0.184874 + 1) / 0.184874;
130 //
131 // 5) Gamma-correct the pixel values, assuming that the
132 // screen's gamma is 0.4545 (or 1/2.2).
133  r = Imath::Math<float>::pow (r, 0.4545);
134  g = Imath::Math<float>::pow (g, 0.4545);
135  b = Imath::Math<float>::pow (b, 0.4545);
136  a = Imath::Math<float>::pow (a, 0.4545);
137 
138 // 6) Scale the values such that pixels middle gray
139 // pixels are mapped to 84.66 (or 3.5 f-stops below
140 // the display's maximum intensity).
141 //
142 // 7) Clamp the values to [0, 255].
143  return qRgba( (unsigned char) (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ),
144  (unsigned char) (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ),
145  (unsigned char) (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ),
146  (unsigned char) (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) );
147 }
148 
149 EXRHandler::EXRHandler()
150 {
151 }
152 
153 bool EXRHandler::canRead() const
154 {
155  if (canRead(device())) {
156  setFormat("exr");
157  return true;
158  }
159  return false;
160 }
161 
162 QByteArray EXRHandler::name() const
163 {
164  // TODO
165  return QByteArray("exr");
166 }
167 
168 bool EXRHandler::read( QImage *outImage )
169 {
170  try
171  {
172  int width, height;
173 
174  K_IStream istr( device(), QByteArray() );
175  Imf::RgbaInputFile file( istr );
176  Imath::Box2i dw = file.dataWindow();
177 
178  width = dw.max.x - dw.min.x + 1;
179  height = dw.max.y - dw.min.y + 1;
180 
181  Imf::Array2D<Imf::Rgba> pixels;
182  pixels.resizeErase (height, width);
183 
184  file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
185  file.readPixels (dw.min.y, dw.max.y);
186 
187  QImage image(width, height, QImage::Format_RGB32);
188  if( image.isNull())
189  return false;
190 
191  // somehow copy pixels into image
192  for ( int y=0; y < height; y++ ) {
193  for ( int x=0; x < width; x++ ) {
194  // copy pixels(x,y) into image(x,y)
195  image.setPixel( x, y, RgbaToQrgba( pixels[y][x] ) );
196  }
197  }
198 
199  *outImage = image;
200 
201  return true;
202  }
203  catch (const std::exception &exc)
204  {
205  kDebug() << exc.what();
206  return false;
207  }
208 }
209 
210 
211 bool EXRHandler::write( const QImage &image )
212 {
213  // TODO: stub
214  Q_UNUSED( image );
215  return false;
216 }
217 
218 
219 bool EXRHandler::canRead(QIODevice *device)
220 {
221  if (!device) {
222  qWarning("EXRHandler::canRead() called with no device");
223  return false;
224  }
225 
226  const QByteArray head = device->peek(4);
227 
228  return Imf::isImfMagic( head.data() );
229 }
230 
231 
232 /* --- Plugin --- */
233 
234 QStringList EXRPlugin::keys() const
235 {
236  return QStringList() << "exr" << "EXR";
237 }
238 
239 
240 QImageIOPlugin::Capabilities EXRPlugin::capabilities(QIODevice *device, const QByteArray &format) const
241 {
242  if ( format == "exr" || format == "EXR" )
243  return Capabilities(CanRead);
244  if ( !format.isEmpty() )
245  return 0;
246  if ( !device->isOpen() )
247  return 0;
248 
249  Capabilities cap;
250  if (device->isReadable() && EXRHandler::canRead(device))
251  cap |= CanRead;
252  return cap;
253 }
254 
255 QImageIOHandler *EXRPlugin::create(QIODevice *device, const QByteArray &format) const
256 {
257  QImageIOHandler *handler = new EXRHandler;
258  handler->setDevice(device);
259  handler->setFormat(format);
260  return handler;
261 }
262 
263 Q_EXPORT_STATIC_PLUGIN( EXRPlugin )
264 Q_EXPORT_PLUGIN2( exr, EXRPlugin )
QIODevice
QImageIOPlugin::Capabilities
typedef Capabilities
RgbaToQrgba
QRgb RgbaToQrgba(struct Imf::Rgba imagePixel)
Definition: exr.cpp:88
QImageIOHandler::device
QIODevice * device() const
exr.h
QByteArray
QImage::setPixel
void setPixel(int x, int y, uint index_or_rgb)
QByteArray::isEmpty
bool isEmpty() const
EXRHandler::read
bool read(QImage *outImage)
Read contents from the file / stream into an image.
Definition: exr.cpp:168
QImage::isNull
bool isNull() const
EXRHandler
QImageIO Routines to read (and perhaps in the future, write) images in the high definition EXR format...
Definition: exr.h:16
QIODevice::isReadable
bool isReadable() const
QIODevice::peek
qint64 peek(char *data, qint64 maxSize)
EXRHandler::write
bool write(const QImage &image)
Write the contents of an image into the file / stream.
Definition: exr.cpp:211
QImageIOHandler::setDevice
void setDevice(QIODevice *device)
QIODevice::read
qint64 read(char *data, qint64 maxSize)
QIODevice::isOpen
bool isOpen() const
EXRHandler::canRead
bool canRead() const
Test if the file / stream can potentially read more data.
Definition: exr.cpp:153
QStringList
QImageIOHandler
QImage
EXRHandler::EXRHandler
EXRHandler()
Definition: exr.cpp:149
qRgba
QRgb qRgba(const QRgb &rgb, int a)
Change a QRgb value's alpha only.
Definition: xcf.cpp:67
QByteArray::data
char * data()
EXRHandler::name
QByteArray name() const
The name of this plugin.
Definition: exr.cpp:162
QImageIOHandler::setFormat
void setFormat(const QByteArray &format)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KImgIO

Skip menu "KImgIO"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal