00001
00031 #include "linden_common.h"
00032 #include "stdtypes.h"
00033
00034 #include "llimagejpeg.h"
00035
00036 #include "llerror.h"
00037
00038 LLImageJPEG::LLImageJPEG()
00039 :
00040 LLImageFormatted(IMG_CODEC_JPEG),
00041 mOutputBuffer( NULL ),
00042 mOutputBufferSize( 0 ),
00043 mEncodeQuality( 75 )
00044 {
00045 }
00046
00047 LLImageJPEG::~LLImageJPEG()
00048 {
00049 llassert( !mOutputBuffer );
00050 delete[] mOutputBuffer;
00051 }
00052
00053 BOOL LLImageJPEG::updateData()
00054 {
00055 resetLastError();
00056
00057
00058 if (!getData() || (0 == getDataSize()))
00059 {
00060 setLastError("Uninitialized instance of LLImageJPEG");
00061 return FALSE;
00062 }
00063
00065
00066
00067
00068
00069 struct jpeg_decompress_struct cinfo;
00070 cinfo.client_data = this;
00071
00072 struct jpeg_error_mgr jerr;
00073 cinfo.err = jpeg_std_error(&jerr);
00074
00075
00076 jerr.error_exit = &LLImageJPEG::errorExit;
00077 jerr.emit_message = &LLImageJPEG::errorEmitMessage;
00078 jerr.output_message = &LLImageJPEG::errorOutputMessage;
00079
00080 try
00081 {
00082
00083 jpeg_create_decompress(&cinfo);
00084
00086
00087
00088 if (cinfo.src == NULL)
00089 {
00090 cinfo.src = (struct jpeg_source_mgr *)
00091 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00092 sizeof(struct jpeg_source_mgr));
00093 }
00094 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
00095 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
00096 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
00097 cinfo.src->resync_to_restart = jpeg_resync_to_restart;
00098 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
00099
00100 cinfo.src->bytes_in_buffer = getDataSize();
00101 cinfo.src->next_input_byte = getData();
00102
00104
00105 jpeg_read_header( &cinfo, TRUE );
00106
00107
00108 setSize(cinfo.image_width, cinfo.image_height, 3);
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 }
00124 catch (int)
00125 {
00126 jpeg_destroy_decompress(&cinfo);
00127
00128 return FALSE;
00129 }
00131
00132 jpeg_destroy_decompress(&cinfo);
00133
00134 return TRUE;
00135 }
00136
00137
00138
00139 void LLImageJPEG::decodeInitSource( j_decompress_ptr cinfo )
00140 {
00141
00142 }
00143
00144
00145 boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
00146 {
00147
00148
00149
00150
00151 ERREXIT(cinfo, JERR_INPUT_EMPTY);
00152
00153 return TRUE;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 void LLImageJPEG::decodeSkipInputData (j_decompress_ptr cinfo, long num_bytes)
00166 {
00167 jpeg_source_mgr* src = cinfo->src;
00168
00169
00170 src->next_input_byte += (size_t) num_bytes;
00171 src->bytes_in_buffer -= (size_t) num_bytes;
00172 }
00173
00174 void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
00175 {
00176
00177 }
00178
00179
00180 BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
00181 {
00182 llassert_always(raw_image);
00183
00184 resetLastError();
00185
00186
00187 if (!getData() || (0 == getDataSize()))
00188 {
00189 setLastError("LLImageJPEG trying to decode an image with no data!");
00190 return FALSE;
00191 }
00192
00193 S32 row_stride = 0;
00194 U8* raw_image_data = NULL;
00195
00197
00198
00199
00200
00201 struct jpeg_decompress_struct cinfo;
00202
00203 struct jpeg_error_mgr jerr;
00204 cinfo.err = jpeg_std_error(&jerr);
00205
00206
00207 jerr.error_exit = &LLImageJPEG::errorExit;
00208 jerr.emit_message = &LLImageJPEG::errorEmitMessage;
00209 jerr.output_message = &LLImageJPEG::errorOutputMessage;
00210
00211
00212 try
00213 {
00214
00215 jpeg_create_decompress(&cinfo);
00216
00218
00219
00220 if (cinfo.src == NULL)
00221 {
00222 cinfo.src = (struct jpeg_source_mgr *)
00223 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00224 sizeof(struct jpeg_source_mgr));
00225 }
00226 cinfo.src->init_source = &LLImageJPEG::decodeInitSource;
00227 cinfo.src->fill_input_buffer = &LLImageJPEG::decodeFillInputBuffer;
00228 cinfo.src->skip_input_data = &LLImageJPEG::decodeSkipInputData;
00229 cinfo.src->resync_to_restart = jpeg_resync_to_restart;
00230 cinfo.src->term_source = &LLImageJPEG::decodeTermSource;
00231 cinfo.src->bytes_in_buffer = getDataSize();
00232 cinfo.src->next_input_byte = getData();
00233
00235
00236
00237 jpeg_read_header(&cinfo, TRUE);
00238
00239
00240
00241
00242
00243
00244 setSize(cinfo.image_width, cinfo.image_height, 3);
00245
00246 raw_image->resize(getWidth(), getHeight(), getComponents());
00247 raw_image_data = raw_image->getData();
00248
00249
00251
00252 cinfo.out_color_components = 3;
00253 cinfo.out_color_space = JCS_RGB;
00254
00255
00257
00258
00259 jpeg_start_decompress(&cinfo);
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 row_stride = cinfo.output_width * cinfo.output_components;
00271
00273
00274
00275
00276
00277
00278
00279
00280 raw_image_data += row_stride * (cinfo.output_height - 1);
00281
00282 while (cinfo.output_scanline < cinfo.output_height)
00283 {
00284
00285
00286
00287
00288 jpeg_read_scanlines(&cinfo, &raw_image_data, 1);
00289 raw_image_data -= row_stride;
00290 }
00291
00293
00294 jpeg_finish_decompress(&cinfo);
00295
00297
00298 jpeg_destroy_decompress(&cinfo);
00299 }
00300
00301 catch (int)
00302 {
00303 jpeg_destroy_decompress(&cinfo);
00304 return FALSE;
00305 }
00306
00307
00308 if( jerr.num_warnings != 0 )
00309 {
00310
00311 setLastError( "Unable to decode JPEG image.");
00312 return FALSE;
00313 }
00314
00315 return TRUE;
00316 }
00317
00318
00319
00320
00321 void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
00322 {
00323 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00324
00325 cinfo->dest->next_output_byte = self->mOutputBuffer;
00326 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
00352 {
00353 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00354
00355
00356
00357
00358
00359 S32 new_buffer_size = self->mOutputBufferSize * 2;
00360 U8* new_buffer = new U8[ new_buffer_size ];
00361 if (!new_buffer)
00362 {
00363 llerrs << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << llendl;
00364 return FALSE;
00365 }
00366 memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize );
00367 delete[] self->mOutputBuffer;
00368 self->mOutputBuffer = new_buffer;
00369
00370 cinfo->dest->next_output_byte = self->mOutputBuffer + self->mOutputBufferSize;
00371 cinfo->dest->free_in_buffer = self->mOutputBufferSize;
00372 self->mOutputBufferSize = new_buffer_size;
00373
00374 return TRUE;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 void LLImageJPEG::encodeTermDestination( j_compress_ptr cinfo )
00384 {
00385 LLImageJPEG* self = (LLImageJPEG*) cinfo->client_data;
00386
00387 S32 file_bytes = (S32)(self->mOutputBufferSize - cinfo->dest->free_in_buffer);
00388 self->allocateData(file_bytes);
00389
00390 memcpy( self->getData(), self->mOutputBuffer, file_bytes );
00391 }
00392
00393
00394 void LLImageJPEG::errorExit( j_common_ptr cinfo )
00395 {
00396
00397
00398
00399 (*cinfo->err->output_message)(cinfo);
00400
00401
00402 jpeg_destroy(cinfo);
00403
00404
00405 throw 1;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 void LLImageJPEG::errorEmitMessage( j_common_ptr cinfo, int msg_level )
00418 {
00419 struct jpeg_error_mgr * err = cinfo->err;
00420
00421 if (msg_level < 0)
00422 {
00423
00424
00425
00426 if (err->num_warnings == 0 || err->trace_level >= 3)
00427 {
00428 (*err->output_message) (cinfo);
00429 }
00430
00431 err->num_warnings++;
00432 }
00433 else
00434 {
00435
00436 if (err->trace_level >= msg_level)
00437 {
00438 (*err->output_message) (cinfo);
00439 }
00440 }
00441 }
00442
00443
00444 void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
00445 {
00446
00447 char buffer[JMSG_LENGTH_MAX];
00448 (*cinfo->err->format_message) (cinfo, buffer);
00449
00450 ((LLImageJPEG*) cinfo->client_data)->setLastError( buffer );
00451
00452 BOOL is_decode = (cinfo->is_decompressor != 0);
00453 llwarns << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << llendl;
00454 }
00455
00456 BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
00457 {
00458 llassert_always(raw_image);
00459
00460 resetLastError();
00461
00462 switch( raw_image->getComponents() )
00463 {
00464 case 1:
00465 case 3:
00466 break;
00467 default:
00468 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
00469 return FALSE;
00470 }
00471
00472 setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
00473
00474
00475
00476 delete[] mOutputBuffer;
00477 mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
00478 mOutputBuffer = new U8[ mOutputBufferSize ];
00479
00480 const U8* raw_image_data = NULL;
00481 S32 row_stride = 0;
00482
00484
00485
00486
00487
00488 struct jpeg_compress_struct cinfo;
00489 cinfo.client_data = this;
00490
00491
00492
00493
00494
00495 struct jpeg_error_mgr jerr;
00496 cinfo.err = jpeg_std_error(&jerr);
00497
00498
00499 jerr.error_exit = &LLImageJPEG::errorExit;
00500 jerr.emit_message = &LLImageJPEG::errorEmitMessage;
00501 jerr.output_message = &LLImageJPEG::errorOutputMessage;
00502
00503
00504 if( setjmp(mSetjmpBuffer) )
00505 {
00506
00507
00508 jpeg_destroy_compress(&cinfo);
00509 delete[] mOutputBuffer;
00510 mOutputBuffer = NULL;
00511 mOutputBufferSize = 0;
00512 return FALSE;
00513 }
00514
00515 try
00516 {
00517
00518
00519 jpeg_create_compress(&cinfo);
00520
00522
00523
00524 if( cinfo.dest == NULL)
00525 {
00526 cinfo.dest = (struct jpeg_destination_mgr *)
00527 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
00528 sizeof(struct jpeg_destination_mgr));
00529 }
00530 cinfo.dest->next_output_byte = mOutputBuffer;
00531 cinfo.dest->free_in_buffer = mOutputBufferSize;
00532 cinfo.dest->init_destination = &LLImageJPEG::encodeInitDestination;
00533 cinfo.dest->empty_output_buffer = &LLImageJPEG::encodeEmptyOutputBuffer;
00534 cinfo.dest->term_destination = &LLImageJPEG::encodeTermDestination;
00535
00537
00538
00539
00540
00541
00542 cinfo.image_width = getWidth();
00543 cinfo.image_height = getHeight();
00544
00545 switch( getComponents() )
00546 {
00547 case 1:
00548 cinfo.input_components = 1;
00549 cinfo.in_color_space = JCS_GRAYSCALE;
00550 break;
00551 case 3:
00552 cinfo.input_components = 3;
00553 cinfo.in_color_space = JCS_RGB;
00554 break;
00555 default:
00556 setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
00557 return FALSE;
00558 }
00559
00560
00561
00562
00563 jpeg_set_defaults(&cinfo);
00564
00565
00566 jpeg_set_quality(&cinfo, mEncodeQuality, TRUE );
00567
00569
00570
00571
00572
00573
00574 jpeg_start_compress(&cinfo, TRUE);
00575
00577
00578
00579
00580
00581
00582
00583
00584
00585 row_stride = getWidth() * getComponents();
00586
00587
00588 raw_image_data = raw_image->getData();
00589
00590 const U8* last_row_data = raw_image_data + (getHeight()-1) * row_stride;
00591
00592 JSAMPROW row_pointer[1];
00593 while (cinfo.next_scanline < cinfo.image_height)
00594 {
00595
00596
00597
00598
00599
00600
00601 row_pointer[0] = (JSAMPROW)(last_row_data - (cinfo.next_scanline * row_stride));
00602
00603 jpeg_write_scanlines(&cinfo, row_pointer, 1);
00604 }
00605
00607
00608 jpeg_finish_compress(&cinfo);
00609
00610
00611 delete[] mOutputBuffer;
00612 mOutputBuffer = NULL;
00613 mOutputBufferSize = 0;
00614
00616
00617 jpeg_destroy_compress(&cinfo);
00618 }
00619
00620 catch(int)
00621 {
00622 jpeg_destroy_compress(&cinfo);
00623 delete[] mOutputBuffer;
00624 mOutputBuffer = NULL;
00625 mOutputBufferSize = 0;
00626 return FALSE;
00627 }
00628
00629 return TRUE;
00630 }