diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llimage/llimagejpeg.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 621 |
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 | |||
34 | LLImageJPEG::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 | |||
43 | LLImageJPEG::~LLImageJPEG() | ||
44 | { | ||
45 | llassert( !mOutputBuffer ); // Should already be deleted at end of encode. | ||
46 | delete[] mOutputBuffer; | ||
47 | } | ||
48 | |||
49 | BOOL 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. | ||
135 | void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo ) | ||
136 | { | ||
137 | // no work necessary here | ||
138 | } | ||
139 | |||
140 | // Fill the input buffer --- called whenever buffer is emptied. | ||
141 | boolean 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. | ||
161 | void 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 | |||
170 | void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo) | ||
171 | { | ||
172 | // no work necessary here | ||
173 | } | ||
174 | |||
175 | |||
176 | BOOL 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 | ||
317 | void 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 | |||
347 | boolean 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. | ||
374 | void 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 | ||
385 | void 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 | ||
408 | void 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 | ||
435 | void 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 | |||
447 | BOOL 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 | } | ||