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 if ( cinfo.output_components == 3 )
00138 {
00139 for (uint j=0; j<cinfo.output_height; j++)
00140 {
00141 uchar *in = scaledImage.scanLine(j) + cinfo.output_width*3;
00142 QRgb *out = (QRgb*)( scaledImage.scanLine(j) );
00143
00144 for (uint i=cinfo.output_width; i--; )
00145 {
00146 in-=3;
00147 out[i] = qRgb(in[0], in[1], in[2]);
00148 }
00149 }
00150 }
00151
00152
00153 if( scaledImage.width() != targetWidth || scaledImage.height() != targetHeight )
00154 {
00155 int clampedTargetWidth = targetWidth;
00156 int clampedTargetHeight = targetHeight;
00157
00158 if(QMIN( ((float)targetWidth)/origWidth, ((float)targetHeight)/origHeight ) > 2)
00159 {
00160 clampedTargetWidth = 2*origWidth;
00161 clampedTargetHeight = 2*origHeight;
00162 }
00163
00164 scaledImage = scaledImage.smoothScale(clampedTargetWidth, clampedTargetHeight, QImage::ScaleMin);
00165 }
00166 jpeg_destroy_decompress(&cinfo);
00167 fclose(inputFile);
00168 return true;
00169 }
00170
00171 bool transformJPEG( QString fileIn, QString fileOut, TRANSFORM_CODE transformation )
00172 {
00173 struct jpeg_decompress_struct srcinfo;
00174 struct jpeg_compress_struct dstinfo;
00175 struct jpeg_error_mgr jsrcerr, jdsterr;
00176 FILE * input_file;
00177 FILE * output_file;
00178 jpeg_transform_info transformoption;
00179 jvirt_barray_ptr * src_coef_arrays;
00180 jvirt_barray_ptr * dst_coef_arrays;
00181
00182
00183
00184 switch( transformation )
00185 {
00186 case ROTATE_90:
00187 transformoption.transform = JXFORM_ROT_90;
00188 break;
00189 case ROTATE_270:
00190 transformoption.transform = JXFORM_ROT_270;
00191 break;
00192 case FLIP_H:
00193 transformoption.transform = JXFORM_FLIP_H;
00194 break;
00195 case FLIP_V:
00196 transformoption.transform = JXFORM_FLIP_V;
00197 break;
00198 default:
00199 return false;
00200 }
00201 transformoption.trim = TRUE;
00202 transformoption.force_grayscale = FALSE;
00203
00204
00205 srcinfo.err = jpeg_std_error(&jsrcerr);
00206 jpeg_create_decompress(&srcinfo);
00207
00208
00209 dstinfo.err = jpeg_std_error(&jdsterr);
00210 jpeg_create_compress(&dstinfo);
00211
00213
00214 dstinfo.err->trace_level = 0;
00215 jsrcerr.trace_level = jdsterr.trace_level;
00216 srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
00218
00219
00220 if ((input_file = fopen(QFile::encodeName(fileIn), "rb")) == NULL) return false;
00221 if ((output_file = fopen(QFile::encodeName(fileOut), "wb")) == NULL) return false;
00222
00223
00224 jpeg_stdio_src(&srcinfo, input_file);
00225
00226
00227 jcopy_markers_setup(&srcinfo, JCOPYOPT_COMMENTS);
00228
00229
00230 (void) jpeg_read_header(&srcinfo, TRUE);
00231
00232
00233
00234 jtransform_request_workspace(&srcinfo, &transformoption);
00235
00236
00237 src_coef_arrays = jpeg_read_coefficients(&srcinfo);
00238
00239
00240 jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
00241
00242
00243
00244 dst_coef_arrays = jtransform_adjust_parameters(&dstinfo, src_coef_arrays,
00245 &transformoption);
00246
00247
00248 jpeg_stdio_dest(&dstinfo, output_file);
00249
00250
00251 jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
00252
00253
00254 jcopy_markers_execute(&srcinfo, &dstinfo);
00255
00256
00257 jtransform_execute_transformation(&srcinfo, &dstinfo,
00258 src_coef_arrays,
00259 &transformoption);
00260
00261
00262 jpeg_finish_compress(&dstinfo);
00263 jpeg_destroy_compress(&dstinfo);
00264 (void) jpeg_finish_decompress(&srcinfo);
00265 jpeg_destroy_decompress(&srcinfo);
00266
00267
00268 fclose(input_file);
00269 fclose(output_file);
00270
00271
00272 return true;
00273 }
00274
00275