diff options
author | thickbrick | 2010-09-21 23:55:50 +0200 |
---|---|---|
committer | thickbrick | 2010-09-21 23:55:50 +0200 |
commit | 721c25d85b39a7b013a182cb0f60e159bfc28807 (patch) | |
tree | 3da601b337fd1629695f1c4f24c0ac2c3b574606 /linden/indra/llimagej2coj | |
parent | Double-click teleport: (diff) | |
download | meta-impy-721c25d85b39a7b013a182cb0f60e159bfc28807.zip meta-impy-721c25d85b39a7b013a182cb0f60e159bfc28807.tar.gz meta-impy-721c25d85b39a7b013a182cb0f60e159bfc28807.tar.bz2 meta-impy-721c25d85b39a7b013a182cb0f60e159bfc28807.tar.xz |
More sanity checks in OpenJPEG decodes for #355
Patch by Carjay McGinnis from VWR-1815. This fixes decoding
lossless and small textures where the viewer's assumption
about compressed size breaks (i.e. discard level only half
there), and also encoding small lossy textures.
This relys on a patched OpenJPEG to work
(see openjpeg_top_corner_fix.diff from VWR-1815.)
Diffstat (limited to 'linden/indra/llimagej2coj')
-rw-r--r-- | linden/indra/llimagej2coj/llimagej2coj.cpp | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/linden/indra/llimagej2coj/llimagej2coj.cpp b/linden/indra/llimagej2coj/llimagej2coj.cpp index b7a1b82..829dceb 100644 --- a/linden/indra/llimagej2coj/llimagej2coj.cpp +++ b/linden/indra/llimagej2coj/llimagej2coj.cpp | |||
@@ -152,8 +152,13 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod | |||
152 | /* open a byte stream */ | 152 | /* open a byte stream */ |
153 | cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); | 153 | cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); |
154 | 154 | ||
155 | /* decode the stream and fill the image structure */ | 155 | /* decode the stream and fill the image structure, also fill in an additional |
156 | image = opj_decode(dinfo, cio); | 156 | structure to get the decoding result. This structure is a bit unusual in that |
157 | it is not received through opj, but still has some dynamically allocated fields | ||
158 | that need to be cleared up at the end by calling a destroy function. */ | ||
159 | opj_codestream_info_t cinfo; | ||
160 | memset(&cinfo, 0, sizeof(opj_codestream_info_t)); | ||
161 | image = opj_decode_with_info(dinfo, cio, &cinfo); | ||
157 | 162 | ||
158 | /* close the byte stream */ | 163 | /* close the byte stream */ |
159 | opj_cio_close(cio); | 164 | opj_cio_close(cio); |
@@ -180,6 +185,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod | |||
180 | LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image wrong number of components: " << img_components << LL_ENDL; | 185 | LL_DEBUGS("Openjpeg") << "ERROR -> decodeImpl: failed to decode image wrong number of components: " << img_components << LL_ENDL; |
181 | if (image) | 186 | if (image) |
182 | { | 187 | { |
188 | opj_destroy_cstr_info(&cinfo); | ||
183 | opj_image_destroy(image); | 189 | opj_image_destroy(image); |
184 | } | 190 | } |
185 | 191 | ||
@@ -187,23 +193,40 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod | |||
187 | } | 193 | } |
188 | 194 | ||
189 | // sometimes we get bad data out of the cache - check to see if the decode succeeded | 195 | // 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++) | 196 | int decompdifference = 0; |
197 | if (cinfo.numdecompos) // sanity | ||
191 | { | 198 | { |
192 | if (image->comps[i].factor != base.getRawDiscardLevel()) | 199 | for (int comp = 0; comp < image->numcomps; comp++) |
200 | { /* get maximum decomposition level difference, first field is from the COD header and the second | ||
201 | is what is actually met in the codestream, NB: if everything was ok, this calculation will | ||
202 | return what was set in the cp_reduce value! */ | ||
203 | decompdifference = std::max(decompdifference, cinfo.numdecompos[comp] - image->comps[comp].resno_decoded); | ||
204 | } | ||
205 | if (decompdifference < 0) // sanity | ||
193 | { | 206 | { |
194 | // if we didn't get the discard level we're expecting, fail | 207 | decompdifference = 0; |
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 | } | 208 | } |
200 | } | 209 | } |
201 | 210 | ||
211 | |||
212 | /* if OpenJPEG failed to decode all requested decomposition levels | ||
213 | the difference will be greater than this level */ | ||
214 | if (decompdifference > base.getRawDiscardLevel()) | ||
215 | { | ||
216 | llwarns << "not enough data for requested discard level, setting mDecoding to FALSE, difference: " << (decompdifference - base.getRawDiscardLevel()) << llendl; | ||
217 | opj_destroy_cstr_info(&cinfo); | ||
218 | opj_image_destroy(image); | ||
219 | base.mDecoding = FALSE; | ||
220 | return TRUE; | ||
221 | } | ||
222 | |||
202 | if(img_components <= first_channel) | 223 | if(img_components <= first_channel) |
203 | { | 224 | { |
225 | // sanity | ||
204 | LL_DEBUGS("Openjpeg") << "trying to decode more channels than are present in image: numcomps: " << img_components << " first_channel: " << first_channel << LL_ENDL; | 226 | 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) | 227 | if (image) |
206 | { | 228 | { |
229 | opj_destroy_cstr_info(&cinfo); | ||
207 | opj_image_destroy(image); | 230 | opj_image_destroy(image); |
208 | } | 231 | } |
209 | 232 | ||
@@ -252,15 +275,17 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod | |||
252 | else // Some rare OpenJPEG versions have this bug. | 275 | else // Some rare OpenJPEG versions have this bug. |
253 | { | 276 | { |
254 | llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; | 277 | llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl; |
278 | opj_destroy_cstr_info(&cinfo); | ||
255 | opj_image_destroy(image); | 279 | opj_image_destroy(image); |
256 | 280 | ||
257 | return TRUE; // done | 281 | return TRUE; // done |
258 | } | 282 | } |
259 | } | 283 | } |
260 | 284 | ||
261 | /* free image data structure */ | 285 | /* free opj data structures */ |
262 | if (image) | 286 | if (image) |
263 | { | 287 | { |
288 | opj_destroy_cstr_info(&cinfo); | ||
264 | opj_image_destroy(image); | 289 | opj_image_destroy(image); |
265 | } | 290 | } |
266 | 291 | ||