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 | |
18 | typedef Q_UINT8 uchar; |
19 | |
20 | namespace { // 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 | |
201 | KDE_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] != |
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 | |
260 | KDE_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.