From 59b844347c19c143e965ac767dc928a98c97fb17 Mon Sep 17 00:00:00 2001 From: Matthieu Darbois Date: Mon, 22 Dec 2014 15:50:32 +0000 Subject: [PATCH] [trunk] fixed component precision upscaling in opj_decompress (fixes issue 458) --- src/bin/jp2/convert.c | 52 ++++++++++++++----------- tests/nonregression/md5refs.txt | 4 ++ tests/nonregression/test_suite.ctest.in | 3 ++ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/bin/jp2/convert.c b/src/bin/jp2/convert.c index d56f3904..7f4593b0 100644 --- a/src/bin/jp2/convert.c +++ b/src/bin/jp2/convert.c @@ -102,43 +102,51 @@ void clip_component(opj_image_comp_t* component, OPJ_UINT32 precision) } /* Component precision scaling */ +static void scale_component_up(opj_image_comp_t* component, OPJ_UINT32 precision) +{ + OPJ_SIZE_T i, len; + + len = (OPJ_SIZE_T)component->w * (OPJ_SIZE_T)component->h; + if (component->sgnd) { + OPJ_INT64 newMax = (1U << (precision - 1)); + OPJ_INT64 oldMax = (1U << (component->prec - 1)); + OPJ_INT32* l_data = component->data; + for (i = 0; i < len; ++i) { + l_data[i] = (OPJ_INT32)(((OPJ_INT64)l_data[i] * newMax) / oldMax); + } + } else { + OPJ_UINT64 newMax = (1U << precision) - 1U; + OPJ_UINT64 oldMax = (1U << component->prec) - 1U; + OPJ_UINT32* l_data = (OPJ_UINT32*)component->data; + for (i = 0; i < len; ++i) { + l_data[i] = (OPJ_UINT32)(((OPJ_UINT64)l_data[i] * newMax) / oldMax); + } + } + component->prec = precision; +} void scale_component(opj_image_comp_t* component, OPJ_UINT32 precision) { int shift; - OPJ_SIZE_T i; - OPJ_SIZE_T len; + OPJ_SIZE_T i, len; if (component->prec == precision) { return; } if (component->prec < precision) { - shift = (int)(precision - component->prec); - } else { - shift = (int)(component->prec - precision); + scale_component_up(component, precision); + return; } + shift = (int)(component->prec - precision); len = (OPJ_SIZE_T)component->w * (OPJ_SIZE_T)component->h; - if (component->sgnd) { OPJ_INT32* l_data = component->data; - if (component->prec < precision) { - for (i = 0; i < len; ++i) { - l_data[i] <<= shift; - } - } else { - for (i = 0; i < len; ++i) { - l_data[i] >>= shift; - } + for (i = 0; i < len; ++i) { + l_data[i] >>= shift; } } else { OPJ_UINT32* l_data = (OPJ_UINT32*)component->data; - if (component->prec < precision) { - for (i = 0; i < len; ++i) { - l_data[i] <<= shift; - } - } else { - for (i = 0; i < len; ++i) { - l_data[i] >>= shift; - } + for (i = 0; i < len; ++i) { + l_data[i] >>= shift; } } component->prec = precision; diff --git a/tests/nonregression/md5refs.txt b/tests/nonregression/md5refs.txt index 40043c08..eb04c0ba 100644 --- a/tests/nonregression/md5refs.txt +++ b/tests/nonregression/md5refs.txt @@ -175,3 +175,7 @@ d5ecef537edf294af83826763c0cf860 issue411-ycc422.jp2_1.pgx 07480962d25b3d8cce18096648963c8a issue411-ycc420.jp2_0.pgx 149a69831b42401f20b8f7492ef99d97 issue411-ycc420.jp2_1.pgx ec8d1c99db9763a8ba489df4f41dda53 issue411-ycc420.jp2_2.pgx +3c7ff2e4bdae849167be36589f32bcd5 issue458.jp2_0.pgx +f004b48eafb2e52529cc9c7b6a3ff5d2 issue458.jp2_1.pgx +3127bd0a591d113c3c2428c8d2c14ec8 issue458.jp2_2.pgx +dacaf60e4c430916a8c2a9ebec32e71c issue458.jp2_3.pgx diff --git a/tests/nonregression/test_suite.ctest.in b/tests/nonregression/test_suite.ctest.in index 7f5d6f08..0cd5387f 100644 --- a/tests/nonregression/test_suite.ctest.in +++ b/tests/nonregression/test_suite.ctest.in @@ -258,6 +258,9 @@ opj_decompress -i @INPUT_NR_PATH@/issue411-ycc420.jp2 -o @TEMP_PATH@/issue411-yc !opj_decompress -i @INPUT_NR_PATH@/issue427-null-image-size.jp2 -o @TEMP_PATH@/issue427-null-image-size.jp2.pgx # issue 427 illegal tile offset !opj_decompress -i @INPUT_NR_PATH@/issue427-illegal-tile-offset.jp2 -o @TEMP_PATH@/issue427-illegal-tile-offset.jp2.pgx +# issue 458 component precision upscaling +opj_decompress -i @INPUT_NR_PATH@/issue458.jp2 -o @TEMP_PATH@/issue458.jp2.pgx + # decode with specific area # prec=12; nb_c=1