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

KImgIO

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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