Warning: That file was not part of the compilation database. It may have many parsing errors.

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>
4
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.
9*/
10
11#include "hdr.h"
12
13#include <QtGui/QImage>
14#include <QtCore/QDataStream>
15
16#include <kdebug.h>
17
18typedef Q_UINT8 uchar;
19
20namespace { // Private.
21
22#define MAXLINE 1024
23#define MINELEN 8 // minimum scanline length for encoding
24#define MAXELEN 0x7fff // maximum scanline length for encoding
25
26 static inline uchar ClipToByte(float value)
27 {
28 if (value > 255.0f) return 255;
29 //else if (value < 0.0f) return 0; // we know value is positive.
30 return uchar(value);
31 }
32
33 // read an old style line from the hdr image file
34 // if 'first' is true the first byte is already read
35 static bool Read_Old_Line (uchar * image, int width, QDataStream & s)
36 {
37 int rshift = 0;
38 int i;
39
40 while (width > 0)
41 {
42 s >> image[0];
43 s >> image[1];
44 s >> image[2];
45 s >> image[3];
46
47 if (s.atEnd()) return false;
48
49 if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1))
50 {
51 for (i = image[3] << rshift; i > 0; i--)
52 {
53 //memcpy(image, image-4, 4);
54 (uint &)image[0] = (uint &)image[0-4];
55 image += 4;
56 width--;
57 }
58 rshift += 8;
59 }
60 else
61 {
62 image += 4;
63 width--;
64 rshift = 0;
65 }
66 }
67 return true;
68 }
69
70
71 static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
72 {
73 for (int j = 0; j < width; j++)
74 {
75 // v = ldexp(1.0, int(image[3]) - 128);
76 float v;
77 int e = int(image[3]) - 128;
78 if( e > 0 )
79 {
80 v = float(1 << e);
81 }
82 else
83 {
84 v = 1.0f / float(1 << -e);
85 }
86
87 scanline[j] = qRgb( ClipToByte(float(image[0]) * v),
88 ClipToByte(float(image[1]) * v),
89 ClipToByte(float(image[2]) * v) );
90
91 image += 4;
92 }
93 }
94
95 // Load the HDR image.
96 static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
97 {
98 uchar val, code;
99
100 // Create dst image.
101 if( !img.create( width, height, 32 ) )
102 {
103 return false;
104 }
105
106 QMemArray<uchar> image( width * 4 );
107
108 for (int cline = 0; cline < height; cline++)
109 {
110 QRgb * scanline = (QRgb *) img.scanLine( cline );
111
112 // determine scanline type
113 if ((width < MINELEN) || (MAXELEN < width))
114 {
115 Read_Old_Line(image.data(), width, s);
116 RGBE_To_QRgbLine(image.data(), scanline, width);
117 continue;
118 }
119
120 s >> val;
121
122 if (s.atEnd())
123 {
124 return true;
125 }
126
127 if (val != 2)
128 {
129 s.device()->at( s.device()->at() - 1 );
130 Read_Old_Line(image.data(), width, s);
131 RGBE_To_QRgbLine(image.data(), scanline, width);
132 continue;
133 }
134
135 s >> image[1];
136 s >> image[2];
137 s >> image[3];
138
139 if (s.atEnd())
140 {
141 return true;
142 }
143
144 if ((image[1] != 2) || (image[2] & 128))
145 {
146 image[0] = 2;
147 Read_Old_Line(image.data()+4, width-1, s);
148 RGBE_To_QRgbLine(image.data(), scanline, width);
149 continue;
150 }
151
152 if ((image[2] << 8 | image[3]) != width)
153 {
154 return false;
155 }
156
157 // read each component
158 for (int i = 0; i < 4; i++)
159 {
160 for (int j = 0; j < width; )
161 {
162 s >> code;
163 if (s.atEnd())
164 {
165 return false;
166 }
167 if (code > 128)
168 {
169 // run
170 code &= 127;
171 s >> val;
172 while( code != 0 )
173 {
174 image[i + j * 4] = val;
175 j++;
176 code--;
177 }
178 }
179 else
180 {
181 // non-run
182 while( code != 0 )
183 {
184 s >> image[i + j * 4];
185 j++;
186 code--;
187 }
188 }
189 }
190 }
191
192 RGBE_To_QRgbLine(image.data(), scanline, width);
193 }
194
195 return true;
196 }
197
198} // namespace
199
200
201KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
202{
203 int len;
204 char line[MAXLINE];
205 //bool validHeader = false;
206 bool validFormat = false;
207
208 // Parse header
209 do {
210 len = io->ioDevice()->readLine(line, MAXLINE);
211
212 /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
213 {
214 validHeader = true;
215 }*/
216 if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
217 {
218 validFormat = true;
219 }
220
221 } while((len > 0) && (line[0] != '\n'));
222
223 if( /*!validHeader ||*/ !validFormat )
224 {
225 kDebug(399) << "Unknown HDR format.";
226 io->setImage( 0 );
227 io->setStatus( -1 );
228 return;
229 }
230
231 io->ioDevice()->readLine(line, MAXLINE);
232
233 char s1[3], s2[3];
234 int width, height;
235 if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
236 //if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
237 {
238 kDebug(399) << "Invalid HDR file.";
239 io->setImage( 0 );
240 io->setStatus( -1 );
241 return;
242 }
243
244 QDataStream s( io->ioDevice() );
245
246 QImage img;
247 if( !LoadHDR(s, width, height, img) )
248 {
249 kDebug(399) << "Error loading HDR file.";
250 io->setImage( 0 );
251 io->setStatus( -1 );
252 return;
253 }
254
255 io->setImage( img );
256 io->setStatus( 0 );
257}
258
259
260KDE_EXPORT void kimgio_hdr_write( QImageIO * )
261{
262 // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
263}
264
265

Warning: That file was not part of the compilation database. It may have many parsing errors.