- /* 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 <tqimage.h>
- #include <tqdatastream.h>
-
- #include <kdebug.h>
- #include <tdeglobal.h>
-
- typedef TQ_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, TQDataStream & 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] = tqRgb( ClipToByte(float(image[0]) * v),
- ClipToByte(float(image[1]) * v),
- ClipToByte(float(image[2]) * v) );
-
- image += 4;
- }
- }
-
- // Load the HDR image.
- static bool LoadHDR( TQDataStream & s, const int width, const int height, TQImage & img )
- {
- uchar val, code;
-
- // Create dst image.
- if( !img.create( width, height, 32 ) )
- {
- return false;
- }
-
- TQMemArray<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( TQImageIO * 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( TQImage() );
- 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( TQImage() );
- io->setStatus( -1 );
- return;
- }
-
- TQDataStream s( io->ioDevice() );
-
- TQImage img;
- if( !LoadHDR(s, width, height, img) )
- {
- kdDebug(399) << "Error loading HDR file." << endl;
- io->setImage( TQImage() );
- io->setStatus( -1 );
- return;
- }
-
- io->setImage( img );
- io->setStatus( 0 );
- }
-
-
- KDE_EXPORT void kimgio_hdr_write( TQImageIO * )
- {
- // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
- }
-
|