From 74ca29440e46136504ed6fc811ccd60da8af8abc Mon Sep 17 00:00:00 2001 From: David Bremner 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 -#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);