imageTools.cpp

Go to the documentation of this file.
00001 //==============================================
00002 //  copyright            : (C) 2003-2005 by Will Stokes
00003 //==============================================
00004 //  This program is free software; you can redistribute it
00005 //  and/or modify it under the terms of the GNU General
00006 //  Public License as published by the Free Software
00007 //  Foundation; either version 2 of the License, or
00008 //  (at your option) any later version.
00009 //==============================================
00010 
00011 //Systemwide includes
00012 #include <fstream>
00013 #include <cstdlib>
00014 #include <iostream>
00015 #include <cmath>
00016 
00017 #include <qstring.h>
00018 #include <qimage.h>
00019 #include <qdir.h>
00020 #include <qfile.h>
00021 #include <qcolor.h>
00022 #include <fstream>
00023 #include <qpoint.h>
00024 #include <qpainter.h>
00025 
00026 //Projectwide includes
00027 #include "imageTools.h"
00028 #include "jpeg/jpegTools.h"
00029 #include "jpeg/jpegSize.h"
00030 #include "../../config.h"
00031 
00032 //==============================================
00033 bool isJpeg(const char* filename)
00034 {
00035   int w,h;
00036   return getJPEGSize( QFile::encodeName(filename), w, h );
00037 }
00038 //==============================================
00039 void calcScaledImageDimensions(int origWidth, int origHeight,
00040                                int idealWidth, int idealHeight,
00041                                int& width, int& height)
00042 {
00043   //if original dimensions are within ideal new size then use
00044   //original dimensions
00045   if(origWidth <= idealWidth &&
00046      origHeight <= idealHeight)
00047   {
00048     width = origWidth;
00049     height = origHeight;
00050     return;
00051   }
00052 
00053   //else find dimension which is way over bounds
00054   float widthRatio = ((float)idealWidth) / ((float)origWidth);
00055   float heightRatio = ((float)idealHeight) / ((float)origHeight);
00056 
00057   if(widthRatio < heightRatio)
00058   {
00059     width = idealWidth;
00060     height = (int)((((float)idealWidth) / ((float)origWidth)) * ((float)origHeight));
00061   }
00062   else
00063   {
00064     height = idealHeight;
00065     width = (int)((((float)idealHeight) / ((float)origHeight)) * ((float)origWidth));
00066   }
00067 }
00068 //==============================================
00069 void constructImages(QString imageName, 
00070                      QImage& slideshowImage, QImage& thumbnailImage)
00071 {
00072   //---------------------------------------------------------
00073   //obtain original image width and height
00074   int origWidth, origHeight;
00075   getImageSize( imageName, origWidth, origHeight );
00076   
00077   //compute dimensions of unhapped scaled thumbnail and slideshow images
00078   int thumbWidth, thumbHeight;
00079   calcScaledImageDimensions( origWidth, origHeight,
00080                              THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT,
00081                              thumbWidth, thumbHeight);
00082   
00083   int slideWidth, slideHeight;
00084   calcScaledImageDimensions( origWidth, origHeight,
00085                              SLIDESHOW_WIDTH, SLIDESHOW_HEIGHT,
00086                              slideWidth, slideHeight);
00087   //---------------------------------------------------------
00088   //create slide show image
00089   
00090   //first scale full image to unpadded dimensions
00091   QImage temp;
00092   scaleImage( imageName, temp, slideWidth, slideHeight );
00093   slideWidth = temp.width();
00094   slideHeight = temp.height();
00095  
00096   //create slideshow image and fill with white
00097   slideshowImage.create( SLIDESHOW_WIDTH, SLIDESHOW_HEIGHT, 32 );
00098   slideshowImage.fill( Qt::white.rgb() );
00099   
00100   //paint unpadded scaled image
00101   int xDiff = SLIDESHOW_WIDTH - slideWidth;
00102   int yDiff = SLIDESHOW_HEIGHT - slideHeight;
00103   bitBlt( &slideshowImage, xDiff/2, yDiff/2,
00104           &temp, 0, 0, slideWidth, slideHeight );
00105    
00106   //---------------------------------------------------------
00107   //create thumnail image
00108   scaleImage( imageName, thumbnailImage, thumbWidth, thumbHeight );
00109   //---------------------------------------------------------
00110 }
00111 //==============================================
00112 bool transformImage( QString fileIn, QString fileOut, TRANSFORM_CODE transformation )
00113 {
00114   //if file is jpeg use faster method
00115   if( isJpeg(fileIn) )
00116     return transformJPEG( fileIn, fileOut, transformation );
00117   
00118   //load image
00119   QImage origImage(fileIn);
00120   QImage transformedImage;
00121   
00122   //transform image
00123   if(transformation == ROTATE_90)
00124   {
00125     if(!transformedImage.create( origImage.height(), origImage.width(), origImage.depth() ) )
00126       return false;
00127     
00128     int x,y;
00129     for(x=0; x < origImage.height(); x++)
00130     {
00131       for(y=0; y < origImage.width(); y++)
00132         transformedImage.setPixel(origImage.height() - 1 - x, y, origImage.pixel(y, x) );
00133     }
00134   }
00135   else if(transformation == ROTATE_270)
00136   {
00137     if(!transformedImage.create( origImage.height(), origImage.width(), origImage.depth() ) )
00138       return false;
00139     
00140     int x,y;
00141     for(x=0; x < origImage.height(); x++)
00142     {
00143       for(y=0; y < origImage.width(); y++)
00144           transformedImage.setPixel(x, origImage.width() - 1 - y, origImage.pixel(y, x) );
00145     }
00146   }
00147   else if(transformation == FLIP_H)
00148   {  transformedImage = origImage.mirror(false,true); }
00149   else
00150   {  transformedImage = origImage.mirror(true,false); }
00151   
00152   //save out transformed image  
00153   transformedImage.save( fileOut, "JPEG", 95 );
00154   return true;  
00155 }
00156 //==============================================
00157 bool scaleImage( QString fileIn, QString fileOut, 
00158                  int newWidth, int newHeight)
00159 {
00160   //scale image
00161   QImage scaledImage;
00162   if( scaleImage(fileIn, scaledImage, newWidth, newHeight ) )
00163   {
00164     scaledImage.save( fileOut, "JPEG", 95 );
00165     return true;
00166   }
00167   else
00168     return false;
00169 }
00170 //==============================================
00171 bool scaleImage(QString fileIn, QImage& scaledImage, int targetWidth, int targetHeight)
00172 {
00173   //if file is jpeg use faster method
00174   QString extension = QFileInfo(fileIn).extension(false).lower();
00175   if( extension.compare("jpeg") == 0 ||
00176       extension.compare("jpg") == 0 )
00177     return scaleJPEG( QFile::encodeName(fileIn), scaledImage, targetWidth, targetHeight );
00178   
00179   //use slow smooth-scale method for scaling image.
00180   //clamp scaling to <= 2x
00181   QImage orig(fileIn);  
00182   if(QMIN( ((float)targetWidth)/orig.width(), ((float)targetHeight)/orig.height() ) > 2)    
00183   {
00184     targetWidth = 2*orig.width();
00185     targetHeight = 2*orig.height();
00186   }
00187   
00188   scaledImage = orig.smoothScale( targetWidth, targetHeight, QImage::ScaleMin );
00189   return true;
00190 }
00191 //==============================================
00192 bool getImageSize( const char* filename,QSize& size )
00193 {
00194   int w,h;
00195   bool result = getImageSize( filename, w, h );
00196   size.setWidth( w );
00197   size.setHeight( h );
00198   return result;
00199 }
00200 //==============================================
00201 bool getImageSize( const char* filename, int& width, int& height )
00202 {
00203   //if file is jpeg use faster method
00204   QString extension = QFileInfo(filename).extension(false).lower();
00205   if( extension.compare("jpeg") == 0 ||
00206       extension.compare("jpg") == 0 )
00207     return getJPEGSize( QFile::encodeName(filename),
00208                         width, height );
00209 
00210   //load entire image to qimage object in order to determine size
00211   QImage image(filename);
00212   width = image.width();
00213   height = image.height();
00214   return true;
00215 }
00216 //==============================================
00217 double RGBtoL(QRgb* rgb)
00218 {
00219   double r = ((double)qRed(*rgb)   )/255.0;
00220   double g = ((double)qGreen(*rgb) )/255.0;
00221   double b = ((double)qBlue(*rgb)  )/255.0;
00222 
00223   double h,s,v;
00224   RGBtoHSV(r,g,b,&h,&s,&v);
00225   return 255.0*v;
00226 }
00227 //==============================================
00228 //RGB to HSV and HSB to RGB algorithms based
00229 //on by A. R. Smith in 1978, found at 
00230 //http://www.cs.rit.edu/~ncs/color/t_convert.html
00231 void RGBtoHSV( double r, double g, double b, 
00232                double *h, double *s, double *v )
00233 {
00234         double min, max, delta;
00235   
00236         min = QMIN(QMIN( r, g), b );
00237         max = QMAX(QMAX( r, g), b );
00238         *v = max;                               // v
00239   
00240         delta = max - min;
00241   
00242         if( max != 0 )
00243                 *s = delta / max;               // s
00244         else {
00245                 // r = g = b = 0                // s = 0, v is undefined
00246                 *s = 0;
00247                 *h = -1;
00248                 return;
00249         }
00250   
00251         if( r == max )
00252                 *h = ( g - b ) / delta;         // between yellow & magenta
00253         else if( g == max )
00254                 *h = 2 + ( b - r ) / delta;     // between cyan & yellow
00255         else
00256                 *h = 4 + ( r - g ) / delta;     // between magenta & cyan
00257   
00258         *h *= 60;                               // degrees
00259         if( *h < 0 )
00260                 *h += 360;
00261   
00262 }
00263 //==============================================
00264 void HSVtoRGB( double *r, double *g, double *b, 
00265                double h, double s, double v )
00266 {
00267         int i;
00268         double f, p, q, t;
00269   
00270         if( s == 0 ) {
00271                 // achromatic (grey)
00272                 *r = *g = *b = v;
00273                 return;
00274         }
00275   
00276         h /= 60;                        // sector 0 to 5
00277         i = (int)floor( h );
00278         f = h - i;                      // factorial part of h
00279         p = v * ( 1 - s );
00280         q = v * ( 1 - s * f );
00281         t = v * ( 1 - s * ( 1 - f ) );
00282   
00283         switch( i ) {
00284                 case 0:
00285                         *r = v;
00286                         *g = t;
00287                         *b = p;
00288                         break;
00289                 case 1:
00290                         *r = q;
00291                         *g = v;
00292                         *b = p;
00293                         break;
00294                 case 2:
00295                         *r = p;
00296                         *g = v;
00297                         *b = t;
00298                         break;
00299                 case 3:
00300                         *r = p;
00301                         *g = q;
00302                         *b = v;
00303                         break;
00304                 case 4:
00305                         *r = t;
00306                         *g = p;
00307                         *b = v;
00308                         break;
00309                 default:                // case 5:
00310                         *r = v;
00311                         *g = p;
00312                         *b = q;
00313                         break;
00314         }  
00315 }
00316 //==============================================

Generated on Wed Jan 24 05:38:28 2007 for AlbumShaper by  doxygen 1.5.1