• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KImgIO

hdr.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
00003    Copyright (C) 2005 Ignacio CastaƱo <castanyo@yahoo.es>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the Lesser GNU General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 */
00010 
00011 #include "hdr.h"
00012 
00013 #include <QtGui/QImage>
00014 #include <QtCore/QDataStream>
00015 
00016 #include <kdebug.h>
00017 
00018 typedef Q_UINT8 uchar;
00019 
00020 namespace { // Private.
00021 
00022 #define MAXLINE     1024
00023 #define MINELEN     8       // minimum scanline length for encoding
00024 #define MAXELEN     0x7fff  // maximum scanline length for encoding
00025 
00026     static inline uchar ClipToByte(float value)
00027     {
00028         if (value > 255.0f) return 255;
00029         //else if (value < 0.0f) return 0;  // we know value is positive.
00030         return uchar(value);
00031     }
00032 
00033     // read an old style line from the hdr image file
00034     // if 'first' is true the first byte is already read
00035     static bool Read_Old_Line (uchar * image, int width, QDataStream & s)
00036     {
00037         int  rshift = 0;
00038         int  i;
00039 
00040         while (width > 0)
00041         {
00042             s >> image[0];
00043             s >> image[1];
00044             s >> image[2];
00045             s >> image[3];
00046 
00047             if (s.atEnd()) return false;
00048 
00049             if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1))
00050             {
00051                 for (i = image[3] << rshift; i > 0; i--)
00052                 {
00053                     //memcpy(image, image-4, 4);
00054                     (uint &)image[0] = (uint &)image[0-4];
00055                     image += 4;
00056                     width--;
00057                 }
00058                 rshift += 8;
00059             }
00060             else
00061             {
00062                 image += 4;
00063                 width--;
00064                 rshift = 0;
00065             }
00066         }
00067         return true;
00068     }
00069 
00070 
00071     static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
00072     {
00073         for (int j = 0; j < width; j++)
00074         {
00075             // v = ldexp(1.0, int(image[3]) - 128);
00076             float v;
00077             int e = int(image[3]) - 128;
00078             if( e > 0 ) 
00079             {
00080                 v = float(1 << e);
00081             }
00082             else 
00083             {
00084                 v = 1.0f / float(1 << -e);
00085             }
00086             
00087             scanline[j] = qRgb( ClipToByte(float(image[0]) * v),
00088                                 ClipToByte(float(image[1]) * v),
00089                                 ClipToByte(float(image[2]) * v) );
00090 
00091             image += 4;
00092         }
00093     }
00094 
00095     // Load the HDR image.
00096     static bool LoadHDR( QDataStream & s, const int width, const int height, QImage & img )
00097     {
00098         uchar val, code;
00099 
00100         // Create dst image.
00101         if( !img.create( width, height, 32 ) )
00102         {
00103             return false;
00104         }
00105 
00106         QMemArray<uchar> image( width * 4 );
00107     
00108         for (int cline = 0; cline < height; cline++)
00109         {
00110             QRgb * scanline = (QRgb *) img.scanLine( cline );
00111 
00112             // determine scanline type
00113             if ((width < MINELEN) || (MAXELEN < width))
00114             {
00115                 Read_Old_Line(image.data(), width, s);
00116                 RGBE_To_QRgbLine(image.data(), scanline, width);
00117                 continue;
00118             }
00119 
00120             s >> val;
00121 
00122             if (s.atEnd()) 
00123             {
00124                 return true;
00125             }
00126 
00127             if (val != 2)
00128             {
00129                 s.device()->at( s.device()->at() - 1 );
00130                 Read_Old_Line(image.data(), width, s);
00131                 RGBE_To_QRgbLine(image.data(), scanline, width);
00132                 continue;
00133             }
00134 
00135             s >> image[1];
00136             s >> image[2];
00137             s >> image[3];
00138 
00139             if (s.atEnd()) 
00140             {
00141                 return true;
00142             }
00143 
00144             if ((image[1] != 2) || (image[2] & 128))
00145             {
00146                 image[0] = 2;
00147                 Read_Old_Line(image.data()+4, width-1, s);
00148                 RGBE_To_QRgbLine(image.data(), scanline, width);
00149                 continue;
00150             }
00151 
00152             if ((image[2] << 8 | image[3]) != width)
00153             {
00154                 return false;
00155             }
00156 
00157             // read each component
00158             for (int i = 0; i < 4; i++)
00159             {
00160                 for (int j = 0; j < width; )
00161                 {
00162                     s >> code;
00163                     if (s.atEnd())
00164                     {
00165                         return false;
00166                     }
00167                     if (code > 128)
00168                     {
00169                         // run
00170                         code &= 127;
00171                         s >> val;
00172                         while( code != 0 )
00173                         {
00174                             image[i + j * 4] = val;
00175                             j++;
00176                             code--;
00177                         }
00178                     }
00179                     else
00180                     {
00181                         // non-run
00182                         while( code != 0 )
00183                         {
00184                             s >> image[i +  j * 4];
00185                             j++;
00186                             code--;
00187                         }
00188                     }
00189                 }
00190             }
00191 
00192             RGBE_To_QRgbLine(image.data(), scanline, width);
00193         }
00194 
00195         return true;
00196     }
00197         
00198 } // namespace
00199 
00200 
00201 KDE_EXPORT void kimgio_hdr_read( QImageIO * io )
00202 {
00203     int len;
00204     char line[MAXLINE];
00205     //bool validHeader = false;
00206     bool validFormat = false;
00207     
00208     // Parse header 
00209     do {
00210         len = io->ioDevice()->readLine(line, MAXLINE);
00211     
00212         /*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
00213         {
00214             validHeader = true;
00215         }*/
00216         if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0)
00217         {
00218             validFormat = true;
00219         }
00220         
00221     } while((len > 0) && (line[0] != '\n'));
00222     
00223     if(  !validFormat )
00224     {
00225         kDebug(399) << "Unknown HDR format.";
00226         io->setImage( 0 );
00227         io->setStatus( -1 );
00228         return;
00229     }
00230     
00231     io->ioDevice()->readLine(line, MAXLINE);    
00232     
00233     char s1[3], s2[3];
00234     int width, height;
00235     if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
00236     //if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
00237     {
00238         kDebug(399) << "Invalid HDR file.";
00239         io->setImage( 0 );
00240         io->setStatus( -1 );
00241         return;
00242     }
00243     
00244     QDataStream s( io->ioDevice() );
00245 
00246     QImage img;
00247     if( !LoadHDR(s, width, height, img) ) 
00248     {
00249         kDebug(399) << "Error loading HDR file.";
00250         io->setImage( 0 );
00251         io->setStatus( -1 );
00252         return;
00253     }
00254 
00255     io->setImage( img );
00256     io->setStatus( 0 );
00257 }
00258 
00259 
00260 KDE_EXPORT void kimgio_hdr_write( QImageIO * )
00261 {
00262     // intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
00263 }
00264  

KImgIO

Skip menu "KImgIO"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal