921 lines
32 KiB
Diff
921 lines
32 KiB
Diff
From 74ca29440e46136504ed6fc811ccd60da8af8abc Mon Sep 17 00:00:00 2001
|
|
From: David Bremner <david@tethera.net>
|
|
Date: Wed, 26 Oct 2016 22:18:48 -0300
|
|
Subject: [PATCH 1/3] debcherry fixup patch
|
|
|
|
88800f7 J2K: use g_strlcpy() instead of g_snprintf()
|
|
- no changes against upstream or conflicts
|
|
c6e0b7c FindOpenJPEG.cmake: use HINTS, not PATHS. NO_DEFAULT_PATH is not needed.
|
|
- no changes against upstream or conflicts
|
|
5cf698f Port to OpenJPEG2
|
|
- extra changes or conflicts
|
|
6f48d69 FindOpenJPEG.cmake: pick right include path if multiple headers.
|
|
- extra changes or conflicts
|
|
acf974a Update cmake stuff to look for OpenJPEG2 (openjpeg >= 2.0.0 aka openjp2)
|
|
- extra changes or conflicts
|
|
ecef362 restore upstream TODO
|
|
- no changes against upstream or conflicts
|
|
898199a debian: cleanup useless / missing docs
|
|
- extra changes or conflicts
|
|
31da456 remove dcraw.c again
|
|
- no changes against upstream or conflicts
|
|
4c3f916 remove dcraw.c
|
|
- no changes against upstream or conflicts
|
|
3b395b6 "undelete" some files now shipped in upstream tarball
|
|
- extra changes or conflicts
|
|
7d30472 remove version.h from git; generate it at build time
|
|
- no changes against upstream or conflicts
|
|
7441226 remove version.sh, unneeded for build
|
|
- no changes against upstream or conflicts
|
|
b0be4a0 commit version.h, version.sh for new version
|
|
- extra changes or conflicts
|
|
b5784e1 commit version.sh for current upstream snapshot
|
|
- extra changes or conflicts
|
|
cea1f68 remove generated files that are no longer carried in upstream branch (since we are not going to import them from tarballs.
|
|
- extra changes or conflicts
|
|
f67ef8e Revert "As a workaround, add files to POTFILES.skip"
|
|
- extra changes or conflicts
|
|
f6a4d09 As a workaround, add files to POTFILES.skip
|
|
- extra changes or conflicts
|
|
1eb15b3 Imported Upstream version 0.5
|
|
- extra changes or conflicts
|
|
---
|
|
cmake/modules/FindOpenJPEG.cmake | 112 ++++---------------
|
|
src/CMakeLists.txt | 17 +--
|
|
src/common/imageio_j2k.c | 228 ++++++++++++++++++++++----------------
|
|
src/imageio/format/CMakeLists.txt | 4 +-
|
|
src/imageio/format/j2k.c | 130 +++++++++++-----------
|
|
5 files changed, 224 insertions(+), 267 deletions(-)
|
|
|
|
diff --git a/cmake/modules/FindOpenJPEG.cmake b/cmake/modules/FindOpenJPEG.cmake
|
|
index b80f922..da6d275 100644
|
|
--- a/cmake/modules/FindOpenJPEG.cmake
|
|
+++ b/cmake/modules/FindOpenJPEG.cmake
|
|
@@ -1,101 +1,29 @@
|
|
-# - Find OpenJPEG library
|
|
-# Find the native OpenJPEG includes and library
|
|
-# This module defines
|
|
-# OPENJPEG_INCLUDE_DIRS, where to find openjpeg.h, Set when
|
|
-# OPENJPEG_INCLUDE_DIR is found.
|
|
-# OPENJPEG_LIBRARIES, libraries to link against to use OpenJPEG.
|
|
-# OPENJPEG_ROOT_DIR, The base directory to search for OpenJPEG.
|
|
-# This can also be an environment variable.
|
|
-# OPENJPEG_FOUND, If false, do not try to use OpenJPEG.
|
|
+# - Try to find OpenJPEG
|
|
+# Once done, this will define
|
|
#
|
|
-# also defined, but not for general use are
|
|
-# OPENJPEG_LIBRARY, where to find the OpenJPEG library.
|
|
-
|
|
-#=============================================================================
|
|
-# Copyright 2011 Blender Foundation.
|
|
-#
|
|
-# Distributed under the OSI-approved BSD License (the "License");
|
|
-# see accompanying file Copyright.txt for details.
|
|
-#
|
|
-# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
-# See the License for more information.
|
|
-#=============================================================================
|
|
-
|
|
-# If OPENJPEG_ROOT_DIR was defined in the environment, use it.
|
|
-IF(NOT OPENJPEG_ROOT_DIR AND NOT $ENV{OPENJPEG_ROOT_DIR} STREQUAL "")
|
|
- SET(OPENJPEG_ROOT_DIR $ENV{OPENJPEG_ROOT_DIR})
|
|
-ENDIF()
|
|
+# OpenJPEG_FOUND - system has OpenJPEG
|
|
+# OpenJPEG_INCLUDE_DIRS - the OpenJPEG include directories
|
|
+# OpenJPEG_LIBRARIES - link these to use OpenJPEG
|
|
|
|
include(LibFindMacros)
|
|
|
|
-libfind_pkg_check_modules(PC_OPENJPEG libopenjpeg1)
|
|
+# Use pkg-config to get hints about paths
|
|
+libfind_pkg_check_modules(OpenJPEG_PKGCONF libopenjp2)
|
|
|
|
-SET(_openjpeg_SEARCH_DIRS
|
|
- ${OPENJPEG_ROOT_DIR}
|
|
- /usr/local
|
|
- /sw # Fink
|
|
- /opt/local # DarwinPorts
|
|
- /opt/csw # Blastwave
|
|
+# Include dir
|
|
+find_path(OpenJPEG_INCLUDE_DIR
|
|
+ NAMES openjpeg.h
|
|
+ HINTS ${OpenJPEG_PKGCONF_INCLUDE_DIRS}
|
|
)
|
|
|
|
-FIND_PATH(OPENJPEG_INCLUDE_DIR
|
|
- NAMES
|
|
- openjpeg.h
|
|
- HINTS
|
|
- ${PC_OPENJPEG_INCLUDEDIR}
|
|
- ${PC_OPENJPEG_INCLUDE_DIRS}
|
|
- ${_openjpeg_SEARCH_DIRS}
|
|
- PATH_SUFFIXES
|
|
- include
|
|
+# Finally the library itself
|
|
+find_library(OpenJPEG_LIBRARY
|
|
+ NAMES openjp2
|
|
+ HINTS ${OpenJPEG_PKGCONF_LIBRARY_DIRS}
|
|
)
|
|
|
|
-FIND_LIBRARY(OPENJPEG_LIBRARY
|
|
- NAMES
|
|
- openjpeg
|
|
- HINTS
|
|
- ${PC_OPENJPEG_LIBDIR}
|
|
- ${PC_OPENJPEG_LIBRARY_DIRS}
|
|
- ${_openjpeg_SEARCH_DIRS}
|
|
- PATH_SUFFIXES
|
|
- lib64 lib
|
|
- )
|
|
-
|
|
-# handle the QUIETLY and REQUIRED arguments and set OPENJPEG_FOUND to TRUE if
|
|
-# all listed variables are TRUE
|
|
-INCLUDE(FindPackageHandleStandardArgs)
|
|
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenJPEG DEFAULT_MSG
|
|
- OPENJPEG_LIBRARY OPENJPEG_INCLUDE_DIR)
|
|
-
|
|
-IF(OPENJPEG_FOUND)
|
|
- SET(OPENJPEG_LIBRARIES ${OPENJPEG_LIBRARY})
|
|
- SET(OPENJPEG_INCLUDE_DIRS ${OPENJPEG_INCLUDE_DIR})
|
|
-
|
|
- # 1.3 didn't have pkg-config support, so we can't use that to get the version.
|
|
- # 1.5 no longer has the #define OPENJPEG_VERSION ... in openjpeg.h so we can't use that either.
|
|
- # Thus we might have to compile a smalltest program to get the version string. Could someone please kill me?
|
|
-
|
|
- # see if pkg-config found the library. this should succeed for cross compiles as they are harder to run test programs
|
|
- if(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
|
|
- # use the version as found by pkg-config
|
|
- set(OPENJPEG_VERSION ${PC_OPENJPEG_VERSION})
|
|
- else(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
|
|
- # too bad, we have to run our test code
|
|
- try_run(run_var result_var
|
|
- ${CMAKE_BINARY_DIR}/CMakeTmp
|
|
- ${CMAKE_SOURCE_DIR}/cmake/modules/openjpeg_version.c
|
|
- CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${OPENJPEG_LIBRARIES}"
|
|
- "-DINCLUDE_DIRECTORIES:STRING=${OPENJPEG_INCLUDE_DIRS}"
|
|
- RUN_OUTPUT_VARIABLE rout_var
|
|
- )
|
|
- if(result_var)
|
|
- set(OPENJPEG_VERSION ${rout_var})
|
|
- endif(result_var)
|
|
- endif(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
|
|
-
|
|
-ENDIF(OPENJPEG_FOUND)
|
|
-
|
|
-MARK_AS_ADVANCED(
|
|
- OPENJPEG_INCLUDE_DIR
|
|
- OPENJPEG_LIBRARY
|
|
-)
|
|
+# Set the include dir variables and the libraries and let libfind_process do the rest.
|
|
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
|
|
+set(OpenJPEG_PROCESS_INCLUDES OpenJPEG_INCLUDE_DIR)
|
|
+set(OpenJPEG_PROCESS_LIBS OpenJPEG_LIBRARY)
|
|
+libfind_process(OpenJPEG)
|
|
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
|
index 9278d91..7d29528 100644
|
|
--- a/src/CMakeLists.txt
|
|
+++ b/src/CMakeLists.txt
|
|
@@ -225,18 +225,13 @@ endif(USE_FLICKR)
|
|
|
|
if(USE_OPENJPEG)
|
|
find_package(OpenJPEG)
|
|
- if(OPENJPEG_FOUND)
|
|
- list(APPEND SOURCES "common/imageio_j2k.c")
|
|
- include_directories(SYSTEM ${OPENJPEG_INCLUDE_DIRS})
|
|
- list(APPEND LIBS ${OPENJPEG_LIBRARIES})
|
|
- add_definitions(${OPENJPEG_DEFINITIONS})
|
|
+ if(OpenJPEG_FOUND)
|
|
add_definitions("-DHAVE_OPENJPEG")
|
|
- if(OPENJPEG_VERSION VERSION_LESS "1.5.0")
|
|
- message(STATUS "OpenJPEG version ${OPENJPEG_VERSION} found. Only 1.5 and newer support reading of icc profiles.")
|
|
- else()
|
|
- add_definitions("-DHAVE_OPENJPEG_ICC")
|
|
- endif()
|
|
- endif(OPENJPEG_FOUND)
|
|
+ list(APPEND SOURCES "common/imageio_j2k.c")
|
|
+
|
|
+ include_directories(SYSTEM ${OpenJPEG_INCLUDE_DIRS})
|
|
+ list(APPEND LIBS ${OpenJPEG_LIBRARIES})
|
|
+ endif(OpenJPEG_FOUND)
|
|
endif(USE_OPENJPEG)
|
|
|
|
#
|
|
diff --git a/src/common/imageio_j2k.c b/src/common/imageio_j2k.c
|
|
index 84bcd28..7f60e7f 100644
|
|
--- a/src/common/imageio_j2k.c
|
|
+++ b/src/common/imageio_j2k.c
|
|
@@ -36,6 +36,7 @@
|
|
#define JPT_CFMT 2
|
|
|
|
static char JP2_HEAD[] = { 0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
|
|
+static char JP2_MAGIC[] = { 0x0d, 0x0a, 0x87, 0x0a };
|
|
static char J2K_HEAD[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00 };
|
|
// there seems to be no JPIP/JPT magic string, so we can't load it ...
|
|
|
|
@@ -74,7 +75,7 @@ static int get_file_format(const char *filename)
|
|
char *ext = strrchr(filename, '.');
|
|
if(ext == NULL) return -1;
|
|
ext++;
|
|
- if(ext)
|
|
+ if(*ext)
|
|
{
|
|
for(i = 0; i < sizeof(format) / sizeof(*format); i++)
|
|
{
|
|
@@ -91,100 +92,116 @@ static int get_file_format(const char *filename)
|
|
dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
|
|
{
|
|
opj_dparameters_t parameters; /* decompression parameters */
|
|
- opj_event_mgr_t event_mgr; /* event manager */
|
|
opj_image_t *image = NULL;
|
|
FILE *fsrc = NULL;
|
|
- unsigned char *src = NULL;
|
|
- size_t file_length;
|
|
- opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */
|
|
- opj_cio_t *cio = NULL;
|
|
+ unsigned char src_header[12] = { 0 };
|
|
+ opj_codec_t *d_codec = NULL;
|
|
OPJ_CODEC_FORMAT codec;
|
|
+ opj_stream_t *d_stream = NULL; /* Stream */
|
|
int ret = DT_IMAGEIO_FILE_CORRUPTED;
|
|
|
|
- int file_format = get_file_format(filename);
|
|
- if(file_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ /* set decoding parameters to default values */
|
|
+ opj_set_default_decoder_parameters(¶meters);
|
|
+
|
|
+ g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
|
|
+
|
|
+ parameters.decod_format = get_file_format(filename);
|
|
+ if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
|
|
|
|
if(!img->exif_inited) (void)dt_exif_read(img, filename);
|
|
|
|
- /* read the input file and put it in memory */
|
|
- /* ---------------------------------------- */
|
|
fsrc = fopen(filename, "rb");
|
|
if(!fsrc)
|
|
{
|
|
fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
|
|
return DT_IMAGEIO_FILE_NOT_FOUND;
|
|
}
|
|
- fseek(fsrc, 0, SEEK_END);
|
|
- file_length = ftell(fsrc);
|
|
- fseek(fsrc, 0, SEEK_SET);
|
|
- src = (unsigned char *)malloc(file_length);
|
|
- if(fread(src, 1, file_length, fsrc) != file_length)
|
|
+ if(fread(src_header, 1, 12, fsrc) != 12)
|
|
{
|
|
- free(src);
|
|
fclose(fsrc);
|
|
fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
|
|
return DT_IMAGEIO_FILE_NOT_FOUND;
|
|
}
|
|
fclose(fsrc);
|
|
|
|
- if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0)
|
|
+ if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
|
|
{
|
|
- file_format = JP2_CFMT; // just in case someone used the wrong extension
|
|
+ parameters.decod_format = JP2_CFMT; // just in case someone used the wrong extension
|
|
}
|
|
- else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0)
|
|
+ else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
|
|
{
|
|
- file_format = J2K_CFMT; // just in case someone used the wrong extension
|
|
+ parameters.decod_format = J2K_CFMT; // just in case someone used the wrong extension
|
|
}
|
|
else // this will also reject jpt files.
|
|
{
|
|
- free(src);
|
|
fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
|
|
return DT_IMAGEIO_FILE_CORRUPTED;
|
|
}
|
|
|
|
- /* configure the event callbacks (not required) */
|
|
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
|
|
- event_mgr.error_handler = error_callback;
|
|
- // event_mgr.warning_handler = warning_callback;
|
|
- // event_mgr.info_handler = info_callback;
|
|
-
|
|
- /* set decoding parameters to default values */
|
|
- opj_set_default_decoder_parameters(¶meters);
|
|
|
|
/* decode the code-stream */
|
|
/* ---------------------- */
|
|
- if(file_format == J2K_CFMT) /* JPEG-2000 codestream */
|
|
- codec = CODEC_J2K;
|
|
- else if(file_format == JP2_CFMT) /* JPEG 2000 compressed image data */
|
|
- codec = CODEC_JP2;
|
|
- else if(file_format == JPT_CFMT) /* JPEG 2000, JPIP */
|
|
- codec = CODEC_JPT;
|
|
+ if(parameters.decod_format == J2K_CFMT) /* JPEG-2000 codestream */
|
|
+ codec = OPJ_CODEC_J2K;
|
|
+ else if(parameters.decod_format == JP2_CFMT) /* JPEG 2000 compressed image data */
|
|
+ codec = OPJ_CODEC_JP2;
|
|
+ else if(parameters.decod_format == JPT_CFMT) /* JPEG 2000, JPIP */
|
|
+ codec = OPJ_CODEC_JPT;
|
|
else
|
|
{
|
|
- free(src);
|
|
return DT_IMAGEIO_FILE_CORRUPTED; // can't happen
|
|
}
|
|
|
|
- /* get a decoder handle */
|
|
- dinfo = opj_create_decompress(codec);
|
|
+ d_codec = opj_create_decompress(codec);
|
|
+ if(!d_codec)
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_open] Error: failed to create the decoder\n");
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
/* catch events using our callbacks and give a local context */
|
|
- opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
|
|
+ opj_set_error_handler(d_codec, error_callback, stderr);
|
|
+ // opj_set_warning_handler(d_codec, error_callback, stderr);
|
|
+ // opj_set_info_handler(d_codec, error_callback, stderr);
|
|
|
|
/* setup the decoder decoding parameters using user parameters */
|
|
- opj_setup_decoder(dinfo, ¶meters);
|
|
+ if(!opj_setup_decoder(d_codec, ¶meters))
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_open] Error: failed to setup the decoder %s\n", parameters.infile);
|
|
+ opj_destroy_codec(d_codec);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* open a byte stream */
|
|
- cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
|
|
+ d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
|
|
+ if(!d_stream)
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_open] Error: failed to create the stream from the file %s\n", parameters.infile);
|
|
+ opj_destroy_codec(d_codec);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* decode the stream and fill the image structure */
|
|
- image = opj_decode(dinfo, cio);
|
|
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
|
|
+ if(!opj_read_header(d_stream, d_codec, &image))
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_open] Error: failed to read the header\n");
|
|
+ opj_stream_destroy(d_stream);
|
|
+ opj_destroy_codec(d_codec);
|
|
+ opj_image_destroy(image);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
|
|
- /* close the byte stream */
|
|
- opj_cio_close(cio);
|
|
+ /* Get the decoded image */
|
|
+ if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_open] Error: failed to decode image!\n");
|
|
+ opj_destroy_codec(d_codec);
|
|
+ opj_stream_destroy(d_stream);
|
|
+ opj_image_destroy(image);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* free the memory containing the code-stream */
|
|
- free(src);
|
|
+ /* Close the byte stream */
|
|
+ opj_stream_destroy(d_stream);
|
|
|
|
if(!image)
|
|
{
|
|
@@ -193,14 +210,11 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
|
|
goto end_of_the_world;
|
|
}
|
|
|
|
- if(image->color_space == CLRSPC_SYCC)
|
|
+ if(image->color_space == OPJ_CLRSPC_SYCC)
|
|
{
|
|
color_sycc_to_rgb(image);
|
|
}
|
|
|
|
-// FIXME: openjpeg didn't have support for icc profiles before version 1.5
|
|
-// this needs some #ifdef magic and proper implementation
|
|
-#ifdef HAVE_OPENJPEG_ICC
|
|
if(image->icc_profile_buf)
|
|
{
|
|
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
|
|
@@ -211,7 +225,6 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
|
|
image->icc_profile_buf = NULL;
|
|
image->icc_profile_len = 0;
|
|
}
|
|
-#endif
|
|
|
|
/* create output image */
|
|
/* ------------------- */
|
|
@@ -289,7 +302,7 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
|
|
|
|
end_of_the_world:
|
|
/* free remaining structures */
|
|
- if(dinfo) opj_destroy_decompress(dinfo);
|
|
+ opj_destroy_codec(d_codec);
|
|
|
|
/* free image data structure */
|
|
opj_image_destroy(image);
|
|
@@ -299,83 +312,113 @@ end_of_the_world:
|
|
|
|
int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
|
|
{
|
|
-#ifdef HAVE_OPENJPEG_ICC
|
|
opj_dparameters_t parameters; /* decompression parameters */
|
|
opj_image_t *image = NULL;
|
|
FILE *fsrc = NULL;
|
|
- unsigned char *src = NULL;
|
|
- size_t file_length;
|
|
- opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */
|
|
- opj_cio_t *cio = NULL;
|
|
+ unsigned char src_header[12] = { 0 };
|
|
+ opj_codec_t *d_codec = NULL;
|
|
OPJ_CODEC_FORMAT codec;
|
|
+ opj_stream_t *d_stream = NULL; /* Stream */
|
|
gboolean res = FALSE;
|
|
unsigned int length = 0;
|
|
*out = NULL;
|
|
|
|
+ /* set decoding parameters to default values */
|
|
+ opj_set_default_decoder_parameters(¶meters);
|
|
+
|
|
+ g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
|
|
+
|
|
+ parameters.decod_format = get_file_format(filename);
|
|
+ if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+
|
|
/* read the input file and put it in memory */
|
|
/* ---------------------------------------- */
|
|
fsrc = fopen(filename, "rb");
|
|
if(!fsrc)
|
|
{
|
|
- fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to open `%s' for reading\n", filename);
|
|
goto another_end_of_the_world;
|
|
}
|
|
- fseek(fsrc, 0, SEEK_END);
|
|
- file_length = ftell(fsrc);
|
|
- fseek(fsrc, 0, SEEK_SET);
|
|
- src = (unsigned char *)malloc(file_length);
|
|
- if(fread(src, 1, file_length, fsrc) != file_length)
|
|
+ if(fread(src_header, 1, 12, fsrc) != 12)
|
|
{
|
|
- free(src);
|
|
fclose(fsrc);
|
|
- fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
|
|
+ fprintf(stderr,
|
|
+ "[j2k_read_profile] Error: fread returned a number of elements different from the expected.\n");
|
|
goto another_end_of_the_world;
|
|
}
|
|
fclose(fsrc);
|
|
|
|
- if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0)
|
|
+ if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
|
|
{
|
|
- codec = CODEC_JP2;
|
|
+ codec = OPJ_CODEC_JP2;
|
|
}
|
|
- else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0)
|
|
+ else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
|
|
{
|
|
- codec = CODEC_J2K;
|
|
+ codec = OPJ_CODEC_J2K;
|
|
}
|
|
else // this will also reject jpt files.
|
|
{
|
|
- free(src);
|
|
- fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: `%s' has unsupported file format.\n", filename);
|
|
goto another_end_of_the_world;
|
|
}
|
|
|
|
- /* set decoding parameters to default values */
|
|
- opj_set_default_decoder_parameters(¶meters);
|
|
- parameters.cp_limit_decoding = LIMIT_TO_MAIN_HEADER;
|
|
-
|
|
/* decode the code-stream */
|
|
/* ---------------------- */
|
|
|
|
/* get a decoder handle */
|
|
- dinfo = opj_create_decompress(codec);
|
|
+ d_codec = opj_create_decompress(codec);
|
|
+ if(!d_codec)
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to create the decoder\n");
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
/* setup the decoder decoding parameters using user parameters */
|
|
- opj_setup_decoder(dinfo, ¶meters);
|
|
+ opj_setup_decoder(d_codec, ¶meters);
|
|
+ if(!d_codec)
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to setup the decoder %s\n", parameters.infile);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* open a byte stream */
|
|
- cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
|
|
+ d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
|
|
+ if(!d_stream)
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to create the stream from the file %s\n", parameters.infile);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* decode the stream and fill the image structure */
|
|
- image = opj_decode(dinfo, cio);
|
|
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
|
|
+ if(!opj_read_header(d_stream, d_codec, &image))
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to read the header\n");
|
|
+ opj_stream_destroy(d_stream);
|
|
+ opj_destroy_codec(d_codec);
|
|
+ opj_image_destroy(image);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
|
|
- /* close the byte stream */
|
|
- opj_cio_close(cio);
|
|
+ /* Get the decoded image */
|
|
+ if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
|
|
+ {
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to decode image!\n");
|
|
+ opj_destroy_codec(d_codec);
|
|
+ opj_stream_destroy(d_stream);
|
|
+ opj_image_destroy(image);
|
|
+ return DT_IMAGEIO_FILE_CORRUPTED;
|
|
+ }
|
|
|
|
- /* free the memory containing the code-stream */
|
|
- free(src);
|
|
+ // FIXME: how to do it without fully-decoding the whole image?
|
|
+ // opj_jp2_decode() copies the icc_profile_{buf,len}
|
|
+ // from opj_codec_t *d_codec d_codec->color into opj_image_t *image, but
|
|
+ // opj_codec_t is private type.
|
|
+
|
|
+ /* Close the byte stream */
|
|
+ opj_stream_destroy(d_stream);
|
|
|
|
if(!image)
|
|
{
|
|
- fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename);
|
|
+ fprintf(stderr, "[j2k_read_profile] Error: failed to decode image `%s'\n", filename);
|
|
goto another_end_of_the_world;
|
|
}
|
|
|
|
@@ -391,15 +434,12 @@ int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
|
|
|
|
another_end_of_the_world:
|
|
/* free remaining structures */
|
|
- if(dinfo) opj_destroy_decompress(dinfo);
|
|
+ opj_destroy_codec(d_codec);
|
|
|
|
/* free image data structure */
|
|
opj_image_destroy(image);
|
|
|
|
return res ? length : 0;
|
|
-#else
|
|
- return 0;
|
|
-#endif
|
|
}
|
|
|
|
|
|
@@ -632,7 +672,7 @@ static void color_sycc_to_rgb(opj_image_t *img)
|
|
{
|
|
if(img->numcomps < 3)
|
|
{
|
|
- img->color_space = CLRSPC_GRAY;
|
|
+ img->color_space = OPJ_CLRSPC_GRAY;
|
|
return;
|
|
}
|
|
|
|
@@ -658,7 +698,7 @@ static void color_sycc_to_rgb(opj_image_t *img)
|
|
fprintf(stderr, "%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__, __LINE__);
|
|
return;
|
|
}
|
|
- img->color_space = CLRSPC_SRGB;
|
|
+ img->color_space = OPJ_CLRSPC_SRGB;
|
|
} /* color_sycc_to_rgb() */
|
|
|
|
// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
|
|
diff --git a/src/imageio/format/CMakeLists.txt b/src/imageio/format/CMakeLists.txt
|
|
index e328cb8..a79f3ee 100644
|
|
--- a/src/imageio/format/CMakeLists.txt
|
|
+++ b/src/imageio/format/CMakeLists.txt
|
|
@@ -22,10 +22,10 @@ if(OPENEXR_FOUND)
|
|
add_library(exr MODULE "exr.cc")
|
|
endif(OPENEXR_FOUND)
|
|
|
|
-if(OPENJPEG_FOUND)
|
|
+if(OpenJPEG_FOUND)
|
|
list(APPEND MODULES "j2k")
|
|
add_library(j2k MODULE "j2k.c")
|
|
-endif(OPENJPEG_FOUND)
|
|
+endif(OpenJPEG_FOUND)
|
|
|
|
foreach(module ${MODULES})
|
|
target_link_libraries(${module} ${LIBS})
|
|
diff --git a/src/imageio/format/j2k.c b/src/imageio/format/j2k.c
|
|
index 0344b75..44a995c 100644
|
|
--- a/src/imageio/format/j2k.c
|
|
+++ b/src/imageio/format/j2k.c
|
|
@@ -63,11 +63,6 @@
|
|
|
|
#include <openjpeg.h>
|
|
|
|
-#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
|
|
-#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
|
|
-#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/
|
|
-#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/
|
|
-
|
|
typedef enum
|
|
{
|
|
J2K_CFMT = 0,
|
|
@@ -168,14 +163,14 @@ static int initialise_4K_poc(opj_poc_t *POC, int numres)
|
|
POC[0].layno1 = 1;
|
|
POC[0].resno1 = numres - 1;
|
|
POC[0].compno1 = 3;
|
|
- POC[0].prg1 = CPRL;
|
|
+ POC[0].prg1 = OPJ_CPRL;
|
|
POC[1].tile = 1;
|
|
POC[1].resno0 = numres - 1;
|
|
POC[1].compno0 = 0;
|
|
POC[1].layno1 = 1;
|
|
POC[1].resno1 = numres;
|
|
POC[1].compno1 = 3;
|
|
- POC[1].prg1 = CPRL;
|
|
+ POC[1].prg1 = OPJ_CPRL;
|
|
return 2;
|
|
}
|
|
|
|
@@ -201,7 +196,7 @@ static void cinema_parameters(opj_cparameters_t *parameters)
|
|
parameters->csty |= 0x01;
|
|
|
|
/*The progression order shall be CPRL*/
|
|
- parameters->prog_order = CPRL;
|
|
+ parameters->prog_order = OPJ_CPRL;
|
|
|
|
/* No ROI */
|
|
parameters->roi_compno = -1;
|
|
@@ -220,9 +215,9 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
|
|
switch(parameters->cp_cinema)
|
|
{
|
|
- case CINEMA2K_24:
|
|
- case CINEMA2K_48:
|
|
- parameters->cp_rsiz = CINEMA2K;
|
|
+ case OPJ_CINEMA2K_24:
|
|
+ case OPJ_CINEMA2K_48:
|
|
+ parameters->cp_rsiz = OPJ_CINEMA2K;
|
|
if(parameters->numresolution > 6)
|
|
{
|
|
parameters->numresolution = 6;
|
|
@@ -233,12 +228,12 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
"Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 "
|
|
"(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n",
|
|
image->comps[0].w, image->comps[0].h);
|
|
- parameters->cp_rsiz = STD_RSIZ;
|
|
+ parameters->cp_rsiz = OPJ_STD_RSIZ;
|
|
}
|
|
break;
|
|
|
|
- case CINEMA4K_24:
|
|
- parameters->cp_rsiz = CINEMA4K;
|
|
+ case OPJ_CINEMA4K_24:
|
|
+ parameters->cp_rsiz = OPJ_CINEMA4K;
|
|
if(parameters->numresolution < 1)
|
|
{
|
|
parameters->numresolution = 1;
|
|
@@ -253,7 +248,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
"Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4"
|
|
"(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n",
|
|
image->comps[0].w, image->comps[0].h);
|
|
- parameters->cp_rsiz = STD_RSIZ;
|
|
+ parameters->cp_rsiz = OPJ_STD_RSIZ;
|
|
}
|
|
parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution);
|
|
break;
|
|
@@ -263,26 +258,26 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
|
|
switch(parameters->cp_cinema)
|
|
{
|
|
- case CINEMA2K_24:
|
|
- case CINEMA4K_24:
|
|
+ case OPJ_CINEMA2K_24:
|
|
+ case OPJ_CINEMA4K_24:
|
|
for(i = 0; i < parameters->tcp_numlayers; i++)
|
|
{
|
|
if(rates[i] == 0)
|
|
{
|
|
parameters->tcp_rates[0]
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
- / (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
+ / (OPJ_CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
}
|
|
else
|
|
{
|
|
temp_rate
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
/ (rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
- if(temp_rate > CINEMA_24_CS)
|
|
+ if(temp_rate > OPJ_CINEMA_24_CS)
|
|
{
|
|
parameters->tcp_rates[i]
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
- / (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
+ / (OPJ_CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
}
|
|
else
|
|
{
|
|
@@ -290,28 +285,28 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
}
|
|
}
|
|
}
|
|
- parameters->max_comp_size = COMP_24_CS;
|
|
+ parameters->max_comp_size = OPJ_CINEMA_24_COMP;
|
|
break;
|
|
|
|
- case CINEMA2K_48:
|
|
+ case OPJ_CINEMA2K_48:
|
|
for(i = 0; i < parameters->tcp_numlayers; i++)
|
|
{
|
|
if(rates[i] == 0)
|
|
{
|
|
parameters->tcp_rates[0]
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
- / (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
+ / (OPJ_CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
}
|
|
else
|
|
{
|
|
temp_rate
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
/ (rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
- if(temp_rate > CINEMA_48_CS)
|
|
+ if(temp_rate > OPJ_CINEMA_48_CS)
|
|
{
|
|
parameters->tcp_rates[0]
|
|
= ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
|
|
- / (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
+ / (OPJ_CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
|
|
}
|
|
else
|
|
{
|
|
@@ -319,7 +314,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
|
|
}
|
|
}
|
|
}
|
|
- parameters->max_comp_size = COMP_48_CS;
|
|
+ parameters->max_comp_size = OPJ_CINEMA_48_COMP;
|
|
break;
|
|
default:
|
|
break;
|
|
@@ -334,19 +329,9 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
|
|
dt_imageio_j2k_t *j2k = (dt_imageio_j2k_t *)j2k_tmp;
|
|
opj_cparameters_t parameters; /* compression parameters */
|
|
float *rates = NULL;
|
|
- opj_event_mgr_t event_mgr; /* event manager */
|
|
opj_image_t *image = NULL;
|
|
const int quality = CLAMP(j2k->quality, 1, 100);
|
|
|
|
- /*
|
|
- configure the event callbacks (not required)
|
|
- setting of each callback is optional
|
|
- */
|
|
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
|
|
- event_mgr.error_handler = error_callback;
|
|
- event_mgr.warning_handler = warning_callback;
|
|
- event_mgr.info_handler = info_callback;
|
|
-
|
|
/* set encoding parameters to default values */
|
|
opj_set_default_encoder_parameters(¶meters);
|
|
|
|
@@ -357,7 +342,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
|
|
|
|
parameters.tcp_numlayers = 1; /* only one resolution */
|
|
parameters.cp_disto_alloc = 1;
|
|
- parameters.cp_rsiz = STD_RSIZ;
|
|
+ parameters.cp_rsiz = OPJ_STD_RSIZ;
|
|
|
|
parameters.cod_format = j2k->format;
|
|
parameters.cp_cinema = (OPJ_CINEMA_MODE)j2k->preset;
|
|
@@ -397,7 +382,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
|
|
cmptparm[i].w = w;
|
|
cmptparm[i].h = h;
|
|
}
|
|
- image = opj_image_create(numcomps, &cmptparm[0], CLRSPC_SRGB);
|
|
+ image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
|
|
if(!image)
|
|
{
|
|
fprintf(stderr, "Error: opj_image_create() failed\n");
|
|
@@ -437,6 +422,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
|
|
fprintf(stderr, "Error: this shouldn't happen, there is no bit depth of %d for jpeg 2000 images.\n",
|
|
prec);
|
|
free(rates);
|
|
+ opj_image_destroy(image);
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -457,58 +443,66 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
|
|
int rc = 1;
|
|
OPJ_CODEC_FORMAT codec;
|
|
if(parameters.cod_format == J2K_CFMT) /* J2K format output */
|
|
- codec = CODEC_J2K;
|
|
+ codec = OPJ_CODEC_J2K;
|
|
else
|
|
- codec = CODEC_JP2;
|
|
+ codec = OPJ_CODEC_JP2;
|
|
|
|
- int codestream_length;
|
|
- size_t res;
|
|
- opj_cio_t *cio = NULL;
|
|
- FILE *f = NULL;
|
|
+ opj_stream_t *cstream = NULL;
|
|
|
|
/* get a J2K/JP2 compressor handle */
|
|
- opj_cinfo_t *cinfo = opj_create_compress(codec);
|
|
+ opj_codec_t *ccodec = opj_create_compress(codec);
|
|
+
|
|
+ opj_set_error_handler(ccodec, error_callback, stderr);
|
|
+ opj_set_warning_handler(ccodec, warning_callback, stderr);
|
|
+ opj_set_info_handler(ccodec, info_callback, stderr);
|
|
|
|
- /* catch events using our callbacks and give a local context */
|
|
- opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
|
|
+ g_strlcpy(parameters.outfile, filename, sizeof(parameters.outfile));
|
|
|
|
/* setup the encoder parameters using the current image and user parameters */
|
|
- opj_setup_encoder(cinfo, ¶meters, image);
|
|
+ opj_setup_encoder(ccodec, ¶meters, image);
|
|
|
|
/* open a byte stream for writing */
|
|
/* allocate memory for all tiles */
|
|
- cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
|
|
-
|
|
- /* encode the image */
|
|
- if(!opj_encode(cinfo, cio, image, NULL))
|
|
+ cstream = opj_stream_create_default_file_stream(parameters.outfile, OPJ_FALSE);
|
|
+ if(!cstream)
|
|
{
|
|
- opj_cio_close(cio);
|
|
- fprintf(stderr, "failed to encode image\n");
|
|
+ opj_destroy_codec(ccodec);
|
|
+ opj_image_destroy(image);
|
|
+ fprintf(stderr, "failed to create output stream\n");
|
|
return 1;
|
|
}
|
|
- codestream_length = cio_tell(cio);
|
|
|
|
- /* write the buffer to disk */
|
|
- f = fopen(filename, "wb");
|
|
- if(!f)
|
|
+ if(!opj_start_compress(ccodec, image, cstream))
|
|
{
|
|
- fprintf(stderr, "failed to open %s for writing\n", filename);
|
|
+ opj_stream_destroy(cstream);
|
|
+ opj_destroy_codec(ccodec);
|
|
+ opj_image_destroy(image);
|
|
+ fprintf(stderr, "failed to encode image: opj_start_compress\n");
|
|
return 1;
|
|
}
|
|
- res = fwrite(cio->buffer, 1, codestream_length, f);
|
|
- if(res < (size_t)codestream_length) /* FIXME */
|
|
+
|
|
+ /* encode the image */
|
|
+ if(!opj_encode(ccodec, cstream))
|
|
{
|
|
- fprintf(stderr, "failed to write %d (%s)\n", codestream_length, filename);
|
|
- fclose(f);
|
|
+ opj_stream_destroy(cstream);
|
|
+ opj_destroy_codec(ccodec);
|
|
+ opj_image_destroy(image);
|
|
+ fprintf(stderr, "failed to encode image: opj_encode\n");
|
|
return 1;
|
|
}
|
|
- fclose(f);
|
|
|
|
- /* close and free the byte stream */
|
|
- opj_cio_close(cio);
|
|
+ /* encode the image */
|
|
+ if(!opj_end_compress(ccodec, cstream))
|
|
+ {
|
|
+ opj_stream_destroy(cstream);
|
|
+ opj_destroy_codec(ccodec);
|
|
+ opj_image_destroy(image);
|
|
+ fprintf(stderr, "failed to encode image: opj_end_compress\n");
|
|
+ return 1;
|
|
+ }
|
|
|
|
- /* free remaining compression structures */
|
|
- opj_destroy_compress(cinfo);
|
|
+ opj_stream_destroy(cstream);
|
|
+ opj_destroy_codec(ccodec);
|
|
|
|
/* add exif data blob. seems to not work for j2k files :( */
|
|
if(exif && j2k->format == JP2_CFMT) rc = dt_exif_write_blob(exif, exif_len, filename, 1);
|