root/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImageToolkit/JPEGTransform.cpp @ 36

Revision 36, 12.7 KB (checked in by vsilva, 8 years ago)

FIX Xades encoding problems

Line 
1// ==========================================================
2// JPEG lossless transformations
3//
4// Design and implementation by
5// - Petr Pytelka (pyta@lightcomp.com)
6// - Hervé Drolon (drolon@infonie.fr)
7//
8// This file is part of FreeImage 3
9//
10// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
11// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
12// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
13// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
14// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
15// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
16// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
17// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
18// THIS DISCLAIMER.
19//
20// Use at your own risk!
21// ==========================================================
22
23extern "C" {
24#define XMD_H
25#undef FAR
26#include <setjmp.h>
27
28#include "../LibJPEG/jinclude.h"
29#include "../LibJPEG/jpeglib.h"
30#include "../LibJPEG/jerror.h"
31#include "../LibJPEG/transupp.h"
32}
33
34#include "FreeImagePTEiD.h"
35#include "Utilities.h"
36
37// ----------------------------------------------------------
38//   IO filename handling
39// ----------------------------------------------------------
40
41typedef struct tagFilenameIO {
42        const char *src_file;
43        const char *dst_file;
44        const wchar_t *wsrc_file;
45        const wchar_t *wdst_file;
46} FilenameIO;
47
48// ----------------------------------------------------------
49//   Error handling
50// ----------------------------------------------------------
51
52/**
53        Receives control for a fatal error.  Information sufficient to
54        generate the error message has been stored in cinfo->err; call
55        output_message to display it.  Control must NOT return to the caller;
56        generally this routine will exit() or longjmp() somewhere.
57*/
58METHODDEF(void)
59ls_jpeg_error_exit (j_common_ptr cinfo) {
60        // always display the message
61        (*cinfo->err->output_message)(cinfo);
62
63        // allow JPEG with a premature end of file
64        if((cinfo)->err->msg_parm.i[0] != 13) {
65       
66                // let the memory manager delete any temp files before we die
67                jpeg_destroy(cinfo);
68               
69                throw FIF_JPEG;
70        }
71}
72
73/**
74        Actual output of any JPEG message.  Note that this method does not know
75        how to generate a message, only where to send it.
76*/
77METHODDEF(void)
78ls_jpeg_output_message (j_common_ptr cinfo) {
79        char buffer[JMSG_LENGTH_MAX];
80
81        // create the message
82        (*cinfo->err->format_message)(cinfo, buffer);
83        // send it to user's message proc
84        FreeImage_OutputMessageProc(FIF_JPEG, buffer);
85}
86
87// ----------------------------------------------------------
88//   Main program
89// ----------------------------------------------------------
90
91static BOOL 
92LosslessTransform(const FilenameIO *filenameIO, FREE_IMAGE_JPEG_OPERATION operation, const char *crop, BOOL perfect) {
93        // We assume all-in-memory processing and can therefore use only a
94        // single file pointer for sequential input and output operation
95        FILE *fp = NULL;
96
97        // check for UNICODE filenames - previous structure filling was done before
98        bool bUseUnicode = filenameIO && filenameIO->wsrc_file && filenameIO->wdst_file;
99
100        // Set up the jpeglib structures
101        jpeg_decompress_struct srcinfo;
102        jpeg_compress_struct dstinfo;
103        jpeg_error_mgr jsrcerr, jdsterr;
104        jvirt_barray_ptr *src_coef_arrays = NULL;
105        jvirt_barray_ptr *dst_coef_arrays = NULL;
106        // Support for copying optional markers from source to destination file
107        JCOPY_OPTION copyoption;
108        // Image transformation options
109        jpeg_transform_info transfoptions;
110       
111        // Initialize structures
112        memset(&srcinfo, 0, sizeof(srcinfo));
113        memset(&jsrcerr, 0, sizeof(jsrcerr));
114        memset(&jdsterr, 0, sizeof(jdsterr));
115        memset(&dstinfo, 0, sizeof(dstinfo));
116        memset(&transfoptions, 0, sizeof(transfoptions));
117       
118        // Copy all extra markers from source file
119        copyoption = JCOPYOPT_ALL;
120       
121        // Set up default JPEG parameters
122        transfoptions.force_grayscale = FALSE;
123        transfoptions.crop = FALSE;
124
125        // Select the transform option
126        switch(operation) {
127                case FIJPEG_OP_FLIP_H:          // horizontal flip
128                        transfoptions.transform = JXFORM_FLIP_H;
129                        break;
130                case FIJPEG_OP_FLIP_V:          // vertical flip
131                        transfoptions.transform = JXFORM_FLIP_V;
132                        break;
133                case FIJPEG_OP_TRANSPOSE:       // transpose across UL-to-LR axis
134                        transfoptions.transform = JXFORM_TRANSPOSE;
135                        break;
136                case FIJPEG_OP_TRANSVERSE:      // transpose across UR-to-LL axis
137                        transfoptions.transform = JXFORM_TRANSVERSE;
138                        break;
139                case FIJPEG_OP_ROTATE_90:       // 90-degree clockwise rotation
140                        transfoptions.transform = JXFORM_ROT_90;
141                        break;
142                case FIJPEG_OP_ROTATE_180:      // 180-degree rotation
143                        transfoptions.transform = JXFORM_ROT_180;
144                        break;
145                case FIJPEG_OP_ROTATE_270:      // 270-degree clockwise (or 90 ccw)
146                        transfoptions.transform = JXFORM_ROT_270;
147                        break;
148                default:
149                case FIJPEG_OP_NONE:            // no transformation
150                        transfoptions.transform = JXFORM_NONE;
151                        break;
152        }
153        // (perfect == TRUE) ==> fail if there is non-transformable edge blocks
154        transfoptions.perfect = (perfect == TRUE) ? TRUE : FALSE;
155        // Drop non-transformable edge blocks: trim off any partial edge MCUs that the transform can't handle.
156        transfoptions.trim = TRUE;
157
158        try {
159
160                // Initialize the JPEG decompression object with default error handling
161                srcinfo.err = jpeg_std_error(&jsrcerr);
162                srcinfo.err->error_exit = ls_jpeg_error_exit;
163                srcinfo.err->output_message = ls_jpeg_output_message;
164                jpeg_create_decompress(&srcinfo);
165
166                // Initialize the JPEG compression object with default error handling
167                dstinfo.err = jpeg_std_error(&jdsterr);
168                dstinfo.err->error_exit = ls_jpeg_error_exit;
169                dstinfo.err->output_message = ls_jpeg_output_message;
170                jpeg_create_compress(&dstinfo);
171
172                // crop option
173                if(crop != NULL) {
174                        if(!jtransform_parse_crop_spec(&transfoptions, crop)) {
175                                FreeImage_OutputMessageProc(FIF_JPEG, "Bogus crop argument %s", crop);
176                                throw(1);
177                        }
178                }
179
180                // Open the input file
181                if(bUseUnicode) {
182#ifdef _WIN32
183                        if((fp = _wfopen(filenameIO->wsrc_file, L"rb")) == NULL) {
184                                FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open input file for reading");
185                        }
186#else
187                        fp = NULL;
188#endif // _WIN32
189                } else {
190                        if((fp = fopen(filenameIO->src_file, "rb")) == NULL) {
191                                FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for reading", filenameIO->src_file);
192                        }
193                }
194                if(fp == NULL) {
195                        jpeg_destroy_compress(&dstinfo);
196                        jpeg_destroy_decompress(&srcinfo);
197                        return FALSE;
198                }
199               
200                // Specify data source for decompression
201                jpeg_stdio_src(&srcinfo, fp);
202               
203                // Enable saving of extra markers that we want to copy
204                jcopy_markers_setup(&srcinfo, copyoption);
205               
206                // Read the file header
207                jpeg_read_header(&srcinfo, TRUE);
208               
209                // Any space needed by a transform option must be requested before
210                // jpeg_read_coefficients so that memory allocation will be done right
211
212                // Prepare transformation workspace
213                // Fails right away if perfect flag is TRUE and transformation is not perfect
214                if( !jtransform_request_workspace(&srcinfo, &transfoptions) ) {
215                        FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect");
216                        throw(1);
217                }
218
219                // Read source file as DCT coefficients
220                src_coef_arrays = jpeg_read_coefficients(&srcinfo);
221               
222                // Initialize destination compression parameters from source values
223                jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
224
225                // Adjust destination parameters if required by transform options;
226                // also find out which set of coefficient arrays will hold the output
227                dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
228               
229                // Close the input file.
230                // Note: we assume that jpeg_read_coefficients consumed all input
231                // until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
232                // only consume more while (! cinfo->inputctl->eoi_reached).
233                // We cannot call jpeg_finish_decompress here since we still need the
234                // virtual arrays allocated from the source object for processing.
235                fclose(fp);
236
237                // Open the output file
238                if(bUseUnicode) {
239#ifdef _WIN32
240                        if((fp = _wfopen(filenameIO->wdst_file, L"wb")) == NULL) {
241                                FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open output file for writing");
242                        }
243#else
244                        fp = NULL;
245#endif // _WIN32
246                } else {
247                        if((fp = fopen(filenameIO->dst_file, "wb")) == NULL) {
248                                FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for writing", filenameIO->dst_file);
249                        }
250                }
251                if(fp == NULL) {
252                        throw(1);
253                }
254               
255                // Specify data destination for compression
256                jpeg_stdio_dest(&dstinfo, fp);
257               
258                // Start compressor (note no image data is actually written here)
259                jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
260               
261                // Copy to the output file any extra markers that we want to preserve
262                jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
263               
264                // Execute image transformation, if any
265                jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
266               
267                // Finish compression and release memory
268                jpeg_finish_compress(&dstinfo);
269                jpeg_destroy_compress(&dstinfo);
270                jpeg_finish_decompress(&srcinfo);
271                jpeg_destroy_decompress(&srcinfo);
272               
273                // Close output file and return
274                fclose(fp);
275        }
276        catch(...) {
277                if(fp) fclose(fp);
278                jpeg_destroy_compress(&dstinfo);
279                jpeg_destroy_decompress(&srcinfo);
280                return FALSE;
281        }
282
283        return TRUE;
284}
285
286// ----------------------------------------------------------
287//   FreeImage interface
288// ----------------------------------------------------------
289
290BOOL DLL_CALLCONV
291FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
292        try {
293                // check the src file format
294                if(FreeImage_GetFileType(src_file) != FIF_JPEG) {
295                        throw FI_MSG_ERROR_MAGIC_NUMBER;
296                }
297
298                // setup IO
299                FilenameIO filenameIO;
300                memset(&filenameIO, 0, sizeof(FilenameIO));
301                filenameIO.src_file = src_file;
302                filenameIO.dst_file = dst_file;
303
304                // perform the transformation
305                return LosslessTransform(&filenameIO, operation, NULL, perfect);
306
307        } catch(const char *text) {
308                FreeImage_OutputMessageProc(FIF_JPEG, text);
309                return FALSE;
310        }
311}
312
313BOOL DLL_CALLCONV
314FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom) {
315        char crop[64];
316
317        try {
318                // check the src file format
319                if(FreeImage_GetFileType(src_file) != FIF_JPEG) {
320                        throw FI_MSG_ERROR_MAGIC_NUMBER;
321                }
322               
323                // normalize the rectangle
324                if(right < left) {
325                        INPLACESWAP(left, right);
326                }
327                if(bottom < top) {
328                        INPLACESWAP(top, bottom);
329                }
330
331                // build the crop option
332                sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top);
333
334                // setup IO
335                FilenameIO filenameIO;
336                memset(&filenameIO, 0, sizeof(FilenameIO));
337                filenameIO.src_file = src_file;
338                filenameIO.dst_file = dst_file;
339
340                // perform the transformation
341                return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE);
342
343        } catch(const char *text) {
344                FreeImage_OutputMessageProc(FIF_JPEG, text);
345                return FALSE;
346        }
347}
348
349BOOL DLL_CALLCONV
350FreeImage_JPEGTransformU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
351#ifdef _WIN32
352        try {
353                // check the src file format
354                if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) {
355                        throw FI_MSG_ERROR_MAGIC_NUMBER;
356                }
357
358                // setup IO
359                FilenameIO filenameIO;
360                memset(&filenameIO, 0, sizeof(FilenameIO));
361                filenameIO.wsrc_file = src_file;
362                filenameIO.wdst_file = dst_file;
363
364                // perform the transformation
365                return LosslessTransform(&filenameIO, operation, NULL, perfect);
366
367        } catch(const char *text) {
368                FreeImage_OutputMessageProc(FIF_JPEG, text);
369        }
370#endif /// _WIN32
371        return FALSE;
372}
373
374BOOL DLL_CALLCONV
375FreeImage_JPEGCropU(const wchar_t *src_file, const wchar_t *dst_file, int left, int top, int right, int bottom) {
376#ifdef _WIN32
377        char crop[64];
378
379        try {
380                // check the src file format
381                if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) {
382                        throw FI_MSG_ERROR_MAGIC_NUMBER;
383                }
384               
385                // normalize the rectangle
386                if(right < left) {
387                        INPLACESWAP(left, right);
388                }
389                if(bottom < top) {
390                        INPLACESWAP(top, bottom);
391                }
392
393                // build the crop option
394                sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top);
395
396                // setup IO
397                FilenameIO filenameIO;
398                memset(&filenameIO, 0, sizeof(FilenameIO));
399                filenameIO.wsrc_file = src_file;
400                filenameIO.wdst_file = dst_file;
401
402                // perform the transformation
403                return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE);
404
405        } catch(const char *text) {
406                FreeImage_OutputMessageProc(FIF_JPEG, text);
407        }
408#endif // _WIN32
409        return FALSE;
410}
Note: See TracBrowser for help on using the browser.