diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llimage/llimagej2c.cpp | |
parent | README.txt (diff) | |
download | meta-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 '')
-rw-r--r-- | linden/indra/llimage/llimagej2c.cpp | 402 |
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 | |||
35 | typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)(); | ||
36 | typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*); | ||
37 | |||
38 | //some "private static" variables so we only attempt to load | ||
39 | //dynamic libaries once | ||
40 | CreateLLImageJ2CFunction j2cimpl_create_func; | ||
41 | DestroyLLImageJ2CFunction j2cimpl_destroy_func; | ||
42 | apr_pool_t *j2cimpl_dso_memory_pool; | ||
43 | apr_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 | ||
49 | LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl(); | ||
50 | void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl); | ||
51 | |||
52 | //static | ||
53 | //Loads the required "create" and "destroy" functions needed | ||
54 | void 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 | ||
145 | void 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 | |||
151 | LLImageJ2C::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 | ||
173 | LLImageJ2C::~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 | ||
195 | S8 LLImageJ2C::getRawDiscardLevel() | ||
196 | { | ||
197 | return mRawDiscardLevel; | ||
198 | } | ||
199 | |||
200 | BOOL 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 | |||
224 | BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) | ||
225 | { | ||
226 | return decode(raw_imagep, decode_time, 0, 4); | ||
227 | } | ||
228 | |||
229 | |||
230 | BOOL 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 | |||
250 | BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time) | ||
251 | { | ||
252 | return encode(raw_imagep, NULL, encode_time); | ||
253 | } | ||
254 | |||
255 | |||
256 | BOOL 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 | ||
263 | S32 LLImageJ2C::calcHeaderSizeJ2C() | ||
264 | { | ||
265 | return 600; //2048; // ??? hack... just needs to be >= actual header size... | ||
266 | } | ||
267 | |||
268 | //static | ||
269 | S32 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 | |||
285 | S32 LLImageJ2C::calcHeaderSize() | ||
286 | { | ||
287 | return calcHeaderSizeJ2C(); | ||
288 | } | ||
289 | |||
290 | S32 LLImageJ2C::calcDataSize(S32 discard_level) | ||
291 | { | ||
292 | return calcDataSizeJ2C(getWidth(), getHeight(), getComponents(), discard_level, mRate); | ||
293 | } | ||
294 | |||
295 | S32 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 | |||
319 | void LLImageJ2C::setRate(F32 rate) | ||
320 | { | ||
321 | mRate = rate; | ||
322 | } | ||
323 | |||
324 | void 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 | |||
335 | BOOL 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 | |||
368 | BOOL 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 | |||
389 | void LLImageJ2C::setDecodingDone(BOOL complete) | ||
390 | { | ||
391 | mDecoding = FALSE; | ||
392 | mDecoded = complete; | ||
393 | } | ||
394 | |||
395 | void LLImageJ2C::updateRawDiscardLevel() | ||
396 | { | ||
397 | mRawDiscardLevel = mMaxBytes ? calcDiscardLevelBytes(mMaxBytes) : mDiscardLevel; | ||
398 | } | ||
399 | |||
400 | LLImageJ2CImpl::~LLImageJ2CImpl() | ||
401 | { | ||
402 | } | ||