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

KImgIO

exr.cpp

Go to the documentation of this file.
00001 // -*- C++;indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
00002 
00011 #include "exr.h"
00012 
00013 #include <config.h>
00014 
00015 #include <ImfRgbaFile.h>
00016 #include <ImfStandardAttributes.h>
00017 #include <ImathBox.h>
00018 #include <ImfInputFile.h>
00019 #include <ImfBoxAttribute.h>
00020 #include <ImfChannelListAttribute.h>
00021 #include <ImfCompressionAttribute.h>
00022 #include <ImfFloatAttribute.h>
00023 #include <ImfIntAttribute.h>
00024 #include <ImfLineOrderAttribute.h>
00025 #include <ImfStringAttribute.h>
00026 #include <ImfVecAttribute.h>
00027 #include <ImfArray.h>
00028 #include <ImfConvert.h>
00029 #include <ImfVersion.h>
00030 #include <IexThrowErrnoExc.h>
00031 
00032 #include <iostream>
00033 
00034 #include <kdebug.h>
00035 
00036 
00037 #include <QImage>
00038 #include <QDataStream>
00039 #include <QImageIOPlugin>
00040 
00041 class K_IStream: public Imf::IStream
00042 {
00043 public:
00044     K_IStream( QIODevice *dev, const QByteArray& fileName ):
00045         IStream( fileName.data() ), m_dev ( dev )
00046     {}
00047 
00048     virtual bool  read( char c[], int n );
00049     virtual Imf::Int64 tellg( );
00050     virtual void seekg( Imf::Int64 pos );
00051     virtual void clear( );
00052 
00053 private:
00054     QIODevice *m_dev;
00055 };
00056 
00057 bool K_IStream::read( char c[], int n )
00058 {
00059     qint64 result = m_dev->read( c, n );
00060     if ( result > 0 ) {
00061         return true;
00062     } else if ( result == 0 ) {
00063         throw Iex::InputExc( "Unexpected end of file" );
00064     } else // negative value {
00065         Iex::throwErrnoExc( "Error in read", result );
00066     return false;
00067 }
00068 
00069 Imf::Int64 K_IStream::tellg( )
00070 {
00071     return m_dev->pos();
00072 }
00073 
00074 void K_IStream::seekg( Imf::Int64 pos )
00075 {
00076     m_dev->seek( pos );
00077 }
00078 
00079 void K_IStream::clear( )
00080 {
00081     // TODO
00082 }
00083 
00084 /* this does a conversion from the ILM Half (equal to Nvidia Half)
00085  * format into the normal 32 bit pixel format. Process is from the
00086  * ILM code.
00087  */
00088 QRgb RgbaToQrgba(struct Imf::Rgba imagePixel)
00089 {
00090     float r,g,b,a;
00091 
00092     //  1) Compensate for fogging by subtracting defog
00093     //     from the raw pixel values.
00094     // Response: We work with defog of 0.0, so this is a no-op
00095 
00096     //  2) Multiply the defogged pixel values by
00097     //     2^(exposure + 2.47393).
00098     // Response: We work with exposure of 0.0.
00099     // (2^2.47393) is 5.55555
00100     r = imagePixel.r * 5.55555;
00101     g = imagePixel.g * 5.55555;
00102     b = imagePixel.b * 5.55555;
00103     a = imagePixel.a * 5.55555;
00104 
00105     //  3) Values, which are now 1.0, are called "middle gray".
00106     //     If defog and exposure are both set to 0.0, then
00107     //     middle gray corresponds to a raw pixel value of 0.18.
00108     //     In step 6, middle gray values will be mapped to an
00109     //     intensity 3.5 f-stops below the display's maximum
00110     //     intensity.
00111     // Response: no apparent content.
00112 
00113     //  4) Apply a knee function.  The knee function has two
00114     //     parameters, kneeLow and kneeHigh.  Pixel values
00115     //     below 2^kneeLow are not changed by the knee
00116     //     function.  Pixel values above kneeLow are lowered
00117     //     according to a logarithmic curve, such that the
00118     //     value 2^kneeHigh is mapped to 2^3.5 (in step 6,
00119     //     this value will be mapped to the display's
00120     //     maximum intensity).
00121     // Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
00122     if (r > 1.0)
00123         r = 1.0 + Imath::Math<float>::log ((r-1.0) * 0.184874 + 1) / 0.184874;
00124     if (g > 1.0)
00125         g = 1.0 + Imath::Math<float>::log ((g-1.0) * 0.184874 + 1) / 0.184874;
00126     if (b > 1.0)
00127         b = 1.0 + Imath::Math<float>::log ((b-1.0) * 0.184874 + 1) / 0.184874;
00128     if (a > 1.0)
00129         a = 1.0 + Imath::Math<float>::log ((a-1.0) * 0.184874 + 1) / 0.184874;
00130 //
00131 //  5) Gamma-correct the pixel values, assuming that the
00132 //     screen's gamma is 0.4545 (or 1/2.2).
00133     r = Imath::Math<float>::pow (r, 0.4545);
00134     g = Imath::Math<float>::pow (g, 0.4545);
00135     b = Imath::Math<float>::pow (b, 0.4545);
00136     a = Imath::Math<float>::pow (a, 0.4545);
00137 
00138 //  6) Scale the values such that pixels middle gray
00139 //     pixels are mapped to 84.66 (or 3.5 f-stops below
00140 //     the display's maximum intensity).
00141 //
00142 //  7) Clamp the values to [0, 255].
00143     return qRgba( char (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ),
00144                   char (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ),
00145                   char (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ),
00146                   char (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) );
00147 }
00148 
00149 EXRHandler::EXRHandler()
00150 {
00151 }
00152 
00153 bool EXRHandler::canRead() const
00154 {
00155     if (canRead(device())) {
00156         setFormat("exr");
00157         return true;
00158     }
00159     return false;
00160 }
00161 
00162 QByteArray EXRHandler::name() const
00163 {
00164     // TODO
00165     return QByteArray("exr");
00166 }
00167 
00168 bool EXRHandler::read( QImage *outImage )
00169 {
00170     try
00171     {
00172         int width, height;
00173 
00174         K_IStream istr( device(), QByteArray() );
00175         Imf::RgbaInputFile file( istr );
00176         Imath::Box2i dw = file.dataWindow();
00177 
00178         width  = dw.max.x - dw.min.x + 1;
00179         height = dw.max.y - dw.min.y + 1;
00180 
00181         Imf::Array2D<Imf::Rgba> pixels;
00182         pixels.resizeErase (height, width);
00183 
00184         file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
00185         file.readPixels (dw.min.y, dw.max.y);
00186 
00187         QImage image(width, height, QImage::Format_RGB32);
00188         if( image.isNull())
00189             return false;
00190 
00191         // somehow copy pixels into image
00192         for ( int y=0; y < height; y++ ) {
00193             for ( int x=0; x < width; x++ ) {
00194                 // copy pixels(x,y) into image(x,y)
00195                 image.setPixel( x, y, RgbaToQrgba( pixels[y][x] ) );
00196             }
00197         }
00198 
00199         *outImage = image;
00200 
00201         return true;
00202     }
00203     catch (const std::exception &exc)
00204     {
00205         kDebug() << exc.what();
00206         return false;
00207     }
00208 }
00209 
00210 
00211 bool EXRHandler::write( const QImage &image )
00212 {
00213     // TODO: stub
00214     Q_UNUSED( image );
00215     return false;
00216 }
00217 
00218 
00219 bool EXRHandler::canRead(QIODevice *device)
00220 {
00221     if (!device) {
00222         qWarning("EXRHandler::canRead() called with no device");
00223         return false;
00224     }
00225 
00226     qint64 oldPos = device->pos();
00227 
00228     const QByteArray head = device->readLine(4);
00229     int readBytes = head.size();
00230     if (device->isSequential()) {
00231         while (readBytes > 0)
00232             device->ungetChar(head[readBytes-- - 1]);
00233     } else {
00234         device->seek(oldPos);
00235     }
00236 
00237     return Imf::isImfMagic( head.data() );
00238 }
00239 
00240 
00241 /* --- Plugin --- */
00242 
00243 QStringList EXRPlugin::keys() const
00244 {
00245     return QStringList() << "exr" << "EXR";
00246 }
00247 
00248 
00249 QImageIOPlugin::Capabilities EXRPlugin::capabilities(QIODevice *device, const QByteArray &format) const
00250 {
00251     if ( format == "exr" || format == "EXR" )
00252         return Capabilities(CanRead);
00253     if ( !format.isEmpty() )
00254         return 0;
00255     if ( !device->isOpen() )
00256         return 0;
00257 
00258     Capabilities cap;
00259     if (device->isReadable() && EXRHandler::canRead(device))
00260         cap |= CanRead;
00261     return cap;
00262 }
00263 
00264 QImageIOHandler *EXRPlugin::create(QIODevice *device, const QByteArray &format) const
00265 {
00266     QImageIOHandler *handler = new EXRHandler;
00267     handler->setDevice(device);
00268     handler->setFormat(format);
00269     return handler;
00270 }
00271 
00272 Q_EXPORT_STATIC_PLUGIN( EXRPlugin )
00273 Q_EXPORT_PLUGIN2( exr, EXRPlugin )

KImgIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal