/linden/indra/llimagej2coj/llimagej2coj.cpp
C++ | 492 lines | 281 code | 94 blank | 117 comment | 31 complexity | f9eb540cb618984bae0a8fe63fa48265 MD5 | raw file
1/**
2 * @file llimagej2coj.cpp
3 * @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG.
4 *
5 * $LicenseInfo:firstyear=2006&license=viewergpl$
6 *
7 * Copyright (c) 2006-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34#include "llimagej2coj.h"
35
36// this is defined so that we get static linking.
37#include "openjpeg.h"
38
39#include "lltimer.h"
40#include "llmemory.h"
41
42const char* fallbackEngineInfoLLImageJ2CImpl()
43{
44 static std::string version_string =
45 std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
46 + opj_version();
47 return version_string.c_str();
48}
49
50LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
51{
52 return new LLImageJ2COJ();
53}
54
55void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
56{
57 delete impl;
58 impl = NULL;
59}
60
61// Return string from message, eliminating final \n if present
62static std::string chomp(const char* msg)
63{
64 // stomp trailing \n
65 std::string message = msg;
66 if (!message.empty())
67 {
68 size_t last = message.size() - 1;
69 if (message[last] == '\n')
70 {
71 message.resize( last );
72 }
73 }
74 return message;
75}
76
77/**
78sample error callback expecting a LLFILE* client object
79*/
80void error_callback(const char* msg, void*)
81{
82 lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
83}
84/**
85sample warning callback expecting a LLFILE* client object
86*/
87void warning_callback(const char* msg, void*)
88{
89 lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
90}
91/**
92sample debug callback expecting no client object
93*/
94void info_callback(const char* msg, void*)
95{
96 lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
97}
98
99
100LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl()
101{
102 mRawImagep=NULL;
103}
104
105
106LLImageJ2COJ::~LLImageJ2COJ()
107{
108}
109
110
111BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
112{
113 //
114 // FIXME: Get the comment field out of the texture
115 //
116
117 LLTimer decode_timer;
118
119 opj_dparameters_t parameters; /* decompression parameters */
120 opj_event_mgr_t event_mgr; /* event manager */
121 opj_image_t *image = NULL;
122
123 opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
124 opj_cio_t *cio = NULL;
125
126
127 /* configure the event callbacks (not required) */
128 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
129 event_mgr.error_handler = error_callback;
130 event_mgr.warning_handler = warning_callback;
131 event_mgr.info_handler = info_callback;
132
133 /* set decoding parameters to default values */
134 opj_set_default_decoder_parameters(¶meters);
135
136 parameters.cp_reduce = base.getRawDiscardLevel();
137
138 /* decode the code-stream */
139 /* ---------------------- */
140
141 /* JPEG-2000 codestream */
142
143 /* get a decoder handle */
144 dinfo = opj_create_decompress(CODEC_J2K);
145
146 /* catch events using our callbacks and give a local context */
147 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
148
149 /* setup the decoder decoding parameters using user parameters */
150 opj_setup_decoder(dinfo, ¶meters);
151
152 /* open a byte stream */
153 cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
154
155 /* decode the stream and fill the image structure */
156 image = opj_decode(dinfo, cio);
157
158 /* close the byte stream */
159 opj_cio_close(cio);
160
161 /* free remaining structures */
162 if(dinfo)
163 {
164 opj_destroy_decompress(dinfo);
165 }
166
167 // The image decode failed if the return was NULL or the component
168 // count was zero. The latter is just a sanity check before we
169 // dereference the array.
170 if(!image)
171 {
172 LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image - no image" << LL_ENDL;
173 return TRUE; // done
174 }
175
176 S32 img_components = image->numcomps;
177
178 if( !img_components ) // < 1 ||img_components > 4 )
179 {
180 LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image wrong number of components: " << img_components << LL_ENDL;
181 if (image)
182 {
183 opj_image_destroy(image);
184 }
185
186 return TRUE; // done
187 }
188
189 // sometimes we get bad data out of the cache - check to see if the decode succeeded
190 for (S32 i = 0; i < img_components; i++)
191 {
192 if (image->comps[i].factor != base.getRawDiscardLevel())
193 {
194 // if we didn't get the discard level we're expecting, fail
195 if (image) //anyway somthing odd with the image, better check than crash
196 opj_image_destroy(image);
197 base.mDecoding = FALSE;
198 return TRUE;
199 }
200 }
201
202 if(img_components <= first_channel)
203 {
204 LL_DEBUGS("Openjpeg") << "trying to decode more channels than are present in image: numcomps: " << img_components << " first_channel: " << first_channel << LL_ENDL;
205 if (image)
206 {
207 opj_image_destroy(image);
208 }
209
210 return TRUE;
211 }
212
213 // Copy image data into our raw image format (instead of the separate channel format
214
215
216 S32 channels = img_components - first_channel;
217 if( channels > max_channel_count )
218 channels = max_channel_count;
219
220 // Component buffers are allocated in an image width by height buffer.
221 // The image placed in that buffer is ceil(width/2^factor) by
222 // ceil(height/2^factor) and if the factor isn't zero it will be at the
223 // top left of the buffer with black filled in the rest of the pixels.
224 // It is integer math so the formula is written in ceildivpo2.
225 // (Assuming all the components have the same width, height and
226 // factor.)
227 S32 comp_width = image->comps[0].w;
228 S32 f=image->comps[0].factor;
229 S32 width = ceildivpow2(image->x1 - image->x0, f);
230 S32 height = ceildivpow2(image->y1 - image->y0, f);
231 raw_image.resize(width, height, channels);
232 U8 *rawp = raw_image.getData();
233
234 // first_channel is what channel to start copying from
235 // dest is what channel to copy to. first_channel comes from the
236 // argument, dest always starts writing at channel zero.
237 for (S32 comp = first_channel, dest=0; comp < first_channel + channels;
238 comp++, dest++)
239 {
240 if (image->comps[comp].data)
241 {
242 S32 offset = dest;
243 for (S32 y = (height - 1); y >= 0; y--)
244 {
245 for (S32 x = 0; x < width; x++)
246 {
247 rawp[offset] = image->comps[comp].data[y*comp_width + x];
248 offset += channels;
249 }
250 }
251 }
252 else // Some rare OpenJPEG versions have this bug.
253 {
254 llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl;
255 opj_image_destroy(image);
256
257 return TRUE; // done
258 }
259 }
260
261 /* free image data structure */
262 if (image)
263 {
264 opj_image_destroy(image);
265 }
266
267 return TRUE; // done
268}
269
270
271BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
272{
273 const S32 MAX_COMPS = 5;
274 opj_cparameters_t parameters; /* compression parameters */
275 opj_event_mgr_t event_mgr; /* event manager */
276
277
278 /*
279 configure the event callbacks (not required)
280 setting of each callback is optional
281 */
282 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
283 event_mgr.error_handler = error_callback;
284 event_mgr.warning_handler = warning_callback;
285 event_mgr.info_handler = info_callback;
286
287 /* set encoding parameters to default values */
288 opj_set_default_encoder_parameters(¶meters);
289 parameters.cod_format = 0;
290 parameters.cp_disto_alloc = 1;
291
292 if (reversible)
293 {
294 parameters.tcp_numlayers = 1;
295 parameters.tcp_rates[0] = 0.0f;
296 }
297 else
298 {
299 parameters.tcp_numlayers = 5;
300 parameters.tcp_rates[0] = 1920.0f;
301 parameters.tcp_rates[1] = 480.0f;
302 parameters.tcp_rates[2] = 120.0f;
303 parameters.tcp_rates[3] = 30.0f;
304 parameters.tcp_rates[4] = 10.0f;
305 parameters.irreversible = 1;
306 if (raw_image.getComponents() >= 3)
307 {
308 parameters.tcp_mct = 1;
309 }
310 }
311
312 if (!comment_text)
313 {
314 parameters.cp_comment = (char *) "";
315 }
316 else
317 {
318 // Awful hacky cast, too lazy to copy right now.
319 parameters.cp_comment = (char *) comment_text;
320 }
321
322 //
323 // Fill in the source image from our raw image
324 //
325 OPJ_COLOR_SPACE color_space = CLRSPC_SRGB;
326 opj_image_cmptparm_t cmptparm[MAX_COMPS];
327 opj_image_t * image = NULL;
328 S32 numcomps = raw_image.getComponents();
329 S32 width = raw_image.getWidth();
330 S32 height = raw_image.getHeight();
331
332 memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t));
333 for(S32 c = 0; c < numcomps; c++) {
334 cmptparm[c].prec = 8;
335 cmptparm[c].bpp = 8;
336 cmptparm[c].sgnd = 0;
337 cmptparm[c].dx = parameters.subsampling_dx;
338 cmptparm[c].dy = parameters.subsampling_dy;
339 cmptparm[c].w = width;
340 cmptparm[c].h = height;
341 }
342
343 /* create the image */
344 image = opj_image_create(numcomps, &cmptparm[0], color_space);
345
346 image->x1 = width;
347 image->y1 = height;
348
349 S32 i = 0;
350 const U8 *src_datap = raw_image.getData();
351 for (S32 y = height - 1; y >= 0; y--)
352 {
353 for (S32 x = 0; x < width; x++)
354 {
355 const U8 *pixel = src_datap + (y*width + x) * numcomps;
356 for (S32 c = 0; c < numcomps; c++)
357 {
358 image->comps[c].data[i] = *pixel;
359 pixel++;
360 }
361 i++;
362 }
363 }
364
365
366
367 /* encode the destination image */
368 /* ---------------------------- */
369
370 int codestream_length;
371 opj_cio_t *cio = NULL;
372
373 /* get a J2K compressor handle */
374 opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
375
376 /* catch events using our callbacks and give a local context */
377 opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
378
379 /* setup the encoder parameters using the current image and using user parameters */
380 opj_setup_encoder(cinfo, ¶meters, image);
381
382 /* open a byte stream for writing */
383 /* allocate memory for all tiles */
384 cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
385
386 /* encode the image */
387 bool bSuccess = opj_encode(cinfo, cio, image, NULL);
388 if (!bSuccess)
389 {
390 opj_cio_close(cio);
391 llinfos << "Failed to encode image." << llendl;
392 return FALSE;
393 }
394 codestream_length = cio_tell(cio);
395
396 base.copyData(cio->buffer, codestream_length);
397 base.updateData(); // set width, height
398
399 /* close and free the byte stream */
400 opj_cio_close(cio);
401
402 /* free remaining compression structures */
403 opj_destroy_compress(cinfo);
404
405
406 /* free user parameters structure */
407 if(parameters.cp_matrice) free(parameters.cp_matrice);
408
409 /* free image data */
410 opj_image_destroy(image);
411 return TRUE;
412}
413
414BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
415{
416 //
417 // FIXME: We get metadata by decoding the ENTIRE image.
418 //
419
420 // Update the raw discard level
421 base.updateRawDiscardLevel();
422
423 opj_dparameters_t parameters; /* decompression parameters */
424 opj_event_mgr_t event_mgr; /* event manager */
425 opj_image_t *image = NULL;
426
427 opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
428 opj_cio_t *cio = NULL;
429
430
431 /* configure the event callbacks (not required) */
432 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
433 event_mgr.error_handler = error_callback;
434 event_mgr.warning_handler = warning_callback;
435 event_mgr.info_handler = info_callback;
436
437 /* set decoding parameters to default values */
438 opj_set_default_decoder_parameters(¶meters);
439
440 // Only decode what's required to get the size data.
441 parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER;
442
443 //parameters.cp_reduce = mRawDiscardLevel;
444
445 /* decode the code-stream */
446 /* ---------------------- */
447
448 /* JPEG-2000 codestream */
449
450 /* get a decoder handle */
451 dinfo = opj_create_decompress(CODEC_J2K);
452
453 /* catch events using our callbacks and give a local context */
454 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
455
456 /* setup the decoder decoding parameters using user parameters */
457 opj_setup_decoder(dinfo, ¶meters);
458
459 /* open a byte stream */
460 cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
461
462 /* decode the stream and fill the image structure */
463 image = opj_decode(dinfo, cio);
464
465 /* close the byte stream */
466 opj_cio_close(cio);
467
468 /* free remaining structures */
469 if(dinfo)
470 {
471 opj_destroy_decompress(dinfo);
472 }
473
474 if(!image)
475 {
476 llwarns << "ERROR -> getMetadata: failed to decode image!" << llendl;
477 return FALSE;
478 }
479
480 // Copy image data into our raw image format (instead of the separate channel format
481 S32 width = 0;
482 S32 height = 0;
483
484 S32 img_components = image->numcomps;
485 width = image->x1 - image->x0;
486 height = image->y1 - image->y0;
487 base.setSize(width, height, img_components);
488
489 /* free image data structure */
490 opj_image_destroy(image);
491 return TRUE;
492}