From 1d45d7514b632e1d4fd1a9870f495b038e206438 Mon Sep 17 00:00:00 2001 From: Antonin Descampe Date: Fri, 4 Jul 2008 11:27:40 +0000 Subject: [PATCH] Initial commit of openjpeg version 2. Temprarily added as a separate directory in the trunk (will maybe be moved to a branch of version 1.3, this has to be investigated). --- v2/CMakeLists.txt | 139 + v2/Free_CMakeImport.cmake | 14 + v2/codec/CMakeLists.txt | 68 + v2/codec/compat/getopt.c | 257 + v2/codec/compat/getopt.h | 29 + v2/codec/convert.c | 2138 ++++ v2/codec/convert.h | 78 + v2/codec/dirent.h | 677 ++ v2/codec/image_to_j2k.c | 1786 ++++ v2/codec/index.c | 391 + v2/codec/index.h | 49 + v2/codec/j2k_to_image.c | 745 ++ v2/libopenjpeg/CMakeLists.txt | 73 + v2/libopenjpeg/bio.c | 189 + v2/libopenjpeg/bio.h | 126 + v2/libopenjpeg/cio.c | 820 ++ v2/libopenjpeg/cio.h | 359 + v2/libopenjpeg/dwt.c | 873 ++ v2/libopenjpeg/dwt.h | 118 + v2/libopenjpeg/event.c | 96 + v2/libopenjpeg/event.h | 86 + v2/libopenjpeg/fix.h | 60 + v2/libopenjpeg/function_list.c | 147 + v2/libopenjpeg/function_list.h | 131 + v2/libopenjpeg/image.c | 175 + v2/libopenjpeg/image.h | 58 + v2/libopenjpeg/int.h | 159 + v2/libopenjpeg/invert.c | 291 + v2/libopenjpeg/invert.h | 40 + v2/libopenjpeg/j2k.c | 9307 +++++++++++++++++ v2/libopenjpeg/j2k.h | 736 ++ v2/libopenjpeg/j2k_lib.c | 65 + v2/libopenjpeg/j2k_lib.h | 54 + v2/libopenjpeg/jp2.c | 2229 ++++ v2/libopenjpeg/jp2.h | 342 + v2/libopenjpeg/jpt.c | 249 + v2/libopenjpeg/jpt.h | 83 + v2/libopenjpeg/mct.c | 304 + v2/libopenjpeg/mct.h | 130 + v2/libopenjpeg/mqc.c | 544 + v2/libopenjpeg/mqc.h | 198 + v2/libopenjpeg/openjpeg.c | 902 ++ v2/libopenjpeg/openjpeg.h | 1079 ++ v2/libopenjpeg/opj_configure.h | 16 + v2/libopenjpeg/opj_includes.h | 104 + v2/libopenjpeg/opj_malloc.h | 145 + v2/libopenjpeg/pi.c | 1999 ++++ v2/libopenjpeg/pi.h | 181 + v2/libopenjpeg/profile.c | 177 + v2/libopenjpeg/profile.h | 83 + v2/libopenjpeg/raw.c | 89 + v2/libopenjpeg/raw.h | 101 + v2/libopenjpeg/t1.c | 1286 +++ v2/libopenjpeg/t1.h | 156 + v2/libopenjpeg/t1_generate_luts.c | 275 + v2/libopenjpeg/t1_luts.h | 143 + v2/libopenjpeg/t2.c | 1290 +++ v2/libopenjpeg/t2.h | 120 + v2/libopenjpeg/tcd.c | 2121 ++++ v2/libopenjpeg/tcd.h | 344 + v2/libopenjpeg/tgt.c | 344 + v2/libopenjpeg/tgt.h | 130 + v2/libs/FreeImage/FreeImage.h | 1046 ++ v2/libs/FreeImage/freeimage.s.lib | Bin 0 -> 1960314 bytes v2/libs/FreeImage/libfreeimage.a | Bin 0 -> 10041296 bytes v2/libs/FreeImage/libfreeimage.s.a | Bin 0 -> 4099612 bytes v2/libs/libtiff/libtiff.lib | Bin 0 -> 440844 bytes v2/libs/libtiff/tiff.h | 647 ++ v2/libs/libtiff/tiffconf.h | 101 + v2/libs/libtiff/tiffio.h | 515 + v2/libs/libtiff/tiffvers.h | 9 + v2/opj_configure.h.in | 16 + .../CMakeLists.txt | 29 + .../test2_decoder.c | 367 + .../test2_encoder.c | 492 + v2/test_V2_tile_handling/CMakeLists.txt | 27 + v2/test_V2_tile_handling/test_decoder.c | 244 + v2/test_V2_tile_handling/test_encoder.c | 299 + 78 files changed, 39290 insertions(+) create mode 100755 v2/CMakeLists.txt create mode 100755 v2/Free_CMakeImport.cmake create mode 100755 v2/codec/CMakeLists.txt create mode 100755 v2/codec/compat/getopt.c create mode 100755 v2/codec/compat/getopt.h create mode 100755 v2/codec/convert.c create mode 100755 v2/codec/convert.h create mode 100755 v2/codec/dirent.h create mode 100755 v2/codec/image_to_j2k.c create mode 100755 v2/codec/index.c create mode 100755 v2/codec/index.h create mode 100755 v2/codec/j2k_to_image.c create mode 100755 v2/libopenjpeg/CMakeLists.txt create mode 100755 v2/libopenjpeg/bio.c create mode 100755 v2/libopenjpeg/bio.h create mode 100755 v2/libopenjpeg/cio.c create mode 100755 v2/libopenjpeg/cio.h create mode 100755 v2/libopenjpeg/dwt.c create mode 100755 v2/libopenjpeg/dwt.h create mode 100755 v2/libopenjpeg/event.c create mode 100755 v2/libopenjpeg/event.h create mode 100755 v2/libopenjpeg/fix.h create mode 100755 v2/libopenjpeg/function_list.c create mode 100755 v2/libopenjpeg/function_list.h create mode 100755 v2/libopenjpeg/image.c create mode 100755 v2/libopenjpeg/image.h create mode 100755 v2/libopenjpeg/int.h create mode 100755 v2/libopenjpeg/invert.c create mode 100755 v2/libopenjpeg/invert.h create mode 100755 v2/libopenjpeg/j2k.c create mode 100755 v2/libopenjpeg/j2k.h create mode 100755 v2/libopenjpeg/j2k_lib.c create mode 100755 v2/libopenjpeg/j2k_lib.h create mode 100755 v2/libopenjpeg/jp2.c create mode 100755 v2/libopenjpeg/jp2.h create mode 100755 v2/libopenjpeg/jpt.c create mode 100755 v2/libopenjpeg/jpt.h create mode 100755 v2/libopenjpeg/mct.c create mode 100755 v2/libopenjpeg/mct.h create mode 100755 v2/libopenjpeg/mqc.c create mode 100755 v2/libopenjpeg/mqc.h create mode 100755 v2/libopenjpeg/openjpeg.c create mode 100755 v2/libopenjpeg/openjpeg.h create mode 100755 v2/libopenjpeg/opj_configure.h create mode 100755 v2/libopenjpeg/opj_includes.h create mode 100755 v2/libopenjpeg/opj_malloc.h create mode 100755 v2/libopenjpeg/pi.c create mode 100755 v2/libopenjpeg/pi.h create mode 100755 v2/libopenjpeg/profile.c create mode 100755 v2/libopenjpeg/profile.h create mode 100755 v2/libopenjpeg/raw.c create mode 100755 v2/libopenjpeg/raw.h create mode 100755 v2/libopenjpeg/t1.c create mode 100755 v2/libopenjpeg/t1.h create mode 100755 v2/libopenjpeg/t1_generate_luts.c create mode 100755 v2/libopenjpeg/t1_luts.h create mode 100755 v2/libopenjpeg/t2.c create mode 100755 v2/libopenjpeg/t2.h create mode 100755 v2/libopenjpeg/tcd.c create mode 100755 v2/libopenjpeg/tcd.h create mode 100755 v2/libopenjpeg/tgt.c create mode 100755 v2/libopenjpeg/tgt.h create mode 100755 v2/libs/FreeImage/FreeImage.h create mode 100755 v2/libs/FreeImage/freeimage.s.lib create mode 100644 v2/libs/FreeImage/libfreeimage.a create mode 100755 v2/libs/FreeImage/libfreeimage.s.a create mode 100755 v2/libs/libtiff/libtiff.lib create mode 100755 v2/libs/libtiff/tiff.h create mode 100755 v2/libs/libtiff/tiffconf.h create mode 100755 v2/libs/libtiff/tiffio.h create mode 100755 v2/libs/libtiff/tiffvers.h create mode 100755 v2/opj_configure.h.in create mode 100755 v2/test_Free_image_V2_tile_handling/CMakeLists.txt create mode 100755 v2/test_Free_image_V2_tile_handling/test2_decoder.c create mode 100755 v2/test_Free_image_V2_tile_handling/test2_encoder.c create mode 100755 v2/test_V2_tile_handling/CMakeLists.txt create mode 100755 v2/test_V2_tile_handling/test_decoder.c create mode 100755 v2/test_V2_tile_handling/test_encoder.c diff --git a/v2/CMakeLists.txt b/v2/CMakeLists.txt new file mode 100755 index 00000000..444092ef --- /dev/null +++ b/v2/CMakeLists.txt @@ -0,0 +1,139 @@ +# Main CMakeLists.txt to build the OpenJPEG project using CMake (www.cmake.org) +# Written by Mathieu Malaterre + +# This CMake project will by default create a library called openjpeg +# But if you want to use this project within your own (CMake) project +# you will eventually like to prefix the library to avoid linking confusion +# For this purpose you can define a CMake var: OPENJPEG_NAMESPACE to whatever you like +# e.g.: +# SET(OPENJPEG_NAMESPACE "GDCMOPENJPEG") +CMAKE_MINIMUM_REQUIRED(VERSION 2.4) + +IF(NOT OPENJPEG_NAMESPACE) + SET(OPENJPEG_NAMESPACE "OPENJPEG") + SET(OPENJPEG_STANDALONE 1) +ENDIF(NOT OPENJPEG_NAMESPACE) +# In all cases: +STRING(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME) + +PROJECT(${OPENJPEG_NAMESPACE} C) + +# Do full dependency headers. +INCLUDE_REGULAR_EXPRESSION("^.*$") + +#----------------------------------------------------------------------------- +# OPENJPEG version number, useful for packaging and doxygen doc: +SET(OPENJPEG_VERSION_MAJOR 1) +SET(OPENJPEG_VERSION_MINOR 2) +SET(OPENJPEG_VERSION_BUILD 0) +SET(OPENJPEG_VERSION + "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") + +# This setting of SOVERSION assumes that any API change +# will increment either the minor or major version number of openjpeg +SET(OPENJPEG_LIBRARY_PROPERTIES + VERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}" + SOVERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}" +) + +#----------------------------------------------------------------------------- +# Test for some required system information. +INCLUDE (${CMAKE_ROOT}/Modules/CMakeBackwardCompatibilityC.cmake) + +#----------------------------------------------------------------------------- +# OpenJPEG build configuration options. +OPTION(BUILD_SHARED_LIBS "Build OpenJPEG with shared libraries." OFF) +OPTION(ENABLE_PROFILING "Enable profiling for the library" OFF) + +#----------------------------------------------------------------------------- +SET (EXECUTABLE_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") +SET (LIBRARY_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") +MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) + + +#----------------------------------------------------------------------------- +# For the codec... +OPTION(BUILD_EXAMPLES "Build the Examples (codec...)." OFF) + + +# configure name mangling to allow multiple libraries to coexist +# peacefully +IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in) +SET(MANGLE_PREFIX ${OPENJPEG_LIBRARY_NAME}) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in + ${CMAKE_CURRENT_BINARY_DIR}/openjpeg_mangle.h + @ONLY IMMEDIATE) +ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in) + +#----------------------------------------------------------------------------- +# Configure files with settings for use by the build. +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/opj_configure.h.in + ${CMAKE_CURRENT_BINARY_DIR}/opj_configure.h) + + +#----------------------------------------------------------------------------- +# Always build the library +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) +SUBDIRS( + libopenjpeg + codec + test_V2_tile_handling + test_Free_image_V2_tile_handling + # mj2 + # cmake 2.4.5 has poor java support + #j2kviewer/src + ) + +#IF(NOT UNIX) +#SUBDIRS( +# jpwl +# jp3d +# indexer_JPIP +# ) +#ENDIF(NOT UNIX) + +#----------------------------------------------------------------------------- +# Build example only if requested +#IF(BUILD_EXAMPLES) +# SUBDIRS(codec) +#ENDIF(BUILD_EXAMPLES) + +#----------------------------------------------------------------------------- +# For the documentation +OPTION(BUILD_DOCUMENTATION "Build the doxygen documentation" OFF) +IF(BUILD_DOCUMENTATION) + SUBDIRS(doc) +ENDIF(BUILD_DOCUMENTATION) + +#----------------------------------------------------------------------------- +# For openjpeg team if they ever want Dart+CMake +#IF(OPENJPEG_STANDALONE) +# INCLUDE(Dart) +# MARK_AS_ADVANCED(BUILD_TESTING DART_ROOT TCL_TCLSH) +# IF(BUILD_TESTING) +# ENABLE_TESTING() +# SET(BUILDNAME "OpenJPEG-${CMAKE_SYSTEM}-${CMAKE_C_COMPILER}" CACHE STRING "Name of build on the dashboard") +# MARK_AS_ADVANCED(BUILDNAME) +# ENDIF(BUILD_TESTING) +#ENDIF(OPENJPEG_STANDALONE) + +# Adding test with dataset from: +# http://www.crc.ricoh.com/~gormish/jpeg2000conformance/ +# http://www.jpeg.org/jpeg2000guide/testimages/testimages.html + +#----------------------------------------------------------------------------- +# Adding JPEG2000_CONFORMANCE_DATA_ROOT +FIND_PATH(JPEG2000_CONFORMANCE_DATA_ROOT testimages.html + ${OPENJPEG_SOURCE_DIR}/../jpeg2000testimages + $ENV{JPEG2000_CONFORMANCE_DATA_ROOT} +) + +#----------------------------------------------------------------------------- +# Compiler specific flags: +IF(CMAKE_COMPILER_IS_GNUCC) + # For all builds, make sure openjpeg is std99 compliant: + SET(CMAKE_C_FLAGS "-Wall -std=c99 ${CMAKE_C_FLAGS}") + # Do not use ffast-math for all build, it would produce incorrect results, only set for release: + SET(CMAKE_C_FLAGS_RELEASE "-ffast-math ${CMAKE_C_FLAGS_RELEASE}") +ENDIF(CMAKE_COMPILER_IS_GNUCC) + diff --git a/v2/Free_CMakeImport.cmake b/v2/Free_CMakeImport.cmake new file mode 100755 index 00000000..bcebe6ef --- /dev/null +++ b/v2/Free_CMakeImport.cmake @@ -0,0 +1,14 @@ +# Import library +#________________ + + # MESSAGE(STATUS "IMPORT : FreeImagelibrary") + + # Include directories + INCLUDE_DIRECTORIES(${OPENJPEG_SOURCE_DIR}/libs/FreeImage) + + # Link libraries + LINK_DIRECTORIES(${OPENJPEG_SOURCE_DIR}/libs/FreeImage) + + LINK_LIBRARIES(freeimage.s) + ADD_DEFINITIONS ( -DFREEIMAGE_LIB ) + diff --git a/v2/codec/CMakeLists.txt b/v2/codec/CMakeLists.txt new file mode 100755 index 00000000..69538ce6 --- /dev/null +++ b/v2/codec/CMakeLists.txt @@ -0,0 +1,68 @@ +# Build the demo app, small examples + +# First thing define the common source: +SET(common_SRCS + convert.c + index.c +) + +# Then check if getopt is present: +INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) +SET(DONT_HAVE_GETOPT 1) +IF(UNIX) #I am pretty sure only *nix sys have this anyway + CHECK_INCLUDE_FILE("getopt.h" CMAKE_HAVE_GETOPT_H) + # Seems like we need the contrary: + IF(CMAKE_HAVE_GETOPT_H) + SET(DONT_HAVE_GETOPT 0) + ENDIF(CMAKE_HAVE_GETOPT_H) +ENDIF(UNIX) + +# If not getopt was found then add it to the lib: +IF(DONT_HAVE_GETOPT) + ADD_DEFINITIONS(-DDONT_HAVE_GETOPT) + SET(common_SRCS + ${common_SRCS} + compat/getopt.c + ) +ENDIF(DONT_HAVE_GETOPT) + +# Headers file are located here: +INCLUDE_DIRECTORIES( + ${OPENJPEG_SOURCE_DIR}/libopenjpeg + ) + +# Do the proper thing when building static...if only there was configured +# headers or def files instead +IF(NOT BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_STATIC) +ENDIF(NOT BUILD_SHARED_LIBS) + +FIND_PACKAGE(TIFF REQUIRED) + +# Loop over all executables: +FOREACH(exe j2k_to_image image_to_j2k) + ADD_EXECUTABLE(${exe} ${exe}.c ${common_SRCS}) + TARGET_LINK_LIBRARIES(${exe} ${OPJ_PREFIX}openjpeg ${TIFF_LIBRARIES}) + ADD_TEST(${exe} ${EXECUTABLE_OUTPUT_PATH}/${exe}) + # calling those exe without option will make them fail always: + SET_TESTS_PROPERTIES(${exe} PROPERTIES WILL_FAIL TRUE) + # On unix you need to link to the math library: + IF(UNIX) + TARGET_LINK_LIBRARIES(${exe} m) + ENDIF(UNIX) + # Install exe + INSTALL_TARGETS(/bin/ ${exe}) +ENDFOREACH(exe) + +# Do testing here, once we know the examples are being built: +FILE(GLOB_RECURSE OPENJPEG_DATA_IMAGES_GLOB + "${JPEG2000_CONFORMANCE_DATA_ROOT}/*.j2k" + "${JPEG2000_CONFORMANCE_DATA_ROOT}/*.j2c" + "${JPEG2000_CONFORMANCE_DATA_ROOT}/*.jp2" + ) + +FOREACH(filename ${OPENJPEG_DATA_IMAGES_GLOB}) + GET_FILENAME_COMPONENT(filename_temp ${filename} NAME) + ADD_TEST(j2i-${filename_temp} ${EXECUTABLE_OUTPUT_PATH}/j2k_to_image -i ${filename} -o ${filename_temp}.tif) +ENDFOREACH(filename) + diff --git a/v2/codec/compat/getopt.c b/v2/codec/compat/getopt.c new file mode 100755 index 00000000..75bbb279 --- /dev/null +++ b/v2/codec/compat/getopt.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* last review : october 29th, 2002 */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +const char *optarg; /* argument associated with option */ + +typedef struct option +{ + char *name; + int has_arg; + int *flag; + int val; +}option_t; + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + + + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int getopt(int nargc, char *const *nargv, const char *ostr) { +# define __progname nargv[0] + static const char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (-1); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (-1); + } + } /* option letter okay? */ + if ((optopt = (int) *place++) == (int) ':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (optopt == (int) '-') + return (-1); + if (!*place) + ++optind; + if (opterr && *ostr != ':') { + fprintf(stderr, + "%s: illegal option -- %c\n", __progname, optopt); + return (BADCH); + } + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) { + fprintf(stderr, + "%s: option requires an argument -- %c\n", + __progname, optopt); + return (BADCH); + } + } else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} + + +int getopt_long(int argc, char * const argv[], const char *optstring, +struct option *longopts, int totlen) { + static int lastidx,lastofs; + char *tmp; + int i,len; + char param = 1; + +again: + if (optind>argc || !argv[optind] || *argv[optind]!='-') + return -1; + + if (argv[optind][0]=='-' && argv[optind][1]==0) { + if(optind >= (argc - 1)){ /* no more input parameters */ + param = 0; + } + else{ /* more input parameters */ + if(argv[optind + 1][0] == '-'){ + param = 0; /* Missing parameter after '-' */ + } + else{ + param = 2; + } + } + } + + if (param == 0) { + ++optind; + return (BADCH); + } + + if (argv[optind][0]=='-') { /* long option */ + char* arg=argv[optind]+1; + const struct option* o; + o=longopts; + len=sizeof(longopts[0]); + + if (param > 1){ + arg = argv[optind+1]; + optind++; + } + else + arg = argv[optind]+1; + + if(strlen(arg)>1){ + for (i=0;iname,arg)) { /* match */ + if (o->has_arg == 0) { + if ((argv[optind+1])&&(!(argv[optind+1][0]=='-'))){ + fprintf(stderr,"%s: option does not require an argument. Ignoring %s\n",arg,argv[optind+1]); + ++optind; + } + }else{ + optarg=argv[optind+1]; + if(optarg){ + if (optarg[0] == '-'){ /* Has read next input parameter: No arg for current parameter */ + if (opterr) { + fprintf(stderr,"%s: option requires an argument\n",arg); + return (BADCH); + } + } + } + if (!optarg && o->has_arg==1) { /* no argument there */ + if (opterr) { + fprintf(stderr,"%s: option requires an argument \n",arg); + return (BADCH); + } + } + ++optind; + } + ++optind; + if (o->flag) + *(o->flag)=o->val; + else + return o->val; + return 0; + } + }//(end for)String not found in the list + fprintf(stderr,"Invalid option %s\n",arg); + ++optind; + return (BADCH); + }else{ /*Single character input parameter*/ + if (*optstring==':') return ':'; + if (lastidx!=optind) { + lastidx=optind; lastofs=0; + } + optopt=argv[optind][lastofs+1]; + if ((tmp=strchr(optstring,optopt))) {/*Found input parameter in list*/ + if (*tmp==0) { /* apparently, we looked for \0, i.e. end of argument */ + ++optind; + goto again; + } + if (tmp[1]==':') { /* argument expected */ + if (tmp[2]==':' || argv[optind][lastofs+2]) { /* "-foo", return "oo" as optarg */ + if (!*(optarg=argv[optind]+lastofs+2)) optarg=0; + goto found; + } + optarg=argv[optind+1]; + if(optarg){ + if (optarg[0] == '-'){ /* Has read next input parameter: No arg for current parameter */ + if (opterr) { + fprintf(stderr,"%s: option requires an argument\n",arg); + return (BADCH); + } + } + } + if (!optarg) { /* missing argument */ + if (opterr) { + fprintf(stderr,"%s: option requires an argument\n",arg); + return (BADCH); + } + } + ++optind; + }else {/*Argument not expected*/ + ++lastofs; + return optopt; + } +found: + ++optind; + return optopt; + } else { /* not found */ + fprintf(stderr,"Invalid option %s\n",arg); + ++optind; + return (BADCH); + }//end of not found + + }// end of single character + }//end '-' + fprintf(stderr,"Invalid option\n"); + ++optind; + return (BADCH);; +}//end function diff --git a/v2/codec/compat/getopt.h b/v2/codec/compat/getopt.h new file mode 100755 index 00000000..7a04b302 --- /dev/null +++ b/v2/codec/compat/getopt.h @@ -0,0 +1,29 @@ +/* last review : october 29th, 2002 */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +typedef struct option +{ + char *name; + int has_arg; + int *flag; + int val; +}option_t; + +#define NO_ARG 0 +#define REQ_ARG 1 +#define OPT_ARG 2 + +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char *optarg; + +extern int getopt(int nargc, char *const *nargv, const char *ostr); +extern int getopt_long(int argc, char * const argv[], const char *optstring, + const struct option *longopts, int totlen); + + +#endif /* _GETOPT_H_ */ diff --git a/v2/codec/convert.c b/v2/codec/convert.c new file mode 100755 index 00000000..99e3e455 --- /dev/null +++ b/v2/codec/convert.c @@ -0,0 +1,2138 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include "openjpeg.h" +#include "../libs/libtiff/tiffio.h" +#include "convert.h" + +/* + * Get logarithm of an integer and round downwards. + * + * log2(a) + */ +static int int_floorlog2(int a) { + int l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; +} + +/* + * Divide an integer by a power of 2 and round upwards. + * + * a divided by 2^b + */ +static int int_ceildivpow2(int a, int b) { + return (a + (1 << b) - 1) >> b; +} + +/* + * Divide an integer and round upwards. + * + * a divided by b + */ +static int int_ceildiv(int a, int b) { + return (a + b - 1) / b; +} + + +/* -->> -->> -->> -->> + + TGA IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +// TGA header definition. +#pragma pack(push,1) // Pack structure byte aligned +typedef struct tga_header +{ + uint8 id_length; /* Image id field length */ + uint8 colour_map_type; /* Colour map type */ + uint8 image_type; /* Image type */ + /* + ** Colour map specification + */ + uint16 colour_map_index; /* First entry index */ + uint16 colour_map_length; /* Colour map length */ + uint8 colour_map_entry_size; /* Colour map entry size */ + /* + ** Image specification + */ + uint16 x_origin; /* x origin of image */ + uint16 y_origin; /* u origin of image */ + uint16 image_width; /* Image width */ + uint16 image_height; /* Image height */ + uint8 pixel_depth; /* Pixel depth */ + uint8 image_desc; /* Image descriptor */ +} tga_header; +#pragma pack(pop) // Return to normal structure packing alignment. + +int tga_readheader(FILE *fp, int *bits_per_pixel, int *width, int *height, int *flip_image) +{ + int palette_size; + tga_header tga ; + + if (!bits_per_pixel || !width || !height || !flip_image) + return 0; + + // Read TGA header + fread((uint8*)&tga, sizeof(tga_header), 1, fp); + + *bits_per_pixel = tga.pixel_depth; + + *width = tga.image_width; + *height = tga.image_height ; + + // Ignore tga identifier, if present ... + if (tga.id_length) + { + uint8 *id = (uint8 *) malloc(tga.id_length); + fread(id, tga.id_length, 1, fp); + free(id); + } + + // Test for compressed formats ... not yet supported ... + // Note :- 9 - RLE encoded palettized. + // 10 - RLE encoded RGB. + if (tga.image_type > 8) + { + fprintf(stderr, "Sorry, compressed tga files are not currently supported.\n"); + return 0 ; + } + + *flip_image = !(tga.image_desc & 32); + + // Palettized formats are not yet supported, skip over the palette, if present ... + palette_size = tga.colour_map_length * (tga.colour_map_entry_size/8); + + if (palette_size>0) + { + fprintf(stderr, "File contains a palette - not yet supported."); + fseek(fp, palette_size, SEEK_CUR); + } + return 1; +} + +int tga_writeheader(FILE *fp, int bits_per_pixel, int width, int height, bool flip_image) +{ + tga_header tga; + + if (!bits_per_pixel || !width || !height) + return 0; + + memset(&tga, 0, sizeof(tga_header)); + + tga.pixel_depth = bits_per_pixel; + tga.image_width = width; + tga.image_height = height; + tga.image_type = 2; // Uncompressed. + tga.image_desc = 8; // 8 bits per component. + + if (flip_image) + tga.image_desc |= 32; + + // Write TGA header + fwrite((uint8*)&tga, sizeof(tga_header), 1, fp); + + return 1; +} + +opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters) { + FILE *f; + opj_image_t *image; + uint32 image_width, image_height, pixel_bit_depth; + uint32 x, y; + int flip_image=0; + opj_image_cmptparm_t cmptparm[4]; /* maximum 4 components */ + int numcomps; + OPJ_COLOR_SPACE color_space; + bool mono ; + bool save_alpha; + int subsampling_dx, subsampling_dy; + int i; + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + return 0; + } + + if (!tga_readheader(f, &pixel_bit_depth, &image_width, &image_height, &flip_image)) + return NULL; + + // We currently only support 24 & 32 bit tga's ... + if (!((pixel_bit_depth == 24) || (pixel_bit_depth == 32))) + return NULL; + + /* initialize image components */ + memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t)); + + mono = (pixel_bit_depth == 8) || (pixel_bit_depth == 16); // Mono with & without alpha. + save_alpha = (pixel_bit_depth == 16) || (pixel_bit_depth == 32); // Mono with alpha, or RGB with alpha + + if (mono) { + color_space = CLRSPC_GRAY; + numcomps = save_alpha ? 2 : 1; + } + else { + numcomps = save_alpha ? 4 : 3; + color_space = CLRSPC_SRGB; + } + + subsampling_dx = parameters->subsampling_dx; + subsampling_dy = parameters->subsampling_dy; + + for (i = 0; i < numcomps; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = image_width; + cmptparm[i].h = image_height; + } + + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + + if (!image) + return NULL; + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (image_width - 1) * subsampling_dx + 1 : image->x0 + (image_width - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (image_height - 1) * subsampling_dy + 1 : image->y0 + (image_height - 1) * subsampling_dy + 1; + + /* set image data */ + for (y=0; y < image_height; y++) + { + int index; + + if (flip_image) + index = (image_height-y-1)*image_width; + else + index = y*image_width; + + if (numcomps==3) + { + for (x=0;xcomps[0].data[index]=r; + image->comps[1].data[index]=g; + image->comps[2].data[index]=b; + index++; + } + } + else if (numcomps==4) + { + for (x=0;xcomps[0].data[index]=r; + image->comps[1].data[index]=g; + image->comps[2].data[index]=b; + image->comps[3].data[index]=a; + index++; + } + } + else { + fprintf(stderr, "Currently unsupported bit depth : %s\n", filename); + } + } + return image; +} + +int imagetotga(opj_image_t * image, const char *outfile) { + int width, height, bpp, x, y; + bool write_alpha; + int i; + uint32 alpha_channel; + float r,g,b,a; + uint8 value; + float scale; + FILE *fdest; + + fdest = fopen(outfile, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } + + for (i = 0; i < image->numcomps-1; i++) { + if ((image->comps[0].dx != image->comps[i+1].dx) + ||(image->comps[0].dy != image->comps[i+1].dy) + ||(image->comps[0].prec != image->comps[i+1].prec)) { + fprintf(stderr, "Unable to create a tga file with such J2K image charateristics."); + return 1; + } + } + + width = image->comps[0].w; + height = image->comps[0].h; + + // Mono with alpha, or RGB with alpha. + write_alpha = (image->numcomps==2) || (image->numcomps==4); + + // Write TGA header + bpp = write_alpha ? 32 : 24; + if (!tga_writeheader(fdest, bpp, width , height, true)) + return 1; + + alpha_channel = image->numcomps-1; + + scale = 255.0f / (float)((1<comps[0].prec)-1); + + for (y=0; y < height; y++) { + uint32 index=y*width; + + for (x=0; x < width; x++, index++) { + r = (float)(image->comps[0].data[index]); + + if (image->numcomps>2) { + g = (float)(image->comps[1].data[index]); + b = (float)(image->comps[2].data[index]); + } + else {// Greyscale ... + g = r; + b = r; + } + + // TGA format writes BGR ... + value = (uint8)(b*scale); + fwrite(&value,1,1,fdest); + + value = (uint8)(g*scale); + fwrite(&value,1,1,fdest); + + value = (uint8)(r*scale); + fwrite(&value,1,1,fdest); + + if (write_alpha) { + a = (float)(image->comps[alpha_channel].data[index]); + value = (uint8)(a*scale); + fwrite(&value,1,1,fdest); + } + } + } + + return 0; +} + +/* -->> -->> -->> -->> + + BMP IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +/* WORD defines a two byte word */ +typedef unsigned short int WORD; + +/* DWORD defines a four byte word */ +typedef unsigned long int DWORD; + +typedef struct { + WORD bfType; /* 'BM' for Bitmap (19776) */ + DWORD bfSize; /* Size of the file */ + WORD bfReserved1; /* Reserved : 0 */ + WORD bfReserved2; /* Reserved : 0 */ + DWORD bfOffBits; /* Offset */ +} BITMAPFILEHEADER_t; + +typedef struct { + DWORD biSize; /* Size of the structure in bytes */ + DWORD biWidth; /* Width of the image in pixels */ + DWORD biHeight; /* Heigth of the image in pixels */ + WORD biPlanes; /* 1 */ + WORD biBitCount; /* Number of color bits by pixels */ + DWORD biCompression; /* Type of encoding 0: none 1: RLE8 2: RLE4 */ + DWORD biSizeImage; /* Size of the image in bytes */ + DWORD biXpelsPerMeter; /* Horizontal (X) resolution in pixels/meter */ + DWORD biYpelsPerMeter; /* Vertical (Y) resolution in pixels/meter */ + DWORD biClrUsed; /* Number of color used in the image (0: ALL) */ + DWORD biClrImportant; /* Number of important color (0: ALL) */ +} BITMAPINFOHEADER_t; + +opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters) { + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + int i, numcomps, w, h; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ + opj_image_t * image = NULL; + + FILE *IN; + BITMAPFILEHEADER_t File_h; + BITMAPINFOHEADER_t Info_h; + unsigned char *RGB; + unsigned char *table_R, *table_G, *table_B; + unsigned int j, PAD = 0; + + int x, y, index; + int gray_scale = 1, not_end_file = 1; + + unsigned int line = 0, col = 0; + unsigned char v, v2; + DWORD W, H; + + IN = fopen(filename, "rb"); + if (!IN) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + return 0; + } + + File_h.bfType = getc(IN); + File_h.bfType = (getc(IN) << 8) + File_h.bfType; + + if (File_h.bfType != 19778) { + fprintf(stderr,"Error, not a BMP file!\n"); + return 0; + } else { + /* FILE HEADER */ + /* ------------- */ + File_h.bfSize = getc(IN); + File_h.bfSize = (getc(IN) << 8) + File_h.bfSize; + File_h.bfSize = (getc(IN) << 16) + File_h.bfSize; + File_h.bfSize = (getc(IN) << 24) + File_h.bfSize; + + File_h.bfReserved1 = getc(IN); + File_h.bfReserved1 = (getc(IN) << 8) + File_h.bfReserved1; + + File_h.bfReserved2 = getc(IN); + File_h.bfReserved2 = (getc(IN) << 8) + File_h.bfReserved2; + + File_h.bfOffBits = getc(IN); + File_h.bfOffBits = (getc(IN) << 8) + File_h.bfOffBits; + File_h.bfOffBits = (getc(IN) << 16) + File_h.bfOffBits; + File_h.bfOffBits = (getc(IN) << 24) + File_h.bfOffBits; + + /* INFO HEADER */ + /* ------------- */ + + Info_h.biSize = getc(IN); + Info_h.biSize = (getc(IN) << 8) + Info_h.biSize; + Info_h.biSize = (getc(IN) << 16) + Info_h.biSize; + Info_h.biSize = (getc(IN) << 24) + Info_h.biSize; + + Info_h.biWidth = getc(IN); + Info_h.biWidth = (getc(IN) << 8) + Info_h.biWidth; + Info_h.biWidth = (getc(IN) << 16) + Info_h.biWidth; + Info_h.biWidth = (getc(IN) << 24) + Info_h.biWidth; + w = Info_h.biWidth; + + Info_h.biHeight = getc(IN); + Info_h.biHeight = (getc(IN) << 8) + Info_h.biHeight; + Info_h.biHeight = (getc(IN) << 16) + Info_h.biHeight; + Info_h.biHeight = (getc(IN) << 24) + Info_h.biHeight; + h = Info_h.biHeight; + + Info_h.biPlanes = getc(IN); + Info_h.biPlanes = (getc(IN) << 8) + Info_h.biPlanes; + + Info_h.biBitCount = getc(IN); + Info_h.biBitCount = (getc(IN) << 8) + Info_h.biBitCount; + + Info_h.biCompression = getc(IN); + Info_h.biCompression = (getc(IN) << 8) + Info_h.biCompression; + Info_h.biCompression = (getc(IN) << 16) + Info_h.biCompression; + Info_h.biCompression = (getc(IN) << 24) + Info_h.biCompression; + + Info_h.biSizeImage = getc(IN); + Info_h.biSizeImage = (getc(IN) << 8) + Info_h.biSizeImage; + Info_h.biSizeImage = (getc(IN) << 16) + Info_h.biSizeImage; + Info_h.biSizeImage = (getc(IN) << 24) + Info_h.biSizeImage; + + Info_h.biXpelsPerMeter = getc(IN); + Info_h.biXpelsPerMeter = (getc(IN) << 8) + Info_h.biXpelsPerMeter; + Info_h.biXpelsPerMeter = (getc(IN) << 16) + Info_h.biXpelsPerMeter; + Info_h.biXpelsPerMeter = (getc(IN) << 24) + Info_h.biXpelsPerMeter; + + Info_h.biYpelsPerMeter = getc(IN); + Info_h.biYpelsPerMeter = (getc(IN) << 8) + Info_h.biYpelsPerMeter; + Info_h.biYpelsPerMeter = (getc(IN) << 16) + Info_h.biYpelsPerMeter; + Info_h.biYpelsPerMeter = (getc(IN) << 24) + Info_h.biYpelsPerMeter; + + Info_h.biClrUsed = getc(IN); + Info_h.biClrUsed = (getc(IN) << 8) + Info_h.biClrUsed; + Info_h.biClrUsed = (getc(IN) << 16) + Info_h.biClrUsed; + Info_h.biClrUsed = (getc(IN) << 24) + Info_h.biClrUsed; + + Info_h.biClrImportant = getc(IN); + Info_h.biClrImportant = (getc(IN) << 8) + Info_h.biClrImportant; + Info_h.biClrImportant = (getc(IN) << 16) + Info_h.biClrImportant; + Info_h.biClrImportant = (getc(IN) << 24) + Info_h.biClrImportant; + + /* Read the data and store them in the OUT file */ + + if (Info_h.biBitCount == 24) { + numcomps = 3; + color_space = CLRSPC_SRGB; + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(IN); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : image->x0 + (w - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : image->y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + /* Place the cursor at the beginning of the image information */ + fseek(IN, 0, SEEK_SET); + fseek(IN, File_h.bfOffBits, SEEK_SET); + + W = Info_h.biWidth; + H = Info_h.biHeight; + + /* PAD = 4 - (3 * W) % 4; */ + /* PAD = (PAD == 4) ? 0 : PAD; */ + PAD = (3 * W) % 4 ? 4 - (3 * W) % 4 : 0; + + RGB = (unsigned char *) malloc((3 * W + PAD) * H * sizeof(unsigned char)); + + fread(RGB, sizeof(unsigned char), (3 * W + PAD) * H, IN); + + index = 0; + + for(y = 0; y < (int)H; y++) { + unsigned char *scanline = RGB + (3 * W + PAD) * (H - 1 - y); + for(x = 0; x < (int)W; x++) { + unsigned char *pixel = &scanline[3 * x]; + image->comps[0].data[index] = pixel[2]; /* R */ + image->comps[1].data[index] = pixel[1]; /* G */ + image->comps[2].data[index] = pixel[0]; /* B */ + index++; + } + } + + free(RGB); + + } else if (Info_h.biBitCount == 8 && Info_h.biCompression == 0) { + table_R = (unsigned char *) malloc(256 * sizeof(unsigned char)); + table_G = (unsigned char *) malloc(256 * sizeof(unsigned char)); + table_B = (unsigned char *) malloc(256 * sizeof(unsigned char)); + + for (j = 0; j < Info_h.biClrUsed; j++) { + table_B[j] = getc(IN); + table_G[j] = getc(IN); + table_R[j] = getc(IN); + getc(IN); + if (table_R[j] != table_G[j] && table_R[j] != table_B[j] && table_G[j] != table_B[j]) + gray_scale = 0; + } + + /* Place the cursor at the beginning of the image information */ + fseek(IN, 0, SEEK_SET); + fseek(IN, File_h.bfOffBits, SEEK_SET); + + W = Info_h.biWidth; + H = Info_h.biHeight; + if (Info_h.biWidth % 2) + W++; + + numcomps = gray_scale ? 1 : 3; + color_space = gray_scale ? CLRSPC_GRAY : CLRSPC_SRGB; + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(IN); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : image->x0 + (w - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : image->y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + RGB = (unsigned char *) malloc(W * H * sizeof(unsigned char)); + + fread(RGB, sizeof(unsigned char), W * H, IN); + if (gray_scale) { + index = 0; + for (j = 0; j < W * H; j++) { + if ((j % W < W - 1 && Info_h.biWidth % 2) || !(Info_h.biWidth % 2)) { + image->comps[0].data[index] = table_R[RGB[W * H - ((j) / (W) + 1) * W + (j) % (W)]]; + index++; + } + } + + } else { + index = 0; + for (j = 0; j < W * H; j++) { + if ((j % W < W - 1 && Info_h.biWidth % 2) || !(Info_h.biWidth % 2)) { + unsigned char pixel_index = RGB[W * H - ((j) / (W) + 1) * W + (j) % (W)]; + image->comps[0].data[index] = table_R[pixel_index]; + image->comps[1].data[index] = table_G[pixel_index]; + image->comps[2].data[index] = table_B[pixel_index]; + index++; + } + } + } + free(RGB); + free(table_R); + free(table_G); + free(table_B); + } else if (Info_h.biBitCount == 8 && Info_h.biCompression == 1) { + table_R = (unsigned char *) malloc(256 * sizeof(unsigned char)); + table_G = (unsigned char *) malloc(256 * sizeof(unsigned char)); + table_B = (unsigned char *) malloc(256 * sizeof(unsigned char)); + + for (j = 0; j < Info_h.biClrUsed; j++) { + table_B[j] = getc(IN); + table_G[j] = getc(IN); + table_R[j] = getc(IN); + getc(IN); + if (table_R[j] != table_G[j] && table_R[j] != table_B[j] && table_G[j] != table_B[j]) + gray_scale = 0; + } + + numcomps = gray_scale ? 1 : 3; + color_space = gray_scale ? CLRSPC_GRAY : CLRSPC_SRGB; + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(IN); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : image->x0 + (w - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : image->y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + /* Place the cursor at the beginning of the image information */ + fseek(IN, 0, SEEK_SET); + fseek(IN, File_h.bfOffBits, SEEK_SET); + + RGB = (unsigned char *) malloc(Info_h.biWidth * Info_h.biHeight * sizeof(unsigned char)); + + while (not_end_file) { + v = getc(IN); + if (v) { + v2 = getc(IN); + for (i = 0; i < (int) v; i++) { + RGB[line * Info_h.biWidth + col] = v2; + col++; + } + } else { + v = getc(IN); + switch (v) { + case 0: + col = 0; + line++; + break; + case 1: + line++; + not_end_file = 0; + break; + case 2: + fprintf(stderr,"No Delta supported\n"); + opj_image_destroy(image); + fclose(IN); + return NULL; + default: + for (i = 0; i < v; i++) { + v2 = getc(IN); + RGB[line * Info_h.biWidth + col] = v2; + col++; + } + if (v % 2) + v2 = getc(IN); + break; + } + } + } + if (gray_scale) { + index = 0; + for (line = 0; line < Info_h.biHeight; line++) { + for (col = 0; col < Info_h.biWidth; col++) { + image->comps[0].data[index] = table_R[(int)RGB[(Info_h.biHeight - line - 1) * Info_h.biWidth + col]]; + index++; + } + } + } else { + index = 0; + for (line = 0; line < Info_h.biHeight; line++) { + for (col = 0; col < Info_h.biWidth; col++) { + unsigned char pixel_index = (int)RGB[(Info_h.biHeight - line - 1) * Info_h.biWidth + col]; + image->comps[0].data[index] = table_R[pixel_index]; + image->comps[1].data[index] = table_G[pixel_index]; + image->comps[2].data[index] = table_B[pixel_index]; + index++; + } + } + } + free(RGB); + free(table_R); + free(table_G); + free(table_B); + } else { + fprintf(stderr, + "Other system than 24 bits/pixels or 8 bits (no RLE coding) is not yet implemented [%d]\n", Info_h.biBitCount); + } + fclose(IN); + } + + return image; +} + +int imagetobmp(opj_image_t * image, const char *outfile) { + int w, h; + int i, pad; + FILE *fdest = NULL; + int adjustR, adjustG, adjustB; + + if (image->numcomps == 3 && image->comps[0].dx == image->comps[1].dx + && image->comps[1].dx == image->comps[2].dx + && image->comps[0].dy == image->comps[1].dy + && image->comps[1].dy == image->comps[2].dy + && image->comps[0].prec == image->comps[1].prec + && image->comps[1].prec == image->comps[2].prec) { + + /* -->> -->> -->> -->> + 24 bits color + <<-- <<-- <<-- <<-- */ + + fdest = fopen(outfile, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } + + w = image->comps[0].w; + h = image->comps[0].h; + + fprintf(fdest, "BM"); + + /* FILE HEADER */ + /* ------------- */ + fprintf(fdest, "%c%c%c%c", + (unsigned char) (h * w * 3 + 3 * h * (w % 2) + 54) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 8) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 16) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2) + 54) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,((54) >> 16) & 0xff, ((54) >> 24) & 0xff); + + /* INFO HEADER */ + /* ------------- */ + fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) ((w) & 0xff), + (unsigned char) ((w) >> 8) & 0xff, + (unsigned char) ((w) >> 16) & 0xff, + (unsigned char) ((w) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) ((h) & 0xff), + (unsigned char) ((h) >> 8) & 0xff, + (unsigned char) ((h) >> 16) & 0xff, + (unsigned char) ((h) >> 24) & 0xff); + fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff); + fprintf(fdest, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) (3 * h * w + 3 * h * (w % 2)) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2)) >> 8) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2)) >> 16) & 0xff, + (unsigned char) ((h * w * 3 + 3 * h * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + + if (image->comps[0].prec > 8) { + adjustR = image->comps[0].prec - 8; + printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); + } + else + adjustR = 0; + if (image->comps[1].prec > 8) { + adjustG = image->comps[1].prec - 8; + printf("BMP CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec); + } + else + adjustG = 0; + if (image->comps[2].prec > 8) { + adjustB = image->comps[2].prec - 8; + printf("BMP CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec); + } + else + adjustB = 0; + + for (i = 0; i < w * h; i++) { + unsigned char rc, gc, bc; + int r, g, b; + + r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; + r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); + rc = (unsigned char) ((r >> adjustR)+((r >> (adjustR-1))%2)); + g = image->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; + g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); + gc = (unsigned char) ((g >> adjustG)+((g >> (adjustG-1))%2)); + b = image->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; + b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); + bc = (unsigned char) ((b >> adjustB)+((b >> (adjustB-1))%2)); + + fprintf(fdest, "%c%c%c", bc, gc, rc); + + if ((i + 1) % w == 0) { + for (pad = (3 * w) % 4 ? 4 - (3 * w) % 4 : 0; pad > 0; pad--) /* ADD */ + fprintf(fdest, "%c", 0); + } + } + fclose(fdest); + } else { /* Gray-scale */ + + /* -->> -->> -->> -->> + 8 bits non code (Gray scale) + <<-- <<-- <<-- <<-- */ + + fdest = fopen(outfile, "wb"); + w = image->comps[0].w; + h = image->comps[0].h; + + fprintf(fdest, "BM"); + + /* FILE HEADER */ + /* ------------- */ + fprintf(fdest, "%c%c%c%c", (unsigned char) (h * w + 54 + 1024 + h * (w % 2)) & 0xff, + (unsigned char) ((h * w + 54 + 1024 + h * (w % 2)) >> 8) & 0xff, + (unsigned char) ((h * w + 54 + 1024 + h * (w % 2)) >> 16) & 0xff, + (unsigned char) ((h * w + 54 + 1024 + w * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (54 + 1024) & 0xff, ((54 + 1024) >> 8) & 0xff, + ((54 + 1024) >> 16) & 0xff, + ((54 + 1024) >> 24) & 0xff); + + /* INFO HEADER */ + /* ------------- */ + fprintf(fdest, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff, ((40) >> 16) & 0xff, ((40) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) ((w) & 0xff), + (unsigned char) ((w) >> 8) & 0xff, + (unsigned char) ((w) >> 16) & 0xff, + (unsigned char) ((w) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) ((h) & 0xff), + (unsigned char) ((h) >> 8) & 0xff, + (unsigned char) ((h) >> 16) & 0xff, + (unsigned char) ((h) >> 24) & 0xff); + fprintf(fdest, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff); + fprintf(fdest, "%c%c", (8) & 0xff, ((8) >> 8) & 0xff); + fprintf(fdest, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff, ((0) >> 16) & 0xff, ((0) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (unsigned char) (h * w + h * (w % 2)) & 0xff, + (unsigned char) ((h * w + h * (w % 2)) >> 8) & 0xff, + (unsigned char) ((h * w + h * (w % 2)) >> 16) & 0xff, + (unsigned char) ((h * w + h * (w % 2)) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff, ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); + fprintf(fdest, "%c%c%c%c", (256) & 0xff, ((256) >> 8) & 0xff, ((256) >> 16) & 0xff, ((256) >> 24) & 0xff); + + if (image->comps[0].prec > 8) { + adjustR = image->comps[0].prec - 8; + printf("BMP CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); + } + + for (i = 0; i < 256; i++) { + fprintf(fdest, "%c%c%c%c", i, i, i, 0); + } + + for (i = 0; i < w * h; i++) { + unsigned char rc; + int r; + + r = image->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)]; + r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); + rc = (unsigned char) ((r >> adjustR)+((r >> (adjustR-1))%2)); + + fprintf(fdest, "%c", rc); + + if ((i + 1) % w == 0) { + for (pad = w % 4 ? 4 - w % 4 : 0; pad > 0; pad--) /* ADD */ + fprintf(fdest, "%c", 0); + } + } + fclose(fdest); + } + + return 0; +} + +/* -->> -->> -->> -->> + +PGX IMAGE FORMAT + +<<-- <<-- <<-- <<-- */ + + +unsigned char readuchar(FILE * f) +{ + unsigned char c1; + fread(&c1, 1, 1, f); + return c1; +} + +unsigned short readushort(FILE * f, int bigendian) +{ + unsigned char c1, c2; + fread(&c1, 1, 1, f); + fread(&c2, 1, 1, f); + if (bigendian) + return (c1 << 8) + c2; + else + return (c2 << 8) + c1; +} + +unsigned int readuint(FILE * f, int bigendian) +{ + unsigned char c1, c2, c3, c4; + fread(&c1, 1, 1, f); + fread(&c2, 1, 1, f); + fread(&c3, 1, 1, f); + fread(&c4, 1, 1, f); + if (bigendian) + return (c1 << 24) + (c2 << 16) + (c3 << 8) + c4; + else + return (c4 << 24) + (c3 << 16) + (c2 << 8) + c1; +} + +opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters) { + FILE *f = NULL; + int w, h, prec; + int i, numcomps, max; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm; /* maximum of 1 component */ + opj_image_t * image = NULL; + + char endian1,endian2,sign; + char signtmp[32]; + + char temp[32]; + int bigendian; + opj_image_comp_t *comp = NULL; + + numcomps = 1; + color_space = CLRSPC_GRAY; + + memset(&cmptparm, 0, sizeof(opj_image_cmptparm_t)); + + max = 0; + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "Failed to open %s for reading !\n", filename); + return NULL; + } + + fseek(f, 0, SEEK_SET); + fscanf(f, "PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d",temp,&endian1,&endian2,signtmp,&prec,temp,&w,temp,&h); + + i=0; + sign='+'; + while (signtmp[i]!='\0') { + if (signtmp[i]=='-') sign='-'; + i++; + } + + fgetc(f); + if (endian1=='M' && endian2=='L') { + bigendian = 1; + } else if (endian2=='M' && endian1=='L') { + bigendian = 0; + } else { + fprintf(stderr, "Bad pgx header, please check input file\n"); + return NULL; + } + + /* initialize image component */ + + cmptparm.x0 = parameters->image_offset_x0; + cmptparm.y0 = parameters->image_offset_y0; + cmptparm.w = !cmptparm.x0 ? (w - 1) * parameters->subsampling_dx + 1 : cmptparm.x0 + (w - 1) * parameters->subsampling_dx + 1; + cmptparm.h = !cmptparm.y0 ? (h - 1) * parameters->subsampling_dy + 1 : cmptparm.y0 + (h - 1) * parameters->subsampling_dy + 1; + + if (sign == '-') { + cmptparm.sgnd = 1; + } else { + cmptparm.sgnd = 0; + } + cmptparm.prec = prec; + cmptparm.bpp = prec; + cmptparm.dx = parameters->subsampling_dx; + cmptparm.dy = parameters->subsampling_dy; + + /* create the image */ + image = opj_image_create(numcomps, &cmptparm, color_space); + if(!image) { + fclose(f); + return NULL; + } + /* set image offset and reference grid */ + image->x0 = cmptparm.x0; + image->y0 = cmptparm.x0; + image->x1 = cmptparm.w; + image->y1 = cmptparm.h; + + /* set image data */ + + comp = &image->comps[0]; + + for (i = 0; i < w * h; i++) { + int v; + if (comp->prec <= 8) { + if (!comp->sgnd) { + v = readuchar(f); + } else { + v = (char) readuchar(f); + } + } else if (comp->prec <= 16) { + if (!comp->sgnd) { + v = readushort(f, bigendian); + } else { + v = (short) readushort(f, bigendian); + } + } else { + if (!comp->sgnd) { + v = readuint(f, bigendian); + } else { + v = (int) readuint(f, bigendian); + } + } + if (v > max) + max = v; + comp->data[i] = v; + } + fclose(f); + //comp->bpp = int_floorlog2(max) + 1; + + return image; +} + +int imagetopgx(opj_image_t * image, const char *outfile) { + int w, h; + int i, j, compno; + FILE *fdest = NULL; + + for (compno = 0; compno < image->numcomps; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + char bname[256]; /* buffer for name */ + char *name = bname; /* pointer */ + int nbytes = 0; + const size_t olen = strlen(outfile); + const size_t dotpos = olen - 4; + const size_t total = dotpos + 1 + 1 + 4; /* '-' + '[1-3]' + '.pgx' */ + if( outfile[dotpos] != '.' ) { + /* `pgx` was recognized but there is no dot at expected position */ + fprintf(stderr, "ERROR -> Impossible happen." ); + return 1; + } + if( total > 256 ) { + name = (char*)malloc(total+1); + } + strncpy(name, outfile, dotpos); + if (image->numcomps > 1) { + sprintf(name+dotpos, "-%d.pgx", compno); + } else { + strcpy(name+dotpos, ".pgx"); + } + fdest = fopen(name, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", name); + return 1; + } + /* dont need name anymore */ + if( total > 256 ) { + free(name); + } + + w = image->comps[compno].w; + h = image->comps[compno].h; + + fprintf(fdest, "PG ML %c %d %d %d\n", comp->sgnd ? '-' : '+', comp->prec, w, h); + if (comp->prec <= 8) { + nbytes = 1; + } else if (comp->prec <= 16) { + nbytes = 2; + } else { + nbytes = 4; + } + for (i = 0; i < w * h; i++) { + int v = image->comps[compno].data[i]; + for (j = nbytes - 1; j >= 0; j--) { + char byte = (char) (v >> (j * 8)); + fwrite(&byte, 1, 1, fdest); + } + } + fclose(fdest); + } + + return 0; +} + +/* -->> -->> -->> -->> + +PNM IMAGE FORMAT + +<<-- <<-- <<-- <<-- */ + +opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters) { + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + FILE *f = NULL; + int i, compno, numcomps, w, h; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ + opj_image_t * image = NULL; + char value; + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + return 0; + } + + if (fgetc(f) != 'P') + return 0; + value = fgetc(f); + + switch(value) { + case '2': /* greyscale image type */ + case '5': + numcomps = 1; + color_space = CLRSPC_GRAY; + break; + + case '3': /* RGB image type */ + case '6': + numcomps = 3; + color_space = CLRSPC_SRGB; + break; + + default: + fclose(f); + return NULL; + } + + fgetc(f); + + /* skip comments */ + while(fgetc(f) == '#') while(fgetc(f) != '\n'); + + fseek(f, -1, SEEK_CUR); + fscanf(f, "%d %d\n255", &w, &h); + fgetc(f); /* */ + + /* initialize image components */ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = 8; + cmptparm[i].bpp = 8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(f); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + /* set image data */ + + if ((value == '2') || (value == '3')) { /* ASCII */ + for (i = 0; i < w * h; i++) { + for(compno = 0; compno < numcomps; compno++) { + unsigned int index = 0; + fscanf(f, "%u", &index); + /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ + image->comps[compno].data[i] = index; + } + } + } else if ((value == '5') || (value == '6')) { /* BINARY */ + for (i = 0; i < w * h; i++) { + for(compno = 0; compno < numcomps; compno++) { + unsigned char index = 0; + fread(&index, 1, 1, f); + /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */ + image->comps[compno].data[i] = index; + } + } + } + + fclose(f); + + return image; +} + +int imagetopnm(opj_image_t * image, const char *outfile) { + int w, wr, h, hr, max; + int i, compno; + int adjustR, adjustG, adjustB, adjustX; + FILE *fdest = NULL; + char S2; + const char *tmp = outfile; + + while (*tmp) { + tmp++; + } + tmp--; + tmp--; + S2 = *tmp; + + if (image->numcomps == 3 && image->comps[0].dx == image->comps[1].dx + && image->comps[1].dx == image->comps[2].dx + && image->comps[0].dy == image->comps[1].dy + && image->comps[1].dy == image->comps[2].dy + && image->comps[0].prec == image->comps[1].prec + && image->comps[1].prec == image->comps[2].prec + && S2 !='g' && S2 !='G') { + + fdest = fopen(outfile, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } + + w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx); + wr = image->comps[0].w; + + h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy); + hr = image->comps[0].h; + + max = image->comps[0].prec > 8 ? 255 : (1 << image->comps[0].prec) - 1; + + image->comps[0].x0 = int_ceildivpow2(image->comps[0].x0 - int_ceildiv(image->x0, image->comps[0].dx), image->comps[0].factor); + image->comps[0].y0 = int_ceildivpow2(image->comps[0].y0 - int_ceildiv(image->y0, image->comps[0].dy), image->comps[0].factor); + + fprintf(fdest, "P6\n%d %d\n%d\n", wr, hr, max); + + if (image->comps[0].prec > 8) { + adjustR = image->comps[0].prec - 8; + printf("PNM CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); + } + else + adjustR = 0; + if (image->comps[1].prec > 8) { + adjustG = image->comps[1].prec - 8; + printf("PNM CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec); + } + else + adjustG = 0; + if (image->comps[2].prec > 8) { + adjustB = image->comps[2].prec - 8; + printf("PNM CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec); + } + else + adjustB = 0; + + + for (i = 0; i < wr * hr; i++) { + int r, g, b; + unsigned char rc,gc,bc; + r = image->comps[0].data[i]; + r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); + rc = (unsigned char) ((r >> adjustR)+((r >> (adjustR-1))%2)); + + g = image->comps[1].data[i]; + g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); + gc = (unsigned char) ((g >> adjustG)+((g >> (adjustG-1))%2)); + + b = image->comps[2].data[i]; + b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); + bc = (unsigned char) ((b >> adjustB)+((b >> (adjustB-1))%2)); + + fprintf(fdest, "%c%c%c", rc, gc, bc); + } + fclose(fdest); + + } else { + int ncomp=(S2=='g' || S2=='G')?1:image->numcomps; + if (image->numcomps > ncomp) { + fprintf(stderr,"WARNING -> [PGM files] Only the first component\n"); + fprintf(stderr," is written to the file\n"); + } + for (compno = 0; compno < ncomp; compno++) { + char name[256]; + if (ncomp > 1) { + sprintf(name, "%d.%s", compno, outfile); + } else { + sprintf(name, "%s", outfile); + } + + fdest = fopen(name, "wb"); + if (!fdest) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", name); + return 1; + } + + w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx); + wr = image->comps[compno].w; + + h = int_ceildiv(image->y1 - image->y0, image->comps[compno].dy); + hr = image->comps[compno].h; + + max = image->comps[compno].prec > 8 ? 255 : (1 << image->comps[compno].prec) - 1; + + image->comps[compno].x0 = int_ceildivpow2(image->comps[compno].x0 - int_ceildiv(image->x0, image->comps[compno].dx), image->comps[compno].factor); + image->comps[compno].y0 = int_ceildivpow2(image->comps[compno].y0 - int_ceildiv(image->y0, image->comps[compno].dy), image->comps[compno].factor); + + fprintf(fdest, "P5\n%d %d\n%d\n", wr, hr, max); + + if (image->comps[compno].prec > 8) { + adjustX = image->comps[0].prec - 8; + printf("PNM CONVERSION: Truncating component %d from %d bits to 8 bits\n",compno, image->comps[compno].prec); + } + else + adjustX = 0; + + for (i = 0; i < wr * hr; i++) { + int l; + unsigned char lc; + l = image->comps[compno].data[i]; + l += (image->comps[compno].sgnd ? 1 << (image->comps[compno].prec - 1) : 0); + lc = (unsigned char) ((l >> adjustX)+((l >> (adjustX-1))%2)); + fprintf(fdest, "%c", lc); + } + fclose(fdest); + } + } + + return 0; +} + +/* -->> -->> -->> -->> + + TIFF IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +typedef struct tiff_infoheader{ + DWORD tiWidth; // Width of Image in pixel + DWORD tiHeight; // Height of Image in pixel + DWORD tiPhoto; // Photometric + WORD tiBps; // Bits per sample + WORD tiSf; // Sample Format + WORD tiSpp; // Sample per pixel 1-bilevel,gray scale , 2- RGB + WORD tiPC; // Planar config (1-Interleaved, 2-Planarcomp) +}tiff_infoheader_t; + +int imagetotif(opj_image_t * image, const char *outfile) { + int width, height, imgsize; + int bps,index,adjust = 0; + int last_i=0; + TIFF *tif; + tdata_t buf; + tstrip_t strip; + tsize_t strip_size; + + if (image->numcomps == 3 && image->comps[0].dx == image->comps[1].dx + && image->comps[1].dx == image->comps[2].dx + && image->comps[0].dy == image->comps[1].dy + && image->comps[1].dy == image->comps[2].dy + && image->comps[0].prec == image->comps[1].prec + && image->comps[1].prec == image->comps[2].prec) { + + /* -->> -->> -->> + RGB color + <<-- <<-- <<-- */ + + tif = TIFFOpen(outfile, "wb"); + if (!tif) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } + + width = image->comps[0].w; + height = image->comps[0].h; + imgsize = width * height ; + bps = image->comps[0].prec; + /* Set tags */ + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); + + /* Get a buffer for the data */ + strip_size=TIFFStripSize(tif); + buf = _TIFFmalloc(strip_size); + index=0; + adjust = image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0; + for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) { + unsigned char *dat8; + int i, ssize; + ssize = TIFFStripSize(tif); + dat8 = buf; + if (image->comps[0].prec == 8){ + for (i=0; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + } + dat8[i+0] = r ; // R + dat8[i+1] = g ; // G + dat8[i+2] = b ; // B + index++; + last_i = i+3; + }else + break; + } + if(last_i < ssize){ + for (i=last_i; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + } + dat8[i+0] = r ; // R + if(i+1 comps[0].prec == 12){ + for (i=0; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + r1 = image->comps[0].data[index+1]; + g1 = image->comps[1].data[index+1]; + b1 = image->comps[2].data[index+1]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + r1 += adjust; + g1 += adjust; + b1 += adjust; + } + dat8[i+0] = (r >> 4); + dat8[i+1] = ((r & 0x0f) << 4 )|((g >> 8)& 0x0f); + dat8[i+2] = g ; + dat8[i+3] = (b >> 4); + dat8[i+4] = ((b & 0x0f) << 4 )|((r1 >> 8)& 0x0f); + dat8[i+5] = r1; + dat8[i+6] = (g1 >> 4); + dat8[i+7] = ((g1 & 0x0f)<< 4 )|((b1 >> 8)& 0x0f); + dat8[i+8] = b1; + index+=2; + last_i = i+9; + }else + break; + } + if(last_i < ssize){ + for (i= last_i; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + r1 = image->comps[0].data[index+1]; + g1 = image->comps[1].data[index+1]; + b1 = image->comps[2].data[index+1]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + r1 += adjust; + g1 += adjust; + b1 += adjust; + } + dat8[i+0] = (r >> 4); + if(i+1 > 8)& 0x0f); else break; + if(i+2 > 4); else break; + if(i+4 > 8)& 0x0f);else break; + if(i+5 > 4); else break; + if(i+7 > 8)& 0x0f);else break; + if(i+8 comps[0].prec == 16){ + for (i=0 ; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + } + dat8[i+0] = r;//LSB + dat8[i+1] = (r >> 8);//MSB + dat8[i+2] = g; + dat8[i+3] = (g >> 8); + dat8[i+4] = b; + dat8[i+5] = (b >> 8); + index++; + last_i = i+6; + }else + break; + } + if(last_i < ssize){ + for (i=0 ; icomps[0].data[index]; + g = image->comps[1].data[index]; + b = image->comps[2].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + g += adjust; + b += adjust; + } + dat8[i+0] = r;//LSB + if(i+1 > 8);else break;//MSB + if(i+2 > 8);else break; + if(i+4 > 8);else break; + index++; + }else + break; + } + } + }else{ + fprintf(stderr,"Bits=%d, Only 8,12,16 bits implemented\n",image->comps[0].prec); + fprintf(stderr,"Aborting\n"); + return 1; + } + TIFFWriteEncodedStrip(tif, strip, buf, strip_size); + } + _TIFFfree(buf); + TIFFClose(tif); + }else if (image->numcomps == 1){ + /* -->> -->> -->> + Black and White + <<-- <<-- <<-- */ + + tif = TIFFOpen(outfile, "wb"); + if (!tif) { + fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile); + return 1; + } + + width = image->comps[0].w; + height = image->comps[0].h; + imgsize = width * height; + bps = image->comps[0].prec; + + /* Set tags */ + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1); + + /* Get a buffer for the data */ + strip_size = TIFFStripSize(tif); + buf = _TIFFmalloc(strip_size); + index = 0; + for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) { + unsigned char *dat8; + int i; + dat8 = buf; + if (image->comps[0].prec == 8){ + for (i=0; icomps[0].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + } + dat8[i+0] = r; + index++; + }else + break; + } + }else if (image->comps[0].prec == 12){ + for (i = 0; icomps[0].data[index]; + r1 = image->comps[0].data[index+1]; + if (image->comps[0].sgnd){ + r += adjust; + r1 += adjust; + } + dat8[i+0] = (r >> 4); + dat8[i+1] = ((r & 0x0f) << 4 )|((r1 >> 8)& 0x0f); + dat8[i+2] = r1 ; + index+=2; + }else + break; + } + }else if (image->comps[0].prec == 16){ + for (i=0; icomps[0].data[index]; + if (image->comps[0].sgnd){ + r += adjust; + } + dat8[i+0] = r; + dat8[i+1] = r >> 8; + index++; + }else + break; + } + }else{ + fprintf(stderr,"TIFF file creation. Bits=%d, Only 8,12,16 bits implemented\n",image->comps[0].prec); + fprintf(stderr,"Aborting\n"); + return 1; + } + TIFFWriteEncodedStrip(tif, strip, buf, strip_size); + } + _TIFFfree(buf); + TIFFClose(tif); + }else{ + fprintf(stderr,"TIFF file creation. Bad color format. Only RGB & Grayscale has been implemented\n"); + fprintf(stderr,"Aborting\n"); + return 1; + } + return 0; +} + +opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters) +{ + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + TIFF *tif; + tiff_infoheader_t Info; + tdata_t buf; + tstrip_t strip; + tsize_t strip_size; + int j, numcomps, w, h,index; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; + opj_image_t * image = NULL; + int imgsize = 0; + + tif = TIFFOpen(filename, "r"); + + if (!tif) { + fprintf(stderr, "Failed to open %s for reading\n", filename); + return 0; + } + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &Info.tiWidth); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &Info.tiHeight); + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &Info.tiBps); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &Info.tiSf); + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &Info.tiSpp); + Info.tiPhoto = 0; + TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &Info.tiPhoto); + TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &Info.tiPC); + w= Info.tiWidth; + h= Info.tiHeight; + + if (Info.tiPhoto == 2) { + /* -->> -->> -->> + RGB color + <<-- <<-- <<-- */ + + numcomps = 3; + color_space = CLRSPC_SRGB; + /* initialize image components*/ + memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t)); + for(j = 0; j < numcomps; j++) { + if (parameters->cp_cinema) { + cmptparm[j].prec = 12; + cmptparm[j].bpp = 12; + }else{ + cmptparm[j].prec = Info.tiBps; + cmptparm[j].bpp = Info.tiBps; + } + cmptparm[j].sgnd = 0; + cmptparm[j].dx = subsampling_dx; + cmptparm[j].dy = subsampling_dy; + cmptparm[j].w = w; + cmptparm[j].h = h; + } + /* create the image*/ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + TIFFClose(tif); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : image->x0 + (w - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : image->y0 + (h - 1) * subsampling_dy + 1; + + buf = _TIFFmalloc(TIFFStripSize(tif)); + strip_size=0; + strip_size=TIFFStripSize(tif); + index = 0; + imgsize = image->comps[0].w * image->comps[0].h ; + /* Read the Image components*/ + for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) { + unsigned char *dat8; + int i, ssize; + ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size); + dat8 = buf; + + if (Info.tiBps==12){ + for (i=0; icomps[0].data[index] = ( dat8[i+0]<<4 ) |(dat8[i+1]>>4); + image->comps[1].data[index] = ((dat8[i+1]& 0x0f)<< 8) | dat8[i+2]; + image->comps[2].data[index] = ( dat8[i+3]<<4) |(dat8[i+4]>>4); + image->comps[0].data[index+1] = ((dat8[i+4]& 0x0f)<< 8) | dat8[i+5]; + image->comps[1].data[index+1] = ( dat8[i+6] <<4) |(dat8[i+7]>>4); + image->comps[2].data[index+1] = ((dat8[i+7]& 0x0f)<< 8) | dat8[i+8]; + index+=2; + }else + break; + } + } + else if( Info.tiBps==16){ + for (i=0; icomps[0].data[index] = ( dat8[i+1] << 8 ) | dat8[i+0]; // R + image->comps[1].data[index] = ( dat8[i+3] << 8 ) | dat8[i+2]; // G + image->comps[2].data[index] = ( dat8[i+5] << 8 ) | dat8[i+4]; // B + if(parameters->cp_cinema){/* Rounding to 12 bits*/ + image->comps[0].data[index] = (image->comps[0].data[index] + 0x08) >> 4 ; + image->comps[1].data[index] = (image->comps[1].data[index] + 0x08) >> 4 ; + image->comps[2].data[index] = (image->comps[2].data[index] + 0x08) >> 4 ; + } + index++; + }else + break; + } + } + else if ( Info.tiBps==8){ + for (i=0; icomps[0].data[index] = dat8[i+0];// R + image->comps[1].data[index] = dat8[i+1];// G + image->comps[2].data[index] = dat8[i+2];// B + if(parameters->cp_cinema){/* Rounding to 12 bits*/ + image->comps[0].data[index] = image->comps[0].data[index] << 4 ; + image->comps[1].data[index] = image->comps[1].data[index] << 4 ; + image->comps[2].data[index] = image->comps[2].data[index] << 4 ; + } + index++; + }else + break; + } + } + else{ + fprintf(stderr,"TIFF file creation. Bits=%d, Only 8,12,16 bits implemented\n",Info.tiBps); + fprintf(stderr,"Aborting\n"); + return NULL; + } + } + + _TIFFfree(buf); + TIFFClose(tif); + }else if(Info.tiPhoto == 1) { + /* -->> -->> -->> + Black and White + <<-- <<-- <<-- */ + + numcomps = 1; + color_space = CLRSPC_GRAY; + /* initialize image components*/ + memset(&cmptparm[0], 0, sizeof(opj_image_cmptparm_t)); + cmptparm[0].prec = Info.tiBps; + cmptparm[0].bpp = Info.tiBps; + cmptparm[0].sgnd = 0; + cmptparm[0].dx = subsampling_dx; + cmptparm[0].dy = subsampling_dy; + cmptparm[0].w = w; + cmptparm[0].h = h; + + /* create the image*/ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + TIFFClose(tif); + return NULL; + } + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = !image->x0 ? (w - 1) * subsampling_dx + 1 : image->x0 + (w - 1) * subsampling_dx + 1; + image->y1 = !image->y0 ? (h - 1) * subsampling_dy + 1 : image->y0 + (h - 1) * subsampling_dy + 1; + + buf = _TIFFmalloc(TIFFStripSize(tif)); + strip_size = 0; + strip_size = TIFFStripSize(tif); + index = 0; + imgsize = image->comps[0].w * image->comps[0].h ; + /* Read the Image components*/ + for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) { + unsigned char *dat8; + int i, ssize; + ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size); + dat8 = buf; + + if (Info.tiBps==12){ + for (i=0; icomps[0].data[index] = ( dat8[i+0]<<4 ) |(dat8[i+1]>>4) ; + image->comps[0].data[index+1] = ((dat8[i+1]& 0x0f)<< 8) | dat8[i+2]; + index+=2; + }else + break; + } + } + else if( Info.tiBps==16){ + for (i=0; icomps[0].data[index] = ( dat8[i+1] << 8 ) | dat8[i+0]; + index++; + }else + break; + } + } + else if ( Info.tiBps==8){ + for (i=0; icomps[0].data[index] = dat8[i+0]; + index++; + }else + break; + } + } + else{ + fprintf(stderr,"TIFF file creation. Bits=%d, Only 8,12,16 bits implemented\n",Info.tiBps); + fprintf(stderr,"Aborting\n"); + return NULL; + } + } + + _TIFFfree(buf); + TIFFClose(tif); + }else{ + fprintf(stderr,"TIFF file creation. Bad color format. Only RGB & Grayscale has been implemented\n"); + fprintf(stderr,"Aborting\n"); + return NULL; + } + return image; +} + +/* -->> -->> -->> -->> + + RAW IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) { + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + FILE *f = NULL; + int i, compno, numcomps, w, h; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t *cmptparm; + opj_image_t * image = NULL; + unsigned short ch; + + if((! (raw_cp->rawWidth & raw_cp->rawHeight & raw_cp->rawComp & raw_cp->rawBitDepth)) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); + fprintf(stderr,"Aborting\n"); + return NULL; + } + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + fprintf(stderr,"Aborting\n"); + return NULL; + } + numcomps = raw_cp->rawComp; + color_space = CLRSPC_SRGB; + w = raw_cp->rawWidth; + h = raw_cp->rawHeight; + cmptparm = (opj_image_cmptparm_t*) malloc(numcomps * sizeof(opj_image_cmptparm_t)); + + /* initialize image components */ + memset(&cmptparm[0], 0, numcomps * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = raw_cp->rawBitDepth; + cmptparm[i].bpp = raw_cp->rawBitDepth; + cmptparm[i].sgnd = raw_cp->rawSigned; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(f); + return NULL; + } + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + if(raw_cp->rawBitDepth <= 8) + { + unsigned char value = 0; + for(compno = 0; compno < numcomps; compno++) { + for (i = 0; i < w * h; i++) { + if (!fread(&value, 1, 1, f)) { + fprintf(stderr,"Error reading raw file. End of file probably reached.\n"); + return NULL; + } + image->comps[compno].data[i] = raw_cp->rawSigned?(char)value:value; + } + } + } + else + { + unsigned short value = 0; + for(compno = 0; compno < numcomps; compno++) { + for (i = 0; i < w * h; i++) { + if (!fread(&value, 2, 1, f)) { + fprintf(stderr,"Error reading raw file. End of file probably reached.\n"); + return NULL; + } + image->comps[compno].data[i] = raw_cp->rawSigned?(short)value:value; + } + } + } + + if (fread(&ch, 1, 1, f)) { + fprintf(stderr,"Warning. End of raw file not reached... processing anyway\n"); + } + fclose(f); + + return image; +} + +int imagetoraw(opj_image_t * image, const char *outfile) +{ + FILE *rawFile = NULL; + int compno; + int w, h; + int line, row; + int *ptr; + + if((image->numcomps * image->x1 * image->y1) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + return 1; + } + + rawFile = fopen(outfile, "wb"); + if (!rawFile) { + fprintf(stderr, "Failed to open %s for writing !!\n", outfile); + return 1; + } + + fprintf(stdout,"Raw image characteristics: %d components\n", image->numcomps); + + for(compno = 0; compno < image->numcomps; compno++) + { + fprintf(stdout,"Component %d characteristics: %dx%dx%d %s\n", compno, image->comps[compno].w, + image->comps[compno].h, image->comps[compno].prec, image->comps[compno].sgnd==1 ? "signed": "unsigned"); + + w = image->comps[compno].w; + h = image->comps[compno].h; + + if(image->comps[compno].prec <= 8) + { + if(image->comps[compno].sgnd == 1) + { + signed char curr; + int mask = (1 << image->comps[compno].prec) - 1; + ptr = image->comps[compno].data; + for (line = 0; line < h; line++) { + for(row = 0; row < w; row++) { + curr = (signed char) (*ptr & mask); + fwrite(&curr, sizeof(signed char), 1, rawFile); + ptr++; + } + } + } + else if(image->comps[compno].sgnd == 0) + { + unsigned char curr; + int mask = (1 << image->comps[compno].prec) - 1; + ptr = image->comps[compno].data; + for (line = 0; line < h; line++) { + for(row = 0; row < w; row++) { + curr = (unsigned char) (*ptr & mask); + fwrite(&curr, sizeof(unsigned char), 1, rawFile); + ptr++; + } + } + } + } + else if(image->comps[compno].prec <= 16) + { + if(image->comps[compno].sgnd == 1) + { + signed short int curr; + int mask = (1 << image->comps[compno].prec) - 1; + ptr = image->comps[compno].data; + for (line = 0; line < h; line++) { + for(row = 0; row < w; row++) { + curr = (signed short int) (*ptr & mask); + fwrite(&curr, sizeof(signed short int), 1, rawFile); + ptr++; + } + } + } + else if(image->comps[compno].sgnd == 0) + { + unsigned short int curr; + int mask = (1 << image->comps[compno].prec) - 1; + ptr = image->comps[compno].data; + for (line = 0; line < h; line++) { + for(row = 0; row < w; row++) { + curr = (unsigned short int) (*ptr & mask); + fwrite(&curr, sizeof(unsigned short int), 1, rawFile); + ptr++; + } + } + } + } + else if (image->comps[compno].prec <= 32) + { + fprintf(stderr,"More than 16 bits per component no handled yet\n"); + return 1; + } + else + { + fprintf(stderr,"Error: invalid precision: %d\n", image->comps[compno].prec); + return 1; + } + } + fclose(rawFile); + return 0; +} diff --git a/v2/codec/convert.h b/v2/codec/convert.h new file mode 100755 index 00000000..99eaf1ad --- /dev/null +++ b/v2/codec/convert.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __J2K_CONVERT_H +#define __J2K_CONVERT_H + +/**@name RAW image encoding parameters */ +/*@{*/ +typedef struct raw_cparameters { + /** width of the raw image */ + int rawWidth; + /** height of the raw image */ + int rawHeight; + /** components of the raw image */ + int rawComp; + /** bit depth of the raw image */ + int rawBitDepth; + /** signed/unsigned raw image */ + bool rawSigned; + /*@}*/ +} raw_cparameters_t; + +/* TGA conversion */ +opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters); +int imagetotga(opj_image_t * image, const char *outfile); + +/* BMP conversion */ +opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters); +int imagetobmp(opj_image_t *image, const char *outfile); + +/* TIFF to image conversion*/ +opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters); +int imagetotif(opj_image_t *image, const char *outfile); +/** +Load a single image component encoded in PGX file format +@param filename Name of the PGX file to load +@param parameters *List ?* +@return Returns a greyscale image if successful, returns NULL otherwise +*/ +opj_image_t* pgxtoimage(const char *filename, opj_cparameters_t *parameters); +int imagetopgx(opj_image_t *image, const char *outfile); + +opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters); +int imagetopnm(opj_image_t *image, const char *outfile); + +/* RAW conversion */ +int imagetoraw(opj_image_t * image, const char *outfile); +opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp); + +#endif /* __J2K_CONVERT_H */ + diff --git a/v2/codec/dirent.h b/v2/codec/dirent.h new file mode 100755 index 00000000..a2b9176f --- /dev/null +++ b/v2/codec/dirent.h @@ -0,0 +1,677 @@ + +/* + * uce-dirent.h - operating system independent dirent implementation + * + * Copyright (C) 1998-2002 Toni Ronkko + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * ``Software''), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + * May 28 1998, Toni Ronkko + * + * $Id: uce-dirent.h,v 1.7 2002/05/13 10:48:35 tr Exp $ + * + * $Log: uce-dirent.h,v $ + * Revision 1.7 2002/05/13 10:48:35 tr + * embedded some source code directly to the header so that no source + * modules need to be included in the MS Visual C project using the + * interface, removed all the dependencies to other headers of the `uce' + * library so that the header can be made public + * + * Revision 1.6 2002/04/12 16:22:04 tr + * Unified Compiling Environment (UCE) replaced `std' library + * + * Revision 1.5 2001/07/20 16:33:40 tr + * moved to `std' library and re-named defines accordingly + * + * Revision 1.4 2001/07/10 16:47:18 tronkko + * revised comments + * + * Revision 1.3 2001/01/11 13:16:43 tr + * using ``uce-machine.h'' for finding out defines such as `FREEBSD' + * + * Revision 1.2 2000/10/08 16:00:41 tr + * copy of FreeBSD man page + * + * Revision 1.1 2000/07/10 05:53:16 tr + * Initial revision + * + * Revision 1.2 1998/07/19 18:29:14 tr + * Added error reporting capabilities and some asserts. + * + * Revision 1.1 1998/07/04 16:27:51 tr + * Initial revision + * + * + * MSVC 1.0 scans automatic dependencies incorrectly when your project + * contains this very header. The problem is that MSVC cannot handle + * include directives inside #if..#endif block those are never entered. + * Since this header ought to compile in many different operating systems, + * there had to be several conditional blocks that are compiled only in + * operating systems for what they were designed for. MSVC 1.0 cannot + * handle inclusion of sys/dir.h in a part that is compiled only in Apollo + * operating system. To fix the problem you need to insert DIR.H into + * SYSINCL.DAT located in MSVC\BIN directory and restart visual C++. + * Consult manuals for more informaton about the problem. + * + * Since many UNIX systems have dirent.h we assume to have one also. + * However, if your UNIX system does not have dirent.h you can download one + * for example at: http://ftp.uni-mannheim.de/ftp/GNU/dirent/dirent.tar.gz. + * You can also see if you have one of dirent.h, direct.h, dir.h, ndir.h, + * sys/dir.h and sys/ndir.h somewhere. Try defining HAVE_DIRENT_H, + * HAVE_DIRECT_H, HAVE_DIR_H, HAVE_NDIR_H, HAVE_SYS_DIR_H and + * HAVE_SYS_NDIR_H according to the files found. + */ +#ifndef DIRENT_H +#define DIRENT_H +#define DIRENT_H_INCLUDED + +/* find out platform */ +#if defined(MSDOS) /* MS-DOS */ +#elif defined(__MSDOS__) /* Turbo C/Borland */ +# define MSDOS +#elif defined(__DOS__) /* Watcom */ +# define MSDOS +#endif + +#if defined(WIN32) /* MS-Windows */ +#elif defined(__NT__) /* Watcom */ +# define WIN32 +#elif defined(_WIN32) /* Microsoft */ +# define WIN32 +#elif defined(__WIN32__) /* Borland */ +# define WIN32 +#endif + +/* + * See what kind of dirent interface we have unless autoconf has already + * determinated that. + */ +#if !defined(HAVE_DIRENT_H) && !defined(HAVE_DIRECT_H) && !defined(HAVE_SYS_DIR_H) && !defined(HAVE_NDIR_H) && !defined(HAVE_SYS_NDIR_H) && !defined(HAVE_DIR_H) +# if defined(_MSC_VER) /* Microsoft C/C++ */ + /* no dirent.h */ +# elif defined(__BORLANDC__) /* Borland C/C++ */ +# define HAVE_DIRENT_H +# define VOID_CLOSEDIR +# elif defined(__TURBOC__) /* Borland Turbo C */ + /* no dirent.h */ +# elif defined(__WATCOMC__) /* Watcom C/C++ */ +# define HAVE_DIRECT_H +# elif defined(__apollo) /* Apollo */ +# define HAVE_SYS_DIR_H +# elif defined(__hpux) /* HP-UX */ +# define HAVE_DIRENT_H +# elif defined(__alpha) || defined(__alpha__) /* Alpha OSF1 */ +# error "not implemented" +# elif defined(__sgi) /* Silicon Graphics */ +# define HAVE_DIRENT_H +# elif defined(sun) || defined(_sun) /* Sun Solaris */ +# define HAVE_DIRENT_H +# elif defined(__FreeBSD__) /* FreeBSD */ +# define HAVE_DIRENT_H +# elif defined(__linux__) /* Linux */ +# define HAVE_DIRENT_H +# elif defined(__GNUC__) /* GNU C/C++ */ +# define HAVE_DIRENT_H +# else +# error "not implemented" +# endif +#endif + +/* include proper interface headers */ +#if defined(HAVE_DIRENT_H) +# include +# ifdef FREEBSD +# define NAMLEN(dp) ((int)((dp)->d_namlen)) +# else +# define NAMLEN(dp) ((int)(strlen((dp)->d_name))) +# endif + +#elif defined(HAVE_NDIR_H) +# include +# define NAMLEN(dp) ((int)((dp)->d_namlen)) + +#elif defined(HAVE_SYS_NDIR_H) +# include +# define NAMLEN(dp) ((int)((dp)->d_namlen)) + +#elif defined(HAVE_DIRECT_H) +# include +# define NAMLEN(dp) ((int)((dp)->d_namlen)) + +#elif defined(HAVE_DIR_H) +# include +# define NAMLEN(dp) ((int)((dp)->d_namlen)) + +#elif defined(HAVE_SYS_DIR_H) +# include +# include +# ifndef dirent +# define dirent direct +# endif +# define NAMLEN(dp) ((int)((dp)->d_namlen)) + +#elif defined(MSDOS) || defined(WIN32) + + /* figure out type of underlaying directory interface to be used */ +# if defined(WIN32) +# define DIRENT_WIN32_INTERFACE +# elif defined(MSDOS) +# define DIRENT_MSDOS_INTERFACE +# else +# error "missing native dirent interface" +# endif + + /*** WIN32 specifics ***/ +# if defined(DIRENT_WIN32_INTERFACE) +# include +# if !defined(DIRENT_MAXNAMLEN) +# define DIRENT_MAXNAMLEN (MAX_PATH) +# endif + + + /*** MS-DOS specifics ***/ +# elif defined(DIRENT_MSDOS_INTERFACE) +# include + + /* Borland defines file length macros in dir.h */ +# if defined(__BORLANDC__) +# include +# if !defined(DIRENT_MAXNAMLEN) +# define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT)) +# endif +# if !defined(_find_t) +# define _find_t find_t +# endif + + /* Turbo C defines ffblk structure in dir.h */ +# elif defined(__TURBOC__) +# include +# if !defined(DIRENT_MAXNAMLEN) +# define DIRENT_MAXNAMLEN ((MAXFILE)+(MAXEXT)) +# endif +# define DIRENT_USE_FFBLK + + /* MSVC */ +# elif defined(_MSC_VER) +# if !defined(DIRENT_MAXNAMLEN) +# define DIRENT_MAXNAMLEN (12) +# endif + + /* Watcom */ +# elif defined(__WATCOMC__) +# if !defined(DIRENT_MAXNAMLEN) +# if defined(__OS2__) || defined(__NT__) +# define DIRENT_MAXNAMLEN (255) +# else +# define DIRENT_MAXNAMLEN (12) +# endif +# endif + +# endif +# endif + + /*** generic MS-DOS and MS-Windows stuff ***/ +# if !defined(NAME_MAX) && defined(DIRENT_MAXNAMLEN) +# define NAME_MAX DIRENT_MAXNAMLEN +# endif +# if NAME_MAX < DIRENT_MAXNAMLEN +# error "assertion failed: NAME_MAX >= DIRENT_MAXNAMLEN" +# endif + + + /* + * Substitute for real dirent structure. Note that `d_name' field is a + * true character array although we have it copied in the implementation + * dependent data. We could save some memory if we had declared `d_name' + * as a pointer refering the name within implementation dependent data. + * We have not done that since some code may rely on sizeof(d_name) to be + * something other than four. Besides, directory entries are typically so + * small that it takes virtually no time to copy them from place to place. + */ + typedef struct dirent { + char d_name[NAME_MAX + 1]; + + /*** Operating system specific part ***/ +# if defined(DIRENT_WIN32_INTERFACE) /*WIN32*/ + WIN32_FIND_DATA data; +# elif defined(DIRENT_MSDOS_INTERFACE) /*MSDOS*/ +# if defined(DIRENT_USE_FFBLK) + struct ffblk data; +# else + struct _find_t data; +# endif +# endif + } dirent; + + /* DIR substitute structure containing directory name. The name is + * essential for the operation of ``rewinndir'' function. */ + typedef struct DIR { + char *dirname; /* directory being scanned */ + dirent current; /* current entry */ + int dirent_filled; /* is current un-processed? */ + + /*** Operating system specific part ***/ +# if defined(DIRENT_WIN32_INTERFACE) + HANDLE search_handle; +# elif defined(DIRENT_MSDOS_INTERFACE) +# endif + } DIR; + +# ifdef __cplusplus +extern "C" { +# endif + +/* supply prototypes for dirent functions */ +static DIR *opendir (const char *dirname); +static struct dirent *readdir (DIR *dirp); +static int closedir (DIR *dirp); +static void rewinddir (DIR *dirp); + +/* + * Implement dirent interface as static functions so that the user does not + * need to change his project in any way to use dirent function. With this + * it is sufficient to include this very header from source modules using + * dirent functions and the functions will be pulled in automatically. + */ +#include +#include +#include +#include +#include + +/* use ffblk instead of _find_t if requested */ +#if defined(DIRENT_USE_FFBLK) +# define _A_ARCH (FA_ARCH) +# define _A_HIDDEN (FA_HIDDEN) +# define _A_NORMAL (0) +# define _A_RDONLY (FA_RDONLY) +# define _A_SUBDIR (FA_DIREC) +# define _A_SYSTEM (FA_SYSTEM) +# define _A_VOLID (FA_LABEL) +# define _dos_findnext(dest) findnext(dest) +# define _dos_findfirst(name,flags,dest) findfirst(name,dest,flags) +#endif + +static int _initdir (DIR *p); +static const char *_getdirname (const struct dirent *dp); +static void _setdirname (struct DIR *dirp); + +/* + * + * open directory stream for reading + * DIR *opendir (const char *dirname); + * + * Open named directory stream for read and return pointer to the + * internal working area that is used for retrieving individual directory + * entries. The internal working area has no fields of your interest. + * + * Returns a pointer to the internal working area or NULL in case the + * directory stream could not be opened. Global `errno' variable will set + * in case of error as follows: + * + * + * [EACESS |Permission denied. + * [EMFILE |Too many open files used by the process. + * [ENFILE |Too many open files in system. + * [ENOENT |Directory does not exist. + * [ENOMEM |Insufficient memory. + * [ENOTDIR |dirname does not refer to directory. This value is not + * reliable on MS-DOS and MS-Windows platforms. Many + * implementations return ENOENT even when the name refers to a + * file.] + *
+ *
+ */ +static DIR *opendir(const char *dirname) +{ + DIR *dirp; + assert (dirname != NULL); + + dirp = (DIR*)malloc (sizeof (struct DIR)); + if (dirp != NULL) { + char *p; + + /* allocate room for directory name */ + dirp->dirname = (char*) malloc (strlen (dirname) + 1 + strlen ("\\*.*")); + if (dirp->dirname == NULL) { + /* failed to duplicate directory name. errno set by malloc() */ + free (dirp); + return NULL; + } + /* Copy directory name while appending directory separator and "*.*". + * Directory separator is not appended if the name already ends with + * drive or directory separator. Directory separator is assumed to be + * '/' or '\' and drive separator is assumed to be ':'. */ + strcpy (dirp->dirname, dirname); + p = strchr (dirp->dirname, '\0'); + if (dirp->dirname < p && + *(p - 1) != '\\' && *(p - 1) != '/' && *(p - 1) != ':') + { + strcpy (p++, "\\"); + } +# ifdef DIRENT_WIN32_INTERFACE + strcpy (p, "*"); /*scan files with and without extension in win32*/ +# else + strcpy (p, "*.*"); /*scan files with and without extension in DOS*/ +# endif + + /* open stream */ + if (_initdir (dirp) == 0) { + /* initialization failed */ + free (dirp->dirname); + free (dirp); + return NULL; + } + } + return dirp; +} + + +/* + * + * read a directory entry + * struct dirent *readdir (DIR *dirp); + * + * Read individual directory entry and return pointer to a structure + * containing the name of the entry. Individual directory entries returned + * include normal files, sub-directories, pseudo-directories "." and ".." + * and also volume labels, hidden files and system files in MS-DOS and + * MS-Windows. You might want to use stat(2) function to determinate which + * one are you dealing with. Many dirent implementations already contain + * equivalent information in dirent structure but you cannot depend on + * this. + * + * The dirent structure contains several system dependent fields that + * generally have no interest to you. The only interesting one is char + * d_name[] that is also portable across different systems. The d_name + * field contains the name of the directory entry without leading path. + * While d_name is portable across different systems the actual storage + * capacity of d_name varies from system to system and there is no portable + * way to find out it at compile time as different systems define the + * capacity of d_name with different macros and some systems do not define + * capacity at all (besides actual declaration of the field). If you really + * need to find out storage capacity of d_name then you might want to try + * NAME_MAX macro. The NAME_MAX is defined in POSIX standard althought + * there are many MS-DOS and MS-Windows implementations those do not define + * it. There are also systems that declare d_name as "char d_name[1]" and + * then allocate suitable amount of memory at run-time. Thanks to Alain + * Decamps (Alain.Decamps@advalvas.be) for pointing it out to me. + * + * This all leads to the fact that it is difficult to allocate space + * for the directory names when the very same program is being compiled on + * number of operating systems. Therefore I suggest that you always + * allocate space for directory names dynamically. + * + * + * Returns a pointer to a structure containing name of the directory entry + * in `d_name' field or NULL if there was an error. In case of an error the + * global `errno' variable will set as follows: + * + * + * [EBADF |dir parameter refers to an invalid directory stream. This value + * is not set reliably on all implementations.] + *
+ *
+ */ +static struct dirent * +readdir (DIR *dirp) +{ + assert(dirp != NULL); + if (dirp == NULL) { + errno = EBADF; + return NULL; + } + +#if defined(DIRENT_WIN32_INTERFACE) + if (dirp->search_handle == INVALID_HANDLE_VALUE) { + /* directory stream was opened/rewound incorrectly or it ended normally */ + errno = EBADF; + return NULL; + } +#endif + + if (dirp->dirent_filled != 0) { + /* + * Directory entry has already been retrieved and there is no need to + * retrieve a new one. Directory entry will be retrieved in advance + * when the user calls readdir function for the first time. This is so + * because real dirent has separate functions for opening and reading + * the stream whereas Win32 and DOS dirents open the stream + * automatically when we retrieve the first file. Therefore, we have to + * save the first file when opening the stream and later we have to + * return the saved entry when the user tries to read the first entry. + */ + dirp->dirent_filled = 0; + } else { + /* fill in entry and return that */ +#if defined(DIRENT_WIN32_INTERFACE) + if (FindNextFile (dirp->search_handle, &dirp->current.data) == FALSE) { + /* Last file has been processed or an error occured */ + FindClose (dirp->search_handle); + dirp->search_handle = INVALID_HANDLE_VALUE; + errno = ENOENT; + return NULL; + } + +# elif defined(DIRENT_MSDOS_INTERFACE) + if (_dos_findnext (&dirp->current.data) != 0) { + /* _dos_findnext and findnext will set errno to ENOENT when no + * more entries could be retrieved. */ + return NULL; + } +# endif + + _setdirname (dirp); + assert (dirp->dirent_filled == 0); + } + return &dirp->current; +} + + +/* + * + * close directory stream. + * int closedir (DIR *dirp); + * + * Close directory stream opened by the `opendir' function. Close of + * directory stream invalidates the DIR structure as well as previously read + * dirent entry. + * + * The function typically returns 0 on success and -1 on failure but + * the function may be declared to return void on same systems. At least + * Borland C/C++ and some UNIX implementations use void as a return type. + * The dirent wrapper tries to define VOID_CLOSEDIR whenever closedir is + * known to return nothing. The very same definition is made by the GNU + * autoconf if you happen to use it. + * + * The global `errno' variable will set to EBADF in case of error. + * + */ +static int +closedir (DIR *dirp) +{ + int retcode = 0; + + /* make sure that dirp points to legal structure */ + assert (dirp != NULL); + if (dirp == NULL) { + errno = EBADF; + return -1; + } + + /* free directory name and search handles */ + if (dirp->dirname != NULL) free (dirp->dirname); + +#if defined(DIRENT_WIN32_INTERFACE) + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + if (FindClose (dirp->search_handle) == FALSE) { + /* Unknown error */ + retcode = -1; + errno = EBADF; + } + } +#endif + + /* clear dirp structure to make sure that it cannot be used anymore*/ + memset (dirp, 0, sizeof (*dirp)); +# if defined(DIRENT_WIN32_INTERFACE) + dirp->search_handle = INVALID_HANDLE_VALUE; +# endif + + free (dirp); + return retcode; +} + + +/* + * + * rewind directory stream to the beginning + * void rewinddir (DIR *dirp); + * + * Rewind directory stream to the beginning so that the next call of + * readdir() returns the very first directory entry again. However, note + * that next call of readdir() may not return the same directory entry as it + * did in first time. The directory stream may have been affected by newly + * created files. + * + * Almost every dirent implementation ensure that rewinddir will update + * the directory stream to reflect any changes made to the directory entries + * since the previous ``opendir'' or ``rewinddir'' call. Keep an eye on + * this if your program depends on the feature. I know at least one dirent + * implementation where you are required to close and re-open the stream to + * see the changes. + * + * Returns nothing. If something went wrong while rewinding, you will + * notice it later when you try to retrieve the first directory entry. + */ +static void +rewinddir (DIR *dirp) +{ + /* make sure that dirp is legal */ + assert (dirp != NULL); + if (dirp == NULL) { + errno = EBADF; + return; + } + assert (dirp->dirname != NULL); + + /* close previous stream */ +#if defined(DIRENT_WIN32_INTERFACE) + if (dirp->search_handle != INVALID_HANDLE_VALUE) { + if (FindClose (dirp->search_handle) == FALSE) { + /* Unknown error */ + errno = EBADF; + } + } +#endif + + /* re-open previous stream */ + if (_initdir (dirp) == 0) { + /* initialization failed but we cannot deal with error. User will notice + * error later when she tries to retrieve first directory enty. */ + /*EMPTY*/; + } +} + + +/* + * Open native directory stream object and retrieve first file. + * Be sure to close previous stream before opening new one. + */ +static int +_initdir (DIR *dirp) +{ + assert (dirp != NULL); + assert (dirp->dirname != NULL); + dirp->dirent_filled = 0; + +# if defined(DIRENT_WIN32_INTERFACE) + /* Open stream and retrieve first file */ + dirp->search_handle = FindFirstFile (dirp->dirname, &dirp->current.data); + if (dirp->search_handle == INVALID_HANDLE_VALUE) { + /* something went wrong but we don't know what. GetLastError() could + * give us more information about the error, but then we should map + * the error code into errno. */ + errno = ENOENT; + return 0; + } + +# elif defined(DIRENT_MSDOS_INTERFACE) + if (_dos_findfirst (dirp->dirname, + _A_SUBDIR | _A_RDONLY | _A_ARCH | _A_SYSTEM | _A_HIDDEN, + &dirp->current.data) != 0) + { + /* _dos_findfirst and findfirst will set errno to ENOENT when no + * more entries could be retrieved. */ + return 0; + } +# endif + + /* initialize DIR and it's first entry */ + _setdirname (dirp); + dirp->dirent_filled = 1; + return 1; +} + + +/* + * Return implementation dependent name of the current directory entry. + */ +static const char * +_getdirname (const struct dirent *dp) +{ +#if defined(DIRENT_WIN32_INTERFACE) + return dp->data.cFileName; + +#elif defined(DIRENT_USE_FFBLK) + return dp->data.ff_name; + +#else + return dp->data.name; +#endif +} + + +/* + * Copy name of implementation dependent directory entry to the d_name field. + */ +static void +_setdirname (struct DIR *dirp) { + /* make sure that d_name is long enough */ + assert (strlen (_getdirname (&dirp->current)) <= NAME_MAX); + + strncpy (dirp->current.d_name, + _getdirname (&dirp->current), + NAME_MAX); + dirp->current.d_name[NAME_MAX] = '\0'; /*char d_name[NAME_MAX+1]*/ +} + +# ifdef __cplusplus +} +# endif +# define NAMLEN(dp) ((int)(strlen((dp)->d_name))) + +#else +# error "missing dirent interface" +#endif + + +#endif /*DIRENT_H*/ diff --git a/v2/codec/image_to_j2k.c b/v2/codec/image_to_j2k.c new file mode 100755 index 00000000..5b3ea525 --- /dev/null +++ b/v2/codec/image_to_j2k.c @@ -0,0 +1,1786 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#define __USE_BSD +#include +#include +#include +#define USE_OPJ_DEPRECATED +#include "openjpeg.h" +#include "compat/getopt.h" +#include "convert.h" +#include "dirent.h" +#include "index.h" + +#ifndef WIN32 +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +/* ----------------------------------------------------------------------- */ + +#define J2K_CFMT 0 +#define JP2_CFMT 1 +#define JPT_CFMT 2 + +#define PXM_DFMT 10 +#define PGX_DFMT 11 +#define BMP_DFMT 12 +#define YUV_DFMT 13 +#define TIF_DFMT 14 +#define RAW_DFMT 15 +#define TGA_DFMT 16 + +/* ----------------------------------------------------------------------- */ +#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 struct dircnt{ + /** Buffer for holding images read from Directory*/ + char *filename_buf; + /** Pointer to the buffer*/ + char **filename; +}dircnt_t; + +typedef struct img_folder{ + /** The directory path of the folder containing input images*/ + char *imgdirpath; + /** Output format*/ + char *out_format; + /** Enable option*/ + char set_imgdir; + /** Enable Cod Format for output*/ + char set_out_format; + /** User specified rate stored in case of cinema option*/ + float *rates; +}img_fol_t; + +void encode_help_display() { + fprintf(stdout,"HELP\n----\n\n"); + fprintf(stdout,"- the -h option displays this help information on screen\n\n"); + +/* UniPG>> */ + fprintf(stdout,"List of parameters for the JPEG 2000 " +#ifdef USE_JPWL + "+ JPWL " +#endif /* USE_JPWL */ + "encoder:\n"); +/* <> */ +#ifdef USE_JPWL + fprintf(stdout," * No JPWL protection\n"); +#endif /* USE_JPWL */ +/* < \n"); + fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP, TIF, RAW and TGA formats\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-i : source file (-i source.pnm also *.pgm, *.ppm, *.bmp, *.tif, *.raw, *.tga) \n"); + fprintf(stdout," When using this option -o must be used\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-o : destination file (-o dest.j2k or .jp2) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"Optional Parameters:\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-h : display the help information \n "); + fprintf(stdout,"\n"); + fprintf(stdout,"-cinema2K : Digital Cinema 2K profile compliant codestream for 2K resolution.(-cinema2k 24 or 48) \n"); + fprintf(stdout," Need to specify the frames per second for a 2K resolution. Only 24 or 48 fps is allowed\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-cinema4K : Digital Cinema 4K profile compliant codestream for 4K resolution \n"); + fprintf(stdout," Frames per second not required. Default value is 24fps\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-r : different compression ratios for successive layers (-r 20,10,5)\n "); + fprintf(stdout," - The rate specified for each quality level is the desired \n"); + fprintf(stdout," compression factor.\n"); + fprintf(stdout," Example: -r 20,10,1 means quality 1: compress 20x, \n"); + fprintf(stdout," quality 2: compress 10x and quality 3: compress lossless\n"); + fprintf(stdout,"\n"); + fprintf(stdout," (options -r and -q cannot be used together)\n "); + fprintf(stdout,"\n"); + + fprintf(stdout,"-q : different psnr for successive layers (-q 30,40,50) \n "); + + fprintf(stdout," (options -r and -q cannot be used together)\n "); + + fprintf(stdout,"\n"); + fprintf(stdout,"-n : number of resolutions (-n 3) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-b : size of code block (-b 32,32) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-c : size of precinct (-c 128,128) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-t : size of tile (-t 512,512) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-p : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-s : subsampling factor (-s 2,2) [-s X,Y] \n"); + fprintf(stdout," Remark: subsampling bigger than 2 can produce error\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-POC : Progression order change (-POC T1=0,0,1,5,3,CPRL/T1=5,0,1,6,3,CPRL) \n"); + fprintf(stdout," Example: T1=0,0,1,5,3,CPRL \n"); + fprintf(stdout," : Ttilenumber=Resolution num start,Component num start,Layer num end,Resolution num end,Component num end,Progression order\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-SOP : write SOP marker before each packet \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-EPH : write EPH marker after each header packet \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-M : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n"); + fprintf(stdout," 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n"); + fprintf(stdout," Indicate multiple modes by adding their values. \n"); + fprintf(stdout," ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-x : create an index file *.Idx (-x index_name.Idx) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-ROI : c=%%d,U=%%d : quantization indices upshifted \n"); + fprintf(stdout," for component c=%%d [%%d = 0,1,2]\n"); + fprintf(stdout," with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI c=0,U=25) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-d : offset of the origin of the image (-d 150,300) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-T : offset of the origin of the tiles (-T 100,75) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-I : use the irreversible DWT 9-7 (-I) \n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-m : use array-based MCT, values are coma separated, line by line\n"); + fprintf(stdout," no specific separators between lines, no space allowed between values\n"); + fprintf(stdout,"\n"); +/* UniPG>> */ +#ifdef USE_JPWL + fprintf(stdout,"-W : adoption of JPWL (Part 11) capabilities (-W params)\n"); + fprintf(stdout," The parameters can be written and repeated in any order:\n"); + fprintf(stdout," [h<=type>,s<=method>,a=,...\n"); + fprintf(stdout," ...,z=,g=,p<=type>]\n"); + fprintf(stdout,"\n"); + fprintf(stdout," h selects the header error protection (EPB): 'type' can be\n"); + fprintf(stdout," [0=none 1,absent=predefined 16=CRC-16 32=CRC-32 37-128=RS]\n"); + fprintf(stdout," if 'tilepart' is absent, it is for main and tile headers\n"); + fprintf(stdout," if 'tilepart' is present, it applies from that tile\n"); + fprintf(stdout," onwards, up to the next h<> spec, or to the last tilepart\n"); + fprintf(stdout," in the codestream (max. %d specs)\n", JPWL_MAX_NO_TILESPECS); + fprintf(stdout,"\n"); + fprintf(stdout," p selects the packet error protection (EEP/UEP with EPBs)\n"); + fprintf(stdout," to be applied to raw data: 'type' can be\n"); + fprintf(stdout," [0=none 1,absent=predefined 16=CRC-16 32=CRC-32 37-128=RS]\n"); + fprintf(stdout," if 'tilepart:pack' is absent, it is from tile 0, packet 0\n"); + fprintf(stdout," if 'tilepart:pack' is present, it applies from that tile\n"); + fprintf(stdout," and that packet onwards, up to the next packet spec\n"); + fprintf(stdout," or to the last packet in the last tilepart in the stream\n"); + fprintf(stdout," (max. %d specs)\n", JPWL_MAX_NO_PACKSPECS); + fprintf(stdout,"\n"); + fprintf(stdout," s enables sensitivity data insertion (ESD): 'method' can be\n"); + fprintf(stdout," [-1=NO ESD 0=RELATIVE ERROR 1=MSE 2=MSE REDUCTION 3=PSNR\n"); + fprintf(stdout," 4=PSNR INCREMENT 5=MAXERR 6=TSE 7=RESERVED]\n"); + fprintf(stdout," if 'tilepart' is absent, it is for main header only\n"); + fprintf(stdout," if 'tilepart' is present, it applies from that tile\n"); + fprintf(stdout," onwards, up to the next s<> spec, or to the last tilepart\n"); + fprintf(stdout," in the codestream (max. %d specs)\n", JPWL_MAX_NO_TILESPECS); + fprintf(stdout,"\n"); + fprintf(stdout," g determines the addressing mode: can be\n"); + fprintf(stdout," [0=PACKET 1=BYTE RANGE 2=PACKET RANGE]\n"); + fprintf(stdout,"\n"); + fprintf(stdout," a determines the size of data addressing: can be\n"); + fprintf(stdout," 2/4 bytes (small/large codestreams). If not set, auto-mode\n"); + fprintf(stdout,"\n"); + fprintf(stdout," z determines the size of sensitivity values: can be\n"); + fprintf(stdout," 1/2 bytes, for the transformed pseudo-floating point value\n"); + fprintf(stdout,"\n"); + fprintf(stdout," ex.:\n"); + fprintf(stdout," h,h0=64,h3=16,h5=32,p0=78,p0:24=56,p1,p3:0=0,p3:20=32,s=0,\n"); + fprintf(stdout," s0=6,s3=-1,a=0,g=1,z=1\n"); + fprintf(stdout," means\n"); + fprintf(stdout," predefined EPB in MH, rs(64,32) from TPH 0 to TPH 2,\n"); + fprintf(stdout," CRC-16 in TPH 3 and TPH 4, CRC-32 in remaining TPHs,\n"); + fprintf(stdout," UEP rs(78,32) for packets 0 to 23 of tile 0,\n"); + fprintf(stdout," UEP rs(56,32) for packs. 24 to the last of tilepart 0,\n"); + fprintf(stdout," UEP rs default for packets of tilepart 1,\n"); + fprintf(stdout," no UEP for packets 0 to 19 of tilepart 3,\n"); + fprintf(stdout," UEP CRC-32 for packs. 20 of tilepart 3 to last tilepart,\n"); + fprintf(stdout," relative sensitivity ESD for MH,\n"); + fprintf(stdout," TSE ESD from TPH 0 to TPH 2, byte range with automatic\n"); + fprintf(stdout," size of addresses and 1 byte for each sensitivity value\n"); + fprintf(stdout,"\n"); + fprintf(stdout," ex.:\n"); + fprintf(stdout," h,s,p\n"); + fprintf(stdout," means\n"); + fprintf(stdout," default protection to headers (MH and TPHs) as well as\n"); + fprintf(stdout," data packets, one ESD in MH\n"); + fprintf(stdout,"\n"); + fprintf(stdout," N.B.: use the following recommendations when specifying\n"); + fprintf(stdout," the JPWL parameters list\n"); + fprintf(stdout," - when you use UEP, always pair the 'p' option with 'h'\n"); + fprintf(stdout," \n"); +#endif /* USE_JPWL */ +/* <d_name)==0 || strcmp("..",content->d_name)==0 ) + continue; + num_images++; + } + return num_images; +} + +int load_images(dircnt_t *dirptr, char *imgdirpath){ + DIR *dir; + struct dirent* content; + int i = 0; + + /*Reading the input images from given input directory*/ + + dir= opendir(imgdirpath); + if(!dir){ + fprintf(stderr,"Could not open Folder %s\n",imgdirpath); + return 1; + }else { + fprintf(stderr,"Folder opened successfully\n"); + } + + while((content=readdir(dir))!=NULL){ + if(strcmp(".",content->d_name)==0 || strcmp("..",content->d_name)==0 ) + continue; + + strcpy(dirptr->filename[i],content->d_name); + i++; + } + return 0; +} + +int get_file_format(char *filename) { + unsigned int i; + static const char *extension[] = { + "pgx", "pnm", "pgm", "ppm", "bmp", "tif", "raw", "tga", "j2k", "jp2", "j2c" + }; + static const int format[] = { + PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, TGA_DFMT, J2K_CFMT, JP2_CFMT, J2K_CFMT + }; + char * ext = strrchr(filename, '.'); + if (ext == NULL) + return -1; + ext++; + for(i = 0; i < sizeof(format)/sizeof(*format); i++) { + if(strnicmp(ext, extension[i], 3) == 0) { + return format[i]; + } + } + return -1; +} + +char * get_file_name(char *name){ + char *fname; + fname= (char*)malloc(OPJ_PATH_LEN*sizeof(char)); + fname= strtok(name,"."); + return fname; +} + +char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_cparameters_t *parameters){ + char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],outfilename[OPJ_PATH_LEN],temp_ofname[OPJ_PATH_LEN]; + char *temp_p, temp1[OPJ_PATH_LEN]=""; + + strcpy(image_filename,dirptr->filename[imageno]); + fprintf(stderr,"File Number %d \"%s\"\n",imageno,image_filename); + parameters->decod_format = get_file_format(image_filename); + if (parameters->decod_format == -1) + return 1; + sprintf(infilename,"%s/%s",img_fol->imgdirpath,image_filename); + strncpy(parameters->infile, infilename, sizeof(infilename)); + + //Set output file + strcpy(temp_ofname,get_file_name(image_filename)); + while((temp_p = strtok(NULL,".")) != NULL){ + strcat(temp_ofname,temp1); + sprintf(temp1,".%s",temp_p); + } + if(img_fol->set_out_format==1){ + sprintf(outfilename,"%s/%s.%s",img_fol->imgdirpath,temp_ofname,img_fol->out_format); + strncpy(parameters->outfile, outfilename, sizeof(outfilename)); + } + return 0; +} + +static int initialise_4K_poc(opj_poc_t *POC, int numres){ + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = numres-1; + POC[0].compno1 = 3; + POC[0].prg1 = 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; + return 2; +} + +void cinema_parameters(opj_cparameters_t *parameters){ + parameters->tile_size_on = false; + parameters->cp_tdx=1; + parameters->cp_tdy=1; + + /*Tile part*/ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; + + /*Tile and Image shall be at (0,0)*/ + parameters->cp_tx0 = 0; + parameters->cp_ty0 = 0; + parameters->image_offset_x0 = 0; + parameters->image_offset_y0 = 0; + + /*Codeblock size= 32*32*/ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + parameters->csty |= 0x01; + + /*The progression order shall be CPRL*/ + parameters->prog_order = CPRL; + + /* No ROI */ + parameters->roi_compno = -1; + + parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; + + /* 9-7 transform */ + parameters->irreversible = 1; + +} + +void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image, img_fol_t *img_fol){ + int i; + float temp_rate; + opj_poc_t *POC = NULL; + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA2K_48: + if(parameters->numresolution > 6){ + parameters->numresolution = 6; + } + if (!((image->comps[0].w == 2048) | (image->comps[0].h == 1080))){ + fprintf(stdout,"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; + } + break; + + case CINEMA4K_24: + if(parameters->numresolution < 1){ + parameters->numresolution = 1; + }else if(parameters->numresolution > 7){ + parameters->numresolution = 7; + } + if (!((image->comps[0].w == 4096) | (image->comps[0].h == 2160))){ + fprintf(stdout,"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->numpocs = initialise_4K_poc(parameters->POC,parameters->numresolution); + break; + default : + break; + } + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA4K_24: + for(i=0 ; itcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->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); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > 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); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_24_CS; + break; + + case CINEMA2K_48: + for(i=0 ; itcp_numlayers ; i++){ + temp_rate = 0 ; + if (img_fol->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); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (img_fol->rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > 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); + }else{ + parameters->tcp_rates[i]= img_fol->rates[i]; + } + } + } + parameters->max_comp_size = COMP_48_CS; + break; + default: + break; + } + parameters->cp_disto_alloc = 1; +} + +/* ------------------------------------------------------------------------------------ */ + +int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, + img_fol_t *img_fol, raw_cparameters_t *raw_cp, char *indexfilename) { + int i, j,totlen; + option_t long_option[]={ + {"cinema2K",REQ_ARG, NULL ,'w'}, + {"cinema4K",NO_ARG, NULL ,'y'}, + {"ImgDir",REQ_ARG, NULL ,'z'}, + {"TP",REQ_ARG, NULL ,'v'}, + {"SOP",NO_ARG, NULL ,'S'}, + {"EPH",NO_ARG, NULL ,'E'}, + {"OutFor",REQ_ARG, NULL ,'O'}, + {"POC",REQ_ARG, NULL ,'P'}, + {"ROI",REQ_ARG, NULL ,'R'}, + }; + + /* parse the command line */ + const char optlist[] = "i:o:hr:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:m:" +#ifdef USE_JPWL + "W:" +#endif /* USE_JPWL */ + ; + + totlen=sizeof(long_option); + img_fol->set_out_format=0; + raw_cp->rawWidth = 0; + + while (1) { + int c = getopt_long(argc, argv, optlist,long_option,totlen); + if (c == -1) + break; + switch (c) { + case 'i': /* input file */ + { + char *infile = optarg; + parameters->decod_format = get_file_format(infile); + switch(parameters->decod_format) { + case PGX_DFMT: + case PXM_DFMT: + case BMP_DFMT: + case TIF_DFMT: + case RAW_DFMT: + case TGA_DFMT: + break; + default: + fprintf(stderr, + "!! Unrecognized format for infile : %s " + "[accept only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga] !!\n\n", + infile); + return 1; + } + strncpy(parameters->infile, infile, sizeof(parameters->infile)-1); + } + break; + + /* ----------------------------------------------------- */ + + case 'o': /* output file */ + { + char *outfile = optarg; + parameters->cod_format = get_file_format(outfile); + switch(parameters->cod_format) { + case J2K_CFMT: + case JP2_CFMT: + break; + default: + fprintf(stderr, "Unknown output format image %s [only *.j2k, *.j2c or *.jp2]!! \n", outfile); + return 1; + } + strncpy(parameters->outfile, outfile, sizeof(parameters->outfile)-1); + } + break; + + /* ----------------------------------------------------- */ + case 'O': /* output format */ + { + char outformat[50]; + char *of = optarg; + sprintf(outformat,".%s",of); + img_fol->set_out_format = 1; + parameters->cod_format = get_file_format(outformat); + switch(parameters->cod_format) { + case J2K_CFMT: + case JP2_CFMT: + img_fol->out_format = optarg; + break; + default: + fprintf(stderr, "Unknown output format image [only j2k, j2c, jp2]!! \n"); + return 1; + } + } + break; + + + /* ----------------------------------------------------- */ + + + case 'r': /* rates rates/distorsion */ + { + char *s = optarg; + while (sscanf(s, "%f", ¶meters->tcp_rates[parameters->tcp_numlayers]) == 1) { + parameters->tcp_numlayers++; + while (*s && *s != ',') { + s++; + } + if (!*s) + break; + s++; + } + parameters->cp_disto_alloc = 1; + } + break; + + /* ----------------------------------------------------- */ + + + case 'F': /* Raw image format parameters */ + { + char signo; + char *s = optarg; + if (sscanf(s, "%d,%d,%d,%d,%c", &raw_cp->rawWidth, &raw_cp->rawHeight, &raw_cp->rawComp, &raw_cp->rawBitDepth, &signo) == 5) { + if (signo == 's') { + raw_cp->rawSigned = true; + fprintf(stdout,"\nRaw file parameters: %d,%d,%d,%d Signed\n", raw_cp->rawWidth, raw_cp->rawHeight, raw_cp->rawComp, raw_cp->rawBitDepth); + } + else if (signo == 'u') { + raw_cp->rawSigned = false; + fprintf(stdout,"\nRaw file parameters: %d,%d,%d,%d Unsigned\n", raw_cp->rawWidth, raw_cp->rawHeight, raw_cp->rawComp, raw_cp->rawBitDepth); + } + else { + fprintf(stderr,"\nError: invalid raw image parameters: Unknown sign of raw file\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); + fprintf(stderr,"Aborting\n"); + } + } + else { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); + fprintf(stderr,"Aborting\n"); + return 1; + } + } + break; + + /* ----------------------------------------------------- */ + + case 'q': /* add fixed_quality */ + { + char *s = optarg; + while (sscanf(s, "%f", ¶meters->tcp_distoratio[parameters->tcp_numlayers]) == 1) { + parameters->tcp_numlayers++; + while (*s && *s != ',') { + s++; + } + if (!*s) + break; + s++; + } + parameters->cp_fixed_quality = 1; + } + break; + + /* dda */ + /* ----------------------------------------------------- */ + + case 'f': /* mod fixed_quality (before : -q) */ + { + int *row = NULL, *col = NULL; + int numlayers = 0, numresolution = 0, matrix_width = 0; + + char *s = optarg; + sscanf(s, "%d", &numlayers); + s++; + if (numlayers > 9) + s++; + + parameters->tcp_numlayers = numlayers; + numresolution = parameters->numresolution; + matrix_width = numresolution * 3; + parameters->cp_matrice = (int *) malloc(numlayers * matrix_width * sizeof(int)); + s = s + 2; + + for (i = 0; i < numlayers; i++) { + row = ¶meters->cp_matrice[i * matrix_width]; + col = row; + parameters->tcp_rates[i] = 1; + sscanf(s, "%d,", &col[0]); + s += 2; + if (col[0] > 9) + s++; + col[1] = 0; + col[2] = 0; + for (j = 1; j < numresolution; j++) { + col += 3; + sscanf(s, "%d,%d,%d", &col[0], &col[1], &col[2]); + s += 6; + if (col[0] > 9) + s++; + if (col[1] > 9) + s++; + if (col[2] > 9) + s++; + } + if (i < numlayers - 1) + s++; + } + parameters->cp_fixed_alloc = 1; + } + break; + + /* ----------------------------------------------------- */ + + case 't': /* tiles */ + { + sscanf(optarg, "%d,%d", ¶meters->cp_tdx, ¶meters->cp_tdy); + parameters->tile_size_on = true; + } + break; + + /* ----------------------------------------------------- */ + + case 'n': /* resolution */ + { + sscanf(optarg, "%d", ¶meters->numresolution); + } + break; + + /* ----------------------------------------------------- */ + case 'c': /* precinct dimension */ + { + char sep; + int res_spec = 0; + + char *s = optarg; + do { + sep = 0; + sscanf(s, "[%d,%d]%c", ¶meters->prcw_init[res_spec], + ¶meters->prch_init[res_spec], &sep); + parameters->csty |= 0x01; + res_spec++; + s = strpbrk(s, "]") + 2; + } + while (sep == ','); + parameters->res_spec = res_spec; + } + break; + + /* ----------------------------------------------------- */ + + case 'b': /* code-block dimension */ + { + int cblockw_init = 0, cblockh_init = 0; + sscanf(optarg, "%d,%d", &cblockw_init, &cblockh_init); + if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 + || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) { + fprintf(stderr, + "!! Size of code_block error (option -b) !!\n\nRestriction :\n" + " * width*height<=4096\n * 4<=width,height<= 1024\n\n"); + return 1; + } + parameters->cblockw_init = cblockw_init; + parameters->cblockh_init = cblockh_init; + } + break; + + /* ----------------------------------------------------- */ + + case 'x': /* creation of index file */ + { + char *index = optarg; + strncpy(indexfilename, index, OPJ_PATH_LEN); + } + break; + + /* ----------------------------------------------------- */ + + case 'p': /* progression order */ + { + char progression[4]; + + strncpy(progression, optarg, 4); + parameters->prog_order = give_progression(progression); + if (parameters->prog_order == -1) { + fprintf(stderr, "Unrecognized progression order " + "[LRCP, RLCP, RPCL, PCRL, CPRL] !!\n"); + return 1; + } + } + break; + + /* ----------------------------------------------------- */ + + case 's': /* subsampling factor */ + { + if (sscanf(optarg, "%d,%d", ¶meters->subsampling_dx, + ¶meters->subsampling_dy) != 2) { + fprintf(stderr, "'-s' sub-sampling argument error ! [-s dx,dy]\n"); + return 1; + } + } + break; + + /* ----------------------------------------------------- */ + + case 'd': /* coordonnate of the reference grid */ + { + if (sscanf(optarg, "%d,%d", ¶meters->image_offset_x0, + ¶meters->image_offset_y0) != 2) { + fprintf(stderr, "-d 'coordonnate of the reference grid' argument " + "error !! [-d x0,y0]\n"); + return 1; + } + } + break; + + /* ----------------------------------------------------- */ + + case 'h': /* display an help description */ + encode_help_display(); + return 1; + + /* ----------------------------------------------------- */ + + case 'P': /* POC */ + { + int numpocs = 0; /* number of progression order change (POC) default 0 */ + opj_poc_t *POC = NULL; /* POC : used in case of Progression order change */ + + char *s = optarg; + POC = parameters->POC; + + while (sscanf(s, "T%d=%d,%d,%d,%d,%d,%4s", &POC[numpocs].tile, + &POC[numpocs].resno0, &POC[numpocs].compno0, + &POC[numpocs].layno1, &POC[numpocs].resno1, + &POC[numpocs].compno1, POC[numpocs].progorder) == 7) { + POC[numpocs].prg1 = give_progression(POC[numpocs].progorder); + numpocs++; + while (*s && *s != '/') { + s++; + } + if (!*s) { + break; + } + s++; + } + parameters->numpocs = numpocs; + } + break; + + /* ------------------------------------------------------ */ + + case 'S': /* SOP marker */ + { + parameters->csty |= 0x02; + } + break; + + /* ------------------------------------------------------ */ + + case 'E': /* EPH marker */ + { + parameters->csty |= 0x04; + } + break; + + /* ------------------------------------------------------ */ + + case 'M': /* Mode switch pas tous au point !! */ + { + int value = 0; + if (sscanf(optarg, "%d", &value) == 1) { + for (i = 0; i <= 5; i++) { + int cache = value & (1 << i); + if (cache) + parameters->mode |= (1 << i); + } + } + } + break; + + /* ------------------------------------------------------ */ + + case 'R': /* ROI */ + { + if (sscanf(optarg, "c=%d,U=%d", ¶meters->roi_compno, + ¶meters->roi_shift) != 2) { + fprintf(stderr, "ROI error !! [-ROI c='compno',U='shift']\n"); + return 1; + } + } + break; + + /* ------------------------------------------------------ */ + + case 'T': /* Tile offset */ + { + if (sscanf(optarg, "%d,%d", ¶meters->cp_tx0, ¶meters->cp_ty0) != 2) { + fprintf(stderr, "-T 'tile offset' argument error !! [-T X0,Y0]"); + return 1; + } + } + break; + + /* ------------------------------------------------------ */ + + case 'C': /* add a comment */ + { + parameters->cp_comment = (char*)malloc(strlen(optarg) + 1); + if(parameters->cp_comment) { + strcpy(parameters->cp_comment, optarg); + } + } + break; + + + /* ------------------------------------------------------ */ + + case 'I': /* reversible or not */ + { + parameters->irreversible = 1; + } + break; + + /* ------------------------------------------------------ */ + + case 'v': /* Tile part generation*/ + { + parameters->tp_flag = optarg[0]; + parameters->tp_on = 1; + } + break; + + /* ------------------------------------------------------ */ + + case 'z': /* Image Directory path */ + { + img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1); + strcpy(img_fol->imgdirpath,optarg); + img_fol->set_imgdir=1; + } + break; + + /* ------------------------------------------------------ */ + + case 'w': /* Digital Cinema 2K profile compliance*/ + { + int fps=0; + sscanf(optarg,"%d",&fps); + if(fps == 24){ + parameters->cp_cinema = CINEMA2K_24; + }else if(fps == 48 ){ + parameters->cp_cinema = CINEMA2K_48; + }else { + fprintf(stderr,"Incorrect value!! must be 24 or 48\n"); + return 1; + } + fprintf(stdout,"CINEMA 2K compliant codestream\n"); + parameters->cp_rsiz = CINEMA2K; + + } + break; + + /* ------------------------------------------------------ */ + + case 'y': /* Digital Cinema 4K profile compliance*/ + { + parameters->cp_cinema = CINEMA4K_24; + fprintf(stdout,"CINEMA 4K compliant codestream\n"); + parameters->cp_rsiz = CINEMA4K; + } + break; + + case 'm': /* output file */ + { + char *lFilename = optarg; + char * lMatrix; + char *lCurrentPtr ; + int lNbComp = 0; + int lTotalComp; + int lMctComp; + float * lCurrentDoublePtr; + float * lSpace; + int * l_int_ptr; + int i; + int lStrLen; + + FILE * lFile = fopen(lFilename,"r"); + if + (lFile == NULL) + { + return 1; + } + fseek(lFile,0,SEEK_END); + lStrLen = ftell(lFile); + fseek(lFile,0,SEEK_SET); + lMatrix = (char *) malloc(lStrLen + 1); + fread(lMatrix,lStrLen,1,lFile); + fclose(lFile); + lMatrix[lStrLen] = 0; + lCurrentPtr = lMatrix; + + // replace ',' by 0 + while + (*lCurrentPtr != 0 ) + { + if + (*lCurrentPtr == ' ') + { + *lCurrentPtr = 0; + ++lNbComp; + } + ++lCurrentPtr; + } + ++lNbComp; + lCurrentPtr = lMatrix; + + lNbComp = (int) (sqrt(4*lNbComp + 1)/2. - 0.5); + lMctComp = lNbComp * lNbComp; + lTotalComp = lMctComp + lNbComp; + lSpace = (float *) malloc(lTotalComp * sizeof(float)); + lCurrentDoublePtr = lSpace; + for + (i=0;i> */ +#ifdef USE_JPWL + /* ------------------------------------------------------ */ + + case 'W': /* JPWL capabilities switched on */ + { + char *token = NULL; + int hprot, pprot, sens, addr, size, range; + + /* we need to enable indexing */ + if (!indexfilename) { + strncpy(indexfilename, JPWL_PRIVATEINDEX_NAME, OPJ_PATH_LEN); + } + + /* search for different protection methods */ + + /* break the option in comma points and parse the result */ + token = strtok(optarg, ","); + while(token != NULL) { + + /* search header error protection method */ + if (*token == 'h') { + + static int tile = 0, tilespec = 0, lasttileno = 0; + + hprot = 1; /* predefined method */ + + if(sscanf(token, "h=%d", &hprot) == 1) { + /* Main header, specified */ + if (!((hprot == 0) || (hprot == 1) || (hprot == 16) || (hprot == 32) || + ((hprot >= 37) && (hprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid main header protection method h = %d\n", hprot); + return 1; + } + parameters->jpwl_hprot_MH = hprot; + + } else if(sscanf(token, "h%d=%d", &tile, &hprot) == 2) { + /* Tile part header, specified */ + if (!((hprot == 0) || (hprot == 1) || (hprot == 16) || (hprot == 32) || + ((hprot >= 37) && (hprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid tile part header protection method h = %d\n", hprot); + return 1; + } + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method t = %d\n", tile); + return 1; + } + if (tilespec < JPWL_MAX_NO_TILESPECS) { + parameters->jpwl_hprot_TPH_tileno[tilespec] = lasttileno = tile; + parameters->jpwl_hprot_TPH[tilespec++] = hprot; + } + + } else if(sscanf(token, "h%d", &tile) == 1) { + /* Tile part header, unspecified */ + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method t = %d\n", tile); + return 1; + } + if (tilespec < JPWL_MAX_NO_TILESPECS) { + parameters->jpwl_hprot_TPH_tileno[tilespec] = lasttileno = tile; + parameters->jpwl_hprot_TPH[tilespec++] = hprot; + } + + + } else if (!strcmp(token, "h")) { + /* Main header, unspecified */ + parameters->jpwl_hprot_MH = hprot; + + } else { + fprintf(stderr, "ERROR -> invalid protection method selection = %s\n", token); + return 1; + }; + + } + + /* search packet error protection method */ + if (*token == 'p') { + + static int pack = 0, tile = 0, packspec = 0, lastpackno = 0; + + pprot = 1; /* predefined method */ + + if (sscanf(token, "p=%d", &pprot) == 1) { + /* Method for all tiles and all packets */ + if (!((pprot == 0) || (pprot == 1) || (pprot == 16) || (pprot == 32) || + ((pprot >= 37) && (pprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid default packet protection method p = %d\n", pprot); + return 1; + } + parameters->jpwl_pprot_tileno[0] = 0; + parameters->jpwl_pprot_packno[0] = 0; + parameters->jpwl_pprot[0] = pprot; + + } else if (sscanf(token, "p%d=%d", &tile, &pprot) == 2) { + /* method specified from that tile on */ + if (!((pprot == 0) || (pprot == 1) || (pprot == 16) || (pprot == 32) || + ((pprot >= 37) && (pprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid packet protection method p = %d\n", pprot); + return 1; + } + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method p = %d\n", tile); + return 1; + } + if (packspec < JPWL_MAX_NO_PACKSPECS) { + parameters->jpwl_pprot_tileno[packspec] = tile; + parameters->jpwl_pprot_packno[packspec] = 0; + parameters->jpwl_pprot[packspec++] = pprot; + } + + } else if (sscanf(token, "p%d:%d=%d", &tile, &pack, &pprot) == 3) { + /* method fully specified from that tile and that packet on */ + if (!((pprot == 0) || (pprot == 1) || (pprot == 16) || (pprot == 32) || + ((pprot >= 37) && (pprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid packet protection method p = %d\n", pprot); + return 1; + } + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method p = %d\n", tile); + return 1; + } + if (pack < 0) { + fprintf(stderr, "ERROR -> invalid packet number on protection method p = %d\n", pack); + return 1; + } + if (packspec < JPWL_MAX_NO_PACKSPECS) { + parameters->jpwl_pprot_tileno[packspec] = tile; + parameters->jpwl_pprot_packno[packspec] = pack; + parameters->jpwl_pprot[packspec++] = pprot; + } + + } else if (sscanf(token, "p%d:%d", &tile, &pack) == 2) { + /* default method from that tile and that packet on */ + if (!((pprot == 0) || (pprot == 1) || (pprot == 16) || (pprot == 32) || + ((pprot >= 37) && (pprot <= 128)))) { + fprintf(stderr, "ERROR -> invalid packet protection method p = %d\n", pprot); + return 1; + } + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method p = %d\n", tile); + return 1; + } + if (pack < 0) { + fprintf(stderr, "ERROR -> invalid packet number on protection method p = %d\n", pack); + return 1; + } + if (packspec < JPWL_MAX_NO_PACKSPECS) { + parameters->jpwl_pprot_tileno[packspec] = tile; + parameters->jpwl_pprot_packno[packspec] = pack; + parameters->jpwl_pprot[packspec++] = pprot; + } + + } else if (sscanf(token, "p%d", &tile) == 1) { + /* default from a tile on */ + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on protection method p = %d\n", tile); + return 1; + } + if (packspec < JPWL_MAX_NO_PACKSPECS) { + parameters->jpwl_pprot_tileno[packspec] = tile; + parameters->jpwl_pprot_packno[packspec] = 0; + parameters->jpwl_pprot[packspec++] = pprot; + } + + + } else if (!strcmp(token, "p")) { + /* all default */ + parameters->jpwl_pprot_tileno[0] = 0; + parameters->jpwl_pprot_packno[0] = 0; + parameters->jpwl_pprot[0] = pprot; + + } else { + fprintf(stderr, "ERROR -> invalid protection method selection = %s\n", token); + return 1; + }; + + } + + /* search sensitivity method */ + if (*token == 's') { + + static int tile = 0, tilespec = 0, lasttileno = 0; + + sens = 0; /* predefined: relative error */ + + if(sscanf(token, "s=%d", &sens) == 1) { + /* Main header, specified */ + if ((sens < -1) || (sens > 7)) { + fprintf(stderr, "ERROR -> invalid main header sensitivity method s = %d\n", sens); + return 1; + } + parameters->jpwl_sens_MH = sens; + + } else if(sscanf(token, "s%d=%d", &tile, &sens) == 2) { + /* Tile part header, specified */ + if ((sens < -1) || (sens > 7)) { + fprintf(stderr, "ERROR -> invalid tile part header sensitivity method s = %d\n", sens); + return 1; + } + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on sensitivity method t = %d\n", tile); + return 1; + } + if (tilespec < JPWL_MAX_NO_TILESPECS) { + parameters->jpwl_sens_TPH_tileno[tilespec] = lasttileno = tile; + parameters->jpwl_sens_TPH[tilespec++] = sens; + } + + } else if(sscanf(token, "s%d", &tile) == 1) { + /* Tile part header, unspecified */ + if (tile < 0) { + fprintf(stderr, "ERROR -> invalid tile part number on sensitivity method t = %d\n", tile); + return 1; + } + if (tilespec < JPWL_MAX_NO_TILESPECS) { + parameters->jpwl_sens_TPH_tileno[tilespec] = lasttileno = tile; + parameters->jpwl_sens_TPH[tilespec++] = hprot; + } + + } else if (!strcmp(token, "s")) { + /* Main header, unspecified */ + parameters->jpwl_sens_MH = sens; + + } else { + fprintf(stderr, "ERROR -> invalid sensitivity method selection = %s\n", token); + return 1; + }; + + parameters->jpwl_sens_size = 2; /* 2 bytes for default size */ + } + + /* search addressing size */ + if (*token == 'a') { + + static int tile = 0, tilespec = 0, lasttileno = 0; + + addr = 0; /* predefined: auto */ + + if(sscanf(token, "a=%d", &addr) == 1) { + /* Specified */ + if ((addr != 0) && (addr != 2) && (addr != 4)) { + fprintf(stderr, "ERROR -> invalid addressing size a = %d\n", addr); + return 1; + } + parameters->jpwl_sens_addr = addr; + + } else if (!strcmp(token, "a")) { + /* default */ + parameters->jpwl_sens_addr = addr; /* auto for default size */ + + } else { + fprintf(stderr, "ERROR -> invalid addressing selection = %s\n", token); + return 1; + }; + + } + + /* search sensitivity size */ + if (*token == 'z') { + + static int tile = 0, tilespec = 0, lasttileno = 0; + + size = 1; /* predefined: 1 byte */ + + if(sscanf(token, "z=%d", &size) == 1) { + /* Specified */ + if ((size != 0) && (size != 1) && (size != 2)) { + fprintf(stderr, "ERROR -> invalid sensitivity size z = %d\n", size); + return 1; + } + parameters->jpwl_sens_size = size; + + } else if (!strcmp(token, "a")) { + /* default */ + parameters->jpwl_sens_size = size; /* 1 for default size */ + + } else { + fprintf(stderr, "ERROR -> invalid size selection = %s\n", token); + return 1; + }; + + } + + /* search range method */ + if (*token == 'g') { + + static int tile = 0, tilespec = 0, lasttileno = 0; + + range = 0; /* predefined: 0 (packet) */ + + if(sscanf(token, "g=%d", &range) == 1) { + /* Specified */ + if ((range < 0) || (range > 3)) { + fprintf(stderr, "ERROR -> invalid sensitivity range method g = %d\n", range); + return 1; + } + parameters->jpwl_sens_range = range; + + } else if (!strcmp(token, "g")) { + /* default */ + parameters->jpwl_sens_range = range; + + } else { + fprintf(stderr, "ERROR -> invalid range selection = %s\n", token); + return 1; + }; + + } + + /* next token or bust */ + token = strtok(NULL, ","); + }; + + + /* some info */ + fprintf(stdout, "Info: JPWL capabilities enabled\n"); + parameters->jpwl_epc_on = true; + + } + break; +#endif /* USE_JPWL */ +/* < Command line not valid\n"); + return 1; + } + } + + /* check for possible errors */ + if (parameters->cp_cinema){ + if(parameters->tcp_numlayers > 1){ + parameters->cp_rsiz = STD_RSIZ; + fprintf(stdout,"Warning: DC profiles do not allow more than one quality layer. The codestream created will not be compliant with the DC profile\n"); + } + } + if(img_fol->set_imgdir == 1){ + if(!(parameters->infile[0] == 0)){ + fprintf(stderr, "Error: options -ImgDir and -i cannot be used together !!\n"); + return 1; + } + if(img_fol->set_out_format == 0){ + fprintf(stderr, "Error: When -ImgDir is used, -OutFor must be used !!\n"); + fprintf(stderr, "Only one format allowed! Valid formats are j2k and jp2!!\n"); + return 1; + } + if(!((parameters->outfile[0] == 0))){ + fprintf(stderr, "Error: options -ImgDir and -o cannot be used together !!\n"); + fprintf(stderr, "Specify OutputFormat using -OutFor !!\n"); + return 1; + } + }else{ + if((parameters->infile[0] == 0) || (parameters->outfile[0] == 0)) { + fprintf(stderr, "Error: One of the options; -i or -ImgDir must be specified\n"); + fprintf(stderr, "Error: When using -i; -o must be used\n"); + fprintf(stderr, "usage: image_to_j2k -i image-file -o j2k/jp2-file (+ options)\n"); + return 1; + } + } + + if (parameters->decod_format == RAW_DFMT && raw_cp->rawWidth == 0) { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); + fprintf(stderr,"Aborting\n"); + return 1; + } + + if ((parameters->cp_disto_alloc || parameters->cp_fixed_alloc || parameters->cp_fixed_quality) + && (!(parameters->cp_disto_alloc ^ parameters->cp_fixed_alloc ^ parameters->cp_fixed_quality))) { + fprintf(stderr, "Error: options -r -q and -f cannot be used together !!\n"); + return 1; + } /* mod fixed_quality */ + + /* if no rate entered, lossless by default */ + if (parameters->tcp_numlayers == 0) { + parameters->tcp_rates[0] = 0; /* MOD antonin : losslessbug */ + parameters->tcp_numlayers++; + parameters->cp_disto_alloc = 1; + } + + if((parameters->cp_tx0 > parameters->image_offset_x0) || (parameters->cp_ty0 > parameters->image_offset_y0)) { + fprintf(stderr, + "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n", + parameters->cp_tx0, parameters->image_offset_x0, parameters->cp_ty0, parameters->image_offset_y0); + return 1; + } + + for (i = 0; i < parameters->numpocs; i++) { + if (parameters->POC[i].prg == -1) { + fprintf(stderr, + "Unrecognized progression order in option -P (POC n %d) [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n", + i + 1); + } + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** +sample debug callback expecting a FILE* client object +*/ +void info_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[INFO] %s", msg); +} + +/* -------------------------------------------------------------------------- */ + +int main(int argc, char **argv) { + bool bSuccess; + opj_cparameters_t parameters; /* compression parameters */ + img_fol_t img_fol; + opj_image_t *image = NULL; + int i,num_images; + int imageno; + dircnt_t *dirptr; + raw_cparameters_t raw_cp; + opj_codestream_info_t cstr_info; /* Codestream information structure */ + char indexfilename[OPJ_PATH_LEN]; /* index file name */ + opj_stream_t *cio = 00; + opj_codec_t* cinfo = 00; + FILE *f = NULL; + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + /* set encoding parameters to default values */ + opj_set_default_encoder_parameters(¶meters); + + /* Initialize indexfilename and img_fol */ + *indexfilename = 0; + memset(&img_fol,0,sizeof(img_fol_t)); + + /* parse input and get user encoding parameters */ + if(parse_cmdline_encoder(argc, argv, ¶meters,&img_fol, &raw_cp, indexfilename) == 1) { + return 1; + } + + if (parameters.cp_cinema){ + img_fol.rates = (float*)malloc(parameters.tcp_numlayers * sizeof(float)); + for(i=0; i< parameters.tcp_numlayers; i++){ + img_fol.rates[i] = parameters.tcp_rates[i]; + } + cinema_parameters(¶meters); + } + + /* Create comment for codestream */ + if(parameters.cp_comment == NULL) { + const char comment[] = "Created by OpenJPEG version "; + const size_t clen = strlen(comment); + const char *version = opj_version(); +/* UniPG>> */ +#ifdef USE_JPWL + parameters.cp_comment = (char*)malloc(clen+strlen(version)+11); + sprintf(parameters.cp_comment,"%s%s with JPWL", comment, version); +#else + parameters.cp_comment = (char*)malloc(clen+strlen(version)+1); + sprintf(parameters.cp_comment,"%s%s", comment, version); +#endif +/* <filename_buf = (char*)malloc(num_images*OPJ_PATH_LEN*sizeof(char)); // Stores at max 10 image file names + dirptr->filename = (char**) malloc(num_images*sizeof(char*)); + if(!dirptr->filename_buf){ + return 0; + } + for(i=0;ifilename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN; + } + } + if(load_images(dirptr,img_fol.imgdirpath)==1){ + return 0; + } + if (num_images==0){ + fprintf(stdout,"Folder is empty\n"); + return 0; + } + }else{ + num_images=1; + } + /*Encoding image one by one*/ + for(imageno=0;imagenonumcomps == 3 ? 1 : 0; + + if(parameters.cp_cinema){ + cinema_setup_encoder(¶meters,image,&img_fol); + } + + /* encode the destination image */ + /* ---------------------------- */ + + + cinfo = parameters.cod_format == J2K_CFMT ? opj_create_compress(CODEC_J2K) : opj_create_compress(CODEC_JP2); + opj_setup_encoder(cinfo, ¶meters, image); + f = fopen(parameters.outfile, "wb"); + if + (! f) + { + fprintf(stderr, "failed to encode image\n"); + return 1; + } + /* open a byte stream for writing */ + /* allocate memory for all tiles */ + cio = opj_stream_create_default_file_stream(f,false); + if + (! cio) + { + return 1; + } + /* encode the image */ + /*if (*indexfilename) // If need to extract codestream information + bSuccess = opj_encode_with_info(cinfo, cio, image, &cstr_info); + else*/ + bSuccess = opj_start_compress(cinfo,image,cio); + bSuccess = bSuccess && opj_encode(cinfo, cio); + bSuccess = bSuccess && opj_end_compress(cinfo, cio); + + if + (!bSuccess) + { + opj_stream_destroy(cio); + fclose(f); + fprintf(stderr, "failed to encode image\n"); + return 1; + } + + fprintf(stderr,"Generated outfile %s\n",parameters.outfile); + /* close and free the byte stream */ + opj_stream_destroy(cio); + fclose(f); + + /* Write the index to disk */ + if (*indexfilename) { + bSuccess = write_index_file(&cstr_info, indexfilename); + if (bSuccess) { + fprintf(stderr, "Failed to output index file\n"); + } + } + + /* free remaining compression structures */ + opj_destroy_codec(cinfo); + if (*indexfilename) + opj_destroy_cstr_info(&cstr_info); + + /* free image data */ + opj_image_destroy(image); + } + + /* free user parameters structure */ + if(parameters.cp_comment) free(parameters.cp_comment); + if(parameters.cp_matrice) free(parameters.cp_matrice); + + return 0; +} diff --git a/v2/codec/index.c b/v2/codec/index.c new file mode 100755 index 00000000..2e0283dd --- /dev/null +++ b/v2/codec/index.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "openjpeg.h" +#include "index.h" + +/* ------------------------------------------------------------------------------------ */ + +/** +Write a structured index to a file +@param cstr_info Codestream information +@param index Index filename +@return Returns 0 if successful, returns 1 otherwise +*/ +int write_index_file(opj_codestream_info_t *cstr_info, char *index) { + int tileno, compno, layno, resno, precno, pack_nb, x, y; + FILE *stream = NULL; + double total_disto = 0; +/* UniPG>> */ + int tilepartno; + char disto_on, numpix_on; + +#ifdef USE_JPWL + if (!strcmp(index, JPWL_PRIVATEINDEX_NAME)) + return 0; +#endif /* USE_JPWL */ +/* <tile[0].distotile) + disto_on = 1; + else + disto_on = 0; + + if (cstr_info->tile[0].numpix) + numpix_on = 1; + else + numpix_on = 0; + + fprintf(stream, "%d %d\n", cstr_info->image_w, cstr_info->image_h); + fprintf(stream, "%d\n", cstr_info->prog); + fprintf(stream, "%d %d\n", cstr_info->tile_x, cstr_info->tile_y); + fprintf(stream, "%d %d\n", cstr_info->tw, cstr_info->th); + fprintf(stream, "%d\n", cstr_info->numcomps); + fprintf(stream, "%d\n", cstr_info->numlayers); + fprintf(stream, "%d\n", cstr_info->numdecompos); + + for (resno = cstr_info->numdecompos[0]; resno >= 0; resno--) { + fprintf(stream, "[%d,%d] ", + (1 << cstr_info->tile[0].pdx[resno]), (1 << cstr_info->tile[0].pdx[resno])); /* based on tile 0 and component 0 */ + } + + fprintf(stream, "\n"); +/* UniPG>> */ + fprintf(stream, "%d\n", cstr_info->main_head_start); +/* <main_head_end); + fprintf(stream, "%d\n", cstr_info->codestream_size); + + fprintf(stream, "\nINFO ON TILES\n"); + fprintf(stream, "tileno start_pos end_hd end_tile nbparts"); + if (disto_on) + fprintf(stream," disto"); + if (numpix_on) + fprintf(stream," nbpix"); + if (disto_on && numpix_on) + fprintf(stream," disto/nbpix"); + fprintf(stream, "\n"); + + for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) { + fprintf(stream, "%4d %9d %9d %9d %9d", + cstr_info->tile[tileno].tileno, + cstr_info->tile[tileno].start_pos, + cstr_info->tile[tileno].end_header, + cstr_info->tile[tileno].end_pos, + cstr_info->tile[tileno].num_tps); + if (disto_on) + fprintf(stream," %9e", cstr_info->tile[tileno].distotile); + if (numpix_on) + fprintf(stream," %9d", cstr_info->tile[tileno].numpix); + if (disto_on && numpix_on) + fprintf(stream," %9e", cstr_info->tile[tileno].distotile / cstr_info->tile[tileno].numpix); + fprintf(stream, "\n"); + } + + for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) { + int start_pos, end_ph_pos, end_pos; + double disto = 0; + int max_numdecompos = 0; + pack_nb = 0; + + for (compno = 0; compno < cstr_info->numcomps; compno++) { + if (max_numdecompos < cstr_info->numdecompos[compno]) + max_numdecompos = cstr_info->numdecompos[compno]; + } + + fprintf(stream, "\nTILE %d DETAILS\n", tileno); + fprintf(stream, "part_nb tileno start_pack num_packs start_pos end_tph_pos end_pos\n"); + for (tilepartno = 0; tilepartno < cstr_info->tile[tileno].num_tps; tilepartno++) + fprintf(stream, "%4d %9d %9d %9d %9d %11d %9d\n", + tilepartno, tileno, + cstr_info->tile[tileno].tp[tilepartno].tp_start_pack, + cstr_info->tile[tileno].tp[tilepartno].tp_numpacks, + cstr_info->tile[tileno].tp[tilepartno].tp_start_pos, + cstr_info->tile[tileno].tp[tilepartno].tp_end_header, + cstr_info->tile[tileno].tp[tilepartno].tp_end_pos + ); + + if (cstr_info->prog == LRCP) { /* LRCP */ + fprintf(stream, "LRCP\npack_nb tileno layno resno compno precno start_pos end_ph_pos end_pos"); + if (disto_on) + fprintf(stream, " disto"); + fprintf(stream,"\n"); + + for (layno = 0; layno < cstr_info->numlayers; layno++) { + for (resno = 0; resno < max_numdecompos + 1; resno++) { + for (compno = 0; compno < cstr_info->numcomps; compno++) { + int prec_max; + if (resno > cstr_info->numdecompos[compno]) + break; + prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + for (precno = 0; precno < prec_max; precno++) { + start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos; + end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos; + end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos; + disto = cstr_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %7d %5d %6d %6d %6d %6d %7d", + pack_nb, tileno, layno, resno, compno, precno, start_pos, end_ph_pos, end_pos); + if (disto_on) + fprintf(stream, " %8e", disto); + fprintf(stream, "\n"); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* LRCP */ + + else if (cstr_info->prog == RLCP) { /* RLCP */ + fprintf(stream, "RLCP\npack_nb tileno resno layno compno precno start_pos end_ph_pos end_pos\n"); + if (disto_on) + fprintf(stream, " disto"); + fprintf(stream,"\n"); + + for (resno = 0; resno < max_numdecompos + 1; resno++) { + for (layno = 0; layno < cstr_info->numlayers; layno++) { + for (compno = 0; compno < cstr_info->numcomps; compno++) { + int prec_max; + if (resno > cstr_info->numdecompos[compno]) + break; + prec_max = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + for (precno = 0; precno < prec_max; precno++) { + start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos; + end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos; + end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos; + disto = cstr_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %5d %7d %6d %6d %9d %9d %7d", + pack_nb, tileno, resno, layno, compno, precno, start_pos, end_ph_pos, end_pos); + if (disto_on) + fprintf(stream, " %8e", disto); + fprintf(stream, "\n"); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* RLCP */ + + else if (cstr_info->prog == RPCL) { /* RPCL */ + + fprintf(stream, "RPCL\npack_nb tileno resno precno compno layno start_pos end_ph_pos end_pos"); + if (disto_on) + fprintf(stream, " disto"); + fprintf(stream,"\n"); + + for (resno = 0; resno < max_numdecompos + 1; resno++) { + int numprec = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + for (precno = 0; precno < numprec; precno++) { + /* I suppose components have same XRsiz, YRsiz */ + int x0 = cstr_info->tile_Ox + tileno - (int)floor((float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x; + int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y; + int x1 = x0 + cstr_info->tile_x; + int y1 = y0 + cstr_info->tile_y; + for (compno = 0; compno < cstr_info->numcomps; compno++) { + int pcnx = cstr_info->tile[tileno].pw[resno]; + int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos[compno] - resno ); + int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos[compno] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + if (resno > cstr_info->numdecompos[compno]) + break; + for(y = y0; y < y1; y++) { + if (precno_y*pcy == y ) { + for (x = x0; x < x1; x++) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < cstr_info->numlayers; layno++) { + start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos; + end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos; + end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos; + disto = cstr_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %5d %6d %6d %7d %9d %9d %7d", + pack_nb, tileno, resno, precno, compno, layno, start_pos, end_ph_pos, end_pos); + if (disto_on) + fprintf(stream, " %8e", disto); + fprintf(stream, "\n"); + total_disto += disto; + pack_nb++; + } + } + }/* x = x0..x1 */ + } + } /* y = y0..y1 */ + } /* precno */ + } /* compno */ + } /* resno */ + } /* RPCL */ + + else if (cstr_info->prog == PCRL) { /* PCRL */ + /* I suppose components have same XRsiz, YRsiz */ + int x0 = cstr_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x; + int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y; + int x1 = x0 + cstr_info->tile_x; + int y1 = y0 + cstr_info->tile_y; + + // Count the maximum number of precincts + int max_numprec = 0; + for (resno = 0; resno < max_numdecompos + 1; resno++) { + int numprec = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + if (numprec > max_numprec) + max_numprec = numprec; + } + + fprintf(stream, "PCRL\npack_nb tileno precno compno resno layno start_pos end_ph_pos end_pos"); + if (disto_on) + fprintf(stream, " disto"); + fprintf(stream,"\n"); + + for (precno = 0; precno < max_numprec; precno++) { + for (compno = 0; compno < cstr_info->numcomps; compno++) { + for (resno = 0; resno < cstr_info->numdecompos[compno] + 1; resno++) { + int numprec = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + int pcnx = cstr_info->tile[tileno].pw[resno]; + int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos[compno] - resno ); + int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos[compno] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + if (precno >= numprec) + continue; + for(y = y0; y < y1; y++) { + if (precno_y*pcy == y ) { + for (x = x0; x < x1; x++) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < cstr_info->numlayers; layno++) { + start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos; + end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos; + end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos; + disto = cstr_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %7d", + pack_nb, tileno, precno, compno, resno, layno, start_pos, end_ph_pos, end_pos); + if (disto_on) + fprintf(stream, " %8e", disto); + fprintf(stream, "\n"); + total_disto += disto; + pack_nb++; + } + } + }/* x = x0..x1 */ + } + } /* y = y0..y1 */ + } /* resno */ + } /* compno */ + } /* precno */ + } /* PCRL */ + + else { /* CPRL */ + // Count the maximum number of precincts + int max_numprec = 0; + for (resno = 0; resno < max_numdecompos + 1; resno++) { + int numprec = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + if (numprec > max_numprec) + max_numprec = numprec; + } + + fprintf(stream, "CPRL\npack_nb tileno compno precno resno layno start_pos end_ph_pos end_pos"); + if (disto_on) + fprintf(stream, " disto"); + fprintf(stream,"\n"); + + for (compno = 0; compno < cstr_info->numcomps; compno++) { + /* I suppose components have same XRsiz, YRsiz */ + int x0 = cstr_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tw * cstr_info->tile_x; + int y0 = cstr_info->tile_Ox + (int)floor( (float)tileno/(float)cstr_info->tw ) * cstr_info->tile_y; + int x1 = x0 + cstr_info->tile_x; + int y1 = y0 + cstr_info->tile_y; + + for (precno = 0; precno < max_numprec; precno++) { + for (resno = 0; resno < cstr_info->numdecompos[compno] + 1; resno++) { + int numprec = cstr_info->tile[tileno].pw[resno] * cstr_info->tile[tileno].ph[resno]; + int pcnx = cstr_info->tile[tileno].pw[resno]; + int pcx = (int) pow( 2, cstr_info->tile[tileno].pdx[resno] + cstr_info->numdecompos[compno] - resno ); + int pcy = (int) pow( 2, cstr_info->tile[tileno].pdy[resno] + cstr_info->numdecompos[compno] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + if (precno >= numprec) + continue; + + for(y = y0; y < y1; y++) { + if (precno_y*pcy == y ) { + for (x = x0; x < x1; x++) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < cstr_info->numlayers; layno++) { + start_pos = cstr_info->tile[tileno].packet[pack_nb].start_pos; + end_ph_pos = cstr_info->tile[tileno].packet[pack_nb].end_ph_pos; + end_pos = cstr_info->tile[tileno].packet[pack_nb].end_pos; + disto = cstr_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %7d", + pack_nb, tileno, compno, precno, resno, layno, start_pos, end_ph_pos, end_pos); + if (disto_on) + fprintf(stream, " %8e", disto); + fprintf(stream, "\n"); + total_disto += disto; + pack_nb++; + } + } + }/* x = x0..x1 */ + } + } /* y = y0..y1 */ + } /* resno */ + } /* precno */ + } /* compno */ + } /* CPRL */ + } /* tileno */ + + if (disto_on) { + fprintf(stream, "%8e\n", cstr_info->D_max); /* SE max */ + fprintf(stream, "%.8e\n", total_disto); /* SE totale */ + } +/* UniPG>> */ + /* print the markers' list */ + if (cstr_info->marknum) { + fprintf(stream, "\nMARKER LIST\n"); + fprintf(stream, "%d\n", cstr_info->marknum); + fprintf(stream, "type\tstart_pos length\n"); + for (x = 0; x < cstr_info->marknum; x++) + fprintf(stream, "%X\t%9d %9d\n", cstr_info->marker[x].type, cstr_info->marker[x].pos, cstr_info->marker[x].len); + } +/* < + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#define __USE_BSD +#include +#include +#include +#define USE_OPJ_DEPRECATED +#include "openjpeg.h" +#include "compat/getopt.h" +#include "convert.h" +#include "dirent.h" +#include "index.h" + +#ifndef WIN32 +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + +/* ----------------------------------------------------------------------- */ + +#define J2K_CFMT 0 +#define JP2_CFMT 1 +#define JPT_CFMT 2 + +#define PXM_DFMT 10 +#define PGX_DFMT 11 +#define BMP_DFMT 12 +#define YUV_DFMT 13 +#define TIF_DFMT 14 +#define RAW_DFMT 15 +#define TGA_DFMT 16 + +/* ----------------------------------------------------------------------- */ + +typedef struct dircnt{ + /** Buffer for holding images read from Directory*/ + char *filename_buf; + /** Pointer to the buffer*/ + char **filename; +}dircnt_t; + + +typedef struct img_folder{ + /** The directory path of the folder containing input images*/ + char *imgdirpath; + /** Output format*/ + char *out_format; + /** Enable option*/ + char set_imgdir; + /** Enable Cod Format for output*/ + char set_out_format; + +}img_fol_t; + +void decode_help_display() { + fprintf(stdout,"HELP\n----\n\n"); + fprintf(stdout,"- the -h option displays this help information on screen\n\n"); + +/* UniPG>> */ + fprintf(stdout,"List of parameters for the JPEG 2000 " +#ifdef USE_JPWL + "+ JPWL " +#endif /* USE_JPWL */ + "decoder:\n"); +/* < \n"); + fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP, TIF, RAW and TGA formats\n"); + fprintf(stdout," -i \n"); + fprintf(stdout," REQUIRED only if an Input image directory not specified\n"); + fprintf(stdout," Currently accepts J2K-files, JP2-files and JPT-files. The file type\n"); + fprintf(stdout," is identified based on its suffix.\n"); + fprintf(stdout," -o \n"); + fprintf(stdout," REQUIRED\n"); + fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP, TIF, RAW and TGA files\n"); + fprintf(stdout," Binary data is written to the file (not ascii). If a PGX\n"); + fprintf(stdout," filename is given, there will be as many output files as there are\n"); + fprintf(stdout," components: an indice starting from 0 will then be appended to the\n"); + fprintf(stdout," output filename, just before the \"pgx\" extension. If a PGM filename\n"); + fprintf(stdout," is given and there are more than one component, only the first component\n"); + fprintf(stdout," will be written to the file.\n"); + fprintf(stdout," -r \n"); + fprintf(stdout," Set the number of highest resolution levels to be discarded. The\n"); + fprintf(stdout," image resolution is effectively divided by 2 to the power of the\n"); + fprintf(stdout," number of discarded levels. The reduce factor is limited by the\n"); + fprintf(stdout," smallest total number of decomposition levels among tiles.\n"); + fprintf(stdout," -l \n"); + fprintf(stdout," Set the maximum number of quality layers to decode. If there are\n"); + fprintf(stdout," less quality layers than the specified number, all the quality layers\n"); + fprintf(stdout," are decoded.\n"); + fprintf(stdout," -x \n"); + fprintf(stdout," Create an index file *.Idx (-x index_name.Idx) \n"); + fprintf(stdout,"\n"); +/* UniPG>> */ +#ifdef USE_JPWL + fprintf(stdout," -W \n"); + fprintf(stdout," Activates the JPWL correction capability, if the codestream complies.\n"); + fprintf(stdout," Options can be a comma separated list of tokens:\n"); + fprintf(stdout," c, c=numcomps\n"); + fprintf(stdout," numcomps is the number of expected components in the codestream\n"); + fprintf(stdout," (search of first EPB rely upon this, default is %d)\n", JPWL_EXPECTED_COMPONENTS); +#endif /* USE_JPWL */ +/* <d_name)==0 || strcmp("..",content->d_name)==0 ) + continue; + num_images++; + } + return num_images; +} + +int load_images(dircnt_t *dirptr, char *imgdirpath){ + DIR *dir; + struct dirent* content; + int i = 0; + + /*Reading the input images from given input directory*/ + + dir= opendir(imgdirpath); + if(!dir){ + fprintf(stderr,"Could not open Folder %s\n",imgdirpath); + return 1; + }else { + fprintf(stderr,"Folder opened successfully\n"); + } + + while((content=readdir(dir))!=NULL){ + if(strcmp(".",content->d_name)==0 || strcmp("..",content->d_name)==0 ) + continue; + + strcpy(dirptr->filename[i],content->d_name); + i++; + } + return 0; +} + +int get_file_format(char *filename) { + unsigned int i; + static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "tga", "j2k", "jp2", "jpt", "j2c" }; + static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, TGA_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT }; + char * ext = strrchr(filename, '.'); + if (ext == NULL) + return -1; + ext++; + if(ext) { + for(i = 0; i < sizeof(format)/sizeof(*format); i++) { + if(strnicmp(ext, extension[i], 3) == 0) { + return format[i]; + } + } + } + + return -1; +} + +char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters){ + char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],outfilename[OPJ_PATH_LEN],temp_ofname[OPJ_PATH_LEN]; + char *temp_p, temp1[OPJ_PATH_LEN]=""; + + strcpy(image_filename,dirptr->filename[imageno]); + fprintf(stderr,"File Number %d \"%s\"\n",imageno,image_filename); + parameters->decod_format = get_file_format(image_filename); + if (parameters->decod_format == -1) + return 1; + sprintf(infilename,"%s/%s",img_fol->imgdirpath,image_filename); + strncpy(parameters->infile, infilename, sizeof(infilename)); + + //Set output file + strcpy(temp_ofname,strtok(image_filename,".")); + while((temp_p = strtok(NULL,".")) != NULL){ + strcat(temp_ofname,temp1); + sprintf(temp1,".%s",temp_p); + } + if(img_fol->set_out_format==1){ + sprintf(outfilename,"%s/%s.%s",img_fol->imgdirpath,temp_ofname,img_fol->out_format); + strncpy(parameters->outfile, outfilename, sizeof(outfilename)); + } + return 0; +} + +/* -------------------------------------------------------------------------- */ +int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol, char *indexfilename) { + /* parse the command line */ + int totlen; + option_t long_option[]={ + {"ImgDir",REQ_ARG, NULL ,'y'}, + {"OutFor",REQ_ARG, NULL ,'O'}, + }; + + const char optlist[] = "i:o:r:l:hx:" + +/* UniPG>> */ +#ifdef USE_JPWL + "W:" +#endif /* USE_JPWL */ +/* <set_out_format = 0; + while (1) { + int c = getopt_long(argc, argv,optlist,long_option,totlen); + if (c == -1) + break; + switch (c) { + case 'i': /* input file */ + { + char *infile = optarg; + parameters->decod_format = get_file_format(infile); + switch(parameters->decod_format) { + case J2K_CFMT: + case JP2_CFMT: + case JPT_CFMT: + break; + default: + fprintf(stderr, + "!! Unrecognized format for infile : %s [accept only *.j2k, *.jp2, *.jpc or *.jpt] !!\n\n", + infile); + return 1; + } + strncpy(parameters->infile, infile, sizeof(parameters->infile)-1); + } + break; + + /* ----------------------------------------------------- */ + + case 'o': /* output file */ + { + char *outfile = optarg; + parameters->cod_format = get_file_format(outfile); + switch(parameters->cod_format) { + case PGX_DFMT: + case PXM_DFMT: + case BMP_DFMT: + case TIF_DFMT: + case RAW_DFMT: + case TGA_DFMT: + break; + default: + fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!! \n", outfile); + return 1; + } + strncpy(parameters->outfile, outfile, sizeof(parameters->outfile)-1); + } + break; + + /* ----------------------------------------------------- */ + + case 'O': /* output format */ + { + char outformat[50]; + char *of = optarg; + sprintf(outformat,".%s",of); + img_fol->set_out_format = 1; + parameters->cod_format = get_file_format(outformat); + switch(parameters->cod_format) { + case PGX_DFMT: + img_fol->out_format = "pgx"; + break; + case PXM_DFMT: + img_fol->out_format = "ppm"; + break; + case BMP_DFMT: + img_fol->out_format = "bmp"; + break; + case TIF_DFMT: + img_fol->out_format = "tif"; + break; + case RAW_DFMT: + img_fol->out_format = "raw"; + break; + case TGA_DFMT: + img_fol->out_format = "raw"; + break; + default: + fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!! \n", outformat); + return 1; + break; + } + } + break; + + /* ----------------------------------------------------- */ + + + case 'r': /* reduce option */ + { + sscanf(optarg, "%d", ¶meters->cp_reduce); + } + break; + + /* ----------------------------------------------------- */ + + + case 'l': /* layering option */ + { + sscanf(optarg, "%d", ¶meters->cp_layer); + } + break; + + /* ----------------------------------------------------- */ + + case 'h': /* display an help description */ + decode_help_display(); + return 1; + + /* ------------------------------------------------------ */ + + case 'y': /* Image Directory path */ + { + img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1); + strcpy(img_fol->imgdirpath,optarg); + img_fol->set_imgdir=1; + } + break; + /* ----------------------------------------------------- */ + case 'x': /* Creation of index file */ + { + char *index = optarg; + strncpy(indexfilename, index, OPJ_PATH_LEN); + } + break; + /* ----------------------------------------------------- */ + /* UniPG>> */ +#ifdef USE_JPWL + + case 'W': /* activate JPWL correction */ + { + char *token = NULL; + + token = strtok(optarg, ","); + while(token != NULL) { + + /* search expected number of components */ + if (*token == 'c') { + + static int compno; + + compno = JPWL_EXPECTED_COMPONENTS; /* predefined no. of components */ + + if(sscanf(token, "c=%d", &compno) == 1) { + /* Specified */ + if ((compno < 1) || (compno > 256)) { + fprintf(stderr, "ERROR -> invalid number of components c = %d\n", compno); + return 1; + } + parameters->jpwl_exp_comps = compno; + + } else if (!strcmp(token, "c")) { + /* default */ + parameters->jpwl_exp_comps = compno; /* auto for default size */ + + } else { + fprintf(stderr, "ERROR -> invalid components specified = %s\n", token); + return 1; + }; + } + + /* search maximum number of tiles */ + if (*token == 't') { + + static int tileno; + + tileno = JPWL_MAXIMUM_TILES; /* maximum no. of tiles */ + + if(sscanf(token, "t=%d", &tileno) == 1) { + /* Specified */ + if ((tileno < 1) || (tileno > JPWL_MAXIMUM_TILES)) { + fprintf(stderr, "ERROR -> invalid number of tiles t = %d\n", tileno); + return 1; + } + parameters->jpwl_max_tiles = tileno; + + } else if (!strcmp(token, "t")) { + /* default */ + parameters->jpwl_max_tiles = tileno; /* auto for default size */ + + } else { + fprintf(stderr, "ERROR -> invalid tiles specified = %s\n", token); + return 1; + }; + } + + /* next token or bust */ + token = strtok(NULL, ","); + }; + parameters->jpwl_correct = true; + fprintf(stdout, "JPWL correction capability activated\n"); + fprintf(stdout, "- expecting %d components\n", parameters->jpwl_exp_comps); + } + break; +#endif /* USE_JPWL */ +/* < this option is not valid \"-%c %s\"\n",c, optarg); + break; + } + } + + /* check for possible errors */ + if(img_fol->set_imgdir==1){ + if(!(parameters->infile[0]==0)){ + fprintf(stderr, "Error: options -ImgDir and -i cannot be used together !!\n"); + return 1; + } + if(img_fol->set_out_format == 0){ + fprintf(stderr, "Error: When -ImgDir is used, -OutFor must be used !!\n"); + fprintf(stderr, "Only one format allowed! Valid format PGM, PPM, PNM, PGX, BMP, TIF, RAW and TGA!!\n"); + return 1; + } + if(!((parameters->outfile[0] == 0))){ + fprintf(stderr, "Error: options -ImgDir and -o cannot be used together !!\n"); + return 1; + } + }else{ + if((parameters->infile[0] == 0) || (parameters->outfile[0] == 0)) { + fprintf(stderr, "Error: One of the options -i or -ImgDir must be specified\n"); + fprintf(stderr, "Error: When using -i, -o must be used\n"); + fprintf(stderr, "usage: image_to_j2k -i *.j2k/jp2/j2c -o *.pgm/ppm/pnm/pgx/bmp/tif/raw/tga(+ options)\n"); + return 1; + } + } + + return 0; +} + +/* -------------------------------------------------------------------------- */ + +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** +sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *client_data) { + (void)client_data; + fprintf(stdout, "[INFO] %s", msg); +} + +/* -------------------------------------------------------------------------- */ + +int main(int argc, char **argv) +{ + opj_dparameters_t parameters; /* decompression parameters */ + img_fol_t img_fol; + opj_image_t *image = NULL; + FILE *fsrc = NULL; + bool bResult; + int num_images; + int i,imageno; + dircnt_t *dirptr; + opj_codec_t* dinfo = NULL; /* handle to a decompressor */ + opj_stream_t *cio = NULL; + opj_codestream_info_t cstr_info; /* Codestream information structure */ + char indexfilename[OPJ_PATH_LEN]; /* index file name */ + OPJ_INT32 l_tile_x0,l_tile_y0; + OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y; + + /* configure the event callbacks (not required) */ + + /* set decoding parameters to default values */ + opj_set_default_decoder_parameters(¶meters); + + /* Initialize indexfilename and img_fol */ + *indexfilename = 0; + memset(&img_fol,0,sizeof(img_fol_t)); + + /* parse input and get user encoding parameters */ + if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol, indexfilename) == 1) { + return 1; + } + + /* Initialize reading of directory */ + if(img_fol.set_imgdir==1){ + num_images=get_num_images(img_fol.imgdirpath); + + dirptr=(dircnt_t*)malloc(sizeof(dircnt_t)); + if(dirptr){ + dirptr->filename_buf = (char*)malloc(num_images*OPJ_PATH_LEN*sizeof(char)); // Stores at max 10 image file names + dirptr->filename = (char**) malloc(num_images*sizeof(char*)); + + if(!dirptr->filename_buf){ + return 0; + } + for(i=0;ifilename[i] = dirptr->filename_buf + i*OPJ_PATH_LEN; + } + } + if(load_images(dirptr,img_fol.imgdirpath)==1){ + return 0; + } + if (num_images==0){ + fprintf(stdout,"Folder is empty\n"); + return 0; + } + }else{ + num_images=1; + } + + /*Encoding image one by one*/ + for(imageno = 0; imageno < num_images ; imageno++) + { + image = NULL; + fprintf(stderr,"\n"); + + if(img_fol.set_imgdir==1){ + if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) { + fprintf(stderr,"skipping file...\n"); + continue; + } + } + + /* read the input file and put it in memory */ + /* ---------------------------------------- */ + fsrc = fopen(parameters.infile, "rb"); + if + (!fsrc) + { + fprintf(stderr, "ERROR -> failed to open %s for reading\n", parameters.infile); + return 1; + } + cio = opj_stream_create_default_file_stream(fsrc,true); + /* decode the code-stream */ + /* ---------------------- */ + + switch + (parameters.decod_format) + { + case J2K_CFMT: + { + /* JPEG-2000 codestream */ + + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_J2K); + break; + } + case JP2_CFMT: + { + /* JPEG 2000 compressed image data */ + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_JP2); + break; + } + case JPT_CFMT: + { + /* JPEG 2000, JPIP */ + /* get a decoder handle */ + dinfo = opj_create_decompress(CODEC_JPT); + break; + } + default: + fprintf(stderr, "skipping file..\n"); + opj_stream_destroy(cio); + continue; + } + /* catch events using our callbacks and give a local context */ + + /* setup the decoder decoding parameters using user parameters */ + opj_setup_decoder(dinfo, ¶meters); + + /* decode the stream and fill the image structure */ + /* if (*indexfilename) // If need to extract codestream information + image = opj_decode_with_info(dinfo, cio, &cstr_info); + else + */ + bResult = opj_read_header( + dinfo, + &image, + &l_tile_x0, + &l_tile_y0, + &l_tile_width, + &l_tile_height, + &l_nb_tiles_x, + &l_nb_tiles_y, + cio); + image = opj_decode(dinfo, cio); + bResult = bResult && (image != 00); + bResult = bResult && opj_end_decompress(dinfo,cio); + if + (!image) + { + fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); + opj_destroy_codec(dinfo); + opj_stream_destroy(cio); + fclose(fsrc); + return 1; + } + + /* close the byte stream */ + opj_stream_destroy(cio); + fclose(fsrc); + /* Write the index to disk */ + if (*indexfilename) { + char bSuccess; + bSuccess = write_index_file(&cstr_info, indexfilename); + if (bSuccess) { + fprintf(stderr, "Failed to output index file\n"); + } + } + + /* create output image */ + /* ------------------- */ + switch (parameters.cod_format) { + case PXM_DFMT: /* PNM PGM PPM */ + if (imagetopnm(image, parameters.outfile)) { + fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); + } + break; + + case PGX_DFMT: /* PGX */ + if(imagetopgx(image, parameters.outfile)){ + fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); + } + break; + + case BMP_DFMT: /* BMP */ + if(imagetobmp(image, parameters.outfile)){ + fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); + } + break; + + case TIF_DFMT: /* TIFF */ + if(imagetotif(image, parameters.outfile)){ + fprintf(stdout,"Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); + } + break; + + case RAW_DFMT: /* RAW */ + if(imagetoraw(image, parameters.outfile)){ + fprintf(stdout,"Error generating raw file. Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); + } + break; + + case TGA_DFMT: /* TGA */ + if(imagetotga(image, parameters.outfile)){ + fprintf(stdout,"Error generating tga file. Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); + } + break; + } + + /* free remaining structures */ + if + (dinfo) + { + opj_destroy_codec(dinfo); + } + /* free codestream information structure */ + if (*indexfilename) + opj_destroy_cstr_info(&cstr_info); + /* free image data structure */ + opj_image_destroy(image); + + } + return 0; +} +//end main + + + + diff --git a/v2/libopenjpeg/CMakeLists.txt b/v2/libopenjpeg/CMakeLists.txt new file mode 100755 index 00000000..492c7196 --- /dev/null +++ b/v2/libopenjpeg/CMakeLists.txt @@ -0,0 +1,73 @@ +INCLUDE_REGULAR_EXPRESSION("^.*$") +# Defines the source code for the library +SET(OPENJPEG_SRCS + tcd.c + bio.c + cio.c + dwt.c + event.c + image.c + j2k.c + j2k_lib.c + jp2.c + jpt.c + mct.c + mqc.c + openjpeg.c + pi.c + raw.c + t1.c + tgt.c + profile.c + invert.c + function_list.c + t2.c + bio.h + cio.h + dwt.h + event.h + image.h + j2k.h + j2k_lib.h + jp2.h + jpt.h + mct.h + mqc.h + openjpeg.h + pi.h + int.h + raw.h + t1.h + t2.h + tcd.h + tgt.h + profile.h + invert.h + function_list.h +) + +# Pass proper definition to preprocessor to generate shared lib +IF(WIN32) + IF(BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_EXPORTS) + ELSE(BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_STATIC) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +IF(ENABLE_PROFILING) + ADD_DEFINITIONS(-D_PROFILE) +ENDIF(ENABLE_PROFILING) + +# Create the library +ADD_LIBRARY(${OPENJPEG_LIBRARY_NAME} ${OPENJPEG_SRCS}) +SET_TARGET_PROPERTIES(${OPENJPEG_LIBRARY_NAME} PROPERTIES + ${OPENJPEG_LIBRARY_PROPERTIES}) + +# Install library +INSTALL(TARGETS ${OPENJPEG_LIBRARY_NAME} + DESTINATION lib) + +# Install includes files +INSTALL(FILES openjpeg.h + DESTINATION ${INCLUDE_INSTALL_DIR}/openjpeg) diff --git a/v2/libopenjpeg/bio.c b/v2/libopenjpeg/bio.c new file mode 100755 index 00000000..81a1081f --- /dev/null +++ b/v2/libopenjpeg/bio.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "bio.h" +#include "opj_malloc.h" + +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Write a bit +@param bio BIO handle +@param b Bit to write (0 or 1) +*/ +static void bio_putbit(opj_bio_t *bio, OPJ_UINT32 b); +/** +Read a bit +@param bio BIO handle +@return Returns the read bit +*/ +static OPJ_UINT32 bio_getbit(opj_bio_t *bio); +/** +Write a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static bool bio_byteout(opj_bio_t *bio); +/** +Read a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static bool bio_bytein(opj_bio_t *bio); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static bool bio_byteout(opj_bio_t *bio) { + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if (bio->bp >= bio->end) { + return true; + } + *bio->bp++ = bio->buf >> 8; + return false; +} + +static bool bio_bytein(opj_bio_t *bio) { + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if (bio->bp >= bio->end) { + return true; + } + bio->buf |= *bio->bp++; + return false; +} + +static void bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) { + if (bio->ct == 0) { + bio_byteout(bio); + } + bio->ct--; + bio->buf |= b << bio->ct; +} + +static OPJ_UINT32 bio_getbit(opj_bio_t *bio) { + if (bio->ct == 0) { + bio_bytein(bio); + } + bio->ct--; + return (bio->buf >> bio->ct) & 1; +} + +/* +========================================================== + Bit Input/Output interface +========================================================== +*/ + +opj_bio_t* bio_create(void) { + opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); + return bio; +} + +void bio_destroy(opj_bio_t *bio) { + if(bio) { + opj_free(bio); + } +} + +OPJ_UINT32 bio_numbytes(opj_bio_t *bio) { + return (bio->bp - bio->start); +} + +void bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) { + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 8; +} + +void bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) { + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 0; +} + +void bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) { + OPJ_UINT32 i; + for (i = n - 1; i != -1 ; --i) { + bio_putbit(bio, (v >> i) & 1); + } +} + +OPJ_UINT32 bio_read(opj_bio_t *bio, OPJ_UINT32 n) { + OPJ_UINT32 i, v; + v = 0; + for (i = n - 1; i != -1 ; --i) { + v += bio_getbit(bio) << i; + } + return v; +} + +bool bio_flush(opj_bio_t *bio) { + bio->ct = 0; + if (bio_byteout(bio)) { + return true; + } + if (bio->ct == 7) { + bio->ct = 0; + if (bio_byteout(bio)) { + return true; + } + } + return false; +} + +bool bio_inalign(opj_bio_t *bio) { + bio->ct = 0; + if ((bio->buf & 0xff) == 0xff) { + if (bio_bytein(bio)) { + return true; + } + bio->ct = 0; + } + return false; +} diff --git a/v2/libopenjpeg/bio.h b/v2/libopenjpeg/bio.h new file mode 100755 index 00000000..2e6feec3 --- /dev/null +++ b/v2/libopenjpeg/bio.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __BIO_H +#define __BIO_H +/** +@file bio.h +@brief Implementation of an individual bit input-output (BIO) + +The functions in BIO.C have for goal to realize an individual bit input - output. +*/ +#include "openjpeg.h" +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** +Individual bit input-output stream (BIO) +*/ +typedef struct opj_bio { + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + OPJ_BYTE *end; + /** pointer to the present position in the buffer */ + OPJ_BYTE *bp; + /** temporary place where each byte is read or written */ + OPJ_UINT32 buf; + /** coder : number of bits free to write. decoder : number of bits read */ + OPJ_UINT32 ct; +} opj_bio_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new BIO handle +@return Returns a new BIO handle if successful, returns NULL otherwise +*/ +opj_bio_t* bio_create(void); +/** +Destroy a previously created BIO handle +@param bio BIO handle to destroy +*/ +void bio_destroy(opj_bio_t *bio); +/** +Number of bytes written. +@param bio BIO handle +@return Returns the number of bytes written +*/ +OPJ_UINT32 bio_numbytes(opj_bio_t *bio); +/** +Init encoder +@param bio BIO handle +@param bp Output buffer +@param len Output buffer length +*/ +void bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Init decoder +@param bio BIO handle +@param bp Input buffer +@param len Input buffer length +*/ +void bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Write bits +@param bio BIO handle +@param v Value of bits +@param n Number of bits to write +*/ +void bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n); +/** +Read bits +@param bio BIO handle +@param n Number of bits to read +@return Returns the corresponding read number +*/ +OPJ_UINT32 bio_read(opj_bio_t *bio, OPJ_UINT32 n); +/** +Flush bits +@param bio BIO handle +@return Returns 1 if successful, returns 0 otherwise +*/ +bool bio_flush(opj_bio_t *bio); +/** +Passes the ending bits (coming from flushing) +@param bio BIO handle +@return Returns 1 if successful, returns 0 otherwise +*/ +bool bio_inalign(opj_bio_t *bio); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __BIO_H */ + diff --git a/v2/libopenjpeg/cio.c b/v2/libopenjpeg/cio.c new file mode 100755 index 00000000..81c1cca7 --- /dev/null +++ b/v2/libopenjpeg/cio.c @@ -0,0 +1,820 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cio.h" +#include "opj_includes.h" +#include "opj_malloc.h" +#include "event.h" + +/* ----------------------------------------------------------------------- */ + + +/** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write +*/ +void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes; + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + memcpy(p_buffer,l_data_ptr,p_nb_bytes); +} + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write + * @return the number of bytes written or -1 if an error occured +*/ +void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1; + OPJ_UINT32 i; + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + for + (i=0;i 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + *p_value = 0; + memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,p_nb_bytes); +} + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occured. + */ +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes-1; + OPJ_UINT32 i; + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + *p_value = 0; + for + (i=0;im_buffer_size = p_size; + l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_size); + if + (! l_stream->m_stored_data) + { + opj_free(l_stream); + return 00; + } + l_stream->m_current_data = l_stream->m_stored_data; + if + (l_is_input) + { + l_stream->m_status |= opj_stream_e_input; + l_stream->m_opj_skip = opj_stream_read_skip; + l_stream->m_opj_seek = opj_stream_read_seek; + } + else + { + l_stream->m_status |= opj_stream_e_output; + l_stream->m_opj_skip = opj_stream_write_skip; + l_stream->m_opj_seek = opj_stream_write_seek; + } + l_stream->m_read_fn = opj_stream_default_read; + l_stream->m_write_fn = opj_stream_default_write; + l_stream->m_skip_fn = opj_stream_default_skip; + l_stream->m_seek_fn = opj_stream_default_seek; + + return (opj_stream_t *) l_stream; +} + +/** + * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. + * @return a stream object. +*/ +opj_stream_t* opj_stream_default_create(bool l_is_input) +{ + return opj_stream_create(J2K_STREAM_CHUNK_SIZE,l_is_input); +} + +/** + * Destroys a stream created by opj_create_stream. This function does NOT close the abstract stream. If needed the user must + * close its own implementation of the stream. + */ +OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if + (l_stream) + { + opj_free(l_stream->m_stored_data); + l_stream->m_stored_data = 00; + opj_free(l_stream); + } + +} + +/** + * Sets the given function to be used as a read function. + * @param p_stream the stream to modify + * @param p_function the function to use a read function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if + ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) + { + return; + } + l_stream->m_read_fn = p_function; +} + +OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if + (!l_stream) + { + return; + } + l_stream->m_seek_fn = p_function; +} + +/** + * Sets the given function to be used as a write function. + * @param p_stream the stream to modify + * @param p_function the function to use a write function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, opj_stream_write_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if + ((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output))) + { + return; + } + l_stream->m_write_fn = p_function; +} + +/** + * Sets the given function to be used as a skip function. + * @param p_stream the stream to modify + * @param p_function the function to use a skip function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, opj_stream_skip_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if + (! l_stream) + { + return; + } + l_stream->m_skip_fn = p_function; +} + +/** + * Sets the given data to be used as a user data for the stream. + * @param p_stream the stream to modify + * @param p_data the data to set. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + l_stream->m_user_data = p_data; +} + +/** + * Reads some bytes from the stream. + * @param p_stream the stream to read data from. + * @param p_buffer pointer to the data buffer that will receive the data. + * @param p_size number of bytes to read. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes read, or -1 if an error occured or if the stream is at the end. + */ +OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_UINT32 l_read_nb_bytes = 0; + if + (p_stream->m_bytes_in_buffer >= p_size) + { + memcpy(p_buffer,p_stream->m_current_data,p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + l_read_nb_bytes += p_size; + p_stream->m_byte_offset += p_size; + return l_read_nb_bytes; + } + + // we are now in the case when the remaining data if not sufficient + if + (p_stream->m_status & opj_stream_e_end) + { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes ? l_read_nb_bytes : -1; + } + + // the flag is not set, we copy data and then do an actual read on the stream + if + (p_stream->m_bytes_in_buffer) + { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + + while + (true) + { + // we should read less than a chunk -> read a chunk + if + (p_size < p_stream->m_buffer_size) + { + // we should do an actual read on the media + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,p_stream->m_buffer_size,p_stream->m_user_data); + if + (p_stream->m_bytes_in_buffer == -1) + { + // end of stream + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= opj_stream_e_end; + // end of stream + return l_read_nb_bytes ? l_read_nb_bytes : -1; + } + else if + (p_stream->m_bytes_in_buffer < p_size) + { + // not enough data + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + else + { + l_read_nb_bytes += p_size; + memcpy(p_buffer,p_stream->m_current_data,p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + p_stream->m_byte_offset += p_size; + return l_read_nb_bytes; + } + } + else + { + // direct read on the dest buffer + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data); + if + (p_stream->m_bytes_in_buffer == -1) + { + // end of stream + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= opj_stream_e_end; + // end of stream + return l_read_nb_bytes ? l_read_nb_bytes : -1; + } + else if + (p_stream->m_bytes_in_buffer < p_size) + { + // not enough data + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + else + { + // we have read the exact size + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes; + } + } + } +} + +/** + * Writes some bytes from the stream. + * @param p_stream the stream to write data to. + * @param p_buffer pointer to the data buffer holds the data to be writtent. + * @param p_size number of bytes to write. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes writtent, or -1 if an error occured. + */ +OPJ_UINT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer,OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_UINT32 l_remaining_bytes = 0; + OPJ_UINT32 l_write_nb_bytes = 0; + + if + (p_stream->m_status & opj_stream_e_error) + { + return -1; + } + + while + (true) + { + l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer; + // we have more memory than required + if + (l_remaining_bytes >= p_size) + { + memcpy(p_stream->m_current_data,p_buffer,p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer += p_size; + l_write_nb_bytes += p_size; + p_stream->m_byte_offset += p_size; + return l_write_nb_bytes; + } + + // we copy data and then do an actual read on the stream + if + (l_remaining_bytes) + { + l_write_nb_bytes += l_remaining_bytes; + memcpy(p_stream->m_current_data,p_buffer,l_remaining_bytes); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += l_remaining_bytes; + p_size -= l_remaining_bytes; + p_stream->m_bytes_in_buffer += l_remaining_bytes; + p_stream->m_byte_offset += l_remaining_bytes; + } + if + (! opj_stream_flush(p_stream, p_event_mgr)) + { + return -1; + } + } + +} + +/** + * Writes the content of the stream buffer to the stream. + * @param p_stream the stream to write data to. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes written, or -1 if an error occured. + */ +bool opj_stream_flush (opj_stream_private_t * p_stream, opj_event_mgr_t * p_event_mgr) +{ + // the number of bytes written on the media. + OPJ_UINT32 l_current_write_nb_bytes = 0; + p_stream->m_current_data = p_stream->m_stored_data; + + while + (p_stream->m_bytes_in_buffer) + { + // we should do an actual write on the media + l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data,p_stream->m_bytes_in_buffer,p_stream->m_user_data); + if + (l_current_write_nb_bytes == -1) + { + p_stream->m_status |= opj_stream_e_error; + opj_event_msg(p_event_mgr, EVT_INFO, "Error on writting stream!\n"); + return false; + } + p_stream->m_current_data += l_current_write_nb_bytes; + p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes; + } + p_stream->m_current_data = p_stream->m_stored_data; + return true; +} + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_SIZE_T l_skip_nb_bytes = 0; + OPJ_SIZE_T l_current_skip_nb_bytes = 0; + + if + (p_stream->m_bytes_in_buffer >= p_size) + { + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + l_skip_nb_bytes += p_size; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes; + } + + // we are now in the case when the remaining data if not sufficient + if + (p_stream->m_status & opj_stream_e_end) + { + l_skip_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T) -1; + } + + // the flag is not set, we copy data and then do an actual skip on the stream + if + (p_stream->m_bytes_in_buffer) + { + l_skip_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + + while + (p_size > 0) + { + // we should do an actual skip on the media + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); + if + (l_current_skip_nb_bytes == (OPJ_SIZE_T) -1) + { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + p_stream->m_status |= opj_stream_e_end; + p_stream->m_byte_offset += l_skip_nb_bytes; + // end if stream + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T) -1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes; +} + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + bool l_is_written = 0; + OPJ_SIZE_T l_current_skip_nb_bytes = 0; + OPJ_SIZE_T l_skip_nb_bytes = 0; + + if + (p_stream->m_status & opj_stream_e_error) + { + return (OPJ_SIZE_T) -1; + } + + // we should flush data + l_is_written = opj_stream_flush (p_stream, p_event_mgr); + if + (! l_is_written) + { + p_stream->m_status |= opj_stream_e_error; + p_stream->m_bytes_in_buffer = 0; + p_stream->m_current_data = p_stream->m_current_data; + return (OPJ_SIZE_T) -1; + } + // then skip + + while + (p_size > 0) + { + // we should do an actual skip on the media + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); + if + (l_current_skip_nb_bytes == (OPJ_SIZE_T)-1) + { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n"); + p_stream->m_status |= opj_stream_e_error; + p_stream->m_byte_offset += l_skip_nb_bytes; + // end if stream + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_T)-1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes; +} + +/** + * Tells the byte offset on the stream (similar to ftell). + * + * @param p_stream the stream to get the information from. + * + * @return the current position o fthe stream. + */ +OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream) +{ + return p_stream->m_byte_offset; +} + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr); +} + + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + if + (! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) + { + p_stream->m_status |= opj_stream_e_end; + return false; + } + else + { + // reset stream status + p_stream->m_status &= (~opj_stream_e_end); + p_stream->m_byte_offset = p_size; + + } + return true; +} + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + if + (! opj_stream_flush(p_stream,p_event_mgr)) + { + p_stream->m_status |= opj_stream_e_error; + return false; + } + + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + + if + (! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) + { + p_stream->m_status |= opj_stream_e_error; + return false; + } + else + { + p_stream->m_byte_offset = p_size; + } + return true; +} + + +/** + * Seeks a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the stream is seekable. + */ +bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr) +{ + return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr); +} + +/** + * Tells if the given stream is seekable. + */ +bool opj_stream_has_seek (const opj_stream_private_t * p_stream) +{ + return p_stream->m_seek_fn != opj_stream_default_seek; +} + + + + + +OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) +{ + return (OPJ_UINT32) -1; +} +OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) +{ + return (OPJ_UINT32) -1; +} +OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data) +{ + return (OPJ_SIZE_T) -1; +} + +bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data) +{ + return false; +} + + + diff --git a/v2/libopenjpeg/cio.h b/v2/libopenjpeg/cio.h new file mode 100755 index 00000000..6315e8f4 --- /dev/null +++ b/v2/libopenjpeg/cio.h @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CIO_H +#define __CIO_H +/** +@file cio.h +@brief Implementation of a byte input-output process (CIO) + +The functions in CIO.C have for goal to realize a byte input / output process. +*/ + +/** @defgroup CIO CIO - byte input-output stream */ +/*@{*/ + +#include "openjpeg.h" +#include "opj_configure.h" +struct opj_event_mgr; +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +#if defined(OPJ_BIG_ENDIAN) + #if !defined(OPJ_LITTLE_ENDIAN) + #define opj_write_bytes opj_write_bytes_BE + #define opj_read_bytes opj_read_bytes_BE + #define opj_write_double opj_write_double_BE + #define opj_read_double opj_read_double_BE + #define opj_write_float opj_write_float_BE + #define opj_read_float opj_read_float_BE + #else + #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both." + #endif +#else + #if defined(OPJ_LITTLE_ENDIAN) + #define opj_write_bytes opj_write_bytes_LE + #define opj_read_bytes opj_read_bytes_LE + #define opj_write_double opj_write_double_LE + #define opj_read_double opj_read_double_LE + #define opj_write_float opj_write_float_LE + #define opj_read_float opj_read_float_LE + #else + #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not none." + #endif +#endif + + + +typedef enum +{ + opj_stream_e_output = 0x1, + opj_stream_e_input = 0x2, + opj_stream_e_end = 0x4, + opj_stream_e_error = 0x8 +} +opj_stream_flag ; + +/** +Byte input-output stream. +*/ +typedef struct opj_stream_private +{ + /** + * User data, be it files, ... The actual data depends on the type of the stream. + */ + void * m_user_data; + + /** + * Pointer to actual read function (NULL at the initialization of the cio. + */ + opj_stream_read_fn m_read_fn; + + /** + * Pointer to actual write function (NULL at the initialization of the cio. + */ + opj_stream_write_fn m_write_fn; + + /** + * Pointer to actual skip function (NULL at the initialization of the cio. + * There is no seek function to prevent from back and forth slow procedures. + */ + opj_stream_skip_fn m_skip_fn; + + /** + * Pointer to actual seek function (if available). + */ + opj_stream_seek_fn m_seek_fn; + + + + + /** + * Actual data stored into the stream if readed from. Data is read by chunk of fixed size. + * you should never access this data directly. + */ + OPJ_BYTE * m_stored_data; + + /** + * Pointer to the current read data. + */ + OPJ_BYTE * m_current_data; + + OPJ_SIZE_T (* m_opj_skip)(struct opj_stream_private * ,OPJ_SIZE_T , struct opj_event_mgr *); + + bool (* m_opj_seek) (struct opj_stream_private * , OPJ_SIZE_T , struct opj_event_mgr *); + + /** + * number of bytes containing in the buffer. + */ + OPJ_UINT32 m_bytes_in_buffer; + + /** + * The number of bytes read/written. + */ + OPJ_SIZE_T m_byte_offset; + + /** + * The size of the buffer. + */ + OPJ_UINT32 m_buffer_size; + + /** + * Flags to tell the status of the stream. + */ + OPJ_UINT32 m_status; + +} +opj_stream_private_t; + + +/** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write +*/ +void opj_write_bytes_BE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occured. + */ +void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes); + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write + * @return the number of bytes written or -1 if an error occured +*/ +void opj_write_bytes_LE (OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, OPJ_UINT32 p_nb_bytes); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occured. + */ +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes); + + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); + +/*** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); + +/*** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); + +/** + * Reads some bytes from the stream. + * @param p_stream the stream to read data from. + * @param p_buffer pointer to the data buffer that will receive the data. + * @param p_size number of bytes to read. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes read, or -1 if an error occured or if the stream is at the end. + */ +OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Writes some bytes to the stream. + * @param p_stream the stream to write data to. + * @param p_buffer pointer to the data buffer holds the data to be writtent. + * @param p_size number of bytes to write. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes writtent, or -1 if an error occured. + */ +OPJ_UINT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Writes the content of the stream buffer to the stream. + * @param p_stream the stream to write data to. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the data could be flushed, false else. + */ +bool opj_stream_flush (opj_stream_private_t * p_stream, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Tells the byte offset on the stream (similar to ftell). + * + * @param p_stream the stream to get the information from. + * + * @return the current position o fthe stream. + */ +OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occured. + */ +bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Seeks a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the stream is seekable. + */ +bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Tells if the given stream is seekable. + */ +bool opj_stream_has_seek (const opj_stream_private_t * p_stream); + +OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data); +OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data); +OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data); +bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __CIO_H */ + diff --git a/v2/libopenjpeg/dwt.c b/v2/libopenjpeg/dwt.c new file mode 100755 index 00000000..0e41f805 --- /dev/null +++ b/v2/libopenjpeg/dwt.c @@ -0,0 +1,873 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Jonathan Ballard + * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef __SSE__ +#include +#endif + +#include "dwt.h" +#include "j2k.h" +#include "tcd.h" +#include "fix.h" +#include "opj_malloc.h" +#include "int.h" + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + +#define WS(i) v->mem[(i)*2] +#define WD(i) v->mem[(1+(i)*2)] + +/** @name Local data structures */ +/*@{*/ + +typedef struct dwt_local { + OPJ_INT32* mem; + OPJ_INT32 dn; + OPJ_INT32 sn; + OPJ_INT32 cas; +} dwt_t; + +typedef union { + OPJ_FLOAT32 f[4]; +} v4; + +typedef struct v4dwt_local { + v4* wavelet ; + OPJ_INT32 dn ; + OPJ_INT32 sn ; + OPJ_INT32 cas ; +} v4dwt_t ; + +static const OPJ_FLOAT32 dwt_alpha = 1.586134342f; // 12994 +static const OPJ_FLOAT32 dwt_beta = 0.052980118f; // 434 +static const OPJ_FLOAT32 dwt_gamma = -0.882911075f; // -7233 +static const OPJ_FLOAT32 delta = -0.443506852f; // -3633 + +static const OPJ_FLOAT32 K = 1.230174105f; // 10078 +/* FIXME: What is this constant? */ +static const OPJ_FLOAT32 c13318 = 1.625732422f; + +/*@}*/ + +/** +Virtual function type for wavelet transform in 1-D +*/ +typedef void (*DWT1DFN)(dwt_t* v); + +/** @name Local static functions */ +/*@{*/ + +/** +Forward lazy transform (horizontal) +*/ +static void dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +/** +Forward lazy transform (vertical) +*/ +static void dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas); +/** +Inverse lazy transform (horizontal) +*/ +static void dwt_interleave_h(dwt_t* h, OPJ_INT32 *a); +/** +Inverse lazy transform (vertical) +*/ +static void dwt_interleave_v(dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x); +/** +Forward 5-3 wavelet transform in 1-D +*/ +static void dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +/** +Inverse 5-3 wavelet transform in 1-D +*/ +static void dwt_decode_1(dwt_t *v); +/** +Forward 9-7 wavelet transform in 1-D +*/ +static void dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); +/** +Explicit calculation of the Quantization Stepsizes +*/ +static void dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize); +/** +Inverse wavelet transform in 2-D. +*/ +static bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn); + +static OPJ_UINT32 dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i); + +static INLINE bool dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ); +/*@}*/ + +/*@}*/ + +#define S(i) a[(i)*2] +#define D(i) a[(1+(i)*2)] +#define S_(i) ((i)<0?S(0):((i)>=sn?S(sn-1):S(i))) +#define D_(i) ((i)<0?D(0):((i)>=dn?D(dn-1):D(i))) +/* new */ +#define SS_(i) ((i)<0?S(0):((i)>=dn?S(dn-1):S(i))) +#define DD_(i) ((i)<0?D(0):((i)>=sn?D(sn-1):D(i))) + +/* */ +/* This table contains the norms of the 5-3 wavelets for different bands. */ +/* */ +static const OPJ_FLOAT64 dwt_norms[4][10] = { + {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93} +}; + +/* */ +/* This table contains the norms of the 9-7 wavelets for different bands. */ +/* */ +static const OPJ_FLOAT64 dwt_norms_real[4][10] = { + {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} +}; + +/* +========================================================== + local functions +========================================================== +*/ + +/* */ +/* Forward lazy transform (horizontal). */ +/* */ +static void dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { + OPJ_INT32 i; + + OPJ_INT32 * l_dest = b; + OPJ_INT32 * l_src = a+cas; + for + (i=0; i */ +/* Forward lazy transform (vertical). */ +/* */ +static void dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) { + OPJ_INT32 i = sn; + OPJ_INT32 * l_dest = b; + OPJ_INT32 * l_src = a+cas; + + while + (i--) + { + *l_dest = *l_src; + l_dest += x; + l_src += 2; + /* b[i*x]=a[2*i+cas]; */ + } + l_dest = b + sn * x; + l_src = a + 1 - cas; + + i = dn; + while + (i--) + { + *l_dest = *l_src; + l_dest += x; + l_src += 2; + /*b[(sn+i)*x]=a[(2*i+1-cas)];*/ + } +} + +/* */ +/* Inverse lazy transform (horizontal). */ +/* */ +static void dwt_interleave_h(dwt_t* h, OPJ_INT32 *a) { + OPJ_INT32 *ai = a; + OPJ_INT32 *bi = h->mem + h->cas; + OPJ_INT32 i = h->sn; + while + ( i-- ) + { + *bi = *(ai++); + bi += 2; + } + ai = a + h->sn; + bi = h->mem + 1 - h->cas; + i = h->dn ; + while + ( i-- ) + { + *bi = *(ai++); + bi += 2; + } +} + +/* */ +/* Inverse lazy transform (vertical). */ +/* */ +static void dwt_interleave_v(dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) { + OPJ_INT32 *ai = a; + OPJ_INT32 *bi = v->mem + v->cas; + OPJ_INT32 i = v->sn; + while( i-- ) { + *bi = *ai; + bi += 2; + ai += x; + } + ai = a + (v->sn * x); + bi = v->mem + 1 - v->cas; + i = v->dn ; + while( i-- ) { + *bi = *ai; + bi += 2; + ai += x; + } +} + + +/* */ +/* Forward 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) D(i) -= (S_(i) + S_(i + 1)) >> 1; + for (i = 0; i < sn; i++) S(i) += (D_(i - 1) + D_(i) + 2) >> 2; + } + } else { + if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ + S(0) *= 2; + else { + for (i = 0; i < dn; i++) S(i) -= (DD_(i) + DD_(i - 1)) >> 1; + for (i = 0; i < sn; i++) D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2; + } + } +} + +/* */ +/* Inverse 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) S(i) -= (D_(i - 1) + D_(i) + 2) >> 2; + for (i = 0; i < dn; i++) D(i) += (S_(i) + S_(i + 1)) >> 1; + } + } else { + if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ + S(0) /= 2; + else { + for (i = 0; i < sn; i++) D(i) -= (SS_(i) + SS_(i + 1) + 2) >> 2; + for (i = 0; i < dn; i++) S(i) += (DD_(i) + DD_(i - 1)) >> 1; + } + } +} + +/* */ +/* Inverse 5-3 wavelet transform in 1-D. */ +/* */ +static void dwt_decode_1(dwt_t *v) { + dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); +} + +/* */ +/* Forward 9-7 wavelet transform in 1-D. */ +/* */ +static void dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { + OPJ_INT32 i; + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) + D(i) -= fix_mul(S_(i) + S_(i + 1), 12993); + for (i = 0; i < sn; i++) + S(i) -= fix_mul(D_(i - 1) + D_(i), 434); + for (i = 0; i < dn; i++) + D(i) += fix_mul(S_(i) + S_(i + 1), 7233); + for (i = 0; i < sn; i++) + S(i) += fix_mul(D_(i - 1) + D_(i), 3633); + for (i = 0; i < dn; i++) + D(i) = fix_mul(D(i), 5038); /*5038 */ + for (i = 0; i < sn; i++) + S(i) = fix_mul(S(i), 6659); /*6660 */ + } + } else { + if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < dn; i++) + S(i) -= fix_mul(DD_(i) + DD_(i - 1), 12993); + for (i = 0; i < sn; i++) + D(i) -= fix_mul(SS_(i) + SS_(i + 1), 434); + for (i = 0; i < dn; i++) + S(i) += fix_mul(DD_(i) + DD_(i - 1), 7233); + for (i = 0; i < sn; i++) + D(i) += fix_mul(SS_(i) + SS_(i + 1), 3633); + for (i = 0; i < dn; i++) + S(i) = fix_mul(S(i), 5038); /*5038 */ + for (i = 0; i < sn; i++) + D(i) = fix_mul(D(i), 6659); /*6660 */ + } + } +} + +static void dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize) { + OPJ_INT32 p, n; + p = int_floorlog2(stepsize) - 13; + n = 11 - int_floorlog2(stepsize); + bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; + bandno_stepsize->expn = numbps - p; +} + +/* +========================================================== + DWT interface +========================================================== +*/ + +/* */ +/* Forward 5-3 wavelet transform in 2-D. */ +/* */ +INLINE bool dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ) +{ + OPJ_INT32 i, j, k; + OPJ_INT32 *a = 00; + OPJ_INT32 *aj = 00; + OPJ_INT32 *bj = 00; + OPJ_INT32 w, l; + + OPJ_INT32 rw; /* width of the resolution level computed */ + OPJ_INT32 rh; /* height of the resolution level computed */ + OPJ_INT32 l_data_size; + + opj_tcd_resolution_t * l_cur_res = 0; + opj_tcd_resolution_t * l_last_res = 0; + + w = tilec->x1-tilec->x0; + l = tilec->numresolutions-1; + a = tilec->data; + + l_cur_res = tilec->resolutions + l; + l_last_res = l_cur_res - 1; + + rw = l_cur_res->x1 - l_cur_res->x0; + rh = l_cur_res->y1 - l_cur_res->y0; + + l_data_size = dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * sizeof(OPJ_INT32); + bj = opj_malloc(l_data_size); + if + (! bj) + { + return false; + } + i = l; + + while + (i--) + { + OPJ_INT32 rw1; /* width of the resolution level once lower than computed one */ + OPJ_INT32 rh1; /* height of the resolution level once lower than computed one */ + OPJ_INT32 cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 dn, sn; + + rw = l_cur_res->x1 - l_cur_res->x0; + rh = l_cur_res->y1 - l_cur_res->y0; + rw1 = l_last_res->x1 - l_last_res->x0; + rh1 = l_last_res->y1 - l_last_res->y0; + + cas_row = l_cur_res->x0 & 1; + cas_col = l_cur_res->y0 & 1; + + sn = rh1; + dn = rh - rh1; + for + (j = 0; j < rw; ++j) + { + aj = a + j; + for + (k = 0; k < rh; ++k) + { + bj[k] = aj[k*w]; + } + (*p_function) (bj, dn, sn, cas_col); + dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + sn = rw1; + dn = rw - rw1; + for (j = 0; j < rh; j++) + { + aj = a + j * w; + for (k = 0; k < rw; k++) bj[k] = aj[k]; + (*p_function) (bj, dn, sn, cas_row); + dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + l_cur_res = l_last_res; + --l_last_res; + } + opj_free(bj); + return true; +} +/* Forward 5-3 wavelet transform in 2-D. */ +/* */ +bool dwt_encode(opj_tcd_tilecomp_t * tilec) +{ + return dwt_encode_procedure(tilec,dwt_encode_1); +} + +/* */ +/* Inverse 5-3 wavelet transform in 2-D. */ +/* */ +bool dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) { + return dwt_decode_tile(tilec, numres, &dwt_decode_1); +} + + +/* */ +/* Get gain of 5-3 wavelet transform. */ +/* */ +OPJ_UINT32 dwt_getgain(OPJ_UINT32 orient) { + if (orient == 0) + return 0; + if (orient == 1 || orient == 2) + return 1; + return 2; +} + +/* */ +/* Get norm of 5-3 wavelet. */ +/* */ +OPJ_FLOAT64 dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) { + return dwt_norms[orient][level]; +} + +/* */ +/* Forward 9-7 wavelet transform in 2-D. */ +/* */ +bool dwt_encode_real(opj_tcd_tilecomp_t * tilec) +{ + return dwt_encode_procedure(tilec,dwt_encode_1_real); +} + + + +/* */ +/* Get gain of 9-7 wavelet transform. */ +/* */ +OPJ_UINT32 dwt_getgain_real(OPJ_UINT32 orient) { + (void)orient; + return 0; +} + +/* */ +/* Get norm of 9-7 wavelet. */ +/* */ +OPJ_FLOAT64 dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) { + return dwt_norms_real[orient][level]; +} + +void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec) { + OPJ_UINT32 numbands, bandno; + numbands = 3 * tccp->numresolutions - 2; + for (bandno = 0; bandno < numbands; bandno++) { + OPJ_FLOAT64 stepsize; + OPJ_UINT32 resno, level, orient, gain; + + resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1); + orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1); + level = tccp->numresolutions - 1 - resno; + gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || (orient == 2)) ? 1 : 2)); + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + stepsize = 1.0; + } else { + OPJ_FLOAT64 norm = dwt_norms_real[orient][level]; + stepsize = (1 << (gain)) / norm; + } + dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]); + } +} + + +/* */ +/* Determine maximum computed resolution level for inverse wavelet transform */ +/* */ +static OPJ_UINT32 dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) { + OPJ_UINT32 mr = 0; + OPJ_UINT32 w; + while( --i ) { + ++r; + if( mr < ( w = r->x1 - r->x0 ) ) + mr = w ; + if( mr < ( w = r->y1 - r->y0 ) ) + mr = w ; + } + return mr ; +} + + +/* */ +/* Inverse wavelet transform in 2-D. */ +/* */ +static bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) { + dwt_t h; + dwt_t v; + + opj_tcd_resolution_t* tr = tilec->resolutions; + + OPJ_UINT32 rw = tr->x1 - tr->x0; /* width of the resolution level computed */ + OPJ_UINT32 rh = tr->y1 - tr->y0; /* height of the resolution level computed */ + + OPJ_UINT32 w = tilec->x1 - tilec->x0; + + h.mem = opj_aligned_malloc(dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32)); + if + (! h.mem) + { + return false; + } + + v.mem = h.mem; + + while( --numres) { + OPJ_INT32 * restrict tiledp = tilec->data; + OPJ_UINT32 j; + + ++tr; + h.sn = rw; + v.sn = rh; + + rw = tr->x1 - tr->x0; + rh = tr->y1 - tr->y0; + + h.dn = rw - h.sn; + h.cas = tr->x0 % 2; + + for(j = 0; j < rh; ++j) { + dwt_interleave_h(&h, &tiledp[j*w]); + (dwt_1D)(&h); + memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32)); + } + + v.dn = rh - v.sn; + v.cas = tr->y0 % 2; + + for(j = 0; j < rw; ++j){ + OPJ_UINT32 k; + dwt_interleave_v(&v, &tiledp[j], w); + (dwt_1D)(&v); + for(k = 0; k < rh; ++k) { + tiledp[k * w + j] = v.mem[k]; + } + } + } + opj_aligned_free(h.mem); + return true; +} + +static void v4dwt_interleave_h(v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size){ + OPJ_FLOAT32* restrict bi = (OPJ_FLOAT32*) (w->wavelet + w->cas); + OPJ_INT32 count = w->sn; + OPJ_INT32 i, k; + for(k = 0; k < 2; ++k){ + for(i = 0; i < count; ++i){ + OPJ_INT32 j = i; + bi[i*8 ] = a[j]; + j += x; + if(j >= size) continue; + bi[i*8 + 1] = a[j]; + j += x; + if(j >= size) continue; + bi[i*8 + 2] = a[j]; + j += x; + if(j >= size) continue; + bi[i*8 + 3] = a[j]; + } + bi = (OPJ_FLOAT32*) (w->wavelet + 1 - w->cas); + a += w->sn; + size -= w->sn; + count = w->dn; + } +} + +static void v4dwt_interleave_v(v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x){ + v4* restrict bi = v->wavelet + v->cas; + OPJ_INT32 i; + for(i = 0; i < v->sn; ++i){ + memcpy(&bi[i*2], &a[i*x], 4 * sizeof(OPJ_FLOAT32)); + } + a += v->sn * x; + bi = v->wavelet + 1 - v->cas; + for(i = 0; i < v->dn; ++i){ + memcpy(&bi[i*2], &a[i*x], 4 * sizeof(OPJ_FLOAT32)); + } +} + +#ifdef __SSE__ + +static void v4dwt_decode_step1_sse(v4* w, OPJ_INT32 count, const __m128 c){ + __m128* restrict vw = (__m128*) w; + OPJ_INT32 i; + for(i = 0; i < count; ++i){ + __m128 tmp = vw[i*2]; + vw[i*2] = tmp * c; + } +} + +static void v4dwt_decode_step2_sse(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, __m128 c){ + __m128* restrict vl = (__m128*) l; + __m128* restrict vw = (__m128*) w; + OPJ_INT32 i; + for(i = 0; i < m; ++i){ + __m128 tmp1 = vl[ 0]; + __m128 tmp2 = vw[-1]; + __m128 tmp3 = vw[ 0]; + vw[-1] = tmp2 + ((tmp1 + tmp3) * c); + vl = vw; + vw += 2; + } + if(m >= k){ + return; + } + c += c; + c *= vl[0]; + for(; m < k; ++m){ + __m128 tmp = vw[-1]; + vw[-1] = tmp + c; + vw += 2; + } +} + +#else + +static void v4dwt_decode_step1(v4* w, OPJ_INT32 count, const OPJ_FLOAT32 c){ + OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; + OPJ_INT32 i; + for(i = 0; i < count; ++i){ + OPJ_FLOAT32 tmp1 = fw[i*8 ]; + OPJ_FLOAT32 tmp2 = fw[i*8 + 1]; + OPJ_FLOAT32 tmp3 = fw[i*8 + 2]; + OPJ_FLOAT32 tmp4 = fw[i*8 + 3]; + fw[i*8 ] = tmp1 * c; + fw[i*8 + 1] = tmp2 * c; + fw[i*8 + 2] = tmp3 * c; + fw[i*8 + 3] = tmp4 * c; + } +} + +static void v4dwt_decode_step2(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c){ + OPJ_FLOAT32* restrict fl = (OPJ_FLOAT32*) l; + OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; + OPJ_INT32 i; + for(i = 0; i < m; ++i){ + OPJ_FLOAT32 tmp1_1 = fl[0]; + OPJ_FLOAT32 tmp1_2 = fl[1]; + OPJ_FLOAT32 tmp1_3 = fl[2]; + OPJ_FLOAT32 tmp1_4 = fl[3]; + OPJ_FLOAT32 tmp2_1 = fw[-4]; + OPJ_FLOAT32 tmp2_2 = fw[-3]; + OPJ_FLOAT32 tmp2_3 = fw[-2]; + OPJ_FLOAT32 tmp2_4 = fw[-1]; + OPJ_FLOAT32 tmp3_1 = fw[0]; + OPJ_FLOAT32 tmp3_2 = fw[1]; + OPJ_FLOAT32 tmp3_3 = fw[2]; + OPJ_FLOAT32 tmp3_4 = fw[3]; + fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c); + fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c); + fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c); + fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c); + fl = fw; + fw += 8; + } + if(m < k){ + OPJ_FLOAT32 c1; + OPJ_FLOAT32 c2; + OPJ_FLOAT32 c3; + OPJ_FLOAT32 c4; + c += c; + c1 = fl[0] * c; + c2 = fl[1] * c; + c3 = fl[2] * c; + c4 = fl[3] * c; + for(; m < k; ++m){ + OPJ_FLOAT32 tmp1 = fw[-4]; + OPJ_FLOAT32 tmp2 = fw[-3]; + OPJ_FLOAT32 tmp3 = fw[-2]; + OPJ_FLOAT32 tmp4 = fw[-1]; + fw[-4] = tmp1 + c1; + fw[-3] = tmp2 + c2; + fw[-2] = tmp3 + c3; + fw[-1] = tmp4 + c4; + fw += 8; + } + } +} + +#endif + +/* */ +/* Inverse 9-7 wavelet transform in 1-D. */ +/* */ +static void v4dwt_decode(v4dwt_t* restrict dwt){ + OPJ_INT32 a, b; + if(dwt->cas == 0) { + if(!((dwt->dn > 0) || (dwt->sn > 1))){ + return; + } + a = 0; + b = 1; + }else{ + if(!((dwt->sn > 0) || (dwt->dn > 1))) { + return; + } + a = 1; + b = 0; + } +#ifdef __SSE__ + v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(K)); + v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(c13318)); + v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(delta)); + v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma)); + v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta)); + v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha)); +#else + v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, K); + v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, c13318); + v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), delta); + v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma); + v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta); + v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha); +#endif +} + +/* */ +/* Inverse 9-7 wavelet transform in 2-D. */ +/* */ +bool dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres){ + v4dwt_t h; + v4dwt_t v; + + opj_tcd_resolution_t* res = tilec->resolutions; + + OPJ_UINT32 rw = res->x1 - res->x0; /* width of the resolution level computed */ + OPJ_UINT32 rh = res->y1 - res->y0; /* height of the resolution level computed */ + + OPJ_UINT32 w = tilec->x1 - tilec->x0; + + h.wavelet = (v4*) opj_aligned_malloc((dwt_max_resolution(res, numres)+5) * sizeof(v4)); + v.wavelet = h.wavelet; + + while( --numres) { + OPJ_FLOAT32 * restrict aj = (OPJ_FLOAT32*) tilec->data; + OPJ_UINT32 bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0); + OPJ_INT32 j; + + h.sn = rw; + v.sn = rh; + + ++res; + + rw = res->x1 - res->x0; /* width of the resolution level computed */ + rh = res->y1 - res->y0; /* height of the resolution level computed */ + + h.dn = rw - h.sn; + h.cas = res->x0 & 1; + + for(j = rh; j > 0; j -= 4){ + v4dwt_interleave_h(&h, aj, w, bufsize); + v4dwt_decode(&h); + if(j >= 4){ + OPJ_INT32 k = rw; + while + (--k >= 0) + { + aj[k ] = h.wavelet[k].f[0]; + aj[k+w ] = h.wavelet[k].f[1]; + aj[k+w*2] = h.wavelet[k].f[2]; + aj[k+w*3] = h.wavelet[k].f[3]; + } + }else{ + OPJ_INT32 k = rw; + while + (--k >= 0) + { + switch(j) { + case 3: aj[k+w*2] = h.wavelet[k].f[2]; + case 2: aj[k+w ] = h.wavelet[k].f[1]; + case 1: aj[k ] = h.wavelet[k].f[0]; + } + } + } + aj += w*4; + bufsize -= w*4; + } + + v.dn = rh - v.sn; + v.cas = res->y0 % 2; + + aj = (OPJ_FLOAT32*) tilec->data; + for(j = rw; j > 0; j -= 4){ + v4dwt_interleave_v(&v, aj, w); + v4dwt_decode(&v); + if(j >= 4){ + OPJ_UINT32 k; + for(k = 0; k < rh; ++k){ + memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32)); + } + }else{ + OPJ_UINT32 k; + for(k = 0; k < rh; ++k){ + memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(OPJ_FLOAT32)); + } + } + aj += 4; + } + } + + opj_aligned_free(h.wavelet); + return true; +} + diff --git a/v2/libopenjpeg/dwt.h b/v2/libopenjpeg/dwt.h new file mode 100755 index 00000000..2729c5d0 --- /dev/null +++ b/v2/libopenjpeg/dwt.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DWT_H +#define __DWT_H +/** +@file dwt.h +@brief Implementation of a discrete wavelet transform (DWT) + +The functions in DWT.C have for goal to realize forward and inverse discret wavelet +transform with filter 5-3 (reversible) and filter 9-7 (irreversible). The functions in +DWT.C are used by some function in TCD.C. +*/ +#include "openjpeg.h" + +struct opj_tcd_tilecomp; +struct opj_tccp; + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Forward 5-3 wavelet tranform in 2-D. +Apply a reversible DWT transform to a component of an image. +@param tilec Tile component information (current tile) +*/ +bool dwt_encode(struct opj_tcd_tilecomp * tilec); +/** +Inverse 5-3 wavelet tranform in 2-D. +Apply a reversible inverse DWT transform to a component of an image. +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +bool dwt_decode(struct opj_tcd_tilecomp* tilec, OPJ_UINT32 numres); +/** +Get the gain of a subband for the reversible 5-3 DWT. +@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) +@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise +*/ +OPJ_UINT32 dwt_getgain(OPJ_UINT32 orient); +/** +Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT. +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the wavelet function +*/ +OPJ_FLOAT64 dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient); +/** +Forward 9-7 wavelet transform in 2-D. +Apply an irreversible DWT transform to a component of an image. +@param tilec Tile component information (current tile) +*/ +bool dwt_encode_real(struct opj_tcd_tilecomp * tilec); +/** +Inverse 9-7 wavelet transform in 2-D. +Apply an irreversible inverse DWT transform to a component of an image. +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +bool dwt_decode_real(struct opj_tcd_tilecomp* tilec, OPJ_UINT32 numres); +/** +Get the gain of a subband for the irreversible 9-7 DWT. +@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) +@return Returns the gain of the 9-7 wavelet transform +*/ +OPJ_UINT32 dwt_getgain_real(OPJ_UINT32 orient); +/** +Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the 9-7 wavelet +*/ +OPJ_FLOAT64 dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient); +/** +Explicit calculation of the Quantization Stepsizes +@param tccp Tile-component coding parameters +@param prec Precint analyzed +*/ +void dwt_calc_explicit_stepsizes(struct opj_tccp * tccp, OPJ_UINT32 prec); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __DWT_H */ diff --git a/v2/libopenjpeg/event.c b/v2/libopenjpeg/event.c new file mode 100755 index 00000000..71d52861 --- /dev/null +++ b/v2/libopenjpeg/event.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "event.h" +#include "openjpeg.h" +#include "opj_includes.h" + + +/* ========================================================== + Utility functions + ==========================================================*/ + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +static OPJ_CHAR* +i2a(OPJ_UINT32 i, OPJ_CHAR *a, OPJ_UINT32 r) { + if (i/r > 0) a = i2a(i/r,a,r); + *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; + return a+1; +} +#endif +/* ----------------------------------------------------------------------- */ + +bool opj_event_msg(opj_event_mgr_t * p_event_mgr, OPJ_INT32 event_type, const OPJ_CHAR *fmt, ...) { +#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ + opj_msg_callback msg_handler = 00; + void * l_data = 00; + + + if(p_event_mgr != 00) { + switch(event_type) { + case EVT_ERROR: + msg_handler = p_event_mgr->error_handler; + l_data = p_event_mgr->m_error_data; + break; + case EVT_WARNING: + msg_handler = p_event_mgr->warning_handler; + l_data = p_event_mgr->m_warning_data; + break; + case EVT_INFO: + msg_handler = p_event_mgr->info_handler; + l_data = p_event_mgr->m_info_data; + break; + default: + break; + } + if(msg_handler == 00) { + return false; + } + } else { + return false; + } + + if ((fmt != 00) && (p_event_mgr != 00)) { + va_list arg; + OPJ_INT32 str_length/*, i, j*/; /* UniPG */ + OPJ_CHAR message[MSG_SIZE]; + memset(message, 0, MSG_SIZE); + /* initialize the optional parameter list */ + va_start(arg, fmt); + /* check the length of the format string */ + str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt); + /* parse the format string and put the result in 'message' */ + vsprintf(message, fmt, arg); /* UniPG */ + /* deinitialize the optional parameter list */ + va_end(arg); + + /* output the message to the user program */ + msg_handler(message, l_data); + } + + return true; +} + diff --git a/v2/libopenjpeg/event.h b/v2/libopenjpeg/event.h new file mode 100755 index 00000000..7d5bb6af --- /dev/null +++ b/v2/libopenjpeg/event.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __EVENT_H +#define __EVENT_H + +#include "openjpeg.h" + +/** +@file event.h +@brief Implementation of a event callback system + +The functions in EVENT.C have for goal to send output messages (errors, warnings, debug) to the user. +*/ +/** +Message handler object +used for +
    +
  • Error messages +
  • Warning messages +
  • Debugging messages +
+*/ +typedef struct opj_event_mgr +{ + /** Data to call the event manager upon */ + void * m_error_data; + /** Data to call the event manager upon */ + void * m_warning_data; + /** Data to call the event manager upon */ + void * m_info_data; + /** Error message callback if available, NULL otherwise */ + opj_msg_callback error_handler; + /** Warning message callback if available, NULL otherwise */ + opj_msg_callback warning_handler; + /** Debug message callback if available, NULL otherwise */ + opj_msg_callback info_handler; +} opj_event_mgr_t; + +#define EVT_ERROR 1 /**< Error event type */ +#define EVT_WARNING 2 /**< Warning event type */ +#define EVT_INFO 4 /**< Debug event type */ + +/** @defgroup EVENT EVENT - Implementation of a event callback system */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** + * Writes formatted data to a string and send the string to a user callback. + * @param p_event_mgr the event manager to display messages. + * @param event_type Event type of the message + * @param fmt Format-control string (plus optionnal arguments) + * @return Returns true if successful, returns false otherwise +*/ +bool opj_event_msg(struct opj_event_mgr * p_event_mgr, OPJ_INT32 event_type, const OPJ_CHAR *fmt, ...); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __EVENT_H */ diff --git a/v2/libopenjpeg/fix.h b/v2/libopenjpeg/fix.h new file mode 100755 index 00000000..40295c27 --- /dev/null +++ b/v2/libopenjpeg/fix.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __FIX_H +#define __FIX_H + +#include "openjpeg.h" +#include "opj_includes.h" + +/** +@file fix.h +@brief Implementation of operations of specific multiplication (FIX) + +The functions in FIX.H have for goal to realize specific multiplication. +*/ +/** @defgroup FIX FIX - Implementation of operations of specific multiplication */ +/*@{*/ + +/** +Multiply two fixed-precision rational numbers. +@param a +@param b +@return Returns a * b +*/ +static INLINE int fix_mul(int a, int b) { + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; + temp += temp & 4096; + return (int) (temp >> 13) ; +} + +/*@}*/ + +#endif /* __FIX_H */ diff --git a/v2/libopenjpeg/function_list.c b/v2/libopenjpeg/function_list.c new file mode 100755 index 00000000..54fe818f --- /dev/null +++ b/v2/libopenjpeg/function_list.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "function_list.h" +#include "opj_includes.h" +#include "opj_malloc.h" +/** + * Default size of the validation list, if not sufficient, data will be reallocated with a double size. + */ +#define OPJ_VALIDATION_SIZE 10 + +/** + * Creates a validation list. + * + * @return the newly created validation list. + */ +opj_procedure_list_t * opj_procedure_list_create() +{ + /* memory allocation */ + opj_procedure_list_t * l_validation = (opj_procedure_list_t *) opj_malloc(sizeof(opj_procedure_list_t)); + if + (! l_validation) + { + return 00; + } + /* initialization */ + memset(l_validation,0,sizeof(opj_procedure_list_t)); + l_validation->m_nb_max_procedures = OPJ_VALIDATION_SIZE; + l_validation->m_procedures = opj_malloc(OPJ_VALIDATION_SIZE * sizeof(opj_procedure)); + if + (! l_validation->m_procedures) + { + opj_free(l_validation); + return 00; + } + memset(l_validation->m_procedures,0,OPJ_VALIDATION_SIZE * sizeof(opj_procedure)); + return l_validation; +} + + + +/** + * Destroys a validation list. + * + * @param p_list the list to destroy. + */ +void opj_procedure_list_destroy(opj_procedure_list_t * p_list) +{ + if + (! p_list) + { + return; + } + /* initialization */ + if + (p_list->m_procedures) + { + opj_free(p_list->m_procedures); + } + opj_free(p_list); +} + +/** + * Adds a new validation procedure. + * + * @param p_validation_list the list of procedure to modify. + * @param p_procedure the procedure to add. + */ +bool opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure) +{ + if + (p_validation_list->m_nb_max_procedures == p_validation_list->m_nb_procedures) + { + p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE; + p_validation_list->m_procedures = opj_realloc(p_validation_list->m_procedures,p_validation_list->m_nb_max_procedures * sizeof(opj_procedure)); + if + (! p_validation_list->m_procedures) + { + p_validation_list->m_nb_max_procedures = 0; + p_validation_list->m_nb_procedures = 0; + return false; + } + } + p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = p_procedure; + ++p_validation_list->m_nb_procedures; + return true; +} + +/** + * Gets the number of validation procedures. + * + * @param p_validation_list the list of procedure to modify. + * + * @return the number of validation procedures. + */ +OPJ_UINT32 opj_procedure_list_get_nb_procedures (opj_procedure_list_t * p_validation_list) +{ + return p_validation_list->m_nb_procedures; +} + +/** + * Gets the pointer on the first validation procedure. This function is similar to the C++ + * iterator class to iterate through all the procedures inside the validation list. + * the caller does not take ownership of the pointer. + * + * @param p_validation_list the list of procedure to get the first procedure from. + * + * @return a pointer to the first procedure. + */ +opj_procedure* opj_procedure_list_get_first_procedure (opj_procedure_list_t * p_validation_list) +{ + return p_validation_list->m_procedures; +} + +/** + * Clears the list of validation procedures. + * + * @param p_validation_list the list of procedure to clear. + * + */ +void opj_procedure_list_clear (opj_procedure_list_t * p_validation_list) +{ + p_validation_list->m_nb_procedures = 0; +} diff --git a/v2/libopenjpeg/function_list.h b/v2/libopenjpeg/function_list.h new file mode 100755 index 00000000..c3f82ca1 --- /dev/null +++ b/v2/libopenjpeg/function_list.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FUNCTION_LIST_H +#define __FUNCTION_LIST_H + +/** + * @file function_list.h + * @brief Implementation of a list of procedures. + + * The functions in validation.c aims to have access to a list of procedures. +*/ + +/** @defgroup validation validation procedure*/ +/*@{*/ + +#include "openjpeg.h" +/************************************************************************************************** + ***************************************** FORWARD DECLARATION ************************************ + **************************************************************************************************/ +struct opj_jp2; + +/** + * ARGGGG, when will the template be added to the C language ??? + * in order not to have to duplicate the code in a vast number of times, use void * and downcast + * it after => UGLY but faster and easier + * TODO : make the class template in C++, use STL vector or duplicate code for each procedure type. + */ +typedef void * opj_procedure; + +/** + * A list of procedures. +*/ +typedef struct opj_procedure_list +{ + /** + * The number of validation procedures. + */ + OPJ_UINT32 m_nb_procedures; + /** + * The number of the array of validation procedures. + */ + OPJ_UINT32 m_nb_max_procedures; + /** + * The array of procedures. + */ + opj_procedure * m_procedures; + +} opj_procedure_list_t; + +/* ----------------------------------------------------------------------- */ + +/** + * Creates a validation list. + * + * @return the newly created validation list. + */ +opj_procedure_list_t * opj_procedure_list_create(); + +/** + * Destroys a validation list. + * + * @param p_list the list to destroy. + */ +void opj_procedure_list_destroy(opj_procedure_list_t * p_list); + +/** + * Adds a new validation procedure. + * + * @param p_validation_list the list of procedure to modify. + * @param p_procedure the procedure to add. + * + * @return true if the procedure could ne added. + */ +bool opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure); + +/** + * Gets the number of validation procedures. + * + * @param p_validation_list the list of procedure to modify. + * + * @return the number of validation procedures. + */ +OPJ_UINT32 opj_procedure_list_get_nb_procedures (opj_procedure_list_t * p_validation_list); + +/** + * Gets the pointer on the first validation procedure. This function is similar to the C++ + * iterator class to iterate through all the procedures inside the validation list. + * the caller does not take ownership of the pointer. + * + * @param p_validation_list the list of procedure to get the first procedure from. + * + * @return a pointer to the first procedure. + */ +opj_procedure* opj_procedure_list_get_first_procedure (opj_procedure_list_t * p_validation_list); + + +/** + * Clears the list of validation procedures. + * + * @param p_validation_list the list of procedure to clear. + * + */ +void opj_procedure_list_clear (opj_procedure_list_t * p_validation_list); + + +#endif /* __FUNCTION_LIST_H */ + diff --git a/v2/libopenjpeg/image.c b/v2/libopenjpeg/image.c new file mode 100755 index 00000000..11b5fc1b --- /dev/null +++ b/v2/libopenjpeg/image.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "image.h" +#include "openjpeg.h" +#include "opj_malloc.h" +#include "j2k.h" +#include "int.h" + +opj_image_t* opj_image_create0(void) { + opj_image_t *image = (opj_image_t*)opj_malloc(sizeof(opj_image_t)); + memset(image,0,sizeof(opj_image_t)); + return image; +} + +opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { + OPJ_UINT32 compno; + opj_image_t *image = 00; + + image = (opj_image_t*) opj_malloc(sizeof(opj_image_t)); + if + (image) + { + memset(image,0,sizeof(opj_image_t)); + image->color_space = clrspc; + image->numcomps = numcmpts; + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t)); + if + (!image->comps) + { + opj_image_destroy(image); + return 00; + } + memset(image->comps,0,image->numcomps * sizeof(opj_image_comp_t)); + /* create the individual image components */ + for(compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->sgnd = cmptparms[compno].sgnd; + comp->data = (OPJ_INT32*) opj_calloc(comp->w * comp->h, sizeof(OPJ_INT32)); + if + (!comp->data) + { + opj_image_destroy(image); + return 00; + } + } + } + return image; +} + +opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { + OPJ_UINT32 compno; + opj_image_t *image = 00; + + image = (opj_image_t*) opj_malloc(sizeof(opj_image_t)); + if + (image) + { + memset(image,0,sizeof(opj_image_t)); + image->color_space = clrspc; + image->numcomps = numcmpts; + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t)); + if + (!image->comps) + { + opj_image_destroy(image); + return 00; + } + memset(image->comps,0,image->numcomps * sizeof(opj_image_comp_t)); + /* create the individual image components */ + for(compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->sgnd = cmptparms[compno].sgnd; + comp->data = 0; + } + } + return image; +} + +void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) { + OPJ_UINT32 i; + if + (image) + { + if + (image->comps) + { + /* image components */ + for(i = 0; i < image->numcomps; i++) { + opj_image_comp_t *image_comp = &image->comps[i]; + if(image_comp->data) { + opj_free(image_comp->data); + } + } + opj_free(image->comps); + } + opj_free(image); + } +} + +/** + * Updates the components of the image from the coding parameters. + * + * @param p_image the image to update. + * @param p_cp the coding parameters from which to update the image. + */ +void opj_image_comp_update(opj_image_t * p_image,const opj_cp_t * p_cp) +{ + OPJ_UINT32 i, l_width, l_height; + OPJ_INT32 l_x0,l_y0,l_x1,l_y1; + OPJ_INT32 l_comp_x0,l_comp_y0,l_comp_x1,l_comp_y1; + opj_image_comp_t * l_img_comp = 00; + + l_x0 = int_max(p_cp->tx0 , p_image->x0); + l_y0 = int_max(p_cp->ty0 , p_image->y0); + l_x1 = int_min(p_cp->tx0 + p_cp->tw * p_cp->tdx, p_image->x1); + l_y1 = int_min(p_cp->ty0 + p_cp->th * p_cp->tdy, p_image->y1); + + l_img_comp = p_image->comps; + for + (i = 0; i < p_image->numcomps; ++i) + { + l_comp_x0 = int_ceildiv(l_x0, l_img_comp->dx); + l_comp_y0 = int_ceildiv(l_y0, l_img_comp->dy); + l_comp_x1 = int_ceildiv(l_x1, l_img_comp->dx); + l_comp_y1 = int_ceildiv(l_y1, l_img_comp->dy); + l_width = int_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor); + l_height = int_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor); + l_img_comp->w = l_width; + l_img_comp->h = l_height; + l_img_comp->x0 = l_x0; + l_img_comp->y0 = l_y0; + ++l_img_comp; + } +} + diff --git a/v2/libopenjpeg/image.h b/v2/libopenjpeg/image.h new file mode 100755 index 00000000..bcdca0e4 --- /dev/null +++ b/v2/libopenjpeg/image.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __IMAGE_H +#define __IMAGE_H +/** +@file image.h +@brief Implementation of operations on images (IMAGE) + +The functions in IMAGE.C have for goal to realize operations on images. +*/ +struct opj_image; +struct opj_cp; +/** @defgroup IMAGE IMAGE - Implementation of operations on images */ +/*@{*/ + +/** +Create an empty image +@todo this function should be removed +@return returns an empty image if successful, returns NULL otherwise +*/ +struct opj_image* opj_image_create0(void); + +/** + * Updates the components of the image from the coding parameters. + * + * @param p_image the image to update. + * @param p_cp the coding parameters from which to update the image. + */ +void opj_image_comp_update(struct opj_image * p_image,const struct opj_cp * p_cp); + +/*@}*/ + +#endif /* __IMAGE_H */ + diff --git a/v2/libopenjpeg/int.h b/v2/libopenjpeg/int.h new file mode 100755 index 00000000..5012cf67 --- /dev/null +++ b/v2/libopenjpeg/int.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __INT_H +#define __INT_H +/** +@file int.h +@brief Implementation of operations on integers (INT) + +The functions in INT.H have for goal to realize operations on integers. +*/ +#include "openjpeg.h" +#include "opj_includes.h" +/** @defgroup INT INT - Implementation of operations on integers */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Get the minimum of two integers +@return Returns a if a < b else b +*/ +static INLINE OPJ_INT32 int_min(OPJ_INT32 a, OPJ_INT32 b) { + return a < b ? a : b; +} + +/** +Get the minimum of two integers +@return Returns a if a < b else b +*/ +static INLINE OPJ_UINT32 uint_min(OPJ_UINT32 a, OPJ_UINT32 b) { + return a < b ? a : b; +} + +/** +Get the maximum of two integers +@return Returns a if a > b else b +*/ +static INLINE OPJ_INT32 int_max(OPJ_INT32 a, OPJ_INT32 b) { + return (a > b) ? a : b; +} + +/** +Get the maximum of two integers +@return Returns a if a > b else b +*/ +static INLINE OPJ_UINT32 uint_max(OPJ_UINT32 a, OPJ_UINT32 b) { + return (a > b) ? a : b; +} +/** +Clamp an integer inside an interval +@return +
    +
  • Returns a if (min < a < max) +
  • Returns max if (a > max) +
  • Returns min if (a < min) +
+*/ +static INLINE OPJ_INT32 int_clamp(OPJ_INT32 a, OPJ_INT32 min, OPJ_INT32 max) { + if (a < min) + return min; + if (a > max) + return max; + return a; +} +/** +@return Get absolute value of integer +*/ +static INLINE OPJ_INT32 int_abs(OPJ_INT32 a) { + return a < 0 ? -a : a; +} +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_INT32 int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) { + return (a + b - 1) / b; +} + +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_UINT32 uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) { + return (a + b - 1) / b; +} +/** +Divide an integer by a power of 2 and round upwards +@return Returns a divided by 2^b +*/ +static INLINE OPJ_INT32 int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) { + return (a + (1 << b) - 1) >> b; +} +/** +Divide an integer by a power of 2 and round downwards +@return Returns a divided by 2^b +*/ +static INLINE OPJ_INT32 int_floordivpow2(OPJ_INT32 a, OPJ_INT32 b) { + return a >> b; +} +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static INLINE OPJ_INT32 int_floorlog2(OPJ_INT32 a) { + OPJ_INT32 l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; +} + +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static INLINE OPJ_UINT32 uint_floorlog2(OPJ_UINT32 a) { + OPJ_UINT32 l; + for (l = 0; a > 1; ++l) + { + a >>= 1; + } + return l; +} +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif diff --git a/v2/libopenjpeg/invert.c b/v2/libopenjpeg/invert.c new file mode 100755 index 00000000..2c38f538 --- /dev/null +++ b/v2/libopenjpeg/invert.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "invert.h" +#include "opj_malloc.h" + + +bool opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, OPJ_FLOAT32 * p_swap_area,OPJ_UINT32 n); +void opj_lupSolve(OPJ_FLOAT32 * pResult, OPJ_FLOAT32* pMatrix, OPJ_FLOAT32* pVector, OPJ_UINT32* pPermutations, OPJ_UINT32 n,OPJ_FLOAT32 * p_intermediate_data); +void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 n, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area); + +/** + * Matrix inversion. + */ +bool opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix,OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 n) +{ + OPJ_BYTE * l_data = 00; + OPJ_UINT32 l_permutation_size = n * sizeof(OPJ_UINT32); + OPJ_UINT32 l_swap_size = n * sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_total_size = l_permutation_size + 3 * l_swap_size; + OPJ_UINT32 * lPermutations = 00; + OPJ_FLOAT32 * l_double_data = 00; + + l_data = (OPJ_BYTE *) opj_malloc(l_total_size); + if + (l_data == 0) + { + return false; + } + lPermutations = (OPJ_UINT32 *) l_data; + l_double_data = (OPJ_FLOAT32 *) (l_data + l_permutation_size); + memset(lPermutations,0,l_permutation_size); + + if + (! opj_lupDecompose(pSrcMatrix,lPermutations,l_double_data,n)) + { + opj_free(l_data); + return false; + } + opj_lupInvert(pSrcMatrix,pDestMatrix,n,lPermutations,l_double_data,l_double_data + n,l_double_data + 2*n); + opj_free(l_data); + return true; +} + + +/** + * LUP decomposition + */ +bool opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, OPJ_FLOAT32 * p_swap_area,OPJ_UINT32 n) +{ + OPJ_UINT32 * tmpPermutations = permutations; + OPJ_UINT32 * dstPermutations; + OPJ_UINT32 k2=0,t; + OPJ_FLOAT32 temp; + OPJ_UINT32 i,j,k; + OPJ_FLOAT32 p; + OPJ_UINT32 lLastColum = n - 1; + OPJ_UINT32 lSwapSize = n * sizeof(OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpMatrix = matrix; + OPJ_FLOAT32 * lColumnMatrix,* lDestMatrix; + OPJ_UINT32 offset = 1; + OPJ_UINT32 lStride = n-1; + + //initialize permutations + for + (i = 0; i < n; ++i) + { + *tmpPermutations++ = i; + } + + + + // now make a pivot with colum switch + tmpPermutations = permutations; + for + (k = 0; k < lLastColum; ++k) + { + p = 0.0; + + // take the middle element + lColumnMatrix = lTmpMatrix + k; + + // make permutation with the biggest value in the column + for + (i = k; i < n; ++i) + { + temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix)); + if + (temp > p) + { + p = temp; + k2 = i; + } + // next line + lColumnMatrix += n; + } + + // a whole rest of 0 -> non singular + if + (p == 0.0) + { + return false; + } + + // should we permute ? + if + (k2 != k) + { + //exchange of line + // k2 > k + dstPermutations = tmpPermutations + k2 - k; + // swap indices + t = *tmpPermutations; + *tmpPermutations = *dstPermutations; + *dstPermutations = t; + + // and swap entire line. + lColumnMatrix = lTmpMatrix + (k2 - k) * n; + memcpy(p_swap_area,lColumnMatrix,lSwapSize); + memcpy(lColumnMatrix,lTmpMatrix,lSwapSize); + memcpy(lTmpMatrix,p_swap_area,lSwapSize); + } + + // now update data in the rest of the line and line after + lDestMatrix = lTmpMatrix + k; + lColumnMatrix = lDestMatrix + n; + // take the middle element + temp = *(lDestMatrix++); + + // now compute up data (i.e. coeff up of the diagonal). + for (i = offset; i < n; ++i) + { + //lColumnMatrix; + // divide the lower column elements by the diagonal value + + // matrix[i][k] /= matrix[k][k]; + // p = matrix[i][k] + p = *lColumnMatrix / temp; + *(lColumnMatrix++) = p; + for + (j = /* k + 1 */ offset; j < n; ++j) + { + // matrix[i][j] -= matrix[i][k] * matrix[k][j]; + *(lColumnMatrix++) -= p * (*(lDestMatrix++)); + } + // come back to the k+1th element + lDestMatrix -= lStride; + // go to kth element of the next line + lColumnMatrix += k; + } + // offset is now k+2 + ++offset; + // 1 element less for stride + --lStride; + // next line + lTmpMatrix+=n; + // next permutation element + ++tmpPermutations; + } + return true; +} + + + +/** + * LUP solving + */ +void opj_lupSolve (OPJ_FLOAT32 * pResult, OPJ_FLOAT32 * pMatrix, OPJ_FLOAT32 * pVector, OPJ_UINT32* pPermutations, OPJ_UINT32 n,OPJ_FLOAT32 * p_intermediate_data) +{ + OPJ_UINT32 i,j; + OPJ_FLOAT32 sum; + OPJ_FLOAT32 u; + OPJ_UINT32 lStride = n+1; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lIntermediatePtr; + OPJ_FLOAT32 * lDestPtr; + OPJ_FLOAT32 * lTmpMatrix; + OPJ_FLOAT32 * lLineMatrix = pMatrix; + OPJ_FLOAT32 * lBeginPtr = pResult + n - 1; + OPJ_FLOAT32 * lGeneratedData; + OPJ_UINT32 * lCurrentPermutationPtr = pPermutations; + + + lIntermediatePtr = p_intermediate_data; + lGeneratedData = p_intermediate_data + n - 1; + + for + (i = 0; i < n; ++i) + { + sum = 0.0; + lCurrentPtr = p_intermediate_data; + lTmpMatrix = lLineMatrix; + for + (j = 1; j <= i; ++j) + { + // sum += matrix[i][j-1] * y[j-1]; + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + } + //y[i] = pVector[pPermutations[i]] - sum; + *(lIntermediatePtr++) = pVector[*(lCurrentPermutationPtr++)] - sum; + lLineMatrix += n; + } + + // we take the last point of the matrix + lLineMatrix = pMatrix + n*n - 1; + + // and we take after the last point of the destination vector + lDestPtr = pResult + n; + + for + (i = n - 1; i != -1 ; --i) + { + sum = 0.0; + lTmpMatrix = lLineMatrix; + u = *(lTmpMatrix++); + lCurrentPtr = lDestPtr--; + for + (j = i + 1; j < n; ++j) + { + // sum += matrix[i][j] * x[j] + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + } + //x[i] = (y[i] - sum) / u; + *(lBeginPtr--) = (*(lGeneratedData--) - sum) / u; + lLineMatrix -= lStride; + } +} + +/** LUP inversion (call with the result of lupDecompose) + */ +void opj_lupInvert ( + OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 n, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area + ) +{ + OPJ_UINT32 j,i; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lLineMatrix = pDestMatrix; + OPJ_UINT32 lSwapSize = n * sizeof(OPJ_FLOAT32); + + for + (j = 0; j < n; ++j) + { + lCurrentPtr = lLineMatrix++; + memset(p_src_temp,0,lSwapSize); + p_src_temp[j] = 1.0; + opj_lupSolve(p_dest_temp,pSrcMatrix,p_src_temp, pPermutations, n , p_swap_area); + + for + (i = 0; i < n; ++i) + { + *(lCurrentPtr) = p_dest_temp[i]; + lCurrentPtr+=n; + } + } +} + diff --git a/v2/libopenjpeg/invert.h b/v2/libopenjpeg/invert.h new file mode 100755 index 00000000..cbb717fd --- /dev/null +++ b/v2/libopenjpeg/invert.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __INVERT_H +#define __INVERT_H +#include "openjpeg.h" +/** + * Calculates a n x n double matrix inversion with a LUP method. Data is aligned, rows after rows (or columns after columns). + * The function does not take ownership of any memory block, data must be fred by the user. + * + * @param pSrcMatrix the matrix to invert. + * @param pDestMatrix data to store the inverted matrix. + * @return 1 if the inversion is successful, 0 if the matrix is singular. + */ +bool opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix,OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 n); +#endif + diff --git a/v2/libopenjpeg/j2k.c b/v2/libopenjpeg/j2k.c new file mode 100755 index 00000000..5b293fd0 --- /dev/null +++ b/v2/libopenjpeg/j2k.c @@ -0,0 +1,9307 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "j2k.h" +#include "opj_malloc.h" +#include "opj_includes.h" +#include "pi.h" +#include "event.h" +#include "cio.h" +#include "int.h" +#include "tcd.h" +#include "function_list.h" +#include "invert.h" +#include "dwt.h" +#include "mct.h" +#include "image.h" + +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + + +/*************************************************************************** + ********************** TYPEDEFS ******************************************* + ***************************************************************************/ +/** + * Correspondance prog order <-> string representation + */ +typedef struct j2k_prog_order +{ + OPJ_PROG_ORDER enum_prog; + OPJ_CHAR str_prog[4]; +} +j2k_prog_order_t; + +typedef struct opj_dec_memory_marker_handler +{ + /** marker value */ + OPJ_UINT32 id; + /** value of the state when the marker can appear */ + OPJ_UINT32 states; + /** action linked to the marker */ + bool (*handler) ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +} +opj_dec_memory_marker_handler_t; + + + +/** @name Local static functions */ +/*@{*/ +/** + * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * + * @param p_comp_no the component number to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +static bool j2k_write_SPCod_SPCoc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * @param p_header_data the data contained in the COM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_SPCod_SPCoc( + opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Gets the size taken by writting a SPCod or SPCoc for the given tile and component. + * + * @param p_tile_no the tile indix. + * @param p_comp_no the component being outputted. + * @param p_j2k the J2K codec. + * + * @return the number of bytes taken by the SPCod element. + */ +static OPJ_UINT32 j2k_get_SPCod_SPCoc_size ( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no + ); + +/** + * Writes a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile to output. + * @param p_comp_no the component number to output. + * @param p_data the data buffer. + * @param p_header_size pointer to the size of the data buffer, it is changed by the function. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +static bool j2k_write_SQcd_SQcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile to output. + * @param p_comp_no the component number to output. + * @param p_data the data buffer. + * @param p_header_size pointer to the size of the data buffer, it is changed by the function. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +static bool j2k_read_SQcd_SQcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Updates the Tile Length Marker. + */ +static void j2k_update_tlm ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_part_size); + +/** + * Gets the size taken by writting SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile indix. + * @param p_comp_no the component being outputted. + * @param p_j2k the J2K codec. + * + * @return the number of bytes taken by the SPCod element. + */ +static OPJ_UINT32 j2k_get_SQcd_SQcc_size ( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no + + ); + +/** + * Copies the tile component parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +static void j2k_copy_tile_component_parameters( + opj_j2k_t *p_j2k + ); + +/** + * Writes the SOC marker (Start Of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ + +static bool j2k_write_soc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a SOC marker (Start of Codestream) + * @param p_header_data the data contained in the SOC box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the SOC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_soc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes the SIZ marker (image and tile size) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_siz( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes the CBD-MCT-MCC-MCO markers (Multi components transform) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_mct_data_group( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a SIZ marker (image and tile size) + * @param p_header_data the data contained in the SIZ box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the SIZ marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_siz ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Writes the COM marker (comment) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_com( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a COM marker (comments) + * @param p_header_data the data contained in the COM box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_com ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); + + + +/** + * Writes the COD marker (Coding style default) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_cod( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a COD marker (Coding Styke defaults) + * @param p_header_data the data contained in the COD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COD marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_cod ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the COC marker (Coding style component) + * + * @param p_comp_number the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_coc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_number, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the COC marker (Coding style component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static void j2k_write_coc_in_memory( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ); +/** + * Gets the maximum size taken by a coc. + * + * @param p_j2k the jpeg2000 codec to use. + */ +static OPJ_UINT32 j2k_get_max_coc_size(opj_j2k_t *p_j2k); + +/** + * Reads a COC marker (Coding Style Component) + * @param p_header_data the data contained in the COC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_coc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the QCD marker (quantization default) + * + * @param p_comp_number the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_qcd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + + +/** + * Reads a QCD marker (Quantization defaults) + * @param p_header_data the data contained in the QCD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCD marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_qcd ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Writes the QCC marker (quantization component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_qcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes the QCC marker (quantization component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static void j2k_write_qcc_in_memory( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ); +/** + * Gets the maximum size taken by a qcc. + */ +static OPJ_UINT32 j2k_get_max_qcc_size (opj_j2k_t *p_j2k); + +/** + * Reads a QCC marker (Quantization component) + * @param p_header_data the data contained in the QCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_qcc( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager); +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_poc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the updated tlm. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_updated_tlm( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + */ +static void j2k_write_poc_in_memory( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ); + +/** + * Gets the maximum size taken by the writting of a POC. + */ +static OPJ_UINT32 j2k_get_max_poc_size(opj_j2k_t *p_j2k); + +/** + * Gets the maximum size taken by the toc headers of all the tile parts of any given tile. + */ +static OPJ_UINT32 j2k_get_max_toc_size (opj_j2k_t *p_j2k); + +/** + * Gets the maximum size taken by the headers of the SOT. + * + * @param p_j2k the jpeg2000 codec to use. + */ +static OPJ_UINT32 j2k_get_specific_header_sizes(opj_j2k_t *p_j2k); + +/** + * Reads a POC marker (Progression Order Change) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_poc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a CRG marker (Component registration) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_crg ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a TLM marker (Tile Length Marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_tlm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a PLM marker (Packet length, main header marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_plm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a PLT marker (Packet length, tile-part header) + * + * @param p_header_data the data contained in the PLT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PLT marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_plt ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a PPM marker (Packed packet headers, main header) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_ppm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_ppt ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Writes the TLM marker (Tile Length Marker) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_tlm( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes the SOT marker (Start of tile-part) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_sot( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + const struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_sot ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Writes the SOD marker (Start of data) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_sod( + opj_j2k_t *p_j2k, + struct opj_tcd * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + const struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a SOD marker (Start Of Data) + * + * @param p_header_data the data contained in the SOD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the SOD marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_sod ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes the RGN marker (Region Of Interest) + * + * @param p_tile_no the tile to output + * @param p_comp_no the component to output + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_rgn( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a RGN marker (Region Of Interest) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_rgn ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) ; +/** + * Writes the EOC marker (End of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_eoc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Copies the tile component parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +static void j2k_copy_tile_quantization_parameters( + opj_j2k_t *p_j2k + ); + +/** + * Reads a EOC marker (End Of Codestream) + * + * @param p_header_data the data contained in the SOD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the SOD marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_eoc ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) ; + +/** + * Inits the Info + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_init_info( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads an unknown marker + * + * @param p_stream the stream object to read from. + * @param p_j2k the jpeg2000 codec. + * @param p_manager the user event manager. + * + * @return true if the marker could be deduced. +*/ +static bool j2k_read_unk ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Ends the encoding, i.e. frees memory. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_end_encoding( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the CBD marker (Component bit depth definition) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_cbd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a CBD marker (Component bit depth definition) + * @param p_header_data the data contained in the CBD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CBD marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_cbd ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager); + +/** + * Writes the MCT marker (Multiple Component Transform) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_mct_record( + opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a MCT marker (Multiple Component Transform) + * + * @param p_header_data the data contained in the MCT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCT marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_mct ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the MCC marker (Multiple Component Collection) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_mcc_record( + opj_j2k_t *p_j2k, + struct opj_simple_mcc_decorrelation_data * p_mcc_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a MCC marker (Multiple Component Collection) + * + * @param p_header_data the data contained in the MCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCC marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_mcc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the MCO marker (Multiple component transformation ordering) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_mco( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a MCO marker (Multiple Component Transform Ordering) + * + * @param p_header_data the data contained in the MCO box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCO marker. + * @param p_manager the user event manager. +*/ +static bool j2k_read_mco ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ); +/** + * Writes the image components. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_image_components( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Writes regions of interests. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_regions( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Writes EPC ???? + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_write_epc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Checks the progression order changes values. Tells of the poc given as input are valid. + * A nice message is outputted at errors. + * + * @param p_pocs the progression order changes. + * @param p_nb_pocs the number of progression order changes. + * @param p_nb_resolutions the number of resolutions. + * @param numcomps the number of components + * @param numlayers the number of layers. + * + * @return true if the pocs are valid. + */ +static bool j2k_check_poc_val( + const opj_poc_t *p_pocs, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 numcomps, + OPJ_UINT32 numlayers, + opj_event_mgr_t * p_manager); + +/** + * Gets the number of tile parts used for the given change of progression (if any) and the given tile. + * + * @param cp the coding parameters. + * @param pino the offset of the given poc (i.e. its position in the coding parameter). + * @param tileno the given tile. + * + * @return the number of tile parts. + */ +static OPJ_UINT32 j2k_get_num_tp( + opj_cp_t *cp, + OPJ_UINT32 pino, + OPJ_UINT32 tileno); +/** + * Calculates the total number of tile parts needed by the encoder to + * encode such an image. If not enough memory is available, then the function return false. + * + * @param p_nb_tiles pointer that will hold the number of tile parts. + * @param cp the coding parameters for the image. + * @param image the image to encode. + * @param p_j2k the p_j2k encoder. + * @param p_manager the user event manager. + * + * @return true if the function was successful, false else. + */ +static bool j2k_calculate_tp( + opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager); + +static bool j2k_write_first_tile_part ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ); +static bool j2k_write_all_tile_parts( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Reads the lookup table containing all the marker, status and action, and returns the handler associated + * with the marker value. + * @param p_id Marker value to look up + * + * @return the handler associated with the id. +*/ +static const struct opj_dec_memory_marker_handler * j2k_get_marker_handler (OPJ_UINT32 p_id); + +/** + * Destroys a tile coding parameter structure. + * + * @param p_tcp the tile coding parameter to destroy. + */ +static void j2k_tcp_destroy (opj_tcp_t *p_tcp); + +static void j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data); + +/** + * Destroys a coding parameter structure. + * + * @param p_cp the coding parameter to destroy. + */ +static void j2k_cp_destroy (opj_cp_t *p_cp); + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +static void j2k_setup_encoding_validation (opj_j2k_t *p_j2k); + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +static void j2k_setup_decoding_validation (opj_j2k_t *p_j2k); + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +static void j2k_setup_end_compress (opj_j2k_t *p_j2k); + +/** + * Creates a tile-coder decoder. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_create_tcd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Excutes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param p_j2k the jpeg2000 codec to execute the procedures on. + * @param p_stream the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +static bool j2k_exec ( + opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Updates the rates of the tcp. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_update_rates( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * The default encoding validation procedure without any extension. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool j2k_encoding_validation ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * The read header procedure. + */ +bool j2k_read_header_procedure( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager); + +/** + * The default decoding validation procedure without any extension. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool j2k_decoding_validation ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Reads the tiles. + */ +bool j2k_decode_tiles ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager); + +/** + * The mct encoding validation procedure. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool j2k_mct_validation ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Builds the tcd decoder to use to decode tile. + */ +bool j2k_build_decoder ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Builds the tcd encoder to use to encode tile. + */ +bool j2k_build_encoder ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Copies the decoding tile parameters onto all the tile parameters. + * Creates also the tile decoder. + */ +bool j2k_copy_default_tcp_and_create_tcd( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +/** + * Destroys the memory associated with the decoding of headers. + */ +bool j2k_destroy_header_memory ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); + +/** + * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. + */ +void j2k_setup_header_writting (opj_j2k_t *p_j2k); + +/** + * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. + */ +void j2k_setup_header_reading (opj_j2k_t *p_j2k); + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +static bool j2k_post_write_tile ( + opj_j2k_t * p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); + +static bool j2k_pre_write_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ); +static bool j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data); + +static bool j2k_add_mct(opj_tcp_t * p_tcp,opj_image_t * p_image, OPJ_UINT32 p_index); +/** + * Gets the offset of the header. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static bool j2k_get_end_header( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +static void j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); + + + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + + + +/**************************************************************************** + ********************* CONSTANTS ******************************************** + ****************************************************************************/ + + + + +/** + * List of progression orders. + */ +const j2k_prog_order_t j2k_prog_order_list [] = +{ + {CPRL, "CPRL"}, + {LRCP, "LRCP"}, + {PCRL, "PCRL"}, + {RLCP, "RLCP"}, + {RPCL, "RPCL"}, + {-1, ""} +}; + +const OPJ_UINT32 MCT_ELEMENT_SIZE [] = +{ + 2, + 4, + 4, + 8 +}; + +typedef void (* j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); + +const j2k_mct_function j2k_mct_read_functions_to_float [] = +{ + j2k_read_int16_to_float, + j2k_read_int32_to_float, + j2k_read_float32_to_float, + j2k_read_float64_to_float +}; + +const j2k_mct_function j2k_mct_read_functions_to_int32 [] = +{ + j2k_read_int16_to_int32, + j2k_read_int32_to_int32, + j2k_read_float32_to_int32, + j2k_read_float64_to_int32 +}; + +const j2k_mct_function j2k_mct_write_functions_from_float [] = +{ + j2k_write_float_to_int16, + j2k_write_float_to_int32, + j2k_write_float_to_float, + j2k_write_float_to_float64 +}; + + + + +/*const opj_dec_stream_marker_handler_t j2k_stream_marker_handler_tab[] = +{ + {J2K_MS_SOC, J2K_DEC_STATE_MHSOC, j2k_read_soc}, + {J2K_MS_SOD, J2K_DEC_STATE_TPH, j2k_read_sod}, + {J2K_MS_EOC, J2K_DEC_STATE_TPHSOT, j2k_read_eoc}, + {J2K_MS_SOP, 0, 0}, +#ifdef USE_JPWL + {J2K_MS_EPC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epc}, + {J2K_MS_EPB, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epb}, + {J2K_MS_ESD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_esd}, + {J2K_MS_RED, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_red}, +#endif +#ifdef USE_JPSEC + {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, + {J2K_MS_INSEC, 0, j2k_read_insec}, +#endif + + {0, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_unk} +};*/ + +const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] = +{ + {J2K_MS_SOT, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPHSOT, j2k_read_sot}, + {J2K_MS_COD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_cod}, + {J2K_MS_COC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_coc}, + {J2K_MS_RGN, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_rgn}, + {J2K_MS_QCD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_qcd}, + {J2K_MS_QCC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_qcc}, + {J2K_MS_POC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_poc}, + {J2K_MS_SIZ, J2K_DEC_STATE_MHSIZ , j2k_read_siz}, + {J2K_MS_TLM, J2K_DEC_STATE_MH, j2k_read_tlm}, + {J2K_MS_PLM, J2K_DEC_STATE_MH, j2k_read_plm}, + {J2K_MS_PLT, J2K_DEC_STATE_TPH, j2k_read_plt}, + {J2K_MS_PPM, J2K_DEC_STATE_MH, j2k_read_ppm}, + {J2K_MS_PPT, J2K_DEC_STATE_TPH, j2k_read_ppt}, + {J2K_MS_SOP, 0, 0}, + {J2K_MS_CRG, J2K_DEC_STATE_MH, j2k_read_crg}, + {J2K_MS_COM, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_com}, + {J2K_MS_MCT, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mct}, + {J2K_MS_CBD, J2K_DEC_STATE_MH , j2k_read_cbd}, + {J2K_MS_MCC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mcc}, + {J2K_MS_MCO, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mco} +#ifdef USE_JPWL + {J2K_MS_EPC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epc}, + {J2K_MS_EPB, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epb}, + {J2K_MS_ESD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_esd}, + {J2K_MS_RED, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_red}, +#endif /* USE_JPWL */ +#ifdef USE_JPSEC + {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, + {J2K_MS_INSEC, 0, j2k_read_insec} +#endif /* USE_JPSEC */ +}; + +void j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for + (i=0;ienum_prog != -1; ++po ) + { + if + (po->enum_prog == p_prg_order) + { + return po->str_prog; + } + } + return po->str_prog; +} + + + + + + + +/** + * Checks the progression order changes values. Tells if the poc given as input are valid. + * + * @param p_pocs the progression order changes. + * @param p_nb_pocs the number of progression order changes. + * @param p_nb_resolutions the number of resolutions. + * @param numcomps the number of components + * @param numlayers the number of layers. + * @param p_manager the user event manager. + * + * @return true if the pocs are valid. + */ +bool j2k_check_poc_val(const opj_poc_t *p_pocs, OPJ_UINT32 p_nb_pocs, OPJ_UINT32 p_nb_resolutions, OPJ_UINT32 p_num_comps, OPJ_UINT32 p_num_layers, opj_event_mgr_t * p_manager) +{ + OPJ_UINT32* packet_array; + OPJ_UINT32 index , resno, compno, layno; + OPJ_UINT32 i; + OPJ_UINT32 step_c = 1; + OPJ_UINT32 step_r = p_num_comps * step_c; + OPJ_UINT32 step_l = p_nb_resolutions * step_r; + bool loss = false; + OPJ_UINT32 layno0 = 0; + + packet_array = (OPJ_UINT32*) opj_calloc(step_l * p_num_layers, sizeof(OPJ_UINT32)); + if + (packet_array == 00) + { + opj_event_msg(p_manager , EVT_ERROR, "Not enough memory for checking the poc values.\n"); + return false; + } + memset(packet_array,0,step_l * p_num_layers* sizeof(OPJ_UINT32)); + if + (p_nb_pocs == 0) + { + return true; + } + + index = step_r * p_pocs->resno0; + // take each resolution for each poc + for + (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) + { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + // take each comp of each resolution for each poc + for + (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) + { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; + // and finally take each layer of each res of ... + for + (layno = layno0; layno < p_pocs->layno1 ; ++layno) + { + //index = step_r * resno + step_c * compno + step_l * layno; + packet_array[comp_index] = 1; + comp_index += step_l; + } + res_index += step_c; + } + index += step_r; + } + ++p_pocs; + // iterate through all the pocs + for + (i = 1; i < p_nb_pocs ; ++i) + { + OPJ_UINT32 l_last_layno1 = (p_pocs-1)->layno1 ; + layno0 = (p_pocs->layno1 > l_last_layno1)? l_last_layno1 : 0; + index = step_r * p_pocs->resno0; + // take each resolution for each poc + for + (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) + { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + // take each comp of each resolution for each poc + for + (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) + { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; + // and finally take each layer of each res of ... + for + (layno = layno0; layno < p_pocs->layno1 ; ++layno) + { + //index = step_r * resno + step_c * compno + step_l * layno; + packet_array[comp_index] = 1; + comp_index += step_l; + } + res_index += step_c; + } + index += step_r; + } + ++p_pocs; + } + + index = 0; + for + (layno = 0; layno < p_num_layers ; ++layno) + { + for + (resno = 0; resno < p_nb_resolutions; ++resno) + { + for + (compno = 0; compno < p_num_comps; ++compno) + { + loss |= (packet_array[index]!=1); + //index = step_r * resno + step_c * compno + step_l * layno; + index += step_c; + } + } + } + if + (loss) + { + opj_event_msg(p_manager , EVT_ERROR, "Missing packets possible loss of data\n"); + } + opj_free(packet_array); + return !loss; +} + + +/* ----------------------------------------------------------------------- */ + +/** + * Gets the number of tile parts used for the given change of progression (if any) and the given tile. + * + * @param cp the coding parameters. + * @param pino the offset of the given poc (i.e. its position in the coding parameter). + * @param tileno the given tile. + * + * @return the number of tile parts. + */ +OPJ_UINT32 j2k_get_num_tp(opj_cp_t *cp,OPJ_UINT32 pino,OPJ_UINT32 tileno) +{ + const OPJ_CHAR *prog = 00; + OPJ_UINT32 i; + OPJ_UINT32 tpnum = 1; + opj_tcp_t *tcp = 00; + opj_poc_t * l_current_poc = 00; + + // preconditions only in debug + assert(tileno < (cp->tw * cp->th)); + assert(pino < (cp->tcps[tileno].numpocs + 1)); + + // get the given tile coding parameter + tcp = &cp->tcps[tileno]; + assert(tcp != 00); + l_current_poc = &(tcp->pocs[pino]); + assert(l_current_poc != 0); + + // get the progression order as a character string + prog = j2k_convert_progression_order(tcp->prg); + assert(strlen(prog) > 0); + + if + (cp->m_specific_param.m_enc.m_tp_on == 1) + { + for + (i=0;i<4;++i) + { + switch + (prog[i]) + { + // component wise + case 'C': + tpnum *= l_current_poc->compE; + break; + // resolution wise + case 'R': + tpnum *= l_current_poc->resE; + break; + // precinct wise + case 'P': + tpnum *= l_current_poc->prcE; + break; + // layer wise + case 'L': + tpnum *= l_current_poc->layE; + break; + } + // whould we split here ? + if + ( cp->m_specific_param.m_enc.m_tp_flag == prog[i] ) + { + cp->m_specific_param.m_enc.m_tp_pos=i; + break; + } + } + } + else + { + tpnum=1; + } + return tpnum; +} + +/** + * Calculates the total number of tile parts needed by the encoder to + * encode such an image. If not enough memory is available, then the function return false. + * + * @param p_nb_tiles pointer that will hold the number of tile parts. + * @param cp the coding parameters for the image. + * @param image the image to encode. + * @param p_j2k the p_j2k encoder. + * @param p_manager the user event manager. + * + * @return true if the function was successful, false else. + */ +bool j2k_calculate_tp( + opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 pino,tileno; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t *tcp; + + // preconditions + assert(p_nb_tiles != 00); + assert(cp != 00); + assert(image != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_nb_tiles = cp->tw * cp->th; + * p_nb_tiles = 0; + tcp = cp->tcps; + + /* INDEX >> */ + if + (p_j2k->cstr_info) + { + opj_tile_info_t * l_info_tile_ptr = p_j2k->cstr_info->tile; + for + (tileno = 0; tileno < l_nb_tiles; ++tileno) + { + OPJ_UINT32 cur_totnum_tp = 0; + pi_update_encoding_parameters(image,cp,tileno); + for + (pino = 0; pino <= tcp->numpocs; ++pino) + { + OPJ_UINT32 tp_num = j2k_get_num_tp(cp,pino,tileno); + *p_nb_tiles = *p_nb_tiles + tp_num; + cur_totnum_tp += tp_num; + } + tcp->m_nb_tile_parts = cur_totnum_tp; + l_info_tile_ptr->tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t)); + if + (l_info_tile_ptr->tp == 00) + { + return false; + } + memset(l_info_tile_ptr->tp,0,cur_totnum_tp * sizeof(opj_tp_info_t)); + l_info_tile_ptr->num_tps = cur_totnum_tp; + ++l_info_tile_ptr; + ++tcp; + } + } + else + { + for + (tileno = 0; tileno < l_nb_tiles; ++tileno) + { + OPJ_UINT32 cur_totnum_tp = 0; + pi_update_encoding_parameters(image,cp,tileno); + for + (pino = 0; pino <= tcp->numpocs; ++pino) + { + OPJ_UINT32 tp_num=0; + tp_num = j2k_get_num_tp(cp,pino,tileno); + *p_nb_tiles = *p_nb_tiles + tp_num; + cur_totnum_tp += tp_num; + } + tcp->m_nb_tile_parts = cur_totnum_tp; + ++tcp; + } + } + return true; +} + +/** + * Writes the SOC marker (Start Of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ + +bool j2k_write_soc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + /* 2 bytes will be written */ + OPJ_BYTE * l_start_stream = 00; + + // preconditions + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_start_stream = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* write SOC identifier */ + opj_write_bytes(l_start_stream,J2K_MS_SOC,2); + if + (opj_stream_write_data(p_stream,l_start_stream,2,p_manager) != 2) + { + return false; + } +/* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2); +#endif /* USE_JPWL */ + return true; +/* <m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MHSIZ; + /* Index */ + if + (p_j2k->cstr_info) + { + //TODO p_j2k->cstr_info->main_head_start = opj_stream_tell(p_stream) - 2; // why - 2 ? + p_j2k->cstr_info->codestream_size = 0;/*p_stream_numbytesleft(p_j2k->p_stream) + 2 - p_j2k->cstr_info->main_head_start*/; + } + return true; +} + +/** + * Writes the SIZ marker (image and tile size) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_siz( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_size_len; + OPJ_BYTE * l_current_ptr; + opj_image_t * l_image = 00; + opj_cp_t *cp = 00; + opj_image_comp_t * l_img_comp = 00; + + // preconditions + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_image; + cp = &(p_j2k->m_cp); + l_size_len = 40 + 3 * l_image->numcomps; + l_img_comp = l_image->comps; + + if + (l_size_len > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_size_len); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_size_len; + } + + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* write SOC identifier */ + opj_write_bytes(l_current_ptr,J2K_MS_SIZ,2); /* SIZ */ + l_current_ptr+=2; + opj_write_bytes(l_current_ptr,l_size_len-2,2); /* L_SIZ */ + l_current_ptr+=2; + opj_write_bytes(l_current_ptr, cp->rsiz, 2); /* Rsiz (capabilities) */ + l_current_ptr+=2; + opj_write_bytes(l_current_ptr, l_image->x1, 4); /* Xsiz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->y1, 4); /* Ysiz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->x0, 4); /* X0siz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->y0, 4); /* Y0siz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tdx, 4); /* XTsiz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tdy, 4); /* YTsiz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->tx0, 4); /* XT0siz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, cp->ty0, 4); /* YT0siz */ + l_current_ptr+=4; + opj_write_bytes(l_current_ptr, l_image->numcomps, 2); /* Csiz */ + l_current_ptr+=2; + for + (i = 0; i < l_image->numcomps; ++i) + { + // TODO here with MCT ? + opj_write_bytes(l_current_ptr, l_img_comp->prec - 1 + (l_img_comp->sgnd << 7), 1); /* Ssiz_i */ + ++l_current_ptr; + opj_write_bytes(l_current_ptr, l_img_comp->dx, 1); /* XRsiz_i */ + ++l_current_ptr; + opj_write_bytes(l_current_ptr, l_img_comp->dy, 1); /* YRsiz_i */ + ++l_current_ptr; + ++l_img_comp; + } + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_size_len,p_manager) != l_size_len) + { + return false; + } + return true; +} + +/** + * Reads a SIZ marker (image and tile size) + * @param p_header_data the data contained in the SIZ box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the SIZ marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_siz ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_size, i; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_comp_remain; + OPJ_UINT32 l_remaining_size; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_tmp; + opj_image_t *l_image = 00; + opj_cp_t *l_cp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcp_t * l_current_tile_param = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_image = p_j2k->m_image; + l_cp = &(p_j2k->m_cp); + if + (p_header_size < 36) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return false; + } + l_remaining_size = p_header_size - 36; + + l_nb_comp = l_remaining_size / 3; + l_nb_comp_remain = l_remaining_size % 3; + if + (l_nb_comp_remain != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return false; + } + l_size = p_header_size + 2; /* Lsiz */ + + opj_read_bytes(p_header_data,&l_tmp ,2); /* Rsiz (capabilities) */ + p_header_data+=2; + l_cp->rsiz = (OPJ_RSIZ_CAPABILITIES) l_tmp; + opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&l_image->x1) ,4); /* Xsiz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(OPJ_UINT32*) (&l_image->y1),4); /* Ysiz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(OPJ_UINT32*) &l_image->x0,4); /* X0siz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(OPJ_UINT32*) &l_image->y0,4); /* Y0siz */ + p_header_data+=4; + opj_read_bytes(p_header_data, (&l_cp->tdx),4); /* XTsiz */ + p_header_data+=4; + opj_read_bytes(p_header_data,&l_cp->tdy,4); /* YTsiz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&l_cp->tx0),4); /* XT0siz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&l_cp->ty0),4); /* YT0siz */ + p_header_data+=4; + opj_read_bytes(p_header_data,(&l_image->numcomps),2); /* Csiz */ + p_header_data+=2; + if + (l_image->numcomps != l_nb_comp) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return false; + } + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if (!(image->x1 * image->y1)) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: bad image size (%d x %d)\n", + image->x1, image->y1); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + if (image->numcomps != ((len - 38) / 3)) { + opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n", + image->numcomps, ((len - 38) / 3)); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"); + if (image->numcomps < ((len - 38) / 3)) { + len = 38 + 3 * image->numcomps; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n", + len); + } else { + image->numcomps = ((len - 38) / 3); + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n", + image->numcomps); + } + } + + /* update components number in the jpwl_exp_comps filed */ + cp->exp_comps = image->numcomps; + } +#endif /* USE_JPWL */ + + l_image->comps = (opj_image_comp_t*) opj_calloc(l_image->numcomps, sizeof(opj_image_comp_t)); + if + (l_image->comps == 00) + { + l_image->numcomps = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(l_image->comps,0,l_image->numcomps * sizeof(opj_image_comp_t)); + l_img_comp = l_image->comps; + for + (i = 0; i < l_image->numcomps; ++i) + { + OPJ_UINT32 tmp; + opj_read_bytes(p_header_data,&tmp,1); /* Ssiz_i */ + ++p_header_data; + l_img_comp->prec = (tmp & 0x7f) + 1; + l_img_comp->sgnd = tmp >> 7; + opj_read_bytes(p_header_data,&l_img_comp->dx,1); /* XRsiz_i */ + ++p_header_data; + opj_read_bytes(p_header_data,&l_img_comp->dy,1); /* YRsiz_i */ + ++p_header_data; +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters, again */ + if (!(image->comps[i].dx * image->comps[i].dy)) { + opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", + i, i, image->comps[i].dx, image->comps[i].dy); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); + if (!image->comps[i].dx) { + image->comps[i].dx = 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", + i, image->comps[i].dx); + } + if (!image->comps[i].dy) { + image->comps[i].dy = 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", + i, image->comps[i].dy); + } + } + + } +#endif /* USE_JPWL */ + l_img_comp->resno_decoded = 0; /* number of resolution decoded */ + l_img_comp->factor = l_cp->m_specific_param.m_dec.m_reduce; /* reducing factor per component */ + ++l_img_comp; + } + + l_cp->tw = int_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); + l_cp->th = int_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); + l_nb_tiles = l_cp->tw * l_cp->th; + if + (p_j2k->m_specific_param.m_decoder.m_discard_tiles) + { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = (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 = int_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 = int_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; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + } + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if ((cp->tw < 1) || (cp->th < 1) || (cp->tw > cp->max_tiles) || (cp->th > cp->max_tiles)) { + opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of tiles (%d x %d)\n", + cp->tw, cp->th); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); + if (cp->tw < 1) { + cp->tw= 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n", + cp->tw); + } + if (cp->tw > cp->max_tiles) { + cp->tw= 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- too large x, increase expectance of %d\n" + "- setting %d tiles in x => HYPOTHESIS!!!\n", + cp->max_tiles, cp->tw); + } + if (cp->th < 1) { + cp->th= 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n", + cp->th); + } + if (cp->th > cp->max_tiles) { + cp->th= 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- too large y, increase expectance of %d to continue\n", + "- setting %d tiles in y => HYPOTHESIS!!!\n", + cp->max_tiles, cp->th); + } + } + } +#endif /* USE_JPWL */ + /* memory allocations */ + l_cp->tcps = (opj_tcp_t*) opj_calloc(l_nb_tiles, sizeof(opj_tcp_t)); + if + (l_cp->tcps == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(l_cp->tcps,0,l_nb_tiles*sizeof(opj_tcp_t)); + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + if (!cp->tcps) { + opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: could not alloc tcps field of cp\n"); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + } +#endif /* USE_JPWL */ + + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps = (opj_tccp_t*) opj_calloc(l_image->numcomps, sizeof(opj_tccp_t)); + if + (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps ,0,l_image->numcomps*sizeof(opj_tccp_t)); + + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records = opj_malloc(J2K_MCT_DEFAULT_NB_RECORDS * sizeof(opj_mct_data_t)); + if + (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records,0,J2K_MCT_DEFAULT_NB_RECORDS * sizeof(opj_mct_data_t)); + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mct_records = J2K_MCT_DEFAULT_NB_RECORDS; + + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records = opj_malloc(J2K_MCC_DEFAULT_NB_RECORDS * sizeof(opj_simple_mcc_decorrelation_data_t)); + if + (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records,0,J2K_MCC_DEFAULT_NB_RECORDS * sizeof(opj_simple_mcc_decorrelation_data_t)); + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mcc_records = J2K_MCC_DEFAULT_NB_RECORDS; + + /* set up default dc level shift */ + for + (i=0;inumcomps;++i) + { + if + (! l_image->comps[i].sgnd) + { + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 << (l_image->comps[i].prec - 1); + } + } + + l_current_tile_param = l_cp->tcps; + for + (i = 0; i < l_nb_tiles; ++i) + { + l_current_tile_param->tccps = (opj_tccp_t*) opj_malloc(l_image->numcomps * sizeof(opj_tccp_t)); + if + (l_current_tile_param->tccps == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(l_current_tile_param->tccps,0,l_image->numcomps * sizeof(opj_tccp_t)); + + ++l_current_tile_param; + + } + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MH; + opj_image_comp_update(l_image,l_cp); + + /* Index */ + if + (p_j2k->cstr_info) + { + opj_codestream_info_t *cstr_info = p_j2k->cstr_info; + cstr_info->image_w = l_image->x1 - l_image->x0; + cstr_info->image_h = l_image->y1 - l_image->y0; + cstr_info->numcomps = l_image->numcomps; + cstr_info->tw = l_cp->tw; + cstr_info->th = l_cp->th; + cstr_info->tile_x = l_cp->tdx; + cstr_info->tile_y = l_cp->tdy; + cstr_info->tile_Ox = l_cp->tx0; + cstr_info->tile_Oy = l_cp->ty0; + cstr_info->tile = (opj_tile_info_t*) opj_calloc(l_nb_tiles, sizeof(opj_tile_info_t)); + if + (cstr_info->tile == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + return false; + } + memset(cstr_info->tile,0,l_nb_tiles * sizeof(opj_tile_info_t)); + } + return true; +} + +/** + * Writes the COM marker (comment) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_com( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_comment_size; + OPJ_UINT32 l_total_com_size; + const OPJ_CHAR *l_comment; + OPJ_BYTE * l_current_ptr = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_comment = p_j2k->m_cp.comment; + l_comment_size = strlen(l_comment); + l_total_com_size = l_comment_size + 6; + + if + (l_total_com_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_total_com_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_total_com_size; + } + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + opj_write_bytes(l_current_ptr,J2K_MS_COM , 2); /* COM */ + l_current_ptr+=2; + opj_write_bytes(l_current_ptr,l_total_com_size - 2 , 2); /* L_COM */ + l_current_ptr+=2; + opj_write_bytes(l_current_ptr,1 , 2); /* General use (IS 8859-15:1999 (Latin) values) */ + l_current_ptr+=2, + memcpy( l_current_ptr,l_comment,l_comment_size); + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_total_com_size,p_manager) != l_total_com_size) + { + return false; + } + return true; +} + +/** + * Reads a COM marker (comments) + * @param p_header_data the data contained in the COM box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_com ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + return true; +} + +/** + * Gets the size taken by writting a SPCod or SPCoc for the given tile and component. + * + * @param p_tile_no the tile indix. + * @param p_comp_no the component being outputted. + * @param p_j2k the J2K codec. + * + * @return the number of bytes taken by the SPCod element. + */ +OPJ_UINT32 j2k_get_SPCod_SPCoc_size ( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + // preconditions + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + // preconditions again + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no < p_j2k->m_image->numcomps); + + if + (l_tccp->csty & J2K_CCP_CSTY_PRT) + { + return 5 + l_tccp->numresolutions; + } + else + { + return 5; + } +} + + +/** + * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * + * @param p_comp_no the component number to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +bool j2k_write_SPCod_SPCoc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + // preconditions again + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no <(p_j2k->m_image->numcomps)); + + if + (*p_header_size < 5) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting SPCod SPCoc element\n"); + return false; + } + + opj_write_bytes(p_data,l_tccp->numresolutions - 1, 1); /* SPcoc (D) */ + ++p_data; + opj_write_bytes(p_data,l_tccp->cblkw - 2, 1); /* SPcoc (E) */ + ++p_data; + opj_write_bytes(p_data,l_tccp->cblkh - 2, 1); /* SPcoc (F) */ + ++p_data; + opj_write_bytes(p_data,l_tccp->cblksty, 1); /* SPcoc (G) */ + ++p_data; + opj_write_bytes(p_data,l_tccp->qmfbid, 1); /* SPcoc (H) */ + ++p_data; + + *p_header_size = *p_header_size - 5; + if + (l_tccp->csty & J2K_CCP_CSTY_PRT) + { + if + (*p_header_size < l_tccp->numresolutions) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting SPCod SPCoc element\n"); + return false; + } + for + (i = 0; i < l_tccp->numresolutions; ++i) + { + opj_write_bytes(p_data,l_tccp->prcw[i] + (l_tccp->prch[i] << 4), 1); /* SPcoc (I_i) */ + ++p_data; + } + *p_header_size = *p_header_size - l_tccp->numresolutions; + + } + return true; +} + + +/** + * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * @param p_header_data the data contained in the COM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_SPCod_SPCoc( + opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // loop + OPJ_UINT32 i; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_BYTE * l_current_ptr = 00; + OPJ_UINT32 l_tmp; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + + // precondition again + assert(compno < p_j2k->m_image->numcomps); + l_tccp = &l_tcp->tccps[compno]; + l_current_ptr = p_header_data; + + + // make sure room is sufficient + if + (* p_header_size < 5) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return false; + } + opj_read_bytes(l_current_ptr, &l_tccp->numresolutions ,1); /* SPcox (D) */ + ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ + ++l_current_ptr; + + // If user wants to remove more resolutions than the codestream contains, return error + if + (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) + { + opj_event_msg(p_manager, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number " + "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); + p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; + return false; + } + + opj_read_bytes(l_current_ptr,&l_tccp->cblkw ,1); /* SPcoc (E) */ + ++l_current_ptr; + l_tccp->cblkw += 2; + + opj_read_bytes(l_current_ptr,&l_tccp->cblkh ,1); /* SPcoc (F) */ + ++l_current_ptr; + l_tccp->cblkh += 2; + + opj_read_bytes(l_current_ptr,&l_tccp->cblksty ,1); /* SPcoc (G) */ + ++l_current_ptr; + + opj_read_bytes(l_current_ptr,&l_tccp->qmfbid ,1); /* SPcoc (H) */ + ++l_current_ptr; + + * p_header_size = * p_header_size - 5; + + // use custom precinct size ? + if + (l_tccp->csty & J2K_CCP_CSTY_PRT) + { + if + (* p_header_size < l_tccp->numresolutions) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return false; + } + for + (i = 0; i < l_tccp->numresolutions; ++i) + { + opj_read_bytes(l_current_ptr,&l_tmp ,1); /* SPcoc (I_i) */ + ++l_current_ptr; + l_tccp->prcw[i] = l_tmp & 0xf; + l_tccp->prch[i] = l_tmp >> 4; + } + * p_header_size = * p_header_size - l_tccp->numresolutions; + } + else + { + /* set default size for the precinct width and height */ + for + (i = 0; i < l_tccp->numresolutions; ++i) + { + l_tccp->prcw[i] = 15; + l_tccp->prch[i] = 15; + } + } + + /* INDEX >> */ + if + (p_j2k->cstr_info && compno == 0) + { + OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdx,l_tccp->prcw, l_data_size); + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdy,l_tccp->prch, l_data_size); + } + /* << INDEX */ + return true; +} + +/** + * Copies the tile component parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +void j2k_copy_tile_component_parameters( + opj_j2k_t *p_j2k + ) +{ + // loop + OPJ_UINT32 i; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_ref_tccp = 00; + opj_tccp_t *l_copied_tccp = 00; + OPJ_UINT32 l_prc_size; + // preconditions + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_prc_size = l_ref_tccp->numresolutions * sizeof(OPJ_UINT32); + + for + (i=1;im_image->numcomps;++i) + { + l_copied_tccp->numresolutions = l_ref_tccp->numresolutions; + l_copied_tccp->cblkw = l_ref_tccp->cblkw; + l_copied_tccp->cblkh = l_ref_tccp->cblkh; + l_copied_tccp->cblksty = l_ref_tccp->cblksty; + l_copied_tccp->qmfbid = l_ref_tccp->qmfbid; + memcpy(l_copied_tccp->prcw,l_ref_tccp->prcw,l_prc_size); + memcpy(l_copied_tccp->prch,l_ref_tccp->prch,l_prc_size); + ++l_copied_tccp; + } +} + + + +/** + * Writes the COD marker (Coding style default) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_cod( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_code_size,l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_code_size = 9 + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,0); + l_remaining_size = l_code_size; + + if + (l_code_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_code_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_code_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data,J2K_MS_COD,2); /* COD */ + l_current_data += 2; + + opj_write_bytes(l_current_data,l_code_size-2,2); /* L_COD */ + l_current_data += 2; + + opj_write_bytes(l_current_data,l_tcp->csty,1); /* Scod */ + ++l_current_data; + + opj_write_bytes(l_current_data,l_tcp->prg,1); /* SGcod (A) */ + ++l_current_data; + + opj_write_bytes(l_current_data,l_tcp->numlayers,2); /* SGcod (B) */ + l_current_data+=2; + + opj_write_bytes(l_current_data,l_tcp->mct,1); /* SGcod (C) */ + ++l_current_data; + + l_remaining_size -= 9; + + if + (! j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting COD marker\n"); + return false; + } + if + (l_remaining_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting COD marker\n"); + return false; + } + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_code_size,p_manager) != l_code_size) + { + return false; + } + return true; +} + +/** + * Reads a COD marker (Coding Styke defaults) + * @param p_header_data the data contained in the COD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COD marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_cod ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // loop + OPJ_UINT32 i; + OPJ_UINT32 l_tmp; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_image_t *l_image = 00; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH) ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_image = p_j2k->m_image; + + // make sure room is sufficient + if + (p_header_size < 5) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return false; + } + + opj_read_bytes(p_header_data,&l_tcp->csty,1); /* Scod */ + ++p_header_data; + opj_read_bytes(p_header_data,&l_tmp,1); /* SGcod (A) */ + ++p_header_data; + l_tcp->prg = (OPJ_PROG_ORDER) l_tmp; + opj_read_bytes(p_header_data,&l_tcp->numlayers,2); /* SGcod (B) */ + p_header_data+=2; + if + (l_cp->m_specific_param.m_dec.m_layer) + { + l_tcp->num_layers_to_decode = l_cp->m_specific_param.m_dec.m_layer; + } + else + { + l_tcp->num_layers_to_decode = l_tcp->numlayers; + } + + opj_read_bytes(p_header_data,&l_tcp->mct,1); /* SGcod (C) */ + ++p_header_data; + + p_header_size -= 5; + for + (i = 0; i < l_image->numcomps; ++i) + { + l_tcp->tccps[i].csty = l_tcp->csty & J2K_CCP_CSTY_PRT; + } + + if + (! j2k_read_SPCod_SPCoc(p_j2k,0,p_header_data,&p_header_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return false; + } + if + (p_header_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return false; + } + j2k_copy_tile_component_parameters(p_j2k); + + + /* Index */ + if + (p_j2k->cstr_info) + { + opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info; + l_cstr_info->prog = l_tcp->prg; + l_cstr_info->numlayers = l_tcp->numlayers; + l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(l_image->numcomps * sizeof(OPJ_UINT32)); + for + (i = 0; i < l_image->numcomps; ++i) + { + l_cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1; + } + } + return true; +} + +/** + * Writes the COC marker (Coding style component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_coc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_coc_size,l_remaining_size; + OPJ_UINT32 l_comp_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_comp_room = (p_j2k->m_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); + if + (l_coc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_coc_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size; + } + + j2k_write_coc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager); + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_coc_size,p_manager) != l_coc_size) + { + return false; + } + return true; +} + +/** + * Gets the maximum size taken by a coc. + * + * @param p_j2k the jpeg2000 codec to use. + */ +OPJ_UINT32 j2k_get_max_coc_size(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 i,j; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max = 0; + + // preconditions + + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + l_nb_comp = p_j2k->m_image->numcomps; + + for + (i=0;im_cp.tcps; + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + + for + (i=0;im_nb_tile_parts); + ++l_tcp; + } + return 12 * l_max; +} + + +/** + * Gets the maximum size taken by the headers of the SOT. + * + * @param p_j2k the jpeg2000 codec to use. + */ +OPJ_UINT32 j2k_get_specific_header_sizes(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_coc_bytes,l_qcc_bytes; + + + l_nb_comps = p_j2k->m_image->numcomps - 1; + l_nb_bytes += j2k_get_max_toc_size(p_j2k); + if + (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == 0) + { + l_coc_bytes = j2k_get_max_coc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_coc_bytes; + l_qcc_bytes = j2k_get_max_qcc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_qcc_bytes; + } + l_nb_bytes += j2k_get_max_poc_size(p_j2k); + /*** DEVELOPER CORNER, Add room for your headers ***/ + + + return l_nb_bytes; +} + + +/** + * Writes the COC marker (Coding style component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +void j2k_write_coc_in_memory( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_coc_size,l_remaining_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 l_comp_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_image = p_j2k->m_image; + l_comp_room = (l_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); + l_remaining_size = l_coc_size; + + l_current_data = p_data; + + opj_write_bytes(l_current_data,J2K_MS_COC,2); /* COC */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_coc_size-2,2); /* L_COC */ + l_current_data += 2; + opj_write_bytes(l_current_data,p_comp_no, l_comp_room); /* Ccoc */ + l_current_data+=l_comp_room; + opj_write_bytes(l_current_data, l_tcp->tccps[p_comp_no].csty, 1); /* Scoc */ + ++l_current_data; + l_remaining_size -= (5 + l_comp_room); + j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager); + * p_data_written = l_coc_size; +} + + +/** + * Reads a COC marker (Coding Style Component) + * @param p_header_data the data contained in the COC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_coc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 l_comp_room; + OPJ_UINT32 l_comp_no; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH) ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_image = p_j2k->m_image; + + l_comp_room = l_image->numcomps <= 256 ? 1 : 2; + // make sure room is sufficient + if + (p_header_size < l_comp_room + 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return false; + } + p_header_size -= l_comp_room + 1; + + opj_read_bytes(p_header_data,&l_comp_no,l_comp_room); /* Ccoc */ + p_header_data += l_comp_room; + if + (l_comp_no >= l_image->numcomps) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker (bad number of components)\n"); + return false; + } + opj_read_bytes(p_header_data,&l_tcp->tccps[l_comp_no].csty,1); /* Scoc */ + ++p_header_data ; + + if + (! j2k_read_SPCod_SPCoc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return false; + } + if + (p_header_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return false; + } + return true; +} + +/** + * Gets the size taken by writting SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile indix. + * @param p_comp_no the component being outputted. + * @param p_j2k the J2K codec. + * + * @return the number of bytes taken by the SPCod element. + */ +OPJ_UINT32 j2k_get_SQcd_SQcc_size ( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no + ) +{ + OPJ_UINT32 l_num_bands; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + // preconditions + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + // preconditions again + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no < p_j2k->m_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2); + + if + (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) + { + return 1 + l_num_bands; + } + else + { + return 1 + 2*l_num_bands; + } +} + +/** + * Writes a SQcd or SQcc element, i.e. the quantization values of a band. + * + * @param p_tile_no the tile to output. + * @param p_comp_no the component number to output. + * @param p_data the data buffer. + * @param p_header_size pointer to the size of the data buffer, it is changed by the function. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +bool j2k_write_SQcd_SQcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_header_size; + OPJ_UINT32 l_band_no, l_num_bands; + OPJ_UINT32 l_expn,l_mant; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + // preconditions again + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no m_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2); + + if + (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) + { + l_header_size = 1 + l_num_bands; + if + (*p_header_size < l_header_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting SQcd SQcc element\n"); + return false; + } + opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1); /* Sqcx */ + ++p_data; + for + (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) + { + l_expn = l_tccp->stepsizes[l_band_no].expn; + opj_write_bytes(p_data, l_expn << 3, 1); /* SPqcx_i */ + ++p_data; + } + } + else + { + l_header_size = 1 + 2*l_num_bands; + if + (*p_header_size < l_header_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting SQcd SQcc element\n"); + return false; + } + opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1); /* Sqcx */ + ++p_data; + for + (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) + { + l_expn = l_tccp->stepsizes[l_band_no].expn; + l_mant = l_tccp->stepsizes[l_band_no].mant; + opj_write_bytes(p_data, (l_expn << 11) + l_mant, 2); /* SPqcx_i */ + p_data += 2; + } + } + *p_header_size = *p_header_size - l_header_size; + return true; +} + +/** + * Reads a SQcd or SQcc element, i.e. the quantization values of a band. + * + * @param p_comp_no the component being targeted. + * @param p_header_data the data contained in the COM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_SQcd_SQcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE* p_header_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // loop + OPJ_UINT32 l_band_no; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_BYTE * l_current_ptr = 00; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_num_band; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + // precondition again + assert(p_comp_no < p_j2k->m_image->numcomps); + l_tccp = &l_tcp->tccps[p_comp_no]; + l_current_ptr = p_header_data; + + if + (* p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SQcd or SQcc element\n"); + return false; + } + * p_header_size -= 1; + + opj_read_bytes(l_current_ptr, &l_tmp ,1); /* Sqcx */ + ++l_current_ptr; + + l_tccp->qntsty = l_tmp & 0x1f; + l_tccp->numgbits = l_tmp >> 5; + if + (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) + { + l_num_band = 1; + } + else + { + l_num_band = (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? (*p_header_size) : (*p_header_size) / 2; + } + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + + /* if JPWL is on, we check whether there are too many subbands */ + if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) { + opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of subbands in Sqcx (%d)\n", + numbands); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + numbands = 1; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n" + "- setting number of bands to %d => HYPOTHESIS!!!\n", + numbands); + }; + + }; +#endif /* USE_JPWL */ + if + (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) + { + for + (l_band_no = 0; l_band_no < l_num_band; l_band_no++) + { + opj_read_bytes(l_current_ptr, &l_tmp ,1); /* SPqcx_i */ + ++l_current_ptr; + l_tccp->stepsizes[l_band_no].expn = l_tmp>>3; + l_tccp->stepsizes[l_band_no].mant = 0; + } + * p_header_size = * p_header_size - l_num_band; + } + else + { + for + (l_band_no = 0; l_band_no < l_num_band; l_band_no++) + { + opj_read_bytes(l_current_ptr, &l_tmp ,2); /* SPqcx_i */ + l_current_ptr+=2; + l_tccp->stepsizes[l_band_no].expn = l_tmp >> 11; + l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; + } + * p_header_size = * p_header_size - 2*l_num_band; + } + + /* Add Antonin : if scalar_derived -> compute other stepsizes */ + if + (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) + { + for + (l_band_no = 1; l_band_no < J2K_MAXBANDS; l_band_no++) + { + l_tccp->stepsizes[l_band_no].expn = + ((l_tccp->stepsizes[0].expn) - ((l_band_no - 1) / 3) > 0) ? + (l_tccp->stepsizes[0].expn) - ((l_band_no - 1) / 3) : 0; + l_tccp->stepsizes[l_band_no].mant = l_tccp->stepsizes[0].mant; + } + + } + return true; +} + + + +/** + * Copies the tile component parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +void j2k_copy_tile_quantization_parameters( + opj_j2k_t *p_j2k + ) +{ + // loop + OPJ_UINT32 i; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_ref_tccp = 00; + opj_tccp_t *l_copied_tccp = 00; + OPJ_UINT32 l_size; + // preconditions + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + // precondition again + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_size = J2K_MAXBANDS * sizeof(opj_stepsize_t); + + for + (i=1;im_image->numcomps;++i) + { + l_copied_tccp->qntsty = l_ref_tccp->qntsty; + l_copied_tccp->numgbits = l_ref_tccp->numgbits; + memcpy(l_copied_tccp->stepsizes,l_ref_tccp->stepsizes,l_size); + ++l_copied_tccp; + } +} + + + +/** + * Writes the QCD marker (quantization default) + * + * @param p_comp_number the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_qcd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_qcd_size,l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_qcd_size = 4 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,0); + l_remaining_size = l_qcd_size; + + if + (l_qcd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_qcd_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcd_size; + } + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data,J2K_MS_QCD,2); /* QCD */ + l_current_data += 2; + + opj_write_bytes(l_current_data,l_qcd_size-2,2); /* L_QCD */ + l_current_data += 2; + + l_remaining_size -= 4; + + if + (! j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting QCD marker\n"); + return false; + } + if + (l_remaining_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error writting QCD marker\n"); + return false; + } + + if + (opj_stream_write_data(p_stream, p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcd_size,p_manager) != l_qcd_size) + { + return false; + } + return true; +} + +/** + * Reads a QCD marker (Quantization defaults) + * @param p_header_data the data contained in the QCD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCD marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_qcd ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (! j2k_read_SQcd_SQcc(p_j2k,0,p_header_data,&p_header_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return false; + } + if + (p_header_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return false; + } + j2k_copy_tile_quantization_parameters(p_j2k); + return true; +} + + +/** + * Writes the QCC marker (quantization component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_qcc( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_qcc_size,l_remaining_size; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_qcc_size = 6 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); + l_remaining_size = l_qcc_size; + if + (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_qcc_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size; + } + j2k_write_qcc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager); + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcc_size,p_manager) != l_qcc_size) + { + return false; + } + return true; +} + + +/** + * Writes the QCC marker (quantization component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +void j2k_write_qcc_in_memory( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_qcc_size,l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + + l_qcc_size = 6 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); + l_remaining_size = l_qcc_size; + + l_current_data = p_data; + + opj_write_bytes(l_current_data,J2K_MS_QCC,2); /* QCC */ + l_current_data += 2; + + if + (p_j2k->m_image->numcomps <= 256) + { + --l_qcc_size; + opj_write_bytes(l_current_data,l_qcc_size-2,2); /* L_QCC */ + l_current_data += 2; + opj_write_bytes(l_current_data, p_comp_no, 1); /* Cqcc */ + ++l_current_data; + // in the case only one byte is sufficient the last byte allocated is useless -> still do -6 for available + l_remaining_size -= 6; + } + else + { + opj_write_bytes(l_current_data,l_qcc_size-2,2); /* L_QCC */ + l_current_data += 2; + opj_write_bytes(l_current_data, p_comp_no, 2); /* Cqcc */ + l_current_data+=2; + l_remaining_size -= 6; + } + j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,p_comp_no,l_current_data,&l_remaining_size,p_manager); + * p_data_written = l_qcc_size; +} + +/** + * Gets the maximum size taken by a qcc. + */ +OPJ_UINT32 j2k_get_max_qcc_size (opj_j2k_t *p_j2k) +{ + return j2k_get_max_coc_size(p_j2k); +} + +/** + * Reads a QCC marker (Quantization component) + * @param p_header_data the data contained in the QCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_qcc( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_num_comp,l_comp_no; + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_num_comp = p_j2k->m_image->numcomps; + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + + static OPJ_UINT32 backup_compno = 0; + + /* compno is negative or larger than the number of components!!! */ + if ((compno < 0) || (compno >= numcomp)) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", + compno, numcomp); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + compno = backup_compno % numcomp; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting component number to %d\n", + compno); + } + + /* keep your private count of tiles */ + backup_compno++; + }; +#endif /* USE_JPWL */ + if + (l_num_comp <= 256) + { + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return false; + } + opj_read_bytes(p_header_data,&l_comp_no,1); + ++p_header_data; + --p_header_size; + } + else + { + if + (p_header_size < 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return false; + } + opj_read_bytes(p_header_data,&l_comp_no,2); + p_header_data+=2; + p_header_size-=2; + } + if + (! j2k_read_SQcd_SQcc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return false; + } + if + (p_header_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return false; + } + return true; + +} + + +/** + * Writes the CBD marker (Component bit depth definition) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_cbd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_cbd_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + opj_image_comp_t * l_comp = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_image = p_j2k->m_image; + l_cbd_size = 6 + p_j2k->m_image->numcomps; + + if + (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_cbd_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_cbd_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + opj_write_bytes(l_current_data,J2K_MS_CBD,2); /* CBD */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_cbd_size-2,2); /* L_CBD */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_image->numcomps, 2); /* Ncbd */ + l_current_data+=2; + l_comp = l_image->comps; + for + (i=0;inumcomps;++i) + { + opj_write_bytes(l_current_data, (l_comp->sgnd << 7) | (l_comp->prec - 1), 1); /* Component bit depth */ + ++l_current_data; + ++l_comp; + } + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_cbd_size,p_manager) != l_cbd_size) + { + return false; + } + return true; +} + +/** + * Reads a CBD marker (Component bit depth definition) + * @param p_header_data the data contained in the CBD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CBD marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_cbd ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_nb_comp,l_num_comp; + OPJ_UINT32 l_comp_def; + OPJ_UINT32 i; + opj_image_comp_t * l_comp = 00; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_num_comp = p_j2k->m_image->numcomps; + + if + (p_header_size != (p_j2k->m_image->numcomps + 2)) + { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return false; + } + opj_read_bytes(p_header_data,&l_nb_comp,2); /* Ncbd */ + p_header_data+=2; + if + (l_nb_comp != l_num_comp) + { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return false; + } + + l_comp = p_j2k->m_image->comps; + for + (i=0;isgnd = (l_comp_def>>7) & 1; + l_comp->prec = (l_comp_def&0x7f) + 1; + ++l_comp; + } + return true; +} + +/** + * Writes the MCC marker (Multiple Component Collection) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_mcc_record( + opj_j2k_t *p_j2k, + struct opj_simple_mcc_decorrelation_data * p_mcc_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_mcc_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_bytes_for_comp; + OPJ_UINT32 l_mask; + OPJ_UINT32 l_tmcc; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + if + (p_mcc_record->m_nb_comps > 255 ) + { + l_nb_bytes_for_comp = 2; + l_mask = 0x8000; + } + else + { + l_nb_bytes_for_comp = 1; + l_mask = 0; + } + + l_mcc_size = p_mcc_record->m_nb_comps * 2 * l_nb_bytes_for_comp + 19; + if + (l_mcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_mcc_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mcc_size; + } + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + opj_write_bytes(l_current_data,J2K_MS_MCC,2); /* MCC */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_mcc_size-2,2); /* Lmcc */ + l_current_data += 2; + + /* first marker */ + opj_write_bytes(l_current_data,0,2); /* Zmcc */ + l_current_data += 2; + opj_write_bytes(l_current_data,p_mcc_record->m_index,1); /* Imcc -> no need for other values, take the first */ + ++l_current_data; + /* only one marker atm */ + opj_write_bytes(l_current_data,0,2); /* Ymcc */ + l_current_data+=2; + opj_write_bytes(l_current_data,1,2); /* Qmcc -> number of collections -> 1 */ + l_current_data+=2; + opj_write_bytes(l_current_data,0x1,1); /* Xmcci type of component transformation -> array based decorrelation */ + ++l_current_data; + + opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps | l_mask,2); /* Nmcci number of input components involved and size for each component offset = 8 bits */ + l_current_data+=2; + + for + (i=0;im_nb_comps;++i) + { + opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp); /* Cmccij Component offset*/ + l_current_data+=l_nb_bytes_for_comp; + } + + opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps|l_mask,2); /* Mmcci number of output components involved and size for each component offset = 8 bits */ + l_current_data+=2; + for + (i=0;im_nb_comps;++i) + { + opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp); /* Wmccij Component offset*/ + l_current_data+=l_nb_bytes_for_comp; + } + l_tmcc = ((!p_mcc_record->m_is_irreversible)&1)<<16; + if + (p_mcc_record->m_decorrelation_array) + { + l_tmcc |= p_mcc_record->m_decorrelation_array->m_index; + } + if + (p_mcc_record->m_offset_array) + { + l_tmcc |= ((p_mcc_record->m_offset_array->m_index)<<8); + } + opj_write_bytes(l_current_data,l_tmcc,3); /* Tmcci : use MCT defined as number 1 and irreversible array based. */ + l_current_data+=3; + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mcc_size,p_manager) != l_mcc_size) + { + return false; + } + return true; +} + + +/** + * Reads a MCC marker (Multiple Component Collection) + * + * @param p_header_data the data contained in the MCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_mcc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i,j; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_tcp_t * l_tcp; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_data; + OPJ_UINT32 l_nb_collections; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_nb_bytes_by_comp; + + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if + (p_header_size < 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + + /* first marker */ + opj_read_bytes(p_header_data,&l_tmp,2); /* Zmcc */ + p_header_data += 2; + if + (l_tmp != 0) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n"); + return true; + } + if + (p_header_size < 7) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + opj_read_bytes(p_header_data,&l_indix,1); /* Imcc -> no need for other values, take the first */ + ++p_header_data; + + l_mcc_record = l_tcp->m_mcc_records; + for + (i=0;im_nb_mcc_records;++i) + { + if + (l_mcc_record->m_index == l_indix) + { + break; + } + ++l_mcc_record; + } + /** NOT FOUND */ + if + (i == l_tcp->m_nb_mcc_records) + { + if + (l_tcp->m_nb_mcc_records == l_tcp->m_nb_max_mcc_records) + { + l_tcp->m_nb_max_mcc_records += J2K_MCC_DEFAULT_NB_RECORDS; + l_tcp->m_mcc_records = opj_realloc(l_tcp->m_mcc_records,l_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t)); + if + (! l_tcp->m_mcc_records) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + memset(l_mcc_record,0,(l_tcp->m_nb_max_mcc_records-l_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); + } + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + } + l_mcc_record->m_index = l_indix; + + /* only one marker atm */ + opj_read_bytes(p_header_data,&l_tmp,2); /* Ymcc */ + p_header_data+=2; + if + (l_tmp != 0) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n"); + return true; + } + opj_read_bytes(p_header_data,&l_nb_collections,2); /* Qmcc -> number of collections -> 1 */ + p_header_data+=2; + if + (l_nb_collections > 1) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple collections\n"); + return true; + } + p_header_size -= 7; + for + (i=0;i array based decorrelation */ + ++p_header_data; + if + (l_tmp != 1) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections other than array decorrelation\n"); + return true; + } + opj_read_bytes(p_header_data,&l_nb_comps,2); + p_header_data+=2; + p_header_size-=3; + l_nb_bytes_by_comp = 1 + (l_nb_comps>>15); + l_mcc_record->m_nb_comps = l_nb_comps & 0x7fff; + if + (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2); + for + (j=0;jm_nb_comps;++j) + { + opj_read_bytes(p_header_data,&l_tmp,l_nb_bytes_by_comp); /* Cmccij Component offset*/ + p_header_data+=l_nb_bytes_by_comp; + if + (l_tmp != j) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n"); + return true; + } + } + opj_read_bytes(p_header_data,&l_nb_comps,2); + p_header_data+=2; + l_nb_bytes_by_comp = 1 + (l_nb_comps>>15); + l_nb_comps &= 0x7fff; + if + (l_nb_comps != l_mcc_record->m_nb_comps) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections without same number of indixes\n"); + return true; + } + if + (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3); + for + (j=0;jm_nb_comps;++j) + { + opj_read_bytes(p_header_data,&l_tmp,l_nb_bytes_by_comp); /* Wmccij Component offset*/ + p_header_data+=l_nb_bytes_by_comp; + if + (l_tmp != j) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n"); + return true; + } + } + opj_read_bytes(p_header_data,&l_tmp,3); /* Wmccij Component offset*/ + p_header_data += 3; + l_mcc_record->m_is_irreversible = ! ((l_tmp>>16) & 1); + l_mcc_record->m_decorrelation_array = 00; + l_mcc_record->m_offset_array = 00; + l_indix = l_tmp & 0xff; + if + (l_indix != 0) + { + l_mct_data = l_tcp->m_mct_records; + for + (j=0;jm_nb_mct_records;++j) + { + if + (l_mct_data->m_index == l_indix) + { + l_mcc_record->m_decorrelation_array = l_mct_data; + break; + } + ++l_mct_data; + } + if + (l_mcc_record->m_decorrelation_array == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + } + l_indix = (l_tmp >> 8) & 0xff; + if + (l_indix != 0) + { + l_mct_data = l_tcp->m_mct_records; + for + (j=0;jm_nb_mct_records;++j) + { + if + (l_mct_data->m_index == l_indix) + { + l_mcc_record->m_offset_array = l_mct_data; + break; + } + ++l_mct_data; + } + if + (l_mcc_record->m_offset_array == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + } + } + if + (p_header_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return false; + } + ++l_tcp->m_nb_mcc_records; + return true; +} + +/** + * Writes the MCT marker (Multiple Component Transform) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_mct_record( + opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_mct_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tmp; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_mct_size = 10 + p_mct_record->m_data_size; + if + (l_mct_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_mct_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mct_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data,J2K_MS_MCT,2); /* MCT */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_mct_size-2,2); /* Lmct */ + l_current_data += 2; + opj_write_bytes(l_current_data,0,2); /* Zmct */ + l_current_data += 2; + /* only one marker atm */ + l_tmp = (p_mct_record->m_index & 0xff) | (p_mct_record->m_array_type << 8) | (p_mct_record->m_element_type << 10); + opj_write_bytes(l_current_data,l_tmp,2); + l_current_data += 2; + opj_write_bytes(l_current_data,0,2); /* Ymct */ + l_current_data+=2; + + memcpy(l_current_data,p_mct_record->m_data,p_mct_record->m_data_size); + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mct_size,p_manager) != l_mct_size) + { + return false; + } + return true; +} + +/** + * Reads a MCT marker (Multiple Component Transform) + * + * @param p_header_data the data contained in the MCT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCT marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_mct ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_mct_data_t * l_mct_data; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if + (p_header_size < 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return false; + } + /* first marker */ + opj_read_bytes(p_header_data,&l_tmp,2); /* Zmct */ + p_header_data += 2; + if + (l_tmp != 0) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge mct data within multiple MCT records\n"); + return true; + } + if + (p_header_size <= 6) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return false; + } + opj_read_bytes(p_header_data,&l_tmp,2); /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/ + p_header_data += 2; + + l_indix = l_tmp & 0xff; + l_mct_data = l_tcp->m_mct_records; + for + (i=0;im_nb_mct_records;++i) + { + if + (l_mct_data->m_index == l_indix) + { + break; + } + ++l_mct_data; + } + /* NOT FOUND */ + if + (i == l_tcp->m_nb_mct_records) + { + if + (l_tcp->m_nb_mct_records == l_tcp->m_nb_max_mct_records) + { + l_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; + l_tcp->m_mct_records = opj_realloc(l_tcp->m_mct_records,l_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if + (! l_tcp->m_mct_records) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return false; + } + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + memset(l_mct_data ,0,(l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + } + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + } + if + (l_mct_data->m_data) + { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + } + l_mct_data->m_index = l_indix; + l_mct_data->m_array_type = (l_tmp >> 8) & 3; + l_mct_data->m_element_type = (l_tmp >> 10) & 3; + + opj_read_bytes(p_header_data,&l_tmp,2); /* Ymct */ + p_header_data+=2; + if + (l_tmp != 0) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple MCT markers\n"); + return true; + } + p_header_size -= 6; + l_mct_data->m_data = opj_malloc(p_header_size); + if + (! l_mct_data->m_data) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return false; + } + memcpy(l_mct_data->m_data,p_header_data,p_header_size); + l_mct_data->m_data_size = p_header_size; + ++l_tcp->m_nb_mct_records; + return true; +} + +bool j2k_setup_mct_encoding (opj_tcp_t * p_tcp,opj_image_t * p_image) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_indix = 1; + opj_mct_data_t * l_mct_deco_data = 00,* l_mct_offset_data = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_data; + OPJ_UINT32 l_mct_size,l_nb_elem; + OPJ_FLOAT32 * l_data, * l_current_data; + opj_tccp_t * l_tccp; + + // preconditions + assert(p_tcp != 00); + + if + (p_tcp->mct != 2) + { + return true; + } + + if + (p_tcp->m_mct_decoding_matrix) + { + if + (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) + { + p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; + p_tcp->m_mct_records = opj_realloc(p_tcp->m_mct_records,p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if + (! p_tcp->m_mct_records) + { + return false; + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + memset(l_mct_deco_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + if + (l_mct_deco_data->m_data) + { + opj_free(l_mct_deco_data->m_data); + l_mct_deco_data->m_data = 00; + } + l_mct_deco_data->m_index = l_indix++; + l_mct_deco_data->m_array_type = MCT_TYPE_DECORRELATION; + l_mct_deco_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_deco_data->m_element_type]; + l_mct_deco_data->m_data = opj_malloc(l_mct_size ); + if + (! l_mct_deco_data->m_data) + { + return false; + } + j2k_mct_write_functions_from_float[l_mct_deco_data->m_element_type](p_tcp->m_mct_decoding_matrix,l_mct_deco_data->m_data,l_nb_elem); + l_mct_deco_data->m_data_size = l_mct_size; + ++p_tcp->m_nb_mct_records; + } + + if + (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) + { + p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; + p_tcp->m_mct_records = opj_realloc(p_tcp->m_mct_records,p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if + (! p_tcp->m_mct_records) + { + return false; + } + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + memset(l_mct_offset_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + if + (l_mct_deco_data) + { + l_mct_deco_data = l_mct_offset_data - 1; + } + } + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + if + (l_mct_offset_data->m_data) + { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + } + + l_mct_offset_data->m_index = l_indix++; + l_mct_offset_data->m_array_type = MCT_TYPE_OFFSET; + l_mct_offset_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_offset_data->m_element_type]; + l_mct_offset_data->m_data = opj_malloc(l_mct_size ); + if + (! l_mct_offset_data->m_data) + { + return false; + } + l_data = opj_malloc(l_nb_elem * sizeof(OPJ_FLOAT32)); + if + (! l_data) + { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + return false; + } + l_tccp = p_tcp->tccps; + l_current_data = l_data; + for + (i=0;im_dc_level_shift); + ++l_tccp; + } + j2k_mct_write_functions_from_float[l_mct_offset_data->m_element_type](l_data,l_mct_offset_data->m_data,l_nb_elem); + opj_free(l_data); + l_mct_offset_data->m_data_size = l_mct_size; + ++p_tcp->m_nb_mct_records; + + if + (p_tcp->m_nb_mcc_records == p_tcp->m_nb_max_mcc_records) + { + p_tcp->m_nb_max_mcc_records += J2K_MCT_DEFAULT_NB_RECORDS; + p_tcp->m_mcc_records = opj_realloc(p_tcp->m_mcc_records,p_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t)); + if + (! p_tcp->m_mcc_records) + { + return false; + } + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + memset(l_mcc_data ,0,(p_tcp->m_nb_max_mcc_records - p_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); + + } + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + l_mcc_data->m_decorrelation_array = l_mct_deco_data; + l_mcc_data->m_is_irreversible = 1; + l_mcc_data->m_nb_comps = p_image->numcomps; + l_mcc_data->m_index = l_indix++; + l_mcc_data->m_offset_array = l_mct_offset_data; + ++p_tcp->m_nb_mcc_records; + return true; +} + +/** + * Writes the MCO marker (Multiple component transformation ordering) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_mco( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_mco_size; + opj_tcp_t * l_tcp = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + OPJ_UINT32 i; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp =&(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + l_mco_size = 5 + l_tcp->m_nb_mcc_records; + if + (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_mco_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size; + } + + opj_write_bytes(l_current_data,J2K_MS_MCO,2); /* MCO */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_mco_size-2,2); /* Lmco */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1); /* Nmco : only one tranform stage*/ + ++l_current_data; + + l_mcc_record = l_tcp->m_mcc_records; + for + (i=0;im_nb_mcc_records;++i) + { + opj_write_bytes(l_current_data,l_mcc_record->m_index,1); /* Imco -> use the mcc indicated by 1*/ + ++l_current_data; + ++l_mcc_record; + } + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mco_size,p_manager) != l_mco_size) + { + return false; + } + return true; +} +/** + * Reads a MCO marker (Multiple Component Transform Ordering) + * + * @param p_header_data the data contained in the MCO box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCO marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_mco ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_tmp, i; + OPJ_UINT32 l_nb_stages; + opj_tcp_t * l_tcp; + opj_tccp_t * l_tccp; + opj_image_t * l_image; + opj_image_comp_t * l_img_comp; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_image; + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH ? &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCO marker\n"); + return false; + } + + opj_read_bytes(p_header_data,&l_nb_stages,1); /* Nmco : only one tranform stage*/ + ++p_header_data; + if + (l_nb_stages > 1) + { + opj_event_msg(p_manager, EVT_WARNING, "Cannot take in charge multiple transformation stages.\n"); + return true; + } + if + (p_header_size != l_nb_stages + 1) + { + opj_event_msg(p_manager, EVT_WARNING, "Error reading MCO marker\n"); + return false; + } + + l_tccp = l_tcp->tccps; + l_img_comp = l_image->comps; + for + (i=0;inumcomps;++i) + { + l_tccp->m_dc_level_shift = 0; + ++l_tccp; + } + if + (l_tcp->m_mct_decoding_matrix) + { + opj_free(l_tcp->m_mct_decoding_matrix); + l_tcp->m_mct_decoding_matrix = 00; + } + + for + (i=0;im_image,l_tmp)) + { + return false; + } + } + return true; +} + +bool j2k_add_mct(opj_tcp_t * p_tcp,opj_image_t * p_image, OPJ_UINT32 p_index) +{ + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_deco_array, * l_offset_array; + OPJ_UINT32 l_data_size,l_mct_size, l_offset_size; + OPJ_UINT32 l_nb_elem; + OPJ_UINT32 * l_offset_data, * l_current_offset_data; + opj_tccp_t * l_tccp; + + + // preconditions + assert(p_tcp != 00); + + l_mcc_record = p_tcp->m_mcc_records; + for + (i=0;im_nb_mcc_records;++i) + { + if + (l_mcc_record->m_index == p_index) + { + break; + } + } + if + (i==p_tcp->m_nb_mcc_records) + { + /** element discarded **/ + return true; + } + if + (l_mcc_record->m_nb_comps != p_image->numcomps) + { + /** do not support number of comps != image */ + return true; + } + l_deco_array = l_mcc_record->m_decorrelation_array; + if + (l_deco_array) + { + l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps * p_image->numcomps; + if + (l_deco_array->m_data_size != l_data_size) + { + return false; + } + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * sizeof(OPJ_FLOAT32); + p_tcp->m_mct_decoding_matrix = opj_malloc(l_mct_size); + if + (! p_tcp->m_mct_decoding_matrix ) + { + return false; + } + j2k_mct_read_functions_to_float[l_deco_array->m_element_type](l_deco_array->m_data,p_tcp->m_mct_decoding_matrix,l_nb_elem); + } + l_offset_array = l_mcc_record->m_offset_array; + if + (l_offset_array) + { + l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * p_image->numcomps; + if + (l_offset_array->m_data_size != l_data_size) + { + return false; + } + l_nb_elem = p_image->numcomps; + l_offset_size = l_nb_elem * sizeof(OPJ_UINT32); + l_offset_data = opj_malloc(l_offset_size); + if + (! l_offset_data ) + { + return false; + } + j2k_mct_read_functions_to_int32[l_offset_array->m_element_type](l_offset_array->m_data,l_offset_data,l_nb_elem); + l_tccp = p_tcp->tccps; + l_current_offset_data = l_offset_data; + for + (i=0;inumcomps;++i) + { + l_tccp->m_dc_level_shift = *(l_current_offset_data++); + ++l_tccp; + } + opj_free(l_offset_data); + } + return true; +} + +/** + * Writes the MCT marker (Multiple Component Transform) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_mct_data_group( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_record; + opj_tcp_t * l_tcp; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + if + (! j2k_write_cbd(p_j2k,p_stream,p_manager)) + { + return false; + } + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + l_mct_record = l_tcp->m_mct_records; + for + (i=0;im_nb_mct_records;++i) + { + if + (! j2k_write_mct_record(p_j2k,l_mct_record,p_stream,p_manager)) + { + return false; + } + ++l_mct_record; + } + l_mcc_record = l_tcp->m_mcc_records; + for + (i=0;im_nb_mcc_records;++i) + { + if + (! j2k_write_mcc_record(p_j2k,l_mcc_record,p_stream,p_manager)) + { + return false; + } + ++l_mcc_record; + } + if + (! j2k_write_mco(p_j2k,p_stream,p_manager)) + { + return false; + } + return true; +} + + +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_poc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + OPJ_UINT32 l_written_size = 0; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_UINT32 l_poc_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_tccp = &l_tcp->tccps[0]; + l_nb_comp = p_j2k->m_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + if + (l_nb_comp <= 256) + { + l_poc_room = 1; + } + else + { + l_poc_room = 2; + } + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + if + (l_poc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_poc_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; + } + + j2k_write_poc_in_memory(p_j2k,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_written_size,p_manager); + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_poc_size,p_manager) != l_poc_size) + { + return false; + } + return true; +} + + +/** + * Writes EPC ???? + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_epc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_codestream_info_t * l_info = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_info = p_j2k->cstr_info; + if + (l_info) + { + l_info->codestream_size = opj_stream_tell(p_stream); + /* UniPG>> */ + /* The following adjustment is done to adjust the codestream size */ + /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */ + /* the first bunch of bytes is not in the codestream */ + l_info->codestream_size -= l_info->main_head_start; + /* <epc_on) { + + /* encode according to JPWL */ + jpwl_encode(p_j2k, p_stream, image); + + } +#endif /* USE_JPWL */ + return true; +} + + +/** + * Gets the maximum size taken by the writting of a POC. + */ +OPJ_UINT32 j2k_get_max_poc_size(opj_j2k_t *p_j2k) +{ + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 l_nb_tiles = 0; + OPJ_UINT32 l_max_poc = 0; + OPJ_UINT32 i; + + l_tcp = p_j2k->m_cp.tcps; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + + for + (i=0;inumpocs); + ++l_tcp; + } + ++l_max_poc; + return 4 + 9 * l_max_poc; +} + + +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +void j2k_write_poc_in_memory( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + opj_image_t *l_image = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + opj_poc_t *l_current_poc = 00; + OPJ_UINT32 l_poc_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_tccp = &l_tcp->tccps[0]; + l_image = p_j2k->m_image; + l_nb_comp = l_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + if + (l_nb_comp <= 256) + { + l_poc_room = 1; + } + else + { + l_poc_room = 2; + } + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + + l_current_data = p_data; + + opj_write_bytes(l_current_data,J2K_MS_POC,2); /* POC */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_poc_size-2,2); /* Lpoc */ + l_current_data += 2; + + l_current_poc = l_tcp->pocs; + for + (i = 0; i < l_nb_poc; ++i) + { + opj_write_bytes(l_current_data,l_current_poc->resno0,1); /* RSpoc_i */ + ++l_current_data; + opj_write_bytes(l_current_data,l_current_poc->compno0,l_poc_room); /* CSpoc_i */ + l_current_data+=l_poc_room; + opj_write_bytes(l_current_data,l_current_poc->layno1,2); /* LYEpoc_i */ + l_current_data+=2; + opj_write_bytes(l_current_data,l_current_poc->resno1,1); /* REpoc_i */ + ++l_current_data; + opj_write_bytes(l_current_data,l_current_poc->compno1,l_poc_room); /* CEpoc_i */ + l_current_data+=l_poc_room; + opj_write_bytes(l_current_data,l_current_poc->prg,1); /* Ppoc_i */ + ++l_current_data; + + /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/ + l_current_poc->layno1 = int_min(l_current_poc->layno1, l_tcp->numlayers); + l_current_poc->resno1 = int_min(l_current_poc->resno1, l_tccp->numresolutions); + l_current_poc->compno1 = int_min(l_current_poc->compno1, l_nb_comp); + ++l_current_poc; + } + * p_data_written = l_poc_size; +} + + +/** + * Reads a POC marker (Progression Order Change) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_poc ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_nb_comp; + opj_image_t * l_image = 00; + OPJ_UINT32 l_old_poc_nb,l_current_poc_nb,l_current_poc_remaining; + OPJ_UINT32 l_chunk_size; + OPJ_UINT32 l_tmp; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_poc_t *l_current_poc = 00; + OPJ_UINT32 l_comp_room; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_image; + l_nb_comp = l_image->numcomps; + if + (l_nb_comp <= 256) + { + l_comp_room = 1; + } + else + { + l_comp_room = 2; + } + l_chunk_size = 5 + 2 * l_comp_room; + l_current_poc_nb = p_header_size / l_chunk_size; + l_current_poc_remaining = p_header_size % l_chunk_size; + + if + ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading POC marker\n"); + return false; + } + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH) ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0; + l_current_poc_nb += l_old_poc_nb; + assert(l_current_poc_nb < 32); + + /* now poc is in use.*/ + l_tcp->POC = 1; + + l_current_poc = &l_tcp->pocs[l_old_poc_nb]; + for + (i = l_old_poc_nb; i < l_current_poc_nb; ++i) + { + opj_read_bytes(p_header_data,&(l_current_poc->resno0),1); /* RSpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data,&(l_current_poc->compno0),l_comp_room); /* CSpoc_i */ + p_header_data+=l_comp_room; + opj_read_bytes(p_header_data,&(l_current_poc->layno1),2); /* LYEpoc_i */ + p_header_data+=2; + opj_read_bytes(p_header_data,&(l_current_poc->resno1),1); /* REpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data,&(l_current_poc->compno1),l_comp_room); /* CEpoc_i */ + p_header_data+=l_comp_room; + opj_read_bytes(p_header_data,&l_tmp,1); /* Ppoc_i */ + ++p_header_data; + l_current_poc->prg = (OPJ_PROG_ORDER) l_tmp; + /* make sure comp is in acceptable bounds */ + l_current_poc->compno1 = uint_min(l_current_poc->compno1, l_nb_comp); + ++l_current_poc; + } + l_tcp->numpocs = l_current_poc_nb - 1; + return true; +} + +/** + * Writes the RGN marker (Region Of Interest) + * + * @param p_tile_no the tile to output + * @param p_comp_no the component to output + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_rgn( + opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_rgn_size; + opj_image_t *l_image = 00; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_UINT32 l_comp_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + l_nb_comp = l_image->numcomps; + + if + (l_nb_comp <= 256) + { + l_comp_room = 1; + } + else + { + l_comp_room = 2; + } + l_rgn_size = 6 + l_comp_room; + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data,J2K_MS_RGN,2); /* RGN */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_rgn_size-2,2); /* Lrgn */ + l_current_data += 2; + opj_write_bytes(l_current_data,p_comp_no,l_comp_room); /* Crgn */ + l_current_data+=l_comp_room; + opj_write_bytes(l_current_data, 0,1); /* Srgn */ + ++l_current_data; + opj_write_bytes(l_current_data, l_tccp->roishift,1); /* SPrgn */ + ++l_current_data; + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_rgn_size,p_manager) != l_rgn_size) + { + return false; + } + return true; +} + +/** + * Reads a RGN marker (Region Of Interest) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_rgn ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + opj_image_t * l_image = 00; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_comp_room; + OPJ_UINT32 l_comp_no; + OPJ_UINT32 l_roi_sty; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_image; + l_nb_comp = l_image->numcomps; + if + (l_nb_comp <= 256) + { + l_comp_room = 1; + } + else + { + l_comp_room = 2; + } + if + (p_header_size != 2 + l_comp_room) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); + return false; + } + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_TPH) ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; + + opj_read_bytes(p_header_data,&l_comp_no,l_comp_room); /* Crgn */ + p_header_data+=l_comp_room; + opj_read_bytes(p_header_data,&l_roi_sty,1); /* Srgn */ + ++p_header_data; + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + /* totlen is negative or larger than the bytes left!!! */ + if (compno >= numcomps) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: bad component number in RGN (%d when there are only %d)\n", + compno, numcomps); + if (!JPWL_ASSUME || JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + } + }; +#endif /* USE_JPWL */ + + opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&(l_tcp->tccps[l_comp_no].roishift)),1); /* SPrgn */ + ++p_header_data; + return true; + +} + +/** + * Writes the TLM marker (Tile Length Marker) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_tlm( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tlm_size; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tlm_size = 6 + (5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + if + (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) + { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_tlm_size); + if + (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size; + } + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* change the way data is written to avoid seeking if possible */ + // TODO + p_j2k->m_specific_param.m_encoder.m_tlm_start = opj_stream_tell(p_stream); + + opj_write_bytes(l_current_data,J2K_MS_TLM,2); /* TLM */ + l_current_data += 2; + opj_write_bytes(l_current_data,l_tlm_size-2,2); /* Lpoc */ + l_current_data += 2; + opj_write_bytes(l_current_data,0,1); /* Ztlm=0*/ + ++l_current_data; + opj_write_bytes(l_current_data,0x50,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + ++l_current_data; + /* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */ + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_tlm_size,p_manager) != l_tlm_size) + { + return false; + } + return true; +} + +/** + * Reads a TLM marker (Tile Length Marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_tlm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, l_tot_num_tp, l_tot_num_tp_remaining, l_quotient, l_Ptlm_size; + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size < 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return false; + } + p_header_size -= 2; + + + opj_read_bytes(p_header_data,&l_Ztlm,1); /* Ztlm */ + ++p_header_data; + opj_read_bytes(p_header_data,&l_Stlm,1); /* Stlm */ + ++p_header_data; + + l_ST = ((l_Stlm >> 4) & 0x3); + l_SP = (l_Stlm >> 6) & 0x1; + + l_Ptlm_size = (l_SP + 1) * 2; + l_quotient = l_Ptlm_size + l_ST; + + l_tot_num_tp = p_header_size / l_quotient; + l_tot_num_tp_remaining = p_header_size % l_quotient; + if + (l_tot_num_tp_remaining != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return false; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_tot_num_tp; ++i) + { + opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i + p_header_data += l_ST; + opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i + p_header_data += l_Ptlm_size; + }*/ + return true; +} + +/** + * Reads a CRG marker (Component registration) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_crg ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_nb_comp = p_j2k->m_image->numcomps; + + if + (p_header_size != l_nb_comp *4) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading CRG marker\n"); + return false; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_nb_comp; ++i) + { + opj_read_bytes(p_header_data,&l_Xcrg_i,2); // Xcrg_i + p_header_data+=2; + opj_read_bytes(p_header_data,&l_Ycrg_i,2); // Xcrg_i + p_header_data+=2; + } + */ + return true; +} + +/** + * Reads a PLM marker (Packet length, main header marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_plm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + opj_read_bytes(p_header_data,&l_Zplm,1); // Zplm + ++p_header_data; + --p_header_size; + + while + (p_header_size > 0) + { + opj_read_bytes(p_header_data,&l_Nplm,1); // Nplm + ++p_header_data; + p_header_size -= (1+l_Nplm); + if + (p_header_size < 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + for + (i = 0; i < l_Nplm; ++i) + { + opj_read_bytes(p_header_data,&l_tmp,1); // Iplm_ij + ++p_header_data; + // take only the last seven bytes + l_packet_len |= (l_tmp & 0x7f); + if + (l_tmp & 0x80) + { + l_packet_len <<= 7; + } + else + { + // store packet length and proceed to next packet + l_packet_len = 0; + } + } + if + (l_packet_len != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + } + */ + return true; +} + +/** + * Reads a PLT marker (Packet length, tile-part header) + * + * @param p_header_data the data contained in the PLT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PLT marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_plt ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_Zplt, l_tmp, l_packet_len = 0, i; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + + opj_read_bytes(p_header_data,&l_Zplt,1); // Zplt + ++p_header_data; + --p_header_size; + for + (i = 0; i < p_header_size; ++i) + { + opj_read_bytes(p_header_data,&l_tmp,1); // Iplm_ij + ++p_header_data; + // take only the last seven bytes + l_packet_len |= (l_tmp & 0x7f); + if + (l_tmp & 0x80) + { + l_packet_len <<= 7; + } + else + { + // store packet length and proceed to next packet + l_packet_len = 0; + } + } + if + (l_packet_len != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + return true; +} + +/** + * Reads a PPM marker (Packed packet headers, main header) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_ppm ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + + opj_cp_t *l_cp = 00; + OPJ_UINT32 l_remaining_data, l_Z_ppm, l_N_ppm; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); + return false; + } + l_cp = &(p_j2k->m_cp); + l_cp->ppm = 1; + + opj_read_bytes(p_header_data,&l_Z_ppm,1); /* Z_ppm */ + ++p_header_data; + --p_header_size; + + // first PPM marker + if + (l_Z_ppm == 0) + { + if + (p_header_size < 4) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n"); + return false; + } + // read a N_ppm + opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm */ + p_header_data+=4; + p_header_size-=4; + /* First PPM marker */ + l_cp->ppm_len = l_N_ppm; + l_cp->ppm_data_size = 0; + l_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_cp->ppm_len); + l_cp->ppm_data = l_cp->ppm_buffer; + if + (l_cp->ppm_buffer == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n"); + return false; + } + memset(l_cp->ppm_buffer,0,l_cp->ppm_len); + } + + while + (true) + { + if + (l_cp->ppm_data_size == l_cp->ppm_len) + { + if + (p_header_size >= 4) + { + // read a N_ppm + opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm */ + p_header_data+=4; + p_header_size-=4; + l_cp->ppm_len += l_N_ppm ; + l_cp->ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len); + l_cp->ppm_data = l_cp->ppm_buffer; + if + (l_cp->ppm_buffer == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n"); + return false; + } + memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm); + } + else + { + return false; + } + } + l_remaining_data = l_cp->ppm_len - l_cp->ppm_data_size; + if + (l_remaining_data <= p_header_size) + { + /* we must store less information than available in the packet */ + memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , l_remaining_data); + l_cp->ppm_data_size = l_cp->ppm_len; + p_header_size -= l_remaining_data; + p_header_data += l_remaining_data; + } + else + { + memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , p_header_size); + l_cp->ppm_data_size += p_header_size; + p_header_data += p_header_size; + p_header_size = 0; + break; + } + } + return true; +} + +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_ppt ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_Z_ppt; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size < 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n"); + return false; + } + + l_cp = &(p_j2k->m_cp); + l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]); + l_tcp->ppt = 1; + + opj_read_bytes(p_header_data,&l_Z_ppt,1); /* Z_ppt */ + ++p_header_data; + --p_header_size; + + // first PPM marker + if + (l_Z_ppt == 0) + { + /* First PPM marker */ + l_tcp->ppt_len = p_header_size; + l_tcp->ppt_data_size = 0; + l_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_tcp->ppt_len); + l_tcp->ppt_data = l_tcp->ppt_buffer; + if + (l_tcp->ppt_buffer == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading PPT marker\n"); + return false; + } + memset(l_tcp->ppt_buffer,0,l_tcp->ppt_len); + } + else + { + l_tcp->ppt_len += p_header_size; + l_tcp->ppt_buffer = (OPJ_BYTE *) opj_realloc(l_tcp->ppt_buffer,l_tcp->ppt_len); + if + (l_tcp->ppt_buffer == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading PPT marker\n"); + return false; + } + l_tcp->ppt_data = l_tcp->ppt_buffer; + memset(l_tcp->ppt_buffer+l_tcp->ppt_data_size,0,p_header_size); + } + memcpy(l_tcp->ppt_buffer+l_tcp->ppt_data_size,p_header_data,p_header_size); + l_tcp->ppt_data_size += p_header_size; + return true; +} + +/** + * Writes the SOT marker (Start of tile-part) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_sot( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + const struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_write_bytes(p_data,J2K_MS_SOT,2); /* SOT */ + p_data += 2; + + opj_write_bytes(p_data,10,2); /* Lsot */ + p_data += 2; + + opj_write_bytes(p_data, p_j2k->m_current_tile_number,2); /* Isot */ + p_data += 2; + + /* Psot */ + p_data += 4; + + opj_write_bytes(p_data, p_j2k->m_specific_param.m_encoder.m_current_tile_part_number,1); /* TPsot */ + ++p_data; + + opj_write_bytes(p_data, p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts,1); /* TNsot */ + ++p_data; + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2); +#endif /* USE_JPWL */ + + * p_data_written = 12; + return true; +} + +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_sot ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + struct opj_event_mgr * p_manager + ) +{ + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tot_len, l_num_parts = 0; + OPJ_UINT32 l_current_part; + OPJ_UINT32 l_tile_x,l_tile_y; + + // preconditions + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_header_size != 8) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); + return false; + } + l_cp = &(p_j2k->m_cp); + opj_read_bytes(p_header_data,&(p_j2k->m_current_tile_number),2); /* Isot */ + p_header_data+=2; + + + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_tile_x = p_j2k->m_current_tile_number % l_cp->tw; + l_tile_y = p_j2k->m_current_tile_number / l_cp->tw; + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + + static int backup_tileno = 0; + + /* tileno is negative or larger than the number of tiles!!! */ + if ((tileno < 0) || (tileno > (cp->tw * cp->th))) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (cp->tw * cp->th)); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + tileno = backup_tileno; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting tile number to %d\n", + tileno); + } + + /* keep your private count of tiles */ + backup_tileno++; + }; +#endif /* USE_JPWL */ + + /* look for the tile in the list of already processed tile (in parts). */ + /* Optimization possible here with a more complex data structure and with the removing of tiles */ + /* since the time taken by this function can only grow at the time */ + + opj_read_bytes(p_header_data,&l_tot_len,4); /* Psot */ + p_header_data+=4; + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + + /* totlen is negative or larger than the bytes left!!! */ + if ((totlen < 0) || (totlen > (p_stream_numbytesleft(p_stream) + 8))) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + totlen, p_stream_numbytesleft(p_stream) + 8); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return; + } + /* we try to correct */ + totlen = 0; + opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" + "- setting Psot to %d => assuming it is the last tile\n", + totlen); + } + + }; +#endif /* USE_JPWL */ + + if + (!l_tot_len) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot read data with no size known, giving up\n"); + return false; + } + + opj_read_bytes(p_header_data,&l_current_part ,1); /* Psot */ + ++p_header_data; + + opj_read_bytes(p_header_data,&l_num_parts ,1); /* Psot */ + ++p_header_data; + + if + (l_num_parts != 0) + { + l_tcp->m_nb_tile_parts = l_num_parts; + } + if + (l_tcp->m_nb_tile_parts) + { + if + (l_tcp->m_nb_tile_parts == (l_current_part + 1)) + { + p_j2k->m_specific_param.m_decoder.m_can_decode = 1; + } + } + p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - 12; + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPH; + p_j2k->m_specific_param.m_decoder.m_skip_data = + (l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x) + || (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x) + || (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y) + || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); + /* Index */ + + /* move this onto a separate method to call before reading any SOT */ + /*if + TODO + (p_j2k->cstr_info) + { + if + (l_tcp->first) + { + if + (tileno == 0) + { + p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; + } + p_j2k->cstr_info->tile[tileno].tileno = tileno; + p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; + p_j2k->cstr_info->tile[tileno].num_tps = numparts; + if + (numparts) + { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); + } + else + { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) + } + } + else + { + p_j2k->cstr_info->tile[tileno].end_pos += totlen; + } + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; + }*/ + return true; +} + +/** + * Writes the SOD marker (Start of data) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_sod( + opj_j2k_t *p_j2k, + struct opj_tcd * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + const struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_tcp_t *l_tcp = 00; + opj_codestream_info_t *l_cstr_info = 00; + opj_cp_t *l_cp = 00; + + OPJ_UINT32 l_size_tile; + OPJ_UINT32 l_remaining_data; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_write_bytes(p_data,J2K_MS_SOD,2); /* SOD */ + p_data += 2; + + /* make room for the EOF marker */ + l_remaining_data = p_total_data_size - 4; + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_cstr_info = p_j2k->cstr_info; + + /* update tile coder */ + p_tile_coder->tp_num = p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number ; + p_tile_coder->cur_tp_num = p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + l_size_tile = l_cp->th * l_cp->tw; + + /* INDEX >> */ + if + (l_cstr_info) + { + if + (!p_j2k->m_specific_param.m_encoder.m_current_tile_part_number ) + { + //TODO cstr_info->tile[p_j2k->m_current_tile_number].end_header = p_stream_tell(p_stream) + p_j2k->pos_correction - 1; + l_cstr_info->tile[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; + } + else + { + /* + TODO + if + (cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno - 1].end_pos < p_stream_tell(p_stream)) + { + cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno].start_pos = p_stream_tell(p_stream); + }*/ + + } + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2); +#endif /* USE_JPWL */ + /* <m_specific_param.m_encoder.m_current_tile_part_number == 0) + { + p_tile_coder->tcd_image->tiles->packno = 0; + if + (l_cstr_info) + { + l_cstr_info->packno = 0; + } + } + *p_data_written = 0; + if + (! tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, p_data, p_data_written, l_remaining_data , l_cstr_info)) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); + return false; + } + *p_data_written += 2; + return true; +} + +/** + * Updates the Tile Length Marker. + */ +void j2k_update_tlm ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_part_size + ) +{ + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_j2k->m_current_tile_number,1); /* PSOT */ + ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current; + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_tile_part_size,4); /* PSOT */ + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 4; +} + + +/** + * Reads a SOD marker (Start Of Data) + * + * @param p_header_data the data contained in the SOD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the SOD marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_sod ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_current_read_size; + opj_codestream_info_t * l_cstr_info = 00; + OPJ_BYTE ** l_current_data = 00; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 * l_tile_len = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; + l_cstr_info = p_j2k->cstr_info; + + l_current_data = &(l_tcp->m_data); + l_tile_len = &l_tcp->m_data_size; + + if + (! *l_current_data) + { + *l_current_data = (OPJ_BYTE*) my_opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length); + } + else + { + *l_current_data = (OPJ_BYTE*) my_opj_realloc(*l_current_data, *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length); + } + if + (*l_current_data == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile\n"); + return false; + } + + /* Index */ + if + (l_cstr_info) + { + OPJ_SIZE_T l_current_pos = opj_stream_tell(p_stream)-1; + l_cstr_info->tile[p_j2k->m_current_tile_number].tp[p_j2k->m_specific_param.m_encoder.m_current_tile_part_number].tp_end_header = l_current_pos; + if + (p_j2k->m_specific_param.m_encoder.m_current_tile_part_number == 0) + { + l_cstr_info->tile[p_j2k->m_current_tile_number].end_header = l_current_pos; + } + l_cstr_info->packno = 0; + } + l_current_read_size = opj_stream_read_data(p_stream, *l_current_data + *l_tile_len , p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager); + if + (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) + { + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_NEOC; + } + else + { + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPHSOT; + } + *l_tile_len += l_current_read_size; + return true; +} + +/** + * Writes the EOC marker (End of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_eoc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_header_tile_data,J2K_MS_EOC,2); /* EOC */ + + +/* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + j2k_add_marker(p_j2k->cstr_info, J2K_MS_EOC, p_stream_tell(p_stream) - 2, 2); +#endif /* USE_JPWL */ + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,2,p_manager) != 2) + { + return false; + } + if + (! opj_stream_flush(p_stream,p_manager)) + { + return false; + } + return true; +} + + +/** + * Inits the Info + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_init_info( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_codestream_info_t * l_cstr_info = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + l_cstr_info = p_j2k->cstr_info; + + if + (l_cstr_info) + { + OPJ_UINT32 compno; + l_cstr_info->tile = (opj_tile_info_t *) opj_malloc(p_j2k->m_cp.tw * p_j2k->m_cp.th * sizeof(opj_tile_info_t)); + l_cstr_info->image_w = p_j2k->m_image->x1 - p_j2k->m_image->x0; + l_cstr_info->image_h = p_j2k->m_image->y1 - p_j2k->m_image->y0; + l_cstr_info->prog = (&p_j2k->m_cp.tcps[0])->prg; + l_cstr_info->tw = p_j2k->m_cp.tw; + l_cstr_info->th = p_j2k->m_cp.th; + l_cstr_info->tile_x = p_j2k->m_cp.tdx; /* new version parser */ + l_cstr_info->tile_y = p_j2k->m_cp.tdy; /* new version parser */ + l_cstr_info->tile_Ox = p_j2k->m_cp.tx0; /* new version parser */ + l_cstr_info->tile_Oy = p_j2k->m_cp.ty0; /* new version parser */ + l_cstr_info->numcomps = p_j2k->m_image->numcomps; + l_cstr_info->numlayers = (&p_j2k->m_cp.tcps[0])->numlayers; + l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(p_j2k->m_image->numcomps * sizeof(OPJ_INT32)); + for (compno=0; compno < p_j2k->m_image->numcomps; compno++) { + l_cstr_info->numdecompos[compno] = (&p_j2k->m_cp.tcps[0])->tccps->numresolutions - 1; + } + l_cstr_info->D_max = 0.0; /* ADD Marcela */ + l_cstr_info->main_head_start = opj_stream_tell(p_stream); /* position of SOC */ + l_cstr_info->maxmarknum = 100; + l_cstr_info->marker = (opj_marker_info_t *) opj_malloc(l_cstr_info->maxmarknum * sizeof(opj_marker_info_t)); + l_cstr_info->marknum = 0; + } + return j2k_calculate_tp(p_j2k,&(p_j2k->m_cp),&p_j2k->m_specific_param.m_encoder.m_total_tile_parts,p_j2k->m_image,p_manager); +} + +/** + * Creates a tile-coder decoder. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_create_tcd( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + p_j2k->m_tcd = tcd_create(false); + if + (! p_j2k->m_tcd) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n"); + return false; + } + if + (! tcd_init(p_j2k->m_tcd,p_j2k->m_image,&p_j2k->m_cp)) + { + tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + return false; + } + return true; +} + +OPJ_FLOAT32 get_tp_stride (opj_tcp_t * p_tcp) +{ + return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14); +} + +OPJ_FLOAT32 get_default_stride (opj_tcp_t * p_tcp) +{ + return 0; +} + +/** + * Updates the rates of the tcp. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_update_rates( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + opj_cp_t * l_cp = 00; + opj_image_t * l_image = 00; + opj_tcp_t * l_tcp = 00; + opj_image_comp_t * l_img_comp = 00; + + OPJ_UINT32 i,j,k; + OPJ_INT32 l_x0,l_y0,l_x1,l_y1; + OPJ_FLOAT32 * l_rates = 0; + OPJ_FLOAT32 l_sot_remove; + OPJ_UINT32 l_bits_empty, l_size_pixel; + OPJ_UINT32 l_tile_size = 0; + OPJ_UINT32 l_last_res; + OPJ_FLOAT32 (* l_tp_stride_func)(opj_tcp_t *) = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + + l_cp = &(p_j2k->m_cp); + l_image = p_j2k->m_image; + l_tcp = l_cp->tcps; + + l_bits_empty = 8 * l_image->comps->dx * l_image->comps->dy; + l_size_pixel = l_image->numcomps * l_image->comps->prec; + l_sot_remove = ((OPJ_FLOAT32) opj_stream_tell(p_stream)) / (l_cp->th * l_cp->tw); + + if + (l_cp->m_specific_param.m_enc.m_tp_on) + { + l_tp_stride_func = get_tp_stride; + } + else + { + l_tp_stride_func = get_default_stride; + } + + for + (i=0;ith;++i) + { + for + (j=0;jtw;++j) + { + OPJ_FLOAT32 l_offset = ((*l_tp_stride_func)(l_tcp)) / l_tcp->numlayers; + /* 4 borders of the tile rescale on the image if necessary */ + l_x0 = int_max(l_cp->tx0 + j * l_cp->tdx, l_image->x0); + l_y0 = int_max(l_cp->ty0 + i * l_cp->tdy, l_image->y0); + l_x1 = int_min(l_cp->tx0 + (j + 1) * l_cp->tdx, l_image->x1); + l_y1 = int_min(l_cp->ty0 + (i + 1) * l_cp->tdy, l_image->y1); + l_rates = l_tcp->rates; + + /* Modification of the RATE >> */ + if + (*l_rates) + { + *l_rates = (( (float) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0))) + / + ((*l_rates) * l_bits_empty) + ) + - + l_offset; + } + ++l_rates; + for + (k = 1; k < l_tcp->numlayers; ++k) + { + if + (*l_rates) + { + *l_rates = (( (OPJ_FLOAT32) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0))) + / + ((*l_rates) * l_bits_empty) + ) + - + l_offset; + } + ++l_rates; + } + ++l_tcp; + } + } + + l_tcp = l_cp->tcps; + for + (i=0;ith;++i) + { + for + (j=0;jtw;++j) + { + l_rates = l_tcp->rates; + if + (*l_rates) + { + *l_rates -= l_sot_remove; + if + (*l_rates < 30) + { + *l_rates = 30; + } + } + ++l_rates; + l_last_res = l_tcp->numlayers - 1; + for + (k = 1; k < l_last_res; ++k) + { + if + (*l_rates) + { + *l_rates -= l_sot_remove; + if + (*l_rates < *(l_rates - 1) + 10) + { + *l_rates = (*(l_rates - 1)) + 20; + } + } + ++l_rates; + } + if + (*l_rates) + { + *l_rates -= (l_sot_remove + 2.f); + if + (*l_rates < *(l_rates - 1) + 10) + { + *l_rates = (*(l_rates - 1)) + 20; + } + } + ++l_tcp; + } + } + + l_img_comp = l_image->comps; + l_tile_size = 0; + for + (i=0;inumcomps;++i) + { + l_tile_size += ( uint_ceildiv(l_cp->tdx,l_img_comp->dx) + * + uint_ceildiv(l_cp->tdy,l_img_comp->dy) + * + l_img_comp->prec + ); + ++l_img_comp; + } + + l_tile_size = (OPJ_UINT32) (l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */ + l_tile_size += j2k_get_specific_header_sizes(p_j2k); + + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = l_tile_size; + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = (OPJ_BYTE *) my_opj_malloc(p_j2k->m_specific_param.m_encoder.m_encoded_tile_size); + if + (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data == 00) + { + return false; + } + if + (l_cp->m_specific_param.m_enc.m_cinema) + { + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = (OPJ_BYTE *) opj_malloc(5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + if + (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) + { + return false; + } + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer; + } + return true; +} + +/** + * Reads a EOC marker (End Of Codestream) + * + * @param p_header_data the data contained in the SOD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the SOD marker. + * @param p_manager the user event manager. +*/ +bool j2k_read_eoc ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 i; + opj_tcd_t * l_tcd = 00; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_tcp = 00; + bool l_success; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + + l_tcd = tcd_create(true); + if + (l_tcd == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return false; + } + + + + for + (i = 0; i < l_nb_tiles; ++i) + { + if + (l_tcp->m_data) + { + if + (! tcd_init_decode_tile(l_tcd, i)) + { + tcd_destroy(l_tcd); + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return false; + } + l_success = tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, p_j2k->cstr_info); + /* cleanup */ + if + (! l_success) + { + p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; + break; + } + } + j2k_tcp_destroy(l_tcp); + ++l_tcp; + } + tcd_destroy(l_tcd); + return true; +} + +/** + * Writes the image components. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_image_components( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 compno; + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + for + (compno = 1; compno < p_j2k->m_image->numcomps; ++compno) + { + if + (! j2k_write_coc(p_j2k,compno,p_stream, p_manager)) + { + return false; + } + if + (! j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) + { + return false; + } + } + return true; +} + +/** + * Writes regions of interests. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_regions( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 compno; + const opj_tccp_t *l_tccp = 00; + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tccp = p_j2k->m_cp.tcps->tccps; + for + (compno = 0; compno < p_j2k->m_image->numcomps; ++compno) + { + if + (l_tccp->roishift) + { + if + (! j2k_write_rgn(p_j2k,0,compno,p_stream,p_manager)) + { + return false; + } + } + ++l_tccp; + } + return true; +} +/** + * Writes the updated tlm. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_write_updated_tlm( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 l_tlm_size; + OPJ_SIZE_T l_tlm_position, l_current_position; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts; + l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start; + l_current_position = opj_stream_tell(p_stream); + + if + (! opj_stream_seek(p_stream,l_tlm_position,p_manager)) + { + return false; + } + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer,l_tlm_size,p_manager) != l_tlm_size) + { + return false; + } + if + (! opj_stream_seek(p_stream,l_current_position,p_manager)) + { + return false; + } + return true; +} + +/** + * Ends the encoding, i.e. frees memory. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_end_encoding( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + + if + (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 0; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 0; + } + if + (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 0; + } + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = 0; + + return true; +} + +/** + * Gets the offset of the header. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +bool j2k_get_end_header( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + p_j2k->cstr_info->main_head_end = opj_stream_tell(p_stream); + return true; +} + + + + +/** + * Reads an unknown marker + * + * @param p_stream the stream object to read from. + * @param p_j2k the jpeg2000 codec. + * @param p_manager the user event manager. + * + * @return true if the marker could be deduced. +*/ +bool j2k_read_unk ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_BYTE l_data [2]; + OPJ_UINT32 l_unknown_size; + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); + +#ifdef USE_JPWL + if (p_j2k->m_cp->correct) { + OPJ_INT32 m = 0, id, i; + OPJ_INT32 min_id = 0, min_dist = 17, cur_dist = 0, tmp_id; + p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); + id = p_stream_read(p_j2k->p_stream, 2); + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "JPWL: really don't know this marker %x\n", + id); + if (!JPWL_ASSUME) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "- possible synch loss due to uncorrectable codestream errors => giving up\n"); + return; + } + /* OK, activate this at your own risk!!! */ + /* we look for the marker at the minimum hamming distance from this */ + while (j2k_dec_mstab[m].id) { + + /* 1's where they differ */ + tmp_id = j2k_dec_mstab[m].id ^ id; + + /* compute the hamming distance between our id and the current */ + cur_dist = 0; + for (i = 0; i < 16; i++) { + if ((tmp_id >> i) & 0x0001) { + cur_dist++; + } + } + + /* if current distance is smaller, set the minimum */ + if (cur_dist < min_dist) { + min_dist = cur_dist; + min_id = j2k_dec_mstab[m].id; + } + + /* jump to the next marker */ + m++; + } + + /* do we substitute the marker? */ + if (min_dist < JPWL_MAXIMUM_HAMMING) { + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "- marker %x is at distance %d from the read %x\n", + min_id, min_dist, id); + opj_event_msg(p_j2k->cinfo, EVT_ERROR, + "- trying to substitute in place and crossing fingers!\n"); + p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); + p_stream_write(p_j2k->p_stream, min_id, 2); + + /* rewind */ + p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); + + } + + }; +#endif /* USE_JPWL */ + if + (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); + return false; + } + opj_read_bytes(l_data,&l_unknown_size,2); + if + (l_unknown_size < 2) + { + return false; + } + l_unknown_size-=2; + + if + (opj_stream_skip(p_stream,l_unknown_size,p_manager) != l_unknown_size) + { + return false; + } + return true; +} + +/** + * Reads the lookup table containing all the marker, status and action, and returns the handler associated + * with the marker value. + * @param p_id Marker value to look up + * + * @return the handler associated with the id. +*/ +const opj_dec_memory_marker_handler_t * j2k_get_marker_handler (OPJ_UINT32 p_id) +{ + const opj_dec_memory_marker_handler_t *e; + for + (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) + { + if + (e->id == p_id) + { + break; + } + } + return e; +} + +/** + * Destroys a tile coding parameter structure. + * + * @param p_tcp the tile coding parameter to destroy. + */ +void j2k_tcp_destroy (opj_tcp_t *p_tcp) +{ + if + (p_tcp == 00) + { + return; + } + if + (p_tcp->ppt_buffer != 00) + { + opj_free(p_tcp->ppt_buffer); + p_tcp->ppt_buffer = 00; + } + if + (p_tcp->tccps != 00) + { + opj_free(p_tcp->tccps); + p_tcp->tccps = 00; + } + if + (p_tcp->m_mct_coding_matrix != 00) + { + opj_free(p_tcp->m_mct_coding_matrix); + p_tcp->m_mct_coding_matrix = 00; + } + if + (p_tcp->m_mct_decoding_matrix != 00) + { + opj_free(p_tcp->m_mct_decoding_matrix); + p_tcp->m_mct_decoding_matrix = 00; + } + if + (p_tcp->m_mcc_records) + { + opj_free(p_tcp->m_mcc_records); + p_tcp->m_mcc_records = 00; + p_tcp->m_nb_max_mcc_records = 0; + p_tcp->m_nb_mcc_records = 0; + } + if + (p_tcp->m_mct_records) + { + opj_mct_data_t * l_mct_data = p_tcp->m_mct_records; + OPJ_UINT32 i; + for + (i=0;im_nb_mct_records;++i) + { + if + (l_mct_data->m_data) + { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + } + ++l_mct_data; + } + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = 00; + } + + if + (p_tcp->mct_norms != 00) + { + opj_free(p_tcp->mct_norms); + p_tcp->mct_norms = 00; + } + if + (p_tcp->m_data) + { + opj_free(p_tcp->m_data); + p_tcp->m_data = 00; + } +} + +/** + * Destroys a coding parameter structure. + * + * @param p_cp the coding parameter to destroy. + */ +void j2k_cp_destroy (opj_cp_t *p_cp) +{ + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_current_tile = 00; + OPJ_UINT32 i; + + if + (p_cp == 00) + { + return; + } + if + (p_cp->tcps != 00) + { + l_current_tile = p_cp->tcps; + l_nb_tiles = p_cp->th * p_cp->tw; + + for + (i = 0; i < l_nb_tiles; ++i) + { + j2k_tcp_destroy(l_current_tile); + ++l_current_tile; + } + opj_free(p_cp->tcps); + p_cp->tcps = 00; + } + if + (p_cp->ppm_buffer != 00) + { + opj_free(p_cp->ppm_buffer); + p_cp->ppm_buffer = 00; + } + if + (p_cp->comment != 00) + { + opj_free(p_cp->comment); + p_cp->comment = 00; + } + if + (! p_cp->m_is_decoder) + { + if + (p_cp->m_specific_param.m_enc.m_matrice) + { + opj_free(p_cp->m_specific_param.m_enc.m_matrice); + p_cp->m_specific_param.m_enc.m_matrice = 00; + } + } +} + +/* ----------------------------------------------------------------------- */ +/* J2K / JPT decoder interface */ +/* ----------------------------------------------------------------------- */ +/** + * Creates a J2K decompression structure. + * + * @return a handle to a J2K decompressor if successful, NULL otherwise. +*/ +opj_j2k_t* j2k_create_decompress() +{ + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_malloc(sizeof(opj_j2k_t)); + if + (!l_j2k) + { + return 00; + } + memset(l_j2k,0,sizeof(opj_j2k_t)); + l_j2k->m_is_decoder = 1; + l_j2k->m_cp.m_is_decoder = 1; + l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_malloc(sizeof(opj_tcp_t)); + if + (!l_j2k->m_specific_param.m_decoder.m_default_tcp) + { + opj_free(l_j2k); + return 00; + } + memset(l_j2k->m_specific_param.m_decoder.m_default_tcp,0,sizeof(opj_tcp_t)); + + l_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE *) opj_malloc(J2K_DEFAULT_HEADER_SIZE); + if + (! l_j2k->m_specific_param.m_decoder.m_header_data) + { + j2k_destroy(l_j2k); + return 00; + } + l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE; + + // validation list creation + l_j2k->m_validation_list = opj_procedure_list_create(); + if + (! l_j2k->m_validation_list) + { + j2k_destroy(l_j2k); + return 00; + } + + // execution list creation + l_j2k->m_procedure_list = opj_procedure_list_create(); + if + (! l_j2k->m_procedure_list) + { + j2k_destroy(l_j2k); + return 00; + } + return l_j2k; +} + +opj_j2k_t* j2k_create_compress() +{ + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_malloc(sizeof(opj_j2k_t)); + if + (!l_j2k) + { + return 00; + } + memset(l_j2k,0,sizeof(opj_j2k_t)); + l_j2k->m_is_decoder = 0; + l_j2k->m_cp.m_is_decoder = 0; + + l_j2k->m_specific_param.m_encoder.m_header_tile_data = (OPJ_BYTE *) opj_malloc(J2K_DEFAULT_HEADER_SIZE); + if + (! l_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + j2k_destroy(l_j2k); + return 00; + } + l_j2k->m_specific_param.m_encoder.m_header_tile_data_size = J2K_DEFAULT_HEADER_SIZE; + + // validation list creation + l_j2k->m_validation_list = opj_procedure_list_create(); + if + (! l_j2k->m_validation_list) + { + j2k_destroy(l_j2k); + return 00; + } + + // execution list creation + l_j2k->m_procedure_list = opj_procedure_list_create(); + if + (! l_j2k->m_procedure_list) + { + j2k_destroy(l_j2k); + return 00; + } + return l_j2k; +} + + +/** + * Destroys a jpeg2000 codec. + * + * @param p_j2k the jpeg20000 structure to destroy. + */ +void j2k_destroy (opj_j2k_t *p_j2k) +{ + if + (p_j2k == 00) + { + return; + } + + if + (p_j2k->m_is_decoder) + { + if + (p_j2k->m_specific_param.m_decoder.m_default_tcp != 00) + { + j2k_tcp_destroy(p_j2k->m_specific_param.m_decoder.m_default_tcp); + opj_free(p_j2k->m_specific_param.m_decoder.m_default_tcp); + p_j2k->m_specific_param.m_decoder.m_default_tcp = 00; + } + if + (p_j2k->m_specific_param.m_decoder.m_header_data != 00) + { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = 00; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + } + + } + else + { + if + (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 00; + } + if + (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 00; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 00; + } + if + (p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 00; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + } + } + tcd_destroy(p_j2k->m_tcd); + + j2k_cp_destroy(&(p_j2k->m_cp)); + memset(&(p_j2k->m_cp),0,sizeof(opj_cp_t)); + + opj_procedure_list_destroy(p_j2k->m_procedure_list); + p_j2k->m_procedure_list = 00; + + opj_procedure_list_destroy(p_j2k->m_validation_list); + p_j2k->m_procedure_list = 00; + + opj_free(p_j2k); +} + +/** + * Starts a compression scheme, i.e. validates the codec parameters, writes the header. + * + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream object. + * @param p_manager the user event manager. + * + * @return true if the codec is valid. + */ +bool j2k_start_compress( + opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager) +{ + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + p_j2k->m_image = p_image; + + + /* customization of the validation */ + j2k_setup_encoding_validation (p_j2k); + + /* validation of the parameters codec */ + if + (! j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) + { + return false; + } + + /* customization of the encoding */ + j2k_setup_header_writting(p_j2k); + + /* write header */ + if + (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) + { + return false; + } + return true; +} +/** + * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. + */ +void j2k_setup_header_reading (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_read_header_procedure); + + /* DEVELOPER CORNER, add your custom procedures */ + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_copy_default_tcp_and_create_tcd); + +} + +/** + * Sets up the procedures to do on decoding data. Developpers wanting to extend the library can add their own reading procedures. + */ +void j2k_setup_decoding (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_decode_tiles); + /* DEVELOPER CORNER, add your custom procedures */ + +} + +/** + * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. + */ +void j2k_setup_header_writting (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_init_info ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_soc ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_siz ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_cod ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_qcd ); + + + if + (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_image_components ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_tlm ); + if + (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == CINEMA4K_24) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_poc ); + } + } + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_regions); + + if + (p_j2k->m_cp.comment != 00) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_com); + } + + /* DEVELOPER CORNER, insert your custom procedures */ + if + (p_j2k->m_cp.rsiz & MCT) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_mct_data_group ); + } + /* End of Developer Corner */ + + if + (p_j2k->cstr_info) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_get_end_header ); + } + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_create_tcd); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_update_rates); +} + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +void j2k_setup_end_compress (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + + /* DEVELOPER CORNER, insert your custom procedures */ + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_eoc ); + if + (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) + { + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_updated_tlm); + } + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_write_epc ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_end_encoding ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,j2k_destroy_header_memory); +} + + + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +void j2k_setup_encoding_validation (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + opj_procedure_list_add_procedure(p_j2k->m_validation_list, j2k_build_encoder); + opj_procedure_list_add_procedure(p_j2k->m_validation_list, j2k_encoding_validation); + + + /* DEVELOPER CORNER, add your custom validation procedure */ + opj_procedure_list_add_procedure(p_j2k->m_validation_list, j2k_mct_validation); +} + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +void j2k_setup_decoding_validation (opj_j2k_t *p_j2k) +{ + // preconditions + assert(p_j2k != 00); + opj_procedure_list_add_procedure(p_j2k->m_validation_list, j2k_build_decoder); + opj_procedure_list_add_procedure(p_j2k->m_validation_list, j2k_decoding_validation); + /* DEVELOPER CORNER, add your custom validation procedure */ + +} + + +/** + * Excutes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param p_j2k the jpeg2000 codec to execute the procedures on. + * @param p_stream the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +bool j2k_exec ( + opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + bool (** l_procedure) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *) = 00; + bool l_result = true; + OPJ_UINT32 l_nb_proc, i; + + // preconditions + assert(p_procedure_list != 00); + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (bool (**) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + for + (i=0;im_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); + + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); + + if + ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) + { + opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); + return false; + } + if + ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) + { + opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); + return false; + } + + /* PARAMETER VALIDATION */ + return l_is_valid; +} + +/** + * The default decoding validation procedure without any extension. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool j2k_decoding_validation ( + opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + bool l_is_valid = true; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); + + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + /* make sure a procedure list is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); + + /* PARAMETER VALIDATION */ + return l_is_valid; +} + +/** + * The mct encoding validation procedure. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool j2k_mct_validation ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + bool l_is_valid = true; + OPJ_UINT32 i,j; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + if + ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) + { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; + for + (i=0;imct == 2) + { + opj_tccp_t * l_tccp = l_tcp->tccps; + l_is_valid &= (l_tcp->m_mct_coding_matrix != 00); + for + (j=0;jm_image->numcomps;++j) + { + l_is_valid &= ! (l_tccp->qmfbid & 1); + ++l_tccp; + } + } + ++l_tcp; + } + } + return l_is_valid; +} + +/** + * Builds the cp decoder parameters to use to decode tile. + */ +bool j2k_build_decoder ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + // add here initialization of cp + // copy paste of setup_decoder + return true; +} + +/** + * Builds the cp encoder parameters to use to encode tile. + */ +bool j2k_build_encoder ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + // add here initialization of cp + // copy paste of setup_encoder + return true; +} + +bool j2k_copy_default_tcp_and_create_tcd + ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_tcp_t * l_tcp = 00; + opj_tcp_t * l_default_tcp = 00; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 i,j; + opj_tccp_t *l_current_tccp = 00; + OPJ_UINT32 l_tccp_size; + OPJ_UINT32 l_mct_size; + opj_image_t * l_image; + OPJ_UINT32 l_mcc_records_size,l_mct_records_size; + opj_mct_data_t * l_src_mct_rec, *l_dest_mct_rec; + opj_simple_mcc_decorrelation_data_t * l_src_mcc_rec, *l_dest_mcc_rec; + OPJ_UINT32 l_offset; + + // preconditions in debug + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_image; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + l_tccp_size = l_image->numcomps * sizeof(opj_tccp_t); + l_default_tcp = p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_mct_size = l_image->numcomps * l_image->numcomps * sizeof(OPJ_FLOAT32); + for + (i=0;itccps; + memcpy(l_tcp,l_default_tcp, sizeof(opj_tcp_t)); + l_tcp->ppt = 0; + l_tcp->ppt_data = 00; + l_tcp->tccps = l_current_tccp; + if + (l_default_tcp->m_mct_decoding_matrix) + { + l_tcp->m_mct_decoding_matrix = opj_malloc(l_mct_size); + if + (! l_tcp->m_mct_decoding_matrix ) + { + return false; + } + memcpy(l_tcp->m_mct_decoding_matrix,l_default_tcp->m_mct_decoding_matrix,l_mct_size); + } + l_mct_records_size = l_default_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t); + l_tcp->m_mct_records = opj_malloc(l_mct_records_size); + if + (! l_tcp->m_mct_records) + { + return false; + } + memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records,l_mct_records_size); + l_src_mct_rec = l_default_tcp->m_mct_records; + l_dest_mct_rec = l_tcp->m_mct_records; + for + (j=0;jm_nb_mct_records;++j) + { + if + (l_src_mct_rec->m_data) + { + l_dest_mct_rec->m_data = opj_malloc(l_src_mct_rec->m_data_size); + if + (! l_dest_mct_rec->m_data) + { + return false; + } + memcpy(l_dest_mct_rec->m_data,l_src_mct_rec->m_data,l_src_mct_rec->m_data_size); + } + ++l_src_mct_rec; + ++l_dest_mct_rec; + } + l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t); + l_tcp->m_mcc_records = opj_malloc(l_mcc_records_size); + if + (! l_tcp->m_mcc_records) + { + return false; + } + memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size); + l_src_mcc_rec = l_default_tcp->m_mcc_records; + l_dest_mcc_rec = l_tcp->m_mcc_records; + for + (j=0;jm_nb_max_mcc_records;++j) + { + if + (l_src_mcc_rec->m_decorrelation_array) + { + l_offset = l_src_mcc_rec->m_decorrelation_array - l_default_tcp->m_mct_records; + l_dest_mcc_rec->m_decorrelation_array = l_tcp->m_mct_records + l_offset; + } + if + (l_src_mcc_rec->m_offset_array) + { + l_offset = l_src_mcc_rec->m_offset_array - l_default_tcp->m_mct_records; + l_dest_mcc_rec->m_offset_array = l_tcp->m_mct_records + l_offset; + } + ++l_src_mcc_rec; + ++l_dest_mcc_rec; + } + memcpy(l_current_tccp,l_default_tcp->tccps,l_tccp_size); + ++l_tcp; + } + p_j2k->m_tcd = tcd_create(true); + if + (! p_j2k->m_tcd ) + { + return false; + } + if + (! tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp))) + { + tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return false; + } + return true; +} + +/** + * Destroys the memory associated with the decoding of headers. + */ +bool j2k_destroy_header_memory ( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + // preconditions in debug + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + if + (p_j2k->m_specific_param.m_encoder.m_header_tile_data) + { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + return true; +} + +/** + * Sets up the decoder decoding parameters using user parameters. + * Decoding parameters are stored in p_j2k->m_cp. + * + * @param p_j2k J2K codec + * @param p_parameters decompression parameters + * @deprecated +*/ +void j2k_setup_decoder( + opj_j2k_t *p_j2k, + opj_dparameters_t *p_parameters + ) +{ + if + (p_j2k && p_parameters) + { + /* create and initialize the coding parameters structure */ + p_j2k->m_cp.m_specific_param.m_dec.m_reduce = p_parameters->cp_reduce; + p_j2k->m_cp.m_specific_param.m_dec.m_layer = p_parameters->cp_layer; + p_j2k->m_specific_param.m_decoder.m_discard_tiles = p_parameters->m_use_restrict_decode; + if + (p_parameters->m_use_restrict_decode) + { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = p_parameters->m_decode_start_x; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = p_parameters->m_decode_start_y; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = p_parameters->m_decode_end_x; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = p_parameters->m_decode_end_y; + } + +#ifdef USE_JPWL + cp->correct = parameters->jpwl_correct; + cp->exp_comps = parameters->jpwl_exp_comps; + cp->max_tiles = parameters->jpwl_max_tiles; +#endif /* USE_JPWL */ + } +} + +void j2k_setup_encoder(opj_j2k_t *p_j2k, opj_cparameters_t *parameters, opj_image_t *image, struct opj_event_mgr * p_manager) { + OPJ_UINT32 i, j, tileno, numpocs_tile; + opj_cp_t *cp = 00; + bool l_res; + if(!p_j2k || !parameters || ! image) { + return; + } + + /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ + cp = &(p_j2k->m_cp); + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + + /* + copy user encoding parameters + */ + cp->m_specific_param.m_enc.m_cinema = parameters->cp_cinema; + cp->m_specific_param.m_enc.m_max_comp_size = parameters->max_comp_size; + cp->rsiz = parameters->cp_rsiz; + cp->m_specific_param.m_enc.m_disto_alloc = parameters->cp_disto_alloc; + cp->m_specific_param.m_enc.m_fixed_alloc = parameters->cp_fixed_alloc; + cp->m_specific_param.m_enc.m_fixed_quality = parameters->cp_fixed_quality; + + /* mod fixed_quality */ + if + (parameters->cp_matrice) + { + size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(OPJ_INT32); + cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); + memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, array_size); + } + + /* tiles */ + cp->tdx = parameters->cp_tdx; + cp->tdy = parameters->cp_tdy; + + /* tile offset */ + cp->tx0 = parameters->cp_tx0; + cp->ty0 = parameters->cp_ty0; + + /* comment string */ + if(parameters->cp_comment) { + cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1); + if(cp->comment) { + strcpy(cp->comment, parameters->cp_comment); + } + } + + /* + calculate other encoding parameters + */ + + if (parameters->tile_size_on) { + cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; + } + + if + (parameters->tp_on) + { + cp->m_specific_param.m_enc.m_tp_flag = parameters->tp_flag; + cp->m_specific_param.m_enc.m_tp_on = 1; + } + +#ifdef USE_JPWL + /* + calculate JPWL encoding parameters + */ + + if (parameters->jpwl_epc_on) { + OPJ_INT32 i; + + /* set JPWL on */ + cp->epc_on = true; + cp->info_on = false; /* no informative technique */ + + /* set EPB on */ + if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { + cp->epb_on = true; + + cp->hprot_MH = parameters->jpwl_hprot_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; + cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; + } + /* if tile specs are not specified, copy MH specs */ + if (cp->hprot_TPH[0] == -1) { + cp->hprot_TPH_tileno[0] = 0; + cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; + } + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; + cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; + cp->pprot[i] = parameters->jpwl_pprot[i]; + } + } + + /* set ESD writing */ + if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { + cp->esd_on = true; + + cp->sens_size = parameters->jpwl_sens_size; + cp->sens_addr = parameters->jpwl_sens_addr; + cp->sens_range = parameters->jpwl_sens_range; + + cp->sens_MH = parameters->jpwl_sens_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; + cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; + } + } + + /* always set RED writing to false: we are at the encoder */ + cp->red_on = false; + + } else { + cp->epc_on = false; + } +#endif /* USE_JPWL */ + + + /* initialize the mutiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if + (parameters->numpocs) + { + /* initialisation of POC */ + l_res = j2k_check_poc_val(parameters->POC,parameters->numpocs, parameters->numresolution, image->numcomps, parameters->tcp_numlayers, p_manager); + // TODO + } + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tcp_t *tcp = &cp->tcps[tileno]; + tcp->numlayers = parameters->tcp_numlayers; + for (j = 0; j < tcp->numlayers; j++) { + if(cp->m_specific_param.m_enc.m_cinema){ + if (cp->m_specific_param.m_enc.m_fixed_quality) { + 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 */ + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } else { + tcp->rates[j] = parameters->tcp_rates[j]; + } + } + } + tcp->csty = parameters->csty; + tcp->prg = parameters->prog_order; + tcp->mct = parameters->tcp_mct; + + + + numpocs_tile = 0; + tcp->POC = 0; + if + (parameters->numpocs) + { + /* initialisation of POC */ + tcp->POC = 1; + // TODO + for (i = 0; i < (unsigned int) parameters->numpocs; i++) { + if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) { + opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; + tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; + tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; + tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; + tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; + tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1; + tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + numpocs_tile++; + } + } + tcp->numpocs = numpocs_tile -1 ; + }else{ + tcp->numpocs = 0; + } + + tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + if + (parameters->mct_data) + { + OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * sizeof(OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpBuf = opj_malloc(lMctSize); + OPJ_INT32 * l_dc_shift = (OPJ_INT32 *) ((OPJ_BYTE *) parameters->mct_data + lMctSize); + tcp->mct = 2; + tcp->m_mct_coding_matrix = opj_malloc(lMctSize); + memcpy(tcp->m_mct_coding_matrix,parameters->mct_data,lMctSize); + memcpy(lTmpBuf,parameters->mct_data,lMctSize); + tcp->m_mct_decoding_matrix = opj_malloc(lMctSize); + assert(opj_matrix_inversion_f(lTmpBuf,(tcp->m_mct_decoding_matrix),image->numcomps)); + tcp->mct_norms = opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); + opj_calculate_norms(tcp->mct_norms,image->numcomps,tcp->m_mct_decoding_matrix); + opj_free(lTmpBuf); + for + (i = 0; i < image->numcomps; i++) + { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->m_dc_level_shift = l_dc_shift[i]; + } + j2k_setup_mct_encoding(tcp,image); + } + else + { + for + (i = 0; i < image->numcomps; i++) + { + opj_tccp_t *tccp = &tcp->tccps[i]; + opj_image_comp_t * l_comp = &(image->comps[i]); + if + (! l_comp->sgnd) + { + tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); + } + } + } + + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */ + tccp->numresolutions = parameters->numresolution; + tccp->cblkw = int_floorlog2(parameters->cblockw_init); + tccp->cblkh = int_floorlog2(parameters->cblockh_init); + tccp->cblksty = parameters->mode; + tccp->qmfbid = parameters->irreversible ? 0 : 1; + tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; + tccp->numgbits = 2; + if (i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + + if(parameters->cp_cinema) + { + //Precinct size for lowest frequency subband=128 + tccp->prcw[0] = 7; + tccp->prch[0] = 7; + //Precinct size at all other resolutions = 256 + for (j = 1; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 8; + tccp->prch[j] = 8; + } + }else{ + if (parameters->csty & J2K_CCP_CSTY_PRT) { + int p = 0; + for (j = tccp->numresolutions - 1; j >= 0; j--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]); + } + + if (parameters->prch_init[p] < 1) { + tccp->prch[j] = 1; + }else { + tccp->prch[j] = int_floorlog2(parameters->prch_init[p]); + } + + } else { + int res_spec = parameters->res_spec; + int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); + + if (size_prcw < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(size_prcw); + } + + if (size_prch < 1) { + tccp->prch[j] = 1; + } else { + tccp->prch[j] = int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */ + } //end for + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; + } + } + } + + dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); + } + } + if + (parameters->mct_data) + { + opj_free(parameters->mct_data); + parameters->mct_data = 00; + } +} + +bool j2k_write_first_tile_part ( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 compno; + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_BYTE * l_begin_data = 00; + + opj_tcp_t *l_tcp = 00; + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; + + l_tcd->cur_pino = 0; + /*Get number of tile parts*/ + + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + /* INDEX >> */ + + /* << INDEX */ + l_current_nb_bytes_written = 0; + l_begin_data = p_data; + if + (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) + { + return false; + } + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + + if + (l_cp->m_specific_param.m_enc.m_cinema == 0) + { + for + (compno = 1; compno < p_j2k->m_image->numcomps; compno++) + { + l_current_nb_bytes_written = 0; + j2k_write_coc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + j2k_write_qcc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + } + if + (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) + { + l_current_nb_bytes_written = 0; + j2k_write_poc_in_memory(p_j2k,p_data,&l_current_nb_bytes_written,p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + } + } + l_current_nb_bytes_written = 0; + if + (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) + { + return false; + } + l_nb_bytes_written += l_current_nb_bytes_written; + * p_data_written = l_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6,l_nb_bytes_written,4); /* PSOT */ + if + (l_cp->m_specific_param.m_enc.m_cinema) + { + j2k_update_tlm(p_j2k,l_nb_bytes_written); + } + return true; +} + +bool j2k_write_all_tile_parts( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 tilepartno=0; + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_UINT32 l_part_tile_size; + OPJ_UINT32 tot_num_tp; + OPJ_UINT32 pino; + + OPJ_BYTE * l_begin_data; + opj_tcp_t *l_tcp = 00; + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; + + /*Get number of tile parts*/ + tot_num_tp = j2k_get_num_tp(l_cp,0,p_j2k->m_current_tile_number); + for + (tilepartno = 1; tilepartno < tot_num_tp ; ++tilepartno) + { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; + if + (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) + { + return false; + } + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_nb_bytes_written; + + l_current_nb_bytes_written = 0; + if + (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) + { + return false; + } + p_data += l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6,l_part_tile_size,4); /* PSOT */ + + if + (l_cp->m_specific_param.m_enc.m_cinema) + { + j2k_update_tlm(p_j2k,l_part_tile_size); + } + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + } + for + (pino = 1; pino <= l_tcp->numpocs; ++pino) + { + l_tcd->cur_pino = pino; + /*Get number of tile parts*/ + tot_num_tp = j2k_get_num_tp(l_cp,pino,p_j2k->m_current_tile_number); + for + (tilepartno = 0; tilepartno < tot_num_tp ; ++tilepartno) + { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; + if + (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) + { + return false; + } + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + if + (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) + { + return false; + } + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + p_total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6,l_part_tile_size,4); /* PSOT */ + + if + (l_cp->m_specific_param.m_enc.m_cinema) + { + j2k_update_tlm(p_j2k,l_part_tile_size); + } + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + } + } + *p_data_written = l_nb_bytes_written; + return true; +} + + +bool j2k_pre_write_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + if + (p_tile_index != p_j2k->m_current_tile_number) + { + opj_event_msg(p_manager, EVT_ERROR, "The given tile index does not match." ); + return false; + } + + opj_event_msg(p_manager, EVT_INFO, "tile number %d / %d\n", p_j2k->m_current_tile_number + 1, p_j2k->m_cp.tw * p_j2k->m_cp.th); + + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number = 0; + p_j2k->m_tcd->cur_totnum_tp = p_j2k->m_cp.tcps[p_tile_index].m_nb_tile_parts; + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + /* initialisation before tile encoding */ + if + (! tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) + { + return false; + } + return true; +} + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_write_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + if + (! j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) + { + return false; + } + return j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager); +} + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_post_write_tile ( + opj_j2k_t * p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 l_nb_bytes_written; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tile_size = 0; + OPJ_UINT32 l_available_data; + + assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; + + l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size; + l_available_data = l_tile_size; + l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data; + if + (! tcd_copy_tile_data(l_tcd,p_data,p_data_size)) + { + opj_event_msg(p_manager, EVT_ERROR, "Size mismtach between tile data and sent data." ); + return false; + } + + l_nb_bytes_written = 0; + if + (! j2k_write_first_tile_part(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) + { + return false; + } + l_current_data += l_nb_bytes_written; + l_available_data -= l_nb_bytes_written; + + l_nb_bytes_written = 0; + if + (! j2k_write_all_tile_parts(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) + { + return false; + } + + l_available_data -= l_nb_bytes_written; + l_nb_bytes_written = l_tile_size - l_available_data; + + if + (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_encoded_tile_data,l_nb_bytes_written,p_manager) != l_nb_bytes_written) + { + return false; + } + ++p_j2k->m_current_tile_number; + return true; +} + +/** + * Reads a tile header. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_read_tile_header ( + opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_current_marker = J2K_MS_SOT; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 l_nb_tiles; + + // preconditions + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_EOC) + { + l_current_marker = J2K_MS_EOC; + } + else if + (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_TPHSOT) + { + return false; + } + + while + (! p_j2k->m_specific_param.m_decoder.m_can_decode && l_current_marker != J2K_MS_EOC) + { + while + (l_current_marker != J2K_MS_SOD) + { + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); + if + (p_j2k->m_specific_param.m_decoder.m_state & J2K_DEC_STATE_TPH) + { + p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); + } + l_marker_size -= 2; + + l_marker_handler = j2k_get_marker_handler(l_current_marker); + // Check if the marker is known + if + (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) + { + opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); + return false; + } + if + (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) + { + p_j2k->m_specific_param.m_decoder.m_header_data = opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); + if + (p_j2k->m_specific_param.m_decoder.m_header_data == 00) + { + return false; + } + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + + } + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + if + (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); + return false; + } + if + (p_j2k->m_specific_param.m_decoder.m_skip_data) + { + if + (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + l_current_marker = J2K_MS_SOD; + } + else + { + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + } + } + + if + (! p_j2k->m_specific_param.m_decoder.m_skip_data) + { + if + (! j2k_read_sod(p_j2k,p_stream,p_manager)) + { + return false; + } + } + else + { + p_j2k->m_specific_param.m_decoder.m_skip_data = 0; + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPHSOT; + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + } + } + + if + (l_current_marker == J2K_MS_EOC) + { + if + (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_EOC) + { + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_EOC; + } + } + if + ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) + { + l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + while + ( + (p_j2k->m_current_tile_number < l_nb_tiles) + && (l_tcp->m_data == 00) + ) + { + ++p_j2k->m_current_tile_number; + ++l_tcp; + } + if + (p_j2k->m_current_tile_number == l_nb_tiles) + { + *p_go_on = false; + return true; + } + } + if + (! tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return false; + } + *p_tile_index = p_j2k->m_current_tile_number; + *p_go_on = true; + *p_data_size = tcd_get_decoded_tile_size(p_j2k->m_tcd); + * p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; + * p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; + * p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; + * p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; + * p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; + p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_DATA; + return true; +} + +bool j2k_decode_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_current_marker; + OPJ_BYTE l_data [2]; + opj_tcp_t * l_tcp; + + // preconditions + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if + (! (p_j2k->m_specific_param.m_decoder.m_state & J2K_DEC_STATE_DATA) || p_tile_index != p_j2k->m_current_tile_number) + { + return false; + } + l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]); + if + (! l_tcp->m_data) + { + j2k_tcp_destroy(&(p_j2k->m_cp.tcps[p_tile_index])); + return false; + } + if + (! tcd_decode_tile(p_j2k->m_tcd, l_tcp->m_data, l_tcp->m_data_size, p_tile_index, p_j2k->cstr_info)) + { + j2k_tcp_destroy(l_tcp); + p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; + return false; + } + if + (! tcd_update_tile_data(p_j2k->m_tcd,p_data,p_data_size)) + { + return false; + } + j2k_tcp_destroy(l_tcp); + p_j2k->m_tcd->tcp = 0; + + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state &= (~J2K_DEC_STATE_DATA); + if + (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_EOC) + { + if + (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(l_data,&l_current_marker,2); + if + (l_current_marker == J2K_MS_EOC) + { + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_EOC; + } + else if + (l_current_marker != J2K_MS_SOT) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short, expected SOT\n"); + return false; + } + } + return true; +} + + +/** + * Ends the compression procedures and possibiliy add data to be read after the + * codestream. + */ +bool j2k_end_compress(opj_j2k_t *p_j2k, struct opj_stream_private *p_stream, struct opj_event_mgr * p_manager) +{ + /* customization of the encoding */ + j2k_setup_end_compress(p_j2k); + + if + (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) + { + return false; + } + return true; +} + +/** + * Reads a jpeg2000 codestream header structure. + * + * @param p_stream the stream to read data from. + * @param p_j2k the jpeg2000 codec. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +bool j2k_read_header( + opj_j2k_t *p_j2k, + struct opj_image ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + *p_image = 00; + /* create an empty image */ + p_j2k->m_image = opj_image_create0(); + if + (! p_j2k->m_image) + { + return false; + } + + /* customization of the validation */ + j2k_setup_decoding_validation (p_j2k); + + /* validation of the parameters codec */ + if + (! j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) + { + opj_image_destroy(p_j2k->m_image); + p_j2k->m_image = 00; + return false; + } + + /* customization of the encoding */ + j2k_setup_header_reading(p_j2k); + + /* read header */ + if + (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) + { + opj_image_destroy(p_j2k->m_image); + p_j2k->m_image = 00; + return false; + } + *p_image = p_j2k->m_image; + * p_tile_x0 = p_j2k->m_cp.tx0; + * p_tile_y0 = p_j2k->m_cp.ty0; + * p_tile_width = p_j2k->m_cp.tdx; + * p_tile_height = p_j2k->m_cp.tdy; + * p_nb_tiles_x = p_j2k->m_cp.tw; + * p_nb_tiles_y = p_j2k->m_cp.th; + return true; +} + +/** + * The read header procedure. + */ +bool j2k_read_header_procedure( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_current_marker; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + + // preconditions + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MHSOC; + + if + (! j2k_read_soc(p_j2k,p_stream,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Expected a SOC marker \n"); + return false; + } + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + + while + (l_current_marker != J2K_MS_SOT) + { + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); + l_marker_size -= 2; + /*if + (l_current_marker < 0xff00) + { + opj_event_msg(p_manager, EVT_ERROR, "%.8x: expected a marker instead of %x\n", opj_stream_tell(p_stream) - 2, l_current_marker); + return 0; + } + */ + l_marker_handler = j2k_get_marker_handler(l_current_marker); + // Check if the marker is known + if + (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) + { + opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); + return false; + } + if + (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) + { + p_j2k->m_specific_param.m_decoder.m_header_data = opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); + if + (p_j2k->m_specific_param.m_decoder.m_header_data == 00) + { + return false; + } + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + } + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + if + (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); + return false; + } + if + (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return false; + } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); + } + p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPHSOT; + return true; +} + + + +/** + * Reads the tiles. + */ +bool j2k_decode_tiles ( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + bool l_go_on = true; + OPJ_UINT32 l_current_tile_no; + OPJ_UINT32 l_data_size,l_max_data_size; + OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1; + OPJ_UINT32 l_nb_comps; + OPJ_BYTE * l_current_data; + + l_current_data = opj_malloc(1000); + if + (! l_current_data) + { + return false; + } + l_max_data_size = 1000; + + while + (true) + { + if + (! j2k_read_tile_header( + p_j2k,&l_current_tile_no, + &l_data_size, + &l_tile_x0, + &l_tile_y0, + &l_tile_x1, + &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) + { + return false; + } + if + (! l_go_on) + { + break; + } + if + (l_data_size > l_max_data_size) + { + l_current_data = opj_realloc(l_current_data,l_data_size); + if + (! l_current_data) + { + return false; + } + l_max_data_size = l_data_size; + } + if + (! j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) + { + opj_free(l_current_data); + return false; + } + if + (! j2k_update_image_data(p_j2k->m_tcd,l_current_data)) + { + opj_free(l_current_data); + return false; + } + + } + opj_free(l_current_data); + return true; +} + + + + + + +/** + * Decodes the tiles of the stream. + */ +opj_image_t * j2k_decode( + opj_j2k_t * p_j2k, + opj_stream_private_t * p_stream, + opj_event_mgr_t * p_manager) +{ + /* customization of the encoding */ + j2k_setup_decoding(p_j2k); + + /* write header */ + if + (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) + { + opj_image_destroy(p_j2k->m_image); + p_j2k->m_image = 00; + } + return p_j2k->m_image; +} + +/** + * Encodes all the tiles in a row. + */ +bool j2k_encode( + opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max_tile_size, l_current_tile_size; + OPJ_BYTE * l_current_data; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_current_data = opj_malloc(1000); + if + (! l_current_data) + { + return false; + } + l_max_tile_size = 1000; + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + for + (i=0;im_tcd); + if + (l_current_tile_size > l_max_tile_size) + { + l_current_data = opj_realloc(l_current_data,l_current_tile_size); + if + (! l_current_data) + { + return false; + } + l_max_tile_size = l_current_tile_size; + } + j2k_get_tile_data(p_j2k->m_tcd,l_current_data); + if + (! j2k_post_write_tile (p_j2k,l_current_data,l_current_tile_size,p_stream,p_manager)) + { + return false; + } + } + opj_free(l_current_data); + return true; +} + + + +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +bool j2k_end_decompress( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + return true; +} + + + +void j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data) +{ + OPJ_UINT32 i,j,k = 0; + OPJ_UINT32 l_width,l_height,l_stride, l_offset_x,l_offset_y, l_image_width; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + opj_image_t * l_image = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_INT32 * l_src_ptr; + l_tilec = p_tcd->tcd_image->tiles->comps; + l_image = p_tcd->image; + l_img_comp = l_image->comps; + for + (i=0;iimage->numcomps;++i) + { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + l_width = (l_tilec->x1 - l_tilec->x0); + l_height = (l_tilec->y1 - l_tilec->y0); + l_offset_x = int_ceildiv(l_image->x0, l_img_comp->dx); + l_offset_y = int_ceildiv(l_image->y0, l_img_comp->dy); + l_image_width = int_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx); + l_stride = l_image_width - l_width; + l_src_ptr = l_img_comp->data + (l_tilec->x0 - l_offset_x) + (l_tilec->y0 - l_offset_y) * l_image_width; + + switch + (l_size_comp) + { + case 1: + { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data; + if + (l_img_comp->sgnd) + { + for + (j=0;jsgnd) + { + for + (j=0;jtcd_image->tiles->comps; + l_image = p_tcd->image; + l_img_comp = l_image->comps; + for + (i=0;iimage->numcomps;++i) + { + if + (!l_img_comp->data) + { + l_img_comp->data = (OPJ_INT32*) opj_malloc(l_img_comp->w * l_img_comp->h * sizeof(OPJ_INT32)); + if + (! l_img_comp->data) + { + return false; + } + memset(l_img_comp->data,0,l_img_comp->w * l_img_comp->h * sizeof(OPJ_INT32)); + } + + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_res = l_tilec->resolutions + l_img_comp->resno_decoded; + + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + l_width = (l_res->x1 - l_res->x0); + l_height = (l_res->y1 - l_res->y0); + l_dest_stride = (l_img_comp->w) - l_width; + l_offset_x = int_ceildivpow2(l_img_comp->x0, l_img_comp->factor); + l_offset_y = int_ceildivpow2(l_img_comp->y0, l_img_comp->factor); + l_dest_ptr = l_img_comp->data + (l_res->x0 - l_offset_x) + (l_res->y0 - l_offset_y) * l_img_comp->w; + + switch + (l_size_comp) + { + case 1: + { + OPJ_CHAR * l_src_ptr = (OPJ_CHAR*) p_data; + if + (l_img_comp->sgnd) + { + for + (j=0;jsgnd) + { + for + (j=0;jm_cp); + + if + (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_TPHSOT) + { + return false; + } + p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_start_x - l_cp->tx0) / l_cp->tdx; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_start_y - l_cp->ty0) / l_cp->tdy; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = int_ceildiv((p_end_x - l_cp->tx0), l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = int_ceildiv((p_end_y - l_cp->ty0), l_cp->tdy); + p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; + return true; +} diff --git a/v2/libopenjpeg/j2k.h b/v2/libopenjpeg/j2k.h new file mode 100755 index 00000000..ccb31e33 --- /dev/null +++ b/v2/libopenjpeg/j2k.h @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __J2K_H +#define __J2K_H +/** +@file j2k.h +@brief The JPEG-2000 Codestream Reader/Writer (J2K) + +The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data. +*/ + +#include "openjpeg.h" + +struct opj_dparameters; +struct opj_stream_private; +struct opj_event_mgr; +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + +#define J2K_CP_CSTY_PRT 0x01 +#define J2K_CP_CSTY_SOP 0x02 +#define J2K_CP_CSTY_EPH 0x04 +#define J2K_CCP_CSTY_PRT 0x01 +#define J2K_CCP_CBLKSTY_LAZY 0x01 +#define J2K_CCP_CBLKSTY_RESET 0x02 +#define J2K_CCP_CBLKSTY_TERMALL 0x04 +#define J2K_CCP_CBLKSTY_VSC 0x08 +#define J2K_CCP_CBLKSTY_PTERM 0x10 +#define J2K_CCP_CBLKSTY_SEGSYM 0x20 +#define J2K_CCP_QNTSTY_NOQNT 0 +#define J2K_CCP_QNTSTY_SIQNT 1 +#define J2K_CCP_QNTSTY_SEQNT 2 + +/* ----------------------------------------------------------------------- */ + +#define J2K_MS_SOC 0xff4f /**< SOC marker value */ +#define J2K_MS_SOT 0xff90 /**< SOT marker value */ +#define J2K_MS_SOD 0xff93 /**< SOD marker value */ +#define J2K_MS_EOC 0xffd9 /**< EOC marker value */ +#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ +#define J2K_MS_COD 0xff52 /**< COD marker value */ +#define J2K_MS_COC 0xff53 /**< COC marker value */ +#define J2K_MS_RGN 0xff5e /**< RGN marker value */ +#define J2K_MS_QCD 0xff5c /**< QCD marker value */ +#define J2K_MS_QCC 0xff5d /**< QCC marker value */ +#define J2K_MS_POC 0xff5f /**< POC marker value */ +#define J2K_MS_TLM 0xff55 /**< TLM marker value */ +#define J2K_MS_PLM 0xff57 /**< PLM marker value */ +#define J2K_MS_PLT 0xff58 /**< PLT marker value */ +#define J2K_MS_PPM 0xff60 /**< PPM marker value */ +#define J2K_MS_PPT 0xff61 /**< PPT marker value */ +#define J2K_MS_SOP 0xff91 /**< SOP marker value */ +#define J2K_MS_EPH 0xff92 /**< EPH marker value */ +#define J2K_MS_CRG 0xff63 /**< CRG marker value */ +#define J2K_MS_COM 0xff64 /**< COM marker value */ +#define J2K_MS_CBD 0xff78 /**< CBD marker value */ +#define J2K_MS_MCC 0xff75 /**< MCC marker value */ +#define J2K_MS_MCT 0xff74 /**< MCT marker value */ +#define J2K_MS_MCO 0xff77 /**< MCO marker value */ + +/* UniPG>> */ +#ifdef USE_JPWL +#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ +#endif /* USE_JPWL */ +#ifdef USE_JPSEC +#define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */ +#define J2K_MS_INSEC 0xff94 /**< INSEC marker value (Part 8: Secure JPEG 2000) */ +#endif /* USE_JPSEC */ +/* < there was a PPT marker for the present tile */ + OPJ_UINT32 ppt : 1; + /** indicates if a POC marker has been used O:NO, 1:YES */ + OPJ_UINT32 POC : 1; +} opj_tcp_t; + +typedef struct opj_encoding_param +{ + /** Digital cinema profile*/ + OPJ_CINEMA_MODE m_cinema; + /** Maximum rate for each component. If == 0, component size limitation is not considered */ + OPJ_UINT32 m_max_comp_size; + /** Position of tile part flag in progression order*/ + OPJ_INT32 m_tp_pos; + /** fixed layer */ + OPJ_INT32 *m_matrice; + /** Flag determining tile part generation*/ + OPJ_BYTE m_tp_flag; + /** allocation by rate/distortion */ + OPJ_UINT32 m_disto_alloc : 1; + /** allocation by fixed layer */ + OPJ_UINT32 m_fixed_alloc : 1; + /** add fixed_quality */ + OPJ_UINT32 m_fixed_quality : 1; + /** Enabling Tile part generation*/ + OPJ_UINT32 m_tp_on : 1; +} +opj_encoding_param_t; + +typedef struct opj_decoding_param +{ + /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ + OPJ_UINT32 m_reduce; + /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + OPJ_UINT32 m_layer; +} +opj_decoding_param_t; + +/** +Coding parameters +*/ +typedef struct opj_cp +{ + /** Size of the image in bits*/ + /*int img_size;*/ + /** Rsiz*/ + OPJ_RSIZ_CAPABILITIES rsiz; + /** XTOsiz */ + OPJ_INT32 tx0; + /** YTOsiz */ + OPJ_INT32 ty0; + /** XTsiz */ + OPJ_UINT32 tdx; + /** YTsiz */ + OPJ_UINT32 tdy; + /** comment */ + OPJ_CHAR *comment; + /** number of tiles in width */ + OPJ_UINT32 tw; + /** number of tiles in heigth */ + OPJ_UINT32 th; + /** packet header storage original buffer */ + OPJ_BYTE *ppm_buffer; + /** packet header store there for futur use in t2_decode_packet */ + OPJ_BYTE *ppm_data; + /** size of the ppm_data*/ + OPJ_UINT32 ppm_len; + /** Number of bytes actually stored inside the ppm_data */ + OPJ_UINT32 ppm_data_size; + /** tile coding parameters */ + opj_tcp_t *tcps; + union + { + opj_decoding_param_t m_dec; + opj_encoding_param_t m_enc; + } + m_specific_param; + + +/* UniPG>> */ +#ifdef USE_JPWL + /** enables writing of EPC in MH, thus activating JPWL */ + bool epc_on; + /** enables writing of EPB, in case of activated JPWL */ + bool epb_on; + /** enables writing of ESD, in case of activated JPWL */ + bool esd_on; + /** enables writing of informative techniques of ESD, in case of activated JPWL */ + bool info_on; + /** enables writing of RED, in case of activated JPWL */ + bool red_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int hprot_MH; + /** tile number of header protection specification (>=0) */ + int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0/2/4 bytes) */ + int sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int sens_addr; + /** sensitivity range (0-3) */ + int sens_range; + /** sensitivity method for MH (-1,0-7) */ + int sens_MH; + /** tile number of sensitivity specification (>=0) */ + int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1,0-7) */ + int sens_TPH[JPWL_MAX_NO_TILESPECS]; + /** enables JPWL correction at the decoder */ + bool correct; + /** expected number of components at the decoder */ + int exp_comps; + /** maximum number of tiles at the decoder */ + int max_tiles; +#endif /* USE_JPWL */ + + /******** FLAGS *********/ + /** if ppm == 1 --> there was a PPM marker*/ + OPJ_UINT32 ppm : 1; + /** tells if the parameter is a coding or decoding one */ + OPJ_UINT32 m_is_decoder : 1; +/* <cp. + * + * @param p_j2k J2K codec + * @param p_parameters decompression parameters + * @deprecated +*/ +void j2k_setup_decoder( + opj_j2k_t *p_j2k, + struct opj_dparameters *p_parameters + ); +/** + * Reads a jpeg2000 codestream header structure. + * + * @param cio the stream to read data from. + * @param p_j2k the jpeg2000 codec. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +bool j2k_read_header( + opj_j2k_t *p_j2k, + struct opj_image ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); +/** +Decode an image from a JPEG-2000 codestream +@param j2k J2K decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +opj_image_t* j2k_decode(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); + +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +bool j2k_end_decompress(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); + +/** +Decode an image form a JPT-stream (JPEG 2000, JPIP) +@param j2k J2K decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_codestream_info *cstr_info); + +/** +Creates a J2K compression structure +@param cinfo Codec context info +@return Returns a handle to a J2K compressor if successful, returns NULL otherwise +*/ +opj_j2k_t* j2k_create_compress(); + +/** +Setup the encoder parameters using the current image and using user parameters. +Coding parameters are returned in j2k->cp. +@param j2k J2K compressor handle +@param parameters compression parameters +@param image input filled image +*/ +void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image, struct opj_event_mgr * p_manager); + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_write_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); + +/** + * Converts an enum type progression order to string type. + * + * @param prg_order the progression order to get. + * + * @return the string representation of the gicen progression order. + */ +const char * j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); + + +/** + * Encodes an image into a JPEG-2000 codestream + */ +bool j2k_encode( + opj_j2k_t * p_j2k, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); +bool j2k_setup_mct_encoding (opj_tcp_t * p_tcp,opj_image_t * p_image); + +/** + * Decode tile data. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_decode_tile ( + opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a tile header. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool j2k_read_tile_header ( + opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_go_on, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_j2k the jpeg2000 codec. + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager + * + * @return true if the area could be set. + */ +bool j2k_set_decode_area( + opj_j2k_t *p_j2k, + OPJ_INT32 p_start_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, + OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager + ); + + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J2K_H */ diff --git a/v2/libopenjpeg/j2k_lib.c b/v2/libopenjpeg/j2k_lib.c new file mode 100755 index 00000000..84d07dd6 --- /dev/null +++ b/v2/libopenjpeg/j2k_lib.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef WIN32 +#include +#else +/*#include +#include +#include +*/ +#endif /* WIN32 */ +#include "j2k_lib.h" + + +OPJ_FLOAT64 opj_clock(void) { +#if 0 +#ifdef WIN32 + /* WIN32: use QueryPerformance (very accurate) */ + LARGE_INTEGER freq , t ; + /* freq is the clock speed of the CPU */ + QueryPerformanceFrequency(&freq) ; + /* cout << "freq = " << ((double) freq.QuadPart) << endl; */ + /* t is the high resolution performance counter (see MSDN) */ + QueryPerformanceCounter ( & t ) ; + return ( t.QuadPart /(double) freq.QuadPart ) ; +#else + /* Unix or Linux: use resource usage */ + struct rusage t; + double procTime; + /* (1) Get the rusage data structure at this moment (man getrusage) */ + getrusage(0,&t); + /* (2) What is the elapsed time ? - CPU time = User time + System time */ + /* (2a) Get the seconds */ + procTime = t.ru_utime.tv_sec + t.ru_stime.tv_sec; + /* (2b) More precisely! Get the microseconds part ! */ + return ( procTime + (t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ; +#endif + +#endif + return 0; +} + diff --git a/v2/libopenjpeg/j2k_lib.h b/v2/libopenjpeg/j2k_lib.h new file mode 100755 index 00000000..d44d3d86 --- /dev/null +++ b/v2/libopenjpeg/j2k_lib.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __J2K_LIB_H +#define __J2K_LIB_H +/** +@file j2k_lib.h +@brief Internal functions + +The functions in J2K_LIB.C are internal utilities mainly used for timing. +*/ +#include "openjpeg.h" +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Difference in successive opj_clock() calls tells you the elapsed time +@return Returns time in seconds +*/ +OPJ_FLOAT64 opj_clock(void); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J2K_LIB_H */ + diff --git a/v2/libopenjpeg/jp2.c b/v2/libopenjpeg/jp2.c new file mode 100755 index 00000000..0d288d5d --- /dev/null +++ b/v2/libopenjpeg/jp2.c @@ -0,0 +1,2229 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "jp2.h" +#include "cio.h" +#include "opj_malloc.h" +#include "event.h" +#include "j2k.h" +#include "function_list.h" +#include "assert.h" + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +#define BOX_SIZE 1024 + + + +/** @name Local static functions */ +/*@{*/ + + + +/** + * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +bool jp2_write_jp2h( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Skips the Jpeg2000 Codestream Header box - JP2C Header box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +bool jp2_skip_jp2c( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. + * + * @return true if the JP2 Header box was successfully reconized. +*/ +bool jp2_read_jp2h( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the Jpeg2000 codestream Header box - JP2C Header box. This function must be called AFTER the coding has been done. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +static bool jp2_write_jp2c( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. + * + * @param cio the input stream to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_manager user event manager. + * + * @return true if the box is reconized, false otherwise +*/ +static bool jp2_read_boxhdr( + opj_jp2_box_t *box, + OPJ_UINT32 * p_number_bytes_read, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. Data is read from a character string + * + * @param p_data the character string to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_box_max_size the maximum number of bytes in the box. + * + * @return true if the box is reconized, false otherwise +*/ +static bool jp2_read_boxhdr_char( + opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a jpeg2000 file signature box. + * + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. + * + * @return true if the file signature box is valid. + */ +static bool jp2_read_jp( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes a jpeg2000 file signature box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writting was successful. + */ +static bool jp2_write_jp( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Writes a FTYP box - File type box + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writting was successful. + */ +static bool jp2_write_ftyp( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a a FTYP box - File type box + * + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. + * + * @return true if the FTYP box is valid. + */ +static bool jp2_read_ftyp( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Reads a IHDR box - Image Header box + * + * @param p_image_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_image_header_size the size of the image header + * @param p_manager the user event manager. + * + * @return true if the image header is valid, fale else. + */ +static bool jp2_read_ihdr( + opj_jp2_t *jp2, + unsigned char * p_image_header_data, + unsigned int p_image_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the Image Header box - Image Header box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static unsigned char * jp2_write_ihdr( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ); + +/** + * Reads a Bit per Component box. + * + * @param p_bpc_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_bpc_header_size the size of the bpc header + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, fale else. + */ +static bool jp2_read_bpcc( + opj_jp2_t *jp2, + unsigned char * p_bpc_header_data, + unsigned int p_bpc_header_size, + struct opj_event_mgr * p_manager + ); + + +/** + * Writes the Bit per Component box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static unsigned char * jp2_write_bpcc( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ); + +/** + * Reads the Colour Specification box. + * + * @param p_colr_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_colr_header_size the size of the color header + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, fale else. +*/ +static bool jp2_read_colr( + opj_jp2_t *jp2, + unsigned char * p_colr_header_data, + unsigned int p_colr_header_size, + struct opj_event_mgr * p_manager + ); + +/** + * Writes the Colour Specification box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static unsigned char *jp2_write_colr( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ); + + +/** + * Reads a jpeg2000 file header structure. + * + * @param cio the stream to read data from. + * @param jp2 the jpeg2000 file header structure. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +bool jp2_read_header_procedure( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); +/** + * Excutes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param cio the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +static bool jp2_exec ( + opj_jp2_t * jp2, + struct opj_procedure_list * p_procedure_list, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); +/** + * Finds the execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or NULL if it could not be found. + */ +static const opj_jp2_header_handler_t * jp2_find_handler (int p_id); + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +static void jp2_setup_encoding_validation (opj_jp2_t *jp2); + +/** + * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. + */ +static void jp2_setup_header_writting (opj_jp2_t *jp2); + +/** + * The default validation procedure without any extension. + * + * @param jp2 the jpeg2000 codec to validate. + * @param cio the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool jp2_default_validation ( + opj_jp2_t * jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); + +/** + * Finds the execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or NULL if it could not be found. + */ +static const opj_jp2_header_handler_t * jp2_find_handler ( + int p_id + ); + +/** + * Finds the image execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or NULL if it could not be found. + */ +static const opj_jp2_header_handler_t * jp2_img_find_handler ( + int p_id + ); + +/** + * Sets up the procedures to do on writting header after the codestream. + * Developpers wanting to extend the library can add their own writting procedures. + */ +static void jp2_setup_end_header_writting (opj_jp2_t *jp2); + +/** + * Sets up the procedures to do on reading header after the codestream. + * Developpers wanting to extend the library can add their own writting procedures. + */ +static void jp2_setup_end_header_reading (opj_jp2_t *jp2); + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +static void jp2_setup_decoding_validation (opj_jp2_t *jp2); + +/** + * Sets up the procedures to do on reading header. + * Developpers wanting to extend the library can add their own writting procedures. + */ +static void jp2_setup_header_reading (opj_jp2_t *jp2); +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ +const opj_jp2_header_handler_t jp2_header [] = +{ + {JP2_JP,jp2_read_jp}, + {JP2_FTYP,jp2_read_ftyp}, + {JP2_JP2H,jp2_read_jp2h} +}; + +const opj_jp2_header_handler_t jp2_img_header [] = +{ + {JP2_IHDR,jp2_read_ihdr}, + {JP2_COLR,jp2_read_colr}, + {JP2_BPCC,jp2_read_bpcc} +}; +/** + * Finds the execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or 00 if it could not be found. + */ +const opj_jp2_header_handler_t * jp2_find_handler ( + int p_id + ) +{ + unsigned int i, l_handler_size = sizeof(jp2_header) / sizeof(opj_jp2_header_handler_t); + for + (i=0;ijp2_state & JP2_STATE_HEADER) + { + jp2->jp2_state |= JP2_STATE_CODESTREAM; + return true; + } + else + { + opj_event_msg(p_manager, EVT_ERROR, "bad placed jpeg codestream\n"); + return false; + } + } + else if + (box.length == 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return false; + } + + l_current_handler = jp2_find_handler(box.type); + l_current_data_size = box.length - l_nb_bytes_read; + + if + (l_current_handler != 00) + { + if + (l_current_data_size > l_last_data_size) + { + l_current_data = opj_realloc(l_current_data,l_current_data_size); + l_last_data_size = l_current_data_size; + } + l_nb_bytes_read = opj_stream_read_data(cio,l_current_data,l_current_data_size,p_manager); + if + (l_nb_bytes_read != l_current_data_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Problem with reading JPEG2000 box, stream error\n"); + return false; + } + if + (! l_current_handler->handler(jp2,l_current_data,l_current_data_size,p_manager)) + { + return false; + } + } + else + { + jp2->jp2_state |= JP2_STATE_UNKNOWN; + if + (opj_stream_skip(cio,l_current_data_size,p_manager) != l_current_data_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n"); + return false; + } + } + } + return true; +} + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. + * + * @param cio the input stream to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (should usually be 8). + * @param p_manager user event manager. + * + * @return true if the box is reconized, false otherwise +*/ +bool jp2_read_boxhdr(opj_jp2_box_t *box, OPJ_UINT32 * p_number_bytes_read,opj_stream_private_t *cio, opj_event_mgr_t * p_manager) +{ + /* read header from file */ + unsigned char l_data_header [8]; + + // preconditions + assert(cio != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + *p_number_bytes_read = opj_stream_read_data(cio,l_data_header,8,p_manager); + if + (*p_number_bytes_read != 8) + { + return false; + } + /* process read data */ + opj_read_bytes(l_data_header,&(box->length), 4); + opj_read_bytes(l_data_header+4,&(box->type), 4); + + // do we have a "special very large box ?" + // read then the XLBox + if + (box->length == 1) + { + OPJ_UINT32 l_xl_part_size; + OPJ_UINT32 l_nb_bytes_read = opj_stream_read_data(cio,l_data_header,8,p_manager); + if + (l_nb_bytes_read != 8) + { + if + (l_nb_bytes_read > 0) + { + *p_number_bytes_read += l_nb_bytes_read; + } + return false; + } + opj_read_bytes(l_data_header,&l_xl_part_size, 4); + if + (l_xl_part_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); + return false; + } + opj_read_bytes(l_data_header,&(box->length), 4); + } + return true; +} + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. Data is read from a character string + * + * @param p_data the character string to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_box_max_size the maximum number of bytes in the box. + * + * @return true if the box is reconized, false otherwise +*/ +static bool jp2_read_boxhdr_char( + opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + opj_event_mgr_t * p_manager + ) +{ + // preconditions + assert(p_data != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + if + (p_box_max_size < 8) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of less than 8 bytes\n"); + return false; + } + /* process read data */ + opj_read_bytes(p_data,&(box->length), 4); + p_data += 4; + opj_read_bytes(p_data,&(box->type), 4); + p_data += 4; + *p_number_bytes_read = 8; + + // do we have a "special very large box ?" + // read then the XLBox + if + (box->length == 1) + { + unsigned int l_xl_part_size; + if + (p_box_max_size < 16) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle XL box of less than 16 bytes\n"); + return false; + } + + opj_read_bytes(p_data,&l_xl_part_size, 4); + p_data += 4; + *p_number_bytes_read += 4; + if + (l_xl_part_size != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n"); + return false; + } + opj_read_bytes(p_data,&(box->length), 4); + *p_number_bytes_read += 4; + if + (box->length == 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return false; + } + + } + else if + (box->length == 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return false; + } + return true; +} + + +/** + * Reads a jpeg2000 file signature box. + * + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. + * + * @return true if the file signature box is valid. + */ +bool jp2_read_jp( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + opj_event_mgr_t * p_manager + ) +{ + unsigned int l_magic_number; + + // preconditions + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if + (jp2->jp2_state != JP2_STATE_NONE) + { + opj_event_msg(p_manager, EVT_ERROR, "The signature box must be the first box in the file.\n"); + return false; + } + + + /* assure length of data is correct (4 -> magic number) */ + if + (p_header_size != 4) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with JP signature Box size\n"); + return false; + } + + // rearrange data + opj_read_bytes(p_header_data,&l_magic_number,4); + if + (l_magic_number != 0x0d0a870a ) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with JP Signature : bad magic number\n"); + return false; + } + jp2->jp2_state |= JP2_STATE_SIGNATURE; + return true; +} + +/** + * Reads a a FTYP box - File type box + * + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. + * + * @return true if the FTYP box is valid. + */ +bool jp2_read_ftyp( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + opj_event_mgr_t * p_manager + ) +{ + unsigned int i; + unsigned int l_remaining_bytes; + + // preconditions + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if + (jp2->jp2_state != JP2_STATE_SIGNATURE) + { + opj_event_msg(p_manager, EVT_ERROR, "The ftyp box must be the second box in the file.\n"); + return false; + } + + /* assure length of data is correct */ + if + (p_header_size < 8) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return false; + } + + opj_read_bytes(p_header_data,&jp2->brand,4); /* BR */ + p_header_data += 4; + + opj_read_bytes(p_header_data,&jp2->minversion,4); /* MinV */ + p_header_data += 4; + + l_remaining_bytes = p_header_size - 8; + + /* the number of remaining bytes should be a multiple of 4 */ + if + ((l_remaining_bytes & 0x3) != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return false; + } + /* div by 4 */ + jp2->numcl = l_remaining_bytes >> 2; + if + (jp2->numcl) + { + jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); + if + (jp2->cl == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n"); + return false; + } + memset(jp2->cl,0,jp2->numcl * sizeof(unsigned int)); + } + + + for + (i = 0; i < jp2->numcl; ++i) + { + opj_read_bytes(p_header_data,&jp2->cl[i],4); /* CLi */ + p_header_data += 4; + + } + jp2->jp2_state |= JP2_STATE_FILE_TYPE; + return true; +} + +/** + * Writes a jpeg2000 file signature box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writting was successful. + */ +bool jp2_write_jp ( + opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + /* 12 bytes will be read */ + unsigned char l_signature_data [12]; + + // preconditions + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + + /* write box length */ + opj_write_bytes(l_signature_data,12,4); + /* writes box type */ + opj_write_bytes(l_signature_data+4,JP2_JP,4); + /* writes magic number*/ + opj_write_bytes(l_signature_data+8,0x0d0a870a,4); + if + (opj_stream_write_data(cio,l_signature_data,12,p_manager) != 12) + { + return false; + } + return true; +} + + +/** + * Writes a FTYP box - File type box + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writting was successful. + */ +bool jp2_write_ftyp( + opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + unsigned int i; + unsigned int l_ftyp_size = 16 + 4 * jp2->numcl; + unsigned char * l_ftyp_data, * l_current_data_ptr; + bool l_result; + + // preconditions + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + l_ftyp_data = (unsigned char *) opj_malloc(l_ftyp_size); + + if + (l_ftyp_data == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n"); + return false; + } + memset(l_ftyp_data,0,l_ftyp_size); + + l_current_data_ptr = l_ftyp_data; + + opj_write_bytes(l_current_data_ptr, l_ftyp_size,4); /* box size */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, JP2_FTYP,4); /* FTYP */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->brand,4); /* BR */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->minversion,4); /* MinV */ + l_current_data_ptr += 4; + + for + (i = 0; i < jp2->numcl; i++) + { + opj_write_bytes(l_current_data_ptr, jp2->cl[i],4); /* CL */ + } + + l_result = (opj_stream_write_data(cio,l_ftyp_data,l_ftyp_size,p_manager) == l_ftyp_size); + if + (! l_result) + { + opj_event_msg(p_manager, EVT_ERROR, "Error while writting ftyp data to stream\n"); + } + opj_free(l_ftyp_data); + return l_result; +} + +/** + * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +bool jp2_write_jp2h( + opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_img_header_writer_handler_t l_writers [3]; + opj_jp2_img_header_writer_handler_t * l_current_writer; + + int i, l_nb_pass; + /* size of data for super box*/ + int l_jp2h_size = 8; + bool l_result = true; + + /* to store the data of the super box */ + unsigned char l_jp2h_data [8]; + + // preconditions + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + memset(l_writers,0,sizeof(l_writers)); + + if + (jp2->bpc == 255) + { + l_nb_pass = 3; + l_writers[0].handler = jp2_write_ihdr; + l_writers[1].handler = jp2_write_bpcc; + l_writers[2].handler = jp2_write_colr; + } + else + { + l_nb_pass = 2; + l_writers[0].handler = jp2_write_ihdr; + l_writers[1].handler = jp2_write_colr; + } + + /* write box header */ + /* write JP2H type */ + opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4); + + l_current_writer = l_writers; + for + (i=0;im_data = l_current_writer->handler(jp2,&(l_current_writer->m_size)); + if + (l_current_writer->m_data == 00) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to hold JP2 Header data\n"); + l_result = false; + break; + } + l_jp2h_size += l_current_writer->m_size; + ++l_current_writer; + } + + if + (! l_result) + { + l_current_writer = l_writers; + for + (i=0;im_data != 00) + { + opj_free(l_current_writer->m_data ); + } + ++l_current_writer; + } + return false; + } + + /* write super box size */ + opj_write_bytes(l_jp2h_data,l_jp2h_size,4); + + /* write super box data on stream */ + if + (opj_stream_write_data(cio,l_jp2h_data,8,p_manager) != 8) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n"); + l_result = false; + } + + if + (l_result) + { + l_current_writer = l_writers; + for + (i=0;im_data,l_current_writer->m_size,p_manager) != l_current_writer->m_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n"); + l_result = false; + break; + } + ++l_current_writer; + } + } + l_current_writer = l_writers; + /* cleanup */ + for + (i=0;im_data != 00) + { + opj_free(l_current_writer->m_data ); + } + ++l_current_writer; + } + return l_result; +} + +/** + * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. + * + * @return true if the JP2 Header box was successfully reconized. +*/ +bool jp2_read_jp2h( + opj_jp2_t *jp2, + unsigned char * p_header_data, + unsigned int p_header_size, + opj_event_mgr_t * p_manager + ) +{ + unsigned int l_box_size=0, l_current_data_size = 0; + opj_jp2_box_t box; + const opj_jp2_header_handler_t * l_current_handler; + + // preconditions + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + /* make sure the box is well placed */ + if + ((jp2->jp2_state & JP2_STATE_FILE_TYPE) != JP2_STATE_FILE_TYPE ) + { + opj_event_msg(p_manager, EVT_ERROR, "The box must be the first box in the file.\n"); + return false; + } + jp2->jp2_img_state = JP2_IMG_STATE_NONE; + + /* iterate while remaining data */ + while + (p_header_size > 0) + { + if + (! jp2_read_boxhdr_char(&box,p_header_data,&l_box_size,p_header_size, p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n"); + return false; + } + if + (box.length > p_header_size) + { + opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n"); + return false; + } + l_current_handler = jp2_img_find_handler(box.type); + + l_current_data_size = box.length - l_box_size; + p_header_data += l_box_size; + + if + (l_current_handler != 00) + { + if + (! l_current_handler->handler(jp2,p_header_data,l_current_data_size,p_manager)) + { + return false; + } + } + else + { + jp2->jp2_img_state |= JP2_IMG_STATE_UNKNOWN; + } + p_header_data += l_current_data_size; + p_header_size -= box.length; + } + jp2->jp2_state |= JP2_STATE_HEADER; + return true; +} + +/** + * Reads a IHDR box - Image Header box + * + * @param p_image_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_image_header_size the size of the image header + * @param p_image_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. + * @param p_manager the user event manager. + * + * @return true if the image header is valid, fale else. + */ +bool jp2_read_ihdr( + opj_jp2_t *jp2, + unsigned char * p_image_header_data, + unsigned int p_image_header_size, + opj_event_mgr_t * p_manager + ) +{ + // preconditions + assert(p_image_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if + (p_image_header_size != 14) + { + opj_event_msg(p_manager, EVT_ERROR, "Bad image header box (bad size)\n"); + return false; + } + opj_read_bytes(p_image_header_data,&(jp2->h),4); /* HEIGHT */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data,&(jp2->w),4); /* WIDTH */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data,&(jp2->numcomps),2); /* NC */ + p_image_header_data += 2; + + /* allocate memory for components */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); + if + (jp2->comps == 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle image header (ihdr)\n"); + return false; + } + memset(jp2->comps,0,jp2->numcomps * sizeof(opj_jp2_comps_t)); + + opj_read_bytes(p_image_header_data,&(jp2->bpc),1); /* BPC */ + ++ p_image_header_data; + opj_read_bytes(p_image_header_data,&(jp2->C),1); /* C */ + ++ p_image_header_data; + opj_read_bytes(p_image_header_data,&(jp2->UnkC),1); /* UnkC */ + ++ p_image_header_data; + opj_read_bytes(p_image_header_data,&(jp2->IPR),1); /* IPR */ + ++ p_image_header_data; + return true; +} + +/** + * Writes the Image Header box - Image Header box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static unsigned char * jp2_write_ihdr( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ) +{ + unsigned char * l_ihdr_data,* l_current_ihdr_ptr; + + // preconditions + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + + /* default image header is 22 bytes wide */ + l_ihdr_data = (unsigned char *) opj_malloc(22); + if + (l_ihdr_data == 00) + { + return 00; + } + memset(l_ihdr_data,0,22); + + l_current_ihdr_ptr = l_ihdr_data; + + opj_write_bytes(l_current_ihdr_ptr,22,4); /* write box size */ + l_current_ihdr_ptr+=4; + opj_write_bytes(l_current_ihdr_ptr,JP2_IHDR, 4); /* IHDR */ + l_current_ihdr_ptr+=4; + opj_write_bytes(l_current_ihdr_ptr,jp2->h, 4); /* HEIGHT */ + l_current_ihdr_ptr+=4; + opj_write_bytes(l_current_ihdr_ptr, jp2->w, 4); /* WIDTH */ + l_current_ihdr_ptr+=4; + opj_write_bytes(l_current_ihdr_ptr, jp2->numcomps, 2); /* NC */ + l_current_ihdr_ptr+=2; + opj_write_bytes(l_current_ihdr_ptr, jp2->bpc, 1); /* BPC */ + ++l_current_ihdr_ptr; + opj_write_bytes(l_current_ihdr_ptr, jp2->C, 1); /* C : Always 7 */ + ++l_current_ihdr_ptr; + opj_write_bytes(l_current_ihdr_ptr, jp2->UnkC, 1); /* UnkC, colorspace unknown */ + ++l_current_ihdr_ptr; + opj_write_bytes(l_current_ihdr_ptr, jp2->IPR, 1); /* IPR, no intellectual property */ + ++l_current_ihdr_ptr; + *p_nb_bytes_written = 22; + return l_ihdr_data; +} + +/** + * Writes the Bit per Component box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +unsigned char * jp2_write_bpcc( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ) +{ + unsigned int i; + /* room for 8 bytes for box and 1 byte for each component */ + int l_bpcc_size = 8 + jp2->numcomps; + unsigned char * l_bpcc_data,* l_current_bpcc_ptr; + + // preconditions + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + + l_bpcc_data = (unsigned char *) opj_malloc(l_bpcc_size); + if + (l_bpcc_data == 00) + { + return 00; + } + memset(l_bpcc_data,0,l_bpcc_size); + + l_current_bpcc_ptr = l_bpcc_data; + + opj_write_bytes(l_current_bpcc_ptr,l_bpcc_size,4); /* write box size */ + l_current_bpcc_ptr += 4; + opj_write_bytes(l_current_bpcc_ptr,JP2_BPCC,4); /* BPCC */ + l_current_bpcc_ptr += 4; + + for + (i = 0; i < jp2->numcomps; ++i) + { + opj_write_bytes(l_current_bpcc_ptr, jp2->comps[i].bpcc, 1); /* write each component information */ + ++l_current_bpcc_ptr; + } + *p_nb_bytes_written = l_bpcc_size; + return l_bpcc_data; +} + +/** + * Reads a Bit per Component box. + * + * @param p_bpc_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_bpc_header_size pointer that will hold the size of the bpc header + * @param p_bpc_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, fale else. + */ +bool jp2_read_bpcc( + opj_jp2_t *jp2, + unsigned char * p_bpc_header_data, + unsigned int p_bpc_header_size, + opj_event_mgr_t * p_manager + ) +{ + unsigned int i; + + // preconditions + assert(p_bpc_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + // and length is relevant + if + (p_bpc_header_size != jp2->numcomps) + { + opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); + return false; + } + + // read info for each component + for + (i = 0; i < jp2->numcomps; ++i) + { + opj_read_bytes(p_bpc_header_data,&jp2->comps[i].bpcc ,1); /* read each BPCC component */ + ++p_bpc_header_data; + } + return true; +} + +/** + * Writes the Colour Specification box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +unsigned char *jp2_write_colr( + opj_jp2_t *jp2, + unsigned int * p_nb_bytes_written + ) +{ + /* room for 8 bytes for box 3 for common data and variable upon profile*/ + unsigned int l_colr_size = 11; + unsigned char * l_colr_data,* l_current_colr_ptr; + + // preconditions + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + + switch + (jp2->meth) + { + case 1 : + l_colr_size += 4; + break; + case 2 : + ++l_colr_size; + break; + default : + return 00; + } + + l_colr_data = (unsigned char *) opj_malloc(l_colr_size); + if + (l_colr_data == 00) + { + return 00; + } + memset(l_colr_data,0,l_colr_size); + l_current_colr_ptr = l_colr_data; + + opj_write_bytes(l_current_colr_ptr,l_colr_size,4); /* write box size */ + l_current_colr_ptr += 4; + opj_write_bytes(l_current_colr_ptr,JP2_COLR,4); /* BPCC */ + l_current_colr_ptr += 4; + + opj_write_bytes(l_current_colr_ptr, jp2->meth,1); /* METH */ + ++l_current_colr_ptr; + opj_write_bytes(l_current_colr_ptr, jp2->precedence,1); /* PRECEDENCE */ + ++l_current_colr_ptr; + opj_write_bytes(l_current_colr_ptr, jp2->approx,1); /* APPROX */ + ++l_current_colr_ptr; + + if + (jp2->meth == 1) + { + opj_write_bytes(l_current_colr_ptr, jp2->enumcs,4); /* EnumCS */ + } + else + { + opj_write_bytes(l_current_colr_ptr, 0, 1); /* PROFILE (??) */ + } + *p_nb_bytes_written = l_colr_size; + return l_colr_data; +} + +/** + * Reads the Colour Specification box. + * + * @param p_colr_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_colr_header_size pointer that will hold the size of the color header + * @param p_colr_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, fale else. +*/ +bool jp2_read_colr( + opj_jp2_t * jp2, + unsigned char * p_colr_header_data, + unsigned int p_colr_header_size, + opj_event_mgr_t * p_manager + ) +{ + // preconditions + assert(jp2 != 00); + assert(p_colr_header_data != 00); + assert(p_manager != 00); + + if + (p_colr_header_size < 3) + { + opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); + return false; + } + + opj_read_bytes(p_colr_header_data,&jp2->meth ,1); /* METH */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data,&jp2->precedence ,1); /* PRECEDENCE */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data,&jp2->approx ,1); /* APPROX */ + ++p_colr_header_data; + + + if + (jp2->meth == 1) + { + if + (p_colr_header_size != 7) + { + opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); + return false; + } + opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4); /* EnumCS */ + } + /*else + { + // do not care with profiles. + }*/ + return true; +} + +/** + * Writes the Jpeg2000 codestream Header box - JP2C Header box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +bool jp2_write_jp2c( + opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + unsigned int j2k_codestream_exit; + unsigned char l_data_header [8]; + + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header,j2k_codestream_exit - jp2->j2k_codestream_offset,4); /* size of codestream */ + opj_write_bytes(l_data_header + 4,JP2_JP2C,4); /* JP2C */ + + if + (! opj_stream_seek(cio,jp2->j2k_codestream_offset,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return false; + } + + if + (opj_stream_write_data(cio,l_data_header,8,p_manager) != 8) + { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return false; + } + + if + (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return false; + } + return true; +} + +/** + * Destroys a jpeg2000 file decompressor. + * + * @param jp2 a jpeg2000 file decompressor. + */ +void jp2_destroy(opj_jp2_t *jp2) +{ + if + (jp2) + { + /* destroy the J2K codec */ + j2k_destroy(jp2->j2k); + jp2->j2k = 00; + if + (jp2->comps) + { + opj_free(jp2->comps); + jp2->comps = 00; + } + if + (jp2->cl) + { + opj_free(jp2->cl); + jp2->cl = 00; + } + if + (jp2->m_validation_list) + { + opj_procedure_list_destroy(jp2->m_validation_list); + jp2->m_validation_list = 00; + } + if + (jp2->m_procedure_list) + { + opj_procedure_list_destroy(jp2->m_procedure_list); + jp2->m_procedure_list = 00; + } + opj_free(jp2); + } +} + + + + + +/* ----------------------------------------------------------------------- */ +/* JP2 encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_jp2_t* jp2_create(bool p_is_decoder) +{ + opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t)); + if + (jp2) + { + memset(jp2,0,sizeof(opj_jp2_t)); + /* create the J2K codec */ + if + (! p_is_decoder) + { + jp2->j2k = j2k_create_compress(); + } + else + { + jp2->j2k = j2k_create_decompress(); + } + if + (jp2->j2k == 00) + { + jp2_destroy(jp2); + return 00; + } + // validation list creation + jp2->m_validation_list = opj_procedure_list_create(); + if + (! jp2->m_validation_list) + { + jp2_destroy(jp2); + return 00; + } + + // execution list creation + jp2->m_procedure_list = opj_procedure_list_create(); + if + (! jp2->m_procedure_list) + { + jp2_destroy(jp2); + return 00; + } + } + return jp2; +} + +/** + * Excutes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param cio the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +bool jp2_exec ( + opj_jp2_t * jp2, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + bool (** l_procedure) (opj_jp2_t * jp2,opj_stream_private_t *,opj_event_mgr_t *) = 00; + bool l_result = true; + unsigned int l_nb_proc, i; + + // preconditions + assert(p_procedure_list != 00); + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (bool (**) (opj_jp2_t * jp2,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + for + (i=0;im_validation_list,cio,p_manager)) + { + return false; + } + + /* customization of the encoding */ + jp2_setup_header_writting(jp2); + + /* write header */ + if + (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) + { + return false; + } + return j2k_start_compress(jp2->j2k,cio,p_image,p_manager); +} + +/** + * Reads a jpeg2000 file header structure. + * + * @param cio the stream to read data from. + * @param jp2 the jpeg2000 file header structure. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +bool jp2_read_header( + opj_jp2_t *jp2, + opj_image_t ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the validation */ + jp2_setup_decoding_validation (jp2); + + /* customization of the encoding */ + jp2_setup_header_reading(jp2); + + /* validation of the parameters codec */ + if + (! jp2_exec(jp2,jp2->m_validation_list,cio,p_manager)) + { + return false; + } + + /* read header */ + if + (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) + { + return false; + } + return j2k_read_header( + jp2->j2k, + p_image, + p_tile_x0, + p_tile_y0, + p_tile_width, + p_tile_height, + p_nb_tiles_x, + p_nb_tiles_y, + cio, + p_manager); +} + +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +bool jp2_end_decompress(opj_jp2_t *jp2, opj_stream_private_t *cio, opj_event_mgr_t * p_manager) +{ + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the end encoding */ + jp2_setup_end_header_reading(jp2); + + /* write header */ + if + (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) + { + return false; + } + return j2k_end_decompress(jp2->j2k, cio, p_manager); +} + + +/** + * Ends the compression procedures and possibiliy add data to be read after the + * codestream. + */ +bool jp2_end_compress(opj_jp2_t *jp2, opj_stream_private_t *cio, opj_event_mgr_t * p_manager) +{ + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the end encoding */ + jp2_setup_end_header_writting(jp2); + + if + (! j2k_end_compress(jp2->j2k,cio,p_manager)) + { + return false; + } + /* write header */ + return jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager); +} + +/** +Encode an image into a JPEG-2000 file stream +@param jp2 JP2 compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +bool jp2_encode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager) +{ + return j2k_encode(jp2->j2k,cio,p_manager); +} +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_write_tile ( + opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + return j2k_write_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); +} + +/** + * Decode tile data. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_decode_tile ( + opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + return j2k_decode_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); +} +/** + * Reads a tile header. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_read_tile_header ( + opj_jp2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + return j2k_read_tile_header (p_jp2->j2k, + p_tile_index, + p_data_size, + p_tile_x0, + p_tile_y0, + p_tile_x1, + p_tile_y1, + p_nb_comps, + p_go_on, + p_stream, + p_manager); +} + +/** + * Sets up the procedures to do on writting header after the codestream. + * Developpers wanting to extend the library can add their own writting procedures. + */ +void jp2_setup_end_header_writting (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_write_jp2c ); + /* DEVELOPER CORNER, add your custom procedures */ +} + +/** + * Sets up the procedures to do on reading header. + * Developpers wanting to extend the library can add their own writting procedures. + */ +void jp2_setup_header_reading (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_read_header_procedure ); + /* DEVELOPER CORNER, add your custom procedures */ +} + +/** + * Sets up the procedures to do on reading header after the codestream. + * Developpers wanting to extend the library can add their own writting procedures. + */ +void jp2_setup_end_header_reading (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_read_header_procedure ); + /* DEVELOPER CORNER, add your custom procedures */ +} + + +/** + * The default validation procedure without any extension. + * + * @param jp2 the jpeg2000 codec to validate. + * @param cio the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +bool jp2_default_validation ( + opj_jp2_t * jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + bool l_is_valid = true; + unsigned int i; + + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + /* JPEG2000 codec validation */ + /*TODO*/ + + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (jp2->jp2_state == JP2_STATE_NONE); + /* make sure not reading a jp2h ???? WEIRD */ + l_is_valid &= (jp2->jp2_img_state == JP2_IMG_STATE_NONE); + + /* POINTER validation */ + /* make sure a j2k codec is present */ + l_is_valid &= (jp2->j2k != 00); + /* make sure a procedure list is present */ + l_is_valid &= (jp2->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (jp2->m_validation_list != 00); + + /* PARAMETER VALIDATION */ + /* number of components */ + l_is_valid &= (jp2->numcl > 0); + /* width */ + l_is_valid &= (jp2->h > 0); + /* height */ + l_is_valid &= (jp2->w > 0); + /* precision */ + for + (i = 0; i < jp2->numcomps; ++i) + { + l_is_valid &= (jp2->comps[i].bpcc > 0); + } + /* METH */ + l_is_valid &= ((jp2->meth > 0) && (jp2->meth < 3)); + + + + /* stream validation */ + /* back and forth is needed */ + l_is_valid &= opj_stream_has_seek(cio); + + return l_is_valid; + +} + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +void jp2_setup_encoding_validation (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + opj_procedure_list_add_procedure(jp2->m_validation_list, jp2_default_validation); + /* DEVELOPER CORNER, add your custom validation procedure */ +} + +/** + * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters + * are valid. Developpers wanting to extend the library can add their own validation procedures. + */ +void jp2_setup_decoding_validation (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + /* DEVELOPER CORNER, add your custom validation procedure */ +} + +/** + * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. + */ +void jp2_setup_header_writting (opj_jp2_t *jp2) +{ + // preconditions + assert(jp2 != 00); + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_write_jp ); + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_write_ftyp ); + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_write_jp2h ); + opj_procedure_list_add_procedure(jp2->m_procedure_list,jp2_skip_jp2c ); + + /* DEVELOPER CORNER, insert your custom procedures */ + +} + + +/** + * Skips the Jpeg2000 Codestream Header box - JP2C Header box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writting was successful. +*/ +bool jp2_skip_jp2c( + opj_jp2_t *jp2, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ) +{ + // preconditions + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + jp2->j2k_codestream_offset = opj_stream_tell(cio); + if + (opj_stream_skip(cio,8,p_manager) != 8) + { + return false; + } + return true; +} + +struct opj_image * jp2_decode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager) +{ + /* J2K decoding */ + struct opj_image * image = j2k_decode(jp2->j2k, cio, p_manager); + if + (!image) + { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode J2K image\n"); + return false; + } + + /* Set Image Color Space */ + if (jp2->enumcs == 16) + image->color_space = CLRSPC_SRGB; + else if (jp2->enumcs == 17) + image->color_space = CLRSPC_GRAY; + else if (jp2->enumcs == 18) + image->color_space = CLRSPC_SYCC; + else + image->color_space = CLRSPC_UNKNOWN; + return image; +} + +void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image,opj_event_mgr_t * p_manager) +{ + unsigned int i; + int depth_0, sign; + + if(!jp2 || !parameters || !image) + return; + + /* setup the J2K codec */ + /* ------------------- */ + + /* Check if number of components respects standard */ + if (image->numcomps < 1 || image->numcomps > 16384) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n"); + return; + } + + j2k_setup_encoder(jp2->j2k, parameters, image,p_manager); + + /* setup the JP2 codec */ + /* ------------------- */ + + /* Profile box */ + + jp2->brand = JP2_JP2; /* BR */ + jp2->minversion = 0; /* MinV */ + jp2->numcl = 1; + jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int)); + jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ + + /* Image Header box */ + + jp2->numcomps = image->numcomps; /* NC */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t)); + jp2->h = image->y1 - image->y0; /* HEIGHT */ + jp2->w = image->x1 - image->x0; /* WIDTH */ + /* BPC */ + depth_0 = image->comps[0].prec - 1; + sign = image->comps[0].sgnd; + jp2->bpc = depth_0 + (sign << 7); + for (i = 1; i < image->numcomps; i++) { + int depth = image->comps[i].prec - 1; + sign = image->comps[i].sgnd; + if (depth_0 != depth) + jp2->bpc = 255; + } + jp2->C = 7; /* C : Always 7 */ + jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ + jp2->IPR = 0; /* IPR, no intellectual property */ + + /* BitsPerComponent box */ + + for (i = 0; i < image->numcomps; i++) { + jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); + } + + /* Colour Specification box */ + + if ((image->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) { + jp2->meth = 1; /* METH: Enumerated colourspace */ + } else { + jp2->meth = 2; /* METH: Restricted ICC profile */ + } + if (jp2->meth == 1) { + if (image->color_space == 1) + jp2->enumcs = 16; /* sRGB as defined by IEC 61966–2–1 */ + else if (image->color_space == 2) + jp2->enumcs = 17; /* greyscale */ + else if (image->color_space == 3) + jp2->enumcs = 18; /* YUV */ + } else { + jp2->enumcs = 0; /* PROFILE (??) */ + } + jp2->precedence = 0; /* PRECEDENCE */ + jp2->approx = 0; /* APPROX */ + +} + +void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) +{ + if(!jp2 || !parameters) + return; + + /* setup the J2K codec */ + /* ------------------- */ + j2k_setup_decoder(jp2->j2k, parameters); +} +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_jp2 the jpeg2000 codec. + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager + * + * @return true if the area could be set. + */ +bool jp2_set_decode_area( + opj_jp2_t *p_jp2, + OPJ_INT32 p_start_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, + OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager + ) +{ + return j2k_set_decode_area(p_jp2->j2k,p_start_x,p_start_y,p_end_x,p_end_y,p_manager); +} + +#if 0 + + + + + +static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { + unsigned int i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_URL, 4); /* DBTL */ + cio_write(cio, 0, 1); /* VERS */ + cio_write(cio, 0, 3); /* FLAG */ + + if(Idx_file) { + for (i = 0; i < strlen(Idx_file); i++) { + cio_write(cio, Idx_file[i], 1); + } + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} +#endif diff --git a/v2/libopenjpeg/jp2.h b/v2/libopenjpeg/jp2.h new file mode 100755 index 00000000..67d6edcc --- /dev/null +++ b/v2/libopenjpeg/jp2.h @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __JP2_H +#define __JP2_H +/** +@file jp2.h +@brief The JPEG-2000 file format Reader/Writer (JP2) + +*/ +#include "openjpeg.h" + + + + +/********************************************************************************** + ********************************* FORWARD DECLARATIONS *************************** + **********************************************************************************/ +struct opj_j2k; +struct opj_procedure_list; +struct opj_event_mgr; +struct opj_stream_private; +struct opj_dparameters; +struct opj_cparameters; + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +#define JPIP_JPIP 0x6a706970 + +#define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */ +#define JP2_FTYP 0x66747970 /**< File type box */ +#define JP2_JP2H 0x6a703268 /**< JP2 header box */ +#define JP2_IHDR 0x69686472 /**< Image header box */ +#define JP2_COLR 0x636f6c72 /**< Colour specification box */ +#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ +#define JP2_URL 0x75726c20 /**< URL box */ +#define JP2_DBTL 0x6474626c /**< ??? */ +#define JP2_BPCC 0x62706363 /**< Bits per component box */ +#define JP2_JP2 0x6a703220 /**< File type fields */ + +/* ----------------------------------------------------------------------- */ + + +typedef enum +{ + JP2_STATE_NONE = 0x0, + JP2_STATE_SIGNATURE = 0x1, + JP2_STATE_FILE_TYPE = 0x2, + JP2_STATE_HEADER = 0x4, + JP2_STATE_CODESTREAM = 0x8, + JP2_STATE_END_CODESTREAM = 0x10, + JP2_STATE_UNKNOWN = 0x80000000 +} +JP2_STATE; + +typedef enum +{ + JP2_IMG_STATE_NONE = 0x0, + JP2_IMG_STATE_UNKNOWN = 0x80000000 +} +JP2_IMG_STATE; + +/** +JP2 component +*/ +typedef struct opj_jp2_comps +{ + unsigned int depth; + int sgnd; + unsigned int bpcc; +} +opj_jp2_comps_t; + +/** +JPEG-2000 file format reader/writer +*/ +typedef struct opj_jp2 +{ + /** handle to the J2K codec */ + struct opj_j2k *j2k; + /** list of validation procedures */ + struct opj_procedure_list * m_validation_list; + /** list of execution procedures */ + struct opj_procedure_list * m_procedure_list; + + /* width of image */ + unsigned int w; + /* height of image */ + unsigned int h; + /* number of components in the image */ + unsigned int numcomps; + unsigned int bpc; + unsigned int C; + unsigned int UnkC; + unsigned int IPR; + unsigned int meth; + unsigned int approx; + unsigned int enumcs; + unsigned int precedence; + unsigned int brand; + unsigned int minversion; + unsigned int numcl; + unsigned int *cl; + opj_jp2_comps_t *comps; + unsigned int j2k_codestream_offset; + unsigned int jp2_state; + unsigned int jp2_img_state; + +} +opj_jp2_t; + +/** +JP2 Box +*/ +typedef struct opj_jp2_box +{ + unsigned int length; + unsigned int type; +} +opj_jp2_box_t; + +typedef struct opj_jp2_header_handler +{ + /* marker value */ + int id; + /* action linked to the marker */ + bool (*handler) (opj_jp2_t *jp2,unsigned char * p_header_data, unsigned int p_header_size,struct opj_event_mgr * p_manager); +} +opj_jp2_header_handler_t; + + +typedef struct opj_jp2_img_header_writer_handler +{ + /* action to perform */ + unsigned char* (*handler) (opj_jp2_t *jp2, unsigned int * p_data_size); + /* result of the action : data */ + unsigned char * m_data; + /* size of data */ + unsigned int m_size; +} +opj_jp2_img_header_writer_handler_t; + + + + + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** + * Creates a jpeg2000 file decompressor. + * + * @return an empty jpeg2000 file codec. + */ +opj_jp2_t* jp2_create (bool p_is_decoder); + +/** +Destroy a JP2 decompressor handle +@param jp2 JP2 decompressor handle to destroy +*/ +void jp2_destroy(opj_jp2_t *jp2); + +/** +Setup the decoder decoding parameters using user parameters. +Decoding parameters are returned in jp2->j2k->cp. +@param jp2 JP2 decompressor handle +@param parameters decompression parameters +*/ +void jp2_setup_decoder(opj_jp2_t *jp2, struct opj_dparameters *parameters); + +/** + * Decode an image from a JPEG-2000 file stream + * @param jp2 JP2 decompressor handle + * @param cio Input buffer stream + * @param cstr_info Codestream information structure if required, NULL otherwise + * @return Returns a decoded image if successful, returns NULL otherwise +*/ +struct opj_image* jp2_decode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); +/** +Setup the encoder parameters using the current image and using user parameters. +Coding parameters are returned in jp2->j2k->cp. +@param jp2 JP2 compressor handle +@param parameters compression parameters +@param image input filled image +*/ +void jp2_setup_encoder(opj_jp2_t *jp2, struct opj_cparameters *parameters, struct opj_image *image,struct opj_event_mgr * p_manager); + +/** + * Starts a compression scheme, i.e. validates the codec parameters, writes the header. + * + * @param jp2 the jpeg2000 file codec. + * @param cio the stream object. + * + * @return true if the codec is valid. + */ +bool jp2_start_compress(opj_jp2_t *jp2, struct opj_stream_private *cio,struct opj_image * p_image,struct opj_event_mgr * p_manager); + +/** + * Ends the compression procedures and possibiliy add data to be read after the + * codestream. + */ +bool jp2_end_compress(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); + +/** +Encode an image into a JPEG-2000 file stream +@param jp2 JP2 compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +bool jp2_encode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); + +/** + * Reads a jpeg2000 file header structure. + * + * @param cio the stream to read data from. + * @param jp2 the jpeg2000 file header structure. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +bool jp2_read_header( + opj_jp2_t *jp2, + struct opj_image ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager + ); +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +bool jp2_end_decompress(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_write_tile ( + opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Decode tile data. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_decode_tile ( + opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Reads a tile header. + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +bool jp2_read_tile_header ( + opj_jp2_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_go_on, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ); +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_jp2 the jpeg2000 codec. + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager + * + * @return true if the area could be set. + */ +bool jp2_set_decode_area( + opj_jp2_t *p_jp2, + OPJ_INT32 p_start_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, + OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager + ); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __JP2_H */ + diff --git a/v2/libopenjpeg/jpt.c b/v2/libopenjpeg/jpt.c new file mode 100755 index 00000000..f09b72d8 --- /dev/null +++ b/v2/libopenjpeg/jpt.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "jpt.h" +#include "openjpeg.h" +#include "cio.h" +#include "event.h" +/* + * Read the information contains in VBAS [JPP/JPT stream message header] + * Store information (7 bits) in value + * @param p_cio the stream to read from. + * @param p_value the data to update + * @return the nb of bytes read or -1 if an io error occurred. + */ +bool jpt_read_VBAS_info(opj_stream_private_t * p_cio, OPJ_UINT32 * p_nb_bytes_read, OPJ_UINT32 * p_value, opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_elmt; + OPJ_UINT32 l_nb_bytes_read = 0; + + // read data till the MSB of the current byte is 1. + // concatenate 7 bits of data, last bit is finish flag + + // read data from the stream + + if + (opj_stream_read_data(p_cio,&l_elmt,1,p_manager) != 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data.\n"); + return false; + } + ++l_nb_bytes_read; + + // is the MSB equal to 1 ? + while + (l_elmt & 0x80) + { + // concatenate 7 bits of data, last bit is finish flag + *p_value = (*p_value << 7) | (l_elmt & 0x7f); + if + (opj_stream_read_data(p_cio,&l_elmt,1,p_manager) != 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data.\n"); + return false; + } + ++l_nb_bytes_read; + } + // concatenate 7 bits of data, last bit is finish flag + *p_value = (*p_value << 7) | (l_elmt & 0x7f); + * p_nb_bytes_read = l_nb_bytes_read; + return true; +} + +/* + * Initialize the value of the message header structure + * + */ +void jpt_init_msg_header(opj_jpt_msg_header_t * header) +{ + header->Id = 0; /* In-class Identifier */ + header->last_byte = 0; /* Last byte information */ + header->Class_Id = 0; /* Class Identifier */ + header->CSn_Id = 0; /* CSn : index identifier */ + header->Msg_offset = 0; /* Message offset */ + header->Msg_length = 0; /* Message length */ + header->Layer_nb = 0; /* Auxiliary for JPP case */ +} + +/* + * Re-initialize the value of the message header structure + * + * Only parameters always present in message header + * + */ +void jpt_reinit_msg_header(opj_jpt_msg_header_t * header) +{ + header->Id = 0; /* In-class Identifier */ + header->last_byte = 0; /* Last byte information */ + header->Msg_offset = 0; /* Message offset */ + header->Msg_length = 0; /* Message length */ +} + +/* + * Read the message header for a JPP/JPT - stream + * + */ +bool jpt_read_msg_header(opj_stream_private_t *cio, opj_jpt_msg_header_t *header, OPJ_UINT32 * p_nb_bytes_read, opj_event_mgr_t * p_manager) +{ + OPJ_BYTE elmt, Class = 0, CSn = 0; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_last_nb_bytes_read; + + + jpt_reinit_msg_header(header); + + /* ------------- */ + /* VBAS : Bin-ID */ + /* ------------- */ + if + (opj_stream_read_data(cio,&elmt,1,p_manager) != 1) + { + opj_event_msg(p_manager, EVT_ERROR, "Forbidden value encounter in message header !!\n"); + return false; + } + ++l_nb_bytes_read; + + /* See for Class and CSn */ + switch ((elmt >> 5) & 0x03) + { + case 0: + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + break; + case 1: + Class = 0; + CSn = 0; + break; + case 2: + Class = 1; + CSn = 0; + break; + case 3: + Class = 1; + CSn = 1; + break; + default: + break; + } + + /* see information on bits 'c' [p 10 : A.2.1 general, ISO/IEC FCD 15444-9] */ + if + (((elmt >> 4) & 0x01) == 1) + { + header->last_byte = 1; + } + + /* In-class identifier */ + header->Id |= (elmt & 0x0f); + if + ((elmt >> 7) == 1) + { + l_last_nb_bytes_read = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Id), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + } + + /* ------------ */ + /* VBAS : Class */ + /* ------------ */ + if (Class == 1) + { + header->Class_Id = 0; + l_last_nb_bytes_read = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Class_Id), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + } + + /* ---------- */ + /* VBAS : CSn */ + /* ---------- */ + if (CSn == 1) + { + header->CSn_Id = 0; + l_last_nb_bytes_read = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->CSn_Id), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + } + + /* ----------------- */ + /* VBAS : Msg_offset */ + /* ----------------- */ + l_last_nb_bytes_read = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Msg_offset), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + + /* ----------------- */ + /* VBAS : Msg_length */ + /* ----------------- */ + l_last_nb_bytes_read = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Msg_length), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + + /* ---------- */ + /* VBAS : Aux */ + /* ---------- */ + if ((header->Class_Id & 0x01) == 1) + { + header->Layer_nb = 0; + if + (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Layer_nb), p_manager)) + { + opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); + return false; + } + l_nb_bytes_read += l_last_nb_bytes_read; + } + * p_nb_bytes_read = l_nb_bytes_read; + return true; +} diff --git a/v2/libopenjpeg/jpt.h b/v2/libopenjpeg/jpt.h new file mode 100755 index 00000000..5e36d439 --- /dev/null +++ b/v2/libopenjpeg/jpt.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __JPT_H +#define __JPT_H +/** +@file jpt.h +@brief JPT-stream reader (JPEG 2000, JPIP) + +JPT-stream functions are implemented in J2K.C. +*/ +#include "openjpeg.h" +struct opj_stream_private; +struct opj_event_mgr; +/** +Message Header JPT stream structure +*/ +typedef struct opj_jpt_msg_header +{ + /** In-class Identifier */ + OPJ_UINT32 Id; + /** Last byte information */ + OPJ_UINT32 last_byte; + /** Class Identifier */ + OPJ_UINT32 Class_Id; + /** CSn : index identifier */ + OPJ_UINT32 CSn_Id; + /** Message offset */ + OPJ_UINT32 Msg_offset; + /** Message length */ + OPJ_UINT32 Msg_length; + /** Auxiliary for JPP case */ + OPJ_UINT32 Layer_nb; +} opj_jpt_msg_header_t; + +/* ----------------------------------------------------------------------- */ + +/** +Initialize the value of the message header structure +@param header Message header structure +*/ +void jpt_init_msg_header(opj_jpt_msg_header_t * header); + +/** + * Read the message header for a JPP/JPT - stream + * @param p_cio stream handle + * @param header JPT Message header structure + * @param p_manager user event manager to display nice messages. +*/ +bool jpt_read_msg_header( + struct opj_stream_private * p_cio, + opj_jpt_msg_header_t * p_header, + OPJ_UINT32 * p_nb_bytes_read, + struct opj_event_mgr * p_manager); + +#endif diff --git a/v2/libopenjpeg/mct.c b/v2/libopenjpeg/mct.c new file mode 100755 index 00000000..84356f34 --- /dev/null +++ b/v2/libopenjpeg/mct.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mct.h" +#include "fix.h" +#include "opj_malloc.h" + +/* */ +/* This table contains the norms of the basis function of the reversible MCT. */ +/* */ +static const OPJ_FLOAT64 mct_norms[3] = { 1.732, .8292, .8292 }; + +/* */ +/* This table contains the norms of the basis function of the irreversible MCT. */ +/* */ +static const OPJ_FLOAT64 mct_norms_real[3] = { 1.732, 1.805, 1.573 }; + + + +const OPJ_FLOAT64 * get_mct_norms () +{ + return mct_norms; +} + +const OPJ_FLOAT64 * get_mct_norms_real () +{ + return mct_norms_real; +} + + + +/* */ +/* Foward reversible MCT. */ +/* */ +void mct_encode( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_UINT32 i; + for(i = 0; i < n; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse reversible MCT. */ +/* */ +void mct_decode( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_UINT32 i; + for (i = 0; i < n; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of reversible MCT. */ +/* */ +OPJ_FLOAT64 mct_getnorm(OPJ_UINT32 compno) { + return mct_norms[compno]; +} + +/* */ +/* Foward irreversible MCT. */ +/* */ +void mct_encode_real( + OPJ_INT32* restrict c0, + OPJ_INT32* restrict c1, + OPJ_INT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_UINT32 i; + for(i = 0; i < n; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934); + OPJ_INT32 u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096); + OPJ_INT32 v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666); + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse irreversible MCT. */ +/* */ +void mct_decode_real( + OPJ_FLOAT32* restrict c0, + OPJ_FLOAT32* restrict c1, + OPJ_FLOAT32* restrict c2, + OPJ_UINT32 n) +{ + OPJ_UINT32 i; + for(i = 0; i < n; ++i) { + OPJ_FLOAT32 y = c0[i]; + OPJ_FLOAT32 u = c1[i]; + OPJ_FLOAT32 v = c2[i]; + OPJ_FLOAT32 r = y + (v * 1.402f); + OPJ_FLOAT32 g = y - (u * 0.34413f) - (v * (0.71414f)); + OPJ_FLOAT32 b = y + (u * 1.772f); + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of irreversible MCT. */ +/* */ +OPJ_FLOAT64 mct_getnorm_real(OPJ_UINT32 compno) { + return mct_norms_real[compno]; +} + +bool mct_encode_custom( + // MCT data + OPJ_BYTE * pCodingdata, + // size of components + OPJ_UINT32 n, + // components + OPJ_BYTE ** pData, + // nb of components (i.e. size of pData) + OPJ_UINT32 pNbComp, + // tells if the data is signed + OPJ_UINT32 isSigned) +{ + OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata; + OPJ_UINT32 i; + OPJ_UINT32 j; + OPJ_UINT32 k; + OPJ_UINT32 lNbMatCoeff = pNbComp * pNbComp; + OPJ_INT32 * lCurrentData = 00; + OPJ_INT32 * lCurrentMatrix = 00; + OPJ_INT32 ** lData = (OPJ_INT32 **) pData; + OPJ_UINT32 lMultiplicator = 1 << 13; + OPJ_INT32 * lMctPtr; + + lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof(OPJ_INT32)); + if + (! lCurrentData) + { + return false; + } + lCurrentMatrix = lCurrentData + pNbComp; + for + (i =0;i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MCT_H +#define __MCT_H +/** +@file mct.h +@brief Implementation of a multi-component transforms (MCT) + +The functions in MCT.C have for goal to realize reversible and irreversible multicomponent +transform. The functions in MCT.C are used by some function in TCD.C. +*/ +#include "openjpeg.h" +/** @defgroup MCT MCT - Implementation of a multi-component transform */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Apply a reversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void mct_encode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +/** +Apply a reversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void mct_decode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +/** +Get norm of the basis function used for the reversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +OPJ_FLOAT64 mct_getnorm(OPJ_UINT32 compno); + +/** +Apply an irreversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void mct_encode_real(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 n); +/** +Apply an irreversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void mct_decode_real(OPJ_FLOAT32* c0, OPJ_FLOAT32* c1, OPJ_FLOAT32* c2, OPJ_UINT32 n); +/** +Get norm of the basis function used for the irreversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +OPJ_FLOAT64 mct_getnorm_real(OPJ_UINT32 compno); + +bool mct_encode_custom( + // MCT data + OPJ_BYTE * p_coding_data, + // size of components + OPJ_UINT32 n, + // components + OPJ_BYTE ** p_data, + // nb of components (i.e. size of p_data) + OPJ_UINT32 p_nb_comp, + // tells if the data is signed + OPJ_UINT32 is_signed); + +bool mct_decode_custom( + // MCT data + OPJ_BYTE * pDecodingData, + // size of components + OPJ_UINT32 n, + // components + OPJ_BYTE ** pData, + // nb of components (i.e. size of pData) + OPJ_UINT32 pNbComp, + // tells if the data is signed + OPJ_UINT32 isSigned); + +void opj_calculate_norms(OPJ_FLOAT64 * pNorms,OPJ_UINT32 p_nb_comps,OPJ_FLOAT32 * pMatrix); + +const OPJ_FLOAT64 * get_mct_norms (); +const OPJ_FLOAT64 * get_mct_norms_real (); + + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MCT_H */ diff --git a/v2/libopenjpeg/mqc.c b/v2/libopenjpeg/mqc.c new file mode 100755 index 00000000..c899dfa9 --- /dev/null +++ b/v2/libopenjpeg/mqc.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mqc.h" +#include "t1.h" +#include "opj_malloc.h" + +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Output a byte, doing bit-stuffing if necessary. +After a 0xff byte, the next byte must be smaller than 0x90. +@param mqc MQC handle +*/ +static void mqc_byteout(opj_mqc_t *mqc); +/** +Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000 +@param mqc MQC handle +*/ +static void mqc_renorme(opj_mqc_t *mqc); +/** +Encode the most probable symbol +@param mqc MQC handle +*/ +static void mqc_codemps(opj_mqc_t *mqc); +/** +Encode the most least symbol +@param mqc MQC handle +*/ +static void mqc_codelps(opj_mqc_t *mqc); +/** +Fill mqc->c with 1's for flushing +@param mqc MQC handle +*/ +static void mqc_setbits(opj_mqc_t *mqc); +/** +FIXME: documentation ??? +@param mqc MQC handle +@return +*/ +static OPJ_INT32 mqc_mpsexchange(opj_mqc_t *mqc); +/** +FIXME: documentation ??? +@param mqc MQC handle +@return +*/ +static OPJ_INT32 mqc_lpsexchange(opj_mqc_t *mqc); +/** +Input a byte +@param mqc MQC handle +*/ +static void mqc_bytein(opj_mqc_t *mqc); +/** +Renormalize mqc->a and mqc->c while decoding +@param mqc MQC handle +*/ +static void mqc_renormd(opj_mqc_t *mqc); + +/*@}*/ + +/*@}*/ + +/* */ +/* This array defines all the possible states for a context. */ +/* */ +static opj_mqc_state_t mqc_states[47 * 2] = { + {0x5601, 0, &mqc_states[2], &mqc_states[3]}, + {0x5601, 1, &mqc_states[3], &mqc_states[2]}, + {0x3401, 0, &mqc_states[4], &mqc_states[12]}, + {0x3401, 1, &mqc_states[5], &mqc_states[13]}, + {0x1801, 0, &mqc_states[6], &mqc_states[18]}, + {0x1801, 1, &mqc_states[7], &mqc_states[19]}, + {0x0ac1, 0, &mqc_states[8], &mqc_states[24]}, + {0x0ac1, 1, &mqc_states[9], &mqc_states[25]}, + {0x0521, 0, &mqc_states[10], &mqc_states[58]}, + {0x0521, 1, &mqc_states[11], &mqc_states[59]}, + {0x0221, 0, &mqc_states[76], &mqc_states[66]}, + {0x0221, 1, &mqc_states[77], &mqc_states[67]}, + {0x5601, 0, &mqc_states[14], &mqc_states[13]}, + {0x5601, 1, &mqc_states[15], &mqc_states[12]}, + {0x5401, 0, &mqc_states[16], &mqc_states[28]}, + {0x5401, 1, &mqc_states[17], &mqc_states[29]}, + {0x4801, 0, &mqc_states[18], &mqc_states[28]}, + {0x4801, 1, &mqc_states[19], &mqc_states[29]}, + {0x3801, 0, &mqc_states[20], &mqc_states[28]}, + {0x3801, 1, &mqc_states[21], &mqc_states[29]}, + {0x3001, 0, &mqc_states[22], &mqc_states[34]}, + {0x3001, 1, &mqc_states[23], &mqc_states[35]}, + {0x2401, 0, &mqc_states[24], &mqc_states[36]}, + {0x2401, 1, &mqc_states[25], &mqc_states[37]}, + {0x1c01, 0, &mqc_states[26], &mqc_states[40]}, + {0x1c01, 1, &mqc_states[27], &mqc_states[41]}, + {0x1601, 0, &mqc_states[58], &mqc_states[42]}, + {0x1601, 1, &mqc_states[59], &mqc_states[43]}, + {0x5601, 0, &mqc_states[30], &mqc_states[29]}, + {0x5601, 1, &mqc_states[31], &mqc_states[28]}, + {0x5401, 0, &mqc_states[32], &mqc_states[28]}, + {0x5401, 1, &mqc_states[33], &mqc_states[29]}, + {0x5101, 0, &mqc_states[34], &mqc_states[30]}, + {0x5101, 1, &mqc_states[35], &mqc_states[31]}, + {0x4801, 0, &mqc_states[36], &mqc_states[32]}, + {0x4801, 1, &mqc_states[37], &mqc_states[33]}, + {0x3801, 0, &mqc_states[38], &mqc_states[34]}, + {0x3801, 1, &mqc_states[39], &mqc_states[35]}, + {0x3401, 0, &mqc_states[40], &mqc_states[36]}, + {0x3401, 1, &mqc_states[41], &mqc_states[37]}, + {0x3001, 0, &mqc_states[42], &mqc_states[38]}, + {0x3001, 1, &mqc_states[43], &mqc_states[39]}, + {0x2801, 0, &mqc_states[44], &mqc_states[38]}, + {0x2801, 1, &mqc_states[45], &mqc_states[39]}, + {0x2401, 0, &mqc_states[46], &mqc_states[40]}, + {0x2401, 1, &mqc_states[47], &mqc_states[41]}, + {0x2201, 0, &mqc_states[48], &mqc_states[42]}, + {0x2201, 1, &mqc_states[49], &mqc_states[43]}, + {0x1c01, 0, &mqc_states[50], &mqc_states[44]}, + {0x1c01, 1, &mqc_states[51], &mqc_states[45]}, + {0x1801, 0, &mqc_states[52], &mqc_states[46]}, + {0x1801, 1, &mqc_states[53], &mqc_states[47]}, + {0x1601, 0, &mqc_states[54], &mqc_states[48]}, + {0x1601, 1, &mqc_states[55], &mqc_states[49]}, + {0x1401, 0, &mqc_states[56], &mqc_states[50]}, + {0x1401, 1, &mqc_states[57], &mqc_states[51]}, + {0x1201, 0, &mqc_states[58], &mqc_states[52]}, + {0x1201, 1, &mqc_states[59], &mqc_states[53]}, + {0x1101, 0, &mqc_states[60], &mqc_states[54]}, + {0x1101, 1, &mqc_states[61], &mqc_states[55]}, + {0x0ac1, 0, &mqc_states[62], &mqc_states[56]}, + {0x0ac1, 1, &mqc_states[63], &mqc_states[57]}, + {0x09c1, 0, &mqc_states[64], &mqc_states[58]}, + {0x09c1, 1, &mqc_states[65], &mqc_states[59]}, + {0x08a1, 0, &mqc_states[66], &mqc_states[60]}, + {0x08a1, 1, &mqc_states[67], &mqc_states[61]}, + {0x0521, 0, &mqc_states[68], &mqc_states[62]}, + {0x0521, 1, &mqc_states[69], &mqc_states[63]}, + {0x0441, 0, &mqc_states[70], &mqc_states[64]}, + {0x0441, 1, &mqc_states[71], &mqc_states[65]}, + {0x02a1, 0, &mqc_states[72], &mqc_states[66]}, + {0x02a1, 1, &mqc_states[73], &mqc_states[67]}, + {0x0221, 0, &mqc_states[74], &mqc_states[68]}, + {0x0221, 1, &mqc_states[75], &mqc_states[69]}, + {0x0141, 0, &mqc_states[76], &mqc_states[70]}, + {0x0141, 1, &mqc_states[77], &mqc_states[71]}, + {0x0111, 0, &mqc_states[78], &mqc_states[72]}, + {0x0111, 1, &mqc_states[79], &mqc_states[73]}, + {0x0085, 0, &mqc_states[80], &mqc_states[74]}, + {0x0085, 1, &mqc_states[81], &mqc_states[75]}, + {0x0049, 0, &mqc_states[82], &mqc_states[76]}, + {0x0049, 1, &mqc_states[83], &mqc_states[77]}, + {0x0025, 0, &mqc_states[84], &mqc_states[78]}, + {0x0025, 1, &mqc_states[85], &mqc_states[79]}, + {0x0015, 0, &mqc_states[86], &mqc_states[80]}, + {0x0015, 1, &mqc_states[87], &mqc_states[81]}, + {0x0009, 0, &mqc_states[88], &mqc_states[82]}, + {0x0009, 1, &mqc_states[89], &mqc_states[83]}, + {0x0005, 0, &mqc_states[90], &mqc_states[84]}, + {0x0005, 1, &mqc_states[91], &mqc_states[85]}, + {0x0001, 0, &mqc_states[90], &mqc_states[86]}, + {0x0001, 1, &mqc_states[91], &mqc_states[87]}, + {0x5601, 0, &mqc_states[92], &mqc_states[92]}, + {0x5601, 1, &mqc_states[93], &mqc_states[93]}, +}; + +/* +========================================================== + local functions +========================================================== +*/ + +static void mqc_byteout(opj_mqc_t *mqc) { + if (*mqc->bp == 0xff) { + mqc->bp++; + *mqc->bp = mqc->c >> 20; + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + if ((mqc->c & 0x8000000) == 0) { /* ((mqc->c&0x8000000)==0) CHANGE */ + mqc->bp++; + *mqc->bp = mqc->c >> 19; + mqc->c &= 0x7ffff; + mqc->ct = 8; + } else { + (*mqc->bp)++; + if (*mqc->bp == 0xff) { + mqc->c &= 0x7ffffff; + mqc->bp++; + *mqc->bp = mqc->c >> 20; + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + mqc->bp++; + *mqc->bp = mqc->c >> 19; + mqc->c &= 0x7ffff; + mqc->ct = 8; + } + } + } +} + +static void mqc_renorme(opj_mqc_t *mqc) { + do { + mqc->a <<= 1; + mqc->c <<= 1; + mqc->ct--; + if (mqc->ct == 0) { + mqc_byteout(mqc); + } + } while ((mqc->a & 0x8000) == 0); +} + +static void mqc_codemps(opj_mqc_t *mqc) { + mqc->a -= (*mqc->curctx)->qeval; + if ((mqc->a & 0x8000) == 0) { + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->a = (*mqc->curctx)->qeval; + } else { + mqc->c += (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nmps; + mqc_renorme(mqc); + } else { + mqc->c += (*mqc->curctx)->qeval; + } +} + +static void mqc_codelps(opj_mqc_t *mqc) { + mqc->a -= (*mqc->curctx)->qeval; + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->c += (*mqc->curctx)->qeval; + } else { + mqc->a = (*mqc->curctx)->qeval; + } + *mqc->curctx = (*mqc->curctx)->nlps; + mqc_renorme(mqc); +} + +static void mqc_setbits(opj_mqc_t *mqc) { + OPJ_UINT32 tempc = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tempc) { + mqc->c -= 0x8000; + } +} + +static OPJ_INT32 mqc_mpsexchange(opj_mqc_t *mqc) { + OPJ_INT32 d; + if (mqc->a < (*mqc->curctx)->qeval) { + d = 1 - (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nlps; + } else { + d = (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nmps; + } + + return d; +} + +static OPJ_INT32 mqc_lpsexchange(opj_mqc_t *mqc) { + OPJ_INT32 d; + if (mqc->a < (*mqc->curctx)->qeval) { + mqc->a = (*mqc->curctx)->qeval; + d = (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nmps; + } else { + mqc->a = (*mqc->curctx)->qeval; + d = 1 - (*mqc->curctx)->mps; + *mqc->curctx = (*mqc->curctx)->nlps; + } + + return d; +} + +static void mqc_bytein(opj_mqc_t *mqc) { + if (mqc->bp != mqc->end) { + OPJ_UINT32 c; + if (mqc->bp + 1 != mqc->end) { + c = *(mqc->bp + 1); + } else { + c = 0xff; + } + if (*mqc->bp == 0xff) { + if (c > 0x8f) { + mqc->c += 0xff00; + mqc->ct = 8; + } else { + mqc->bp++; + mqc->c += c << 9; + mqc->ct = 7; + } + } else { + mqc->bp++; + mqc->c += c << 8; + mqc->ct = 8; + } + } else { + mqc->c += 0xff00; + mqc->ct = 8; + } +} + +static void mqc_renormd(opj_mqc_t *mqc) { + do { + if (mqc->ct == 0) { + mqc_bytein(mqc); + } + mqc->a <<= 1; + mqc->c <<= 1; + mqc->ct--; + } while (mqc->a < 0x8000); +} + +/* +========================================================== + MQ-Coder interface +========================================================== +*/ + +opj_mqc_t* mqc_create(void) { + opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t)); + return mqc; +} + +void mqc_destroy(opj_mqc_t *mqc) { + if + (mqc) + { + opj_free(mqc); + } +} + +OPJ_UINT32 mqc_numbytes(opj_mqc_t *mqc) { + return mqc->bp - mqc->start; +} + +void mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) { + mqc_setcurctx(mqc, 0); + mqc->a = 0x8000; + mqc->c = 0; + mqc->bp = bp - 1; + *(mqc->bp) = 0; + mqc->ct = 12; + /*if (*mqc->bp == 0xff) { + mqc->ct = 13; + }*/ + mqc->start = bp; +} + +void mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) { + if ((*mqc->curctx)->mps == d) { + mqc_codemps(mqc); + } else { + mqc_codelps(mqc); + } +} + +void mqc_flush(opj_mqc_t *mqc) { + mqc_setbits(mqc); + mqc->c <<= mqc->ct; + mqc_byteout(mqc); + mqc->c <<= mqc->ct; + mqc_byteout(mqc); + + if (*mqc->bp != 0xff) { + mqc->bp++; + } +} + +void mqc_bypass_init_enc(opj_mqc_t *mqc) { + mqc->c = 0; + mqc->ct = 8; + /*if (*mqc->bp == 0xff) { + mqc->ct = 7; + } */ +} + +void mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d) { + mqc->ct--; + mqc->c = mqc->c + (d << mqc->ct); + if (mqc->ct == 0) { + mqc->bp++; + *mqc->bp = mqc->c; + mqc->ct = 8; + if (*mqc->bp == 0xff) { + mqc->ct = 7; + } + mqc->c = 0; + } +} + +OPJ_UINT32 mqc_bypass_flush_enc(opj_mqc_t *mqc) { + OPJ_BYTE bit_padding; + + bit_padding = 0; + + if (mqc->ct != 0) { + while (mqc->ct > 0) { + mqc->ct--; + mqc->c += bit_padding << mqc->ct; + bit_padding = (bit_padding + 1) & 0x01; + } + mqc->bp++; + *mqc->bp = mqc->c; + mqc->ct = 8; + mqc->c = 0; + } + + return 1; +} + +void mqc_reset_enc(opj_mqc_t *mqc) { + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); +} + +OPJ_UINT32 mqc_restart_enc(opj_mqc_t *mqc) { + OPJ_UINT32 correction = 1; + + /* */ + OPJ_INT32 n = 27 - 15 - mqc->ct; + mqc->c <<= mqc->ct; + while (n > 0) { + mqc_byteout(mqc); + n -= mqc->ct; + mqc->c <<= mqc->ct; + } + mqc_byteout(mqc); + + return correction; +} + +void mqc_restart_init_enc(opj_mqc_t *mqc) { + /* */ + mqc_setcurctx(mqc, 0); + mqc->a = 0x8000; + mqc->c = 0; + mqc->ct = 12; + mqc->bp--; + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } +} + +void mqc_erterm_enc(opj_mqc_t *mqc) { + OPJ_INT32 k = 11 - mqc->ct + 1; + + while (k > 0) { + mqc->c <<= mqc->ct; + mqc->ct = 0; + mqc_byteout(mqc); + k -= mqc->ct; + } + + if (*mqc->bp != 0xff) { + mqc_byteout(mqc); + } +} + +void mqc_segmark_enc(opj_mqc_t *mqc) { + OPJ_UINT32 i; + mqc_setcurctx(mqc, 18); + + for (i = 1; i < 5; i++) { + mqc_encode(mqc, i % 2); + } +} + +void mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len) { + mqc_setcurctx(mqc, 0); + mqc->start = bp; + mqc->end = bp + len; + mqc->bp = bp; + if (len==0) mqc->c = 0xff << 16; + else mqc->c = *mqc->bp << 16; + mqc_bytein(mqc); + mqc->c <<= 7; + mqc->ct -= 7; + mqc->a = 0x8000; +} + +OPJ_UINT32 mqc_decode(opj_mqc_t *mqc) { + OPJ_INT32 d; + mqc->a -= (*mqc->curctx)->qeval; + if ((mqc->c >> 16) < (*mqc->curctx)->qeval) { + d = mqc_lpsexchange(mqc); + mqc_renormd(mqc); + } else { + mqc->c -= (*mqc->curctx)->qeval << 16; + if ((mqc->a & 0x8000) == 0) { + d = mqc_mpsexchange(mqc); + mqc_renormd(mqc); + } else { + d = (*mqc->curctx)->mps; + } + } + + return (OPJ_UINT32)d; +} + +void mqc_resetstates(opj_mqc_t *mqc) { + OPJ_UINT32 i; + for (i = 0; i < MQC_NUMCTXS; i++) { + mqc->ctxs[i] = mqc_states; + } +} + +void mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, OPJ_INT32 prob) { + mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)]; +} + + diff --git a/v2/libopenjpeg/mqc.h b/v2/libopenjpeg/mqc.h new file mode 100755 index 00000000..d4c5dd77 --- /dev/null +++ b/v2/libopenjpeg/mqc.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MQC_H +#define __MQC_H +/** +@file mqc.h +@brief Implementation of an MQ-Coder (MQC) + +The functions in MQC.C have for goal to realize the MQ-coder operations. The functions +in MQC.C are used by some function in T1.C. +*/ +#include "openjpeg.h" +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** +This struct defines the state of a context. +*/ +typedef struct opj_mqc_state { + /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */ + OPJ_UINT32 qeval; + /** the Most Probable Symbol (0 or 1) */ + OPJ_INT32 mps; + /** next state if the next encoded symbol is the MPS */ + struct opj_mqc_state *nmps; + /** next state if the next encoded symbol is the LPS */ + struct opj_mqc_state *nlps; +} opj_mqc_state_t; + +#define MQC_NUMCTXS 32 + +/** +MQ coder +*/ +typedef struct opj_mqc { + OPJ_UINT32 c; + OPJ_UINT32 a; + OPJ_UINT32 ct; + OPJ_BYTE *bp; + OPJ_BYTE *start; + OPJ_BYTE *end; + opj_mqc_state_t *ctxs[MQC_NUMCTXS]; + opj_mqc_state_t **curctx; +} opj_mqc_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new MQC handle +@return Returns a new MQC handle if successful, returns NULL otherwise +*/ +opj_mqc_t* mqc_create(void); +/** +Destroy a previously created MQC handle +@param mqc MQC handle to destroy +*/ +void mqc_destroy(opj_mqc_t *mqc); +/** +Return the number of bytes written/read since initialisation +@param mqc MQC handle +@return Returns the number of bytes already encoded +*/ +OPJ_UINT32 mqc_numbytes(opj_mqc_t *mqc); +/** +Reset the states of all the context of the coder/decoder +(each context is set to a state where 0 and 1 are more or less equiprobable) +@param mqc MQC handle +*/ +void mqc_resetstates(opj_mqc_t *mqc); +/** +Set the state of a particular context +@param mqc MQC handle +@param ctxno Number that identifies the context +@param msb The MSB of the new state of the context +@param prob Number that identifies the probability of the symbols for the new state of the context +*/ +void mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, OPJ_INT32 prob); +/** +Initialize the encoder +@param mqc MQC handle +@param bp Pointer to the start of the buffer where the bytes will be written +*/ +void mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp); +/** +Set the current context used for coding/decoding +@param mqc MQC handle +@param ctxno Number that identifies the context +*/ +#define mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] +/** +Encode a symbol using the MQ-coder +@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +void mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d); +/** +Flush the encoder, so that all remaining data is written +@param mqc MQC handle +*/ +void mqc_flush(opj_mqc_t *mqc); +/** +BYPASS mode switch, initialization operation. +JPEG 2000 p 505. +

Not fully implemented and tested !!

+@param mqc MQC handle +*/ +void mqc_bypass_init_enc(opj_mqc_t *mqc); +/** +BYPASS mode switch, coding operation. +JPEG 2000 p 505. +

Not fully implemented and tested !!

+@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +void mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d); +/** +BYPASS mode switch, flush operation +

Not fully implemented and tested !!

+@param mqc MQC handle +@return Returns 1 (always) +*/ +OPJ_UINT32 mqc_bypass_flush_enc(opj_mqc_t *mqc); +/** +RESET mode switch +@param mqc MQC handle +*/ +void mqc_reset_enc(opj_mqc_t *mqc); +/** +RESTART mode switch (TERMALL) +@param mqc MQC handle +@return Returns 1 (always) +*/ +OPJ_UINT32 mqc_restart_enc(opj_mqc_t *mqc); +/** +RESTART mode switch (TERMALL) reinitialisation +@param mqc MQC handle +*/ +void mqc_restart_init_enc(opj_mqc_t *mqc); +/** +ERTERM mode switch (PTERM) +@param mqc MQC handle +*/ +void mqc_erterm_enc(opj_mqc_t *mqc); +/** +SEGMARK mode switch (SEGSYM) +@param mqc MQC handle +*/ +void mqc_segmark_enc(opj_mqc_t *mqc); +/** +Initialize the decoder +@param mqc MQC handle +@param bp Pointer to the start of the buffer from which the bytes will be read +@param len Length of the input buffer +*/ +void mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Decode a symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +OPJ_UINT32 mqc_decode(opj_mqc_t *mqc); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MQC_H */ diff --git a/v2/libopenjpeg/openjpeg.c b/v2/libopenjpeg/openjpeg.c new file mode 100755 index 00000000..a635c78f --- /dev/null +++ b/v2/libopenjpeg/openjpeg.c @@ -0,0 +1,902 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef WIN32 +#include +#endif /* WIN32 */ + +#include "openjpeg.h" +#include "opj_malloc.h" +#include "j2k.h" +#include "jp2.h" +#include "event.h" +#include "cio.h" + +typedef struct opj_decompression +{ + bool (* opj_read_header) ( + void *p_codec, + opj_image_t **, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager); + opj_image_t* (* opj_decode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); + bool (*opj_read_tile_header)( + void * p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32* p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_should_go_on, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + bool (*opj_decode_tile_data)(void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private *p_cio,struct opj_event_mgr * p_manager); + bool (* opj_end_decompress) (void *p_codec,struct opj_stream_private *cio,struct opj_event_mgr * p_manager); + void (* opj_destroy) (void * p_codec); + void (*opj_setup_decoder) (void * p_codec,opj_dparameters_t * p_param); + bool (*opj_set_decode_area) (void * p_codec,OPJ_INT32 p_start_x,OPJ_INT32 p_end_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_y,struct opj_event_mgr * p_manager); + + +}opj_decompression_t; + +typedef struct opj_compression +{ + bool (* opj_start_compress) (void *p_codec,struct opj_stream_private *cio,struct opj_image * p_image, struct opj_event_mgr * p_manager); + bool (* opj_encode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); + bool (* opj_write_tile) (void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private * p_cio,struct opj_event_mgr * p_manager); + bool (* opj_end_compress) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); + void (* opj_destroy) (void * p_codec); + void (*opj_setup_encoder) (void * p_codec,opj_cparameters_t * p_param,struct opj_image * p_image, struct opj_event_mgr * p_manager); + +}opj_compression_t; + + + +typedef struct opj_codec_private +{ + union + { /* code-blocks informations */ + opj_decompression_t m_decompression; + opj_compression_t m_compression; + } m_codec_data; + void * m_codec; + opj_event_mgr_t m_event_mgr; + unsigned is_decompressor : 1; +} +opj_codec_private_t; + + + +/** + * Default callback function. + * Do nothing. + */ +void opj_default_callback (const char *msg, void *client_data) +{ +} + +void set_default_event_handler(opj_event_mgr_t * p_manager) +{ + p_manager->m_error_data = 00; + p_manager->m_warning_data = 00; + p_manager->m_info_data = 00; + p_manager->error_handler = opj_default_callback; + p_manager->info_handler = opj_default_callback; + p_manager->warning_handler = opj_default_callback; +} + +OPJ_UINT32 opj_read_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file) +{ + OPJ_UINT32 l_nb_read = fread(p_buffer,1,p_nb_bytes,p_file); + return l_nb_read ? l_nb_read : -1; +} + +OPJ_UINT32 opj_write_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file) +{ + return fwrite(p_buffer,1,p_nb_bytes,p_file); +} + +OPJ_SIZE_T opj_skip_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) +{ + if + (fseek(p_user_data,p_nb_bytes,SEEK_CUR)) + { + return -1; + } + return p_nb_bytes; +} + +bool opj_seek_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) +{ + if + (fseek(p_user_data,p_nb_bytes,SEEK_SET)) + { + return false; + } + return true; +} + +/* ---------------------------------------------------------------------- */ +#ifdef WIN32 +#ifndef OPJ_STATIC +BOOL APIENTRY +DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH : + break; + case DLL_PROCESS_DETACH : + break; + case DLL_THREAD_ATTACH : + case DLL_THREAD_DETACH : + break; + } + + return TRUE; +} +#endif /* OPJ_STATIC */ +#endif /* WIN32 */ + +/* ---------------------------------------------------------------------- */ + + +const char* OPJ_CALLCONV opj_version(void) { + return OPENJPEG_VERSION; +} + +opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) +{ + opj_codec_private_t *l_info = 00; + + l_info = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t)); + if + (!l_info) + { + return 00; + } + memset(l_info, 0, sizeof(opj_codec_private_t)); + l_info->is_decompressor = 1; + switch + (p_format) + { + case CODEC_J2K: + l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))j2k_decode; + l_info->m_codec_data.m_decompression.opj_end_decompress = (bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *))j2k_end_decompress; + l_info->m_codec_data.m_decompression.opj_read_header = (bool (*) ( + void *, + opj_image_t **, + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + struct opj_stream_private *, + struct opj_event_mgr * )) j2k_read_header; + l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))j2k_destroy; + l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) j2k_setup_decoder; + l_info->m_codec_data.m_decompression.opj_read_tile_header = (bool (*) ( + void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_UINT32 * , + bool *, + struct opj_stream_private *, + struct opj_event_mgr * )) j2k_read_tile_header; + l_info->m_codec_data.m_decompression.opj_decode_tile_data = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) j2k_decode_tile; + l_info->m_codec_data.m_decompression.opj_set_decode_area = (bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) j2k_set_decode_area; + l_info->m_codec = j2k_create_decompress(); + if + (! l_info->m_codec) + { + opj_free(l_info); + return 00; + } + break; + + case CODEC_JP2: + /* get a JP2 decoder handle */ + l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))jp2_decode; + l_info->m_codec_data.m_decompression.opj_end_decompress = (bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *)) jp2_end_decompress; + l_info->m_codec_data.m_decompression.opj_read_header = (bool (*) ( + void *, + opj_image_t **, + + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + OPJ_UINT32 * , + struct opj_stream_private *, + struct opj_event_mgr * )) jp2_read_header; + + l_info->m_codec_data.m_decompression.opj_read_tile_header = ( + bool (*) ( + void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, + OPJ_INT32*, + OPJ_INT32 * , + OPJ_INT32 * , + OPJ_UINT32 * , + bool *, + struct opj_stream_private *, + struct opj_event_mgr * )) jp2_read_tile_header; + + l_info->m_codec_data.m_decompression.opj_decode_tile_data = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) jp2_decode_tile; + + l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))jp2_destroy; + l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) jp2_setup_decoder; + l_info->m_codec_data.m_decompression.opj_set_decode_area = (bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area; + + + l_info->m_codec = jp2_create(true); + if + (! l_info->m_codec) + { + opj_free(l_info); + return 00; + } + break; + case CODEC_UNKNOWN: + case CODEC_JPT: + default: + opj_free(l_info); + return 00; + } + set_default_event_handler(&(l_info->m_event_mgr)); + return (opj_codec_t*) l_info; +} + +void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_info) +{ + if + (p_info) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_info; + if + (l_info->is_decompressor) + { + l_info->m_codec_data.m_decompression.opj_destroy(l_info->m_codec); + } + else + { + l_info->m_codec_data.m_compression.opj_destroy(l_info->m_codec); + } + l_info->m_codec = 00; + opj_free(l_info); + } +} + +void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters) { + if(parameters) { + memset(parameters, 0, sizeof(opj_dparameters_t)); + /* default decoding parameters */ + parameters->cp_layer = 0; + parameters->cp_reduce = 0; + + parameters->decod_format = -1; + parameters->cod_format = -1; +/* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_correct = false; + parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; + parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; +#endif /* USE_JPWL */ +/* <is_decompressor) + { + return false; + } + l_info->m_codec_data.m_decompression.opj_setup_decoder(l_info->m_codec,parameters); + return true; + } + return false; +} + +opj_image_t* OPJ_CALLCONV opj_decode(opj_codec_t *p_info, opj_stream_t *cio) +{ + if + (p_info && cio) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_info; + opj_stream_private_t * l_cio = (opj_stream_private_t *) cio; + if + (! l_info->is_decompressor) + { + return 00; + } + return l_info->m_codec_data.m_decompression.opj_decode(l_info->m_codec,l_cio,&(l_info->m_event_mgr)); + } + return 00; +} + +/** + * Writes a tile with the given data. + * + * @param p_compressor the jpeg2000 codec. + * @param p_tile_index the index of the tile to write. At the moment, the tiles must be written from 0 to n-1 in sequence. + * @param p_data pointer to the data to write. Data is arranged in sequence, data_comp0, then data_comp1, then ... NO INTERLEAVING should be set. + * @param p_data_size this value os used to make sure the data being written is correct. The size must be equal to the sum for each component of tile_width * tile_height * component_size. component_size can be 1,2 or 4 bytes, + * depending on the precision of the given component. + * @param p_stream the stream to write data to. + */ +bool opj_write_tile ( + opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ) +{ + if + (p_codec && p_stream && p_data) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; + if + (l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_compression.opj_write_tile(l_info->m_codec,p_tile_index,p_data,p_data_size,l_cio,&(l_info->m_event_mgr)); + } + return false; +} + +/** + * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. + */ +bool opj_read_tile_header( + opj_codec_t *p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_should_go_on, + opj_stream_t * p_stream) +{ + if + (p_codec && p_stream && p_data_size && p_tile_index) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; + if + (! l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_decompression.opj_read_tile_header( + l_info->m_codec, + p_tile_index, + p_data_size, + p_tile_x0, + p_tile_y0, + p_tile_x1, + p_tile_y1, + p_nb_comps, + p_should_go_on, + l_cio,&(l_info->m_event_mgr)); + } + return false; +} + +/** + * Reads a tile data. This function is compulsory and allows one to decode tile data. opj_read_tile_header should be called before. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile being decoded, this should be the value set by opj_read_tile_header. + * @param p_data pointer to a memory block that will hold the decoded data. + * @param p_data_size size of p_data. p_data_size should be bigger or equal to the value set by opj_read_tile_header. + * @param p_stream the stream to decode. + * + * @return true if the data could be decoded. + */ +bool opj_decode_tile_data( + opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ) +{ + if + (p_codec && p_data && p_stream) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; + if + (! l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_decompression.opj_decode_tile_data(l_info->m_codec,p_tile_index,p_data,p_data_size,l_cio,&(l_info->m_event_mgr)); + } + return false; +} + +bool OPJ_CALLCONV opj_read_header ( + opj_codec_t *p_codec, + opj_image_t ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + opj_stream_t *p_cio) +{ + if + (p_codec && p_cio) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; + if + (! l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_decompression.opj_read_header( + l_info->m_codec, + p_image, + p_tile_x0, + p_tile_y0, + p_tile_width, + p_tile_height, + p_nb_tiles_x, + p_nb_tiles_y, + l_cio, + &(l_info->m_event_mgr)); + } + return false; +} + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_codec the jpeg2000 codec. + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * + * @return true if the area could be set. + */ +bool opj_set_decode_area( + opj_codec_t *p_codec, + OPJ_INT32 p_start_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, + OPJ_INT32 p_end_y + ) +{ + if + (p_codec) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + if + (! l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_decompression.opj_set_decode_area( + l_info->m_codec, + p_start_x, + p_start_y, + p_end_x, + p_end_y, + &(l_info->m_event_mgr)); + + } + return false; + +} + +bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio) +{ + if + (p_codec && p_cio) + { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; + if + (! l_info->is_decompressor) + { + return false; + } + return l_info->m_codec_data.m_decompression.opj_end_decompress(l_info->m_codec,l_cio,&(l_info->m_event_mgr)); + } + return false; +} + + +opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) +{ + opj_codec_private_t *l_info = 00; + + l_info = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t)); + if + (!l_info) + { + return 00; + } + memset(l_info, 0, sizeof(opj_codec_private_t)); + l_info->is_decompressor = 0; + switch + (p_format) + { + case CODEC_J2K: + l_info->m_codec_data.m_compression.opj_encode = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr * )) j2k_encode; + l_info->m_codec_data.m_compression.opj_end_compress = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr *)) j2k_end_compress; + l_info->m_codec_data.m_compression.opj_start_compress = (bool (*) (void *,struct opj_stream_private *,struct opj_image * , struct opj_event_mgr *)) j2k_start_compress; + l_info->m_codec_data.m_compression.opj_write_tile = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr *)) j2k_write_tile; + l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) j2k_destroy; + l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (void *,opj_cparameters_t *,struct opj_image *, struct opj_event_mgr * )) j2k_setup_encoder; + + l_info->m_codec = j2k_create_compress(); + if + (! l_info->m_codec) + { + opj_free(l_info); + return 00; + } + break; + + case CODEC_JP2: + /* get a JP2 decoder handle */ + l_info->m_codec_data.m_compression.opj_encode = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr * )) jp2_encode; + l_info->m_codec_data.m_compression.opj_end_compress = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr *)) jp2_end_compress; + l_info->m_codec_data.m_compression.opj_start_compress = (bool (*) (void *,struct opj_stream_private *,struct opj_image * , struct opj_event_mgr *)) jp2_start_compress; + l_info->m_codec_data.m_compression.opj_write_tile = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr *)) jp2_write_tile; + l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) jp2_destroy; + l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (void *,opj_cparameters_t *,struct opj_image *, struct opj_event_mgr * )) jp2_setup_encoder; + + l_info->m_codec = jp2_create(false); + if + (! l_info->m_codec) + { + opj_free(l_info); + return 00; + } + break; + case CODEC_UNKNOWN: + case CODEC_JPT: + default: + opj_free(l_info); + return 00; + } + set_default_event_handler(&(l_info->m_event_mgr)); + return (opj_codec_t*) l_info; +} + +void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters) { + if(parameters) { + memset(parameters, 0, sizeof(opj_cparameters_t)); + /* default coding parameters */ + parameters->cp_cinema = OFF; + parameters->max_comp_size = 0; + parameters->numresolution = 6; + parameters->cp_rsiz = STD_RSIZ; + parameters->cblockw_init = 64; + parameters->cblockh_init = 64; + parameters->prog_order = LRCP; + parameters->roi_compno = -1; /* no ROI */ + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + parameters->tp_on = 0; + parameters->decod_format = -1; + parameters->cod_format = -1; +/* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_epc_on = false; + parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_hprot_TPH[i] = 0; /* absent */ + } + }; + { + int i; + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */ + parameters->jpwl_pprot_packno[i] = -1; /* unassigned */ + parameters->jpwl_pprot[i] = 0; /* absent */ + } + }; + parameters->jpwl_sens_size = 0; /* 0 means no ESD */ + parameters->jpwl_sens_addr = 0; /* 0 means auto */ + parameters->jpwl_sens_range = 0; /* 0 means packet */ + parameters->jpwl_sens_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_sens_TPH[i] = -1; /* absent */ + } + }; +#endif /* USE_JPWL */ +/* <is_decompressor) + { + l_codec->m_codec_data.m_compression.opj_setup_encoder(l_codec->m_codec,parameters,image,&(l_codec->m_event_mgr)); + return true; + } + } + return false; +} + +bool OPJ_CALLCONV opj_encode(opj_codec_t *p_info, opj_stream_t *cio) +{ + if + (p_info && cio) + { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info; + opj_stream_private_t * l_cio = (opj_stream_private_t *) cio; + if + (! l_codec->is_decompressor) + { + l_codec->m_codec_data.m_compression.opj_encode(l_codec->m_codec,l_cio,&(l_codec->m_event_mgr)); + return true; + } + } + return false; + +} + +bool OPJ_CALLCONV opj_start_compress (opj_codec_t *p_codec,opj_image_t * p_image,opj_stream_t *p_cio) +{ + if + (p_codec && p_cio) + { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; + if + (! l_codec->is_decompressor) + { + return l_codec->m_codec_data.m_compression.opj_start_compress(l_codec->m_codec,l_cio,p_image,&(l_codec->m_event_mgr)); + } + } + return false; +} + +bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio) +{ + if + (p_codec && p_cio) + { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; + if + (! l_codec->is_decompressor) + { + return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec,l_cio,&(l_codec->m_event_mgr)); + } + } + return false; + +} + +bool OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if + (! l_codec) + { + return false; + } + l_codec->m_event_mgr.info_handler = p_callback; + l_codec->m_event_mgr.m_info_data = p_user_data; + return true; +} + +bool OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if + (! l_codec) + { + return false; + } + l_codec->m_event_mgr.warning_handler = p_callback; + l_codec->m_event_mgr.m_warning_data = p_user_data; + return true; +} + +bool OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if + (! l_codec) + { + return false; + } + l_codec->m_event_mgr.error_handler = p_callback; + l_codec->m_event_mgr.m_error_data = p_user_data; + return true; +} + +/*bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_stream_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { + if(cinfo && cio && image) { + switch(cinfo->codec_format) { + case CODEC_J2K: + return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, (opj_stream_private_t *) cio, image, cstr_info); + case CODEC_JP2: + return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, (opj_stream_private_t *) cio, image, cstr_info); + case CODEC_JPT: + case CODEC_UNKNOWN: + default: + break; + } + } + return false; +}*/ + +void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { + if + (cstr_info) + { + int tileno; + for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) { + opj_tile_info_t *tile_info = &cstr_info->tile[tileno]; + opj_free(tile_info->thresh); + opj_free(tile_info->packet); + opj_free(tile_info->tp); + } + opj_free(cstr_info->tile); + opj_free(cstr_info->marker); + } +} + +bool opj_set_MCT(opj_cparameters_t *parameters,OPJ_FLOAT32 * pEncodingMatrix,OPJ_INT32 * p_dc_shift,OPJ_UINT32 pNbComp) +{ + OPJ_UINT32 l_matrix_size = pNbComp * pNbComp * sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_dc_shift_size = pNbComp * sizeof(OPJ_INT32); + OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size; + // add MCT capability + parameters->cp_rsiz |= 0x8100; + parameters->irreversible = 1; + // use array based MCT + parameters->tcp_mct = 2; + parameters->mct_data = opj_malloc(l_mct_total_size); + if + (! parameters->mct_data) + { + return false; + } + memcpy(parameters->mct_data,pEncodingMatrix,l_matrix_size); + memcpy(((OPJ_BYTE *) parameters->mct_data) + l_matrix_size,p_dc_shift,l_dc_shift_size); + return true; +} + +/** + * Restricts the decoding to the given image area. + * + * @param parameters the parameters to update. + * @param p_start_x the starting x position of the area to decode. + * @param p_start_y the starting y position of the area to decode. + * @param p_end_x the x end position of the area to decode. + * @param p_end_x the y end position of the area to decode. + */ +OPJ_API bool OPJ_CALLCONV opj_restrict_decoding (opj_dparameters_t *parameters,OPJ_INT32 p_start_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_x,OPJ_INT32 p_end_y) +{ + parameters->m_use_restrict_decode = 1; + parameters->m_decode_start_x = p_start_x; + parameters->m_decode_start_y = p_start_y; + parameters->m_decode_end_x = p_end_x; + parameters->m_decode_end_y = p_end_y; + return true; +} diff --git a/v2/libopenjpeg/openjpeg.h b/v2/libopenjpeg/openjpeg.h new file mode 100755 index 00000000..e52bf41f --- /dev/null +++ b/v2/libopenjpeg/openjpeg.h @@ -0,0 +1,1079 @@ + /* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OPENJPEG_H +#define OPENJPEG_H + +#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__)) + #define OPJ_API + #define OPJ_CALLCONV +#else + #define OPJ_CALLCONV __stdcall + #ifdef OPJ_EXPORTS + #define OPJ_API __declspec(dllexport) + #else + #define OPJ_API __declspec(dllimport) + #endif /* OPJ_EXPORTS */ +#endif /* !OPJ_STATIC || !WIN32 */ + +#ifndef __cplusplus + #if defined(HAVE_STDBOOL_H) + #include + #else + #if !defined(bool) + #define bool int + #endif + #if !defined(true) + #define true 1 + #endif + #if !defined(false) + #define false 0 + #endif + #endif +#endif /* __cplusplus */ +typedef unsigned int OPJ_UINT32; +typedef int OPJ_INT32; +typedef unsigned short OPJ_UINT16; +typedef short OPJ_INT16; +typedef char OPJ_CHAR; +typedef unsigned char OPJ_BYTE; +typedef unsigned int OPJ_SIZE_T; +typedef double OPJ_FLOAT64; +typedef float OPJ_FLOAT32; +#if defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 OPJ_INT64; +#else + typedef long long OPJ_INT64; +#endif + +#define OPENJPEG_VERSION "1.2.0" +/* +========================================================== + Compiler directives +========================================================== +*/ +#include + + + + + +/* +========================================================== + Useful constant definitions +========================================================== +*/ + +#define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */ +#define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ +#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ +#define J2K_DEFAULT_NB_SEGS 10 +#define J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */ +#define J2K_DEFAULT_HEADER_SIZE 1000 +#define J2K_MCC_DEFAULT_NB_RECORDS 10 +#define J2K_MCT_DEFAULT_NB_RECORDS 10 + +/* UniPG>> */ +#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */ +#define JPWL_PRIVATEINDEX_NAME "jpwl_index_privatefilename" /**< index file name used when JPWL is on */ +#define JPWL_EXPECTED_COMPONENTS 3 /**< Expect this number of components, so you'll find better the first EPB */ +#define JPWL_MAXIMUM_TILES 8192 /**< Expect this maximum number of tiles, to avoid some crashes */ +#define JPWL_MAXIMUM_HAMMING 2 /**< Expect this maximum number of bit errors in marker id's */ +#define JPWL_MAXIMUM_EPB_ROOM 65450 /**< Expect this maximum number of bytes for composition of EPBs */ +/* <> */ + /**@name JPWL encoding parameters */ + /*@{*/ + /** enables writing of EPC in MH, thus activating JPWL */ + bool jpwl_epc_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int jpwl_hprot_MH; + /** tile number of header protection specification (>=0) */ + int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int jpwl_pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0=no/1/2 bytes) */ + int jpwl_sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int jpwl_sens_addr; + /** sensitivity range (0-3) */ + int jpwl_sens_range; + /** sensitivity method for MH (-1=no,0-7) */ + int jpwl_sens_MH; + /** tile number of sensitivity specification (>=0) */ + int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1=no,0-7) */ + int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS]; + /*@}*/ +/* <> */ + /**@name JPWL decoding parameters */ + /*@{*/ + /** activates the JPWL correction capabilities */ + bool jpwl_correct; + /** expected number of components */ + int jpwl_exp_comps; + /** maximum number of tiles */ + int jpwl_max_tiles; + + /** use restrictive decoding ? */ + OPJ_UINT32 m_use_restrict_decode : 1; + /*@}*/ +/* <> */ +/** +Marker structure +*/ +typedef struct opj_marker_info_t { + /** marker type */ + unsigned short int type; + /** position in codestream */ + int pos; + /** length, marker val included */ + int len; +} opj_marker_info_t; +/* <> */ + /** number of markers */ + int marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + int maxmarknum; +/* <cp. +@param dinfo decompressor handle +@param parameters decompression parameters +*/ +OPJ_API bool OPJ_CALLCONV opj_setup_decoder(opj_codec_t *dinfo, opj_dparameters_t *parameters); +#endif + +/** +Decode an image from a JPEG-2000 codestream +@param dinfo decompressor handle +@param cio Input buffer stream +@return Returns a decoded image if successful, returns NULL otherwise +*/ +OPJ_API opj_image_t* OPJ_CALLCONV opj_decode(opj_codec_t *p_decompressor, opj_stream_t * cio); + +/** + * Writes a tile with the given data. + * + * @param p_compressor the jpeg2000 codec. + * @param p_tile_index the index of the tile to write. At the moment, the tiles must be written from 0 to n-1 in sequence. + * @param p_data pointer to the data to write. Data is arranged in sequence, data_comp0, then data_comp1, then ... NO INTERLEAVING should be set. + * @param p_data_size this value os used to make sure the data being written is correct. The size must be equal to the sum for each component of tile_width * tile_height * component_size. component_size can be 1,2 or 4 bytes, + * depending on the precision of the given component. + * @param p_stream the stream to write data to. + * + * @return true if the data could be written. + */ +OPJ_API bool OPJ_CALLCONV opj_write_tile ( + opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ); + +/** + * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. + */ +OPJ_API bool OPJ_CALLCONV opj_read_tile_header( + opj_codec_t *p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + bool * p_should_go_on, + opj_stream_t * p_stream); + + +/** + * Reads a tile data. This function is compulsory and allows one to decode tile data. opj_read_tile_header should be called before. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile being decoded, this should be the value set by opj_read_tile_header. + * @param p_data pointer to a memory block that will hold the decoded data. + * @param p_data_size size of p_data. p_data_size should be bigger or equal to the value set by opj_read_tile_header. + * @param p_stream the stream to decode. + * + * @return true if the data could be decoded. + */ +OPJ_API bool OPJ_CALLCONV opj_decode_tile_data( + opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ); + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_codec the jpeg2000 codec. + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * + * @return true if the area could be set. + */ +OPJ_API bool OPJ_CALLCONV opj_set_decode_area( + opj_codec_t *p_codec, + OPJ_INT32 p_start_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, + OPJ_INT32 p_end_y + ); + + +/** +Decode an image from a JPEG-2000 codestream and extract the codestream information +@param dinfo decompressor handle +@param cio Input buffer stream +@param cstr_info Codestream information structure if needed afterwards, NULL otherwise +@return Returns a decoded image if successful, returns NULL otherwise +*/ +//OPJ_API opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_stream_t cio, opj_codestream_info_t *cstr_info); +/** +Creates a J2K/JP2 compression structure +@param format Coder to select +@return Returns a handle to a compressor if successful, returns NULL otherwise +*/ +OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format); + +/** +Destroy a decompressor handle +@param dinfo decompressor handle to destroy +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec); + +/** +Set encoding parameters to default values, that means : +
    +
  • Lossless +
  • 1 tile +
  • Size of precinct : 2^15 x 2^15 (means 1 precinct) +
  • Size of code-block : 64 x 64 +
  • Number of resolutions: 6 +
  • No SOP marker in the codestream +
  • No EPH marker in the codestream +
  • No sub-sampling in x or y direction +
  • No mode switch activated +
  • Progression order: LRCP +
  • No index file +
  • No ROI upshifted +
  • No offset of the origin of the image +
  • No offset of the origin of the tiles +
  • Reversible DWT 5-3 +
+@param parameters Compression parameters +*/ +OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters); + +/** + * Sets the MCT matrix to use. + * + * @param parameters the parameters to change. + * @param pEncodingMatrix the encoding matrix. + * @param p_dc_shift the dc shift coefficients to use. + * @param pNbComp the number of components of the image. + * + * @return true if the parameters could be set. + */ +OPJ_API bool OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters,OPJ_FLOAT32 * pEncodingMatrix,OPJ_INT32 * p_dc_shift,OPJ_UINT32 pNbComp); + +/** + * Restricts the decoding to the given image area. + * + * @param parameters the parameters to update. + * @param p_start_x the starting x position of the area to decode. + * @param p_start_y the starting y position of the area to decode. + * @param p_end_x the x end position of the area to decode. + * @param p_end_x the y end position of the area to decode. + */ +OPJ_API bool OPJ_CALLCONV opj_restrict_decoding (opj_dparameters_t *parameters,OPJ_INT32 p_start_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_x,OPJ_INT32 p_end_y); + +#ifdef USE_OPJ_DEPRECATED +#ifdef _MSC_VER +#pragma message ("warning, opj_setup_encoder is deprecated") +#else +#warning "warning, opj_setup_encoder is deprecated" +#endif +/** +Setup the encoder parameters using the current image and using user parameters. +@param cinfo Compressor handle +@param parameters Compression parameters +@param image Input filled image +*/ +OPJ_API bool OPJ_CALLCONV opj_setup_encoder(opj_codec_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image); +#endif + +/** + * Decodes an image header. + * + * @param p_codec codec to use to decode the image. + * @param p_image pointer to a previously created image. + * @param p_tile_x0 pointer to a value that will hold the reference point x0 of the tiling grid. + * @param p_tile_y0 pointer to a value that will hold the reference point y0 of the tiling grid. + * @param p_tile_width pointer to a value that will hold the size in x of a tile in the grid. + * @param p_tile_height pointer to a value that will hold the size in y of a tile in the grid. + * @param p_nb_tiles_x pointer to a value that will hold the number of tiles in the x direction. + * @param p_nb_tiles_y pointer to a value that will hold the number of tiles in the y direction. + */ +OPJ_API bool OPJ_CALLCONV opj_read_header ( + opj_codec_t *p_codec, + opj_image_t ** p_image, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_UINT32 * p_tile_width, + OPJ_UINT32 * p_tile_height, + OPJ_UINT32 * p_nb_tiles_x, + OPJ_UINT32 * p_nb_tiles_y, + opj_stream_t *p_cio); + + +OPJ_API bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio); +/** +Encode an image into a JPEG-2000 codestream +@param cinfo compressor handle +@param cio Output buffer stream +@param image Image to encode +@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci() +@return Returns true if successful, returns false otherwise +*/ +OPJ_API bool OPJ_CALLCONV opj_encode(opj_codec_t *cinfo, opj_stream_t * cio); + +OPJ_API bool OPJ_CALLCONV opj_start_compress (opj_codec_t *p_codec,opj_image_t * p_image,opj_stream_t *p_cio); + +OPJ_API bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio); +/** +Encode an image into a JPEG-2000 codestream and extract the codestream information +@param cinfo compressor handle +@param cio Output buffer stream +@param image Image to encode +@param cstr_info Codestream information structure if needed afterwards, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +//OPJ_API bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_stream_t cio, opj_image_t *image, opj_codestream_info_t *cstr_info); +/** +Destroy Codestream information after compression or decompression +@param cstr_info Codestream information structure +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info); + +//============================================================================== +//============================================================================== +/** profiling part */ +#ifdef _PROFILE +void _ProfInit(void); +void _ProfPrint(void); +#define PROFINIT() _ProfInit(); +#define PROFSAVE(file) _ProfSave(file); +#define PROFPRINT() _ProfPrint(); +#else +#define PROFINIT() +#define PROFSAVE(file) +#define PROFPRINT() +#endif // !_PROFILE + +#ifdef __cplusplus +} +#endif + +#endif /* OPENJPEG_H */ + + diff --git a/v2/libopenjpeg/opj_configure.h b/v2/libopenjpeg/opj_configure.h new file mode 100755 index 00000000..60058cbd --- /dev/null +++ b/v2/libopenjpeg/opj_configure.h @@ -0,0 +1,16 @@ +/* + * here is where system comupted values get stored these values should only + * change when the target compile platform changes + */ + +/* what byte order */ +#ifndef __OPJ_CONFIGURE_H +#define __OPJ_CONFIGURE_H +/* #undef CMAKE_WORDS_BIGENDIAN */ +#ifdef CMAKE_WORDS_BIGENDIAN + #define OPJ_BIG_ENDIAN +#else + #define OPJ_LITTLE_ENDIAN +#endif + +#endif /* __OPJ_CONFIGURE_H */ diff --git a/v2/libopenjpeg/opj_includes.h b/v2/libopenjpeg/opj_includes.h new file mode 100755 index 00000000..371db8aa --- /dev/null +++ b/v2/libopenjpeg/opj_includes.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef OPJ_INCLUDES_H +#define OPJ_INCLUDES_H + +/* + ========================================================== + Standard includes used by the library + ========================================================== +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + ========================================================== + OpenJPEG interface + ========================================================== + */ + +/* + ========================================================== + OpenJPEG modules + ========================================================== +*/ + +/* Ignore GCC attributes if this is not GCC */ +#ifndef __GNUC__ + #define __attribute__(x) /* __attribute__(x) */ +#endif + +/* +The inline keyword is supported by C99 but not by C90. +Most compilers implement their own version of this keyword ... +*/ +#ifndef INLINE + #if defined(_MSC_VER) + #define INLINE __inline + #elif defined(__GNUC__) + #define INLINE __inline__ + #elif defined(__MWERKS__) + #define INLINE inline + #else + /* add other compilers here ... */ + #define INLINE + #endif /* defined() */ +#endif /* INLINE */ + +/* Are restricted pointers available? (C99) */ +#if (__STDC_VERSION__ != 199901L) + /* Not a C99 compiler */ + #ifdef __GNUC__ + #define restrict __restrict__ + #else + #define restrict /* restrict */ + #endif +#endif + +/* MSVC does not have lrintf */ +#ifdef _MSC_VER +static INLINE long lrintf(float f){ + int i; + + _asm{ + fld f + fistp i + }; + + return i; +} +#endif + +#endif /* OPJ_INCLUDES_H */ diff --git a/v2/libopenjpeg/opj_malloc.h b/v2/libopenjpeg/opj_malloc.h new file mode 100755 index 00000000..0dd1bcdb --- /dev/null +++ b/v2/libopenjpeg/opj_malloc.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2005, Hervé Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __OPJ_MALLOC_H +#define __OPJ_MALLOC_H +/** +@file opj_malloc.h +@brief Internal functions + +The functions in opj_malloc.h are internal utilities used for memory management. +*/ +#include "openjpeg.h" +#include "opj_includes.h" +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Allocate an uninitialized memory block +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +#define opj_malloc(size) malloc(size) +#define my_opj_malloc(size) malloc(size) + +/** +Allocate a memory block with elements initialized to 0 +@param num Blocks to allocate +@param size Bytes per block to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +#define opj_calloc(num, size) calloc(num, size) + +/** +Allocate memory aligned to a 16 byte boundry +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ +#ifdef WIN32 + /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ + #ifdef __GNUC__ + #include + #define HAVE_MM_MALLOC + #else /* MSVC, Intel C++ */ + #include + #ifdef _mm_malloc + #define HAVE_MM_MALLOC + #endif + #endif +#else /* Not WIN32 */ + #if defined(__sun) + #define HAVE_MEMALIGN + /* Linux x86_64 and OSX always align allocations to 16 bytes */ + #elif !defined(__amd64__) && !defined(__APPLE__) + /* FIXME: Yes, this is a big assumption */ + #define HAVE_POSIX_MEMALIGN + #endif +#endif + +#define opj_aligned_malloc(size) malloc(size) +#define opj_aligned_free(m) free(m) + +#ifdef HAVE_MM_MALLOC + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) _mm_malloc(size, 16) + #undef opj_aligned_free + #define opj_aligned_free(m) _mm_free(m) +#endif + +#ifdef HAVE_MEMALIGN + extern void* memalign(size_t, size_t); + #undef opj_aligned_malloc + #define opj_aligned_malloc(size) memalign(16, (size)) + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) +#endif + +#ifdef HAVE_POSIX_MEMALIGN + #undef opj_aligned_malloc + extern int posix_memalign(void**, size_t, size_t); + + static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ + void* mem = NULL; + posix_memalign(&mem, 16, size); + return mem; + } + #undef opj_aligned_free + #define opj_aligned_free(m) free(m) +#endif + +/** +Reallocate memory blocks. +@param memblock Pointer to previously allocated memory block +@param size New size in bytes +@return Returns a void pointer to the reallocated (and possibly moved) memory block +*/ +#define opj_realloc(m, s) realloc(m, s) +#define my_opj_realloc(m,s) realloc(m,s) + + +/** +Deallocates or frees a memory block. +@param memblock Previously allocated memory block to be freed +*/ +#define opj_free(m) free(m) + +#ifdef __GNUC__ +#pragma GCC poison malloc calloc realloc free +#endif + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __OPJ_MALLOC_H */ + diff --git a/v2/libopenjpeg/pi.c b/v2/libopenjpeg/pi.c new file mode 100755 index 00000000..f0dcd11e --- /dev/null +++ b/v2/libopenjpeg/pi.c @@ -0,0 +1,1999 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "pi.h" +#include "int.h" +#include "opj_malloc.h" +#include "j2k.h" +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Get next packet in layer-resolution-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static bool pi_next_lrcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-layer-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static bool pi_next_rlcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-precinct-component-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static bool pi_next_rpcl(opj_pi_iterator_t * pi); +/** +Get next packet in precinct-component-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static bool pi_next_pcrl(opj_pi_iterator_t * pi); +/** +Get next packet in component-precinct-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static bool pi_next_cprl(opj_pi_iterator_t * pi); + +/** + * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +void pi_update_encode_poc_and_final ( + opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); + +/** + * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +void pi_update_encode_not_poc ( + opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); + +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. + * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. + */ +void get_encoding_parameters( + const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res + ); + +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * The precinct widths, heights, dx and dy for each component at each resolution will be stored as well. + * the last parameter of the function should be an array of pointers of size nb components, each pointer leading + * to an area of size 4 * max_res. The data is stored inside this area with the following pattern : + * dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ... + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. + * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. + * @param p_resolutions pointer to an area corresponding to the one described above. + */ +void get_all_encoding_parameters( + const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions + ); +/** + * Allocates memory for a packet iterator. Data and data sizes are set by this operation. + * No other data is set. The include section of the packet iterator is not allocated. + * + * @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant. + * @param p_cp the coding parameters. + * @param p_tile_no the index of the tile from which creating the packet iterator. + */ +opj_pi_iterator_t * pi_create( + const opj_image_t *image, + const opj_cp_t *cp, + OPJ_UINT32 tileno + ); +void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res); +void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res); + + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static bool pi_next_lrcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = 00; + opj_pi_resolution_t *res = 00; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; + pi->resno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on){ + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + + return false; +} + +static bool pi_next_rlcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = 00; + opj_pi_resolution_t *res = 00; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if(!pi->tp_on){ + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + + return false; +} + +static bool pi_next_rpcl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = 00; + opj_pi_resolution_t *res = 00; + OPJ_UINT32 index = 0; + + if (!pi->first) { + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + } + } +if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->ph==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + } + + return false; +} + +static bool pi_next_pcrl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = 00; + opj_pi_resolution_t *res = 00; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + } + } + if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + // TODO + for (pi->resno = pi->poc.resno0; pi->resno < uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->ph==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + } + + return false; +} + +static bool pi_next_cprl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = 00; + opj_pi_resolution_t *res = 00; + OPJ_UINT32 index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 resno; + comp = &pi->comps[pi->compno]; + pi->dx = 0; + pi->dy = 0; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + if (!pi->tp_on){ + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + // TODO + for (pi->resno = pi->poc.resno0; pi->resno < uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_INT32 trx0, try0; + OPJ_INT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_INT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); + try0 = int_ceildiv(pi->ty0, comp->dy << levelno); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); + try1 = int_ceildiv(pi->ty1, comp->dy << levelno); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){ + continue; + } + if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ + continue; + } + + if ((res->pw==0)||(res->pw==0)) continue; + + if ((trx0==trx1)||(try0==try1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) + - int_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + } + + return false; +} + +/* +========================================================== + Packet iterator interface +========================================================== +*/ +opj_pi_iterator_t *pi_create_decode( + opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no + ) +{ + // loop + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + // to store w, h, dx and dy fro all components and resolutions + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + // encoding prameters to set + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; + OPJ_UINT32 l_dx_min,l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ; + OPJ_UINT32 l_data_stride; + + // pointers + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + // preconditions in debug + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + // initializations + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs+1; + + l_data_stride = 4 * J2K_MAXRLVLS; + l_tmp_data = opj_malloc(l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); + if + (! l_tmp_data) + { + return 00; + } + l_tmp_ptr = opj_malloc(p_image->numcomps * sizeof(OPJ_UINT32 *)); + if + (! l_tmp_ptr) + { + opj_free(l_tmp_data); + return 00; + } + + // memory allocation for pi + l_pi = pi_create(p_image,p_cp,p_tile_no); + if + (!l_pi) + { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + // update pointer array + for + (compno = 0; compno < p_image->numcomps; ++compno) + { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + // get encoding parameters + get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr); + + // step calculations + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = p_image->numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + // set values for first packet iterator + l_current_pi = l_pi; + + // memory allocation for include + l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16)); + if + (!l_current_pi->include) + { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + pi_destroy(l_pi, l_bound); + return 00; + } + memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16)); + + // special treatment for the first packet iterator + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + + //l_current_pi->dx = l_img_comp->dx; + //l_current_pi->dy = l_img_comp->dy; + + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by pi_create */ + for + (compno = 0; compno < l_current_pi->numcomps; ++compno) + { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) + { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for + (pino = 1 ; pinocomps; + opj_image_comp_t * l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + //l_current_pi->dx = l_dx_min; + //l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by pi_create */ + for + (compno = 0; compno < l_current_pi->numcomps; ++compno) + { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) + { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + // special treatment + l_current_pi->include = (l_current_pi-1)->include; + ++l_current_pi; + } + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; + if + (l_tcp->POC) + { + pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res); + } + else + { + pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res); + } + return l_pi; +} + +void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res) +{ + // loop + OPJ_UINT32 pino; + + // encoding prameters to set + OPJ_UINT32 l_bound; + + opj_pi_iterator_t * l_current_pi = 00; + opj_poc_t* l_current_poc = 0; + + // preconditions in debug + assert(p_pi != 00); + assert(p_tcp != 00); + + // initializations + l_bound = p_tcp->numpocs+1; + l_current_pi = p_pi; + l_current_poc = p_tcp->pocs; + + for + (pino = 0;pinopoc.prg = l_current_poc->prg; + l_current_pi->first = 1; + + l_current_pi->poc.resno0 = l_current_poc->resno0; + l_current_pi->poc.compno0 = l_current_poc->compno0; + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = l_current_poc->resno1; + l_current_pi->poc.compno1 = l_current_poc->compno1; + l_current_pi->poc.layno1 = l_current_poc->layno1; + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + ++l_current_poc; + } +} + +void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res) +{ + // loop + OPJ_UINT32 pino; + + // encoding prameters to set + OPJ_UINT32 l_bound; + + opj_pi_iterator_t * l_current_pi = 00; + // preconditions in debug + assert(p_tcp != 00); + assert(p_pi != 00); + + // initializations + l_bound = p_tcp->numpocs+1; + l_current_pi = p_pi; + + for + (pino = 0;pinopoc.prg = p_tcp->prg; + l_current_pi->first = 1; + l_current_pi->poc.resno0 = 0; + l_current_pi->poc.compno0 = 0; + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = p_max_res; + l_current_pi->poc.compno1 = l_current_pi->numcomps; + l_current_pi->poc.layno1 = p_tcp->numlayers; + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + } +} + +/** + * Creates a packet iterator for encoding. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. + * @param p_t2_mode the type of pass for generating the packet iterator + * @return a list of packet iterator that points to the first packet of the tile (not true). +*/ +opj_pi_iterator_t *pi_initialise_encode( + const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no, + J2K_T2_MODE p_t2_mode + ) +{ + // loop + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + // to store w, h, dx and dy fro all components and resolutions + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + // encoding prameters to set + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; + OPJ_UINT32 l_dx_min,l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ; + OPJ_UINT32 l_data_stride; + + // pointers + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + // preconditions in debug + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + // initializations + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs+1; + + l_data_stride = 4 * J2K_MAXRLVLS; + l_tmp_data = opj_malloc(l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); + if + (! l_tmp_data) + { + return 00; + } + l_tmp_ptr = opj_malloc(p_image->numcomps * sizeof(OPJ_UINT32 *)); + if + (! l_tmp_ptr) + { + opj_free(l_tmp_data); + return 00; + } + + // memory allocation for pi + l_pi = pi_create(p_image,p_cp,p_tile_no); + if + (!l_pi) + { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + // update pointer array + for + (compno = 0; compno < p_image->numcomps; ++compno) + { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + // get encoding parameters + get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr); + + // step calculations + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = p_image->numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + // set values for first packet iterator + l_pi->tp_on = p_cp->m_specific_param.m_enc.m_tp_on; + l_current_pi = l_pi; + + // memory allocation for include + l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16)); + if + (!l_current_pi->include) + { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + pi_destroy(l_pi, l_bound); + return 00; + } + memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16)); + + // special treatment for the first packet iterator + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by pi_create */ + for + (compno = 0; compno < l_current_pi->numcomps; ++compno) + { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) + { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for + (pino = 1 ; pinocomps; + opj_image_comp_t * l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by pi_create */ + for + (compno = 0; compno < l_current_pi->numcomps; ++compno) + { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) + { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + // special treatment + l_current_pi->include = (l_current_pi-1)->include; + ++l_current_pi; + } + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; + if + (l_tcp->POC && ( p_cp->m_specific_param.m_enc.m_cinema || p_t2_mode == FINAL_PASS)) + { + pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); + } + else + { + pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); + } + return l_pi; +} + +/** + * Updates the encoding parameters of the codec. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. +*/ +void pi_update_encoding_parameters( + const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no + ) +{ + // encoding prameters to set + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; + OPJ_UINT32 l_dx_min,l_dy_min; + + // pointers + opj_tcp_t *l_tcp = 00; + + // preconditions in debug + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + l_tcp = &(p_cp->tcps[p_tile_no]); + // get encoding parameters + get_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res); + if + (l_tcp->POC) + { + pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); + } + else + { + pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min); + } +} + + +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. + * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. + */ +void get_encoding_parameters( + const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res + ) +{ + // loop + OPJ_UINT32 compno, resno; + // pointers + const opj_tcp_t *l_tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + // position in x and y of tile + OPJ_UINT32 p, q; + + // preconditions in debug + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + // initializations + l_tcp = &p_cp->tcps [p_tileno]; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, dx and dy */ + p = p_tileno % p_cp->tw; + q = p_tileno / p_cp->tw; + + // find extent of tile + *p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0); + *p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1); + *p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0); + *p_ty1 = int_min(p_cp->ty0 + (q + 1) * p_cp->tdy, p_image->y1); + + // max precision is 0 (can only grow) + *p_max_prec = 0; + *p_max_res = 0; + + // take the largest value for dx_min and dy_min + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for + (compno = 0; compno < p_image->numcomps; ++compno) + { + // aritmetic variables to calculate + OPJ_UINT32 l_level_no; + OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_INT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_pdx, l_pdy; + OPJ_UINT32 l_pw, l_ph; + OPJ_UINT32 l_product; + OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + + l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx); + l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy); + l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx); + l_tcy1 = int_ceildiv(*p_ty1, l_img_comp->dy); + if + (l_tccp->numresolutions > *p_max_res) + { + *p_max_res = l_tccp->numresolutions; + } + // use custom size for precincts + for + (resno = 0; resno < l_tccp->numresolutions; ++resno) + { + OPJ_UINT32 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 * (1 << (l_pdx + l_tccp->numresolutions - 1 - resno)); + l_dy = l_img_comp->dy * (1 << (l_pdy + l_tccp->numresolutions - 1 - resno)); + // take the minimum size for dx for each comp and resolution + *p_dx_min = uint_min(*p_dx_min, l_dx); + *p_dy_min = uint_min(*p_dy_min, l_dy); + // various calculations of extents + l_level_no = l_tccp->numresolutions - 1 - resno; + l_rx0 = int_ceildivpow2(l_tcx0, l_level_no); + l_ry0 = int_ceildivpow2(l_tcy0, l_level_no); + l_rx1 = int_ceildivpow2(l_tcx1, l_level_no); + l_ry1 = int_ceildivpow2(l_tcy1, l_level_no); + l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx; + l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy; + l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx; + py1 = int_ceildivpow2(l_ry1, l_pdy) << l_pdy; + l_pw = (l_rx0==l_rx1)?0:((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0==l_ry1)?0:((py1 - l_py0) >> l_pdy); + l_product = l_pw * l_ph; + // update precision + if + (l_product > *p_max_prec) + { + *p_max_prec = l_product; + } + } + ++l_img_comp; + ++l_tccp; + } +} + +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * The precinct widths, heights, dx and dy for each component at each resolution will be stored as well. + * the last parameter of the function should be an array of pointers of size nb components, each pointer leading + * to an area of size 4 * max_res. The data is stored inside this area with the following pattern : + * dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ... + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. + * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. + * @param p_resolutions pointer to an area corresponding to the one described above. + */ +void get_all_encoding_parameters( + const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_INT32 * p_tx0, + OPJ_INT32 * p_tx1, + OPJ_INT32 * p_ty0, + OPJ_INT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions + ) +{ + // loop + OPJ_UINT32 compno, resno; + + // pointers + const opj_tcp_t *tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + // to store l_dx, l_dy, w and h for each resolution and component. + OPJ_UINT32 * lResolutionPtr; + + // position in x and y of tile + OPJ_UINT32 p, q; + + // preconditions in debug + assert(p_cp != 00); + assert(p_image != 00); + assert(tileno < p_cp->tw * p_cp->th); + + // initializations + tcp = &p_cp->tcps [tileno]; + l_tccp = tcp->tccps; + l_img_comp = p_image->comps; + + // position in x and y of tile + + p = tileno % p_cp->tw; + q = tileno / p_cp->tw; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */ + *p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0); + *p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1); + *p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0); + *p_ty1 = int_min(p_cp->ty0 + (q + 1) * p_cp->tdy, p_image->y1); + + // max precision and resolution is 0 (can only grow) + *p_max_prec = 0; + *p_max_res = 0; + + // take the largest value for dx_min and dy_min + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for + (compno = 0; compno < p_image->numcomps; ++compno) + { + // aritmetic variables to calculate + OPJ_UINT32 l_level_no; + OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_INT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_product; + OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + OPJ_UINT32 l_pdx, l_pdy , l_pw , l_ph; + + lResolutionPtr = p_resolutions[compno]; + + l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx); + l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy); + l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx); + l_tcy1 = int_ceildiv(*p_ty1, l_img_comp->dy); + if + (l_tccp->numresolutions > *p_max_res) + { + *p_max_res = l_tccp->numresolutions; + } + + // use custom size for precincts + l_level_no = l_tccp->numresolutions - 1; + for + (resno = 0; resno < l_tccp->numresolutions; ++resno) + { + OPJ_UINT32 l_dx, l_dy; + // precinct width and height + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + *lResolutionPtr++ = l_pdx; + *lResolutionPtr++ = l_pdy; + l_dx = l_img_comp->dx * (1 << (l_pdx + l_level_no)); + l_dy = l_img_comp->dy * (1 << (l_pdy + l_level_no)); + // take the minimum size for l_dx for each comp and resolution + *p_dx_min = int_min(*p_dx_min, l_dx); + *p_dy_min = int_min(*p_dy_min, l_dy); + // various calculations of extents + + l_rx0 = int_ceildivpow2(l_tcx0, l_level_no); + l_ry0 = int_ceildivpow2(l_tcy0, l_level_no); + l_rx1 = int_ceildivpow2(l_tcx1, l_level_no); + l_ry1 = int_ceildivpow2(l_tcy1, l_level_no); + l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx; + l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy; + l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx; + py1 = int_ceildivpow2(l_ry1, l_pdy) << l_pdy; + l_pw = (l_rx0==l_rx1)?0:((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0==l_ry1)?0:((py1 - l_py0) >> l_pdy); + *lResolutionPtr++ = l_pw; + *lResolutionPtr++ = l_ph; + l_product = l_pw * l_ph; + // update precision + if + (l_product > *p_max_prec) + { + *p_max_prec = l_product; + } + --l_level_no; + } + ++l_tccp; + ++l_img_comp; + } +} + +/** + * Allocates memory for a packet iterator. Data and data sizes are set by this operation. + * No other data is set. The include section of the packet iterator is not allocated. + * + * @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant. + * @param p_cp the coding parameters. + * @param p_tile_no the index of the tile from which creating the packet iterator. + */ +opj_pi_iterator_t * pi_create( + const opj_image_t *image, + const opj_cp_t *cp, + OPJ_UINT32 tileno + ) +{ + // loop + OPJ_UINT32 pino, compno; + // number of poc in the p_pi + OPJ_UINT32 l_poc_bound; + + // pointers to tile coding parameters and components. + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *tcp = 00; + const opj_tccp_t *tccp = 00; + + // current packet iterator being allocated + opj_pi_iterator_t *l_current_pi = 00; + + // preconditions in debug + assert(cp != 00); + assert(image != 00); + assert(tileno < cp->tw * cp->th); + + // initializations + tcp = &cp->tcps[tileno]; + l_poc_bound = tcp->numpocs+1; + + + // memory allocations + l_pi = (opj_pi_iterator_t*) opj_calloc((l_poc_bound), sizeof(opj_pi_iterator_t)); + + if + (!l_pi) + { + return 00; + } + memset(l_pi,0,l_poc_bound * sizeof(opj_pi_iterator_t)); + l_current_pi = l_pi; + for + (pino = 0; pino < l_poc_bound ; ++pino) + { + l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t)); + if + (! l_current_pi->comps) + { + pi_destroy(l_pi, l_poc_bound); + return 00; + } + l_current_pi->numcomps = image->numcomps; + memset(l_current_pi->comps,0,image->numcomps * sizeof(opj_pi_comp_t)); + for + (compno = 0; compno < image->numcomps; ++compno) + { + opj_pi_comp_t *comp = &l_current_pi->comps[compno]; + tccp = &tcp->tccps[compno]; + comp->resolutions = (opj_pi_resolution_t*) opj_malloc(tccp->numresolutions * sizeof(opj_pi_resolution_t)); + if + (!comp->resolutions) + { + pi_destroy(l_pi, l_poc_bound); + return 00; + } + comp->numresolutions = tccp->numresolutions; + memset(comp->resolutions,0,tccp->numresolutions * sizeof(opj_pi_resolution_t)); + } + ++l_current_pi; + } + return l_pi; +} + +/** + * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +void pi_update_encode_poc_and_final ( + opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) +{ + // loop + OPJ_UINT32 pino; + // tile coding parameter + opj_tcp_t *l_tcp = 00; + // current poc being updated + opj_poc_t * l_current_poc = 00; + + // number of pocs + OPJ_UINT32 l_poc_bound; + + // preconditions in debug + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + // initializations + l_tcp = &p_cp->tcps [p_tileno]; + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs+1; + + // start at first element, and to make sure the compiler will not make a calculation each time in the loop + // store a pointer to the current element to modify rather than l_tcp->pocs[i] + l_current_poc = l_tcp->pocs; + + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE = l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + + // special treatment for the first element + l_current_poc->layS = 0; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = p_tx0; + l_current_poc->txE = p_tx1; + l_current_poc->tyS = p_ty0; + l_current_poc->tyE = p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + + ++ l_current_poc; + for + (pino = 1;pino < l_poc_bound ; ++pino) + { + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE= l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + // special treatment here different from the first element + l_current_poc->layS = (l_current_poc->layE > (l_current_poc-1)->layE) ? l_current_poc->layE : 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = p_tx0; + l_current_poc->txE = p_tx1; + l_current_poc->tyS = p_ty0; + l_current_poc->tyE = p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } +} + +/** + * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +void pi_update_encode_not_poc ( + opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_INT32 p_tx0, + OPJ_INT32 p_tx1, + OPJ_INT32 p_ty0, + OPJ_INT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) +{ + // loop + OPJ_UINT32 pino; + // tile coding parameter + opj_tcp_t *l_tcp = 00; + // current poc being updated + opj_poc_t * l_current_poc = 00; + // number of pocs + OPJ_UINT32 l_poc_bound; + + // preconditions in debug + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + // initializations + l_tcp = &p_cp->tcps [p_tileno]; + + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs+1; + + // start at first element, and to make sure the compiler will not make a calculation each time in the loop + // store a pointer to the current element to modify rather than l_tcp->pocs[i] + l_current_poc = l_tcp->pocs; + + for + (pino = 0; pino < l_poc_bound ; ++pino) + { + l_current_poc->compS = 0; + l_current_poc->compE = p_num_comps;/*p_image->numcomps;*/ + l_current_poc->resS = 0; + l_current_poc->resE = p_max_res; + l_current_poc->layS = 0; + l_current_poc->layE = l_tcp->numlayers; + l_current_poc->prg = l_tcp->prg; + l_current_poc->prcS = 0; + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = p_tx0; + l_current_poc->txE = p_tx1; + l_current_poc->tyS = p_ty0; + l_current_poc->tyE = p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } +} + +/** + * Destroys a packet iterator array. + * + * @param p_pi the packet iterator array to destroy. + * @param p_nb_elements the number of elements in the array. + */ +void pi_destroy( + opj_pi_iterator_t *p_pi, + OPJ_UINT32 p_nb_elements) +{ + OPJ_UINT32 compno, pino; + opj_pi_iterator_t *l_current_pi = p_pi; + if + (p_pi) + { + if + (p_pi->include) + { + opj_free(p_pi->include); + p_pi->include = 00; + } + // TODO + for + (pino = 0; pino < p_nb_elements; ++pino) + { + if + (l_current_pi->comps) + { + opj_pi_comp_t *l_current_component = l_current_pi->comps; + for + (compno = 0; compno < l_current_pi->numcomps; compno++) + { + if + (l_current_component->resolutions) + { + opj_free(l_current_component->resolutions); + l_current_component->resolutions = 00; + } + ++l_current_component; + } + opj_free(l_current_pi->comps); + l_current_pi->comps = 0; + } + ++l_current_pi; + } + opj_free(p_pi); + } +} + +bool pi_next(opj_pi_iterator_t * pi) { + switch (pi->poc.prg) { + case LRCP: + return pi_next_lrcp(pi); + case RLCP: + return pi_next_rlcp(pi); + case RPCL: + return pi_next_rpcl(pi); + case PCRL: + return pi_next_pcrl(pi); + case CPRL: + return pi_next_cprl(pi); + case PROG_UNKNOWN: + return false; + } + + return false; +} + +OPJ_INT32 pi_check_next_level(OPJ_INT32 pos,opj_cp_t *cp,OPJ_UINT32 tileno, OPJ_UINT32 pino, const OPJ_CHAR *prog) +{ + OPJ_INT32 i,l; + opj_tcp_t *tcps =&cp->tcps[tileno]; + opj_poc_t *tcp = &tcps->pocs[pino]; + if(pos>=0){ + for(i=pos;pos>=0;i--){ + switch(prog[i]){ + case 'R': + if(tcp->res_t==tcp->resE){ + l=pi_check_next_level(pos-1,cp,tileno,pino,prog); + if(l==1){ + return 1; + }else{ + return 0; + } + }else{ + return 1; + } + break; + case 'C': + if(tcp->comp_t==tcp->compE){ + l=pi_check_next_level(pos-1,cp,tileno,pino,prog); + if(l==1){ + return 1; + }else{ + return 0; + } + }else{ + return 1; + } + break; + case 'L': + if(tcp->lay_t==tcp->layE){ + l=pi_check_next_level(pos-1,cp,tileno,pino,prog); + if(l==1){ + return 1; + }else{ + return 0; + } + }else{ + return 1; + } + break; + case 'P': + switch(tcp->prg){ + case LRCP||RLCP: + if(tcp->prc_t == tcp->prcE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + return 1; + }else{ + return 0; + } + }else{ + return 1; + } + break; + default: + if(tcp->tx0_t == tcp->txE){ + //TY + if(tcp->ty0_t == tcp->tyE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + return 1; + }else{ + return 0; + } + }else{ + return 1; + }//TY + }else{ + return 1; + } + break; + }//end case P + }//end switch + }//end for + }//end if + return 0; +} + + +void pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,OPJ_UINT32 tileno, OPJ_UINT32 pino,OPJ_UINT32 tpnum, OPJ_INT32 tppos, J2K_T2_MODE t2_mode) +{ + const OPJ_CHAR *prog; + OPJ_INT32 i,l; + OPJ_UINT32 incr_top=1,resetX=0; + opj_tcp_t *tcps =&cp->tcps[tileno]; + opj_poc_t *tcp= &tcps->pocs[pino]; + + prog = j2k_convert_progression_order(tcp->prg); + + pi[pino].first = 1; + pi[pino].poc.prg = tcp->prg; + + if(!(cp->m_specific_param.m_enc.m_tp_on&& ((!cp->m_specific_param.m_enc.m_cinema && (t2_mode == FINAL_PASS)) || cp->m_specific_param.m_enc.m_cinema))){ + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + }else { + for(i=tppos+1;i<4;i++){ + switch(prog[i]){ + case 'R': + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + break; + case 'C': + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + break; + case 'L': + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + break; + case 'P': + switch(tcp->prg){ + case LRCP: + case RLCP: + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + break; + default: + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + break; + } + break; + } + } + + if(tpnum==0){ + for(i=tppos;i>=0;i--){ + switch(prog[i]){ + case 'C': + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + break; + case 'R': + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + break; + case 'L': + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + break; + case 'P': + switch(tcp->prg){ + case LRCP: + case RLCP: + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + break; + default: + tcp->tx0_t = tcp->txS; + tcp->ty0_t = tcp->tyS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->tx0_t = pi[pino].poc.tx1; + tcp->ty0_t = pi[pino].poc.ty1; + break; + } + break; + } + } + incr_top=1; + }else{ + for(i=tppos;i>=0;i--){ + switch(prog[i]){ + case 'C': + pi[pino].poc.compno0 = tcp->comp_t-1; + pi[pino].poc.compno1 = tcp->comp_t; + break; + case 'R': + pi[pino].poc.resno0 = tcp->res_t-1; + pi[pino].poc.resno1 = tcp->res_t; + break; + case 'L': + pi[pino].poc.layno0 = tcp->lay_t-1; + pi[pino].poc.layno1 = tcp->lay_t; + break; + case 'P': + switch(tcp->prg){ + case LRCP: + case RLCP: + pi[pino].poc.precno0 = tcp->prc_t-1; + pi[pino].poc.precno1 = tcp->prc_t; + break; + default: + pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.tx1 = tcp->tx0_t ; + pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); + pi[pino].poc.ty1 = tcp->ty0_t ; + break; + } + break; + } + if(incr_top==1){ + switch(prog[i]){ + case 'R': + if(tcp->res_t==tcp->resE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + incr_top=1; + }else{ + incr_top=0; + } + }else{ + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t+1; + tcp->res_t+=1; + incr_top=0; + } + break; + case 'C': + if(tcp->comp_t ==tcp->compE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + incr_top=1; + }else{ + incr_top=0; + } + }else{ + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t+1; + tcp->comp_t+=1; + incr_top=0; + } + break; + case 'L': + if(tcp->lay_t == tcp->layE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + incr_top=1; + }else{ + incr_top=0; + } + }else{ + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t+1; + tcp->lay_t+=1; + incr_top=0; + } + break; + case 'P': + switch(tcp->prg){ + case LRCP: + case RLCP: + if(tcp->prc_t == tcp->prcE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + incr_top=1; + }else{ + incr_top=0; + } + }else{ + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t+1; + tcp->prc_t+=1; + incr_top=0; + } + break; + default: + if(tcp->tx0_t >= tcp->txE){ + if(tcp->ty0_t >= tcp->tyE){ + l=pi_check_next_level(i-1,cp,tileno,pino,prog); + if(l==1){ + tcp->ty0_t = tcp->tyS; + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = pi[pino].poc.ty1; + incr_top=1;resetX=1; + }else{ + incr_top=0;resetX=0; + } + }else{ + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = pi[pino].poc.ty1; + incr_top=0;resetX=1; + } + if(resetX==1){ + tcp->tx0_t = tcp->txS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx); + tcp->tx0_t = pi[pino].poc.tx1; + } + }else{ + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx); + tcp->tx0_t = pi[pino].poc.tx1; + incr_top=0; + } + break; + } + break; + } + } + } + } + } +} + + + diff --git a/v2/libopenjpeg/pi.h b/v2/libopenjpeg/pi.h new file mode 100755 index 00000000..8e6b35fd --- /dev/null +++ b/v2/libopenjpeg/pi.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PI_H +#define __PI_H +/** +@file pi.h +@brief Implementation of a packet iterator (PI) + +The functions in PI.C have for goal to realize a packet iterator that permits to get the next +packet following the progression order and change of it. The functions in PI.C are used +by some function in T2.C. +*/ +#include "openjpeg.h" +#include "t2.h" +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ +struct opj_poc; +struct opj_image; +struct opj_cp; + +/** +FIXME: documentation +*/ +typedef struct opj_pi_resolution { + OPJ_UINT32 pdx, pdy; + OPJ_UINT32 pw, ph; +} opj_pi_resolution_t; + +/** +FIXME: documentation +*/ +typedef struct opj_pi_comp { + OPJ_UINT32 dx, dy; + /** number of resolution levels */ + OPJ_UINT32 numresolutions; + opj_pi_resolution_t *resolutions; +} opj_pi_comp_t; + +/** +Packet iterator +*/ +typedef struct opj_pi_iterator { + /** Enabling Tile part generation*/ + OPJ_BYTE tp_on; + /** precise if the packet has been already used (usefull for progression order change) */ + OPJ_INT16 *include; + /** layer step used to localize the packet in the include vector */ + OPJ_UINT32 step_l; + /** resolution step used to localize the packet in the include vector */ + OPJ_UINT32 step_r; + /** component step used to localize the packet in the include vector */ + OPJ_UINT32 step_c; + /** precinct step used to localize the packet in the include vector */ + OPJ_UINT32 step_p; + /** component that identify the packet */ + OPJ_UINT32 compno; + /** resolution that identify the packet */ + OPJ_UINT32 resno; + /** precinct that identify the packet */ + OPJ_UINT32 precno; + /** layer that identify the packet */ + OPJ_UINT32 layno; + /** progression order change information */ + struct opj_poc poc; + /** number of components in the image */ + OPJ_UINT32 numcomps; + /** Components*/ + opj_pi_comp_t *comps; + OPJ_INT32 tx0, ty0, tx1, ty1; + OPJ_INT32 x, y; + OPJ_UINT32 dx, dy; + /** 0 if the first packet */ + OPJ_UINT32 first : 1; +} opj_pi_iterator_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** + * Creates a packet iterator for encoding. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. + * @param p_t2_mode the type of pass for generating the packet iterator + * @return a list of packet iterator that points to the first packet of the tile (not true). +*/ +opj_pi_iterator_t *pi_initialise_encode(const struct opj_image *image,struct opj_cp *cp, OPJ_UINT32 tileno,J2K_T2_MODE t2_mode); + +/** + * Updates the encoding parameters of the codec. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. +*/ +void pi_update_encoding_parameters( + const struct opj_image *p_image, + struct opj_cp *p_cp, + OPJ_UINT32 p_tile_no + ); + + + +/** +Modify the packet iterator for enabling tile part generation +@param pi Handle to the packet iterator generated in pi_initialise_encode +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +*/ +void pi_create_encode( opj_pi_iterator_t *pi, struct opj_cp *cp,OPJ_UINT32 tileno, OPJ_UINT32 pino,OPJ_UINT32 tpnum, OPJ_INT32 tppos, J2K_T2_MODE t2_mode); + + +/** +Create a packet iterator for Decoder +@param image Raw image for which the packets will be listed +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@return Returns a packet iterator that points to the first packet of the tile +@see pi_destroy +*/ +opj_pi_iterator_t *pi_create_decode(struct opj_image * image, struct opj_cp * cp, OPJ_UINT32 tileno); + + + +/** + * Destroys a packet iterator array. + * + * @param p_pi the packet iterator array to destroy. + * @param p_nb_elements the number of elements in the array. + */ +void pi_destroy( + opj_pi_iterator_t *p_pi, + OPJ_UINT32 p_nb_elements); + +/** +Modify the packet iterator to point to the next packet +@param pi Packet iterator to modify +@return Returns false if pi pointed to the last packet or else returns true +*/ +bool pi_next(opj_pi_iterator_t * pi); + + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __PI_H */ diff --git a/v2/libopenjpeg/profile.c b/v2/libopenjpeg/profile.c new file mode 100755 index 00000000..68c6c0c1 --- /dev/null +++ b/v2/libopenjpeg/profile.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Adapted from Herb Marselas +"Profiling, Data Analysis, Scalability, and Magic Numbers: Meeting the Minimum System Requirements for AGE OF EMPIRES 2: THE AGE OF KINGS" +Game Developer magazine +June, 2000 issue. +*/ + +#include "profile.h" +#include +#include +#include +//============================================================================== +static OPJ_PROFILE_LIST group_list [PGROUP_LASTGROUP]; + +//============================================================================== +static void GetTimeStamp(OPJ_UINT32 *pdwtime); + +//============================================================================== +#define SetMajorSection(entry, major) \ + { group_list[ entry ].section = entry ; \ + group_list[ entry ].sectionName = #major ; } + +//============================================================================== +void _ProfInit(void) +{ + // clear everything out + memset(group_list, 0, sizeof(group_list)); + + // set groups and parents for timing + SetMajorSection(PGROUP_DWT,PGROUP_DWT); + SetMajorSection(PGROUP_T1, PGROUP_T1); + SetMajorSection(PGROUP_T2, PGROUP_T2); +} // ProfInit + +//============================================================================== +void _ProfStart (OPJ_PROFILE_GROUP group) +{ + // make sure this hasn't been incorrectly started twice + if (group_list[group].start) + { + return; + } + + // get the start time + GetTimeStamp(&(group_list[group].start)); + +} // _ProfStart + +//============================================================================== +void _ProfStop(OPJ_PROFILE_GROUP group) +{ + // make sure we called start first + if (!group_list[group].start) + { + return; + } + + // get ending time + GetTimeStamp(&(group_list[group].end)); + + // calculate this latest elapsed interval + group_list[group].total_time += group_list[group].end - group_list[group].start; + + // reset starting time + group_list[group].start = 0; + + // incr the number of calls made + ++group_list[group].totalCalls; + +} // _ProfStop + +//============================================================================== +#define proftracef(id,totalTime) \ + fprintf(p, #id "\t%u\t\t%6.6f\t\t%12.6f\t%2.2f%%\n", \ + group_list[ id ].totalCalls, \ + (OPJ_FLOAT64) group_list[ id ].total_time / CLOCKS_PER_SEC, \ + ((OPJ_FLOAT64) group_list[ id ].total_time / (group_list[ id ].totalCalls ? group_list[ id ].totalCalls : 1)), \ + ((OPJ_FLOAT64) group_list[ id ].total_time / totalTime * 100)) + +#define proftracep(id,totalTime) \ + printf(#id "\t%u\t\t%6.6f\t\t%12.6f\t%2.2f%%\n", \ + group_list[ id ].totalCalls, \ + (OPJ_FLOAT64) group_list[ id ].total_time / CLOCKS_PER_SEC, \ + ((OPJ_FLOAT64) group_list[ id ].total_time / (group_list[ id ].totalCalls ? group_list[ id ].totalCalls : 1)), \ + ((OPJ_FLOAT64) group_list[ id ].total_time / totalTime * 100)) + +//============================================================================== +void _ProfSave(const OPJ_CHAR * pFileName) +{ + FILE *p = fopen(pFileName, "wt"); + OPJ_FLOAT64 totalTime = 0.; + OPJ_UINT32 i; + + if (!p) + { + return; + } + + for + (i=0;i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Adapted from Herb Marselas +"Profiling, Data Analysis, Scalability, and Magic Numbers: Meeting the Minimum System Requirements for AGE OF EMPIRES 2: THE AGE OF KINGS" +Game Developer magazine +June, 2000 issue. +*/ + + +#ifndef __PROFILE_H +#define __PROFILE_H + +#include "openjpeg.h" +//============================================================================== +typedef enum +{ + PGROUP_RATE, + PGROUP_DC_SHIFT, + PGROUP_MCT, + PGROUP_DWT, + PGROUP_T1, + PGROUP_T2, + PGROUP_LASTGROUP +} OPJ_PROFILE_GROUP; + +//============================================================================== +typedef struct PROFILELIST +{ + OPJ_UINT32 start; + OPJ_UINT32 end; + OPJ_UINT32 total_time; + OPJ_UINT32 totalCalls; + OPJ_PROFILE_GROUP section; + const OPJ_CHAR *sectionName; // string name of the profile group +} OPJ_PROFILE_LIST; + +//============================================================================== +void _ProfStart(OPJ_PROFILE_GROUP group); +void _ProfStop (OPJ_PROFILE_GROUP group); + +//============================================================================== +//============================================================================== +#ifdef _PROFILE +#define PROFINIT() _ProfInit(); +#define PROFSTART (group) _ProfStart (group); +#define PROFSTOP (group) _ProfStop (group); +#define PROFSAVE(file) _ProfSave(file); +#define PROFPRINT() _ProfPrint(); +#else +#define PROFINIT() +#define PROFSTART(group) +#define PROFSTOP (group) +#define PROFSAVE(file) +#define PROFPRINT() +#endif // !_PROFILE + +//============================================================================== +#endif // __PROFILE_H diff --git a/v2/libopenjpeg/raw.c b/v2/libopenjpeg/raw.c new file mode 100755 index 00000000..a243c461 --- /dev/null +++ b/v2/libopenjpeg/raw.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "raw.h" +#include "opj_malloc.h" + +/* +========================================================== + local functions +========================================================== +*/ + + +/* +========================================================== + RAW encoding interface +========================================================== +*/ + +opj_raw_t* raw_create(void) { + opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t)); + return raw; +} + +void raw_destroy(opj_raw_t *raw) { + if(raw) { + opj_free(raw); + } +} + +OPJ_UINT32 raw_numbytes(opj_raw_t *raw) { + return raw->bp - raw->start; +} + +void raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len) { + raw->start = bp; + raw->lenmax = len; + raw->len = 0; + raw->c = 0; + raw->ct = 0; +} + +OPJ_UINT32 raw_decode(opj_raw_t *raw) { + OPJ_UINT32 d; + if (raw->ct == 0) { + raw->ct = 8; + if (raw->len == raw->lenmax) { + raw->c = 0xff; + } else { + if (raw->c == 0xff) { + raw->ct = 7; + } + raw->c = *(raw->start + raw->len); + raw->len++; + } + } + raw->ct--; + d = (raw->c >> raw->ct) & 0x01; + + return d; +} + diff --git a/v2/libopenjpeg/raw.h b/v2/libopenjpeg/raw.h new file mode 100755 index 00000000..bb80c625 --- /dev/null +++ b/v2/libopenjpeg/raw.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __RAW_H +#define __RAW_H +/** +@file raw.h +@brief Implementation of operations for raw encoding (RAW) + +The functions in RAW.C have for goal to realize the operation of raw encoding linked +with the corresponding mode switch. +*/ +#include "openjpeg.h" +/** @defgroup RAW RAW - Implementation of operations for raw encoding */ +/*@{*/ + +/** +RAW encoding operations +*/ +typedef struct opj_raw { + /** temporary buffer where bits are coded or decoded */ + OPJ_BYTE c; + /** number of bits already read or free to write */ + OPJ_UINT32 ct; + /** maximum length to decode */ + OPJ_UINT32 lenmax; + /** length decoded */ + OPJ_UINT32 len; + /** pointer to the current position in the buffer */ + OPJ_BYTE *bp; + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + unsigned char *end; +} opj_raw_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new RAW handle +@return Returns a new RAW handle if successful, returns NULL otherwise +*/ +opj_raw_t* raw_create(void); +/** +Destroy a previously created RAW handle +@param raw RAW handle to destroy +*/ +void raw_destroy(opj_raw_t *raw); +/** +Return the number of bytes written/read since initialisation +@param raw RAW handle to destroy +@return Returns the number of bytes already encoded +*/ +OPJ_UINT32 raw_numbytes(opj_raw_t *raw); +/** +Initialize the decoder +@param raw RAW handle +@param bp Pointer to the start of the buffer from which the bytes will be read +@param len Length of the input buffer +*/ +void raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN +@param raw RAW handle +@return Returns the decoded symbol (0 or 1) +*/ +OPJ_UINT32 raw_decode(opj_raw_t *raw); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __RAW_H */ diff --git a/v2/libopenjpeg/t1.c b/v2/libopenjpeg/t1.c new file mode 100755 index 00000000..4f95fc61 --- /dev/null +++ b/v2/libopenjpeg/t1.c @@ -0,0 +1,1286 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "t1.h" +#include "t1_luts.h" +#include "opj_includes.h" +#include "j2k.h" +#include "tcd.h" +#include "mqc.h" +#include "raw.h" +#include "opj_malloc.h" +#include "int.h" +#include "dwt.h" +#include "fix.h" +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static INLINE OPJ_BYTE t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient); +static OPJ_BYTE t1_getctxno_sc(OPJ_UINT32 f); +static INLINE OPJ_UINT32 t1_getctxno_mag(OPJ_UINT32 f); +static OPJ_BYTE t1_getspb(OPJ_UINT32 f); +static OPJ_INT16 t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos); +static OPJ_INT16 t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos); +static void t1_updateflags(flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride); +/** +Encode significant pass +*/ +static void t1_enc_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 vsc); +/** +Decode significant pass +*/ +static void t1_dec_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 oneplushalf, + OPJ_BYTE type, + OPJ_UINT32 vsc); +/** +Encode significant pass +*/ +static void t1_enc_sigpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty); +/** +Decode significant pass +*/ +static void t1_dec_sigpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_BYTE type, + OPJ_UINT32 cblksty); +/** +Encode refinement pass +*/ +static void t1_enc_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 vsc); +/** +Decode refinement pass +*/ +static void t1_dec_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_INT32 neghalf, + OPJ_BYTE type, + OPJ_UINT32 vsc); +/** +Encode refinement pass +*/ +static void t1_enc_refpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty); +/** +Decode refinement pass +*/ +static void t1_dec_refpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_BYTE type, + OPJ_UINT32 cblksty); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_UINT32 partial, + OPJ_UINT32 vsc); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 oneplushalf, + OPJ_UINT32 partial, + OPJ_UINT32 vsc); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_UINT32 cblksty); + +static OPJ_FLOAT64 t1_getwmsedec( + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms); +/** +Encode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param compno Component number +@param level +@param qmfbid +@param stepsize +@param cblksty Code-block style +@param numcomps +@param tile +*/ +static void t1_encode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + opj_tcd_tile_t * tile, + const OPJ_FLOAT64 * mct_norms); +/** +Decode 1 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 +*/ +static void t1_decode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static OPJ_BYTE t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) { + return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)]; +} + +static OPJ_BYTE t1_getctxno_sc(OPJ_UINT32 f) { + return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static OPJ_UINT32 t1_getctxno_mag(OPJ_UINT32 f) { + OPJ_UINT32 tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; + OPJ_UINT32 tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1; + return (tmp2); +} + +static OPJ_BYTE t1_getspb(OPJ_UINT32 f) { + return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static OPJ_INT16 t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) +{ + if (bitpos > T1_NMSEDEC_FRACBITS) { + return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static OPJ_INT16 t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static void t1_updateflags(flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride) { + flag_t *np = flagsp - stride; + flag_t *sp = flagsp + stride; + + static const flag_t mod[] = { + T1_SIG_S, T1_SIG_S|T1_SGN_S, + T1_SIG_E, T1_SIG_E|T1_SGN_E, + T1_SIG_W, T1_SIG_W|T1_SGN_W, + T1_SIG_N, T1_SIG_N|T1_SGN_N + }; + + np[-1] |= T1_SIG_SE; + np[0] |= mod[s]; + np[1] |= T1_SIG_SW; + + flagsp[-1] |= mod[s+2]; + flagsp[0] |= T1_SIG; + flagsp[1] |= mod[s+4]; + + sp[-1] |= T1_SIG_NE; + sp[0] |= mod[s+6]; + sp[1] |= T1_SIG_NW; +} + +static void t1_enc_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 vsc) +{ + OPJ_INT32 v; + OPJ_UINT32 flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + v = int_abs(*datap) & one ? 1 : 0; + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v); + } + if (v) { + v = *datap < 0 ? 1 : 0; + *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v ^ t1_getspb(flag)); + } + t1_updateflags(flagsp, v, t1->flags_stride); + } + *flagsp |= T1_VISIT; + } +} + +static void t1_dec_sigpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 oneplushalf, + OPJ_BYTE type, + OPJ_UINT32 vsc) +{ + OPJ_UINT32 v, flag; + + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + if (type == T1_TYPE_RAW) { + if (raw_decode(raw)) { + v = raw_decode(raw); /* ESSAI */ + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + } else { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp |= T1_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_sigpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k, vsc; + OPJ_INT32 one; + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_sigpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + bpno, + one, + nmsedec, + type, + vsc); + } + } + } +} + +static void t1_dec_sigpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_BYTE type, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k, vsc; + OPJ_INT32 one, half, oneplushalf; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_sigpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + oneplushalf, + type, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 vsc) +{ + OPJ_INT32 v; + OPJ_UINT32 flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + *nmsedec += t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + v = int_abs(*datap) & one ? 1 : 0; + mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_bypass_enc(mqc, v); + } else { + mqc_encode(mqc, v); + } + *flagsp |= T1_REFINE; + } +} + +static void t1_dec_refpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_INT32 neghalf, + OPJ_BYTE type, + OPJ_UINT32 vsc) +{ + OPJ_INT32 t; + OPJ_UINT32 v,flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + opj_raw_t *raw = t1->raw; /* RAW component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ + if (type == T1_TYPE_RAW) { + v = raw_decode(raw); + } else { + v = mqc_decode(mqc); + } + t = v ? poshalf : neghalf; + *datap += *datap < 0 ? -t : t; + *flagsp |= T1_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k, vsc; + OPJ_INT32 one; + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_refpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + bpno, + one, + nmsedec, + type, + vsc); + } + } + } +} + +static void t1_dec_refpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_BYTE type, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k; + OPJ_INT32 one, poshalf, neghalf; + OPJ_UINT32 vsc; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + for (j = k; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_refpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + poshalf, + neghalf, + type, + vsc); + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_INT32 one, + OPJ_INT32 *nmsedec, + OPJ_UINT32 partial, + OPJ_UINT32 vsc) +{ + OPJ_INT32 v; + OPJ_UINT32 flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(*flagsp & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + v = int_abs(*datap) & one ? 1 : 0; + mqc_encode(mqc, v); + if (v) { +LABEL_PARTIAL: + *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = *datap < 0 ? 1 : 0; + mqc_encode(mqc, v ^ t1_getspb(flag)); + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp &= ~T1_VISIT; +} + +static void t1_dec_clnpass_step( + opj_t1_t *t1, + flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_UINT32 orient, + OPJ_INT32 oneplushalf, + OPJ_UINT32 partial, + OPJ_UINT32 vsc) +{ + OPJ_INT32 v; + OPJ_UINT32 flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { +LABEL_PARTIAL: + mqc_setcurctx(mqc, t1_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_getspb(flag); + *datap = v ? -oneplushalf : oneplushalf; + t1_updateflags(flagsp, v, t1->flags_stride); + } + } + *flagsp &= ~T1_VISIT; +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k; + OPJ_INT32 one; + OPJ_UINT32 agg, runlen, vsc; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + if (k + 3 < t1->h) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (MACRO_t1_flags(1 + k + 3,1 + i) + & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } else { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } + } else { + agg = 0; + } + if (agg) { + for (runlen = 0; runlen < 4; ++runlen) { + if (int_abs(t1->data[((k + runlen)*t1->w) + i]) & one) + break; + } + mqc_setcurctx(mqc, T1_CTXNO_AGG); + mqc_encode(mqc, runlen != 4); + if (runlen == 4) { + continue; + } + mqc_setcurctx(mqc, T1_CTXNO_UNI); + mqc_encode(mqc, runlen >> 1); + mqc_encode(mqc, runlen & 1); + } else { + runlen = 0; + } + for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_enc_clnpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + bpno, + one, + nmsedec, + agg && (j == k + runlen), + vsc); + } + } + } +} + +static void t1_dec_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_UINT32 orient, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, j, k, one; + OPJ_INT32 half, oneplushalf; + OPJ_UINT32 agg, runlen, vsc; + OPJ_UINT32 segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (k = 0; k < t1->h; k += 4) { + for (i = 0; i < t1->w; ++i) { + if (k + 3 < t1->h) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (MACRO_t1_flags(1 + k + 3,1 + i) + & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } else { + agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); + } + } else { + agg = 0; + } + if (agg) { + mqc_setcurctx(mqc, T1_CTXNO_AGG); + if (!mqc_decode(mqc)) { + continue; + } + mqc_setcurctx(mqc, T1_CTXNO_UNI); + runlen = mqc_decode(mqc); + runlen = (runlen << 1) | mqc_decode(mqc); + } else { + runlen = 0; + } + for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; + t1_dec_clnpass_step( + t1, + &t1->flags[((j+1) * t1->flags_stride) + i + 1], + &t1->data[(j * t1->w) + i], + orient, + oneplushalf, + agg && (j == k + runlen), + vsc); + } + } + } + if (segsym) { + OPJ_UINT32 v = 0; + mqc_setcurctx(mqc, T1_CTXNO_UNI); + v = mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + v = (v << 1) | mqc_decode(mqc); + /* + if (v!=0xa) { + opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); + } + */ + } +} /* VSC and BYPASS by Antonin */ + + +/** mod fixed_quality */ +static OPJ_FLOAT64 t1_getwmsedec( + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms) +{ + OPJ_FLOAT64 w1 = 1, w2, wmsedec; + if + (mct_norms) + { + w1 = mct_norms[compno]; + } + if (qmfbid == 1) + { + w2 = dwt_getnorm(level, orient); + } else { /* if (qmfbid == 0) */ + w2 = dwt_getnorm_real(level, orient); + } + wmsedec = w1 * w2 * stepsize * (1 << bpno); + wmsedec *= wmsedec * nmsedec / 8192.0; + return wmsedec; +} + +static bool allocate_buffers( + opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h) +{ + OPJ_UINT32 datasize=w * h; + OPJ_UINT32 flagssize; + + if(datasize > t1->datasize){ + opj_aligned_free(t1->data); + t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); + if(!t1->data){ + return false; + } + t1->datasize=datasize; + } + memset(t1->data,0,datasize * sizeof(OPJ_INT32)); + + t1->flags_stride=w+2; + flagssize=t1->flags_stride * (h+2); + + if(flagssize > t1->flagssize){ + opj_aligned_free(t1->flags); + t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t)); + if(!t1->flags){ + return false; + } + t1->flagssize=flagssize; + } + memset(t1->flags,0,flagssize * sizeof(flag_t)); + + t1->w=w; + t1->h=h; + + return true; +} + +/** mod fixed_quality */ +static void t1_encode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + opj_tcd_tile_t * tile, + const OPJ_FLOAT64 * mct_norms) +{ + OPJ_FLOAT64 cumwmsedec = 0.0; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + OPJ_UINT32 passno; + OPJ_INT32 bpno; + OPJ_UINT32 passtype; + OPJ_INT32 nmsedec = 0; + OPJ_INT32 max; + OPJ_UINT32 i; + OPJ_BYTE type = T1_TYPE_MQ; + OPJ_FLOAT64 tempwmsedec; + + max = 0; + for (i = 0; i < t1->w * t1->h; ++i) { + OPJ_INT32 tmp = abs(t1->data[i]); + max = int_max(max, tmp); + } + + cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0; + + bpno = cblk->numbps - 1; + passtype = 2; + + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; ++passno) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + OPJ_UINT32 correction = 3; + type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + switch (passtype) { + case 0: + t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty); + break; + case 1: + t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty); + break; + case 2: + t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) + mqc_segmark_enc(mqc); + break; + } + + /* fixed_quality */ + tempwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms) ; + cumwmsedec += tempwmsedec; + tile->distotile += tempwmsedec; + + /* Code switch "RESTART" (i.e. TERMALL) */ + if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) { + if (type == T1_TYPE_RAW) { + mqc_flush(mqc); + correction = 1; + /* correction = mqc_bypass_flush_enc(); */ + } else { /* correction = mqc_restart_enc(); */ + mqc_flush(mqc); + correction = 1; + } + pass->term = 1; + } else { + if (((bpno < ((OPJ_INT32) (cblk->numbps) - 4) && (passtype > 0)) + || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) { + if (type == T1_TYPE_RAW) { + mqc_flush(mqc); + correction = 1; + /* correction = mqc_bypass_flush_enc(); */ + } else { /* correction = mqc_restart_enc(); */ + mqc_flush(mqc); + correction = 1; + } + pass->term = 1; + } else { + pass->term = 0; + } + } + + if (++passtype == 3) { + passtype = 0; + bpno--; + } + + if (pass->term && bpno > 0) { + type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + if (type == T1_TYPE_RAW) + mqc_bypass_init_enc(mqc); + else + mqc_restart_init_enc(mqc); + } + + pass->distortiondec = cumwmsedec; + pass->rate = mqc_numbytes(mqc) + correction; /* FIXME */ + + /* Code-switch "RESET" */ + if (cblksty & J2K_CCP_CBLKSTY_RESET) + mqc_reset_enc(mqc); + } + + /* Code switch "ERTERM" (i.e. PTERM) */ + if (cblksty & J2K_CCP_CBLKSTY_PTERM) + mqc_erterm_enc(mqc); + else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY)) + mqc_flush(mqc); + + cblk->totalpasses = passno; + + for (passno = 0; passnototalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + if (pass->rate > mqc_numbytes(mqc)) + pass->rate = mqc_numbytes(mqc); + /*Preventing generation of FF as last data byte of a pass*/ + if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){ + pass->rate--; + } + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + } +} + +static void t1_decode_cblk( + opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty) +{ + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + OPJ_INT32 bpno; + OPJ_UINT32 passtype; + OPJ_UINT32 segno, passno; + OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ + + if(!allocate_buffers( + t1, + cblk->x1 - cblk->x0, + cblk->y1 - cblk->y0)) + { + return; + } + + bpno = roishift + cblk->numbps - 1; + passtype = 2; + + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + + for (segno = 0; segno < cblk->real_num_segs; ++segno) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno <= ((OPJ_INT32) (cblk->numbps) - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */ + if(seg->data == 00){ + continue; + } + if (type == T1_TYPE_RAW) { + raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len); + } else { + mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len); + } + + for (passno = 0; passno < seg->real_num_passes; ++passno) { + switch (passtype) { + case 0: + t1_dec_sigpass(t1, bpno+1, orient, type, cblksty); + break; + case 1: + t1_dec_refpass(t1, bpno+1, type, cblksty); + break; + case 2: + t1_dec_clnpass(t1, bpno+1, orient, cblksty); + break; + } + + if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + } + if (++passtype == 3) { + passtype = 0; + bpno--; + } + } + } +} + +/* ----------------------------------------------------------------------- */ +/** + * Creates a new Tier 1 handle + * and initializes the look-up tables of the Tier-1 coder/decoder + * @return a new T1 handle if successful, returns NULL otherwise +*/ +opj_t1_t* t1_create() +{ + opj_t1_t *l_t1 = 00; + + l_t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t)); + if + (!l_t1) + { + return 00; + } + memset(l_t1,0,sizeof(opj_t1_t)); + + /* create MQC and RAW handles */ + l_t1->mqc = mqc_create(); + if + (! l_t1->mqc) + { + t1_destroy(l_t1); + return 00; + } + l_t1->raw = raw_create(); + if + (! l_t1->raw) + { + t1_destroy(l_t1); + return 00; + } + return l_t1; +} + +/** + * Destroys a previously created T1 handle + * + * @param p_t1 Tier 1 handle to destroy +*/ +void t1_destroy(opj_t1_t *p_t1) +{ + if + (! p_t1) + { + return; + } + + /* destroy MQC and RAW handles */ + mqc_destroy(p_t1->mqc); + p_t1->mqc = 00; + raw_destroy(p_t1->raw); + p_t1->raw = 00; + if + (p_t1->data) + { + opj_aligned_free(p_t1->data); + p_t1->data = 00; + } + if + (p_t1->flags) + { + opj_aligned_free(p_t1->flags); + p_t1->flags = 00; + } + opj_free(p_t1); +} + +bool t1_encode_cblks( + opj_t1_t *t1, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + const OPJ_FLOAT64 * mct_norms) +{ + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + + tile->distotile = 0; /* fixed_quality */ + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + opj_tccp_t* tccp = &tcp->tccps[compno]; + OPJ_UINT32 tile_w = tilec->x1 - tilec->x0; + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* restrict band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + OPJ_INT32 * restrict datap; + OPJ_INT32* restrict tiledp; + OPJ_UINT32 cblk_w; + OPJ_UINT32 cblk_h; + OPJ_UINT32 i, j; + + OPJ_INT32 x = cblk->x0 - band->x0; + OPJ_INT32 y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + if(!allocate_buffers( + t1, + cblk->x1 - cblk->x0, + cblk->y1 - cblk->y0)) + { + return false; + } + + datap=t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + tiledp=&tilec->data[(y * tile_w) + x]; + if (tccp->qmfbid == 1) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 tmp = tiledp[(j * tile_w) + i]; + datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS; + } + } + } else { /* if (tccp->qmfbid == 0) */ + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 tmp = tiledp[(j * tile_w) + i]; + datap[(j * cblk_w) + i] = + fix_mul( + tmp, + 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS); + } + } + } + + t1_encode_cblk( + t1, + cblk, + band->bandno, + compno, + tilec->numresolutions - 1 - resno, + tccp->qmfbid, + band->stepsize, + tccp->cblksty, + tile->numcomps, + tile, + mct_norms); + + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + return true; +} + +void t1_decode_cblks( + opj_t1_t* t1, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp) +{ + OPJ_UINT32 resno, bandno, precno, cblkno; + + OPJ_UINT32 tile_w = tilec->x1 - tilec->x0; + + for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* restrict band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + OPJ_INT32* restrict datap; + void* restrict tiledp; + OPJ_UINT32 cblk_w, cblk_h; + OPJ_INT32 x, y; + OPJ_UINT32 i, j; + + t1_decode_cblk( + t1, + cblk, + band->bandno, + tccp->roishift, + tccp->cblksty); + + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + datap=t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + if (tccp->roishift) { + OPJ_INT32 thresh = 1 << tccp->roishift; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 val = datap[(j * cblk_w) + i]; + OPJ_INT32 mag = abs(val); + if (mag >= thresh) { + mag >>= tccp->roishift; + datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; + } + } + } + } + + tiledp=(void*)&tilec->data[(y * tile_w) + x]; + if (tccp->qmfbid == 1) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 tmp = datap[(j * cblk_w) + i]; + ((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp >> 1; + } + } + } else { /* if (tccp->qmfbid == 0) */ + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + float tmp = datap[(j * cblk_w) + i] * band->stepsize; + ((float*)tiledp)[(j * tile_w) + i] = tmp; + } + } + } + //opj_free(cblk->segs); + //cblk->segs = 00; + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ +} + + diff --git a/v2/libopenjpeg/t1.h b/v2/libopenjpeg/t1.h new file mode 100755 index 00000000..909c126c --- /dev/null +++ b/v2/libopenjpeg/t1.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __T1_H +#define __T1_H +/** +@file t1.h +@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1) + +The functions in T1.C have for goal to realize the tier-1 coding operation. The functions +in T1.C are used by some function in TCD.C. +*/ +#include "openjpeg.h" +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ +//#include "raw.h" +/* ----------------------------------------------------------------------- */ +#define T1_NMSEDEC_BITS 7 + +#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */ +#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */ +#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */ +#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */ +#define T1_SIG_N 0x0010 /**< Context orientation : North direction */ +#define T1_SIG_E 0x0020 /**< Context orientation : East direction */ +#define T1_SIG_S 0x0040 /**< Context orientation : South direction */ +#define T1_SIG_W 0x0080 /**< Context orientation : West direction */ +#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW) +#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W) + +#define T1_SGN_N 0x0100 +#define T1_SGN_E 0x0200 +#define T1_SGN_S 0x0400 +#define T1_SGN_W 0x0800 +#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W) + +#define T1_SIG 0x1000 +#define T1_REFINE 0x2000 +#define T1_VISIT 0x4000 + +#define T1_NUMCTXS_ZC 9 +#define T1_NUMCTXS_SC 5 +#define T1_NUMCTXS_MAG 3 +#define T1_NUMCTXS_AGG 1 +#define T1_NUMCTXS_UNI 1 + +#define T1_CTXNO_ZC 0 +#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC) +#define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC) +#define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG) +#define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG) +#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI) + +#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1) + +#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */ +#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/ + +/* ----------------------------------------------------------------------- */ +struct opj_common_struct; +struct opj_tcd_tile; +struct opj_tcp; +struct opj_tcd_tilecomp; +struct opj_mqc; +struct opj_raw; +struct opj_tccp; + + +typedef short flag_t; + +/** +Tier-1 coding (coding of code-block coefficients) +*/ +typedef struct opj_t1 { + /** MQC component */ + struct opj_mqc *mqc; + /** RAW component */ + struct opj_raw *raw; + + OPJ_INT32 *data; + flag_t *flags; + OPJ_UINT32 w; + OPJ_UINT32 h; + OPJ_UINT32 datasize; + OPJ_UINT32 flagssize; + OPJ_UINT32 flags_stride; +} opj_t1_t; + +#define MACRO_t1_flags(x,y) t1->flags[((x)*(t1->flags_stride))+(y)] + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** + * Creates a new Tier 1 handle + * and initializes the look-up tables of the Tier-1 coder/decoder + * @return a new T1 handle if successful, returns NULL otherwise +*/ +opj_t1_t* t1_create(); + +/** + * Destroys a previously created T1 handle + * + * @param p_t1 Tier 1 handle to destroy +*/ +void t1_destroy(opj_t1_t *p_t1); + +/** +Encode the code-blocks of a tile +@param t1 T1 handle +@param tile The tile to encode +@param tcp Tile coding parameters +*/ +bool t1_encode_cblks(opj_t1_t *t1, struct opj_tcd_tile *tile, struct opj_tcp *tcp,const OPJ_FLOAT64 * mct_norms); +/** +Decode the code-blocks of a tile +@param t1 T1 handle +@param tile The tile to decode +@param tcp Tile coding parameters +*/ +void t1_decode_cblks(opj_t1_t* t1, struct opj_tcd_tilecomp* tilec, struct opj_tccp* tccp); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T1_H */ diff --git a/v2/libopenjpeg/t1_generate_luts.c b/v2/libopenjpeg/t1_generate_luts.c new file mode 100755 index 00000000..1925b951 --- /dev/null +++ b/v2/libopenjpeg/t1_generate_luts.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opj_includes.h" +#include + +static int t1_init_ctxno_zc(int f, int orient) { + int h, v, d, n, t, hv; + n = 0; + h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0); + v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0); + d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0); + + switch (orient) { + case 2: + t = h; + h = v; + v = t; + case 0: + case 1: + if (!h) { + if (!v) { + if (!d) + n = 0; + else if (d == 1) + n = 1; + else + n = 2; + } else if (v == 1) { + n = 3; + } else { + n = 4; + } + } else if (h == 1) { + if (!v) { + if (!d) + n = 5; + else + n = 6; + } else { + n = 7; + } + } else + n = 8; + break; + case 3: + hv = h + v; + if (!d) { + if (!hv) { + n = 0; + } else if (hv == 1) { + n = 1; + } else { + n = 2; + } + } else if (d == 1) { + if (!hv) { + n = 3; + } else if (hv == 1) { + n = 4; + } else { + n = 5; + } + } else if (d == 2) { + if (!hv) { + n = 6; + } else { + n = 7; + } + } else { + n = 8; + } + break; + } + + return (T1_CTXNO_ZC + n); +} + +static int t1_init_ctxno_sc(int f) { + int hc, vc, n; + n = 0; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_SGN_S)), 1); + + if (hc < 0) { + hc = -hc; + vc = -vc; + } + if (!hc) { + if (vc == -1) + n = 1; + else if (!vc) + n = 0; + else + n = 1; + } else if (hc == 1) { + if (vc == -1) + n = 2; + else if (!vc) + n = 3; + else + n = 4; + } + + return (T1_CTXNO_SC + n); +} + +static int t1_init_spb(int f) { + int hc, vc, n; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_SGN_S)), 1); + + if (!hc && !vc) + n = 0; + else + n = (!(hc > 0 || (!hc && vc > 0))); + + return n; +} + +void dump_array16(int array[],int size){ + int i; + --size; + for (i = 0; i < size; ++i) { + printf("0x%04x, ", array[i]); + if(!((i+1)&0x7)) + printf("\n "); + } + printf("0x%04x\n};\n\n", array[size]); +} + +int main(){ + int i, j; + double u, v, t; + + int lut_ctxno_zc[1024]; + int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; + + printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); + + // lut_ctxno_zc + for (j = 0; j < 4; ++j) { + for (i = 0; i < 256; ++i) { + int orient = j; + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j); + } + } + + printf("static char lut_ctxno_zc[1024] = {\n "); + for (i = 0; i < 1023; ++i) { + printf("%i, ", lut_ctxno_zc[i]); + if(!((i+1)&0x1f)) + printf("\n "); + } + printf("%i\n};\n\n", lut_ctxno_zc[1023]); + + // lut_ctxno_sc + printf("static char lut_ctxno_sc[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("0x%x, ", t1_init_ctxno_sc(i << 4)); + if(!((i+1)&0xf)) + printf("\n "); + } + printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4)); + + // lut_spb + printf("static char lut_spb[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("%i, ", t1_init_spb(i << 4)); + if(!((i+1)&0x1f)) + printf("\n "); + } + printf("%i\n};\n\n", t1_init_spb(255 << 4)); + + /* FIXME FIXME FIXME */ + /* fprintf(stdout,"nmsedec luts:\n"); */ + for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + lut_nmsedec_sig[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_sig0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + u = t - 1.0; + if (i & (1 << (T1_NMSEDEC_BITS - 1))) { + v = t - 1.5; + } else { + v = t - 0.5; + } + lut_nmsedec_ref[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_ref0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + } + + printf("static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(&lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(&lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(&lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS); + + printf("static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n "); + dump_array16(&lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS); + + return 0; +} diff --git a/v2/libopenjpeg/t1_luts.h b/v2/libopenjpeg/t1_luts.h new file mode 100755 index 00000000..e5e33f66 --- /dev/null +++ b/v2/libopenjpeg/t1_luts.h @@ -0,0 +1,143 @@ +/* This file was automatically generated by t1_generate_luts.c */ + +static char lut_ctxno_zc[1024] = { + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 3, 3, 6, 3, 6, 6, 8, 3, 6, 6, 8, 6, 8, 8, 8, 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, + 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8 +}; + +static char lut_ctxno_sc[256] = { + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, + 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, + 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, + 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, + 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd +}; + +static char lut_spb[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80, + 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680, + 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280, + 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80, + 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80, + 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280, + 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80, + 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80, + 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680 +}; + +static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780, + 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100, + 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00, + 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300, + 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080, + 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80, + 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00 +}; + +static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = { + 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480, + 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080, + 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80, + 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480, + 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80, + 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80, + 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, + 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780 +}; + +static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = { + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980, + 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300, + 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00, + 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500, + 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280, + 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00 +}; + diff --git a/v2/libopenjpeg/t2.c b/v2/libopenjpeg/t2.c new file mode 100755 index 00000000..d9baaaef --- /dev/null +++ b/v2/libopenjpeg/t2.c @@ -0,0 +1,1290 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "openjpeg.h" +#include "opj_includes.h" +#include "t2.h" +#include "bio.h" +#include "tcd.h" +#include "pi.h" +#include "event.h" +#include "j2k.h" +#include "tgt.h" +#include "int.h" +#include "opj_malloc.h" +#include "pi.h" + + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static void t2_putcommacode(opj_bio_t *bio, OPJ_UINT32 n); +static OPJ_UINT32 t2_getcommacode(opj_bio_t *bio); +/** +Variable length code for signalling delta Zil (truncation point) +@param bio Bit Input/Output component +@param n delta Zil +*/ +static void t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n); +static OPJ_UINT32 t2_getnumpasses(opj_bio_t *bio); +/** +Encode a packet of a tile to a destination buffer +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param dest Destination buffer +@param len Length of the destination buffer +@param cstr_info Codestream information structure +@param tileno Number of the tile encoded +@return +*/ +static bool t2_encode_packet( + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info); +/** +@param seg +@param cblksty +@param first +*/ +static bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 index, OPJ_UINT32 cblksty, OPJ_UINT32 first); +/** +Decode a packet of a tile from a source buffer +@param t2 T2 handle +@param src Source buffer +@param len Length of the source buffer +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@return +*/ +static bool t2_decode_packet( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +/* #define RESTART 0x04 */ + +static void t2_putcommacode(opj_bio_t *bio, OPJ_UINT32 n) { + while + (--n != -1) + { + bio_write(bio, 1, 1); + } + bio_write(bio, 0, 1); +} + +static OPJ_UINT32 t2_getcommacode(opj_bio_t *bio) { + OPJ_UINT32 n = 0; + while + (bio_read(bio, 1)) + { + ++n; + } + return n; +} + +static void t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) { + if (n == 1) { + bio_write(bio, 0, 1); + } else if (n == 2) { + bio_write(bio, 2, 2); + } else if (n <= 5) { + bio_write(bio, 0xc | (n - 3), 4); + } else if (n <= 36) { + bio_write(bio, 0x1e0 | (n - 6), 9); + } else if (n <= 164) { + bio_write(bio, 0xff80 | (n - 37), 16); + } +} + +static OPJ_UINT32 t2_getnumpasses(opj_bio_t *bio) { + OPJ_UINT32 n; + if (!bio_read(bio, 1)) + return 1; + if (!bio_read(bio, 1)) + return 2; + if ((n = bio_read(bio, 2)) != 3) + return (3 + n); + if ((n = bio_read(bio, 5)) != 31) + return (6 + n); + return (37 + bio_read(bio, 7)); +} + +static bool t2_encode_packet( + OPJ_UINT32 tileno, + opj_tcd_tile_t * tile, + opj_tcp_t * tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 length, + opj_codestream_info_t *cstr_info) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_BYTE *c = dest; + OPJ_UINT32 l_nb_bytes; + OPJ_UINT32 compno = pi->compno; /* component value */ + OPJ_UINT32 resno = pi->resno; /* resolution level value */ + OPJ_UINT32 precno = pi->precno; /* precinct value */ + OPJ_UINT32 layno = pi->layno; /* quality layer value */ + OPJ_UINT32 l_nb_blocks; + opj_tcd_band_t *band = 00; + opj_tcd_cblk_enc_t* cblk = 00; + opj_tcd_pass_t *pass = 00; + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + opj_bio_t *bio = 00; /* BIO component */ + + /* */ + if (tcp->csty & J2K_CP_CSTY_SOP) { + c[0] = 255; + c[1] = 145; + c[2] = 0; + c[3] = 4; + c[4] = (tile->packno % 65536) / 256; + c[5] = (tile->packno % 65536) % 256; + c += 6; + length -= 6; + } + /* */ + + if (!layno) { + band = res->bands; + for + (bandno = 0; bandno < res->numbands; ++bandno) + { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + tgt_reset(prc->incltree); + tgt_reset(prc->imsbtree); + l_nb_blocks = prc->cw * prc->ch; + for + (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) + { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + cblk->numpasses = 0; + tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps); + } + ++band; + } + } + + bio = bio_create(); + bio_init_enc(bio, c, length); + bio_write(bio, 1, 1); /* Empty header bit */ + + /* Writing Packet header */ + band = res->bands; + for + (bandno = 0; bandno < res->numbands; ++bandno) + { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) + { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if + (!cblk->numpasses && layer->numpasses) + { + tgt_setvalue(prc->incltree, cblkno, layno); + } + ++cblk; + } + cblk = prc->cblks.enc; + for + (cblkno = 0; cblkno < l_nb_blocks; cblkno++) + { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 increment = 0; + OPJ_UINT32 nump = 0; + OPJ_UINT32 len = 0, passno; + OPJ_UINT32 l_nb_passes; + /* cblk inclusion bits */ + if (!cblk->numpasses) { + tgt_encode(bio, prc->incltree, cblkno, layno + 1); + } else { + bio_write(bio, layer->numpasses != 0, 1); + } + /* if cblk not included, go to the next cblk */ + if + (!layer->numpasses) + { + ++cblk; + continue; + } + /* if first instance of cblk --> zero bit-planes information */ + if + (!cblk->numpasses) + { + cblk->numlenbits = 3; + tgt_encode(bio, prc->imsbtree, cblkno, 999); + } + /* number of coding passes included */ + t2_putnumpasses(bio, layer->numpasses); + l_nb_passes = cblk->numpasses + layer->numpasses; + pass = cblk->passes + cblk->numpasses; + /* computation of the increase of the length indicator and insertion in the header */ + for + (passno = cblk->numpasses; passno < l_nb_passes; ++passno) + { + ++nump; + len += pass->len; + if + (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) + { + increment = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump))); + len = 0; + nump = 0; + } + ++pass; + } + t2_putcommacode(bio, increment); + + /* computation of the new Length indicator */ + cblk->numlenbits += increment; + + pass = cblk->passes + cblk->numpasses; + /* insertion of the codeword segment length */ + for + (passno = cblk->numpasses; passno < l_nb_passes; ++passno) + { + nump++; + len += pass->len; + if + (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) + { + bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump)); + len = 0; + nump = 0; + } + ++pass; + } + ++cblk; + } + ++band; + } + + if + (bio_flush(bio)) + { + bio_destroy(bio); + return false; /* modified to eliminate longjmp !! */ + } + l_nb_bytes = bio_numbytes(bio); + c += l_nb_bytes; + length -= l_nb_bytes; + bio_destroy(bio); + + /* */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + c[0] = 255; + c[1] = 146; + c += 2; + length -= 2; + } + /* */ + + /* << INDEX */ + // End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value + if(cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->end_ph_pos = (OPJ_INT32)(c - dest); + } + /* INDEX >> */ + + /* Writing the packet body */ + band = res->bands; + for + (bandno = 0; bandno < res->numbands; bandno++) + { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + for + (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) + { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if + (!layer->numpasses) + { + ++cblk; + continue; + } + if + (layer->len > length) + { + return false; + } + memcpy(c, layer->data, layer->len); + cblk->numpasses += layer->numpasses; + c += layer->len; + length -= layer->len; + /* << INDEX */ + if(cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->disto += layer->disto; + if (cstr_info->D_max < info_PK->disto) { + cstr_info->D_max = info_PK->disto; + } + } + ++cblk; + /* INDEX >> */ + } + ++band; + } + * p_data_written += (c - dest); + return true; +} + +static bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 index, OPJ_UINT32 cblksty, OPJ_UINT32 first) +{ + opj_tcd_seg_t* seg = 00; + OPJ_UINT32 l_nb_segs = index + 1; + + if + (l_nb_segs > cblk->m_current_max_segs) + { + cblk->m_current_max_segs += J2K_DEFAULT_NB_SEGS; + cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, cblk->m_current_max_segs * sizeof(opj_tcd_seg_t)); + if + (! cblk->segs) + { + return false; + } + } + seg = &cblk->segs[index]; + memset(seg,0,sizeof(opj_tcd_seg_t)); + + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + seg->maxpasses = 1; + } + else if (cblksty & J2K_CCP_CBLKSTY_LAZY) { + if (first) { + seg->maxpasses = 10; + } else { + seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1; + } + } else { + seg->maxpasses = 109; + } + return true; +} + +static bool t2_read_packet_header( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + bool * p_is_data_present, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info) +{ + /* loop */ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_UINT32 l_remaining_length; + OPJ_UINT32 l_header_length; + OPJ_UINT32 * l_modified_length_ptr = 00; + OPJ_BYTE *l_current_data = p_src_data; + opj_cp_t *l_cp = p_t2->cp; + opj_bio_t *l_bio = 00; /* BIO component */ + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + OPJ_BYTE *l_header_data = 00; + OPJ_BYTE **l_header_data_start = 00; + + OPJ_UINT32 l_present; + + if + (p_pi->layno == 0) + { + l_band = l_res->bands; + /* reset tagtrees */ + for + (bandno = 0; bandno < l_res->numbands; ++bandno) + { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if ( + ! ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0))) + { + tgt_reset(l_prc->incltree); + tgt_reset(l_prc->imsbtree); + l_cblk = l_prc->cblks.dec; + l_nb_code_blocks = l_prc->cw * l_prc->ch; + for + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) + { + l_cblk->numsegs = 0; + l_cblk->real_num_segs = 0; + ++l_cblk; + } + } + ++l_band; + } + } + + /* SOP markers */ + + if (p_tcp->csty & J2K_CP_CSTY_SOP) { + if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) { + // TODO opj_event_msg(t2->cinfo->event_mgr, EVT_WARNING, "Expected SOP marker\n"); + } else { + l_current_data += 6; + } + + /** TODO : check the Nsop value */ + } + + /* + When the marker PPT/PPM is used the packet header are store in PPT/PPM marker + This part deal with this caracteristic + step 1: Read packet header in the saved structure + step 2: Return to codestream for decoding + */ + + l_bio = bio_create(); + if + (! l_bio) + { + return false; + } + + if + (l_cp->ppm == 1) + { /* PPM */ + l_header_data_start = &l_cp->ppm_data; + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(l_cp->ppm_len); + + } + else if + (p_tcp->ppt == 1) + { /* PPT */ + l_header_data_start = &(p_tcp->ppt_data); + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(p_tcp->ppt_len); + } + else + { /* Normal Case */ + l_header_data_start = &(l_current_data); + l_header_data = *l_header_data_start; + l_remaining_length = p_src_data+p_max_length-l_header_data; + l_modified_length_ptr = &(l_remaining_length); + } + bio_init_dec(l_bio, l_header_data,*l_modified_length_ptr); + l_present = bio_read(l_bio, 1); + if + (!l_present) + { + bio_inalign(l_bio); + l_header_data += bio_numbytes(l_bio); + bio_destroy(l_bio); + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + printf("Error : expected EPH marker\n"); + } else { + l_header_data += 2; + } + } + l_header_length = (l_header_data - *l_header_data_start); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; + /* << INDEX */ + // End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value + if + (p_pack_info) + { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ + * p_is_data_present = false; + *p_data_read = l_current_data - p_src_data; + return true; + } + + l_band = l_res->bands; + for + (bandno = 0; bandno < l_res->numbands; ++bandno) + { + opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]); + + if ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) + { + ++l_band; + continue; + } + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + for + (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) + { + OPJ_UINT32 l_included,l_increment, l_segno; + OPJ_INT32 n; + /* if cblk not yet included before --> inclusion tagtree */ + if + (!l_cblk->numsegs) + { + l_included = tgt_decode(l_bio, l_prc->incltree, cblkno, p_pi->layno + 1); + /* else one bit */ + } + else + { + l_included = bio_read(l_bio, 1); + } + /* if cblk not included */ + if + (!l_included) + { + l_cblk->numnewpasses = 0; + ++l_cblk; + continue; + } + /* if cblk not yet included --> zero-bitplane tagtree */ + if + (!l_cblk->numsegs) + { + OPJ_UINT32 i = 0; + while + (!tgt_decode(l_bio, l_prc->imsbtree, cblkno, i)) + { + ++i; + } + l_cblk->numbps = l_band->numbps + 1 - i; + l_cblk->numlenbits = 3; + } + /* number of coding passes */ + l_cblk->numnewpasses = t2_getnumpasses(l_bio); + l_increment = t2_getcommacode(l_bio); + /* length indicator increment */ + l_cblk->numlenbits += l_increment; + l_segno = 0; + if + (!l_cblk->numsegs) + { + if + (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) + { + bio_destroy(l_bio); + return false; + } + + } + else + { + l_segno = l_cblk->numsegs - 1; + if + (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) + { + ++l_segno; + if + (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) + { + bio_destroy(l_bio); + return false; + } + } + } + n = l_cblk->numnewpasses; + + do { + l_cblk->segs[l_segno].numnewpasses = int_min(l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses, n); + l_cblk->segs[l_segno].newlen = bio_read(l_bio, l_cblk->numlenbits + uint_floorlog2(l_cblk->segs[l_segno].numnewpasses)); + n -= l_cblk->segs[l_segno].numnewpasses; + if + (n > 0) + { + ++l_segno; + if + (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) + { + bio_destroy(l_bio); + return false; + } + } + } + while (n > 0); + ++l_cblk; + } + ++l_band; + } + + if + (bio_inalign(l_bio)) + { + bio_destroy(l_bio); + return false; + } + + l_header_data += bio_numbytes(l_bio); + bio_destroy(l_bio); + + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + // TODO opj_event_msg(t2->cinfo->event_mgr, EVT_ERROR, "Expected EPH marker\n"); + } else { + l_header_data += 2; + } + } + + + l_header_length = (l_header_data - *l_header_data_start); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; + /* << INDEX */ + // End of packet header position. Currently only represents the distance to start of packet + // Will be updated later by incrementing with packet start value + if + (p_pack_info) + { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ + * p_is_data_present = true; + *p_data_read = l_current_data - p_src_data; + return true; +} + +static bool t2_read_packet_data( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_BYTE *l_current_data = p_src_data; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + l_band = l_res->bands; + for + (bandno = 0; bandno < l_res->numbands; ++bandno) + { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if + ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) + { + ++l_band; + continue; + } + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + for + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) + { + opj_tcd_seg_t *l_seg = 00; + if + (!l_cblk->numnewpasses) + { + /* nothing to do */ + ++l_cblk; + continue; + } + if + (!l_cblk->numsegs) + { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + l_cblk->len = 0; + } + else + { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + if + (l_seg->numpasses == l_seg->maxpasses) + { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do + { + if + (l_current_data + l_seg->newlen > p_src_data + p_max_length) + { + return false; + } + +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((cblk->len + seg->newlen) > 8192) { + opj_event_msg(t2->cinfo, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + seg->newlen, cblkno, precno, bandno, resno, compno); + if (!JPWL_ASSUME) { + opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return -999; + } + seg->newlen = 8192 - cblk->len; + opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen); + break; + }; + +#endif /* USE_JPWL */ + + memcpy(l_cblk->data + l_cblk->len, l_current_data, l_seg->newlen); + if + (l_seg->numpasses == 0) + { + l_seg->data = &l_cblk->data; + l_seg->dataindex = l_cblk->len; + } + l_current_data += l_seg->newlen; + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + + l_seg->real_num_passes = l_seg->numpasses; + l_cblk->len += l_seg->newlen; + l_seg->len += l_seg->newlen; + if + (l_cblk->numnewpasses > 0) + { + ++l_seg; + ++l_cblk->numsegs; + } + } + while (l_cblk->numnewpasses > 0); + l_cblk->real_num_segs = l_cblk->numsegs; + ++l_cblk; + } + ++l_band; + } + *(p_data_read) = l_current_data - p_src_data; + return true; +} + + +static bool t2_skip_packet_data( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + + opj_tcd_resolution_t* l_res = &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + *p_data_read = 0; + l_band = l_res->bands; + for + (bandno = 0; bandno < l_res->numbands; ++bandno) + { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if + ((l_band->x1-l_band->x0 == 0)||(l_band->y1-l_band->y0 == 0)) + { + ++l_band; + continue; + } + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + for + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) + { + opj_tcd_seg_t *l_seg = 00; + if + (!l_cblk->numnewpasses) + { + /* nothing to do */ + ++l_cblk; + continue; + } + if + (!l_cblk->numsegs) + { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + l_cblk->len = 0; + } + else + { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + if + (l_seg->numpasses == l_seg->maxpasses) + { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do + { + if + (* p_data_read + l_seg->newlen > p_max_length) + { + return false; + } + +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((cblk->len + seg->newlen) > 8192) { + opj_event_msg(t2->cinfo, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + seg->newlen, cblkno, precno, bandno, resno, compno); + if (!JPWL_ASSUME) { + opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n"); + return -999; + } + seg->newlen = 8192 - cblk->len; + opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen); + break; + }; + +#endif /* USE_JPWL */ + *(p_data_read) += l_seg->newlen; + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + if + (l_cblk->numnewpasses > 0) + { + ++l_seg; + ++l_cblk->numsegs; + } + } + while (l_cblk->numnewpasses > 0); + ++l_cblk; + } + } + return true; +} + +static bool t2_decode_packet( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info) +{ + bool l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; + + *p_data_read = 0; + + if + (! t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) + { + return false; + } + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; + /* we should read data for the packet */ + if + (l_read_data) + { + l_nb_bytes_read = 0; + if + (! t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) + { + return false; + } + l_nb_total_bytes_read += l_nb_bytes_read; + } + *p_data_read = l_nb_total_bytes_read; + return true; +} + +static bool t2_skip_packet( + opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info) +{ + bool l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; + + *p_data_read = 0; + + if + (! t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) + { + return false; + } + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; + /* we should read data for the packet */ + if + (l_read_data) + { + l_nb_bytes_read = 0; + if + (! t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info)) + { + return false; + } + l_nb_total_bytes_read += l_nb_bytes_read; + } + *p_data_read = l_nb_total_bytes_read; + return true; +} + +/* ----------------------------------------------------------------------- */ + +bool t2_encode_packets( + opj_t2_t* p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_UINT32 p_maxlayers, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_len, + opj_codestream_info_t *cstr_info, + OPJ_UINT32 p_tp_num, + OPJ_INT32 p_tp_pos, + OPJ_UINT32 p_pino, + J2K_T2_MODE p_t2_mode) +{ + OPJ_BYTE *l_current_data = p_dest; + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 compno; + OPJ_UINT32 poc; + opj_pi_iterator_t *l_pi = 00; + opj_pi_iterator_t *l_current_pi = 00; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = &l_cp->tcps[p_tile_no]; + OPJ_UINT32 pocno = l_cp->m_specific_param.m_enc.m_cinema == CINEMA4K_24? 2: 1; + OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? l_image->numcomps : 1; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + + l_pi = pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode); + if + (!l_pi) + { + return false; + } + * p_data_written = 0; + if + (p_t2_mode == THRESH_CALC ) + { /* Calculating threshold */ + l_current_pi = l_pi; + for + (compno = 0; compno < l_max_comp; ++compno) + { + OPJ_UINT32 l_comp_len = 0; + l_current_pi = l_pi; + + for + (poc = 0; poc < pocno ; ++poc) + { + OPJ_UINT32 l_tp_num = compno; + pi_create_encode(l_pi, l_cp,p_tile_no,poc,l_tp_num,p_tp_pos,p_t2_mode); + while + (pi_next(l_current_pi)) + { + if + (l_current_pi->layno < p_maxlayers) + { + l_nb_bytes = 0; + if + (! t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) + { + pi_destroy(l_pi, l_nb_pocs); + return false; + } + l_comp_len += l_nb_bytes; + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; + * p_data_written += l_nb_bytes; + } + } + if + (l_cp->m_specific_param.m_enc.m_max_comp_size) + { + if + (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) + { + pi_destroy(l_pi, l_nb_pocs); + return false; + } + } + ++l_current_pi; + } + } + } + else + { /* t2_mode == FINAL_PASS */ + pi_create_encode(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos,p_t2_mode); + l_current_pi = &l_pi[p_pino]; + while + (pi_next(l_current_pi)) + { + if + (l_current_pi->layno < p_maxlayers) + { + l_nb_bytes=0; + if + (! t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) + { + pi_destroy(l_pi, l_nb_pocs); + return false; + } + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; + * p_data_written += l_nb_bytes; + + /* INDEX >> */ + if(cstr_info) { + if(cstr_info->index_write) { + opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; + info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance + // to start of packet is incremented by value of start of packet + } + + cstr_info->packno++; + } + /* << INDEX */ + ++p_tile->packno; + } + } + } + pi_destroy(l_pi, l_nb_pocs); + return true; +} + +bool t2_decode_packets( + opj_t2_t *p_t2, + OPJ_UINT32 p_tile_no, + struct opj_tcd_tile *p_tile, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_len, + struct opj_codestream_info *p_cstr_info) +{ + OPJ_BYTE *l_current_data = p_src; + opj_pi_iterator_t *l_pi = 00; + OPJ_UINT32 pino; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_cp_t *cp = p_t2->cp; + opj_tcp_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]); + OPJ_UINT32 l_nb_bytes_read; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + opj_pi_iterator_t *l_current_pi = 00; + OPJ_UINT32 curtp = 0; + OPJ_UINT32 tp_start_packno; + opj_packet_info_t *l_pack_info = 00; + opj_image_comp_t* l_img_comp = 00; + + + if + (p_cstr_info) + { + l_pack_info = p_cstr_info->tile[p_tile_no].packet; + } + + /* create a packet iterator */ + l_pi = pi_create_decode(l_image, l_cp, p_tile_no); + if + (!l_pi) + { + return false; + } + + tp_start_packno = 0; + l_current_pi = l_pi; + + for + (pino = 0; pino <= l_tcp->numpocs; ++pino) + { + while + (pi_next(l_current_pi)) + { + + if + (l_tcp->num_layers_to_decode > l_current_pi->layno && l_current_pi->resno < p_tile->comps[l_current_pi->compno].minimum_num_resolutions) + { + l_nb_bytes_read = 0; + if + (! t2_decode_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info)) + { + pi_destroy(l_pi,l_nb_pocs); + return false; + } + l_img_comp = &(l_image->comps[l_current_pi->compno]); + l_img_comp->resno_decoded = uint_max(l_current_pi->resno, l_img_comp->resno_decoded); + } + else + { + l_nb_bytes_read = 0; + if + (! t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info)) + { + pi_destroy(l_pi,l_nb_pocs); + return false; + } + } + l_current_data += l_nb_bytes_read; + p_max_len -= l_nb_bytes_read; + + /* INDEX >> */ + if(p_cstr_info) { + opj_tile_info_t *info_TL = &p_cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; + if (!p_cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else if (info_TL->packet[p_cstr_info->packno-1].end_pos >= (OPJ_INT32)p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos){ // New tile part + info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; // Number of packets in previous tile-part + tp_start_packno = p_cstr_info->packno; + curtp++; + info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header+1; + } else { + info_PK->start_pos = (cp->m_specific_param.m_enc.m_tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1; + info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance + ++p_cstr_info->packno; + } + /* << INDEX */ + } + ++l_current_pi; + } + /* INDEX >> */ + if + (p_cstr_info) { + p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno - tp_start_packno; // Number of packets in last tile-part + } + /* << INDEX */ + + /* don't forget to release pi */ + pi_destroy(l_pi,l_nb_pocs); + *p_data_read = l_current_data - p_src; + return true; +} + +/* ----------------------------------------------------------------------- */ +/** + * Creates a Tier 2 handle + * + * @param p_image Source or destination image + * @param p_cp Image coding parameters. + * @return a new T2 handle if successful, NULL otherwise. +*/ +opj_t2_t* t2_create( + opj_image_t *p_image, + opj_cp_t *p_cp) +{ + /* create the tcd structure */ + opj_t2_t *l_t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t)); + if + (!l_t2) + { + return 00; + } + memset(l_t2,0,sizeof(opj_t2_t)); + l_t2->image = p_image; + l_t2->cp = p_cp; + return l_t2; +} + +/** + * Destroys a Tier 2 handle. + * + * @param p_t2 the Tier 2 handle to destroy +*/ +void t2_destroy(opj_t2_t *p_t2) +{ + if + (p_t2) + { + opj_free(p_t2); + } +} + + + + diff --git a/v2/libopenjpeg/t2.h b/v2/libopenjpeg/t2.h new file mode 100755 index 00000000..0ecf95bf --- /dev/null +++ b/v2/libopenjpeg/t2.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __T2_H +#define __T2_H +/** +@file t2.h +@brief Implementation of a tier-2 coding (packetization of code-block data) (T2) + +*/ +#include "openjpeg.h" + +struct opj_common_struct; +struct opj_image; +struct opj_cp; +struct opj_tcd_tile; +struct opj_codestream_info; + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** +T2 encoding mode +*/ +typedef enum T2_MODE +{ + THRESH_CALC = 0, /** Function called in Rate allocation process*/ + FINAL_PASS = 1 /** Function called in Tier 2 process*/ +} +J2K_T2_MODE; + +/** +Tier-2 coding +*/ + +typedef struct opj_t2 { + /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ + struct opj_image *image; + /** pointer to the image coding parameters */ + struct opj_cp *cp; +} opj_t2_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Encode the packets of a tile to a destination buffer +@param t2 T2 handle +@param tileno number of the tile encoded +@param tile the tile for which to write the packets +@param maxlayers maximum number of layers +@param dest the destination buffer +@param len the length of the destination buffer +@param cstr_info Codestream information structure +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass +*/ +bool t2_encode_packets(opj_t2_t* t2,OPJ_UINT32 tileno, struct opj_tcd_tile *tile, OPJ_UINT32 maxlayers, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, struct opj_codestream_info *cstr_info,OPJ_UINT32 tpnum, OPJ_INT32 tppos,OPJ_UINT32 pino,J2K_T2_MODE t2_mode); +/** +Decode the packets of a tile from a source buffer +@param t2 T2 handle +@param src the source buffer +@param len length of the source buffer +@param tileno number that identifies the tile for which to decode the packets +@param tile tile for which to decode the packets + */ +bool t2_decode_packets(opj_t2_t *t2, OPJ_UINT32 tileno,struct opj_tcd_tile *tile, OPJ_BYTE *src, OPJ_UINT32 * p_data_read, OPJ_UINT32 len, struct opj_codestream_info *cstr_info); + +/** + * Creates a Tier 2 handle + * + * @param p_image Source or destination image + * @param p_cp Image coding parameters. + * @return a new T2 handle if successful, NULL otherwise. +*/ +opj_t2_t* t2_create(struct opj_image *p_image, struct opj_cp *p_cp); + +/** + * Destroys a Tier 2 handle. + * + * @param p_t2 the Tier 2 handle to destroy +*/ +void t2_destroy(opj_t2_t *t2); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T2_H */ diff --git a/v2/libopenjpeg/tcd.c b/v2/libopenjpeg/tcd.c new file mode 100755 index 00000000..b84c2ce5 --- /dev/null +++ b/v2/libopenjpeg/tcd.c @@ -0,0 +1,2121 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tcd.h" +#include "openjpeg.h" +#include "j2k.h" +#include "opj_includes.h" +#include "event.h" +#include "t2.h" +#include "t1.h" +#include "opj_malloc.h" +#include "int.h" +#include "tgt.h" +#include "dwt.h" +#include "mct.h" +#include "j2k_lib.h" +#include "profile.h" + +/** + * Deallocates the encoding data of the given precinct. + */ +static void tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct); +/** + * Allocates memory for an encoding code block. + */ +static bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block); +/** + * Allocates memory for a decoding code block. + */ +static bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block); +/** +Free the memory allocated for encoding +@param tcd TCD handle +*/ +static void tcd_free_tile(opj_tcd_t *tcd); + +/* ----------------------------------------------------------------------- */ + +/** +Create a new TCD handle +*/ +opj_tcd_t* tcd_create(bool p_is_decoder) +{ + opj_tcd_t *l_tcd = 00; + + /* create the tcd structure */ + l_tcd = (opj_tcd_t*) opj_malloc(sizeof(opj_tcd_t)); + if + (!l_tcd) + { + return 00; + } + memset(l_tcd,0,sizeof(opj_tcd_t)); + l_tcd->m_is_decoder = p_is_decoder ? 1 : 0; + l_tcd->tcd_image = (opj_tcd_image_t*)opj_malloc(sizeof(opj_tcd_image_t)); + if + (!l_tcd->tcd_image) + { + opj_free(l_tcd); + return 00; + } + memset(l_tcd->tcd_image,0,sizeof(opj_tcd_image_t)); + return l_tcd; +} + +/** +Destroy a previously created TCD handle +*/ +void tcd_destroy(opj_tcd_t *tcd) { + if + (tcd) + { + tcd_free_tile(tcd); + if + (tcd->tcd_image) + { + opj_free(tcd->tcd_image); + tcd->tcd_image = 00; + } + opj_free(tcd); + } +} + +/* ----------------------------------------------------------------------- */ +/** + * Initialize the tile coder and may reuse some meory. + * @param p_tcd TCD handle. + * @param p_image raw image. + * @param p_cp coding parameters. + * @param p_tile_no current tile index to encode. + * + * @return true if the encoding values could be set (false otherwise). +*/ +#define MACRO_TCD_ALLOCATE(FUNCTION,TYPE,FRACTION,ELEMENT,FUNCTION_ELEMENT) \ +bool FUNCTION \ + ( \ + opj_tcd_t *p_tcd, \ + OPJ_UINT32 p_tile_no \ + ) \ +{ \ + OPJ_UINT32 (*l_gain_ptr)(OPJ_UINT32) = 00; \ + OPJ_UINT32 compno, resno, bandno, precno, cblkno; \ + opj_tcp_t * l_tcp = 00; \ + opj_cp_t * l_cp = 00; \ + opj_tcd_tile_t * l_tile = 00; \ + opj_tccp_t *l_tccp = 00; \ + opj_tcd_tilecomp_t *l_tilec = 00; \ + opj_image_comp_t * l_image_comp = 00; \ + opj_tcd_resolution_t *l_res = 00; \ + opj_tcd_band_t *l_band = 00; \ + opj_stepsize_t * l_step_size = 00; \ + opj_tcd_precinct_t *l_current_precinct = 00; \ + TYPE* l_code_block = 00; \ + opj_image_t * l_image = 00; \ + OPJ_UINT32 p,q; \ + OPJ_UINT32 l_level_no; \ + OPJ_UINT32 l_pdx, l_pdy; \ + OPJ_UINT32 l_gain; \ + OPJ_INT32 l_x0b, l_y0b; \ + /* extent of precincts , top left, bottom right**/ \ + OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end; \ + /* number of precinct for a resolution */ \ + OPJ_UINT32 l_nb_precincts; \ + /* room needed to store l_nb_precinct precinct for a resolution */ \ + OPJ_UINT32 l_nb_precinct_size; \ + /* number of code blocks for a precinct*/ \ + OPJ_UINT32 l_nb_code_blocks; \ + /* room needed to store l_nb_code_blocks code blocks for a precinct*/ \ + OPJ_UINT32 l_nb_code_blocks_size; \ + /* size of data for a tile */ \ + OPJ_UINT32 l_data_size; \ + l_cp = p_tcd->cp; \ + l_tcp = &(l_cp->tcps[p_tile_no]); \ + l_tile = p_tcd->tcd_image->tiles; \ + l_tccp = l_tcp->tccps; \ + l_tilec = l_tile->comps; \ + l_image = p_tcd->image; \ + l_image_comp = p_tcd->image->comps; \ + \ + p = p_tile_no % l_cp->tw; /* tile coordinates */ \ + q = p_tile_no / l_cp->tw; \ + \ + /* 4 borders of the tile rescale on the image if necessary */ \ + l_tile->x0 = int_max(l_cp->tx0 + p * l_cp->tdx, l_image->x0); \ + l_tile->y0 = int_max(l_cp->ty0 + q * l_cp->tdy, l_image->y0); \ + l_tile->x1 = int_min(l_cp->tx0 + (p + 1) * l_cp->tdx, l_image->x1); \ + l_tile->y1 = int_min(l_cp->ty0 + (q + 1) * l_cp->tdy, l_image->y1); \ + /*tile->numcomps = image->numcomps; */ \ + for \ + (compno = 0; compno < l_tile->numcomps; ++compno) \ + { \ + /* border of each l_tile component (global) */ \ + l_tilec->x0 = int_ceildiv(l_tile->x0, l_image_comp->dx); \ + l_tilec->y0 = int_ceildiv(l_tile->y0, l_image_comp->dy); \ + l_tilec->x1 = int_ceildiv(l_tile->x1, l_image_comp->dx); \ + l_tilec->y1 = int_ceildiv(l_tile->y1, l_image_comp->dy); \ + \ + l_data_size = (l_tilec->x1 - l_tilec->x0) \ + * (l_tilec->y1 - l_tilec->y0) * sizeof(OPJ_UINT32 ); \ + l_tilec->numresolutions = l_tccp->numresolutions; \ + if \ + (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce)\ + { \ + l_tilec->minimum_num_resolutions = 1; \ + } \ + else \ + { \ + l_tilec->minimum_num_resolutions = l_tccp->numresolutions - l_cp->m_specific_param.m_dec.m_reduce;\ + } \ + if \ + (l_tilec->data == 00) \ + { \ + l_tilec->data = (OPJ_INT32 *) opj_aligned_malloc(l_data_size); \ + if \ + (! l_tilec->data ) \ + { \ + return false; \ + } \ + l_tilec->data_size = l_data_size; \ + } \ + else if \ + (l_data_size > l_tilec->data_size) \ + { \ + l_tilec->data = (OPJ_INT32 *) opj_realloc(l_tilec->data, l_data_size);\ + if \ + (! l_tilec->data) \ + { \ + return false; \ + } \ + l_tilec->data_size = l_data_size; \ + } \ + l_data_size = l_tilec->numresolutions * sizeof(opj_tcd_resolution_t);\ + if \ + (l_tilec->resolutions == 00) \ + { \ + l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size);\ + if \ + (! l_tilec->resolutions ) \ + { \ + return false; \ + } \ + l_tilec->resolutions_size = l_data_size; \ + memset(l_tilec->resolutions,0,l_data_size); \ + } \ + else if \ + (l_data_size > l_tilec->resolutions_size) \ + { \ + l_tilec->resolutions = (opj_tcd_resolution_t *) opj_realloc(l_tilec->resolutions, l_data_size);\ + if \ + (! l_tilec->resolutions) \ + { \ + return false; \ + } \ + memset(((OPJ_BYTE*) l_tilec->resolutions)+l_tilec->resolutions_size,0,l_data_size - l_tilec->resolutions_size);\ + l_tilec->resolutions_size = l_data_size; \ + } \ + l_level_no = l_tilec->numresolutions - 1; \ + l_res = l_tilec->resolutions; \ + l_step_size = l_tccp->stepsizes; \ + if \ + (l_tccp->qmfbid == 0) \ + { \ + l_gain_ptr = &dwt_getgain_real; \ + } \ + else \ + { \ + l_gain_ptr = &dwt_getgain; \ + } \ + for \ + (resno = 0; resno < l_tilec->numresolutions; ++resno) \ + { \ + OPJ_INT32 tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; \ + OPJ_UINT32 cbgwidthexpn, cbgheightexpn; \ + OPJ_UINT32 cblkwidthexpn, cblkheightexpn; \ + /* border for each resolution level (global) */ \ + l_res->x0 = int_ceildivpow2(l_tilec->x0, l_level_no); \ + l_res->y0 = int_ceildivpow2(l_tilec->y0, l_level_no); \ + l_res->x1 = int_ceildivpow2(l_tilec->x1, l_level_no); \ + l_res->y1 = int_ceildivpow2(l_tilec->y1, l_level_no); \ + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */\ + l_pdx = l_tccp->prcw[resno]; \ + l_pdy = l_tccp->prch[resno]; \ + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ \ + l_tl_prc_x_start = int_floordivpow2(l_res->x0, l_pdx) << l_pdx; \ + l_tl_prc_y_start = int_floordivpow2(l_res->y0, l_pdy) << l_pdy; \ + l_br_prc_x_end = int_ceildivpow2(l_res->x1, l_pdx) << l_pdx; \ + l_br_prc_y_end = int_ceildivpow2(l_res->y1, l_pdy) << l_pdy; \ + \ + l_res->pw = (l_res->x0 == l_res->x1) ? 0 : ((l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx);\ + l_res->ph = (l_res->y0 == l_res->y1) ? 0 : ((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy);\ + l_nb_precincts = l_res->pw * l_res->ph; \ + l_nb_precinct_size = l_nb_precincts * sizeof(opj_tcd_precinct_t);\ + if \ + (resno == 0) \ + { \ + tlcbgxstart = l_tl_prc_x_start; \ + tlcbgystart = l_tl_prc_y_start; \ + brcbgxend = l_br_prc_x_end; \ + brcbgyend = l_br_prc_y_end; \ + cbgwidthexpn = l_pdx; \ + cbgheightexpn = l_pdy; \ + l_res->numbands = 1; \ + } \ + else \ + { \ + tlcbgxstart = int_ceildivpow2(l_tl_prc_x_start, 1); \ + tlcbgystart = int_ceildivpow2(l_tl_prc_y_start, 1); \ + brcbgxend = int_ceildivpow2(l_br_prc_x_end, 1); \ + brcbgyend = int_ceildivpow2(l_br_prc_y_end, 1); \ + cbgwidthexpn = l_pdx - 1; \ + cbgheightexpn = l_pdy - 1; \ + l_res->numbands = 3; \ + } \ + \ + cblkwidthexpn = uint_min(l_tccp->cblkw, cbgwidthexpn); \ + cblkheightexpn = uint_min(l_tccp->cblkh, cbgheightexpn); \ + l_band = l_res->bands; \ + for \ + (bandno = 0; bandno < l_res->numbands; ++bandno) \ + { \ + OPJ_INT32 numbps; \ + if \ + (resno == 0) \ + { \ + l_band->bandno = 0 ; \ + l_band->x0 = int_ceildivpow2(l_tilec->x0, l_level_no); \ + l_band->y0 = int_ceildivpow2(l_tilec->y0, l_level_no); \ + l_band->x1 = int_ceildivpow2(l_tilec->x1, l_level_no); \ + l_band->y1 = int_ceildivpow2(l_tilec->y1, l_level_no); \ + } \ + else \ + { \ + l_band->bandno = bandno + 1; \ + /* x0b = 1 if bandno = 1 or 3 */ \ + l_x0b = l_band->bandno&1; \ + /* y0b = 1 if bandno = 2 or 3 */ \ + l_y0b = (l_band->bandno)>>1; \ + /* l_band border (global) */ \ + l_band->x0 = int_ceildivpow2(l_tilec->x0 - (1 << l_level_no) * l_x0b, l_level_no + 1);\ + l_band->y0 = int_ceildivpow2(l_tilec->y0 - (1 << l_level_no) * l_y0b, l_level_no + 1);\ + l_band->x1 = int_ceildivpow2(l_tilec->x1 - (1 << l_level_no) * l_x0b, l_level_no + 1);\ + l_band->y1 = int_ceildivpow2(l_tilec->y1 - (1 << l_level_no) * l_y0b, l_level_no + 1);\ + } \ + /** avoid an if with storing function pointer */ \ + l_gain = (*l_gain_ptr) (l_band->bandno); \ + numbps = l_image_comp->prec + l_gain; \ + l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, (OPJ_INT32) (numbps - l_step_size->expn)))) * FRACTION;\ + l_band->numbps = l_step_size->expn + l_tccp->numgbits - 1; /* WHY -1 ? */\ + if \ + (! l_band->precincts) \ + { \ + l_band->precincts = (opj_tcd_precinct_t *) opj_malloc(/*3 * */ l_nb_precinct_size);\ + if \ + (! l_band->precincts) \ + { \ + return false; \ + } \ + memset(l_band->precincts,0,l_nb_precinct_size); \ + l_band->precincts_data_size = l_nb_precinct_size; \ + } \ + else if \ + (l_band->precincts_data_size < l_nb_precinct_size) \ + { \ + l_band->precincts = (opj_tcd_precinct_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size);\ + if \ + (! l_band->precincts) \ + { \ + return false; \ + } \ + memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size,0,l_nb_precinct_size - l_band->precincts_data_size);\ + l_band->precincts_data_size = l_nb_precinct_size; \ + } \ + l_current_precinct = l_band->precincts; \ + for \ + (precno = 0; precno < l_nb_precincts; ++precno) \ + { \ + OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; \ + OPJ_INT32 cbgxstart = tlcbgxstart + (precno % l_res->pw) * (1 << cbgwidthexpn);\ + OPJ_INT32 cbgystart = tlcbgystart + (precno / l_res->pw) * (1 << cbgheightexpn);\ + OPJ_INT32 cbgxend = cbgxstart + (1 << cbgwidthexpn); \ + OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); \ + /* precinct size (global) */ \ + l_current_precinct->x0 = int_max(cbgxstart, l_band->x0);\ + l_current_precinct->y0 = int_max(cbgystart, l_band->y0);\ + l_current_precinct->x1 = int_min(cbgxend, l_band->x1); \ + l_current_precinct->y1 = int_min(cbgyend, l_band->y1); \ + tlcblkxstart = int_floordivpow2(l_current_precinct->x0, cblkwidthexpn) << cblkwidthexpn;\ + tlcblkystart = int_floordivpow2(l_current_precinct->y0, cblkheightexpn) << cblkheightexpn;\ + brcblkxend = int_ceildivpow2(l_current_precinct->x1, cblkwidthexpn) << cblkwidthexpn;\ + brcblkyend = int_ceildivpow2(l_current_precinct->y1, cblkheightexpn) << cblkheightexpn;\ + l_current_precinct->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;\ + l_current_precinct->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;\ + l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch;\ + l_nb_code_blocks_size = l_nb_code_blocks * sizeof(TYPE);\ + if \ + (! l_current_precinct->cblks.ELEMENT) \ + { \ + l_current_precinct->cblks.ELEMENT = (TYPE*) opj_malloc(l_nb_code_blocks_size);\ + if \ + (! l_current_precinct->cblks.ELEMENT ) \ + { \ + return false; \ + } \ + memset(l_current_precinct->cblks.ELEMENT,0,l_nb_code_blocks_size);\ + l_current_precinct->block_size = l_nb_code_blocks_size;\ + } \ + else if \ + (l_nb_code_blocks_size > l_current_precinct->block_size)\ + { \ + l_current_precinct->cblks.ELEMENT = (TYPE*) \ + opj_realloc(l_current_precinct->cblks.ELEMENT, l_nb_code_blocks_size);\ + if \ + (! l_current_precinct->cblks.ELEMENT ) \ + { \ + return false; \ + } \ + memset(((OPJ_BYTE *) l_current_precinct->cblks.ELEMENT) + l_current_precinct->block_size\ + ,0 \ + ,l_nb_code_blocks_size - l_current_precinct->block_size);\ + l_current_precinct->block_size = l_nb_code_blocks_size;\ + } \ + if \ + (! l_current_precinct->incltree) \ + { \ + l_current_precinct->incltree = tgt_create(l_current_precinct->cw,\ + l_current_precinct->ch);\ + } \ + else \ + { \ + l_current_precinct->incltree = tgt_init(l_current_precinct->incltree,\ + l_current_precinct->cw, \ + l_current_precinct->ch);\ + } \ + if \ + (! l_current_precinct->incltree) \ + { \ + return false; \ + } \ + if \ + (! l_current_precinct->imsbtree) \ + { \ + l_current_precinct->imsbtree = tgt_create( \ + l_current_precinct->cw,\ + l_current_precinct->ch);\ + } \ + else \ + { \ + l_current_precinct->imsbtree = tgt_init( \ + l_current_precinct->imsbtree,\ + l_current_precinct->cw,\ + l_current_precinct->ch);\ + } \ + if \ + (! l_current_precinct->imsbtree) \ + { \ + return false; \ + } \ + l_code_block = l_current_precinct->cblks.ELEMENT; \ + for \ + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) \ + { \ + OPJ_INT32 cblkxstart = tlcblkxstart + (cblkno % l_current_precinct->cw) * (1 << cblkwidthexpn);\ + OPJ_INT32 cblkystart = tlcblkystart + (cblkno / l_current_precinct->cw) * (1 << cblkheightexpn);\ + OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); \ + OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); \ + /* code-block size (global) */ \ + l_code_block->x0 = int_max(cblkxstart, l_current_precinct->x0);\ + l_code_block->y0 = int_max(cblkystart, l_current_precinct->y0);\ + l_code_block->x1 = int_min(cblkxend, l_current_precinct->x1);\ + l_code_block->y1 = int_min(cblkyend, l_current_precinct->y1);\ + if \ + (! FUNCTION_ELEMENT(l_code_block)) \ + { \ + return false; \ + } \ + ++l_code_block; \ + } \ + ++l_current_precinct; \ + } /* precno */ \ + ++l_band; \ + ++l_step_size; \ + } /* bandno */ \ + ++l_res; \ + --l_level_no; \ + } /* resno */ \ + ++l_tccp; \ + ++l_tilec; \ + ++l_image_comp; \ + } /* compno */ \ + return true; \ +} \ + +MACRO_TCD_ALLOCATE(tcd_init_encode_tile,opj_tcd_cblk_enc_t,1.f,enc,tcd_code_block_enc_allocate) +MACRO_TCD_ALLOCATE(tcd_init_decode_tile,opj_tcd_cblk_dec_t,0.5f,dec,tcd_code_block_dec_allocate) + +#undef MACRO_TCD_ALLOCATE + +/** + * Allocates memory for an encoding code block. + */ +bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block) +{ + if + (! p_code_block->data) + { + p_code_block->data = (OPJ_BYTE*) opj_malloc(8192+1); + if + (! p_code_block->data) + { + return false; + } + p_code_block->data+=1; + /* no memset since data */ + p_code_block->layers = (opj_tcd_layer_t*) opj_malloc(100 * sizeof(opj_tcd_layer_t)); + if + (! p_code_block->layers) + { + return false; + } + p_code_block->passes = (opj_tcd_pass_t*) opj_malloc(100 * sizeof(opj_tcd_pass_t)); + if + (! p_code_block->passes) + { + return false; + } + } + memset(p_code_block->layers,0,100 * sizeof(opj_tcd_layer_t)); + memset(p_code_block->passes,0,100 * sizeof(opj_tcd_pass_t)); + return true; +} + +/** + * Allocates memory for a decoding code block. + */ +bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block) +{ + OPJ_UINT32 l_seg_size; + + if + (! p_code_block->data) + { + p_code_block->data = (OPJ_BYTE*) opj_malloc(8192); + if + (! p_code_block->data) + { + return false; + } + l_seg_size = J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t); + p_code_block->segs = (opj_tcd_seg_t *) opj_malloc(l_seg_size); + if + (! p_code_block->segs) + { + return false; + } + memset(p_code_block->segs,0,l_seg_size); + p_code_block->m_current_max_segs = J2K_DEFAULT_NB_SEGS; + } + // TODO + //p_code_block->numsegs = 0; + return true; +} + +/** + * Deallocates the encoding data of the given precinct. + */ +void tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct) +{ + OPJ_UINT32 cblkno , l_nb_code_blocks; + + opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc; + if + (l_code_block) + { + l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_enc_t); + for + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) + { + if + (l_code_block->data) + { + opj_free(l_code_block->data-1); + l_code_block->data = 00; + } + if + (l_code_block->layers) + { + opj_free(l_code_block->layers ); + l_code_block->layers = 00; + } + if + (l_code_block->passes) + { + opj_free(l_code_block->passes ); + l_code_block->passes = 00; + } + ++l_code_block; + } + opj_free(p_precinct->cblks.enc); + p_precinct->cblks.enc = 00; + } +} + +/** + * Deallocates the encoding data of the given precinct. + */ +void tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct) +{ + OPJ_UINT32 cblkno , l_nb_code_blocks; + + opj_tcd_cblk_dec_t * l_code_block = p_precinct->cblks.dec; + if + (l_code_block) + { + l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_t); + for + (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) + { + if + (l_code_block->data) + { + opj_free(l_code_block->data); + l_code_block->data = 00; + } + if + (l_code_block->segs) + { + opj_free(l_code_block->segs ); + l_code_block->segs = 00; + } + ++l_code_block; + } + opj_free(p_precinct->cblks.dec); + p_precinct->cblks.dec = 00; + } +} + +void tcd_free_tile(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno, resno, bandno, precno; + opj_tcd_tile_t *l_tile = 00; + opj_tcd_tilecomp_t *l_tile_comp = 00; + opj_tcd_resolution_t *l_res = 00; + opj_tcd_band_t *l_band = 00; + opj_tcd_precinct_t *l_precinct = 00; + OPJ_UINT32 l_nb_resolutions, l_nb_precincts; + void (* l_tcd_code_block_deallocate) (opj_tcd_precinct_t *) = 00; + + if + (! p_tcd) + { + return; + } + if + (! p_tcd->tcd_image) + { + return; + } + if + (p_tcd->m_is_decoder) + { + l_tcd_code_block_deallocate = tcd_code_block_dec_deallocate; + } + else + { + l_tcd_code_block_deallocate = tcd_code_block_enc_deallocate; + } + + + l_tile = p_tcd->tcd_image->tiles; + if + (! l_tile) + { + return; + } + l_tile_comp = l_tile->comps; + + for + (compno = 0; compno < l_tile->numcomps; ++compno) + { + l_res = l_tile_comp->resolutions; + if + (l_res) + { + l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t); + for + (resno = 0; resno < l_nb_resolutions; ++resno) + { + l_band = l_res->bands; + for + (bandno = 0; bandno < 3; ++bandno) + { + l_precinct = l_band->precincts; + if + (l_precinct) + { + l_nb_precincts = l_band->precincts_data_size / sizeof(opj_tcd_precinct_t); + for + (precno = 0; precno < l_nb_precincts; ++precno) + { + tgt_destroy(l_precinct->incltree); + l_precinct->incltree = 00; + tgt_destroy(l_precinct->imsbtree); + l_precinct->imsbtree = 00; + (*l_tcd_code_block_deallocate) (l_precinct); + ++l_precinct; + } + opj_free(l_band->precincts); + l_band->precincts = 00; + } + ++l_band; + } /* for (resno */ + ++l_res; + } + opj_free(l_tile_comp->resolutions); + l_tile_comp->resolutions = 00; + } + if + (l_tile_comp->data) + { + opj_aligned_free(l_tile_comp->data); + l_tile_comp->data = 00; + } + ++l_tile_comp; + } + opj_free(l_tile->comps); + l_tile->comps = 00; + opj_free(p_tcd->tcd_image->tiles); + p_tcd->tcd_image->tiles = 00; +} + +bool tcd_init( + opj_tcd_t *p_tcd, + opj_image_t * p_image, + opj_cp_t * p_cp + ) +{ + OPJ_UINT32 l_tile_comp_size; + + p_tcd->image = p_image; + p_tcd->cp = p_cp; + p_tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t)); + + if + (! p_tcd->tcd_image->tiles) + { + return false; + } + memset(p_tcd->tcd_image->tiles,0, sizeof(opj_tcd_tile_t)); + + l_tile_comp_size = p_image->numcomps * sizeof(opj_tcd_tilecomp_t); + p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_t *) opj_malloc(l_tile_comp_size); + if + (! p_tcd->tcd_image->tiles->comps ) + { + return false; + } + memset( p_tcd->tcd_image->tiles->comps , 0 , l_tile_comp_size); + p_tcd->tcd_image->tiles->numcomps = p_image->numcomps; + p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos; + return true; +} + +void 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_UINT32 i, j, k; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + for (i = 0; i < tcd_tcp->numlayers; i++) { + for (j = 0; j < tilec->numresolutions; j++) { + for (k = 0; k < 3; k++) { + matrice[i][j][k] = + (OPJ_INT32) (cp->m_specific_param.m_enc.m_matrice[i * tilec->numresolutions * 3 + j * 3 + k] + * (OPJ_FLOAT32) (tcd->image->comps[compno].prec / 16.0)); + } + } + } + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 n; + OPJ_INT32 imsb = tcd->image->comps[compno].prec - cblk->numbps; /* number of bit-plan equal to zero */ + /* Correction of the matrix of coefficient to include the IMSB information */ + if (layno == 0) { + value = matrice[layno][resno][bandno]; + if (imsb >= value) { + value = 0; + } else { + value -= imsb; + } + } else { + value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno]; + if (imsb >= matrice[layno - 1][resno][bandno]) { + value -= (imsb - matrice[layno - 1][resno][bandno]); + if (value < 0) { + value = 0; + } + } + } + + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + + n = cblk->numpassesinlayers; + if (cblk->numpassesinlayers == 0) { + if (value != 0) { + n = 3 * value - 2 + cblk->numpassesinlayers; + } else { + n = cblk->numpassesinlayers; + } + } else { + n = 3 * value + cblk->numpassesinlayers; + } + + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) + continue; + + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + } + if (final) + cblk->numpassesinlayers = n; + } + } + } + } + } +} + +void tcd_rateallocate_fixed(opj_tcd_t *tcd) { + OPJ_UINT32 layno; + for (layno = 0; layno < tcd->tcp->numlayers; layno++) { + tcd_makelayer_fixed(tcd, layno, 1); + } +} + +void 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; + + tcd_tile->distolayer[layno] = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + OPJ_UINT32 n; + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + n = cblk->numpassesinlayers; + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + OPJ_INT32 dr; + OPJ_FLOAT64 dd; + opj_tcd_pass_t *pass = &cblk->passes[passno]; + if (n == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; + } + if (!dr) { + if (dd != 0) + n = passno + 1; + continue; + } + if (dd / dr >= thresh) + n = passno + 1; + } + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) { + layer->disto = 0; + continue; + } + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + layer->disto = cblk->passes[n - 1].distortiondec; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec; + } + + tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */ + + if (final) + cblk->numpassesinlayers = n; + } + } + } + } + } +} + +bool tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, opj_codestream_info_t *cstr_info) { + 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 maxSE = 0; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; + + min = DBL_MAX; + max = 0; + + tcd_tile->numpix = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + tilec->numpix = 0; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + OPJ_INT32 dr; + OPJ_FLOAT64 dd, rdslope; + if (passno == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[passno - 1].rate; + dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; + } + if (dr == 0) { + continue; + } + rdslope = dd / dr; + if (rdslope < min) { + min = rdslope; + } + if (rdslope > max) { + max = rdslope; + } + } /* passno */ + + /* fixed_quality */ + tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); + } /* cbklno */ + } /* precno */ + } /* bandno */ + } /* resno */ + + maxSE += (((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0) + * ((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) -1.0)) + * ((OPJ_FLOAT64)(tilec->numpix)); + } /* compno */ + + /* 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->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(OPJ_FLOAT64)); + } + + for (layno = 0; layno < tcd_tcp->numlayers; layno++) { + OPJ_FLOAT64 lo = min; + OPJ_FLOAT64 hi = max; + bool success = false; + OPJ_UINT32 maxlen = tcd_tcp->rates[layno] ? uint_min(((OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len; + OPJ_FLOAT64 goodthresh = 0; + OPJ_FLOAT64 stable_thresh = 0; + OPJ_UINT32 i; + OPJ_FLOAT64 distotarget; /* fixed_quality */ + + /* 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) + ==> possible to have some lossy layers and the last layer for sure lossless */ + if ( ((cp->m_specific_param.m_enc.m_disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->m_specific_param.m_enc.m_fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) { + opj_t2_t *t2 = t2_create(tcd->image, cp); + OPJ_FLOAT64 thresh = 0; + if + (t2 == 00) + { + return false; + } + + for + (i = 0; i < 32; ++i) + { + OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ + thresh = (lo + hi) / 2; + + tcd_makelayer(tcd, layno, thresh, 0); + + if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ + if(cp->m_specific_param.m_enc.m_cinema){ + if + (! t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) + { + lo = thresh; + continue; + } + else + { + distoachieved = layno == 0 ? + tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + if (distoachieved < distotarget) { + hi=thresh; + stable_thresh = thresh; + continue; + }else{ + lo=thresh; + } + } + }else{ + distoachieved = (layno == 0) ? + tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } + lo = thresh; + } + } else { + if + (! t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) + { + /* TODO: what to do with l ??? seek / tell ??? */ + /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ + lo = thresh; + continue; + } + hi = thresh; + stable_thresh = thresh; + } + } + success = true; + goodthresh = stable_thresh == 0? thresh : stable_thresh; + t2_destroy(t2); + } else { + success = true; + goodthresh = min; + } + + if (!success) { + return false; + } + + if(cstr_info) { /* Threshold for Marcela Index */ + cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; + } + tcd_makelayer(tcd, layno, goodthresh, 1); + + /* fixed_quality */ + cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + } + + return true; +} + +OPJ_UINT32 tcd_get_encoded_tile_size ( + opj_tcd_t *p_tcd + ) +{ + OPJ_UINT32 i,l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for + (i=0;iimage->numcomps;++i) + { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + l_data_size += l_size_comp * (l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0); + ++l_img_comp; + ++l_tilec; + } + return l_data_size; +} + +bool tcd_copy_tile_data ( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_UINT32 p_src_length + ) +{ + OPJ_UINT32 i,j,l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_UINT32 l_nb_elem; + + l_data_size = tcd_get_encoded_tile_size(p_tcd); + if + (l_data_size != p_src_length) + { + return false; + } + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for + (i=0;iimage->numcomps;++i) + { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_nb_elem = (l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0); + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + switch + (l_size_comp) + { + case 1: + { + OPJ_CHAR * l_src_ptr = (OPJ_CHAR *) p_src; + OPJ_INT32 * l_dest_ptr = l_tilec->data; + if + (l_img_comp->sgnd) + { + for + (j=0;jdata; + OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src; + if + (l_img_comp->sgnd) + { + for + (j=0;jdata; + for + (j=0;j p_dest_length) + { + return false; + } + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for + (i=0;iimage->numcomps;++i) + { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_res = l_tilec->resolutions + l_img_comp->resno_decoded; + l_width = (l_res->x1 - l_res->x0); + l_height = (l_res->y1 - l_res->y0); + l_stride = (l_tilec->x1 - l_tilec->x0) - l_width; + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + switch + (l_size_comp) + { + case 1: + { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest; + const OPJ_INT32 * l_src_ptr = l_tilec->data; + if + (l_img_comp->sgnd) + { + for + (j=0;jdata; + OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; + if + (l_img_comp->sgnd) + { + for + (j=0;jdata; + for + (j=0;jtcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for + (i=0;iimage->numcomps;++i) + { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + if + (l_remaining) + { + ++l_size_comp; + } + if + (l_size_comp == 3) + { + l_size_comp = 4; + } + l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; + l_data_size += l_size_comp * (l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0); + ++l_img_comp; + ++l_tile_comp; + } + return l_data_size; +} + +bool tcd_dc_level_shift_encode ( + opj_tcd_t *p_tcd + ) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcp_t * l_tcp = 00; + opj_tcd_tile_t * l_tile; + OPJ_UINT32 l_nb_elem,i; + OPJ_INT32 * l_current_ptr; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tcp = p_tcd->tcp; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + for + (compno = 0; compno < l_tile->numcomps; compno++) + { + l_current_ptr = l_tile_comp->data; + l_nb_elem = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0); + if + (l_tccp->qmfbid == 1) + { + for + (i = 0; i < l_nb_elem; ++i) + { + *l_current_ptr -= l_tccp->m_dc_level_shift ; + ++l_current_ptr; + } + } + else + { + for + (i = 0; i < l_nb_elem; ++i) + { + *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) << 11 ; + ++l_current_ptr; + } + } + ++l_img_comp; + ++l_tccp; + ++l_tile_comp; + } + return true; +} + +bool tcd_mct_encode ( + opj_tcd_t *p_tcd + ) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + OPJ_UINT32 samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0); + OPJ_UINT32 i; + OPJ_BYTE ** l_data = 00; + opj_tcp_t * l_tcp = p_tcd->tcp; + if + (!p_tcd->tcp->mct) + { + return true; + } + + if + (p_tcd->tcp->mct == 2) + { + if + (! p_tcd->tcp->m_mct_coding_matrix) + { + return true; + } + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); + if + (! l_data) + { + return false; + } + for + (i=0;inumcomps;++i) + { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + ++l_tile_comp; + } + if + (! mct_encode_custom(// MCT data + (OPJ_BYTE*) p_tcd->tcp->m_mct_coding_matrix, + // size of components + samples, + // components + l_data, + // nb of components (i.e. size of pData) + l_tile->numcomps, + // tells if the data is signed + p_tcd->image->comps->sgnd) + ) + { + opj_free(l_data); + return false; + } + opj_free(l_data); + } + else if (l_tcp->tccps->qmfbid == 0) + { + mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); + } + else + { + mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); + } + return true; +} + +bool tcd_dwt_encode ( + opj_tcd_t *p_tcd + ) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + OPJ_UINT32 compno; + + + for + (compno = 0; compno < l_tile->numcomps; ++compno) + { + if + (l_tccp->qmfbid == 1) + { + if + (! dwt_encode(l_tile_comp)) + { + return false; + } + } + else if + (l_tccp->qmfbid == 0) + { + if + (! dwt_encode_real(l_tile_comp)) + { + return false; + } + } + ++l_tile_comp; + ++l_tccp; + } + return true; +} + +bool tcd_t1_encode ( + opj_tcd_t *p_tcd + ) +{ + opj_t1_t * l_t1; + const OPJ_FLOAT64 * l_mct_norms; + opj_tcp_t * l_tcp = p_tcd->tcp; + + l_t1 = t1_create(); + if + (l_t1 == 00) + { + return false; + } + if + (l_tcp->mct == 1) + { + // irreversible encoding + if + (l_tcp->tccps->qmfbid == 0) + { + l_mct_norms = get_mct_norms_real(); + } + else + { + l_mct_norms = get_mct_norms(); + } + } + else + { + l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms); + } + + if + (! t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) + { + t1_destroy(l_t1); + return false; + } + t1_destroy(l_t1); + return true; +} + +bool tcd_t2_encode ( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info + ) +{ + opj_t2_t * l_t2; + + l_t2 = t2_create(p_tcd->image, p_tcd->cp); + if + (l_t2 == 00) + { + return false; + } + + if + (! t2_encode_packets( + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_tcd->tcp->numlayers, + p_dest_data, + p_data_written, + p_max_dest_size, + p_cstr_info, + p_tcd->tp_num, + p_tcd->tp_pos, + p_tcd->cur_pino, + FINAL_PASS)) + { + t2_destroy(l_t2); + return false; + } + t2_destroy(l_t2); + + /*---------------CLEAN-------------------*/ + return true; +} + +bool tcd_rate_allocate_encode( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info + ) +{ + opj_cp_t * l_cp = p_tcd->cp; + OPJ_UINT32 l_nb_written = 0; + + if + (p_cstr_info) + { + 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 + (! tcd_rateallocate(p_tcd, p_dest_data,&l_nb_written, p_max_dest_size, p_cstr_info)) + { + return false; + } + } + else + { + /* Fixed layer allocation */ + tcd_rateallocate_fixed(p_tcd); + } + return true; +} + +bool tcd_t2_decode ( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_src_size, + opj_codestream_info_t *p_cstr_info + ) +{ + opj_t2_t * l_t2; + + l_t2 = t2_create(p_tcd->image, p_tcd->cp); + if + (l_t2 == 00) + { + return false; + } + + if + (! t2_decode_packets( + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_src_data, + p_data_read, + p_max_src_size, + p_cstr_info)) + { + t2_destroy(l_t2); + return false; + } + t2_destroy(l_t2); + + /*---------------CLEAN-------------------*/ + return true; +} + +bool tcd_t1_decode ( + opj_tcd_t *p_tcd + ) +{ + OPJ_UINT32 compno; + opj_t1_t * l_t1; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + + + l_t1 = t1_create(); + if + (l_t1 == 00) + { + return false; + } + for + (compno = 0; compno < l_tile->numcomps; ++compno) + { + /* The +3 is headroom required by the vectorized DWT */ + t1_decode_cblks(l_t1, l_tile_comp, l_tccp); + ++l_tile_comp; + ++l_tccp; + } + t1_destroy(l_t1); + return true; +} + +bool tcd_dwt_decode ( + opj_tcd_t *p_tcd + ) +{ + OPJ_UINT32 compno; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + opj_image_comp_t * l_img_comp = p_tcd->image->comps; + + for + (compno = 0; compno < l_tile->numcomps; compno++) + { + /* + if (tcd->cp->reduce != 0) { + tcd->image->comps[compno].resno_decoded = + tile->comps[compno].numresolutions - tcd->cp->reduce - 1; + if (tcd->image->comps[compno].resno_decoded < 0) + { + return false; + } + } + numres2decode = tcd->image->comps[compno].resno_decoded + 1; + if(numres2decode > 0){ + */ + if + (l_tccp->qmfbid == 1) + { + if + (! dwt_decode(l_tile_comp, l_img_comp->resno_decoded+1)) + { + return false; + } + } + else + { + if + (! dwt_decode_real(l_tile_comp, l_img_comp->resno_decoded+1)) + { + return false; + } + } + ++l_tile_comp; + ++l_img_comp; + ++l_tccp; + } + return true; +} +bool tcd_mct_decode ( + opj_tcd_t *p_tcd + ) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcp_t * l_tcp = p_tcd->tcp; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + OPJ_UINT32 l_samples,i; + + if + (! l_tcp->mct) + { + return true; + } + l_samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0); + if + (l_tcp->mct == 2) + { + OPJ_BYTE ** l_data; + if + (! l_tcp->m_mct_decoding_matrix) + { + return true; + } + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); + if + (! l_data) + { + return false; + } + for + (i=0;inumcomps;++i) + { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + ++l_tile_comp; + } + if + (! mct_decode_custom( // MCT data + (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, + // size of components + l_samples, + // components + l_data, + // nb of components (i.e. size of pData) + l_tile->numcomps, + // tells if the data is signed + p_tcd->image->comps->sgnd)) + { + opj_free(l_data); + return false; + } + opj_free(l_data); + } + else + { + if + (l_tcp->tccps->qmfbid == 1) + { + mct_decode( + l_tile->comps[0].data, + l_tile->comps[1].data, + l_tile->comps[2].data, + l_samples); + } + else + { + mct_decode_real( + (float*)l_tile->comps[0].data, + (float*)l_tile->comps[1].data, + (float*)l_tile->comps[2].data, + l_samples); + } + } + return true; +} + +bool tcd_dc_level_shift_decode ( + opj_tcd_t *p_tcd + ) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_resolution_t* l_res = 00; + opj_tcp_t * l_tcp = 00; + opj_tcd_tile_t * l_tile; + OPJ_UINT32 l_width,l_height,i,j; + OPJ_INT32 * l_current_ptr; + OPJ_INT32 l_min, l_max; + OPJ_UINT32 l_stride; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tcp = p_tcd->tcp; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + + for + (compno = 0; compno < l_tile->numcomps; compno++) + { + l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; + l_width = (l_res->x1 - l_res->x0); + l_height = (l_res->y1 - l_res->y0); + l_stride = (l_tile_comp->x1 - l_tile_comp->x0) - l_width; + if + (l_img_comp->sgnd) + { + l_min = -(1 << (l_img_comp->prec - 1)); + l_max = (1 << (l_img_comp->prec - 1)) - 1; + } + else + { + l_min = 0; + l_max = (1 << l_img_comp->prec) - 1; + } + l_current_ptr = l_tile_comp->data; + if + (l_tccp->qmfbid == 1) + { + for + (j=0;jm_dc_level_shift, l_min, l_max); + ++l_current_ptr; + } + l_current_ptr += l_stride; + } + } + else + { + for + (j=0;jm_dc_level_shift, l_min, l_max); ; + ++l_current_ptr; + } + l_current_ptr += l_stride; + } + } + ++l_img_comp; + ++l_tccp; + ++l_tile_comp; + } + return true; +} + +bool tcd_encode_tile( + opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_length, + opj_codestream_info_t *p_cstr_info) +{ + + if + (p_tcd->cur_tp_num == 0) + { + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &p_tcd->cp->tcps[p_tile_no]; + /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ + if(p_cstr_info) + { + OPJ_UINT32 l_num_packs = 0; + OPJ_UINT32 i; + opj_tcd_tilecomp_t *l_tilec_idx = &p_tcd->tcd_image->tiles->comps[0]; /* based on component 0 */ + opj_tccp_t *l_tccp = p_tcd->tcp->tccps; /* based on component 0 */ + for (i = 0; i < l_tilec_idx->numresolutions; i++) { + opj_tcd_resolution_t *l_res_idx = &l_tilec_idx->resolutions[i]; + + p_cstr_info->tile[p_tile_no].pw[i] = l_res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[i] = l_res_idx->ph; + + l_num_packs += l_res_idx->pw * l_res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[i] = l_tccp->prcw[i]; + p_cstr_info->tile[p_tile_no].pdy[i] = l_tccp->prch[i]; + } + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(p_cstr_info->numcomps * p_cstr_info->numlayers * l_num_packs, sizeof(opj_packet_info_t)); + } + /* << INDEX */ + _ProfStart(PGROUP_DC_SHIFT); + /*---------------TILE-------------------*/ + if + (! tcd_dc_level_shift_encode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_DC_SHIFT); + + _ProfStart(PGROUP_MCT); + if + (! tcd_mct_encode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_MCT); + + _ProfStart(PGROUP_DWT); + if + (! tcd_dwt_encode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_DWT); + + _ProfStart(PGROUP_T1); + if + (! tcd_t1_encode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_T1); + + _ProfStart(PGROUP_RATE); + if + (! tcd_rate_allocate_encode(p_tcd,p_dest,p_max_length,p_cstr_info)) + { + return false; + } + _ProfStop(PGROUP_RATE); + + } + /*--------------TIER2------------------*/ + + /* INDEX */ + if + (p_cstr_info) + { + p_cstr_info->index_write = 1; + } + _ProfStart(PGROUP_T2); + if + (! tcd_t2_encode(p_tcd,p_dest,p_data_written,p_max_length,p_cstr_info)) + { + return false; + } + _ProfStop(PGROUP_T2); + /*---------------CLEAN-------------------*/ + return true; +} + +bool tcd_decode_tile( + opj_tcd_t *p_tcd, + OPJ_BYTE *p_src, + OPJ_UINT32 p_max_length, + OPJ_UINT32 p_tile_no, + opj_codestream_info_t *p_cstr_info) +{ + OPJ_UINT32 l_data_read; + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); + + /* INDEX >> */ + if(p_cstr_info) { + OPJ_UINT32 resno, compno, numprec = 0; + for (compno = 0; compno < (OPJ_UINT32) p_cstr_info->numcomps; compno++) { + opj_tcp_t *tcp = &p_tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec_idx = &p_tcd->tcd_image->tiles->comps[compno]; + for (resno = 0; resno < tilec_idx->numresolutions; resno++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno]; + p_cstr_info->tile[p_tile_no].pw[resno] = res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[resno] = res_idx->ph; + numprec += res_idx->pw * res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[resno] = tccp->prcw[resno]; + p_cstr_info->tile[p_tile_no].pdy[resno] = tccp->prch[resno]; + } + } + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t *) opj_malloc(p_cstr_info->numlayers * numprec * sizeof(opj_packet_info_t)); + p_cstr_info->packno = 0; + } + /* << INDEX */ + + /*--------------TIER2------------------*/ + _ProfStart(PGROUP_T2); + l_data_read = 0; + if + (! tcd_t2_decode(p_tcd,p_src,&l_data_read,p_max_length,p_cstr_info)) + { + return false; + } + _ProfStop(PGROUP_T2); + + /*------------------TIER1-----------------*/ + + _ProfStart(PGROUP_T1); + if + (! tcd_t1_decode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_T1); + + /*----------------DWT---------------------*/ + + _ProfStart(PGROUP_DWT); + if + (! tcd_dwt_decode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_DWT); + + /*----------------MCT-------------------*/ + _ProfStart(PGROUP_MCT); + if + (! tcd_mct_decode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_MCT); + + _ProfStart(PGROUP_DC_SHIFT); + if + (! tcd_dc_level_shift_decode(p_tcd)) + { + return false; + } + _ProfStop(PGROUP_DC_SHIFT); + + + /*---------------TILE-------------------*/ + return true; +} diff --git a/v2/libopenjpeg/tcd.h b/v2/libopenjpeg/tcd.h new file mode 100755 index 00000000..95d49d47 --- /dev/null +++ b/v2/libopenjpeg/tcd.h @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __TCD_H +#define __TCD_H +/** +@file tcd.h +@brief Implementation of a tile coder/decoder (TCD) + +The functions in TCD.C have for goal to encode or decode each tile independently from +each other. The functions in TCD.C are used by some function in J2K.C. +*/ +#include "openjpeg.h" +/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ +/*@{*/ +struct opj_common_struct; +struct opj_codestream_info; +struct opj_image; +struct opj_tcp; +struct opj_cp; +struct opj_tgt_tree; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_seg { + OPJ_BYTE ** data; + OPJ_UINT32 dataindex; + OPJ_UINT32 numpasses; + OPJ_UINT32 real_num_passes; + OPJ_UINT32 len; + OPJ_UINT32 maxpasses; + OPJ_UINT32 numnewpasses; + OPJ_UINT32 newlen; +} opj_tcd_seg_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_pass { + OPJ_UINT32 rate; + OPJ_FLOAT64 distortiondec; + OPJ_UINT32 len; + OPJ_UINT32 term : 1; +} opj_tcd_pass_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_layer { + OPJ_UINT32 numpasses; /* Number of passes in the layer */ + OPJ_UINT32 len; /* len of information */ + OPJ_FLOAT64 disto; /* add for index (Cfr. Marcela) */ + OPJ_BYTE *data; /* data */ +} opj_tcd_layer_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_cblk_enc { + OPJ_BYTE* data; /* Data */ + opj_tcd_layer_t* layers; /* layer information */ + opj_tcd_pass_t* passes; /* information about the passes */ + OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 numbps; + OPJ_UINT32 numlenbits; + OPJ_UINT32 numpasses; /* number of pass already done for the code-blocks */ + OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ + OPJ_UINT32 totalpasses; /* total number of passes */ +} opj_tcd_cblk_enc_t; + +typedef struct opj_tcd_cblk_dec { + OPJ_BYTE * data; /* Data */ + opj_tcd_seg_t* segs; /* segments informations */ + OPJ_INT32 x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 numbps; + OPJ_UINT32 numlenbits; + OPJ_UINT32 len; /* length */ + OPJ_UINT32 numnewpasses; /* number of pass added to the code-blocks */ + OPJ_UINT32 numsegs; /* number of segments */ + OPJ_UINT32 real_num_segs; + OPJ_UINT32 m_current_max_segs; +} opj_tcd_cblk_dec_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_precinct { + OPJ_INT32 x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 cw, ch; /* number of precinct in width and heigth */ + union{ /* code-blocks informations */ + opj_tcd_cblk_enc_t* enc; + opj_tcd_cblk_dec_t* dec; + } cblks; + OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */ + struct opj_tgt_tree *incltree; /* inclusion tree */ + struct opj_tgt_tree *imsbtree; /* IMSB tree */ +} opj_tcd_precinct_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_band { + OPJ_INT32 x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 bandno; + opj_tcd_precinct_t *precincts; /* precinct information */ + OPJ_UINT32 precincts_data_size; /* size of data taken by precincts */ + OPJ_INT32 numbps; + OPJ_FLOAT32 stepsize; +} opj_tcd_band_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_resolution { + OPJ_INT32 x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 pw, ph; + OPJ_UINT32 numbands; /* number sub-band for the resolution level */ + opj_tcd_band_t bands[3]; /* subband information */ +} opj_tcd_resolution_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_tilecomp +{ + OPJ_INT32 x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 numresolutions; /* number of resolutions level */ + OPJ_UINT32 minimum_num_resolutions; /* number of resolutions level to decode (at max)*/ + opj_tcd_resolution_t *resolutions; /* resolutions information */ + OPJ_UINT32 resolutions_size; /* size of data for resolutions (in bytes) */ + OPJ_INT32 *data; /* data of the component */ + OPJ_UINT32 data_size; /* size of the data of the component */ + OPJ_INT32 numpix; /* add fixed_quality */ +} opj_tcd_tilecomp_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_tile { + OPJ_INT32 x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (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 */ + /** packet number */ + OPJ_UINT32 packno; +} opj_tcd_tile_t; + +/** +FIXME: documentation +*/ +typedef struct opj_tcd_image +{ + opj_tcd_tile_t *tiles; /* Tiles information */ +} +opj_tcd_image_t; + +/** +Tile coder/decoder +*/ +typedef struct opj_tcd +{ + /** Position of the tilepart flag in Progression order*/ + OPJ_INT32 tp_pos; + /** Tile part number*/ + OPJ_UINT32 tp_num; + /** Current tile part number*/ + OPJ_UINT32 cur_tp_num; + /** Total number of tileparts of the current tile*/ + OPJ_UINT32 cur_totnum_tp; + /** Current Packet iterator number */ + OPJ_UINT32 cur_pino; + /** info on each image tile */ + struct opj_tcd_image *tcd_image; + /** image */ + struct opj_image *image; + /** coding parameters */ + struct opj_cp *cp; + /** coding/decoding parameters common to all tiles */ + struct opj_tcp *tcp; + /** current encoded/decoded tile */ + OPJ_UINT32 tcd_tileno; + /** tell if the tcd is a decoder. */ + OPJ_UINT32 m_is_decoder : 1; +} opj_tcd_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Dump the content of a tcd structure +*/ +//void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img); +/** +Create a new TCD handle +@param cinfo Codec context info +@return Returns a new TCD handle if successful returns NULL otherwise +*/ +opj_tcd_t* tcd_create(bool p_is_decoder); + +/** +Destroy a previously created TCD handle +@param tcd TCD handle to destroy +*/ +void tcd_destroy(opj_tcd_t *tcd); + + + + +/** + * Initialize the tile coder and may reuse some meory. + * @param p_tcd TCD handle. + * @param p_image raw image. + * @param p_cp coding parameters. + * @param p_tile_no current tile index to encode. + * + * @return true if the encoding values could be set (false otherwise). +*/ +bool tcd_init( + opj_tcd_t *p_tcd, + struct opj_image * p_image, + struct opj_cp * p_cp + ); + + +/** + * Allocates memory for decoding a specific tile. + * + * @param p_tcd the tile decoder. + * @param p_image the image to decode. + * @param p_cp the decoding parameters. + * @param p_tile_no the index of the tile received in sequence. This not necesseraly lead to the + * tile at index p_tile_no. + * @param p_cstr_info codestream info (if any). + * + * @return true if the remaining data is sufficient.s + */ +bool tcd_init_decode_tile( + opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no + ); +/** + * Initialize the tile coder and may reuse some meory. + * @param p_tcd TCD handle. + * @param p_image raw image. + * @param p_cp coding parameters. + * @param p_tile_no current tile index to encode. + * + * @return true if the encoding values could be set (false otherwise). +*/ +bool tcd_init_encode_tile + ( + opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no + ); + +void tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final); +void tcd_rateallocate_fixed(opj_tcd_t *tcd); +void tcd_makelayer(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_FLOAT64 thresh, OPJ_UINT32 final); +bool tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, struct opj_codestream_info *cstr_info); +/** + * Encodes a tile from the raw image into the given buffer. + * @param p_tcd Tile Coder handle + * @param p_tile_no Index of the tile to encode. + * @param p_dest Destination buffer + * @param p_data_written pointer to an int that is incremented by the number of bytes really written on p_dest + * @param p_len Maximum length of the destination buffer + * @param p_cstr_info Codestream information structure + * @return true if the coding is successfull. +*/ +bool tcd_encode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BYTE *p_dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 p_len, struct opj_codestream_info *p_cstr_info); + +/** +Decode a tile from a buffer into a raw image +@param tcd TCD handle +@param src Source buffer +@param len Length of source buffer +@param tileno Number that identifies one of the tiles to be decoded +*/ +bool tcd_decode_tile(opj_tcd_t *tcd, OPJ_BYTE *src, OPJ_UINT32 len, OPJ_UINT32 tileno, struct opj_codestream_info *cstr_info); + +/** + * Copies tile data from the given memory block onto the system. + */ +bool tcd_copy_tile_data ( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_UINT32 p_src_length + ); +/** + * Copies tile data from the system onto the given memory block. + */ +bool tcd_update_tile_data ( + opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest, + OPJ_UINT32 p_dest_length + ); +/** + * Gets the maximum tile size that will be taken by the tile once decoded. + */ +OPJ_UINT32 tcd_get_decoded_tile_size ( + opj_tcd_t *p_tcd + ); + +OPJ_UINT32 tcd_get_encoded_tile_size ( + opj_tcd_t *p_tcd + ); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __TCD_H */ diff --git a/v2/libopenjpeg/tgt.c b/v2/libopenjpeg/tgt.c new file mode 100755 index 00000000..5eb24893 --- /dev/null +++ b/v2/libopenjpeg/tgt.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tgt.h" +#include "bio.h" +#include "opj_malloc.h" + +/* +========================================================== + Tag-tree coder interface +========================================================== +*/ + +opj_tgt_tree_t *tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv) { + OPJ_INT32 nplh[32]; + OPJ_INT32 nplv[32]; + opj_tgt_node_t *node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + opj_tgt_tree_t *tree = 00; + OPJ_UINT32 i; + OPJ_INT32 j,k; + OPJ_UINT32 numlvls; + OPJ_UINT32 n; + + tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t)); + if(!tree) return 00; + memset(tree,0,sizeof(opj_tgt_tree_t)); + + tree->numleafsh = numleafsh; + tree->numleafsv = numleafsv; + + numlvls = 0; + nplh[0] = numleafsh; + nplv[0] = numleafsv; + tree->numnodes = 0; + do { + n = nplh[numlvls] * nplv[numlvls]; + nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; + nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; + tree->numnodes += n; + ++numlvls; + } while (n > 1); + + /* ADD */ + if (tree->numnodes == 0) { + opj_free(tree); + return 00; + } + + tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t)); + if(!tree->nodes) { + opj_free(tree); + return 00; + } + memset(tree->nodes,0,tree->numnodes * sizeof(opj_tgt_node_t)); + tree->nodes_size = tree->numnodes * sizeof(opj_tgt_node_t); + + node = tree->nodes; + l_parent_node = &tree->nodes[tree->numleafsh * tree->numleafsv]; + l_parent_node0 = l_parent_node; + + for (i = 0; i < numlvls - 1; ++i) { + for (j = 0; j < nplv[i]; ++j) { + k = nplh[i]; + while (--k >= 0) { + node->parent = l_parent_node; + ++node; + if (--k >= 0) { + node->parent = l_parent_node; + ++node; + } + ++l_parent_node; + } + if ((j & 1) || j == nplv[i] - 1) { + l_parent_node0 = l_parent_node; + } else { + l_parent_node = l_parent_node0; + l_parent_node0 += nplh[i]; + } + } + } + node->parent = 0; + tgt_reset(tree); + return tree; +} +/** + * Reinitialises a tag-tree from an exixting one. + * + * @param p_tree the tree to reinitialize. + * @param p_num_leafs_h the width of the array of leafs of the tree + * @param p_num_leafs_v the height of the array of leafs of the tree + * @return a new tag-tree if successful, NULL otherwise +*/ +opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v) +{ + OPJ_INT32 l_nplh[32]; + OPJ_INT32 l_nplv[32]; + opj_tgt_node_t *l_node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + OPJ_UINT32 i; + OPJ_INT32 j,k; + OPJ_UINT32 l_num_levels; + OPJ_UINT32 n; + OPJ_UINT32 l_node_size; + + if + (! p_tree) + { + return 00; + } + if + ((p_tree->numleafsh != p_num_leafs_h) || (p_tree->numleafsv != p_num_leafs_v)) + { + p_tree->numleafsh = p_num_leafs_h; + p_tree->numleafsv = p_num_leafs_v; + + l_num_levels = 0; + l_nplh[0] = p_num_leafs_h; + l_nplv[0] = p_num_leafs_v; + p_tree->numnodes = 0; + do + { + n = l_nplh[l_num_levels] * l_nplv[l_num_levels]; + l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2; + l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2; + p_tree->numnodes += n; + ++l_num_levels; + } + while (n > 1); + + /* ADD */ + if + (p_tree->numnodes == 0) + { + tgt_destroy(p_tree); + return 00; + } + l_node_size = p_tree->numnodes * sizeof(opj_tgt_node_t); + if + (l_node_size > p_tree->nodes_size) + { + p_tree->nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size); + if + (! p_tree->nodes) + { + tgt_destroy(p_tree); + return 00; + } + memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0 , l_node_size - p_tree->nodes_size); + p_tree->nodes_size = l_node_size; + } + l_node = p_tree->nodes; + l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv]; + l_parent_node0 = l_parent_node; + + for + (i = 0; i < l_num_levels - 1; ++i) + { + for + (j = 0; j < l_nplv[i]; ++j) + { + k = l_nplh[i]; + while + (--k >= 0) + { + l_node->parent = l_parent_node; + ++l_node; + if (--k >= 0) + { + l_node->parent = l_parent_node; + ++l_node; + } + ++l_parent_node; + } + if ((j & 1) || j == l_nplv[i] - 1) + { + l_parent_node0 = l_parent_node; + } + else + { + l_parent_node = l_parent_node0; + l_parent_node0 += l_nplh[i]; + } + } + } + l_node->parent = 0; + } + tgt_reset(p_tree); + + return p_tree; +} + +void tgt_destroy(opj_tgt_tree_t *p_tree) +{ + if + (! p_tree) + { + return; + } + if + (p_tree->nodes) + { + opj_free(p_tree->nodes); + p_tree->nodes = 00; + } + opj_free(p_tree); +} + +void tgt_reset(opj_tgt_tree_t *p_tree) { + OPJ_UINT32 i; + opj_tgt_node_t * l_current_node = 00;; + + if + (! p_tree) + { + return; + } + l_current_node = p_tree->nodes; + for + (i = 0; i < p_tree->numnodes; ++i) + { + l_current_node->value = 999; + l_current_node->low = 0; + l_current_node->known = 0; + ++l_current_node; + } +} + +void tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value) { + opj_tgt_node_t *node; + node = &tree->nodes[leafno]; + while (node && node->value > value) { + node->value = value; + node = node->parent; + } +} + +void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + + while (low < threshold) { + if (low >= node->value) { + if (!node->known) { + bio_write(bio, 1, 1); + node->known = 1; + } + break; + } + bio_write(bio, 0, 1); + ++low; + } + + node->low = low; + if (stkptr == stk) + break; + node = *--stkptr; + } +} + +OPJ_UINT32 tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + while (low < threshold && low < node->value) { + if (bio_read(bio, 1)) { + node->value = low; + } else { + ++low; + } + } + node->low = low; + if (stkptr == stk) { + break; + } + node = *--stkptr; + } + + return (node->value < threshold) ? 1 : 0; +} diff --git a/v2/libopenjpeg/tgt.h b/v2/libopenjpeg/tgt.h new file mode 100755 index 00000000..212060c0 --- /dev/null +++ b/v2/libopenjpeg/tgt.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TGT_H +#define __TGT_H +/** +@file tgt.h +@brief Implementation of a tag-tree coder (TGT) + +The functions in TGT.C have for goal to realize a tag-tree coder. The functions in TGT.C +are used by some function in T2.C. +*/ +#include "openjpeg.h" +/** @defgroup TGT TGT - Implementation of a tag-tree coder */ +/*@{*/ +struct opj_bio; + +/** +Tag node +*/ +typedef struct opj_tgt_node +{ + struct opj_tgt_node *parent; + OPJ_INT32 value; + OPJ_INT32 low; + OPJ_UINT32 known : 1; +} opj_tgt_node_t; + +/** +Tag tree +*/ +typedef struct opj_tgt_tree +{ + OPJ_UINT32 numleafsh; + OPJ_UINT32 numleafsv; + OPJ_UINT32 numnodes; + opj_tgt_node_t *nodes; + OPJ_UINT32 nodes_size; /* maximum size taken by nodes */ +} opj_tgt_tree_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a tag-tree +@param numleafsh Width of the array of leafs of the tree +@param numleafsv Height of the array of leafs of the tree +@return Returns a new tag-tree if successful, returns NULL otherwise +*/ +opj_tgt_tree_t *tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv); + +/** + * Reinitialises a tag-tree from an exixting one. + * + * @param p_tree the tree to reinitialize. + * @param p_num_leafs_h the width of the array of leafs of the tree + * @param p_num_leafs_v the height of the array of leafs of the tree + * @return a new tag-tree if successful, NULL otherwise +*/ +opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v); + +/** +Destroy a tag-tree, liberating memory +@param tree Tag-tree to destroy +*/ +void tgt_destroy(opj_tgt_tree_t *tree); +/** +Reset a tag-tree (set all leaves to 0) +@param tree Tag-tree to reset +*/ +void tgt_reset(opj_tgt_tree_t *tree); +/** +Set the value of a leaf of a tag-tree +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to modify +@param value New value of the leaf +*/ +void tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value); +/** +Encode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to encode +@param threshold Threshold to use when encoding value of the leaf +*/ +void tgt_encode(struct opj_bio *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold); +/** +Decode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to decode +@param leafno Number that identifies the leaf to decode +@param threshold Threshold to use when decoding value of the leaf +@return Returns 1 if the node's value < threshold, returns 0 otherwise +*/ +OPJ_UINT32 tgt_decode(struct opj_bio *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __TGT_H */ diff --git a/v2/libs/FreeImage/FreeImage.h b/v2/libs/FreeImage/FreeImage.h new file mode 100755 index 00000000..7125acc4 --- /dev/null +++ b/v2/libs/FreeImage/FreeImage.h @@ -0,0 +1,1046 @@ +// ========================================================== +// FreeImage 3 +// +// Design and implementation by +// - Floris van den Berg (flvdberg@wxs.nl) +// - Hervé Drolon (drolon@infonie.fr) +// +// Contributors: +// - Adam Gates (radad@xoasis.com) +// - Alex Kwak +// - Alexander Dymerets (sashad@te.net.ua) +// - Detlev Vendt (detlev.vendt@brillit.de) +// - Jan L. Nauta (jln@magentammt.com) +// - Jani Kajala (janik@remedy.fi) +// - Juergen Riecker (j.riecker@gmx.de) +// - Karl-Heinz Bussian (khbussian@moss.de) +// - Laurent Rocher (rocherl@club-internet.fr) +// - Luca Piergentili (l.pierge@terra.es) +// - Machiel ten Brinke (brinkem@uni-one.nl) +// - Markus Loibl (markus.loibl@epost.de) +// - Martin Weber (martweb@gmx.net) +// - Matthias Wandel (mwandel@rim.net) +// - Michal Novotny (michal@etc.cz) +// - Petr Pytelka (pyta@lightcomp.com) +// - Riley McNiff (rmcniff@marexgroup.com) +// - Ryan Rubley (ryan@lostreality.org) +// - Volker Gärtner (volkerg@gmx.at) +// +// This file is part of FreeImage 3 +// +// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE +// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED +// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT +// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY +// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL +// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER +// THIS DISCLAIMER. +// +// Use at your own risk! +// ========================================================== + +#ifndef FREEIMAGE_H +#define FREEIMAGE_H + +// Version information ------------------------------------------------------ + +#define FREEIMAGE_MAJOR_VERSION 3 +#define FREEIMAGE_MINOR_VERSION 10 +#define FREEIMAGE_RELEASE_SERIAL 0 + +// Compiler options --------------------------------------------------------- + +#include // needed for UNICODE functions + +#if defined(FREEIMAGE_LIB) + #define DLL_API + #define DLL_CALLCONV +#else + #if defined(_WIN32) || defined(__WIN32__) + #define DLL_CALLCONV __stdcall + // The following ifdef block is the standard way of creating macros which make exporting + // from a DLL simpler. All files within this DLL are compiled with the FREEIMAGE_EXPORTS + // symbol defined on the command line. this symbol should not be defined on any project + // that uses this DLL. This way any other project whose source files include this file see + // DLL_API functions as being imported from a DLL, wheras this DLL sees symbols + // defined with this macro as being exported. + #ifdef FREEIMAGE_EXPORTS + #define DLL_API __declspec(dllexport) + #else + #define DLL_API __declspec(dllimport) + #endif // FREEIMAGE_EXPORTS + #else + // try the gcc visibility support (see http://gcc.gnu.org/wiki/Visibility) + #if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) + #ifndef GCC_HASCLASSVISIBILITY + #define GCC_HASCLASSVISIBILITY + #endif + #endif // __GNUC__ + #define DLL_CALLCONV + #if defined(GCC_HASCLASSVISIBILITY) + #define DLL_API __attribute__ ((visibility("default"))) + #else + #define DLL_API + #endif + #endif // WIN32 / !WIN32 +#endif // FREEIMAGE_LIB + +// Some versions of gcc may have BYTE_ORDER or __BYTE_ORDER defined +// If your big endian system isn't being detected, add an OS specific check +#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \ + defined(__BIG_ENDIAN__) +#define FREEIMAGE_BIGENDIAN +#endif // BYTE_ORDER + +// This really only affects 24 and 32 bit formats, the rest are always RGB order. +#define FREEIMAGE_COLORORDER_BGR 0 +#define FREEIMAGE_COLORORDER_RGB 1 +#if defined(__APPLE__) || defined(FREEIMAGE_BIGENDIAN) +#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_RGB +#else +#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_BGR +#endif + +// Ensure 4-byte enums if we're using Borland C++ compilers +#if defined(__BORLANDC__) +#pragma option push -b +#endif + +// For C compatibility -------------------------------------------------------- + +#ifdef __cplusplus +#define FI_DEFAULT(x) = x +#define FI_ENUM(x) enum x +#define FI_STRUCT(x) struct x +#else +#define FI_DEFAULT(x) +#define FI_ENUM(x) typedef int x; enum x +#define FI_STRUCT(x) typedef struct x x; struct x +#endif + +// Bitmap types ------------------------------------------------------------- + +FI_STRUCT (FIBITMAP) { void *data; }; +FI_STRUCT (FIMULTIBITMAP) { void *data; }; + +// Types used in the library (directly copied from Windows) ----------------- + +#ifndef _WINDOWS_ +#define _WINDOWS_ + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#ifndef _MSC_VER +// define portable types for 32-bit / 64-bit OS +#include +typedef int32_t BOOL; +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef int32_t LONG; +#else +// MS is not C99 ISO compliant +typedef long BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef long LONG; +#endif // _MSC_VER + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif // WIN32 + +typedef struct tagRGBQUAD { +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; +#else + BYTE rgbRed; + BYTE rgbGreen; + BYTE rgbBlue; +#endif // FREEIMAGE_COLORORDER + BYTE rgbReserved; +} RGBQUAD; + +typedef struct tagRGBTRIPLE { +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + BYTE rgbtBlue; + BYTE rgbtGreen; + BYTE rgbtRed; +#else + BYTE rgbtRed; + BYTE rgbtGreen; + BYTE rgbtBlue; +#endif // FREEIMAGE_COLORORDER +} RGBTRIPLE; + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(pop) +#else +#pragma pack() +#endif // WIN32 + +typedef struct tagBITMAPINFOHEADER{ + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER, *PBITMAPINFOHEADER; + +typedef struct tagBITMAPINFO { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO, *PBITMAPINFO; + +#endif // _WINDOWS_ + +// Types used in the library (specific to FreeImage) ------------------------ + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif // WIN32 + +/** 48-bit RGB +*/ +typedef struct tagFIRGB16 { + WORD red; + WORD green; + WORD blue; +} FIRGB16; + +/** 64-bit RGBA +*/ +typedef struct tagFIRGBA16 { + WORD red; + WORD green; + WORD blue; + WORD alpha; +} FIRGBA16; + +/** 96-bit RGB Float +*/ +typedef struct tagFIRGBF { + float red; + float green; + float blue; +} FIRGBF; + +/** 128-bit RGBA Float +*/ +typedef struct tagFIRGBAF { + float red; + float green; + float blue; + float alpha; +} FIRGBAF; + +/** Data structure for COMPLEX type (complex number) +*/ +typedef struct tagFICOMPLEX { + /// real part + double r; + /// imaginary part + double i; +} FICOMPLEX; + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(pop) +#else +#pragma pack() +#endif // WIN32 + +// Indexes for byte arrays, masks and shifts for treating pixels as words --- +// These coincide with the order of RGBQUAD and RGBTRIPLE ------------------- + +#ifndef FREEIMAGE_BIGENDIAN +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR +// Little Endian (x86 / MS Windows, Linux) : BGR(A) order +#define FI_RGBA_RED 2 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 0 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0x00FF0000 +#define FI_RGBA_GREEN_MASK 0x0000FF00 +#define FI_RGBA_BLUE_MASK 0x000000FF +#define FI_RGBA_ALPHA_MASK 0xFF000000 +#define FI_RGBA_RED_SHIFT 16 +#define FI_RGBA_GREEN_SHIFT 8 +#define FI_RGBA_BLUE_SHIFT 0 +#define FI_RGBA_ALPHA_SHIFT 24 +#else +// Little Endian (x86 / MaxOSX) : RGB(A) order +#define FI_RGBA_RED 0 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 2 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0x000000FF +#define FI_RGBA_GREEN_MASK 0x0000FF00 +#define FI_RGBA_BLUE_MASK 0x00FF0000 +#define FI_RGBA_ALPHA_MASK 0xFF000000 +#define FI_RGBA_RED_SHIFT 0 +#define FI_RGBA_GREEN_SHIFT 8 +#define FI_RGBA_BLUE_SHIFT 16 +#define FI_RGBA_ALPHA_SHIFT 24 +#endif // FREEIMAGE_COLORORDER +#else +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR +// Big Endian (PPC / none) : BGR(A) order +#define FI_RGBA_RED 2 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 0 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0x0000FF00 +#define FI_RGBA_GREEN_MASK 0x00FF0000 +#define FI_RGBA_BLUE_MASK 0xFF000000 +#define FI_RGBA_ALPHA_MASK 0x000000FF +#define FI_RGBA_RED_SHIFT 8 +#define FI_RGBA_GREEN_SHIFT 16 +#define FI_RGBA_BLUE_SHIFT 24 +#define FI_RGBA_ALPHA_SHIFT 0 +#else +// Big Endian (PPC / Linux, MaxOSX) : RGB(A) order +#define FI_RGBA_RED 0 +#define FI_RGBA_GREEN 1 +#define FI_RGBA_BLUE 2 +#define FI_RGBA_ALPHA 3 +#define FI_RGBA_RED_MASK 0xFF000000 +#define FI_RGBA_GREEN_MASK 0x00FF0000 +#define FI_RGBA_BLUE_MASK 0x0000FF00 +#define FI_RGBA_ALPHA_MASK 0x000000FF +#define FI_RGBA_RED_SHIFT 24 +#define FI_RGBA_GREEN_SHIFT 16 +#define FI_RGBA_BLUE_SHIFT 8 +#define FI_RGBA_ALPHA_SHIFT 0 +#endif // FREEIMAGE_COLORORDER +#endif // FREEIMAGE_BIGENDIAN + +#define FI_RGBA_RGB_MASK (FI_RGBA_RED_MASK|FI_RGBA_GREEN_MASK|FI_RGBA_BLUE_MASK) + +// The 16bit macros only include masks and shifts, since each color element is not byte aligned + +#define FI16_555_RED_MASK 0x7C00 +#define FI16_555_GREEN_MASK 0x03E0 +#define FI16_555_BLUE_MASK 0x001F +#define FI16_555_RED_SHIFT 10 +#define FI16_555_GREEN_SHIFT 5 +#define FI16_555_BLUE_SHIFT 0 +#define FI16_565_RED_MASK 0xF800 +#define FI16_565_GREEN_MASK 0x07E0 +#define FI16_565_BLUE_MASK 0x001F +#define FI16_565_RED_SHIFT 11 +#define FI16_565_GREEN_SHIFT 5 +#define FI16_565_BLUE_SHIFT 0 + +// ICC profile support ------------------------------------------------------ + +#define FIICC_DEFAULT 0x00 +#define FIICC_COLOR_IS_CMYK 0x01 + +FI_STRUCT (FIICCPROFILE) { + WORD flags; // info flag + DWORD size; // profile's size measured in bytes + void *data; // points to a block of contiguous memory containing the profile +}; + +// Important enums ---------------------------------------------------------- + +/** I/O image format identifiers. +*/ +FI_ENUM(FREE_IMAGE_FORMAT) { + FIF_UNKNOWN = -1, + FIF_BMP = 0, + FIF_ICO = 1, + FIF_JPEG = 2, + FIF_JNG = 3, + FIF_KOALA = 4, + FIF_LBM = 5, + FIF_IFF = FIF_LBM, + FIF_MNG = 6, + FIF_PBM = 7, + FIF_PBMRAW = 8, + FIF_PCD = 9, + FIF_PCX = 10, + FIF_PGM = 11, + FIF_PGMRAW = 12, + FIF_PNG = 13, + FIF_PPM = 14, + FIF_PPMRAW = 15, + FIF_RAS = 16, + FIF_TARGA = 17, + FIF_TIFF = 18, + FIF_WBMP = 19, + FIF_PSD = 20, + FIF_CUT = 21, + FIF_XBM = 22, + FIF_XPM = 23, + FIF_DDS = 24, + FIF_GIF = 25, + FIF_HDR = 26, + FIF_FAXG3 = 27, + FIF_SGI = 28, + FIF_EXR = 29, + FIF_J2K = 30, + FIF_JP2 = 31 +}; + +/** Image type used in FreeImage. +*/ +FI_ENUM(FREE_IMAGE_TYPE) { + FIT_UNKNOWN = 0, // unknown type + FIT_BITMAP = 1, // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit + FIT_UINT16 = 2, // array of unsigned short : unsigned 16-bit + FIT_INT16 = 3, // array of short : signed 16-bit + FIT_UINT32 = 4, // array of unsigned long : unsigned 32-bit + FIT_INT32 = 5, // array of long : signed 32-bit + FIT_FLOAT = 6, // array of float : 32-bit IEEE floating point + FIT_DOUBLE = 7, // array of double : 64-bit IEEE floating point + FIT_COMPLEX = 8, // array of FICOMPLEX : 2 x 64-bit IEEE floating point + FIT_RGB16 = 9, // 48-bit RGB image : 3 x 16-bit + FIT_RGBA16 = 10, // 64-bit RGBA image : 4 x 16-bit + FIT_RGBF = 11, // 96-bit RGB float image : 3 x 32-bit IEEE floating point + FIT_RGBAF = 12 // 128-bit RGBA float image : 4 x 32-bit IEEE floating point +}; + +/** Image color type used in FreeImage. +*/ +FI_ENUM(FREE_IMAGE_COLOR_TYPE) { + FIC_MINISWHITE = 0, // min value is white + FIC_MINISBLACK = 1, // min value is black + FIC_RGB = 2, // RGB color model + FIC_PALETTE = 3, // color map indexed + FIC_RGBALPHA = 4, // RGB color model with alpha channel + FIC_CMYK = 5 // CMYK color model +}; + +/** Color quantization algorithms. +Constants used in FreeImage_ColorQuantize. +*/ +FI_ENUM(FREE_IMAGE_QUANTIZE) { + FIQ_WUQUANT = 0, // Xiaolin Wu color quantization algorithm + FIQ_NNQUANT = 1 // NeuQuant neural-net quantization algorithm by Anthony Dekker +}; + +/** Dithering algorithms. +Constants used in FreeImage_Dither. +*/ +FI_ENUM(FREE_IMAGE_DITHER) { + FID_FS = 0, // Floyd & Steinberg error diffusion + FID_BAYER4x4 = 1, // Bayer ordered dispersed dot dithering (order 2 dithering matrix) + FID_BAYER8x8 = 2, // Bayer ordered dispersed dot dithering (order 3 dithering matrix) + FID_CLUSTER6x6 = 3, // Ordered clustered dot dithering (order 3 - 6x6 matrix) + FID_CLUSTER8x8 = 4, // Ordered clustered dot dithering (order 4 - 8x8 matrix) + FID_CLUSTER16x16= 5, // Ordered clustered dot dithering (order 8 - 16x16 matrix) + FID_BAYER16x16 = 6 // Bayer ordered dispersed dot dithering (order 4 dithering matrix) +}; + +/** Lossless JPEG transformations +Constants used in FreeImage_JPEGTransform +*/ +FI_ENUM(FREE_IMAGE_JPEG_OPERATION) { + FIJPEG_OP_NONE = 0, // no transformation + FIJPEG_OP_FLIP_H = 1, // horizontal flip + FIJPEG_OP_FLIP_V = 2, // vertical flip + FIJPEG_OP_TRANSPOSE = 3, // transpose across UL-to-LR axis + FIJPEG_OP_TRANSVERSE = 4, // transpose across UR-to-LL axis + FIJPEG_OP_ROTATE_90 = 5, // 90-degree clockwise rotation + FIJPEG_OP_ROTATE_180 = 6, // 180-degree rotation + FIJPEG_OP_ROTATE_270 = 7 // 270-degree clockwise (or 90 ccw) +}; + +/** Tone mapping operators. +Constants used in FreeImage_ToneMapping. +*/ +FI_ENUM(FREE_IMAGE_TMO) { + FITMO_DRAGO03 = 0, // Adaptive logarithmic mapping (F. Drago, 2003) + FITMO_REINHARD05 = 1, // Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005) + FITMO_FATTAL02 = 2 // Gradient domain high dynamic range compression (R. Fattal, 2002) +}; + +/** Upsampling / downsampling filters. +Constants used in FreeImage_Rescale. +*/ +FI_ENUM(FREE_IMAGE_FILTER) { + FILTER_BOX = 0, // Box, pulse, Fourier window, 1st order (constant) b-spline + FILTER_BICUBIC = 1, // Mitchell & Netravali's two-param cubic filter + FILTER_BILINEAR = 2, // Bilinear filter + FILTER_BSPLINE = 3, // 4th order (cubic) b-spline + FILTER_CATMULLROM = 4, // Catmull-Rom spline, Overhauser spline + FILTER_LANCZOS3 = 5 // Lanczos3 filter +}; + +/** Color channels. +Constants used in color manipulation routines. +*/ +FI_ENUM(FREE_IMAGE_COLOR_CHANNEL) { + FICC_RGB = 0, // Use red, green and blue channels + FICC_RED = 1, // Use red channel + FICC_GREEN = 2, // Use green channel + FICC_BLUE = 3, // Use blue channel + FICC_ALPHA = 4, // Use alpha channel + FICC_BLACK = 5, // Use black channel + FICC_REAL = 6, // Complex images: use real part + FICC_IMAG = 7, // Complex images: use imaginary part + FICC_MAG = 8, // Complex images: use magnitude + FICC_PHASE = 9 // Complex images: use phase +}; + +// Metadata support --------------------------------------------------------- + +/** + Tag data type information (based on TIFF specifications) + + Note: RATIONALs are the ratio of two 32-bit integer values. +*/ +FI_ENUM(FREE_IMAGE_MDTYPE) { + FIDT_NOTYPE = 0, // placeholder + FIDT_BYTE = 1, // 8-bit unsigned integer + FIDT_ASCII = 2, // 8-bit bytes w/ last byte null + FIDT_SHORT = 3, // 16-bit unsigned integer + FIDT_LONG = 4, // 32-bit unsigned integer + FIDT_RATIONAL = 5, // 64-bit unsigned fraction + FIDT_SBYTE = 6, // 8-bit signed integer + FIDT_UNDEFINED = 7, // 8-bit untyped data + FIDT_SSHORT = 8, // 16-bit signed integer + FIDT_SLONG = 9, // 32-bit signed integer + FIDT_SRATIONAL = 10, // 64-bit signed fraction + FIDT_FLOAT = 11, // 32-bit IEEE floating point + FIDT_DOUBLE = 12, // 64-bit IEEE floating point + FIDT_IFD = 13, // 32-bit unsigned integer (offset) + FIDT_PALETTE = 14 // 32-bit RGBQUAD +}; + +/** + Metadata models supported by FreeImage +*/ +FI_ENUM(FREE_IMAGE_MDMODEL) { + FIMD_NODATA = -1, + FIMD_COMMENTS = 0, // single comment or keywords + FIMD_EXIF_MAIN = 1, // Exif-TIFF metadata + FIMD_EXIF_EXIF = 2, // Exif-specific metadata + FIMD_EXIF_GPS = 3, // Exif GPS metadata + FIMD_EXIF_MAKERNOTE = 4, // Exif maker note metadata + FIMD_EXIF_INTEROP = 5, // Exif interoperability metadata + FIMD_IPTC = 6, // IPTC/NAA metadata + FIMD_XMP = 7, // Abobe XMP metadata + FIMD_GEOTIFF = 8, // GeoTIFF metadata + FIMD_ANIMATION = 9, // Animation metadata + FIMD_CUSTOM = 10 // Used to attach other metadata types to a dib +}; + +/** + Handle to a metadata model +*/ +FI_STRUCT (FIMETADATA) { void *data; }; + +/** + Handle to a FreeImage tag +*/ +FI_STRUCT (FITAG) { void *data; }; + +// File IO routines --------------------------------------------------------- + +#ifndef FREEIMAGE_IO +#define FREEIMAGE_IO + +typedef void* fi_handle; +typedef unsigned (DLL_CALLCONV *FI_ReadProc) (void *buffer, unsigned size, unsigned count, fi_handle handle); +typedef unsigned (DLL_CALLCONV *FI_WriteProc) (void *buffer, unsigned size, unsigned count, fi_handle handle); +typedef int (DLL_CALLCONV *FI_SeekProc) (fi_handle handle, long offset, int origin); +typedef long (DLL_CALLCONV *FI_TellProc) (fi_handle handle); + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(push, 1) +#else +#pragma pack(1) +#endif // WIN32 + +FI_STRUCT(FreeImageIO) { + FI_ReadProc read_proc; // pointer to the function used to read data + FI_WriteProc write_proc; // pointer to the function used to write data + FI_SeekProc seek_proc; // pointer to the function used to seek + FI_TellProc tell_proc; // pointer to the function used to aquire the current position +}; + +#if (defined(_WIN32) || defined(__WIN32__)) +#pragma pack(pop) +#else +#pragma pack() +#endif // WIN32 + +/** +Handle to a memory I/O stream +*/ +FI_STRUCT (FIMEMORY) { void *data; }; + +#endif // FREEIMAGE_IO + +// Plugin routines ---------------------------------------------------------- + +#ifndef PLUGINS +#define PLUGINS + +typedef const char *(DLL_CALLCONV *FI_FormatProc) (); +typedef const char *(DLL_CALLCONV *FI_DescriptionProc) (); +typedef const char *(DLL_CALLCONV *FI_ExtensionListProc) (); +typedef const char *(DLL_CALLCONV *FI_RegExprProc) (); +typedef void *(DLL_CALLCONV *FI_OpenProc)(FreeImageIO *io, fi_handle handle, BOOL read); +typedef void (DLL_CALLCONV *FI_CloseProc)(FreeImageIO *io, fi_handle handle, void *data); +typedef int (DLL_CALLCONV *FI_PageCountProc)(FreeImageIO *io, fi_handle handle, void *data); +typedef int (DLL_CALLCONV *FI_PageCapabilityProc)(FreeImageIO *io, fi_handle handle, void *data); +typedef FIBITMAP *(DLL_CALLCONV *FI_LoadProc)(FreeImageIO *io, fi_handle handle, int page, int flags, void *data); +typedef BOOL (DLL_CALLCONV *FI_SaveProc)(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data); +typedef BOOL (DLL_CALLCONV *FI_ValidateProc)(FreeImageIO *io, fi_handle handle); +typedef const char *(DLL_CALLCONV *FI_MimeProc) (); +typedef BOOL (DLL_CALLCONV *FI_SupportsExportBPPProc)(int bpp); +typedef BOOL (DLL_CALLCONV *FI_SupportsExportTypeProc)(FREE_IMAGE_TYPE type); +typedef BOOL (DLL_CALLCONV *FI_SupportsICCProfilesProc)(); + +FI_STRUCT (Plugin) { + FI_FormatProc format_proc; + FI_DescriptionProc description_proc; + FI_ExtensionListProc extension_proc; + FI_RegExprProc regexpr_proc; + FI_OpenProc open_proc; + FI_CloseProc close_proc; + FI_PageCountProc pagecount_proc; + FI_PageCapabilityProc pagecapability_proc; + FI_LoadProc load_proc; + FI_SaveProc save_proc; + FI_ValidateProc validate_proc; + FI_MimeProc mime_proc; + FI_SupportsExportBPPProc supports_export_bpp_proc; + FI_SupportsExportTypeProc supports_export_type_proc; + FI_SupportsICCProfilesProc supports_icc_profiles_proc; +}; + +typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id); + +#endif // PLUGINS + + +// Load / Save flag constants ----------------------------------------------- + +#define BMP_DEFAULT 0 +#define BMP_SAVE_RLE 1 +#define CUT_DEFAULT 0 +#define DDS_DEFAULT 0 +#define EXR_DEFAULT 0 // save data as half with piz-based wavelet compression +#define EXR_FLOAT 0x0001 // save data as float instead of as half (not recommended) +#define EXR_NONE 0x0002 // save with no compression +#define EXR_ZIP 0x0004 // save with zlib compression, in blocks of 16 scan lines +#define EXR_PIZ 0x0008 // save with piz-based wavelet compression +#define EXR_PXR24 0x0010 // save with lossy 24-bit float compression +#define EXR_B44 0x0020 // save with lossy 44% float compression - goes to 22% when combined with EXR_LC +#define EXR_LC 0x0040 // save images with one luminance and two chroma channels, rather than as RGB (lossy compression) +#define FAXG3_DEFAULT 0 +#define GIF_DEFAULT 0 +#define GIF_LOAD256 1 // Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color +#define GIF_PLAYBACK 2 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading +#define HDR_DEFAULT 0 +#define ICO_DEFAULT 0 +#define ICO_MAKEALPHA 1 // convert to 32bpp and create an alpha channel from the AND-mask when loading +#define IFF_DEFAULT 0 +#define J2K_DEFAULT 0 // save with a 16:1 rate +#define JP2_DEFAULT 0 // save with a 16:1 rate +#define JPEG_DEFAULT 0 // loading (see JPEG_FAST); saving (see JPEG_QUALITYGOOD) +#define JPEG_FAST 0x0001 // load the file as fast as possible, sacrificing some quality +#define JPEG_ACCURATE 0x0002 // load the file with the best quality, sacrificing some speed +#define JPEG_CMYK 0x0004 // load separated CMYK "as is" (use | to combine with other load flags) +#define JPEG_QUALITYSUPERB 0x80 // save with superb quality (100:1) +#define JPEG_QUALITYGOOD 0x0100 // save with good quality (75:1) +#define JPEG_QUALITYNORMAL 0x0200 // save with normal quality (50:1) +#define JPEG_QUALITYAVERAGE 0x0400 // save with average quality (25:1) +#define JPEG_QUALITYBAD 0x0800 // save with bad quality (10:1) +#define JPEG_PROGRESSIVE 0x2000 // save as a progressive-JPEG (use | to combine with other save flags) +#define KOALA_DEFAULT 0 +#define LBM_DEFAULT 0 +#define MNG_DEFAULT 0 +#define PCD_DEFAULT 0 +#define PCD_BASE 1 // load the bitmap sized 768 x 512 +#define PCD_BASEDIV4 2 // load the bitmap sized 384 x 256 +#define PCD_BASEDIV16 3 // load the bitmap sized 192 x 128 +#define PCX_DEFAULT 0 +#define PNG_DEFAULT 0 +#define PNG_IGNOREGAMMA 1 // avoid gamma correction +#define PNM_DEFAULT 0 +#define PNM_SAVE_RAW 0 // If set the writer saves in RAW format (i.e. P4, P5 or P6) +#define PNM_SAVE_ASCII 1 // If set the writer saves in ASCII format (i.e. P1, P2 or P3) +#define PSD_DEFAULT 0 +#define RAS_DEFAULT 0 +#define SGI_DEFAULT 0 +#define TARGA_DEFAULT 0 +#define TARGA_LOAD_RGB888 1 // If set the loader converts RGB555 and ARGB8888 -> RGB888. +#define TIFF_DEFAULT 0 +#define TIFF_CMYK 0x0001 // reads/stores tags for separated CMYK (use | to combine with compression flags) +#define TIFF_PACKBITS 0x0100 // save using PACKBITS compression +#define TIFF_DEFLATE 0x0200 // save using DEFLATE compression (a.k.a. ZLIB compression) +#define TIFF_ADOBE_DEFLATE 0x0400 // save using ADOBE DEFLATE compression +#define TIFF_NONE 0x0800 // save without any compression +#define TIFF_CCITTFAX3 0x1000 // save using CCITT Group 3 fax encoding +#define TIFF_CCITTFAX4 0x2000 // save using CCITT Group 4 fax encoding +#define TIFF_LZW 0x4000 // save using LZW compression +#define TIFF_JPEG 0x8000 // save using JPEG compression +#define WBMP_DEFAULT 0 +#define XBM_DEFAULT 0 +#define XPM_DEFAULT 0 + + +#ifdef __cplusplus +extern "C" { +#endif + +// Init / Error routines ---------------------------------------------------- + +DLL_API void DLL_CALLCONV FreeImage_Initialise(BOOL load_local_plugins_only FI_DEFAULT(FALSE)); +DLL_API void DLL_CALLCONV FreeImage_DeInitialise(void); + +// Version routines --------------------------------------------------------- + +DLL_API const char *DLL_CALLCONV FreeImage_GetVersion(void); +DLL_API const char *DLL_CALLCONV FreeImage_GetCopyrightMessage(void); + +// Message output functions ------------------------------------------------- + +typedef void (*FreeImage_OutputMessageFunction)(FREE_IMAGE_FORMAT fif, const char *msg); +typedef void (DLL_CALLCONV *FreeImage_OutputMessageFunctionStdCall)(FREE_IMAGE_FORMAT fif, const char *msg); + +DLL_API void DLL_CALLCONV FreeImage_SetOutputMessageStdCall(FreeImage_OutputMessageFunctionStdCall omf); +DLL_API void DLL_CALLCONV FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf); +DLL_API void DLL_CALLCONV FreeImage_OutputMessageProc(int fif, const char *fmt, ...); + +// Allocate / Clone / Unload routines --------------------------------------- + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp FI_DEFAULT(8), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); +DLL_API FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib); +DLL_API void DLL_CALLCONV FreeImage_Unload(FIBITMAP *dib); + +// Load / Save routines ----------------------------------------------------- + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0)); + +// Memory I/O stream routines ----------------------------------------------- + +DLL_API FIMEMORY *DLL_CALLCONV FreeImage_OpenMemory(BYTE *data FI_DEFAULT(0), DWORD size_in_bytes FI_DEFAULT(0)); +DLL_API void DLL_CALLCONV FreeImage_CloseMemory(FIMEMORY *stream); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags FI_DEFAULT(0)); +DLL_API long DLL_CALLCONV FreeImage_TellMemory(FIMEMORY *stream); +DLL_API BOOL DLL_CALLCONV FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin); +DLL_API BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes); +DLL_API unsigned DLL_CALLCONV FreeImage_ReadMemory(void *buffer, unsigned size, unsigned count, FIMEMORY *stream); +DLL_API unsigned DLL_CALLCONV FreeImage_WriteMemory(const void *buffer, unsigned size, unsigned count, FIMEMORY *stream); +DLL_API FIMULTIBITMAP *DLL_CALLCONV FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags FI_DEFAULT(0)); + +// Plugin Interface --------------------------------------------------------- + +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0)); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterExternalPlugin(const char *path, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0)); +DLL_API int DLL_CALLCONV FreeImage_GetFIFCount(void); +DLL_API int DLL_CALLCONV FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable); +DLL_API int DLL_CALLCONV FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFormat(const char *format); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromMime(const char *mime); +DLL_API const char *DLL_CALLCONV FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif); +DLL_API const char *DLL_CALLCONV FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif); +DLL_API const char *DLL_CALLCONV FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif); +DLL_API const char *DLL_CALLCONV FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif); +DLL_API const char *DLL_CALLCONV FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilename(const char *filename); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilenameU(const wchar_t *filename); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int bpp); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif); + +// Multipaging interface ---------------------------------------------------- + +DLL_API FIMULTIBITMAP * DLL_CALLCONV FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory FI_DEFAULT(FALSE), int flags FI_DEFAULT(0)); +DLL_API BOOL DLL_CALLCONV FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags FI_DEFAULT(0)); +DLL_API int DLL_CALLCONV FreeImage_GetPageCount(FIMULTIBITMAP *bitmap); +DLL_API void DLL_CALLCONV FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data); +DLL_API void DLL_CALLCONV FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data); +DLL_API void DLL_CALLCONV FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page); +DLL_API FIBITMAP * DLL_CALLCONV FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page); +DLL_API void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *data, BOOL changed); +DLL_API BOOL DLL_CALLCONV FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source); +DLL_API BOOL DLL_CALLCONV FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count); + +// Filetype request routines ------------------------------------------------ + +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0)); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeU(const wchar_t *filename, int size FI_DEFAULT(0)); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size FI_DEFAULT(0)); +DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size FI_DEFAULT(0)); + +// Image type request routine ----------------------------------------------- + +DLL_API FREE_IMAGE_TYPE DLL_CALLCONV FreeImage_GetImageType(FIBITMAP *dib); + +// FreeImage helper routines ------------------------------------------------ + +DLL_API BOOL DLL_CALLCONV FreeImage_IsLittleEndian(void); +DLL_API BOOL DLL_CALLCONV FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue); +DLL_API BOOL DLL_CALLCONV FreeImage_LookupSVGColor(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue); + + +// Pixel access routines ---------------------------------------------------- + +DLL_API BYTE *DLL_CALLCONV FreeImage_GetBits(FIBITMAP *dib); +DLL_API BYTE *DLL_CALLCONV FreeImage_GetScanLine(FIBITMAP *dib, int scanline); + +DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value); +DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value); +DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value); +DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value); + +// DIB info routines -------------------------------------------------------- + +DLL_API unsigned DLL_CALLCONV FreeImage_GetColorsUsed(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetBPP(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetWidth(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetHeight(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetLine(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetPitch(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetDIBSize(FIBITMAP *dib); +DLL_API RGBQUAD *DLL_CALLCONV FreeImage_GetPalette(FIBITMAP *dib); + +DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterX(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterY(FIBITMAP *dib); +DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res); +DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res); + +DLL_API BITMAPINFOHEADER *DLL_CALLCONV FreeImage_GetInfoHeader(FIBITMAP *dib); +DLL_API BITMAPINFO *DLL_CALLCONV FreeImage_GetInfo(FIBITMAP *dib); +DLL_API FREE_IMAGE_COLOR_TYPE DLL_CALLCONV FreeImage_GetColorType(FIBITMAP *dib); + +DLL_API unsigned DLL_CALLCONV FreeImage_GetRedMask(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetGreenMask(FIBITMAP *dib); +DLL_API unsigned DLL_CALLCONV FreeImage_GetBlueMask(FIBITMAP *dib); + +DLL_API unsigned DLL_CALLCONV FreeImage_GetTransparencyCount(FIBITMAP *dib); +DLL_API BYTE * DLL_CALLCONV FreeImage_GetTransparencyTable(FIBITMAP *dib); +DLL_API void DLL_CALLCONV FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled); +DLL_API void DLL_CALLCONV FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count); +DLL_API BOOL DLL_CALLCONV FreeImage_IsTransparent(FIBITMAP *dib); +DLL_API void DLL_CALLCONV FreeImage_SetTransparentIndex(FIBITMAP *dib, int index); +DLL_API int DLL_CALLCONV FreeImage_GetTransparentIndex(FIBITMAP *dib); + +DLL_API BOOL DLL_CALLCONV FreeImage_HasBackgroundColor(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor); +DLL_API BOOL DLL_CALLCONV FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor); + + +// ICC profile routines ----------------------------------------------------- + +DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_GetICCProfile(FIBITMAP *dib); +DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size); +DLL_API void DLL_CALLCONV FreeImage_DestroyICCProfile(FIBITMAP *dib); + +// Line conversion routines ------------------------------------------------- + +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_565_To16_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_555_To16_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels); +DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels); + +// Smart conversion routines ------------------------------------------------ + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo4Bits(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo8Bits(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToGreyscale(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits555(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits565(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo24Bits(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo32Bits(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantize(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize FI_DEFAULT(FIQ_WUQUANT), int PaletteSize FI_DEFAULT(256), int ReserveSize FI_DEFAULT(0), RGBQUAD *ReservePalette FI_DEFAULT(NULL)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Threshold(FIBITMAP *dib, BYTE T); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm); + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertFromRawBits(BYTE *bits, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE)); +DLL_API void DLL_CALLCONV FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE)); + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGBF(FIBITMAP *dib); + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear FI_DEFAULT(TRUE)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear FI_DEFAULT(TRUE)); + +// tone mapping operators +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ToneMapping(FIBITMAP *dib, FREE_IMAGE_TMO tmo, double first_param FI_DEFAULT(0), double second_param FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoDrago03(FIBITMAP *src, double gamma FI_DEFAULT(2.2), double exposure FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoReinhard05(FIBITMAP *src, double intensity FI_DEFAULT(0), double contrast FI_DEFAULT(0)); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoFattal02(FIBITMAP *src, double color_saturation FI_DEFAULT(0.5), double attenuation FI_DEFAULT(0.85)); + +// ZLib interface ----------------------------------------------------------- + +DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +DLL_API DWORD DLL_CALLCONV FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size); +DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size); + +// -------------------------------------------------------------------------- +// Metadata routines -------------------------------------------------------- +// -------------------------------------------------------------------------- + +// tag creation / destruction +DLL_API FITAG *DLL_CALLCONV FreeImage_CreateTag(); +DLL_API void DLL_CALLCONV FreeImage_DeleteTag(FITAG *tag); +DLL_API FITAG *DLL_CALLCONV FreeImage_CloneTag(FITAG *tag); + +// tag getters and setters +DLL_API const char *DLL_CALLCONV FreeImage_GetTagKey(FITAG *tag); +DLL_API const char *DLL_CALLCONV FreeImage_GetTagDescription(FITAG *tag); +DLL_API WORD DLL_CALLCONV FreeImage_GetTagID(FITAG *tag); +DLL_API FREE_IMAGE_MDTYPE DLL_CALLCONV FreeImage_GetTagType(FITAG *tag); +DLL_API DWORD DLL_CALLCONV FreeImage_GetTagCount(FITAG *tag); +DLL_API DWORD DLL_CALLCONV FreeImage_GetTagLength(FITAG *tag); +DLL_API const void *DLL_CALLCONV FreeImage_GetTagValue(FITAG *tag); + +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagKey(FITAG *tag, const char *key); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagDescription(FITAG *tag, const char *description); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagID(FITAG *tag, WORD id); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagCount(FITAG *tag, DWORD count); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagLength(FITAG *tag, DWORD length); +DLL_API BOOL DLL_CALLCONV FreeImage_SetTagValue(FITAG *tag, const void *value); + +// iterator +DLL_API FIMETADATA *DLL_CALLCONV FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag); +DLL_API BOOL DLL_CALLCONV FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag); +DLL_API void DLL_CALLCONV FreeImage_FindCloseMetadata(FIMETADATA *mdhandle); + +// metadata setter and getter +DLL_API BOOL DLL_CALLCONV FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag); +DLL_API BOOL DLL_CALLCONV FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag); + +// helpers +DLL_API unsigned DLL_CALLCONV FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib); + +// tag to C string conversion +DLL_API const char* DLL_CALLCONV FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make FI_DEFAULT(NULL)); + +// -------------------------------------------------------------------------- +// Image manipulation toolkit ----------------------------------------------- +// -------------------------------------------------------------------------- + +// rotation and flipping +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask); +DLL_API BOOL DLL_CALLCONV FreeImage_FlipHorizontal(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_FlipVertical(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect FI_DEFAULT(FALSE)); + +// upsampling / downsampling +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rescale(FIBITMAP *dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert FI_DEFAULT(TRUE)); + +// color manipulation routines (point operations) +DLL_API BOOL DLL_CALLCONV FreeImage_AdjustCurve(FIBITMAP *dib, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel); +DLL_API BOOL DLL_CALLCONV FreeImage_AdjustGamma(FIBITMAP *dib, double gamma); +DLL_API BOOL DLL_CALLCONV FreeImage_AdjustBrightness(FIBITMAP *dib, double percentage); +DLL_API BOOL DLL_CALLCONV FreeImage_AdjustContrast(FIBITMAP *dib, double percentage); +DLL_API BOOL DLL_CALLCONV FreeImage_Invert(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_GetHistogram(FIBITMAP *dib, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel FI_DEFAULT(FICC_BLACK)); +DLL_API int DLL_CALLCONV FreeImage_GetAdjustColorsLookupTable(BYTE *LUT, double brightness, double contrast, double gamma, BOOL invert); +DLL_API BOOL DLL_CALLCONV FreeImage_AdjustColors(FIBITMAP *dib, double brightness, double contrast, double gamma, BOOL invert FI_DEFAULT(FALSE)); +DLL_API unsigned DLL_CALLCONV FreeImage_ApplyColorMapping(FIBITMAP *dib, RGBQUAD *srccolors, RGBQUAD *dstcolors, unsigned count, BOOL ignore_alpha, BOOL swap); +DLL_API unsigned DLL_CALLCONV FreeImage_SwapColors(FIBITMAP *dib, RGBQUAD *color_a, RGBQUAD *color_b, BOOL ignore_alpha); +DLL_API unsigned DLL_CALLCONV FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices, BYTE *dstindices, unsigned count, BOOL swap); +DLL_API unsigned DLL_CALLCONV FreeImage_SwapPaletteIndices(FIBITMAP *dib, BYTE *index_a, BYTE *index_b); + +// channel processing routines +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetChannel(FIBITMAP *dib, FREE_IMAGE_COLOR_CHANNEL channel); +DLL_API BOOL DLL_CALLCONV FreeImage_SetChannel(FIBITMAP *dib, FIBITMAP *dib8, FREE_IMAGE_COLOR_CHANNEL channel); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel); +DLL_API BOOL DLL_CALLCONV FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel); + +// copy / paste / composite routines +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Copy(FIBITMAP *dib, int left, int top, int right, int bottom); +DLL_API BOOL DLL_CALLCONV FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg FI_DEFAULT(FALSE), RGBQUAD *appBkColor FI_DEFAULT(NULL), FIBITMAP *bg FI_DEFAULT(NULL)); +DLL_API BOOL DLL_CALLCONV FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom); +DLL_API BOOL DLL_CALLCONV FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib); + +// miscellaneous algorithms +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle FI_DEFAULT(3)); + +// restore the borland-specific enum size option +#if defined(__BORLANDC__) +#pragma option pop +#endif + +#ifdef __cplusplus +} +#endif + +#endif // FREEIMAGE_H diff --git a/v2/libs/FreeImage/freeimage.s.lib b/v2/libs/FreeImage/freeimage.s.lib new file mode 100755 index 0000000000000000000000000000000000000000..ca3c5002af1cd0898d453293c0610c7f028cf965 GIT binary patch literal 1960314 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

S9LEQkezu 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 BqIFiPqbh-w0;xr;na7a{#vyD=djfr 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

U0it=@?@cQfhrg3VNjeaCu@&_nkp2pw3rfj* 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