1 /* This file is part of the KDE project
2 Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
3 Copyright (C) 2005 Ignacio CastaƱo <castanyo@yahoo.es>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the Lesser GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
13 #include <QtGui/QImage>
14 #include <QtCore/QDataStream>
19 typedef Q_UINT8 uchar
;
21 namespace { // Private.
24 #define MINELEN 8 // minimum scanline length for encoding
25 #define MAXELEN 0x7fff // maximum scanline length for encoding
27 static inline uchar
ClipToByte(float value
)
29 if (value
> 255.0f
) return 255;
30 //else if (value < 0.0f) return 0; // we know value is positive.
34 // read an old style line from the hdr image file
35 // if 'first' is true the first byte is already read
36 static bool Read_Old_Line (uchar
* image
, int width
, QDataStream
& s
)
48 if (s
.atEnd()) return false;
50 if ((image
[0] == 1) && (image
[1] == 1) && (image
[2] == 1))
52 for (i
= image
[3] << rshift
; i
> 0; i
--)
54 //memcpy(image, image-4, 4);
55 (uint
&)image
[0] = (uint
&)image
[0-4];
72 static void RGBE_To_QRgbLine(uchar
* image
, QRgb
* scanline
, int width
)
74 for (int j
= 0; j
< width
; j
++)
76 // v = ldexp(1.0, int(image[3]) - 128);
78 int e
= int(image
[3]) - 128;
85 v
= 1.0f
/ float(1 << -e
);
88 scanline
[j
] = qRgb( ClipToByte(float(image
[0]) * v
),
89 ClipToByte(float(image
[1]) * v
),
90 ClipToByte(float(image
[2]) * v
) );
96 // Load the HDR image.
97 static bool LoadHDR( QDataStream
& s
, const int width
, const int height
, QImage
& img
)
102 if( !img
.create( width
, height
, 32 ) )
107 QMemArray
<uchar
> image( width
* 4 );
109 for (int cline
= 0; cline
< height
; cline
++)
111 QRgb
* scanline
= (QRgb
*) img
.scanLine( cline
);
113 // determine scanline type
114 if ((width
< MINELEN
) || (MAXELEN
< width
))
116 Read_Old_Line(image
.data(), width
, s
);
117 RGBE_To_QRgbLine(image
.data(), scanline
, width
);
130 s
.device()->at( s
.device()->at() - 1 );
131 Read_Old_Line(image
.data(), width
, s
);
132 RGBE_To_QRgbLine(image
.data(), scanline
, width
);
145 if ((image
[1] != 2) || (image
[2] & 128))
148 Read_Old_Line(image
.data()+4, width
-1, s
);
149 RGBE_To_QRgbLine(image
.data(), scanline
, width
);
153 if ((image
[2] << 8 | image
[3]) != width
)
158 // read each component
159 for (int i
= 0; i
< 4; i
++)
161 for (int j
= 0; j
< width
; )
175 image
[i
+ j
* 4] = val
;
185 s
>> image
[i
+ j
* 4];
193 RGBE_To_QRgbLine(image
.data(), scanline
, width
);
202 KDE_EXPORT
void kimgio_hdr_read( QImageIO
* io
)
206 //bool validHeader = false;
207 bool validFormat
= false;
211 len
= io
->ioDevice()->readLine(line
, MAXLINE
);
213 /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
217 if (strcmp(line
, "FORMAT=32-bit_rle_rgbe\n") == 0)
222 } while((len
> 0) && (line
[0] != '\n'));
224 if( /*!validHeader ||*/ !validFormat
)
226 kDebug(399) << "Unknown HDR format.";
232 io
->ioDevice()->readLine(line
, MAXLINE
);
236 if (sscanf(line
, "%2[+-XY] %d %2[+-XY] %d\n", s1
, &height
, s2
, &width
) != 4)
237 //if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
239 kDebug(399) << "Invalid HDR file.";
245 QDataStream
s( io
->ioDevice() );
248 if( !LoadHDR(s
, width
, height
, img
) )
250 kDebug(399) << "Error loading HDR file.";
261 KDE_EXPORT
void kimgio_hdr_write( QImageIO
* )
263 // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)