aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llimagej2coj
diff options
context:
space:
mode:
authorthickbrick2010-09-21 23:55:50 +0200
committerthickbrick2010-09-21 23:55:50 +0200
commit721c25d85b39a7b013a182cb0f60e159bfc28807 (patch)
tree3da601b337fd1629695f1c4f24c0ac2c3b574606 /linden/indra/llimagej2coj
parentDouble-click teleport: (diff)
downloadmeta-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.cpp45
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