aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimage/llimagej2c.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llimage/llimagej2c.cpp
parentREADME.txt (diff)
downloadmeta-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/llimagej2c.cpp')
-rw-r--r--linden/indra/llimage/llimagej2c.cpp402
1 files changed, 402 insertions, 0 deletions
diff --git a/linden/indra/llimage/llimagej2c.cpp b/linden/indra/llimage/llimagej2c.cpp
new file mode 100644
index 0000000..87852e7
--- /dev/null
+++ b/linden/indra/llimage/llimagej2c.cpp
@@ -0,0 +1,402 @@
1/**
2 * @file llimagej2c.cpp
3 *
4 * Copyright (c) 2001-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#include "linden_common.h"
27
28#include <apr-1/apr_pools.h>
29#include <apr-1/apr_dso.h>
30
31#include "lldir.h"
32#include "llimagej2c.h"
33#include "llmemory.h"
34
35typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
36typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
37
38//some "private static" variables so we only attempt to load
39//dynamic libaries once
40CreateLLImageJ2CFunction j2cimpl_create_func;
41DestroyLLImageJ2CFunction j2cimpl_destroy_func;
42apr_pool_t *j2cimpl_dso_memory_pool;
43apr_dso_handle_t *j2cimpl_dso_handle;
44
45//Declare the prototype for theses functions here, their functionality
46//will be implemented in other files which define a derived LLImageJ2CImpl
47//but only ONE static library which has the implementation for this
48//function should ever be included
49LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
50void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
51
52//static
53//Loads the required "create" and "destroy" functions needed
54void LLImageJ2C::openDSO()
55{
56 //attempt to load a DSO and get some functions from it
57 std::string dso_name;
58 std::string dso_path;
59
60 bool all_functions_loaded = false;
61 apr_status_t rv;
62
63#if LL_WINDOWS
64 dso_name = "llkdu.dll";
65#elif LL_DARWIN
66 dso_name = "libllkdu.dylib";
67#else
68 dso_name = "libllkdu.so";
69#endif
70
71 dso_path = gDirUtilp->findFile(dso_name,
72 gDirUtilp->getAppRODataDir(),
73 gDirUtilp->getExecutableDir());
74
75 j2cimpl_dso_handle = NULL;
76 j2cimpl_dso_memory_pool = NULL;
77
78 //attempt to load the shared library
79 apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
80 rv = apr_dso_load(&j2cimpl_dso_handle,
81 dso_path.c_str(),
82 j2cimpl_dso_memory_pool);
83
84 //now, check for success
85 if ( rv == APR_SUCCESS )
86 {
87 //found the dynamic library
88 //now we want to load the functions we're interested in
89 CreateLLImageJ2CFunction create_func = NULL;
90 DestroyLLImageJ2CFunction dest_func = NULL;
91
92 rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
93 j2cimpl_dso_handle,
94 "createLLImageJ2CKDU");
95 if ( rv == APR_SUCCESS )
96 {
97 //we've loaded the create function ok
98 //we need to delete via the DSO too
99 //so lets check for a destruction function
100 rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
101 j2cimpl_dso_handle,
102 "destroyLLImageJ2CKDU");
103 if ( rv == APR_SUCCESS )
104 {
105 //k, everything is loaded alright
106 j2cimpl_create_func = create_func;
107 j2cimpl_destroy_func = dest_func;
108 all_functions_loaded = true;
109 }
110 }
111 }
112
113 if ( !all_functions_loaded )
114 {
115 //something went wrong with the DSO or function loading..
116 //fall back onto our satefy impl creation function
117
118#if 0
119 // precious verbose debugging, sadly we can't use our
120 // 'llinfos' stream etc. this early in the initialisation seq.
121 char errbuf[256];
122 fprintf(stderr, "failed to load syms from DSO %s (%s)\n",
123 dso_name.c_str(), dso_path.c_str());
124 apr_strerror(rv, errbuf, sizeof(errbuf));
125 fprintf(stderr, "error: %d, %s\n", rv, errbuf);
126 apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
127 fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf);
128#endif
129
130 if ( j2cimpl_dso_handle )
131 {
132 apr_dso_unload(j2cimpl_dso_handle);
133 j2cimpl_dso_handle = NULL;
134 }
135
136 if ( j2cimpl_dso_memory_pool )
137 {
138 apr_pool_destroy(j2cimpl_dso_memory_pool);
139 j2cimpl_dso_memory_pool = NULL;
140 }
141 }
142}
143
144//static
145void LLImageJ2C::closeDSO()
146{
147 if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
148 if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
149}
150
151LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
152 mMaxBytes(0),
153 mRawDiscardLevel(-1),
154 mRate(0.0f)
155{
156 //We assume here that if we wanted to destory via
157 //a dynamic library that the approriate open calls were made
158 //before any calls to this constructor.
159
160 //Therefore, a NULL creation function pointer here means
161 //we either did not want to create using functions from the dynamic
162 //library or there were issues loading it, either way
163 //use our fall back
164 if ( !j2cimpl_create_func )
165 {
166 j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
167 }
168
169 mImpl = j2cimpl_create_func();
170}
171
172// virtual
173LLImageJ2C::~LLImageJ2C()
174{
175 //We assume here that if we wanted to destory via
176 //a dynamic library that the approriate open calls were made
177 //before any calls to this destructor.
178
179 //Therefore, a NULL creation function pointer here means
180 //we either did not want to destroy using functions from the dynamic
181 //library or there were issues loading it, either way
182 //use our fall back
183 if ( !j2cimpl_destroy_func )
184 {
185 j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
186 }
187
188 if ( mImpl )
189 {
190 j2cimpl_destroy_func(mImpl);
191 }
192}
193
194// virtual
195S8 LLImageJ2C::getRawDiscardLevel()
196{
197 return mRawDiscardLevel;
198}
199
200BOOL LLImageJ2C::updateData()
201{
202 resetLastError();
203
204 // Check to make sure that this instance has been initialized with data
205 if (!getData() || (getDataSize() < 16))
206 {
207 setLastError("LLImageJ2C uninitialized");
208 return FALSE;
209 }
210
211 if (!mImpl->getMetadata(*this))
212 {
213 return FALSE;
214 }
215 // SJB: override discard based on mMaxBytes elsewhere
216 S32 max_bytes = getDataSize(); // mMaxBytes ? mMaxBytes : getDataSize();
217 S32 discard = calcDiscardLevelBytes(max_bytes);
218 setDiscardLevel(discard);
219
220 return TRUE;
221}
222
223
224BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
225{
226 return decode(raw_imagep, decode_time, 0, 4);
227}
228
229
230BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
231{
232 LLMemType mt1((LLMemType::EMemType)mMemType);
233
234 resetLastError();
235
236 // Check to make sure that this instance has been initialized with data
237 if (!getData() || (getDataSize() < 16))
238 {
239 setLastError("LLImageJ2C uninitialized");
240 return FALSE;
241 }
242
243 // Update the raw discard level
244 updateRawDiscardLevel();
245
246 return mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
247}
248
249
250BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
251{
252 return encode(raw_imagep, NULL, encode_time);
253}
254
255
256BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
257{
258 LLMemType mt1((LLMemType::EMemType)mMemType);
259 return mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time);
260}
261
262//static
263S32 LLImageJ2C::calcHeaderSizeJ2C()
264{
265 return 600; //2048; // ??? hack... just needs to be >= actual header size...
266}
267
268//static
269S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate)
270{
271 if (rate <= 0.f) rate = .125f;
272 while (discard_level > 0)
273 {
274 if (w < 1 || h < 1)
275 break;
276 w >>= 1;
277 h >>= 1;
278 discard_level--;
279 }
280 S32 bytes = (S32)((F32)(w*h*comp)*rate);
281 bytes = llmax(bytes, calcHeaderSizeJ2C());
282 return bytes;
283}
284
285S32 LLImageJ2C::calcHeaderSize()
286{
287 return calcHeaderSizeJ2C();
288}
289
290S32 LLImageJ2C::calcDataSize(S32 discard_level)
291{
292 return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate);
293}
294
295S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
296{
297 llassert(bytes >= 0);
298 S32 discard_level = 0;
299 if (bytes == 0)
300 {
301 return MAX_DISCARD_LEVEL;
302 }
303 while (1)
304 {
305 S32 bytes_needed = calcDataSize(discard_level); // virtual
306 if (bytes >= bytes_needed - (bytes_needed>>2)) // For J2c, up the res at 75% of the optimal number of bytes
307 {
308 break;
309 }
310 discard_level++;
311 if (discard_level >= MAX_DISCARD_LEVEL)
312 {
313 break;
314 }
315 }
316 return discard_level;
317}
318
319void LLImageJ2C::setRate(F32 rate)
320{
321 mRate = rate;
322}
323
324void LLImageJ2C::setMaxBytes(S32 max_bytes)
325{
326 mMaxBytes = max_bytes;
327}
328// NOT USED
329// void LLImageJ2C::setReversible(const BOOL reversible)
330// {
331// mReversible = reversible;
332// }
333
334
335BOOL LLImageJ2C::loadAndValidate(const LLString &filename)
336{
337 resetLastError();
338
339 S32 file_size = 0;
340 apr_file_t* apr_file = ll_apr_file_open(filename, LL_APR_RB, &file_size);
341 if (!apr_file)
342 {
343 setLastError("Unable to open file for reading", filename);
344 return FALSE;
345 }
346 if (file_size == 0)
347 {
348 setLastError("File is empty",filename);
349 apr_file_close(apr_file);
350 return FALSE;
351 }
352
353 U8 *data = new U8[file_size];
354 apr_size_t bytes_read = file_size;
355 apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
356 if (s != APR_SUCCESS || bytes_read != file_size)
357 {
358 delete[] data;
359 setLastError("Unable to read entire file");
360 return FALSE;
361 }
362 apr_file_close(apr_file);
363
364 return validate(data, file_size);
365}
366
367
368BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
369{
370 LLMemType mt1((LLMemType::EMemType)mMemType);
371 // Taken from setData()
372
373 BOOL res = LLImageFormatted::setData(data, file_size);
374 if ( !res )
375 {
376 return FALSE;
377 }
378
379 // Check to make sure that this instance has been initialized with data
380 if (!getData() || (0 == getDataSize()))
381 {
382 setLastError("LLImageJ2C uninitialized");
383 return FALSE;
384 }
385
386 return mImpl->getMetadata(*this);
387}
388
389void LLImageJ2C::setDecodingDone(BOOL complete)
390{
391 mDecoding = FALSE;
392 mDecoded = complete;
393}
394
395void LLImageJ2C::updateRawDiscardLevel()
396{
397 mRawDiscardLevel = mMaxBytes ? calcDiscardLevelBytes(mMaxBytes) : mDiscardLevel;
398}
399
400LLImageJ2CImpl::~LLImageJ2CImpl()
401{
402}