KImgIO
hdr.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "hdr.h"
00012
00013 #include <qimage.h>
00014 #include <qdatastream.h>
00015
00016 #include <kdebug.h>
00017 #include <kglobal.h>
00018
00019 typedef Q_UINT8 uchar;
00020
00021 namespace {
00022
00023 #define MAXLINE 1024
00024 #define MINELEN 8 // minimum scanline length for encoding
00025 #define MAXELEN 0x7fff // maximum scanline length for encoding
00026
00027 static inline uchar ClipToByte(float value)
00028 {
00029 if (value > 255.0f) return 255;
00030
00031 return uchar(value);
00032 }
00033
00034
00035
00036 static bool Read_Old_Line (uchar * image, int width, QDataStream & s)
00037 {
00038 int rshift = 0;
00039 int i;
00040
00041 while (width > 0)
00042 {
00043 s >> image[0];
00044 s >> image[1];
00045 s >> image[2];
00046 s >> image[3];
00047
00048 if (s.atEnd()) return false;
00049
00050 if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1))
00051 {
00052 for (i = image[3] << rshift; i > 0; i--)
00053 {
00054
00055 (uint &)image[0] = (uint &)image[0-4];
00056 image += 4;
00057 width--;
00058 }
00059 rshift += 8;
00060 }
00061 else
00062 {
00063 image += 4;
00064 width--;
00065 rshift = 0;
00066 }
00067 }
00068 return true;
00069 }
00070
00071
00072 static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
00073 {
00074 for (int j = 0; j < width; j++)
00075 {
00076
00077 float v;
00078 int e = int(image[3]) - 128;
00079 if( e > 0 )
00080 {
00081 v = float(1 << e);
00082 }
00083 else
00084 {
00085 v = 1.0f / float(1 << -e);
00086 }
00087
00088 scanline[j] = qRgb( ClipToByte(float(image[0]) * v),
00089 ClipToByte(float(image[1]) * v),
00090 ClipToByte(float(image[2]) * v) );
00091
00092 image += 4;
00093 }
00094 }
00095
00096
00097 static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
00098 {
00099 uchar val, code;
00100
00101
00102 if( !img.create( width, height, 32 ) )
00103 {
00104 return false;
00105 }
00106
00107 QMemArray<uchar> image( width * 4 );
00108
00109 for (int cline = 0; cline < height; cline++)
00110 {
00111 QRgb * scanline = (QRgb *) img.scanLine( cline );
00112
00113
00114 if ((width < MINELEN) || (MAXELEN < width))
00115 {
00116 Read_Old_Line(image.data(), width, s);
00117 RGBE_To_QRgbLine(image.data(), scanline, width);
00118 continue;
00119 }
00120
00121 s >> val;
00122
00123 if (s.atEnd())
00124 {
00125 return true;
00126 }
00127
00128 if (val != 2)
00129 {
00130 s.device()->at( s.device()->at() - 1 );
00131 Read_Old_Line(image.data(), width, s);
00132 RGBE_To_QRgbLine(image.data(), scanline, width);
00133 continue;
00134 }
00135
00136 s >> image[1];
00137 s >> image[2];
00138 s >> image[3];
00139
00140 if (s.atEnd())
00141 {
00142 return true;
00143 }
00144
00145 if ((image[1] != 2) || (image[2] & 128))
00146 {
00147 image[0] = 2;
00148 Read_Old_Line(image.data()+4, width-1, s);
00149 RGBE_To_QRgbLine(image.data(), scanline, width);
00150 continue;
00151 }
00152
00153 if ((image[2] << 8 | image[3]) != width)
00154 {
00155 return false;
00156 }
00157
00158
00159 for (int i = 0; i < 4; i++)
00160 {
00161 for (int j = 0; j < width; )
00162 {
00163 s >> code;
00164 if (s.atEnd())
00165 {
00166 return false;
00167 }
00168 if (code > 128)
00169 {
00170
00171 code &= 127;
00172 s >> val;
00173 while( code != 0 )
00174 {
00175 image[i + j * 4] = val;
00176 j++;
00177 code--;
00178 }
00179 }
00180 else
00181 {
00182
00183 while( code != 0 )
00184 {
00185 s >> image[i + j * 4];
00186 j++;
00187 code--;
00188 }
00189 }
00190 }
00191 }
00192
00193 RGBE_To_QRgbLine(image.data(), scanline, width);
00194 }
00195
00196 return true;
00197 }
00198
00199 }
00200
00201
00202 KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
00203 {
00204 int len;
00205 char line[MAXLINE];
00206
00207 bool validFormat = false;
00208
00209
00210 do {
00211 len = io->ioDevice()->readLine(line, MAXLINE);
00212
00213
00214
00215
00216
00217 if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
00218 {
00219 validFormat = true;
00220 }
00221
00222 } while((len > 0) && (line[0] != '\n'));
00223
00224 if( !validFormat )
00225 {
00226 kdDebug(399) << "Unknown HDR format." << endl;
00227 io->setImage( 0 );
00228 io->setStatus( -1 );
00229 return;
00230 }
00231
00232 io->ioDevice()->readLine(line, MAXLINE);
00233
00234 char s1[3], s2[3];
00235 int width, height;
00236 if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
00237
00238 {
00239 kdDebug(399) << "Invalid HDR file." << endl;
00240 io->setImage( 0 );
00241 io->setStatus( -1 );
00242 return;
00243 }
00244
00245 QDataStream s( io->ioDevice() );
00246
00247 QImage img;
00248 if( !LoadHDR(s, width, height, img) )
00249 {
00250 kdDebug(399) << "Error loading HDR file." << endl;
00251 io->setImage( 0 );
00252 io->setStatus( -1 );
00253 return;
00254 }
00255
00256 io->setImage( img );
00257 io->setStatus( 0 );
00258 }
00259
00260
00261 KDE_EXPORT void kimgio_hdr_write( QImageIO * )
00262 {
00263
00264 }
00265