AlbumShaper  1.0a3
imageTools.cpp
Go to the documentation of this file.
1 //==============================================
2 // copyright : (C) 2003-2005 by Will Stokes
3 //==============================================
4 // This program is free software; you can redistribute it
5 // and/or modify it under the terms of the GNU General
6 // Public License as published by the Free Software
7 // Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //==============================================
10 
11 //Systemwide includes
12 #include <fstream>
13 #include <cstdlib>
14 #include <iostream>
15 #include <cmath>
16 
17 #include <qstring.h>
18 #include <qimage.h>
19 #include <qdir.h>
20 #include <qfile.h>
21 #include <qcolor.h>
22 #include <fstream>
23 #include <qpoint.h>
24 #include <qpainter.h>
25 
26 //Projectwide includes
27 #include "imageTools.h"
28 #include "jpeg/jpegTools.h"
29 #include "jpeg/jpegSize.h"
30 #include "../../config.h"
31 
32 //==============================================
33 bool isJpeg(const char* filename)
34 {
35  int w,h;
36  return getJPEGSize( QFile::encodeName(filename), w, h );
37 }
38 //==============================================
39 void calcScaledImageDimensions(int origWidth, int origHeight,
40  int idealWidth, int idealHeight,
41  int& width, int& height)
42 {
43  //if original dimensions are within ideal new size then use
44  //original dimensions
45  if(origWidth <= idealWidth &&
46  origHeight <= idealHeight)
47  {
48  width = origWidth;
49  height = origHeight;
50  return;
51  }
52 
53  //else find dimension which is way over bounds
54  float widthRatio = ((float)idealWidth) / ((float)origWidth);
55  float heightRatio = ((float)idealHeight) / ((float)origHeight);
56 
57  if(widthRatio < heightRatio)
58  {
59  width = idealWidth;
60  height = (int)((((float)idealWidth) / ((float)origWidth)) * ((float)origHeight));
61  }
62  else
63  {
64  height = idealHeight;
65  width = (int)((((float)idealHeight) / ((float)origHeight)) * ((float)origWidth));
66  }
67 }
68 //==============================================
69 void constructImages(QString imageName,
70  QImage& slideshowImage, QImage& thumbnailImage)
71 {
72  //---------------------------------------------------------
73  //obtain original image width and height
74  int origWidth, origHeight;
75  getImageSize( imageName, origWidth, origHeight );
76 
77  //compute dimensions of unhapped scaled thumbnail and slideshow images
78  int thumbWidth, thumbHeight;
79  calcScaledImageDimensions( origWidth, origHeight,
81  thumbWidth, thumbHeight);
82 
83  int slideWidth, slideHeight;
84  calcScaledImageDimensions( origWidth, origHeight,
86  slideWidth, slideHeight);
87  //---------------------------------------------------------
88  //create slide show image
89 
90  //first scale full image to unpadded dimensions
91  QImage temp;
92  scaleImage( imageName, temp, slideWidth, slideHeight );
93  slideWidth = temp.width();
94  slideHeight = temp.height();
95 
96  //create slideshow image and fill with white
97  slideshowImage.create( SLIDESHOW_WIDTH, SLIDESHOW_HEIGHT, 32 );
98  slideshowImage.fill( QColor(Qt::white).rgb() );
99 
100  //paint unpadded scaled image
101  int xDiff = SLIDESHOW_WIDTH - slideWidth;
102  int yDiff = SLIDESHOW_HEIGHT - slideHeight;
103  bitBlt( &slideshowImage, xDiff/2, yDiff/2,
104  &temp, 0, 0, slideWidth, slideHeight );
105 
106  //---------------------------------------------------------
107  //create thumnail image
108  scaleImage( imageName, thumbnailImage, thumbWidth, thumbHeight );
109  //---------------------------------------------------------
110 }
111 //==============================================
112 bool transformImage( QString fileIn, QString fileOut, TRANSFORM_CODE transformation )
113 {
114  //if file is jpeg use faster method
115  if( isJpeg(fileIn) )
116  return transformJPEG( fileIn, fileOut, transformation );
117 
118  //load image
119  QImage origImage(fileIn);
120  QImage transformedImage;
121 
122  //transform image
123  if(transformation == ROTATE_90)
124  {
125  if(!transformedImage.create( origImage.height(), origImage.width(), origImage.depth() ) )
126  return false;
127 
128  int x,y;
129  for(x=0; x < origImage.height(); x++)
130  {
131  for(y=0; y < origImage.width(); y++)
132  transformedImage.setPixel(origImage.height() - 1 - x, y, origImage.pixel(y, x) );
133  }
134  }
135  else if(transformation == ROTATE_270)
136  {
137  if(!transformedImage.create( origImage.height(), origImage.width(), origImage.depth() ) )
138  return false;
139 
140  int x,y;
141  for(x=0; x < origImage.height(); x++)
142  {
143  for(y=0; y < origImage.width(); y++)
144  transformedImage.setPixel(x, origImage.width() - 1 - y, origImage.pixel(y, x) );
145  }
146  }
147  else if(transformation == FLIP_H)
148  { transformedImage = origImage.mirror(false,true); }
149  else
150  { transformedImage = origImage.mirror(true,false); }
151 
152  //save out transformed image
153  transformedImage.save( fileOut, "JPEG", 95 );
154  return true;
155 }
156 //==============================================
157 bool scaleImage( QString fileIn, QString fileOut,
158  int newWidth, int newHeight)
159 {
160  //scale image
161  QImage scaledImage;
162  if( scaleImage(fileIn, scaledImage, newWidth, newHeight ) )
163  {
164  scaledImage.save( fileOut, "JPEG", 95 );
165  return true;
166  }
167  else
168  return false;
169 }
170 //==============================================
171 bool scaleImage(QString fileIn, QImage& scaledImage, int targetWidth, int targetHeight)
172 {
173  //if file is jpeg use faster method
174  QString extension = QFileInfo(fileIn).extension(false).lower();
175  if( extension.compare("jpeg") == 0 ||
176  extension.compare("jpg") == 0 )
177  return scaleJPEG( QFile::encodeName(fileIn), scaledImage, targetWidth, targetHeight );
178 
179  //use slow smooth-scale method for scaling image.
180  //clamp scaling to <= 2x
181  QImage orig(fileIn);
182  if(QMIN( ((float)targetWidth)/orig.width(), ((float)targetHeight)/orig.height() ) > 2)
183  {
184  targetWidth = 2*orig.width();
185  targetHeight = 2*orig.height();
186  }
187 
188  scaledImage = orig.smoothScale( targetWidth, targetHeight, Qt::KeepAspectRatio );
189  return true;
190 }
191 //==============================================
192 bool getImageSize( const char* filename,QSize& size )
193 {
194  int w,h;
195  bool result = getImageSize( filename, w, h );
196  size.setWidth( w );
197  size.setHeight( h );
198  return result;
199 }
200 //==============================================
201 bool getImageSize( const char* filename, int& width, int& height )
202 {
203  //if file is jpeg use faster method
204  QString extension = QFileInfo(filename).extension(false).lower();
205  if( extension.compare("jpeg") == 0 ||
206  extension.compare("jpg") == 0 )
207  return getJPEGSize( QFile::encodeName(filename),
208  width, height );
209 
210  //load entire image to qimage object in order to determine size
211  QImage image(filename);
212  width = image.width();
213  height = image.height();
214  return true;
215 }
216 //==============================================
217 double RGBtoL(QRgb* rgb)
218 {
219  double r = ((double)qRed(*rgb) )/255.0;
220  double g = ((double)qGreen(*rgb) )/255.0;
221  double b = ((double)qBlue(*rgb) )/255.0;
222 
223  double h,s,v;
224  RGBtoHSV(r,g,b,&h,&s,&v);
225  return 255.0*v;
226 }
227 //==============================================
228 //RGB to HSV and HSB to RGB algorithms based
229 //on by A. R. Smith in 1978, found at
230 //http://www.cs.rit.edu/~ncs/color/t_convert.html
231 void RGBtoHSV( double r, double g, double b,
232  double *h, double *s, double *v )
233 {
234  double min, max, delta;
235 
236  min = QMIN(QMIN( r, g), b );
237  max = QMAX(QMAX( r, g), b );
238  *v = max; // v
239 
240  delta = max - min;
241 
242  if( max != 0 )
243  *s = delta / max; // s
244  else {
245  // r = g = b = 0 // s = 0, v is undefined
246  *s = 0;
247  *h = -1;
248  return;
249  }
250 
251  if( r == max )
252  *h = ( g - b ) / delta; // between yellow & magenta
253  else if( g == max )
254  *h = 2 + ( b - r ) / delta; // between cyan & yellow
255  else
256  *h = 4 + ( r - g ) / delta; // between magenta & cyan
257 
258  *h *= 60; // degrees
259  if( *h < 0 )
260  *h += 360;
261 
262 }
263 //==============================================
264 void HSVtoRGB( double *r, double *g, double *b,
265  double h, double s, double v )
266 {
267  int i;
268  double f, p, q, t;
269 
270  if( s == 0 ) {
271  // achromatic (grey)
272  *r = *g = *b = v;
273  return;
274  }
275 
276  h /= 60; // sector 0 to 5
277  i = (int)floor( h );
278  f = h - i; // factorial part of h
279  p = v * ( 1 - s );
280  q = v * ( 1 - s * f );
281  t = v * ( 1 - s * ( 1 - f ) );
282 
283  switch( i ) {
284  case 0:
285  *r = v;
286  *g = t;
287  *b = p;
288  break;
289  case 1:
290  *r = q;
291  *g = v;
292  *b = p;
293  break;
294  case 2:
295  *r = p;
296  *g = v;
297  *b = t;
298  break;
299  case 3:
300  *r = p;
301  *g = q;
302  *b = v;
303  break;
304  case 4:
305  *r = t;
306  *g = p;
307  *b = v;
308  break;
309  default: // case 5:
310  *r = v;
311  *g = p;
312  *b = q;
313  break;
314  }
315 }
316 //==============================================
bool transformJPEG(QString fileIn, QString fileOut, TRANSFORM_CODE transformation)
Definition: jpegTools.cpp:178
double RGBtoL(QRgb *rgb)
find luminance of a rgb color triplet
Definition: imageTools.cpp:217
void HSVtoRGB(double *r, double *g, double *b, double h, double s, double v)
Convert a HSV color triplet to RGB.
Definition: imageTools.cpp:264
TRANSFORM_CODE
Definition: imageTools.h:24
long b
Definition: jpegInternal.h:125
float q
Definition: blur.cpp:78
#define THUMBNAIL_HEIGHT
Definition: config.h:25
int width
Definition: blur.cpp:79
bool transformImage(QString fileIn, QString fileOut, TRANSFORM_CODE transformation)
Apply image transformation on image.
Definition: imageTools.cpp:112
bool scaleImage(QString fileIn, QString fileOut, int newWidth, int newHeight)
Scale image and save copy to disk.
Definition: imageTools.cpp:157
bool getImageSize(const char *filename, QSize &size)
Get image dimensions.
Definition: imageTools.cpp:192
bool isJpeg(const char *filename)
Checks to see if an image is a valid jpg by seeing if the image dimensions can be read...
Definition: imageTools.cpp:33
void constructImages(QString imageName, QImage &slideshowImage, QImage &thumbnailImage)
Constructs slideshow and thumbnail images for a full sized image.
Definition: imageTools.cpp:69
void RGBtoHSV(double r, double g, double b, double *h, double *s, double *v)
Convert a RGB color triplet to HSV.
Definition: imageTools.cpp:231
#define THUMBNAIL_WIDTH
Definition: config.h:24
void calcScaledImageDimensions(int origWidth, int origHeight, int idealWidth, int idealHeight, int &width, int &height)
Computes scale of image dimensions while respecting aspect ratio, equivalent to a QImage::scaleMin wi...
Definition: imageTools.cpp:39
bool getJPEGSize(const char *filename, int &width, int &height)
Definition: jpegSize.cpp:65
#define SLIDESHOW_WIDTH
Definition: config.h:26
#define SLIDESHOW_HEIGHT
Definition: config.h:27
int height
Definition: blur.cpp:79
bool scaleJPEG(QString fileIn, QImage &scaledImage, int targetWidth, int targetHeight)
Definition: jpegTools.cpp:54