PageRenderTime 233ms CodeModel.GetById 88ms app.highlight 119ms RepoModel.GetById 10ms app.codeStats 0ms

/linden/indra/llimagej2coj/llimagej2coj.cpp

https://github.com/TechyeFox/imprudence
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(&parameters);
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, &parameters);
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(&parameters);
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, &parameters, 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(&parameters);
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, &parameters);
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}