00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
#include <qglobal.h>
00016
00017
00018
#ifdef Q_OS_WIN
00019
typedef unsigned char boolean;
00020
#define HAVE_BOOLEAN
00021
#endif
00022
00023
00024
00025
#include <stdio.h>
00026
#include <qfileinfo.h>
00027
#include <qstring.h>
00028
#include <qimage.h>
00029
#include <setjmp.h>
00030 #define XMD_H
00031
extern "C" {
00032
#include <jpeglib.h>
00033
#include "jpegInternal.h"
00034 }
00035
00036
00037
#include "../imageTools.h"
00038
#include "jpegTools.h"
00039
00040
00041
00042 struct GVJPEGFatalError :
public jpeg_error_mgr
00043 {
00044 jmp_buf
mJmpBuffer;
00045
00046 static void handler(j_common_ptr cinfo)
00047 {
00048
GVJPEGFatalError* error=static_cast<GVJPEGFatalError*>(cinfo->err);
00049 (error->output_message)(cinfo);
00050 longjmp(error->
mJmpBuffer,1);
00051 }
00052 };
00053
00054 bool scaleJPEG(QString fileIn, QImage& scaledImage,
00055
int targetWidth,
int targetHeight)
00056 {
00057
00058
struct jpeg_decompress_struct cinfo;
00059
00060
00061 FILE* inputFile=fopen( fileIn.ascii(),
"rb" );
00062
if(!inputFile)
return false;
00063
00064
00065
struct GVJPEGFatalError jerr;
00066 cinfo.err = jpeg_std_error(&jerr);
00067 cinfo.err->error_exit = GVJPEGFatalError::handler;
00068
if (setjmp(jerr.
mJmpBuffer))
00069 {
00070 jpeg_destroy_decompress(&cinfo);
00071 fclose(inputFile);
00072
return false;
00073 }
00074
00075
00076 jpeg_create_decompress(&cinfo);
00077 jpeg_stdio_src(&cinfo, inputFile);
00078 jpeg_read_header(&cinfo, TRUE);
00079
00080
00081
int origWidth = (
int)cinfo.image_width;
00082
int origHeight = (
int)cinfo.image_height;
00083
int num = 1;
00084
int denom = 1;
00085
00086
00087
if( origWidth > targetWidth || origHeight > targetHeight )
00088 {
00089
while( denom < 8 &&
00090 ( origWidth / (denom*2) >= targetWidth || origHeight / (denom*2) >= targetHeight )
00091 )
00092 { denom = denom*2; }
00093 }
00094
00095
00096 cinfo.scale_num=num;
00097 cinfo.scale_denom=denom;
00098
00099
00100 jpeg_start_decompress(&cinfo);
00101
00102
switch(cinfo.output_components)
00103 {
00104
00105
case 1:
00106 {
00107 scaledImage.create( cinfo.output_width, cinfo.output_height, 8, 256 );
00108
for (
int i=0; i<256; i++)
00109 {
00110 scaledImage.setColor(i, qRgb(i,i,i));
00111 }
00112 }
00113
break;
00114
00115
00116
case 3:
00117
case 4:
00118 scaledImage.create( cinfo.output_width, cinfo.output_height, 32 );
00119
break;
00120
00121
00122
default:
00123 jpeg_destroy_decompress(&cinfo);
00124 fclose(inputFile);
00125
return false;
00126 }
00127
00128
00129 uchar** lines = scaledImage.jumpTable();
00130
while (cinfo.output_scanline < cinfo.output_height)
00131 {
00132 jpeg_read_scanlines(&cinfo, lines + cinfo.output_scanline, cinfo.output_height);
00133 }
00134 jpeg_finish_decompress(&cinfo);
00135
00136
00137
00138
if ( cinfo.output_components == 1 )
00139 {
00140 scaledImage = scaledImage.convertDepth( 32, Qt::AutoColor );
00141 }
00142
00143
00144
if ( cinfo.output_components == 3 )
00145 {
00146
for (uint j=0; j<cinfo.output_height; j++)
00147 {
00148 uchar *in = scaledImage.scanLine(j) + cinfo.output_width*3;
00149 QRgb *out = (QRgb*)( scaledImage.scanLine(j) );
00150
00151
for (uint i=cinfo.output_width; i--; )
00152 {
00153 in-=3;
00154 out[i] = qRgb(in[0], in[1], in[2]);
00155 }
00156 }
00157 }
00158
00159
00160
if( scaledImage.width() != targetWidth || scaledImage.height() != targetHeight )
00161 {
00162
int clampedTargetWidth = targetWidth;
00163
int clampedTargetHeight = targetHeight;
00164
00165
if(QMIN( ((
float)targetWidth)/origWidth, ((
float)targetHeight)/origHeight ) > 2)
00166 {
00167 clampedTargetWidth = 2*origWidth;
00168 clampedTargetHeight = 2*origHeight;
00169 }
00170
00171 scaledImage = scaledImage.smoothScale(clampedTargetWidth, clampedTargetHeight, QImage::ScaleMin);
00172 }
00173 jpeg_destroy_decompress(&cinfo);
00174 fclose(inputFile);
00175
return true;
00176 }
00177
00178 bool transformJPEG( QString fileIn, QString fileOut, TRANSFORM_CODE transformation )
00179 {
00180
struct jpeg_decompress_struct srcinfo;
00181
struct jpeg_compress_struct dstinfo;
00182
struct jpeg_error_mgr jsrcerr, jdsterr;
00183 FILE * input_file;
00184 FILE * output_file;
00185
jpeg_transform_info transformoption;
00186 jvirt_barray_ptr * src_coef_arrays;
00187 jvirt_barray_ptr * dst_coef_arrays;
00188
00189
00190
00191
switch( transformation )
00192 {
00193
case ROTATE_90:
00194 transformoption.
transform =
JXFORM_ROT_90;
00195
break;
00196
case ROTATE_270:
00197 transformoption.
transform =
JXFORM_ROT_270;
00198
break;
00199
case FLIP_H:
00200 transformoption.
transform =
JXFORM_FLIP_H;
00201
break;
00202
case FLIP_V:
00203 transformoption.
transform =
JXFORM_FLIP_V;
00204
break;
00205
default:
00206
return false;
00207 }
00208 transformoption.
trim = TRUE;
00209 transformoption.
force_grayscale = FALSE;
00210
00211
00212 srcinfo.err = jpeg_std_error(&jsrcerr);
00213 jpeg_create_decompress(&srcinfo);
00214
00215
00216 dstinfo.err = jpeg_std_error(&jdsterr);
00217 jpeg_create_compress(&dstinfo);
00218
00220
00221 dstinfo.err->trace_level = 0;
00222 jsrcerr.trace_level = jdsterr.trace_level;
00223 srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
00225
00226
00227
if ((input_file = fopen(QFile::encodeName(fileIn),
"rb")) == NULL)
return false;
00228
if ((output_file = fopen(QFile::encodeName(fileOut),
"wb")) == NULL)
return false;
00229
00230
00231 jpeg_stdio_src(&srcinfo, input_file);
00232
00233
00234
jcopy_markers_setup(&srcinfo,
JCOPYOPT_COMMENTS);
00235
00236
00237 (
void) jpeg_read_header(&srcinfo, TRUE);
00238
00239
00240
00241
jtransform_request_workspace(&srcinfo, &transformoption);
00242
00243
00244 src_coef_arrays = jpeg_read_coefficients(&srcinfo);
00245
00246
00247 jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
00248
00249
00250
00251 dst_coef_arrays =
jtransform_adjust_parameters(&dstinfo, src_coef_arrays,
00252 &transformoption);
00253
00254
00255 jpeg_stdio_dest(&dstinfo, output_file);
00256
00257
00258 jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
00259
00260
00261
jcopy_markers_execute(&srcinfo, &dstinfo);
00262
00263
00264
jtransform_execute_transformation(&srcinfo, &dstinfo,
00265 src_coef_arrays,
00266 &transformoption);
00267
00268
00269 jpeg_finish_compress(&dstinfo);
00270 jpeg_destroy_compress(&dstinfo);
00271 (
void) jpeg_finish_decompress(&srcinfo);
00272 jpeg_destroy_decompress(&srcinfo);
00273
00274
00275 fclose(input_file);
00276 fclose(output_file);
00277
00278
00279
return true;
00280 }
00281
00282