KImgIO
exr.cpp
Go to the documentation of this file.00001
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
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
00082 }
00083
00084
00085
00086
00087
00088 QRgb RgbaToQrgba(struct Imf::Rgba imagePixel)
00089 {
00090 float r,g,b,a;
00091
00092
00093
00094
00095
00096
00097
00098
00099
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
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
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
00132
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
00139
00140
00141
00142
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
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
00192 for ( int y=0; y < height; y++ ) {
00193 for ( int x=0; x < width; x++ ) {
00194
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
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
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 )