some more win32'fication to fix non-ascii filename handling
[kdelibs.git] / kimgio / hdr.cpp
blob57f81a1fff2ca071782eb148bf93c87133122367
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.
9 */
11 #include "hdr.h"
13 #include <QtGui/QImage>
14 #include <QtCore/QDataStream>
16 #include <kdebug.h>
17 #include <kglobal.h>
19 typedef Q_UINT8 uchar;
21 namespace { // Private.
23 #define MAXLINE 1024
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.
31 return uchar(value);
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)
38 int rshift = 0;
39 int i;
41 while (width > 0)
43 s >> image[0];
44 s >> image[1];
45 s >> image[2];
46 s >> image[3];
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];
56 image += 4;
57 width--;
59 rshift += 8;
61 else
63 image += 4;
64 width--;
65 rshift = 0;
68 return true;
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);
77 float v;
78 int e = int(image[3]) - 128;
79 if( e > 0 )
81 v = float(1 << e);
83 else
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) );
92 image += 4;
96 // Load the HDR image.
97 static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
99 uchar val, code;
101 // Create dst image.
102 if( !img.create( width, height, 32 ) )
104 return false;
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);
118 continue;
121 s >> val;
123 if (s.atEnd())
125 return true;
128 if (val != 2)
130 s.device()->at( s.device()->at() - 1 );
131 Read_Old_Line(image.data(), width, s);
132 RGBE_To_QRgbLine(image.data(), scanline, width);
133 continue;
136 s >> image[1];
137 s >> image[2];
138 s >> image[3];
140 if (s.atEnd())
142 return true;
145 if ((image[1] != 2) || (image[2] & 128))
147 image[0] = 2;
148 Read_Old_Line(image.data()+4, width-1, s);
149 RGBE_To_QRgbLine(image.data(), scanline, width);
150 continue;
153 if ((image[2] << 8 | image[3]) != width)
155 return false;
158 // read each component
159 for (int i = 0; i < 4; i++)
161 for (int j = 0; j < width; )
163 s >> code;
164 if (s.atEnd())
166 return false;
168 if (code > 128)
170 // run
171 code &= 127;
172 s >> val;
173 while( code != 0 )
175 image[i + j * 4] = val;
176 j++;
177 code--;
180 else
182 // non-run
183 while( code != 0 )
185 s >> image[i + j * 4];
186 j++;
187 code--;
193 RGBE_To_QRgbLine(image.data(), scanline, width);
196 return true;
199 } // namespace
202 KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
204 int len;
205 char line[MAXLINE];
206 //bool validHeader = false;
207 bool validFormat = false;
209 // Parse header
210 do {
211 len = io->ioDevice()->readLine(line, MAXLINE);
213 /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
215 validHeader = true;
217 if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
219 validFormat = true;
222 } while((len > 0) && (line[0] != '\n'));
224 if( /*!validHeader ||*/ !validFormat )
226 kDebug(399) << "Unknown HDR format.";
227 io->setImage( 0 );
228 io->setStatus( -1 );
229 return;
232 io->ioDevice()->readLine(line, MAXLINE);
234 char s1[3], s2[3];
235 int width, height;
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.";
240 io->setImage( 0 );
241 io->setStatus( -1 );
242 return;
245 QDataStream s( io->ioDevice() );
247 QImage img;
248 if( !LoadHDR(s, width, height, img) )
250 kDebug(399) << "Error loading HDR file.";
251 io->setImage( 0 );
252 io->setStatus( -1 );
253 return;
256 io->setImage( img );
257 io->setStatus( 0 );
261 KDE_EXPORT void kimgio_hdr_write( QImageIO * )
263 // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)