Upgrade OpenJPEG to 2.5.2
- Update opj_config*. (Forgot to do that in the 2.5.0 update)
- Regenerate patches that no longer apply cleanly.
- Remove patches that have been applied upstream.
Bug: 342451731
Change-Id: I4fb45b5030648db7a7901f6ec345a030d5890041
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119757
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/third_party/libopenjpeg/0005-jp2_apply_pclr.patch b/third_party/libopenjpeg/0005-jp2_apply_pclr.patch
index 85e0698..d8a6fb4 100644
--- a/third_party/libopenjpeg/0005-jp2_apply_pclr.patch
+++ b/third_party/libopenjpeg/0005-jp2_apply_pclr.patch
@@ -13,15 +13,6 @@
}
/* Palette mapping: */
-@@ -1108,7 +1108,7 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
- pcol = cmap[i].pcol;
- src = old_comps[cmp].data;
- assert(src); /* verified above */
-- max = new_comps[pcol].w * new_comps[pcol].h;
-+ max = new_comps[i].w * new_comps[i].h;
-
- /* Direct use: */
- if (cmap[i].mtyp == 0) {
@@ -1118,8 +1118,8 @@ static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
dst[j] = src[j];
}
diff --git a/third_party/libopenjpeg/0026-use_opj_uint_ceildiv.patch b/third_party/libopenjpeg/0026-use_opj_uint_ceildiv.patch
deleted file mode 100644
index e65f4c6..0000000
--- a/third_party/libopenjpeg/0026-use_opj_uint_ceildiv.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c
-index 889c2cfc8..711dd73e8 100644
---- a/third_party/libopenjpeg/j2k.c
-+++ b/third_party/libopenjpeg/j2k.c
-@@ -2299,10 +2299,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
- }
-
- /* Compute the number of tiles */
-- l_cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->x1 - l_cp->tx0),
-- (OPJ_INT32)l_cp->tdx);
-- l_cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->y1 - l_cp->ty0),
-- (OPJ_INT32)l_cp->tdy);
-+ l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx);
-+ l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy);
-
- /* Check that the number of tiles is valid */
- if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) {
-@@ -2319,12 +2317,10 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
- (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx;
- p_j2k->m_specific_param.m_decoder.m_start_tile_y =
- (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy;
-- p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv((
-- OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0),
-- (OPJ_INT32)l_cp->tdx);
-- p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv((
-- OPJ_INT32)(p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0),
-- (OPJ_INT32)l_cp->tdy);
-+ p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(
-+ p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx);
-+ p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(
-+ p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy);
- } else {
- p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0;
- p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0;
-@@ -10035,10 +10029,8 @@ static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image,
- return OPJ_FALSE;
- }
-
-- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0,
-- (OPJ_INT32)l_img_comp->dx);
-- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0,
-- (OPJ_INT32)l_img_comp->dy);
-+ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx);
-+ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy);
- l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx);
- l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy);
-
-@@ -11950,10 +11942,8 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
-
- l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor;
-
-- l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0,
-- (OPJ_INT32)l_img_comp->dx);
-- l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0,
-- (OPJ_INT32)l_img_comp->dy);
-+ l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx);
-+ l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy);
- l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx);
- l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy);
-
-@@ -12304,10 +12294,8 @@ static void opj_get_tile_dimensions(opj_image_t * l_image,
-
- *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0);
- *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
-- *l_offset_x = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x0,
-- (OPJ_INT32)l_img_comp->dx);
-- *l_offset_y = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->y0,
-- (OPJ_INT32)l_img_comp->dy);
-+ *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx);
-+ *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy);
- *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 -
- (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx);
- *l_stride = *l_image_width - *l_width;
diff --git a/third_party/libopenjpeg/0041-remove_opj_clock.patch b/third_party/libopenjpeg/0041-remove_opj_clock.patch
index 036a3bf..a4b4b05 100644
--- a/third_party/libopenjpeg/0041-remove_opj_clock.patch
+++ b/third_party/libopenjpeg/0041-remove_opj_clock.patch
@@ -1,11 +1,11 @@
diff --git a/third_party/libopenjpeg/opj_includes.h b/third_party/libopenjpeg/opj_includes.h
-index 0a8628c96..43c00a556 100644
+index 13613ce52..34235921f 100644
--- a/third_party/libopenjpeg/opj_includes.h
+++ b/third_party/libopenjpeg/opj_includes.h
-@@ -219,7 +219,6 @@ typedef unsigned int OPJ_BITFIELD;
+@@ -220,7 +220,6 @@ typedef unsigned int OPJ_BITFIELD;
+
#define OPJ_UNUSED(x) (void)x
- #include "opj_inttypes.h"
-#include "opj_clock.h"
#include "opj_malloc.h"
#include "event.h"
diff --git a/third_party/libopenjpeg/0042-popcnt-windows-arm64.patch b/third_party/libopenjpeg/0042-popcnt-windows-arm64.patch
deleted file mode 100644
index 93606e3..0000000
--- a/third_party/libopenjpeg/0042-popcnt-windows-arm64.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 098bb874db85c185e2e3598f735fece7552e6dca Mon Sep 17 00:00:00 2001
-From: Alexander Neumann <30894796+Neumann-A@users.noreply.github.com>
-Date: Mon, 16 May 2022 23:10:26 +0200
-Subject: [PATCH] Fix windows arm builds
-
----
- src/lib/openjp2/ht_dec.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/lib/openjp2/ht_dec.c b/src/lib/openjp2/ht_dec.c
-index 1eb4d525f..e2f3afd6a 100644
---- a/src/lib/openjp2/ht_dec.c
-+++ b/src/lib/openjp2/ht_dec.c
-@@ -69,7 +69,7 @@ static OPJ_BOOL only_cleanup_pass_is_decoded = OPJ_FALSE;
- static INLINE
- OPJ_UINT32 population_count(OPJ_UINT32 val)
- {
--#ifdef OPJ_COMPILER_MSVC
-+#if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64))
- return (OPJ_UINT32)__popcnt(val);
- #elif (defined OPJ_COMPILER_GNUC)
- return (OPJ_UINT32)__builtin_popcount(val);
diff --git a/third_party/libopenjpeg/0043-mel_init.patch b/third_party/libopenjpeg/0043-mel_init.patch
deleted file mode 100644
index 7197bac..0000000
--- a/third_party/libopenjpeg/0043-mel_init.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-commit 4da04cd3e88a0280be526e16077c540a45cbbfa8
-Author: Aous Naman <aous72@yahoo.com>
-Date: Fri Aug 12 02:29:40 2022 +1000
-
- Replace the assert in mel_init to an if statement to address an issue with fuzzing. (#1436)
-
- Modified the mel_init code to replace the assert statement with an if statement, returning false when an incorrect sequence of bytes are encountered in the MEL segment. Similar code should be added to the main MEL decoding subrountine, but the change is more involved; in any case, an incorrect sequence produces incorrect results, but should not be harmful or cause a crash.
-
-diff --git a/src/lib/openjp2/ht_dec.c b/src/lib/openjp2/ht_dec.c
-index a803d1bb..62a6c9e1 100644
---- a/src/lib/openjp2/ht_dec.c
-+++ b/src/lib/openjp2/ht_dec.c
-@@ -294,7 +294,7 @@ void mel_decode(dec_mel_t *melp)
- * @param [in] scup is the length of MEL+VLC segments
- */
- static INLINE
--void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup)
-+OPJ_BOOL mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup)
- {
- int num;
- int i;
-@@ -316,7 +316,9 @@ void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup)
- OPJ_UINT64 d;
- int d_bits;
-
-- assert(melp->unstuff == OPJ_FALSE || melp->data[0] <= 0x8F);
-+ if (melp->unstuff == OPJ_TRUE && melp->data[0] > 0x8F) {
-+ return OPJ_FALSE;
-+ }
- d = (melp->size > 0) ? *melp->data : 0xFF; // if buffer is consumed
- // set data to 0xFF
- if (melp->size == 1) {
-@@ -332,6 +334,7 @@ void mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup)
- }
- melp->tmp <<= (64 - melp->bits); //push all the way up so the first bit
- // is the MSB
-+ return OPJ_TRUE;
- }
-
- //************************************************************************/
-@@ -1374,7 +1377,17 @@ OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1,
- }
-
- // init structures
-- mel_init(&mel, coded_data, lcup, scup);
-+ if (mel_init(&mel, coded_data, lcup, scup) == OPJ_FALSE) {
-+ if (p_manager_mutex) {
-+ opj_mutex_lock(p_manager_mutex);
-+ }
-+ opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. "
-+ "Incorrect MEL segment sequence.\n");
-+ if (p_manager_mutex) {
-+ opj_mutex_unlock(p_manager_mutex);
-+ }
-+ return OPJ_FALSE;
-+ }
- rev_init(&vlc, coded_data, lcup, scup);
- frwd_init(&magsgn, coded_data, lcup - scup, 0xFF);
- if (num_passes > 1) { // needs to be tested
diff --git a/third_party/libopenjpeg/0044-opj_t1_allocate_buffers.patch b/third_party/libopenjpeg/0044-opj_t1_allocate_buffers.patch
deleted file mode 100644
index 3d77b74..0000000
--- a/third_party/libopenjpeg/0044-opj_t1_allocate_buffers.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-commit 0535bfc3b7d5cd6fc73a7d4a6749a338fc5d7703
-Author: Yuan <zodf0055980@gmail.com>
-Date: Tue May 31 17:55:12 2022 +0800
-
- HT_DEC: Fix opj_t1_allocate_buffers malloc size error (#1426) (fixes #1413)
-
-diff --git a/src/lib/openjp2/ht_dec.c b/src/lib/openjp2/ht_dec.c
-index e2f3afd6..a803d1bb 100644
---- a/src/lib/openjp2/ht_dec.c
-+++ b/src/lib/openjp2/ht_dec.c
-@@ -1063,7 +1063,7 @@ static OPJ_BOOL opj_t1_allocate_buffers(
- if (flagssize > t1->flagssize) {
-
- opj_aligned_free(t1->flags);
-- t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize);
-+ t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof(opj_flag_t));
- if (!t1->flags) {
- /* FIXME event manager error callback */
- return OPJ_FALSE;
-@@ -1071,7 +1071,7 @@ static OPJ_BOOL opj_t1_allocate_buffers(
- }
- t1->flagssize = flagssize;
-
-- memset(t1->flags, 0, flagssize);
-+ memset(t1->flags, 0, flagssize * sizeof(opj_flag_t));
- }
-
- t1->w = w;
diff --git a/third_party/libopenjpeg/0045-openjp2-j2k-replace-sprintf-calls-with-snprintf.patch b/third_party/libopenjpeg/0045-openjp2-j2k-replace-sprintf-calls-with-snprintf.patch
deleted file mode 100644
index 01ef487..0000000
--- a/third_party/libopenjpeg/0045-openjp2-j2k-replace-sprintf-calls-with-snprintf.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-https://github.com/uclouvain/openjpeg/pull/1450
-https://patch-diff.githubusercontent.com/raw/uclouvain/openjpeg/pull/1450.patch
-
-From 093ccb0ecdba7d5c4b5363e7dda33b1769fcc08a Mon Sep 17 00:00:00 2001
-From: Mark Mentovai <mark@chromium.org>
-Date: Mon, 7 Nov 2022 09:32:02 -0500
-Subject: [PATCH] openjp2/j2k: replace sprintf calls with snprintf
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This makes it possible to build j2k.c without warnings using the macOS
-13 SDK. Calls to sprintf are replaced with snprintf, passing appropriate
-buffer sizes.
-
-It doesn’t appear that any of the changed uses of sprintf were actually
-unsafe, so no behavior change is expected aside from SDK compatibility.
-
-The macOS 13 SDK deprecates sprintf as it’s difficult to use safely. The
-deprecation warning message is visible when building C++, but it is not
-normally visible when building plain C code due to a quirk in how
-sprintf is declared in the SDK. However, the deprecation message is
-visible when building plain C under Address Sanitizer
-(-fsanitize=address). This discrepancy was discovered at
-https://crbug.com/1381706 and reported to Apple with a copy at
-https://openradar.appspot.com/FB11761475.
-
-The macOS 13 SDK is packaged in Xcode 14.1, released on 2022-11-01. This
-also affects the iOS 16 SDK and other 2022-era Apple OS SDKs packaged in
-Xcode 14.0, released on 2022-09-12.
-
-j2k.c is visible to the Chromium build via PDFium, and this change is
-needed to allow Chromium to move forward to the macOS 13 SDK.
-
-This change is limited to src/lib/openjp2. Other uses of sprintf were
-found throughout openjpeg.
----
- src/lib/openjp2/j2k.c | 13 ++++++++-----
- 1 file changed, 8 insertions(+), 5 deletions(-)
-
-diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
-index 923bd8916..354415df7 100644
---- a/src/lib/openjp2/j2k.c
-+++ b/src/lib/openjp2/j2k.c
-@@ -7954,21 +7954,24 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
-
- /* UniPG>> */
- #ifdef USE_JPWL
-- cp->comment = (char*)opj_malloc(clen + strlen(version) + 11);
-+ const size_t cp_comment_buf_size = clen + strlen(version) + 11;
-+ cp->comment = (char*)opj_malloc(cp_comment_buf_size);
- if (!cp->comment) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Not enough memory to allocate comment string\n");
- return OPJ_FALSE;
- }
-- sprintf(cp->comment, "%s%s with JPWL", comment, version);
-+ snprintf(cp->comment, cp_comment_buf_size, "%s%s with JPWL",
-+ comment, version);
- #else
-- cp->comment = (char*)opj_malloc(clen + strlen(version) + 1);
-+ const size_t cp_comment_buf_size = clen + strlen(version) + 1;
-+ cp->comment = (char*)opj_malloc(cp_comment_buf_size);
- if (!cp->comment) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Not enough memory to allocate comment string\n");
- return OPJ_FALSE;
- }
-- sprintf(cp->comment, "%s%s", comment, version);
-+ snprintf(cp->comment, cp_comment_buf_size, "%s%s", comment, version);
- #endif
- /* <<UniPG */
- }
-@@ -11973,7 +11976,7 @@ static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k,
- p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
- #if 0
- char fn[256];
-- sprintf(fn, "/tmp/%d.raw", compno);
-+ snprintf(fn, sizeof fn, "/tmp/%d.raw", compno);
- FILE *debug = fopen(fn, "wb");
- fwrite(p_image->comps[compno].data, sizeof(OPJ_INT32),
- p_image->comps[compno].w * p_image->comps[compno].h, debug);
diff --git a/third_party/libopenjpeg/0046-func-ptr-mixup.patch b/third_party/libopenjpeg/0046-func-ptr-mixup.patch
index f60e550..cdd2288 100644
--- a/third_party/libopenjpeg/0046-func-ptr-mixup.patch
+++ b/third_party/libopenjpeg/0046-func-ptr-mixup.patch
@@ -692,7 +692,7 @@
/* preconditions */
assert(jp2 != 00);
assert(stream != 00);
-@@ -2854,11 +2863,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box,
+@@ -2849,11 +2849,12 @@ static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box,
}
OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream,
@@ -703,9 +703,9 @@
)
{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ int ret;
+
/* preconditions */
- assert(jp2 != 00);
- assert(p_stream != 00);
@@ -2981,7 +2991,7 @@ static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2,
return OPJ_TRUE;
}
diff --git a/third_party/libopenjpeg/README.pdfium b/third_party/libopenjpeg/README.pdfium
index 638c817..edc5db9 100644
--- a/third_party/libopenjpeg/README.pdfium
+++ b/third_party/libopenjpeg/README.pdfium
@@ -1,10 +1,10 @@
Name: OpenJPEG
URL: http://www.openjpeg.org/
-Version: 2.5.0 (also update in opj_config*)
+Version: 2.5.2 (also update in opj_config*)
Security Critical: yes
Shipped: yes
License: 2-clause BSD
-CPEPrefix: cpe:/a:uclouvain:openjpeg:2.5.0
+CPEPrefix: cpe:/a:uclouvain:openjpeg:2.5.2
Description:
JPEG 2000 library.
@@ -25,13 +25,8 @@
0022-jp2_apply_pclr_overflow.patch: Prevent integer overflow in opj_jp2_apply_pclr.
0023-opj_j2k_read_mct_records.patch: Fix opj_j2k_read to prevent heap-use-after-free.
0025-opj_j2k_add_mct_null_data.patch: Check m_data != null before trying to read from it.
-0026-use_opj_uint_ceildiv.patch: Remove (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)a, (OPJ_INT32) b).
0034-opj_malloc.patch: PDFium changes in opj_malloc.
0035-opj_image_data_free.patch: Use the right free function in opj_jp2_apply_pclr.
0039-opj_mqc_renorme.patch: Remove unused opj_mqc_renorme().
0041-remove_opj_clock.patch: Remove unused opj_clock.h include.
-0042-popcnt-windows-arm64.patch: Backport to fix Windows arm64 build.
-0043-mel_init.patch: Backport fix for assertion failure in mel_init().
-0044-opj_t1_allocate_buffers.patch: Backport fix for malloc size error in opj_t1_allocate_buffers().
-0045-openjp2-j2k-replace-sprintf-calls-with-snprintf.patch: Replace sprintf with snprintf for macOS 13 SDK compatibility, from https://github.com/uclouvain/openjpeg/pull/1450.
0046-func-ptr-mixup.patch: Prevent mixing up function pointer types.
diff --git a/third_party/libopenjpeg/bio.c b/third_party/libopenjpeg/bio.c
index 09dcd7f..8106df7 100644
--- a/third_party/libopenjpeg/bio.c
+++ b/third_party/libopenjpeg/bio.c
@@ -44,12 +44,6 @@
/*@{*/
/**
-Write a bit
-@param bio BIO handle
-@param b Bit to write (0 or 1)
-*/
-static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b);
-/**
Read a bit
@param bio BIO handle
@return Returns the read bit
@@ -100,16 +94,6 @@
return OPJ_TRUE;
}
-static void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b)
-{
- if (bio->ct == 0) {
- opj_bio_byteout(
- bio); /* MSD: why not check the return value of this function ? */
- }
- bio->ct--;
- bio->buf |= b << bio->ct;
-}
-
static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio)
{
if (bio->ct == 0) {
@@ -162,6 +146,16 @@
bio->ct = 0;
}
+void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b)
+{
+ if (bio->ct == 0) {
+ opj_bio_byteout(
+ bio); /* MSD: why not check the return value of this function ? */
+ }
+ bio->ct--;
+ bio->buf |= b << bio->ct;
+}
+
void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n)
{
OPJ_INT32 i;
diff --git a/third_party/libopenjpeg/bio.h b/third_party/libopenjpeg/bio.h
index 448fdda..d482f9e 100644
--- a/third_party/libopenjpeg/bio.h
+++ b/third_party/libopenjpeg/bio.h
@@ -106,6 +106,14 @@
@param n Number of bits to write
*/
void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n);
+
+/**
+Write a bit
+@param bio BIO handle
+@param b Bit to write (0 or 1)
+*/
+void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b);
+
/**
Read bits
@param bio BIO handle
diff --git a/third_party/libopenjpeg/dwt.c b/third_party/libopenjpeg/dwt.c
index 0184aa1..b6f0e48 100644
--- a/third_party/libopenjpeg/dwt.c
+++ b/third_party/libopenjpeg/dwt.c
@@ -2088,7 +2088,9 @@
OPJ_SIZE_T h_mem_size;
int num_threads;
- if (numres == 1U) {
+ /* Not entirely sure for the return code of w == 0 which is triggered per */
+ /* https://github.com/uclouvain/openjpeg/issues/1505 */
+ if (numres == 1U || w == 0) {
return OPJ_TRUE;
}
num_threads = opj_thread_pool_get_thread_count(tp);
diff --git a/third_party/libopenjpeg/ht_dec.c b/third_party/libopenjpeg/ht_dec.c
index 62a6c9e..a554b24 100644
--- a/third_party/libopenjpeg/ht_dec.c
+++ b/third_party/libopenjpeg/ht_dec.c
@@ -55,6 +55,16 @@
#define OPJ_COMPILER_GNUC
#endif
+#if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) \
+ && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \
+ && !defined(__INTEL_COMPILER) && !defined(__clang__)
+#define MSVC_NEON_INTRINSICS
+#endif
+
+#ifdef MSVC_NEON_INTRINSICS
+#include <arm64_neon.h>
+#endif
+
//************************************************************************/
/** @brief Displays the error message for disabling the decoding of SPP and
* MRP passes
@@ -71,6 +81,9 @@
{
#if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64))
return (OPJ_UINT32)__popcnt(val);
+#elif defined(OPJ_COMPILER_MSVC) && defined(MSVC_NEON_INTRINSICS)
+ const __n64 temp = neon_cnt(__uint64ToN64_v(val));
+ return neon_addv8(temp).n8_i8[0];
#elif (defined OPJ_COMPILER_GNUC)
return (OPJ_UINT32)__builtin_popcount(val);
#else
@@ -1083,6 +1096,26 @@
return OPJ_TRUE;
}
+/**
+Decode 1 HT code-block
+@param t1 T1 handle
+@param cblk Code-block coding parameters
+@param orient
+@param roishift Region of interest shifting value
+@param cblksty Code-block style
+@param p_manager the event manager
+@param p_manager_mutex mutex for the event manager
+@param check_pterm whether PTERM correct termination should be checked
+*/
+OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1,
+ opj_tcd_cblk_dec_t* cblk,
+ OPJ_UINT32 orient,
+ OPJ_UINT32 roishift,
+ OPJ_UINT32 cblksty,
+ opj_event_mgr_t *p_manager,
+ opj_mutex_t* p_manager_mutex,
+ OPJ_BOOL check_pterm);
+
//************************************************************************/
/** @brief Decodes one codeblock, processing the cleanup, siginificance
* propagation, and magnitude refinement pass
@@ -1190,6 +1223,9 @@
/* Concatenate all chunks */
cblkdata = t1->cblkdatabuffer;
+ if (cblkdata == NULL) {
+ return OPJ_FALSE;
+ }
cblk_len = 0;
for (i = 0; i < cblk->numchunks; i++) {
memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len);
diff --git a/third_party/libopenjpeg/j2k.c b/third_party/libopenjpeg/j2k.c
index e2e0487..de10825 100644
--- a/third_party/libopenjpeg/j2k.c
+++ b/third_party/libopenjpeg/j2k.c
@@ -2352,9 +2352,11 @@
p_j2k->m_specific_param.m_decoder.m_start_tile_y =
(p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy;
p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(
- p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, l_cp->tdx);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0,
+ l_cp->tdx);
p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(
- p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, l_cp->tdy);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0,
+ l_cp->tdy);
} else {
p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0;
p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0;
@@ -3957,9 +3959,12 @@
opj_read_bytes(l_data, &l_N_ppm, 4);
l_data += 4;
l_data_size -= 4;
- l_ppm_data_size +=
- l_N_ppm; /* can't overflow, max 256 markers of max 65536 bytes, that is when PPM markers are not corrupted which is checked elsewhere */
+ if (l_ppm_data_size > UINT_MAX - l_N_ppm) {
+ opj_event_msg(p_manager, EVT_ERROR, "Too large value for Nppm\n");
+ return OPJ_FALSE;
+ }
+ l_ppm_data_size += l_N_ppm;
if (l_data_size >= l_N_ppm) {
l_data_size -= l_N_ppm;
l_data += l_N_ppm;
@@ -6729,7 +6734,7 @@
return OPJ_FALSE;
}
-static int opj_j2k_get_default_thread_count()
+static int opj_j2k_get_default_thread_count(void)
{
const char* num_threads_str = getenv("OPJ_NUM_THREADS");
int num_cpus;
@@ -7670,6 +7675,27 @@
return OPJ_FALSE;
}
+ if (parameters->cp_fixed_alloc) {
+ if (parameters->cp_matrice == NULL) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "cp_fixed_alloc set, but cp_matrice missing\n");
+ return OPJ_FALSE;
+ }
+
+ if (parameters->tcp_numlayers > J2K_TCD_MATRIX_MAX_LAYER_COUNT) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "tcp_numlayers when cp_fixed_alloc set should not exceed %d\n",
+ J2K_TCD_MATRIX_MAX_LAYER_COUNT);
+ return OPJ_FALSE;
+ }
+ if (parameters->numresolution > J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "numresolution when cp_fixed_alloc set should not exceed %d\n",
+ J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT);
+ return OPJ_FALSE;
+ }
+ }
+
j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps;
/* keep a link to cp so that we can destroy it later in j2k_destroy_compress */
@@ -7800,7 +7826,7 @@
image->comps[0].h * image->comps[0].prec) /
((double)parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 *
image->comps[0].dx * image->comps[0].dy));
- if (temp_size > INT_MAX) {
+ if (temp_size > (OPJ_FLOAT32)INT_MAX) {
parameters->max_cs_size = INT_MAX;
} else {
parameters->max_cs_size = (int) floor(temp_size);
@@ -7889,15 +7915,17 @@
cp->m_specific_param.m_enc.m_max_comp_size = (OPJ_UINT32)
parameters->max_comp_size;
cp->rsiz = parameters->rsiz;
- cp->m_specific_param.m_enc.m_disto_alloc = (OPJ_UINT32)
- parameters->cp_disto_alloc & 1u;
- cp->m_specific_param.m_enc.m_fixed_alloc = (OPJ_UINT32)
- parameters->cp_fixed_alloc & 1u;
- cp->m_specific_param.m_enc.m_fixed_quality = (OPJ_UINT32)
- parameters->cp_fixed_quality & 1u;
+ if (parameters->cp_fixed_alloc) {
+ cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = FIXED_LAYER;
+ } else if (parameters->cp_fixed_quality) {
+ cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy =
+ FIXED_DISTORTION_RATIO;
+ } else {
+ cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy =
+ RATE_DISTORTION_RATIO;
+ }
- /* mod fixed_quality */
- if (parameters->cp_fixed_alloc && parameters->cp_matrice) {
+ if (parameters->cp_fixed_alloc) {
size_t array_size = (size_t)parameters->tcp_numlayers *
(size_t)parameters->numresolution * 3 * sizeof(OPJ_INT32);
cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size);
@@ -7970,10 +7998,8 @@
opj_event_msg(p_manager, EVT_ERROR, "Invalid tile height\n");
return OPJ_FALSE;
}
- cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->x1 - cp->tx0),
- (OPJ_INT32)cp->tdx);
- cp->th = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(image->y1 - cp->ty0),
- (OPJ_INT32)cp->tdy);
+ cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx);
+ cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy);
/* Check that the number of tiles is valid */
if (cp->tw > 65535 / cp->th) {
opj_event_msg(p_manager, EVT_ERROR,
@@ -8058,22 +8084,25 @@
for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
opj_tcp_t *tcp = &cp->tcps[tileno];
+ const OPJ_BOOL fixed_distoratio =
+ cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO;
tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers;
for (j = 0; j < tcp->numlayers; j++) {
if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) {
- if (cp->m_specific_param.m_enc.m_fixed_quality) {
+ if (fixed_distoratio) {
tcp->distoratio[j] = parameters->tcp_distoratio[j];
}
tcp->rates[j] = parameters->tcp_rates[j];
} else {
- if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */
+ if (fixed_distoratio) {
tcp->distoratio[j] = parameters->tcp_distoratio[j];
} else {
tcp->rates[j] = parameters->tcp_rates[j];
}
}
- if (!cp->m_specific_param.m_enc.m_fixed_quality &&
+ if (!fixed_distoratio &&
tcp->rates[j] <= 1.0) {
tcp->rates[j] = 0.0; /* force lossless */
}
@@ -10383,8 +10412,8 @@
p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw;
p_image->x1 = l_image->x1;
} else {
- p_j2k->m_specific_param.m_decoder.m_end_tile_x = (OPJ_UINT32)opj_int_ceildiv(
- p_end_x - (OPJ_INT32)l_cp->tx0, (OPJ_INT32)l_cp->tdx);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv((
+ OPJ_UINT32)p_end_x - l_cp->tx0, l_cp->tdx);
p_image->x1 = (OPJ_UINT32)p_end_x;
}
@@ -10407,8 +10436,8 @@
p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th;
p_image->y1 = l_image->y1;
} else {
- p_j2k->m_specific_param.m_decoder.m_end_tile_y = (OPJ_UINT32)opj_int_ceildiv(
- p_end_y - (OPJ_INT32)l_cp->ty0, (OPJ_INT32)l_cp->tdy);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv((
+ OPJ_UINT32)p_end_y - l_cp->ty0, l_cp->tdy);
p_image->y1 = (OPJ_UINT32)p_end_y;
}
/* ----- */
@@ -11101,6 +11130,10 @@
l_tccp->stepsizes[l_band_no].mant = 0;
}
}
+
+ if (*p_header_size < l_num_band) {
+ return OPJ_FALSE;
+ }
*p_header_size = *p_header_size - l_num_band;
} else {
for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) {
@@ -11111,6 +11144,10 @@
l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff;
}
}
+
+ if (*p_header_size < 2 * l_num_band) {
+ return OPJ_FALSE;
+ }
*p_header_size = *p_header_size - 2 * l_num_band;
}
@@ -11339,9 +11376,12 @@
fprintf(out_stream, "Codestream info from main header: {\n");
- fprintf(out_stream, "\t tx0=%d, ty0=%d\n", p_j2k->m_cp.tx0, p_j2k->m_cp.ty0);
- fprintf(out_stream, "\t tdx=%d, tdy=%d\n", p_j2k->m_cp.tdx, p_j2k->m_cp.tdy);
- fprintf(out_stream, "\t tw=%d, th=%d\n", p_j2k->m_cp.tw, p_j2k->m_cp.th);
+ fprintf(out_stream, "\t tx0=%" PRIu32 ", ty0=%" PRIu32 "\n", p_j2k->m_cp.tx0,
+ p_j2k->m_cp.ty0);
+ fprintf(out_stream, "\t tdx=%" PRIu32 ", tdy=%" PRIu32 "\n", p_j2k->m_cp.tdx,
+ p_j2k->m_cp.tdy);
+ fprintf(out_stream, "\t tw=%" PRIu32 ", th=%" PRIu32 "\n", p_j2k->m_cp.tw,
+ p_j2k->m_cp.th);
opj_j2k_dump_tile_info(p_j2k->m_specific_param.m_decoder.m_default_tcp,
(OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream);
fprintf(out_stream, "}\n");
@@ -12489,8 +12529,7 @@
*l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
*l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx);
*l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy);
- *l_image_width = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)l_image->x1 -
- (OPJ_INT32)l_image->x0, (OPJ_INT32)l_img_comp->dx);
+ *l_image_width = opj_uint_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx);
*l_stride = *l_image_width - *l_width;
*l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + ((
OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width;
diff --git a/third_party/libopenjpeg/j2k.h b/third_party/libopenjpeg/j2k.h
index 1d824c0..08dc35a 100644
--- a/third_party/libopenjpeg/j2k.h
+++ b/third_party/libopenjpeg/j2k.h
@@ -113,6 +113,9 @@
#define J2K_MAX_POCS 32 /**< Maximum number of POCs */
+#define J2K_TCD_MATRIX_MAX_LAYER_COUNT 10
+#define J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT 10
+
/* ----------------------------------------------------------------------- */
/**
@@ -272,7 +275,7 @@
OPJ_UINT32 ppt_data_size;
/** size of ppt_data*/
OPJ_UINT32 ppt_len;
- /** add fixed_quality */
+ /** PSNR values */
OPJ_FLOAT32 distoratio[100];
/** tile-component coding parameters */
opj_tccp_t *tccps;
@@ -314,6 +317,14 @@
} opj_tcp_t;
+/**
+Rate allocation strategy
+*/
+typedef enum {
+ RATE_DISTORTION_RATIO = 0, /** allocation by rate/distortion */
+ FIXED_DISTORTION_RATIO = 1, /** allocation by fixed distortion ratio (PSNR) (fixed quality) */
+ FIXED_LAYER = 2, /** allocation by fixed layer (number of passes per layer / resolution / subband) */
+} J2K_QUALITY_LAYER_ALLOCATION_STRATEGY;
typedef struct opj_encoding_param {
@@ -325,12 +336,8 @@
OPJ_INT32 *m_matrice;
/** Flag determining tile part generation*/
OPJ_BYTE m_tp_flag;
- /** allocation by rate/distortion */
- OPJ_BITFIELD m_disto_alloc : 1;
- /** allocation by fixed layer */
- OPJ_BITFIELD m_fixed_alloc : 1;
- /** add fixed_quality */
- OPJ_BITFIELD m_fixed_quality : 1;
+ /** Quality layer allocation strategy */
+ J2K_QUALITY_LAYER_ALLOCATION_STRATEGY m_quality_layer_alloc_strategy;
/** Enabling Tile part generation*/
OPJ_BITFIELD m_tp_on : 1;
}
diff --git a/third_party/libopenjpeg/jp2.c b/third_party/libopenjpeg/jp2.c
index 6db728d..d69178b 100644
--- a/third_party/libopenjpeg/jp2.c
+++ b/third_party/libopenjpeg/jp2.c
@@ -1609,23 +1609,10 @@
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_decode(void *p_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)
{
- opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
- 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;
@@ -1636,21 +1623,6 @@
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) {
@@ -1666,17 +1638,31 @@
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(void *p_jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
+{
+ opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ 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
@@ -2869,6 +2855,8 @@
)
{
opj_jp2_t *jp2 = (opj_jp2_t*)p_jp2;
+ int ret;
+
/* preconditions */
assert(jp2 != 00);
assert(p_stream != 00);
@@ -2902,10 +2890,34 @@
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,
@@ -3156,53 +3168,7 @@
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/third_party/libopenjpeg/openjpeg.c b/third_party/libopenjpeg/openjpeg.c
index 9dd4256..b8a4bfb 100644
--- a/third_party/libopenjpeg/openjpeg.c
+++ b/third_party/libopenjpeg/openjpeg.c
@@ -144,6 +144,11 @@
/* ---------------------------------------------------------------------- */
#ifdef _WIN32
#ifndef OPJ_STATIC
+
+/* declaration to avoid warning: no previous prototype for 'DllMain' */
+BOOL APIENTRY
+DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
+
BOOL APIENTRY
DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
@@ -358,7 +363,7 @@
return OPJ_FALSE;
}
-OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec,
+OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec,
OPJ_BOOL strict)
{
if (p_codec) {
diff --git a/third_party/libopenjpeg/openjpeg.h b/third_party/libopenjpeg/openjpeg.h
index ebce53d..67d168b 100644
--- a/third_party/libopenjpeg/openjpeg.h
+++ b/third_party/libopenjpeg/openjpeg.h
@@ -122,7 +122,7 @@
typedef double OPJ_FLOAT64;
typedef unsigned char OPJ_BYTE;
-#include "opj_stdint.h"
+#include <stdint.h>
typedef int8_t OPJ_INT8;
typedef uint8_t OPJ_UINT8;
@@ -138,6 +138,8 @@
#include <stdio.h>
typedef size_t OPJ_SIZE_T;
+#include "opj_config.h"
+
/* Avoid compile-time warning because parameter is not used */
#define OPJ_ARG_NOT_USED(x) (void)(x)
@@ -405,7 +407,7 @@
int cp_disto_alloc;
/** allocation by fixed layer */
int cp_fixed_alloc;
- /** add fixed_quality */
+ /** allocation by fixed quality (PSNR) */
int cp_fixed_quality;
/** fixed layer */
int *cp_matrice;
@@ -829,9 +831,9 @@
int pdy[33];
/** information concerning packets inside tile */
opj_packet_info_t *packet;
- /** add fixed_quality */
+ /** number of pixels of the tile */
int numpix;
- /** add fixed_quality */
+ /** distortion of the tile */
double distotile;
/** number of markers */
int marknum;
diff --git a/third_party/libopenjpeg/opj_config.h b/third_party/libopenjpeg/opj_config.h
index 794c926..b0c616f 100644
--- a/third_party/libopenjpeg/opj_config.h
+++ b/third_party/libopenjpeg/opj_config.h
@@ -12,5 +12,5 @@
/* Version number. */
#define OPJ_VERSION_MAJOR 2
-#define OPJ_VERSION_MINOR 4
-#define OPJ_VERSION_BUILD 0
+#define OPJ_VERSION_MINOR 5
+#define OPJ_VERSION_BUILD 2
diff --git a/third_party/libopenjpeg/opj_config_private.h b/third_party/libopenjpeg/opj_config_private.h
index 1964577..85a2969 100644
--- a/third_party/libopenjpeg/opj_config_private.h
+++ b/third_party/libopenjpeg/opj_config_private.h
@@ -7,7 +7,7 @@
/* create opj_config_private.h for CMake */
#define OPJ_HAVE_INTTYPES_H 1
-#define OPJ_PACKAGE_VERSION "2.4.0"
+#define OPJ_PACKAGE_VERSION "2.5.2"
/* Not used by openjp2*/
/*#define HAVE_MEMORY_H 1*/
diff --git a/third_party/libopenjpeg/opj_includes.h b/third_party/libopenjpeg/opj_includes.h
index 43c00a5..3423592 100644
--- a/third_party/libopenjpeg/opj_includes.h
+++ b/third_party/libopenjpeg/opj_includes.h
@@ -55,6 +55,8 @@
#include <ctype.h>
#include <assert.h>
#include <limits.h>
+#include <stdint.h>
+#include <inttypes.h>
/*
Use fseeko() and ftello() if they are available since they use
@@ -218,7 +220,6 @@
#define OPJ_UNUSED(x) (void)x
-#include "opj_inttypes.h"
#include "opj_malloc.h"
#include "event.h"
#include "function_list.h"
diff --git a/third_party/libopenjpeg/opj_intmath.h b/third_party/libopenjpeg/opj_intmath.h
index 1b0c9d0..cce7a3c 100644
--- a/third_party/libopenjpeg/opj_intmath.h
+++ b/third_party/libopenjpeg/opj_intmath.h
@@ -174,6 +174,17 @@
}
/**
+Divide an integer and round upwards
+@return Returns a divided by b
+*/
+static INLINE OPJ_UINT32 opj_uint64_ceildiv_res_uint32(OPJ_UINT64 a,
+ OPJ_UINT64 b)
+{
+ assert(b);
+ return (OPJ_UINT32)((a + b - 1) / b);
+}
+
+/**
Divide an integer by a power of 2 and round upwards
@return Returns a divided by 2^b
*/
diff --git a/third_party/libopenjpeg/pi.c b/third_party/libopenjpeg/pi.c
index ce86dcc..ad96f47 100644
--- a/third_party/libopenjpeg/pi.c
+++ b/third_party/libopenjpeg/pi.c
@@ -411,41 +411,37 @@
}
res = &comp->resolutions[pi->resno];
levelno = comp->numresolutions - 1 - pi->resno;
- /* Avoids division by zero */
- /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (levelno >= 32 ||
- ((comp->dx << levelno) >> levelno) != comp->dx ||
- ((comp->dy << levelno) >> levelno) != comp->dy) {
+
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) {
continue;
}
- if ((comp->dx << levelno) > INT_MAX ||
- (comp->dy << levelno) > INT_MAX) {
- continue;
- }
- trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno));
- try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno));
- trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno));
- try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno));
+
+ trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0,
+ ((OPJ_UINT64)comp->dy << levelno));
+ trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1,
+ ((OPJ_UINT64)comp->dy << levelno));
rpx = res->pdx + levelno;
rpy = res->pdy + levelno;
- /* To avoid divisions by zero / undefined behaviour on shift */
- /* in below tests */
- /* Fixes reading id:000026,sig:08,src:002419,op:int32,pos:60,val:+32 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
- rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
/* See ISO-15441. B.12.1.3 Resolution level-position-component-layer progression */
- if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
- ((try0 << levelno) % (1U << rpy))))) {
+ if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) ||
+ ((pi->y == pi->ty0) &&
+ (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) {
continue;
}
- if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) &&
- ((trx0 << levelno) % (1U << rpx))))) {
+ if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) ||
+ ((pi->x == pi->tx0) &&
+ (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) {
continue;
}
@@ -457,11 +453,11 @@
continue;
}
- prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x,
- (comp->dx << levelno)), res->pdx)
+ prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x,
+ ((OPJ_UINT64)comp->dx << levelno)), res->pdx)
- opj_uint_floordivpow2(trx0, res->pdx);
- prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y,
- (comp->dy << levelno)), res->pdy)
+ prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y,
+ ((OPJ_UINT64)comp->dy << levelno)), res->pdy)
- opj_uint_floordivpow2(try0, res->pdy);
pi->precno = prci + prcj * res->pw;
if (pi->precno >= res->pw * res->ph) {
@@ -552,41 +548,37 @@
OPJ_UINT32 prci, prcj;
res = &comp->resolutions[pi->resno];
levelno = comp->numresolutions - 1 - pi->resno;
- /* Avoids division by zero */
- /* Relates to id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (levelno >= 32 ||
- ((comp->dx << levelno) >> levelno) != comp->dx ||
- ((comp->dy << levelno) >> levelno) != comp->dy) {
+
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) {
continue;
}
- if ((comp->dx << levelno) > INT_MAX ||
- (comp->dy << levelno) > INT_MAX) {
- continue;
- }
- trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno));
- try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno));
- trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno));
- try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno));
+
+ trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0,
+ ((OPJ_UINT64)comp->dy << levelno));
+ trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1,
+ ((OPJ_UINT64)comp->dy << levelno));
rpx = res->pdx + levelno;
rpy = res->pdy + levelno;
- /* To avoid divisions by zero / undefined behaviour on shift */
- /* in below tests */
- /* Relates to id:000019,sig:08,src:001098,op:flip1,pos:49 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
- rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
/* See ISO-15441. B.12.1.4 Position-component-resolution level-layer progression */
- if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
- ((try0 << levelno) % (1U << rpy))))) {
+ if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) ||
+ ((pi->y == pi->ty0) &&
+ (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) {
continue;
}
- if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) &&
- ((trx0 << levelno) % (1U << rpx))))) {
+ if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) ||
+ ((pi->x == pi->tx0) &&
+ (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) {
continue;
}
@@ -598,11 +590,11 @@
continue;
}
- prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x,
- (comp->dx << levelno)), res->pdx)
+ prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x,
+ ((OPJ_UINT64)comp->dx << levelno)), res->pdx)
- opj_uint_floordivpow2(trx0, res->pdx);
- prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y,
- (comp->dy << levelno)), res->pdy)
+ prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y,
+ ((OPJ_UINT64)comp->dy << levelno)), res->pdy)
- opj_uint_floordivpow2(try0, res->pdy);
pi->precno = prci + prcj * res->pw;
if (pi->precno >= res->pw * res->ph) {
@@ -691,40 +683,37 @@
OPJ_UINT32 prci, prcj;
res = &comp->resolutions[pi->resno];
levelno = comp->numresolutions - 1 - pi->resno;
- /* Avoids division by zero on id_000004,sig_06,src_000679,op_arith8,pos_49,val_-17 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (levelno >= 32 ||
- ((comp->dx << levelno) >> levelno) != comp->dx ||
- ((comp->dy << levelno) >> levelno) != comp->dy) {
+
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) {
continue;
}
- if ((comp->dx << levelno) > INT_MAX ||
- (comp->dy << levelno) > INT_MAX) {
- continue;
- }
- trx0 = opj_uint_ceildiv(pi->tx0, (comp->dx << levelno));
- try0 = opj_uint_ceildiv(pi->ty0, (comp->dy << levelno));
- trx1 = opj_uint_ceildiv(pi->tx1, (comp->dx << levelno));
- try1 = opj_uint_ceildiv(pi->ty1, (comp->dy << levelno));
+
+ trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0,
+ ((OPJ_UINT64)comp->dy << levelno));
+ trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1,
+ ((OPJ_UINT64)comp->dx << levelno));
+ try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1,
+ ((OPJ_UINT64)comp->dy << levelno));
rpx = res->pdx + levelno;
rpy = res->pdy + levelno;
- /* To avoid divisions by zero / undefined behaviour on shift */
- /* in below tests */
- /* Fixes reading id:000019,sig:08,src:001098,op:flip1,pos:49 */
- /* of https://github.com/uclouvain/openjpeg/issues/938 */
- if (rpx >= 31 || ((comp->dx << rpx) >> rpx) != comp->dx ||
- rpy >= 31 || ((comp->dy << rpy) >> rpy) != comp->dy) {
+ if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx ||
+ (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) {
continue;
}
/* See ISO-15441. B.12.1.5 Component-position-resolution level-layer progression */
- if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) &&
- ((try0 << levelno) % (1U << rpy))))) {
+ if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) ||
+ ((pi->y == pi->ty0) &&
+ (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) {
continue;
}
- if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) &&
- ((trx0 << levelno) % (1U << rpx))))) {
+ if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) ||
+ ((pi->x == pi->tx0) &&
+ (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) {
continue;
}
@@ -736,11 +725,11 @@
continue;
}
- prci = opj_uint_floordivpow2(opj_uint_ceildiv(pi->x,
- (comp->dx << levelno)), res->pdx)
+ prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x,
+ ((OPJ_UINT64)comp->dx << levelno)), res->pdx)
- opj_uint_floordivpow2(trx0, res->pdx);
- prcj = opj_uint_floordivpow2(opj_uint_ceildiv(pi->y,
- (comp->dy << levelno)), res->pdy)
+ prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y,
+ ((OPJ_UINT64)comp->dy << levelno)), res->pdy)
- opj_uint_floordivpow2(try0, res->pdy);
pi->precno = (OPJ_UINT32)(prci + prcj * res->pw);
if (pi->precno >= res->pw * res->ph) {
@@ -846,18 +835,24 @@
/* use custom size for precincts */
for (resno = 0; resno < l_tccp->numresolutions; ++resno) {
- OPJ_UINT32 l_dx, l_dy;
+ OPJ_UINT64 l_dx, l_dy;
/* precinct width and height */
l_pdx = l_tccp->prcw[resno];
l_pdy = l_tccp->prch[resno];
- l_dx = l_img_comp->dx * (1u << (l_pdx + l_tccp->numresolutions - 1 - resno));
- l_dy = l_img_comp->dy * (1u << (l_pdy + l_tccp->numresolutions - 1 - resno));
+ l_dx = l_img_comp->dx * ((OPJ_UINT64)1u << (l_pdx + l_tccp->numresolutions - 1 -
+ resno));
+ l_dy = l_img_comp->dy * ((OPJ_UINT64)1u << (l_pdy + l_tccp->numresolutions - 1 -
+ resno));
/* take the minimum size for dx for each comp and resolution */
- *p_dx_min = opj_uint_min(*p_dx_min, l_dx);
- *p_dy_min = opj_uint_min(*p_dy_min, l_dy);
+ if (l_dx <= UINT_MAX) {
+ *p_dx_min = opj_uint_min(*p_dx_min, (OPJ_UINT32)l_dx);
+ }
+ if (l_dy <= UINT_MAX) {
+ *p_dy_min = opj_uint_min(*p_dy_min, (OPJ_UINT32)l_dy);
+ }
/* various calculations of extents */
l_level_no = l_tccp->numresolutions - 1 - resno;
diff --git a/third_party/libopenjpeg/t1.c b/third_party/libopenjpeg/t1.c
index f5fd233..52e466e 100644
--- a/third_party/libopenjpeg/t1.c
+++ b/third_party/libopenjpeg/t1.c
@@ -1410,7 +1410,6 @@
}
-/** mod fixed_quality */
static OPJ_FLOAT64 opj_t1_getwmsedec(
OPJ_INT32 nmsedec,
OPJ_UINT32 compno,
@@ -2313,7 +2312,7 @@
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
opj_mutex_t* mutex = opj_mutex_create();
- tile->distotile = 0; /* fixed_quality */
+ tile->distotile = 0;
for (compno = 0; compno < tile->numcomps; ++compno) {
opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
@@ -2401,7 +2400,6 @@
}
-/** mod fixed_quality */
static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1,
opj_tcd_cblk_enc_t* cblk,
OPJ_UINT32 orient,
@@ -2443,6 +2441,13 @@
OPJ_INT32 tmp = *datap;
if (tmp < 0) {
OPJ_UINT32 tmp_unsigned;
+ if (tmp == INT_MIN) {
+ /* To avoid undefined behaviour when negating INT_MIN */
+ /* but if we go here, it means we have supplied an input */
+ /* with more bit depth than we we can really support. */
+ /* Cf https://github.com/uclouvain/openjpeg/issues/1432 */
+ tmp = INT_MIN + 1;
+ }
max = opj_int_max(max, -tmp);
tmp_unsigned = opj_to_smr(tmp);
memcpy(datap, &tmp_unsigned, sizeof(OPJ_INT32));
@@ -2498,7 +2503,6 @@
break;
}
- /* fixed_quality */
tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid,
stepsize, numcomps, mct_norms, mct_numcomps) ;
cumwmsedec += tempwmsedec;
diff --git a/third_party/libopenjpeg/t2.c b/third_party/libopenjpeg/t2.c
index ebda005..781a6a5 100644
--- a/third_party/libopenjpeg/t2.c
+++ b/third_party/libopenjpeg/t2.c
@@ -167,9 +167,9 @@
static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n)
{
while (--n >= 0) {
- opj_bio_write(bio, 1, 1);
+ opj_bio_putbit(bio, 1);
}
- opj_bio_write(bio, 0, 1);
+ opj_bio_putbit(bio, 0);
}
static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio)
@@ -184,7 +184,7 @@
static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n)
{
if (n == 1) {
- opj_bio_write(bio, 0, 1);
+ opj_bio_putbit(bio, 0);
} else if (n == 2) {
opj_bio_write(bio, 2, 2);
} else if (n <= 5) {
@@ -801,7 +801,7 @@
}
}
#endif
- opj_bio_write(bio, packet_empty ? 0 : 1, 1); /* Empty header bit */
+ opj_bio_putbit(bio, packet_empty ? 0 : 1); /* Empty header bit */
/* Writing Packet header */
band = res->bands;
@@ -849,7 +849,7 @@
if (!cblk->numpasses) {
opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1));
} else {
- opj_bio_write(bio, layer->numpasses != 0, 1);
+ opj_bio_putbit(bio, layer->numpasses != 0);
}
/* if cblk not included, go to the next cblk */
@@ -978,7 +978,9 @@
return OPJ_FALSE;
}
- memcpy(c, layer->data, layer->len);
+ if (p_t2_mode == FINAL_PASS) {
+ memcpy(c, layer->data, layer->len);
+ }
cblk->numpasses += layer->numpasses;
c += layer->len;
length -= layer->len;
@@ -1227,9 +1229,17 @@
while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) {
++i;
}
-
l_cblk->Mb = (OPJ_UINT32)l_band->numbps;
- l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i;
+ if ((OPJ_UINT32)l_band->numbps + 1 < i) {
+ /* Not totally sure what we should do in that situation,
+ * but that avoids the integer overflow of
+ * https://github.com/uclouvain/openjpeg/pull/1488
+ * while keeping the regression test suite happy.
+ */
+ l_cblk->numbps = (OPJ_UINT32)(l_band->numbps + 1 - (int)i);
+ } else {
+ l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i;
+ }
l_cblk->numlenbits = 3;
}
@@ -1590,6 +1600,7 @@
"skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
+ return OPJ_TRUE;
}
}
diff --git a/third_party/libopenjpeg/tcd.c b/third_party/libopenjpeg/tcd.c
index b9f5714..981d90c 100644
--- a/third_party/libopenjpeg/tcd.c
+++ b/third_party/libopenjpeg/tcd.c
@@ -42,6 +42,8 @@
#include "opj_includes.h"
#include "opj_common.h"
+// #define DEBUG_RATE_ALLOC
+
/* ----------------------------------------------------------------------- */
/* TODO MSD: */
@@ -143,6 +145,9 @@
*/
static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct);
+static
+void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno,
+ OPJ_UINT32 final);
/**
Free the memory allocated for encoding
@@ -224,6 +229,7 @@
/* ----------------------------------------------------------------------- */
+static
void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd)
{
OPJ_UINT32 layno;
@@ -234,17 +240,23 @@
}
-void opj_tcd_makelayer(opj_tcd_t *tcd,
- OPJ_UINT32 layno,
- OPJ_FLOAT64 thresh,
- OPJ_UINT32 final)
+/* ----------------------------------------------------------------------- */
+
+/** Returns OPJ_TRUE if the layer allocation is unchanged w.r.t to the previous
+ * invokation with a different threshold */
+static
+OPJ_BOOL opj_tcd_makelayer(opj_tcd_t *tcd,
+ OPJ_UINT32 layno,
+ OPJ_FLOAT64 thresh,
+ OPJ_UINT32 final)
{
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
OPJ_UINT32 passno;
opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles;
+ OPJ_BOOL layer_allocation_is_same = OPJ_TRUE;
- tcd_tile->distolayer[layno] = 0; /* fixed_quality */
+ tcd_tile->distolayer[layno] = 0;
for (compno = 0; compno < tcd_tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
@@ -304,7 +316,10 @@
}
}
- layer->numpasses = n - cblk->numpassesinlayers;
+ if (layer->numpasses != n - cblk->numpassesinlayers) {
+ layer_allocation_is_same = OPJ_FALSE;
+ layer->numpasses = n - cblk->numpassesinlayers;
+ }
if (!layer->numpasses) {
layer->disto = 0;
@@ -323,7 +338,7 @@
cblk->passes[cblk->numpassesinlayers - 1].distortiondec;
}
- tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */
+ tcd_tile->distolayer[layno] += layer->disto;
if (final) {
cblk->numpassesinlayers = n;
@@ -333,14 +348,17 @@
}
}
}
+ return layer_allocation_is_same;
}
+/** For m_quality_layer_alloc_strategy == FIXED_LAYER */
+static
void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno,
OPJ_UINT32 final)
{
OPJ_UINT32 compno, resno, bandno, precno, cblkno;
OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */
- OPJ_INT32 matrice[10][10][3];
+ OPJ_INT32 matrice[J2K_TCD_MATRIX_MAX_LAYER_COUNT][J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT][3];
OPJ_UINT32 i, j, k;
opj_cp_t *cp = tcd->cp;
@@ -440,6 +458,11 @@
}
}
+/** Rate allocation for the following methods:
+ * - allocation by rate/distortio (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO)
+ * - allocation by fixed quality (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO)
+ */
+static
OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd,
OPJ_BYTE *dest,
OPJ_UINT32 * p_data_written,
@@ -450,8 +473,8 @@
OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno;
OPJ_UINT32 passno;
OPJ_FLOAT64 min, max;
- OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */
- const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */
+ OPJ_FLOAT64 cumdisto[100];
+ const OPJ_FLOAT64 K = 1;
OPJ_FLOAT64 maxSE = 0;
opj_cp_t *cp = tcd->cp;
@@ -461,7 +484,7 @@
min = DBL_MAX;
max = 0;
- tcd_tile->numpix = 0; /* fixed_quality */
+ tcd_tile->numpix = 0;
for (compno = 0; compno < tcd_tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
@@ -511,9 +534,12 @@
}
} /* passno */
- /* fixed_quality */
- tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
- tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+ {
+ const OPJ_SIZE_T cblk_pix_count = (OPJ_SIZE_T)((cblk->x1 - cblk->x0) *
+ (cblk->y1 - cblk->y0));
+ tcd_tile->numpix += cblk_pix_count;
+ tilec->numpix += cblk_pix_count;
+ }
} /* cbklno */
} /* precno */
} /* bandno */
@@ -527,8 +553,8 @@
/* index file */
if (cstr_info) {
opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno];
- tile_info->numpix = tcd_tile->numpix;
- tile_info->distotile = tcd_tile->distotile;
+ tile_info->numpix = (int)tcd_tile->numpix;
+ tile_info->distotile = (int)tcd_tile->distotile;
tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(
OPJ_FLOAT64));
if (!tile_info->thresh) {
@@ -545,35 +571,54 @@
OPJ_FLOAT64 goodthresh = 0;
OPJ_FLOAT64 stable_thresh = 0;
OPJ_UINT32 i;
- OPJ_FLOAT64 distotarget; /* fixed_quality */
+ OPJ_FLOAT64 distotarget;
- /* fixed_quality */
distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10,
tcd_tcp->distoratio[layno] / 10));
/* Don't try to find an optimal threshold but rather take everything not included yet, if
- -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0)
- -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0)
+ -r xx,yy,zz,0 (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO and rates == NULL)
+ -q xx,yy,zz,0 (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO and distoratio == NULL)
==> possible to have some lossy layers and the last layer for sure lossless */
- if (((cp->m_specific_param.m_enc.m_disto_alloc == 1) &&
+ if (((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ RATE_DISTORTION_RATIO) &&
(tcd_tcp->rates[layno] > 0.0f)) ||
- ((cp->m_specific_param.m_enc.m_fixed_quality == 1) &&
+ ((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) &&
(tcd_tcp->distoratio[layno] > 0.0))) {
opj_t2_t*t2 = opj_t2_create(tcd->image, cp);
OPJ_FLOAT64 thresh = 0;
+ OPJ_BOOL last_layer_allocation_ok = OPJ_FALSE;
if (t2 == 00) {
return OPJ_FALSE;
}
for (i = 0; i < 128; ++i) {
- OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */
+ OPJ_FLOAT64 distoachieved = 0;
+ OPJ_BOOL layer_allocation_is_same;
- thresh = (lo + hi) / 2;
+ OPJ_FLOAT64 new_thresh = (lo + hi) / 2;
+ /* Stop iterating when the threshold has stabilized enough */
+ /* 0.5 * 1e-5 is somewhat arbitrary, but has been selected */
+ /* so that this doesn't change the results of the regression */
+ /* test suite. */
+ if (fabs(new_thresh - thresh) <= 0.5 * 1e-5 * thresh) {
+ break;
+ }
+ thresh = new_thresh;
+#ifdef DEBUG_RATE_ALLOC
+ opj_event_msg(p_manager, EVT_INFO, "layno=%u, iter=%u, thresh=%g",
+ layno, i, new_thresh);
+#endif
- opj_tcd_makelayer(tcd, layno, thresh, 0);
-
- if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */
+ layer_allocation_is_same = opj_tcd_makelayer(tcd, layno, thresh, 0) && i != 0;
+#ifdef DEBUG_RATE_ALLOC
+ opj_event_msg(p_manager, EVT_INFO, "--> layer_allocation_is_same = %d",
+ layer_allocation_is_same);
+#endif
+ if (cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) {
if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) {
if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,
p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos,
@@ -605,17 +650,41 @@
}
lo = thresh;
}
- } else {
- if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,
- p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos,
- tcd->cur_pino,
- THRESH_CALC, p_manager)) {
- /* TODO: what to do with l ??? seek / tell ??? */
- /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */
+ } else { /* Disto/rate based optimization */
+ /* Check if the layer allocation done by opj_tcd_makelayer()
+ * is compatible of the maximum rate allocation. If not,
+ * retry with a higher threshold.
+ * If OK, try with a lower threshold.
+ * Call opj_t2_encode_packets() only if opj_tcd_makelayer()
+ * has resulted in different truncation points since its last
+ * call. */
+ if ((layer_allocation_is_same && !last_layer_allocation_ok) ||
+ (!layer_allocation_is_same &&
+ ! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,
+ p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos,
+ tcd->cur_pino,
+ THRESH_CALC, p_manager))) {
+
+#ifdef DEBUG_RATE_ALLOC
+ if (!layer_allocation_is_same) {
+ opj_event_msg(p_manager, EVT_INFO,
+ "--> check rate alloc failed (> maxlen=%u)\n", maxlen);
+ }
+#endif
+ last_layer_allocation_ok = OPJ_FALSE;
lo = thresh;
continue;
}
+#ifdef DEBUG_RATE_ALLOC
+ if (!layer_allocation_is_same) {
+ opj_event_msg(p_manager, EVT_INFO,
+ "--> check rate alloc success (len=%u <= maxlen=%u)\n", *p_data_written,
+ maxlen);
+ }
+#endif
+
+ last_layer_allocation_ok = OPJ_TRUE;
hi = thresh;
stable_thresh = thresh;
}
@@ -635,7 +704,6 @@
opj_tcd_makelayer(tcd, layno, goodthresh, 1);
- /* fixed_quality */
cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] :
(cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
}
@@ -2255,6 +2323,9 @@
l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1);
}
+ if (l_width == 0 || l_height == 0) {
+ continue;
+ }
if (l_tccp->qmfbid == 1) {
for (j = 0; j < l_height; ++j) {
@@ -2270,7 +2341,7 @@
for (j = 0; j < l_height; ++j) {
for (i = 0; i < l_width; ++i) {
OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr);
- if (l_value > INT_MAX) {
+ if (l_value > (OPJ_FLOAT32)INT_MAX) {
*l_current_ptr = l_max;
} else if (l_value < INT_MIN) {
*l_current_ptr = l_min;
@@ -2607,10 +2678,10 @@
p_cstr_info->index_write = 0;
}
- if (l_cp->m_specific_param.m_enc.m_disto_alloc ||
- l_cp->m_specific_param.m_enc.m_fixed_quality) {
- /* fixed_quality */
- /* Normal Rate/distortion allocation */
+ if (l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ RATE_DISTORTION_RATIO ||
+ l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy ==
+ FIXED_DISTORTION_RATIO) {
if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size,
p_cstr_info, p_manager)) {
return OPJ_FALSE;
diff --git a/third_party/libopenjpeg/tcd.h b/third_party/libopenjpeg/tcd.h
index 340c2bf..f659869 100644
--- a/third_party/libopenjpeg/tcd.h
+++ b/third_party/libopenjpeg/tcd.h
@@ -222,8 +222,8 @@
OPJ_UINT32 win_x1;
OPJ_UINT32 win_y1;
- /* add fixed_quality */
- OPJ_INT32 numpix;
+ /* number of pixels */
+ OPJ_SIZE_T numpix;
} opj_tcd_tilecomp_t;
@@ -235,9 +235,9 @@
OPJ_INT32 x0, y0, x1, y1;
OPJ_UINT32 numcomps; /* number of components in tile */
opj_tcd_tilecomp_t *comps; /* Components information */
- OPJ_INT32 numpix; /* add fixed_quality */
- OPJ_FLOAT64 distotile; /* add fixed_quality */
- OPJ_FLOAT64 distolayer[100]; /* add fixed_quality */
+ OPJ_SIZE_T numpix; /* number of pixels */
+ OPJ_FLOAT64 distotile; /* distortion of the tile */
+ OPJ_FLOAT64 distolayer[100]; /* distortion per layer */
OPJ_UINT32 packno; /* packet number */
} opj_tcd_tile_t;
@@ -369,23 +369,6 @@
OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
opj_event_mgr_t* p_manager);
-void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno,
- OPJ_UINT32 final);
-
-void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd);
-
-void opj_tcd_makelayer(opj_tcd_t *tcd,
- OPJ_UINT32 layno,
- OPJ_FLOAT64 thresh,
- OPJ_UINT32 final);
-
-OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd,
- OPJ_BYTE *dest,
- OPJ_UINT32 * p_data_written,
- OPJ_UINT32 len,
- opj_codestream_info_t *cstr_info,
- opj_event_mgr_t *p_manager);
-
/**
* Gets the maximum tile size that will be taken by the tile once decoded.
*/
diff --git a/third_party/libopenjpeg/tgt.c b/third_party/libopenjpeg/tgt.c
index 0cbad12..711d753 100644
--- a/third_party/libopenjpeg/tgt.c
+++ b/third_party/libopenjpeg/tgt.c
@@ -287,12 +287,12 @@
while (low < threshold) {
if (low >= node->value) {
if (!node->known) {
- opj_bio_write(bio, 1, 1);
+ opj_bio_putbit(bio, 1);
node->known = 1;
}
break;
}
- opj_bio_write(bio, 0, 1);
+ opj_bio_putbit(bio, 0);
++low;
}
diff --git a/third_party/libopenjpeg/thread.c b/third_party/libopenjpeg/thread.c
index f2fca2e..240810b 100644
--- a/third_party/libopenjpeg/thread.c
+++ b/third_party/libopenjpeg/thread.c
@@ -221,7 +221,7 @@
HANDLE hThread;
};
-unsigned int __stdcall opj_thread_callback_adapter(void *info)
+static unsigned int __stdcall opj_thread_callback_adapter(void *info)
{
opj_thread_t* thread = (opj_thread_t*) info;
HANDLE hEvent = NULL;