summaryrefslogtreecommitdiffstats
path: root/kimgio/hdr.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kimgio/hdr.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kimgio/hdr.cpp')
-rw-r--r--kimgio/hdr.cpp265
1 files changed, 265 insertions, 0 deletions
diff --git a/kimgio/hdr.cpp b/kimgio/hdr.cpp
new file mode 100644
index 000000000..edc49f91b
--- /dev/null
+++ b/kimgio/hdr.cpp
@@ -0,0 +1,265 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
+ Copyright (C) 2005 Ignacio Castaņo <castanyo@yahoo.es>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the Lesser GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+*/
+
+#include "hdr.h"
+
+#include <qimage.h>
+#include <qdatastream.h>
+
+#include <kdebug.h>
+#include <kglobal.h>
+
+typedef Q_UINT8 uchar;
+
+namespace { // Private.
+
+#define MAXLINE 1024
+#define MINELEN 8 // minimum scanline length for encoding
+#define MAXELEN 0x7fff // maximum scanline length for encoding
+
+ static inline uchar ClipToByte(float value)
+ {
+ if (value > 255.0f) return 255;
+ //else if (value < 0.0f) return 0; // we know value is positive.
+ return uchar(value);
+ }
+
+ // read an old style line from the hdr image file
+ // if 'first' is true the first byte is already read
+ static bool Read_Old_Line (uchar * image, int width, QDataStream & s)
+ {
+ int rshift = 0;
+ int i;
+
+ while (width > 0)
+ {
+ s >> image[0];
+ s >> image[1];
+ s >> image[2];
+ s >> image[3];
+
+ if (s.atEnd()) return false;
+
+ if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1))
+ {
+ for (i = image[3] << rshift; i > 0; i--)
+ {
+ //memcpy(image, image-4, 4);
+ (uint &)image[0] = (uint &)image[0-4];
+ image += 4;
+ width--;
+ }
+ rshift += 8;
+ }
+ else
+ {
+ image += 4;
+ width--;
+ rshift = 0;
+ }
+ }
+ return true;
+ }
+
+
+ static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
+ {
+ for (int j = 0; j < width; j++)
+ {
+ // v = ldexp(1.0, int(image[3]) - 128);
+ float v;
+ int e = int(image[3]) - 128;
+ if( e > 0 )
+ {
+ v = float(1 << e);
+ }
+ else
+ {
+ v = 1.0f / float(1 << -e);
+ }
+
+ scanline[j] = qRgb( ClipToByte(float(image[0]) * v),
+ ClipToByte(float(image[1]) * v),
+ ClipToByte(float(image[2]) * v) );
+
+ image += 4;
+ }
+ }
+
+ // Load the HDR image.
+ static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
+ {
+ uchar val, code;
+
+ // Create dst image.
+ if( !img.create( width, height, 32 ) )
+ {
+ return false;
+ }
+
+ QMemArray<uchar> image( width * 4 );
+
+ for (int cline = 0; cline < height; cline++)
+ {
+ QRgb * scanline = (QRgb *) img.scanLine( cline );
+
+ // determine scanline type
+ if ((width < MINELEN) || (MAXELEN < width))
+ {
+ Read_Old_Line(image.data(), width, s);
+ RGBE_To_QRgbLine(image.data(), scanline, width);
+ continue;
+ }
+
+ s >> val;
+
+ if (s.atEnd())
+ {
+ return true;
+ }
+
+ if (val != 2)
+ {
+ s.device()->at( s.device()->at() - 1 );
+ Read_Old_Line(image.data(), width, s);
+ RGBE_To_QRgbLine(image.data(), scanline, width);
+ continue;
+ }
+
+ s >> image[1];
+ s >> image[2];
+ s >> image[3];
+
+ if (s.atEnd())
+ {
+ return true;
+ }
+
+ if ((image[1] != 2) || (image[2] & 128))
+ {
+ image[0] = 2;
+ Read_Old_Line(image.data()+4, width-1, s);
+ RGBE_To_QRgbLine(image.data(), scanline, width);
+ continue;
+ }
+
+ if ((image[2] << 8 | image[3]) != width)
+ {
+ return false;
+ }
+
+ // read each component
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < width; )
+ {
+ s >> code;
+ if (s.atEnd())
+ {
+ return false;
+ }
+ if (code > 128)
+ {
+ // run
+ code &= 127;
+ s >> val;
+ while( code != 0 )
+ {
+ image[i + j * 4] = val;
+ j++;
+ code--;
+ }
+ }
+ else
+ {
+ // non-run
+ while( code != 0 )
+ {
+ s >> image[i + j * 4];
+ j++;
+ code--;
+ }
+ }
+ }
+ }
+
+ RGBE_To_QRgbLine(image.data(), scanline, width);
+ }
+
+ return true;
+ }
+
+} // namespace
+
+
+KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
+{
+ int len;
+ char line[MAXLINE];
+ //bool validHeader = false;
+ bool validFormat = false;
+
+ // Parse header
+ do {
+ len = io->ioDevice()->readLine(line, MAXLINE);
+
+ /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
+ {
+ validHeader = true;
+ }*/
+ if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
+ {
+ validFormat = true;
+ }
+
+ } while((len > 0) && (line[0] != '\n'));
+
+ if( /*!validHeader ||*/ !validFormat )
+ {
+ kdDebug(399) << "Unknown HDR format." << endl;
+ io->setImage( 0 );
+ io->setStatus( -1 );
+ return;
+ }
+
+ io->ioDevice()->readLine(line, MAXLINE);
+
+ char s1[3], s2[3];
+ int width, height;
+ if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
+ //if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
+ {
+ kdDebug(399) << "Invalid HDR file." << endl;
+ io->setImage( 0 );
+ io->setStatus( -1 );
+ return;
+ }
+
+ QDataStream s( io->ioDevice() );
+
+ QImage img;
+ if( !LoadHDR(s, width, height, img) )
+ {
+ kdDebug(399) << "Error loading HDR file." << endl;
+ io->setImage( 0 );
+ io->setStatus( -1 );
+ return;
+ }
+
+ io->setImage( img );
+ io->setStatus( 0 );
+}
+
+
+KDE_EXPORT void kimgio_hdr_write( QImageIO * )
+{
+ // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
+}
+