aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimagej2coj/llimagej2coj.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llimagej2coj/llimagej2coj.cpp')
-rw-r--r--linden/indra/llimagej2coj/llimagej2coj.cpp375
1 files changed, 375 insertions, 0 deletions
diff --git a/linden/indra/llimagej2coj/llimagej2coj.cpp b/linden/indra/llimagej2coj/llimagej2coj.cpp
new file mode 100644
index 0000000..f292da9
--- /dev/null
+++ b/linden/indra/llimagej2coj/llimagej2coj.cpp
@@ -0,0 +1,375 @@
1/**
2 * @file llimagej2coj.cpp
3 * @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG.
4 *
5 * Copyright (c) 2006-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29#include "llimagej2coj.h"
30
31#include "openjpeg/openjpeg.h"
32
33#include "lltimer.h"
34#include "llmemory.h"
35
36LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
37{
38 return new LLImageJ2COJ();
39}
40
41void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
42{
43 delete impl;
44 impl = NULL;
45}
46
47/**
48sample error callback expecting a FILE* client object
49*/
50void error_callback(const char *msg, void *client_data) {
51 FILE *stream = (FILE*)client_data;
52 fprintf(stream, "[ERROR] %s", msg);
53}
54/**
55sample warning callback expecting a FILE* client object
56*/
57void warning_callback(const char *msg, void *client_data) {
58 FILE *stream = (FILE*)client_data;
59 fprintf(stream, "[WARNING] %s", msg);
60}
61/**
62sample debug callback expecting no client object
63*/
64void info_callback(const char *msg, void *client_data) {
65 fprintf(stdout, "[INFO] %s", msg);
66}
67
68
69LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl()
70{
71}
72
73
74LLImageJ2COJ::~LLImageJ2COJ()
75{
76}
77
78
79BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
80{
81 //
82 // FIXME: Get the comment field out of the texture
83 //
84
85 LLTimer decode_timer;
86
87 opj_dparameters_t parameters; /* decompression parameters */
88 opj_event_mgr_t event_mgr; /* event manager */
89 opj_image_t *image = NULL;
90
91 opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
92 opj_cio_t *cio = NULL;
93
94
95 /* configure the event callbacks (not required) */
96 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
97 event_mgr.error_handler = error_callback;
98 event_mgr.warning_handler = warning_callback;
99 event_mgr.info_handler = info_callback;
100
101 /* set decoding parameters to default values */
102 opj_set_default_decoder_parameters(&parameters);
103
104 parameters.cp_reduce = base.getRawDiscardLevel();
105
106 /* decode the code-stream */
107 /* ---------------------- */
108
109 /* JPEG-2000 codestream */
110
111 /* get a decoder handle */
112 dinfo = opj_create_decompress(CODEC_J2K);
113
114 /* catch events using our callbacks and give a local context */
115 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
116
117 /* setup the decoder decoding parameters using user parameters */
118 opj_setup_decoder(dinfo, &parameters);
119
120 /* open a byte stream */
121 cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
122
123 /* decode the stream and fill the image structure */
124 image = opj_decode(dinfo, cio);
125 if(!image)
126 {
127 fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
128 opj_destroy_decompress(dinfo);
129 opj_cio_close(cio);
130 return 1;
131 }
132
133 /* close the byte stream */
134 opj_cio_close(cio);
135
136
137 /* free remaining structures */
138 if(dinfo) {
139 opj_destroy_decompress(dinfo);
140 }
141
142 // Copy image data into our raw image format (instead of the separate channel format
143 S32 width = 0;
144 S32 height = 0;
145
146 S32 img_components = image->numcomps;
147 S32 channels = img_components - first_channel;
148 if( channels > max_channel_count )
149 {
150 channels = max_channel_count;
151 }
152 width = image->x1 - image->x0;
153 height = image->y1 - image->y0;
154 raw_image.resize(width, height, channels);
155 U8 *rawp = raw_image.getData();
156
157 for (S32 comp = first_channel; comp < first_channel + channels; comp++)
158 {
159 S32 offset = comp;
160 for (S32 y = (height - 1); y >= 0; y--)
161 {
162 for (S32 x = 0; x < width; x++)
163 {
164 rawp[offset] = image->comps[comp].data[y*width + x];
165 offset += channels;
166 }
167 }
168 }
169
170 /* free image data structure */
171 opj_image_destroy(image);
172
173 base.setDecodingDone();
174 return TRUE;
175}
176
177
178BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time)
179{
180 const S32 MAX_COMPS = 5;
181 opj_cparameters_t parameters; /* compression parameters */
182 opj_event_mgr_t event_mgr; /* event manager */
183
184
185 /*
186 configure the event callbacks (not required)
187 setting of each callback is optional
188 */
189 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
190 event_mgr.error_handler = error_callback;
191 event_mgr.warning_handler = warning_callback;
192 event_mgr.info_handler = info_callback;
193
194 /* set encoding parameters to default values */
195 opj_set_default_encoder_parameters(&parameters);
196 parameters.tcp_rates[0] = 0;
197 parameters.tcp_numlayers++;
198 parameters.cp_disto_alloc = 1;
199 parameters.cod_format = 0;
200 if (!comment_text)
201 {
202 parameters.cp_comment = "";
203 }
204 else
205 {
206 // Awful hacky cast, too lazy to copy right now.
207 parameters.cp_comment = (char *)comment_text;
208 }
209
210 //
211 // Fill in the source image from our raw image
212 //
213 OPJ_COLOR_SPACE color_space = CLRSPC_SRGB;
214 opj_image_cmptparm_t cmptparm[MAX_COMPS];
215 opj_image_t * image = NULL;
216 S32 numcomps = raw_image.getComponents();
217 S32 width = raw_image.getWidth();
218 S32 height = raw_image.getHeight();
219
220 memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t));
221 for(S32 c = 0; c < numcomps; c++) {
222 cmptparm[c].prec = 8;
223 cmptparm[c].bpp = 8;
224 cmptparm[c].sgnd = 0;
225 cmptparm[c].dx = parameters.subsampling_dx;
226 cmptparm[c].dy = parameters.subsampling_dy;
227 cmptparm[c].w = width;
228 cmptparm[c].h = height;
229 }
230
231 /* create the image */
232 image = opj_image_create(numcomps, &cmptparm[0], color_space);
233
234 image->x1 = width;
235 image->y1 = height;
236
237 S32 i = 0;
238 const U8 *src_datap = raw_image.getData();
239 for (S32 y = height - 1; y >= 0; y--)
240 {
241 for (S32 x = 0; x < width; x++)
242 {
243 const U8 *pixel = src_datap + (y*width + x) * numcomps;
244 for (S32 c = 0; c < numcomps; c++)
245 {
246 image->comps[c].data[i] = *pixel;
247 pixel++;
248 }
249 i++;
250 }
251 }
252
253
254
255 /* encode the destination image */
256 /* ---------------------------- */
257
258 int codestream_length;
259 opj_cio_t *cio = NULL;
260
261 /* get a J2K compressor handle */
262 opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
263
264 /* catch events using our callbacks and give a local context */
265 opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
266
267 /* setup the encoder parameters using the current image and using user parameters */
268 opj_setup_encoder(cinfo, &parameters, image);
269
270 /* open a byte stream for writing */
271 /* allocate memory for all tiles */
272 cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
273
274 /* encode the image */
275 bool bSuccess = opj_encode(cinfo, cio, image, parameters.index);
276 if (!bSuccess) {
277 opj_cio_close(cio);
278 fprintf(stderr, "failed to encode image\n");
279 return FALSE;
280 }
281 codestream_length = cio_tell(cio);
282
283 base.copyData(cio->buffer, codestream_length);
284
285 /* close and free the byte stream */
286 opj_cio_close(cio);
287
288 /* free remaining compression structures */
289 opj_destroy_compress(cinfo);
290
291
292 /* free user parameters structure */
293 if(parameters.cp_matrice) free(parameters.cp_matrice);
294
295 /* free image data */
296 opj_image_destroy(image);
297 return TRUE;
298}
299
300BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
301{
302 //
303 // FIXME: We get metadata by decoding the ENTIRE image.
304 //
305
306 // Update the raw discard level
307 base.updateRawDiscardLevel();
308
309 opj_dparameters_t parameters; /* decompression parameters */
310 opj_event_mgr_t event_mgr; /* event manager */
311 opj_image_t *image = NULL;
312
313 opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
314 opj_cio_t *cio = NULL;
315
316
317 /* configure the event callbacks (not required) */
318 memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
319 event_mgr.error_handler = error_callback;
320 event_mgr.warning_handler = warning_callback;
321 event_mgr.info_handler = info_callback;
322
323 /* set decoding parameters to default values */
324 opj_set_default_decoder_parameters(&parameters);
325
326 //parameters.cp_reduce = mRawDiscardLevel;
327
328 /* decode the code-stream */
329 /* ---------------------- */
330
331 /* JPEG-2000 codestream */
332
333 /* get a decoder handle */
334 dinfo = opj_create_decompress(CODEC_J2K);
335
336 /* catch events using our callbacks and give a local context */
337 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
338
339 /* setup the decoder decoding parameters using user parameters */
340 opj_setup_decoder(dinfo, &parameters);
341
342 /* open a byte stream */
343 cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
344
345 /* decode the stream and fill the image structure */
346 image = opj_decode(dinfo, cio);
347 if(!image)
348 {
349 fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
350 opj_destroy_decompress(dinfo);
351 opj_cio_close(cio);
352 return 1;
353 }
354
355 /* close the byte stream */
356 opj_cio_close(cio);
357
358
359 /* free remaining structures */
360 if(dinfo) {
361 opj_destroy_decompress(dinfo);
362 }
363
364 // Copy image data into our raw image format (instead of the separate channel format
365 S32 width = 0;
366 S32 height = 0;
367
368 S32 img_components = image->numcomps;
369 width = image->x1 - image->x0;
370 height = image->y1 - image->y0;
371 base.setSize(width, height, img_components);
372
373 /* free image data structure */
374 opj_image_destroy(image); return TRUE;
375}