summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2023-03-26 16:08:24 +0200
committerGitHub <noreply@github.com>2023-03-26 16:08:24 +0200
commit1ee6d115e80036d1d38bad7f95a680bfc612c1bf (patch)
tree7a8a61469b1c560f5a2e1a9ac99c04292f48a3d3
parent15c0dca5206d0101de2ce73b97138a2b26949011 (diff)
parent59ec1f0ae6edb19f45ab06792aa8902759af6954 (diff)
Merge pull request #1463 from rouault/fix_570
opj_jp2_read_header(): move setting color_space here instead in opj_jp2_decode()/get_tile() (fixes #570)
-rw-r--r--src/lib/openjp2/jp2.c140
-rw-r--r--tests/unit/CMakeLists.txt4
-rw-r--r--tests/unit/testjp2.c144
3 files changed, 201 insertions, 87 deletions
diff --git a/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c
index ec202272..6015190e 100644
--- a/src/lib/openjp2/jp2.c
+++ b/src/lib/openjp2/jp2.c
@@ -1594,22 +1594,10 @@ static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2,
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
- opj_stream_private_t *p_stream,
- opj_image_t* p_image,
- opj_event_mgr_t * p_manager)
+static OPJ_BOOL opj_jp2_apply_color_postprocessing(opj_jp2_t *jp2,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
{
- if (!p_image) {
- return OPJ_FALSE;
- }
-
- /* J2K decoding */
- if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Failed to decode the codestream in the JP2 file\n");
- return OPJ_FALSE;
- }
-
if (jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) {
/* Bypass all JP2 component transforms */
return OPJ_TRUE;
@@ -1620,21 +1608,6 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
return OPJ_FALSE;
}
- /* Set Image Color Space */
- if (jp2->enumcs == 16) {
- p_image->color_space = OPJ_CLRSPC_SRGB;
- } else if (jp2->enumcs == 17) {
- p_image->color_space = OPJ_CLRSPC_GRAY;
- } else if (jp2->enumcs == 18) {
- p_image->color_space = OPJ_CLRSPC_SYCC;
- } else if (jp2->enumcs == 24) {
- p_image->color_space = OPJ_CLRSPC_EYCC;
- } else if (jp2->enumcs == 12) {
- p_image->color_space = OPJ_CLRSPC_CMYK;
- } else {
- p_image->color_space = OPJ_CLRSPC_UNKNOWN;
- }
-
if (jp2->color.jp2_pclr) {
/* Part 1, I.5.3.4: Either both or none : */
if (!jp2->color.jp2_pclr->cmap) {
@@ -1650,17 +1623,30 @@ OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
if (jp2->color.jp2_cdef) {
opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager);
}
-
- if (jp2->color.icc_profile_buf) {
- p_image->icc_profile_buf = jp2->color.icc_profile_buf;
- p_image->icc_profile_len = jp2->color.icc_profile_len;
- jp2->color.icc_profile_buf = NULL;
- }
}
return OPJ_TRUE;
}
+OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
+{
+ if (!p_image) {
+ return OPJ_FALSE;
+ }
+
+ /* J2K decoding */
+ if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ return opj_jp2_apply_color_postprocessing(jp2, p_image, p_manager);
+}
+
static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
opj_stream_private_t *stream,
opj_event_mgr_t * p_manager
@@ -2843,6 +2829,8 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager
)
{
+ int ret;
+
/* preconditions */
assert(jp2 != 00);
assert(p_stream != 00);
@@ -2876,10 +2864,34 @@ OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
return OPJ_FALSE;
}
- return opj_j2k_read_header(p_stream,
- jp2->j2k,
- p_image,
- p_manager);
+ ret = opj_j2k_read_header(p_stream,
+ jp2->j2k,
+ p_image,
+ p_manager);
+
+ if (p_image && *p_image) {
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16) {
+ (*p_image)->color_space = OPJ_CLRSPC_SRGB;
+ } else if (jp2->enumcs == 17) {
+ (*p_image)->color_space = OPJ_CLRSPC_GRAY;
+ } else if (jp2->enumcs == 18) {
+ (*p_image)->color_space = OPJ_CLRSPC_SYCC;
+ } else if (jp2->enumcs == 24) {
+ (*p_image)->color_space = OPJ_CLRSPC_EYCC;
+ } else if (jp2->enumcs == 12) {
+ (*p_image)->color_space = OPJ_CLRSPC_CMYK;
+ } else {
+ (*p_image)->color_space = OPJ_CLRSPC_UNKNOWN;
+ }
+
+ if (jp2->color.icc_profile_buf) {
+ (*p_image)->icc_profile_buf = jp2->color.icc_profile_buf;
+ (*p_image)->icc_profile_len = jp2->color.icc_profile_len;
+ jp2->color.icc_profile_buf = NULL;
+ }
+ }
+ return ret;
}
static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2,
@@ -3123,53 +3135,7 @@ OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2,
return OPJ_FALSE;
}
- if (p_jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) {
- /* Bypass all JP2 component transforms */
- return OPJ_TRUE;
- }
-
- if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) {
- return OPJ_FALSE;
- }
-
- /* Set Image Color Space */
- if (p_jp2->enumcs == 16) {
- p_image->color_space = OPJ_CLRSPC_SRGB;
- } else if (p_jp2->enumcs == 17) {
- p_image->color_space = OPJ_CLRSPC_GRAY;
- } else if (p_jp2->enumcs == 18) {
- p_image->color_space = OPJ_CLRSPC_SYCC;
- } else if (p_jp2->enumcs == 24) {
- p_image->color_space = OPJ_CLRSPC_EYCC;
- } else if (p_jp2->enumcs == 12) {
- p_image->color_space = OPJ_CLRSPC_CMYK;
- } else {
- p_image->color_space = OPJ_CLRSPC_UNKNOWN;
- }
-
- if (p_jp2->color.jp2_pclr) {
- /* Part 1, I.5.3.4: Either both or none : */
- if (!p_jp2->color.jp2_pclr->cmap) {
- opj_jp2_free_pclr(&(p_jp2->color));
- } else {
- if (!opj_jp2_apply_pclr(p_image, &(p_jp2->color), p_manager)) {
- return OPJ_FALSE;
- }
- }
- }
-
- /* Apply the color space if needed */
- if (p_jp2->color.jp2_cdef) {
- opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager);
- }
-
- if (p_jp2->color.icc_profile_buf) {
- p_image->icc_profile_buf = p_jp2->color.icc_profile_buf;
- p_image->icc_profile_len = p_jp2->color.icc_profile_len;
- p_jp2->color.icc_profile_buf = NULL;
- }
-
- return OPJ_TRUE;
+ return opj_jp2_apply_color_postprocessing(p_jp2, p_image, p_manager);
}
/* ----------------------------------------------------------------------- */
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 772b1a30..652643e6 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -15,3 +15,7 @@ foreach(ut ${unit_test})
target_link_libraries(${ut} openjp2)
add_test(NAME ${ut} COMMAND ${ut})
endforeach()
+
+add_executable(testjp2 testjp2.c)
+target_link_libraries(testjp2 openjp2)
+add_test(NAME testjp2 COMMAND testjp2 ${OPJ_DATA_ROOT})
diff --git a/tests/unit/testjp2.c b/tests/unit/testjp2.c
new file mode 100644
index 00000000..0e7a85b3
--- /dev/null
+++ b/tests/unit/testjp2.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2023, Even Rouault
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+
+#include "openjpeg.h"
+
+static void test_colorspace(const char* pszDirectory)
+{
+ char szFile[2048];
+ opj_image_t* image = NULL;
+ opj_stream_t *l_stream = NULL; /* Stream */
+ opj_codec_t* l_codec = NULL; /* Handle to a decompressor */
+ opj_dparameters_t parameters; /* decompression parameters */
+
+ snprintf(szFile, sizeof(szFile), "%s/input/conformance/file1.jp2",
+ pszDirectory);
+ l_stream = opj_stream_create_default_file_stream(szFile, 1);
+ if (!l_stream) {
+ fprintf(stderr, "ERROR -> failed to create the stream from the file %s\n",
+ szFile);
+ exit(1);
+ }
+ l_codec = opj_create_decompress(OPJ_CODEC_JP2);
+
+ /* Setup the decoder */
+ opj_set_default_decoder_parameters(&parameters);
+ if (!opj_setup_decoder(l_codec, &parameters)) {
+ fprintf(stderr, "ERROR -> opj_decompress: failed to setup the decoder\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ exit(1);
+ }
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if (! opj_read_header(l_stream, l_codec, &image)) {
+ fprintf(stderr, "ERROR -> opj_decompress: failed to read the header\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ exit(1);
+ }
+
+ /* Check that color_space is set after opj_read_header() */
+ if (image->color_space != OPJ_CLRSPC_SRGB) {
+ fprintf(stderr, "ERROR -> image->color_space (=%d) != OPJ_CLRSPC_SRGB\n",
+ image->color_space);
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ exit(1);
+ }
+
+ opj_destroy_codec(l_codec);
+ opj_stream_destroy(l_stream);
+ opj_image_destroy(image);
+}
+
+static void test_iccprofile(const char* pszDirectory)
+{
+ char szFile[2048];
+ opj_image_t* image = NULL;
+ opj_stream_t *l_stream = NULL; /* Stream */
+ opj_codec_t* l_codec = NULL; /* Handle to a decompressor */
+ opj_dparameters_t parameters; /* decompression parameters */
+
+ snprintf(szFile, sizeof(szFile), "%s/input/nonregression/relax.jp2",
+ pszDirectory);
+ l_stream = opj_stream_create_default_file_stream(szFile, 1);
+ if (!l_stream) {
+ fprintf(stderr, "ERROR -> failed to create the stream from the file %s\n",
+ szFile);
+ exit(1);
+ }
+ l_codec = opj_create_decompress(OPJ_CODEC_JP2);
+
+ /* Setup the decoder */
+ opj_set_default_decoder_parameters(&parameters);
+ if (!opj_setup_decoder(l_codec, &parameters)) {
+ fprintf(stderr, "ERROR -> opj_decompress: failed to setup the decoder\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ exit(1);
+ }
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if (! opj_read_header(l_stream, l_codec, &image)) {
+ fprintf(stderr, "ERROR -> opj_decompress: failed to read the header\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ exit(1);
+ }
+
+ /* Check that icc_profile_len is set after opj_read_header() */
+ if (image->icc_profile_len != 278) {
+ fprintf(stderr, "ERROR -> image->icc_profile_len (=%d) != 278\n",
+ image->icc_profile_len);
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ exit(1);
+ }
+
+ opj_destroy_codec(l_codec);
+ opj_stream_destroy(l_stream);
+ opj_image_destroy(image);
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: testjp2 /path/to/opj_data_root\n");
+ exit(1);
+ }
+
+ test_colorspace(argv[1]);
+ test_iccprofile(argv[1]);
+
+ return 0;
+}