aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage/llimagejpeg.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llimage/llimagejpeg.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llimage/llimagejpeg.cpp')
-rw-r--r--linden/indra/llimage/llimagejpeg.cpp621
1 files changed, 621 insertions, 0 deletions
diff --git a/linden/indra/llimage/llimagejpeg.cpp b/linden/indra/llimage/llimagejpeg.cpp
new file mode 100644
index 0000000..5c83f20
--- /dev/null
+++ b/linden/indra/llimage/llimagejpeg.cpp
@@ -0,0 +1,621 @@
1/**
2 * @file llimagejpeg.cpp
3 *
4 * Copyright (c) 2002-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "linden_common.h"
28#include "stdtypes.h"
29
30#include "llimagejpeg.h"
31
32#include "llerror.h"
33
34LLImageJPEG::LLImageJPEG()
35 :
36 LLImageFormatted(IMG_CODEC_JPEG),
37 mOutputBuffer( NULL ),
38 mOutputBufferSize( 0 ),
39 mEncodeQuality( 75 ) // on a scale from 1 to 100
40{
41}
42
43LLImageJPEG::~LLImageJPEG()
44{
45 llassert( !mOutputBuffer ); // Should already be deleted at end of encode.
46 delete[] mOutputBuffer;
47}
48
49BOOL LLImageJPEG::updateData()
50{
51 resetLastError();
52
53 // Check to make sure that this instance has been initialized with data
54 if (!getData() || (0 == getDataSize()))
55 {
56 setLastError("Uninitialized instance of LLImageJPEG");
57 return FALSE;
58 }
59
60 ////////////////////////////////////////
61 // Step 1: allocate and initialize JPEG decompression object
62
63 // This struct contains the JPEG decompression parameters and pointers to
64 // working space (which is allocated as needed by the JPEG library).
65 struct jpeg_decompress_struct cinfo;
66 cinfo.client_data = this;
67
68 struct jpeg_error_mgr jerr;
69 cinfo.err = jpeg_std_error(&jerr);
70
71 // Customize with our own callbacks
72 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
73 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
74 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
75
76 try
77 {
78 // Now we can initialize the JPEG decompression object.
79 jpeg_create_decompress(&cinfo);
80
81 ////////////////////////////////////////
82 // Step 2: specify data source
83 // (Code is modified version of jpeg_stdio_src();
84 if (cinfo.src == NULL)
85 {
86 cinfo.src = (struct jpeg_source_mgr *)
87 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
88 sizeof(struct jpeg_source_mgr));
89 }
90 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
91 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
92 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
93 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
94 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
95
96 cinfo.src->bytes_in_buffer = getDataSize();
97 cinfo.src->next_input_byte = getData();
98
99 ////////////////////////////////////////
100 // Step 3: read file parameters with jpeg_read_header()
101 jpeg_read_header( &cinfo, TRUE );
102
103 // Data set by jpeg_read_header
104 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
105
106 /*
107 // More data set by jpeg_read_header
108 cinfo.num_components;
109 cinfo.jpeg_color_space; // Colorspace of image
110 cinfo.saw_JFIF_marker; // TRUE if a JFIF APP0 marker was seen
111 cinfo.JFIF_major_version; // Version information from JFIF marker
112 cinfo.JFIF_minor_version; //
113 cinfo.density_unit; // Resolution data from JFIF marker
114 cinfo.X_density;
115 cinfo.Y_density;
116 cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
117 cinfo.Adobe_transform; // Color transform code from Adobe marker
118 */
119 }
120 catch (int)
121 {
122 jpeg_destroy_decompress(&cinfo);
123
124 return FALSE;
125 }
126 ////////////////////////////////////////
127 // Step 4: Release JPEG decompression object
128 jpeg_destroy_decompress(&cinfo);
129
130 return TRUE;
131}
132
133// Initialize source --- called by jpeg_read_header
134// before any data is actually read.
135void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo )
136{
137 // no work necessary here
138}
139
140// Fill the input buffer --- called whenever buffer is emptied.
141boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
142{
143// jpeg_source_mgr* src = cinfo->src;
144// LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
145
146 // Should never get here, since we provide the entire buffer up front.
147 ERREXIT(cinfo, JERR_INPUT_EMPTY);
148
149 return TRUE;
150}
151
152// Skip data --- used to skip over a potentially large amount of
153// uninteresting data (such as an APPn marker).
154//
155// Writers of suspendable-input applications must note that skip_input_data
156// is not granted the right to give a suspension return. If the skip extends
157// beyond the data currently in the buffer, the buffer can be marked empty so
158// that the next read will cause a fill_input_buffer call that can suspend.
159// Arranging for additional bytes to be discarded before reloading the input
160// buffer is the application writer's problem.
161void LLImageJPEG::decodeSkipInputData (j_decompress_ptr cinfo, long num_bytes)
162{
163 jpeg_source_mgr* src = cinfo->src;
164// LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
165
166 src->next_input_byte += (size_t) num_bytes;
167 src->bytes_in_buffer -= (size_t) num_bytes;
168}
169
170void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
171{
172 // no work necessary here
173}
174
175
176BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
177{
178 llassert_always(raw_image);
179
180 resetLastError();
181
182 // Check to make sure that this instance has been initialized with data
183 if (!getData() || (0 == getDataSize()))
184 {
185 setLastError("LLImageJPEG trying to decode an image with no data!");
186 return FALSE;
187 }
188
189 S32 row_stride = 0;
190 U8* raw_image_data = NULL;
191
192 ////////////////////////////////////////
193 // Step 1: allocate and initialize JPEG decompression object
194
195 // This struct contains the JPEG decompression parameters and pointers to
196 // working space (which is allocated as needed by the JPEG library).
197 struct jpeg_decompress_struct cinfo;
198
199 struct jpeg_error_mgr jerr;
200 cinfo.err = jpeg_std_error(&jerr);
201
202 // Customize with our own callbacks
203 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
204 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
205 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
206
207
208 try
209 {
210 // Now we can initialize the JPEG decompression object.
211 jpeg_create_decompress(&cinfo);
212
213 ////////////////////////////////////////
214 // Step 2: specify data source
215 // (Code is modified version of jpeg_stdio_src();
216 if (cinfo.src == NULL)
217 {
218 cinfo.src = (struct jpeg_source_mgr *)
219 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
220 sizeof(struct jpeg_source_mgr));
221 }
222 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
223 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
224 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
225 cinfo.src->resync_to_restart = jpeg_resync_to_restart; // For now, use default method, but we should be able to do better.
226 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
227 cinfo.src->bytes_in_buffer = getDataSize();
228 cinfo.src->next_input_byte = getData();
229
230 ////////////////////////////////////////
231 // Step 3: read file parameters with jpeg_read_header()
232
233 jpeg_read_header(&cinfo, TRUE);
234
235 // We can ignore the return value from jpeg_read_header since
236 // (a) suspension is not possible with our data source, and
237 // (b) we passed TRUE to reject a tables-only JPEG file as an error.
238 // See libjpeg.doc for more info.
239
240 setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
241
242 raw_image->resize(getWidth(), getHeight(), getComponents());
243 raw_image_data = raw_image->getData();
244
245
246 ////////////////////////////////////////
247 // Step 4: set parameters for decompression
248 cinfo.out_color_components = 3;
249 cinfo.out_color_space = JCS_RGB;
250
251
252 ////////////////////////////////////////
253 // Step 5: Start decompressor
254
255 jpeg_start_decompress(&cinfo);
256 // We can ignore the return value since suspension is not possible
257 // with our data source.
258
259 // We may need to do some setup of our own at this point before reading
260 // the data. After jpeg_start_decompress() we have the correct scaled
261 // output image dimensions available, as well as the output colormap
262 // if we asked for color quantization.
263 // In this example, we need to make an output work buffer of the right size.
264
265 // JSAMPLEs per row in output buffer
266 row_stride = cinfo.output_width * cinfo.output_components;
267
268 ////////////////////////////////////////
269 // Step 6: while (scan lines remain to be read)
270 // jpeg_read_scanlines(...);
271
272 // Here we use the library's state variable cinfo.output_scanline as the
273 // loop counter, so that we don't have to keep track ourselves.
274
275 // Move pointer to last line
276 raw_image_data += row_stride * (cinfo.output_height - 1);
277
278 while (cinfo.output_scanline < cinfo.output_height)
279 {
280 // jpeg_read_scanlines expects an array of pointers to scanlines.
281 // Here the array is only one element long, but you could ask for
282 // more than one scanline at a time if that's more convenient.
283
284 jpeg_read_scanlines(&cinfo, &raw_image_data, 1);
285 raw_image_data -= row_stride; // move pointer up a line
286 }
287
288 ////////////////////////////////////////
289 // Step 7: Finish decompression
290 jpeg_finish_decompress(&cinfo);
291
292 ////////////////////////////////////////
293 // Step 8: Release JPEG decompression object
294 jpeg_destroy_decompress(&cinfo);
295 }
296
297 catch (int)
298 {
299 jpeg_destroy_decompress(&cinfo);
300 return FALSE;
301 }
302
303 // Check to see whether any corrupt-data warnings occurred
304 if( jerr.num_warnings != 0 )
305 {
306 // TODO: extract the warning to find out what went wrong.
307 setLastError( "Unable to decode JPEG image.");
308 return FALSE;
309 }
310
311 return TRUE;
312}
313
314
315// Initialize destination --- called by jpeg_start_compress before any data is actually written.
316// static
317void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
318{
319 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
320
321 cinfo->dest->next_output_byte = self->mOutputBuffer;
322 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
323}
324
325
326// Empty the output buffer --- called whenever buffer fills up.
327//
328// In typical applications, this should write the entire output buffer
329// (ignoring the current state of next_output_byte & free_in_buffer),
330// reset the pointer & count to the start of the buffer, and return TRUE
331// indicating that the buffer has been dumped.
332//
333// In applications that need to be able to suspend compression due to output
334// overrun, a FALSE return indicates that the buffer cannot be emptied now.
335// In this situation, the compressor will return to its caller (possibly with
336// an indication that it has not accepted all the supplied scanlines). The
337// application should resume compression after it has made more room in the
338// output buffer. Note that there are substantial restrictions on the use of
339// suspension --- see the documentation.
340//
341// When suspending, the compressor will back up to a convenient restart point
342// (typically the start of the current MCU). next_output_byte & free_in_buffer
343// indicate where the restart point will be if the current call returns FALSE.
344// Data beyond this point will be regenerated after resumption, so do not
345// write it out when emptying the buffer externally.
346
347boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
348{
349 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
350
351 // Should very rarely happen, since our output buffer is
352 // as large as the input to start out with.
353
354 // Double the buffer size;
355 S32 new_buffer_size = self->mOutputBufferSize * 2;
356 U8* new_buffer = new U8[ new_buffer_size ];
357 memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize );
358 delete[] self->mOutputBuffer;
359 self->mOutputBuffer = new_buffer;
360
361 cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize;
362 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
363 self->mOutputBufferSize = new_buffer_size;
364
365 return TRUE;
366}
367
368// Terminate destination --- called by jpeg_finish_compress
369// after all data has been written. Usually needs to flush buffer.
370//
371// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
372// application must deal with any cleanup that should happen even
373// for error exit.
374void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
375{
376 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
377
378 S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
379 self->allocateData(file_bytes);
380
381 memcpy( self->getData(), self->mOutputBuffer, file_bytes );
382}
383
384// static
385void LLImageJPEG::errorExit( j_common_ptr cinfo )
386{
387 //LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
388
389 // Always display the message
390 (*cinfo->err->output_message)(cinfo);
391
392 // Let the memory manager delete any temp files
393 jpeg_destroy(cinfo);
394
395 // Return control to the setjmp point
396 throw 1;
397}
398
399// Decide whether to emit a trace or warning message.
400// msg_level is one of:
401// -1: recoverable corrupt-data warning, may want to abort.
402// 0: important advisory messages (always display to user).
403// 1: first level of tracing detail.
404// 2,3,...: successively more detailed tracing messages.
405// An application might override this method if it wanted to abort on warnings
406// or change the policy about which messages to display.
407// static
408void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
409{
410 struct jpeg_error_mgr * err = cinfo->err;
411
412 if (msg_level < 0)
413 {
414 // It's a warning message. Since corrupt files may generate many warnings,
415 // the policy implemented here is to show only the first warning,
416 // unless trace_level >= 3.
417 if (err->num_warnings == 0 || err->trace_level >= 3)
418 {
419 (*err->output_message) (cinfo);
420 }
421 // Always count warnings in num_warnings.
422 err->num_warnings++;
423 }
424 else
425 {
426 // It's a trace message. Show it if trace_level >= msg_level.
427 if (err->trace_level >= msg_level)
428 {
429 (*err->output_message) (cinfo);
430 }
431 }
432}
433
434// static
435void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
436{
437 // Create the message
438 char buffer[JMSG_LENGTH_MAX];
439 (*cinfo->err->format_message) (cinfo, buffer);
440
441 ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer );
442
443 BOOL is_decode = (cinfo->is_decompressor != 0);
444 llwarns << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << llendl;
445}
446
447BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
448{
449 llassert_always(raw_image);
450
451 resetLastError();
452
453 switch( raw_image->getComponents() )
454 {
455 case 1:
456 case 3:
457 break;
458 default:
459 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
460 return FALSE;
461 }
462
463 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
464
465 // Allocate a temporary buffer big enough to hold the entire compressed image (and then some)
466 // (Note: we make it bigger in emptyOutputBuffer() if we need to)
467 delete[] mOutputBuffer;
468 mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
469 mOutputBuffer = new U8[ mOutputBufferSize ];
470
471 const U8* raw_image_data = NULL;
472 S32 row_stride = 0;
473
474 ////////////////////////////////////////
475 // Step 1: allocate and initialize JPEG compression object
476
477 // This struct contains the JPEG compression parameters and pointers to
478 // working space (which is allocated as needed by the JPEG library).
479 struct jpeg_compress_struct cinfo;
480 cinfo.client_data = this;
481
482 // We have to set up the error handler first, in case the initialization
483 // step fails. (Unlikely, but it could happen if you are out of memory.)
484 // This routine fills in the contents of struct jerr, and returns jerr's
485 // address which we place into the link field in cinfo.
486 struct jpeg_error_mgr jerr;
487 cinfo.err = jpeg_std_error(&jerr);
488
489 // Customize with our own callbacks
490 jerr.error_exit = &LLImageJPEG::errorExit; // Error exit handler: does not return to caller
491 jerr.emit_message = &LLImageJPEG::errorEmitMessage; // Conditionally emit a trace or warning message
492 jerr.output_message = &LLImageJPEG::errorOutputMessage; // Routine that actually outputs a trace or error message
493
494 // Establish the setjmp return context mSetjmpBuffer. Used by library to abort.
495 if( setjmp(mSetjmpBuffer) )
496 {
497 // If we get here, the JPEG code has signaled an error.
498 // We need to clean up the JPEG object, close the input file, and return.
499 jpeg_destroy_compress(&cinfo);
500 delete[] mOutputBuffer;
501 mOutputBuffer = NULL;
502 mOutputBufferSize = 0;
503 return FALSE;
504 }
505
506 try
507 {
508
509 // Now we can initialize the JPEG compression object.
510 jpeg_create_compress(&cinfo);
511
512 ////////////////////////////////////////
513 // Step 2: specify data destination
514 // (code is a modified form of jpeg_stdio_dest() )
515 if( cinfo.dest == NULL)
516 {
517 cinfo.dest = (struct jpeg_destination_mgr *)
518 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
519 sizeof(struct jpeg_destination_mgr));
520 }
521 cinfo.dest->next_output_byte = mOutputBuffer; // => next byte to write in buffer
522 cinfo.dest->free_in_buffer = mOutputBufferSize; // # of byte spaces remaining in buffer
523 cinfo.dest->init_destination = &LLImageJPEG::encodeInitDestination;
524 cinfo.dest->empty_output_buffer = &LLImageJPEG::encodeEmptyOutputBuffer;
525 cinfo.dest->term_destination = &LLImageJPEG::encodeTermDestination;
526
527 ////////////////////////////////////////
528 // Step 3: set parameters for compression
529 //
530 // First we supply a description of the input image.
531 // Four fields of the cinfo struct must be filled in:
532
533 cinfo.image_width = getWidth(); // image width and height, in pixels
534 cinfo.image_height = getHeight();
535
536 switch( getComponents() )
537 {
538 case 1:
539 cinfo.input_components = 1; // # of color components per pixel
540 cinfo.in_color_space = JCS_GRAYSCALE; // colorspace of input image
541 break;
542 case 3:
543 cinfo.input_components = 3; // # of color components per pixel
544 cinfo.in_color_space = JCS_RGB; // colorspace of input image
545 break;
546 default:
547 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
548 return FALSE;
549 }
550
551 // Now use the library's routine to set default compression parameters.
552 // (You must set at least cinfo.in_color_space before calling this,
553 // since the defaults depend on the source color space.)
554 jpeg_set_defaults(&cinfo);
555
556 // Now you can set any non-default parameters you wish to.
557 jpeg_set_quality(&cinfo, mEncodeQuality, TRUE ); // limit to baseline-JPEG values
558
559 ////////////////////////////////////////
560 // Step 4: Start compressor
561 //
562 // TRUE ensures that we will write a complete interchange-JPEG file.
563 // Pass TRUE unless you are very sure of what you're doing.
564
565 jpeg_start_compress(&cinfo, TRUE);
566
567 ////////////////////////////////////////
568 // Step 5: while (scan lines remain to be written)
569 // jpeg_write_scanlines(...);
570
571 // Here we use the library's state variable cinfo.next_scanline as the
572 // loop counter, so that we don't have to keep track ourselves.
573 // To keep things simple, we pass one scanline per call; you can pass
574 // more if you wish, though.
575
576 row_stride = getWidth() * getComponents(); // JSAMPLEs per row in image_buffer
577
578 // NOTE: For compatibility with LLImage, we need to invert the rows.
579 raw_image_data = raw_image->getData();
580
581 const U8* last_row_data = raw_image_data + (getHeight()-1) * row_stride;
582
583 JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
584 while (cinfo.next_scanline < cinfo.image_height)
585 {
586 // jpeg_write_scanlines expects an array of pointers to scanlines.
587 // Here the array is only one element long, but you could pass
588 // more than one scanline at a time if that's more convenient.
589
590 //Ugly const uncast here (jpeg_write_scanlines should take a const* but doesn't)
591 //row_pointer[0] = (JSAMPROW)(raw_image_data + (cinfo.next_scanline * row_stride));
592 row_pointer[0] = (JSAMPROW)(last_row_data - (cinfo.next_scanline * row_stride));
593
594 jpeg_write_scanlines(&cinfo, row_pointer, 1);
595 }
596
597 ////////////////////////////////////////
598 // Step 6: Finish compression
599 jpeg_finish_compress(&cinfo);
600
601 // After finish_compress, we can release the temp output buffer.
602 delete[] mOutputBuffer;
603 mOutputBuffer = NULL;
604 mOutputBufferSize = 0;
605
606 ////////////////////////////////////////
607 // Step 7: release JPEG compression object
608 jpeg_destroy_compress(&cinfo);
609 }
610
611 catch(int)
612 {
613 jpeg_destroy_compress(&cinfo);
614 delete[] mOutputBuffer;
615 mOutputBuffer = NULL;
616 mOutputBufferSize = 0;
617 return FALSE;
618 }
619
620 return TRUE;
621}