summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathieu Malaterre <mathieu.malaterre@gmail.com>2012-09-28 08:11:41 +0000
committerMathieu Malaterre <mathieu.malaterre@gmail.com>2012-09-28 08:11:41 +0000
commitd518970039a19a2a9b6d2bdd592cc88a43897bbb (patch)
tree57bac2cf7e63e9352228231062763baac627563c /src
parent8363a6ab1e031bb4b2e40a92e56efd40fdab1aa1 (diff)
[trunk] Start FolderReorgProposal task
Update issue 177
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/bin/CMakeLists.txt20
-rw-r--r--src/bin/common/CMakeLists.txt0
-rw-r--r--src/bin/common/color.c466
-rw-r--r--src/bin/common/color.h38
-rw-r--r--src/bin/common/format_defs.h49
-rw-r--r--src/bin/common/opj_getopt.c254
-rw-r--r--src/bin/common/opj_getopt.h29
-rw-r--r--src/bin/jp2/CMakeLists.txt113
-rw-r--r--src/bin/jp2/Makefile.am118
-rw-r--r--src/bin/jp2/README8
-rw-r--r--src/bin/jp2/convert.c3621
-rw-r--r--src/bin/jp2/convert.h84
-rw-r--r--src/bin/jp2/image_to_j2k.c1901
-rw-r--r--src/bin/jp2/index.c392
-rw-r--r--src/bin/jp2/index.h49
-rw-r--r--src/bin/jp2/j2k_dump.c585
-rw-r--r--src/bin/jp2/j2k_to_image.c975
-rw-r--r--src/bin/jp2/windirent.h679
-rw-r--r--src/bin/jpip/CMakeLists.txt150
-rw-r--r--src/bin/jpip/Makefile.am85
-rw-r--r--src/bin/jpip/addXMLinJP2.c181
-rw-r--r--src/bin/jpip/jpip_to_j2k.c72
-rw-r--r--src/bin/jpip/jpip_to_jp2.c72
-rw-r--r--src/bin/jpip/opj_dec_server.c92
-rw-r--r--src/bin/jpip/opj_server.c127
-rw-r--r--src/bin/jpip/opj_viewer/dist/manifest.txt4
-rw-r--r--src/bin/jpip/opj_viewer/src/ImageManager.java136
-rw-r--r--src/bin/jpip/opj_viewer/src/ImageViewer.java266
-rw-r--r--src/bin/jpip/opj_viewer/src/ImageWindow.java120
-rw-r--r--src/bin/jpip/opj_viewer/src/ImgdecClient.java350
-rw-r--r--src/bin/jpip/opj_viewer/src/JPIPHttpClient.java503
-rw-r--r--src/bin/jpip/opj_viewer/src/MML.java116
-rw-r--r--src/bin/jpip/opj_viewer/src/PnmImage.java154
-rw-r--r--src/bin/jpip/opj_viewer/src/RegimViewer.java114
-rw-r--r--src/bin/jpip/opj_viewer/src/ResizeListener.java67
-rw-r--r--src/bin/jpip/opj_viewer_xerces/dist/manifest.txt.in5
-rw-r--r--src/bin/jpip/opj_viewer_xerces/src/ImageViewer.java266
-rw-r--r--src/bin/jpip/opj_viewer_xerces/src/ImageWindow.java124
-rw-r--r--src/bin/jpip/opj_viewer_xerces/src/JP2XMLparser.java122
-rw-r--r--src/bin/jpip/opj_viewer_xerces/src/OptionPanel.java98
-rw-r--r--src/bin/jpip/test_index.c73
-rw-r--r--src/bin/mj2/CMakeLists.txt94
-rw-r--r--src/bin/mj2/Makefile.am111
-rw-r--r--src/bin/mj2/extract_j2k_from_mj2.c150
-rw-r--r--src/bin/mj2/frames_to_mj2.c843
-rw-r--r--src/bin/mj2/meta_out.c2181
-rw-r--r--src/bin/mj2/meta_out.h13
-rw-r--r--src/bin/mj2/mj2.c2915
-rw-r--r--src/bin/mj2/mj2.h393
-rw-r--r--src/bin/mj2/mj2_convert.c372
-rw-r--r--src/bin/mj2/mj2_convert.h45
-rw-r--r--src/bin/mj2/mj2_to_frames.c252
-rw-r--r--src/bin/mj2/mj2_to_metadata.c312
-rw-r--r--src/bin/mj2/mj2_to_metadata.dtd425
-rw-r--r--src/bin/mj2/mj2_to_metadata.h9
-rw-r--r--src/bin/mj2/mj2_to_metadata.sln29
-rw-r--r--src/bin/mj2/mj2_to_metadata.vcproj349
-rw-r--r--src/bin/mj2/mj2_to_metadata_Notes.docbin0 -> 35328 bytes
-rw-r--r--src/bin/mj2/readme.txt3
-rw-r--r--src/bin/mj2/wrap_j2k_in_mj2.c523
-rw-r--r--src/bin/wx/CMakeLists.txt0
-rw-r--r--src/bin/wx/OPJViewer/CMakeLists.txt25
-rw-r--r--src/bin/wx/OPJViewer/OPJViewer.iss48
-rw-r--r--src/bin/wx/OPJViewer/Readme.txt100
-rw-r--r--src/bin/wx/OPJViewer/about/about.htm36
-rw-r--r--src/bin/wx/OPJViewer/about/opj_logo.pngbin0 -> 6500 bytes
-rw-r--r--src/bin/wx/OPJViewer/source/OPJAbout.cpp87
-rw-r--r--src/bin/wx/OPJViewer/source/OPJChild.icobin0 -> 1078 bytes
-rw-r--r--src/bin/wx/OPJViewer/source/OPJChild16.xpm28
-rw-r--r--src/bin/wx/OPJViewer/source/OPJDialogs.cpp1373
-rw-r--r--src/bin/wx/OPJViewer/source/OPJThreads.cpp1268
-rw-r--r--src/bin/wx/OPJViewer/source/OPJViewer.cpp1666
-rw-r--r--src/bin/wx/OPJViewer/source/OPJViewer.h812
-rw-r--r--src/bin/wx/OPJViewer/source/OPJViewer.icobin0 -> 1078 bytes
-rw-r--r--src/bin/wx/OPJViewer/source/OPJViewer.rc3
-rw-r--r--src/bin/wx/OPJViewer/source/OPJViewer16.xpm26
-rw-r--r--src/bin/wx/OPJViewer/source/about_htm.h54
-rw-r--r--src/bin/wx/OPJViewer/source/build.h1
-rw-r--r--src/bin/wx/OPJViewer/source/icon1.xpm79
-rw-r--r--src/bin/wx/OPJViewer/source/icon2.xpm53
-rw-r--r--src/bin/wx/OPJViewer/source/icon3.xpm79
-rw-r--r--src/bin/wx/OPJViewer/source/icon4.xpm43
-rw-r--r--src/bin/wx/OPJViewer/source/icon5.xpm79
-rw-r--r--src/bin/wx/OPJViewer/source/imagjpeg2000.cpp1464
-rw-r--r--src/bin/wx/OPJViewer/source/imagjpeg2000.h177
-rw-r--r--src/bin/wx/OPJViewer/source/imagmxf.cpp502
-rw-r--r--src/bin/wx/OPJViewer/source/imagmxf.h99
-rw-r--r--src/bin/wx/OPJViewer/source/license.txt14
-rw-r--r--src/bin/wx/OPJViewer/source/opj_logo.xpm285
-rw-r--r--src/bin/wx/OPJViewer/source/readmeafter.txt34
-rw-r--r--src/bin/wx/OPJViewer/source/readmebefore.txt11
-rw-r--r--src/bin/wx/OPJViewer/source/wxj2kparser.cpp1465
-rw-r--r--src/bin/wx/OPJViewer/source/wxjp2parser.cpp1116
-rw-r--r--src/lib/openjp2/CMakeLists.txt77
-rw-r--r--src/lib/openjp2/Makefile.am109
-rw-r--r--src/lib/openjp2/bio.c187
-rw-r--r--src/lib/openjp2/bio.h128
-rw-r--r--src/lib/openjp2/cidx_manager.c211
-rw-r--r--src/lib/openjp2/cidx_manager.h56
-rw-r--r--src/lib/openjp2/cio.c786
-rw-r--r--src/lib/openjp2/cio.h409
-rw-r--r--src/lib/openjp2/dwt.c1061
-rw-r--r--src/lib/openjp2/dwt.h122
-rw-r--r--src/lib/openjp2/event.c179
-rw-r--r--src/lib/openjp2/event.h104
-rw-r--r--src/lib/openjp2/fix.h64
-rw-r--r--src/lib/openjp2/function_list.c114
-rw-r--r--src/lib/openjp2/function_list.h126
-rw-r--r--src/lib/openjp2/image.c235
-rw-r--r--src/lib/openjp2/image.h63
-rw-r--r--src/lib/openjp2/indexbox_manager.h118
-rw-r--r--src/lib/openjp2/int.h159
-rw-r--r--src/lib/openjp2/j2k.c9754
-rw-r--r--src/lib/openjp2/j2k.h1043
-rw-r--r--src/lib/openjp2/j2k_lib.c59
-rw-r--r--src/lib/openjp2/j2k_lib.h54
-rw-r--r--src/lib/openjp2/jp2.c2324
-rw-r--r--src/lib/openjp2/jp2.h511
-rw-r--r--src/lib/openjp2/jpt.c155
-rw-r--r--src/lib/openjp2/jpt.h75
-rw-r--r--src/lib/openjp2/mct.c333
-rw-r--r--src/lib/openjp2/mct.h128
-rw-r--r--src/lib/openjp2/mqc.c599
-rw-r--r--src/lib/openjp2/mqc.h200
-rw-r--r--src/lib/openjp2/openjpeg.c1062
-rw-r--r--src/lib/openjp2/openjpeg.h1546
-rw-r--r--src/lib/openjp2/opj_includes.h185
-rw-r--r--src/lib/openjp2/opj_inttypes.h43
-rw-r--r--src/lib/openjp2/opj_malloc.h163
-rw-r--r--src/lib/openjp2/opj_stdint.h60
-rw-r--r--src/lib/openjp2/phix_manager.c169
-rw-r--r--src/lib/openjp2/pi.c2376
-rw-r--r--src/lib/openjp2/pi.h216
-rw-r--r--src/lib/openjp2/ppix_manager.c170
-rw-r--r--src/lib/openjp2/raw.c87
-rw-r--r--src/lib/openjp2/raw.h100
-rw-r--r--src/lib/openjp2/t1.c1410
-rw-r--r--src/lib/openjp2/t1.h159
-rw-r--r--src/lib/openjp2/t1_generate_luts.c274
-rw-r--r--src/lib/openjp2/t1_luts.h143
-rw-r--r--src/lib/openjp2/t2.c1271
-rw-r--r--src/lib/openjp2/t2.h140
-rw-r--r--src/lib/openjp2/tcd.c2109
-rw-r--r--src/lib/openjp2/tcd.h475
-rw-r--r--src/lib/openjp2/tgt.c433
-rw-r--r--src/lib/openjp2/tgt.h131
-rw-r--r--src/lib/openjp2/thix_manager.c118
-rw-r--r--src/lib/openjp2/tpix_manager.c152
-rw-r--r--src/lib/openjpip/CMakeLists.txt72
-rw-r--r--src/lib/openjpip/Makefile.am153
-rw-r--r--src/lib/openjpip/auxtrans_manager.c267
-rw-r--r--src/lib/openjpip/auxtrans_manager.h72
-rw-r--r--src/lib/openjpip/bool.h52
-rw-r--r--src/lib/openjpip/box_manager.c434
-rw-r--r--src/lib/openjpip/box_manager.h264
-rw-r--r--src/lib/openjpip/boxheader_manager.c84
-rw-r--r--src/lib/openjpip/boxheader_manager.h71
-rw-r--r--src/lib/openjpip/byte_manager.c172
-rw-r--r--src/lib/openjpip/byte_manager.h129
-rw-r--r--src/lib/openjpip/cache_manager.c275
-rw-r--r--src/lib/openjpip/cache_manager.h177
-rw-r--r--src/lib/openjpip/cachemodel_manager.c236
-rw-r--r--src/lib/openjpip/cachemodel_manager.h115
-rw-r--r--src/lib/openjpip/channel_manager.c180
-rw-r--r--src/lib/openjpip/channel_manager.h120
-rw-r--r--src/lib/openjpip/codestream_manager.c81
-rw-r--r--src/lib/openjpip/codestream_manager.h101
-rw-r--r--src/lib/openjpip/dec_clientmsg_handler.c253
-rw-r--r--src/lib/openjpip/dec_clientmsg_handler.h113
-rw-r--r--src/lib/openjpip/faixbox_manager.c195
-rw-r--r--src/lib/openjpip/faixbox_manager.h146
-rw-r--r--src/lib/openjpip/ihdrbox_manager.c78
-rw-r--r--src/lib/openjpip/ihdrbox_manager.h56
-rw-r--r--src/lib/openjpip/imgreg_manager.c157
-rw-r--r--src/lib/openjpip/imgreg_manager.h101
-rw-r--r--src/lib/openjpip/imgsock_manager.c209
-rw-r--r--src/lib/openjpip/imgsock_manager.h174
-rw-r--r--src/lib/openjpip/index_manager.c732
-rw-r--r--src/lib/openjpip/index_manager.h187
-rw-r--r--src/lib/openjpip/j2kheader_manager.c295
-rw-r--r--src/lib/openjpip/j2kheader_manager.h73
-rw-r--r--src/lib/openjpip/jp2k_decoder.c236
-rw-r--r--src/lib/openjpip/jp2k_decoder.h39
-rw-r--r--src/lib/openjpip/jp2k_encoder.c804
-rw-r--r--src/lib/openjpip/jp2k_encoder.h74
-rw-r--r--src/lib/openjpip/jpip_parser.c460
-rw-r--r--src/lib/openjpip/jpip_parser.h114
-rw-r--r--src/lib/openjpip/jpipstream_manager.c120
-rw-r--r--src/lib/openjpip/jpipstream_manager.h41
-rw-r--r--src/lib/openjpip/manfbox_manager.c115
-rw-r--r--src/lib/openjpip/manfbox_manager.h81
-rw-r--r--src/lib/openjpip/marker_manager.c68
-rw-r--r--src/lib/openjpip/marker_manager.h87
-rw-r--r--src/lib/openjpip/metadata_manager.c253
-rw-r--r--src/lib/openjpip/metadata_manager.h151
-rw-r--r--src/lib/openjpip/mhixbox_manager.c141
-rw-r--r--src/lib/openjpip/mhixbox_manager.h102
-rw-r--r--src/lib/openjpip/msgqueue_manager.c762
-rw-r--r--src/lib/openjpip/msgqueue_manager.h188
-rw-r--r--src/lib/openjpip/openjpip.c450
-rw-r--r--src/lib/openjpip/openjpip.h308
-rw-r--r--src/lib/openjpip/placeholder_manager.c143
-rw-r--r--src/lib/openjpip/placeholder_manager.h115
-rw-r--r--src/lib/openjpip/query_parser.c429
-rw-r--r--src/lib/openjpip/query_parser.h97
-rw-r--r--src/lib/openjpip/session_manager.c196
-rw-r--r--src/lib/openjpip/session_manager.h116
-rw-r--r--src/lib/openjpip/sock_manager.c181
-rw-r--r--src/lib/openjpip/sock_manager.h106
-rw-r--r--src/lib/openjpip/target_manager.c345
-rw-r--r--src/lib/openjpip/target_manager.h159
-rw-r--r--src/lib/openjpwl/CMakeLists.txt63
-rw-r--r--src/lib/openjpwl/Makefile.am78
-rw-r--r--src/lib/openjpwl/README.txt136
-rw-r--r--src/lib/openjpwl/crc.c160
-rw-r--r--src/lib/openjpwl/crc.h84
-rw-r--r--src/lib/openjpwl/jpwl.c1380
-rw-r--r--src/lib/openjpwl/jpwl.h427
-rw-r--r--src/lib/openjpwl/jpwl_lib.c1797
-rw-r--r--src/lib/openjpwl/rs.c597
-rw-r--r--src/lib/openjpwl/rs.h108
222 files changed, 82406 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 00000000..673843ec
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,12 @@
+# required dep for server:
+if(BUILD_JPIP_SERVER)
+ find_package(CURL REQUIRED)
+ find_package(FCGI REQUIRED)
+ find_package(Threads REQUIRED)
+ if(NOT CMAKE_USE_PTHREADS_INIT)
+ message(FATAL_ERROR "Only pthread are supported")
+ endif()
+endif()
+
+add_subdirectory(lib)
+#add_subdirectory(bin)
diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt
new file mode 100644
index 00000000..fa94d070
--- /dev/null
+++ b/src/bin/CMakeLists.txt
@@ -0,0 +1,20 @@
+# source code for openjpeg apps:
+add_subdirectory(common)
+# Part 1 & 2:
+add_subdirectory(jp2)
+
+# optionals components:
+if(BUILD_JPWL)
+# add_subdirectory(jpwl)
+endif()
+if(BUILD_MJ2)
+ add_subdirectory(mj2)
+endif()
+if(BUILD_JPIP)
+ add_subdirectory(jpip)
+endif()
+if(BUILD_JP3D)
+ add_subdirectory(jp3d)
+endif()
+
+add_subdirectory(wx)
diff --git a/src/bin/common/CMakeLists.txt b/src/bin/common/CMakeLists.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/bin/common/CMakeLists.txt
diff --git a/src/bin/common/color.c b/src/bin/common/color.c
new file mode 100644
index 00000000..21b02156
--- /dev/null
+++ b/src/bin/common/color.c
@@ -0,0 +1,466 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "opj_config.h"
+#include "openjpeg.h"
+#include "color.h"
+
+#ifdef HAVE_LIBLCMS2
+#include <lcms2.h>
+#endif
+#ifdef HAVE_LIBLCMS1
+#include <lcms.h>
+#endif
+
+/*--------------------------------------------------------
+Matrix for sYCC, Amendment 1 to IEC 61966-2-1
+
+Y : 0.299 0.587 0.114 :R
+Cb: -0.1687 -0.3312 0.5 :G
+Cr: 0.5 -0.4187 -0.0812 :B
+
+Inverse:
+
+R: 1 -3.68213e-05 1.40199 :Y
+G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
+B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
+
+-----------------------------------------------------------*/
+static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
+ int *out_r, int *out_g, int *out_b)
+{
+ int r, g, b;
+
+ cb -= offset; cr -= offset;
+ r = y + (int)(1.402 * (float)cr);
+ if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
+
+ g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
+ if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
+
+ b = y + (int)(1.772 * (float)cb);
+ if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
+}
+
+static void sycc444_to_rgb(opj_image_t *img)
+{
+ int *d0, *d1, *d2, *r, *g, *b;
+ const int *y, *cb, *cr;
+ int maxw, maxh, max, i, offset, upb;
+
+ i = img->comps[0].prec;
+ offset = 1<<(i - 1); upb = (1<<i)-1;
+
+ maxw = img->comps[0].w; maxh = img->comps[0].h;
+ max = maxw * maxh;
+
+ y = img->comps[0].data;
+ cb = img->comps[1].data;
+ cr = img->comps[2].data;
+
+ d0 = r = (int*)malloc(sizeof(int) * max);
+ d1 = g = (int*)malloc(sizeof(int) * max);
+ d2 = b = (int*)malloc(sizeof(int) * max);
+
+ for(i = 0; i < max; ++i)
+ {
+ sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+ ++y; ++cb; ++cr; ++r; ++g; ++b;
+ }
+ free(img->comps[0].data); img->comps[0].data = d0;
+ free(img->comps[1].data); img->comps[1].data = d1;
+ free(img->comps[2].data); img->comps[2].data = d2;
+
+}/* sycc444_to_rgb() */
+
+static void sycc422_to_rgb(opj_image_t *img)
+{
+ int *d0, *d1, *d2, *r, *g, *b;
+ const int *y, *cb, *cr;
+ int maxw, maxh, max, offset, upb;
+ int i, j;
+
+ i = img->comps[0].prec;
+ offset = 1<<(i - 1); upb = (1<<i)-1;
+
+ maxw = img->comps[0].w; maxh = img->comps[0].h;
+ max = maxw * maxh;
+
+ y = img->comps[0].data;
+ cb = img->comps[1].data;
+ cr = img->comps[2].data;
+
+ d0 = r = (int*)malloc(sizeof(int) * max);
+ d1 = g = (int*)malloc(sizeof(int) * max);
+ d2 = b = (int*)malloc(sizeof(int) * max);
+
+ for(i=0; i < maxh; ++i)
+ {
+ for(j=0; j < maxw; j += 2)
+ {
+ sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+ ++y; ++r; ++g; ++b;
+
+ sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+ ++y; ++r; ++g; ++b; ++cb; ++cr;
+ }
+ }
+ free(img->comps[0].data); img->comps[0].data = d0;
+ free(img->comps[1].data); img->comps[1].data = d1;
+ free(img->comps[2].data); img->comps[2].data = d2;
+
+ img->comps[1].w = maxw; img->comps[1].h = maxh;
+ img->comps[2].w = maxw; img->comps[2].h = maxh;
+ img->comps[1].dx = img->comps[0].dx;
+ img->comps[2].dx = img->comps[0].dx;
+ img->comps[1].dy = img->comps[0].dy;
+ img->comps[2].dy = img->comps[0].dy;
+
+}/* sycc422_to_rgb() */
+
+static void sycc420_to_rgb(opj_image_t *img)
+{
+ int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
+ const int *y, *cb, *cr, *ny;
+ int maxw, maxh, max, offset, upb;
+ int i, j;
+
+ i = img->comps[0].prec;
+ offset = 1<<(i - 1); upb = (1<<i)-1;
+
+ maxw = img->comps[0].w; maxh = img->comps[0].h;
+ max = maxw * maxh;
+
+ y = img->comps[0].data;
+ cb = img->comps[1].data;
+ cr = img->comps[2].data;
+
+ d0 = r = (int*)malloc(sizeof(int) * max);
+ d1 = g = (int*)malloc(sizeof(int) * max);
+ d2 = b = (int*)malloc(sizeof(int) * max);
+
+ for(i=0; i < maxh; i += 2)
+ {
+ ny = y + maxw;
+ nr = r + maxw; ng = g + maxw; nb = b + maxw;
+
+ for(j=0; j < maxw; j += 2)
+ {
+ sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+ ++y; ++r; ++g; ++b;
+
+ sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
+
+ ++y; ++r; ++g; ++b;
+
+ sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
+
+ ++ny; ++nr; ++ng; ++nb;
+
+ sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
+
+ ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
+ }
+ y += maxw; r += maxw; g += maxw; b += maxw;
+ }
+ free(img->comps[0].data); img->comps[0].data = d0;
+ free(img->comps[1].data); img->comps[1].data = d1;
+ free(img->comps[2].data); img->comps[2].data = d2;
+
+ img->comps[1].w = maxw; img->comps[1].h = maxh;
+ img->comps[2].w = maxw; img->comps[2].h = maxh;
+ img->comps[1].dx = img->comps[0].dx;
+ img->comps[2].dx = img->comps[0].dx;
+ img->comps[1].dy = img->comps[0].dy;
+ img->comps[2].dy = img->comps[0].dy;
+
+}/* sycc420_to_rgb() */
+
+void color_sycc_to_rgb(opj_image_t *img)
+{
+ if(img->numcomps < 3)
+ {
+ img->color_space = CLRSPC_GRAY;
+ return;
+ }
+
+ if((img->comps[0].dx == 1)
+ && (img->comps[1].dx == 2)
+ && (img->comps[2].dx == 2)
+ && (img->comps[0].dy == 1)
+ && (img->comps[1].dy == 2)
+ && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
+ {
+ sycc420_to_rgb(img);
+ }
+ else
+ if((img->comps[0].dx == 1)
+ && (img->comps[1].dx == 2)
+ && (img->comps[2].dx == 2)
+ && (img->comps[0].dy == 1)
+ && (img->comps[1].dy == 1)
+ && (img->comps[2].dy == 1))/* horizontal sub-sample only */
+ {
+ sycc422_to_rgb(img);
+ }
+ else
+ if((img->comps[0].dx == 1)
+ && (img->comps[1].dx == 1)
+ && (img->comps[2].dx == 1)
+ && (img->comps[0].dy == 1)
+ && (img->comps[1].dy == 1)
+ && (img->comps[2].dy == 1))/* no sub-sample */
+ {
+ sycc444_to_rgb(img);
+ }
+ else
+ {
+ fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
+ __FILE__,__LINE__);
+ return;
+ }
+ img->color_space = CLRSPC_SRGB;
+
+}/* color_sycc_to_rgb() */
+
+#if defined(HAVE_LIBLCMS2) || defined(HAVE_LIBLCMS1)
+#ifdef HAVE_LIBLCMS1
+/* Bob Friesenhahn proposed:*/
+#define cmsSigXYZData icSigXYZData
+#define cmsSigLabData icSigLabData
+#define cmsSigCmykData icSigCmykData
+#define cmsSigYCbCrData icSigYCbCrData
+#define cmsSigLuvData icSigLuvData
+#define cmsSigGrayData icSigGrayData
+#define cmsSigRgbData icSigRgbData
+#define cmsUInt32Number DWORD
+
+#define cmsColorSpaceSignature icColorSpaceSignature
+#define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
+
+#endif /* HAVE_LIBLCMS1 */
+
+void color_apply_icc_profile(opj_image_t *image)
+{
+ cmsHPROFILE in_prof, out_prof;
+ cmsHTRANSFORM transform;
+ cmsColorSpaceSignature in_space, out_space;
+ cmsUInt32Number intent, in_type, out_type, nr_samples;
+ int *r, *g, *b;
+ int prec, i, max, max_w, max_h;
+ OPJ_COLOR_SPACE oldspace;
+
+ in_prof =
+ cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
+
+ if(in_prof == NULL) return;
+
+ in_space = cmsGetPCS(in_prof);
+ out_space = cmsGetColorSpace(in_prof);
+ intent = cmsGetHeaderRenderingIntent(in_prof);
+
+
+ max_w = image->comps[0].w; max_h = image->comps[0].h;
+ prec = image->comps[0].prec;
+ oldspace = image->color_space;
+
+ if(out_space == cmsSigRgbData) /* enumCS 16 */
+ {
+ in_type = TYPE_RGB_16;
+ out_type = TYPE_RGB_16;
+ out_prof = cmsCreate_sRGBProfile();
+ image->color_space = CLRSPC_SRGB;
+ }
+ else
+ if(out_space == cmsSigGrayData) /* enumCS 17 */
+ {
+ in_type = TYPE_GRAY_8;
+ out_type = TYPE_RGB_8;
+ out_prof = cmsCreate_sRGBProfile();
+ image->color_space = CLRSPC_SRGB;
+ }
+ else
+ if(out_space == cmsSigYCbCrData) /* enumCS 18 */
+ {
+ in_type = TYPE_YCbCr_16;
+ out_type = TYPE_RGB_16;
+ out_prof = cmsCreate_sRGBProfile();
+ image->color_space = CLRSPC_SRGB;
+ }
+ else
+ {
+#ifdef DEBUG_PROFILE
+fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
+"output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
+__FILE__,__LINE__,out_space,
+(out_space>>24) & 0xff,(out_space>>16) & 0xff,
+(out_space>>8) & 0xff, out_space & 0xff);
+#endif
+ return;
+ }
+
+#ifdef DEBUG_PROFILE
+fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
+"\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
+max_w,max_h, (void*)in_prof,(void*)out_prof);
+
+fprintf(stderr,"\trender_intent (%u)\n\t"
+"color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
+" type: in(%u) out:(%u)\n",
+intent,
+in_space,
+(in_space>>24) & 0xff,(in_space>>16) & 0xff,
+(in_space>>8) & 0xff, in_space & 0xff,
+
+out_space,
+(out_space>>24) & 0xff,(out_space>>16) & 0xff,
+(out_space>>8) & 0xff, out_space & 0xff,
+
+in_type,out_type
+ );
+#endif /* DEBUG_PROFILE */
+
+ transform = cmsCreateTransform(in_prof, in_type,
+ out_prof, out_type, intent, 0);
+
+#ifdef HAVE_LIBLCMS2
+/* Possible for: LCMS_VERSION >= 2000 :*/
+ cmsCloseProfile(in_prof);
+ cmsCloseProfile(out_prof);
+#endif
+
+ if(transform == NULL)
+ {
+#ifdef DEBUG_PROFILE
+fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
+"ICC Profile ignored.\n",__FILE__,__LINE__);
+#endif
+ image->color_space = oldspace;
+#ifdef HAVE_LIBLCMS1
+ cmsCloseProfile(in_prof);
+ cmsCloseProfile(out_prof);
+#endif
+ return;
+ }
+
+ if(image->numcomps > 2)/* RGB, RGBA */
+ {
+ unsigned short *inbuf, *outbuf, *in, *out;
+ max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned short);
+ in = inbuf = (unsigned short*)malloc(nr_samples);
+ out = outbuf = (unsigned short*)malloc(nr_samples);
+
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+
+ for(i = 0; i < max; ++i)
+ {
+ *in++ = (unsigned short)*r++;
+ *in++ = (unsigned short)*g++;
+ *in++ = (unsigned short)*b++;
+ }
+
+ cmsDoTransform(transform, inbuf, outbuf, max);
+
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+
+ for(i = 0; i < max; ++i)
+ {
+ *r++ = (int)*out++;
+ *g++ = (int)*out++;
+ *b++ = (int)*out++;
+ }
+ free(inbuf); free(outbuf);
+ }
+ else /* GRAY, GRAYA */
+ {
+ unsigned char *in, *inbuf, *out, *outbuf;
+
+ max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned char);
+ in = inbuf = (unsigned char*)malloc(nr_samples);
+ out = outbuf = (unsigned char*)malloc(nr_samples);
+
+ image->comps = (opj_image_comp_t*)
+ realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
+
+ if(image->numcomps == 2)
+ image->comps[3] = image->comps[1];
+
+ image->comps[1] = image->comps[0];
+ image->comps[2] = image->comps[0];
+
+ image->comps[1].data = (int*)calloc(max, sizeof(int));
+ image->comps[2].data = (int*)calloc(max, sizeof(int));
+
+ image->numcomps += 2;
+
+ r = image->comps[0].data;
+
+ for(i = 0; i < max; ++i)
+ {
+ *in++ = (unsigned char)*r++;
+ }
+ cmsDoTransform(transform, inbuf, outbuf, max);
+
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+
+ for(i = 0; i < max; ++i)
+ {
+ *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
+ }
+ free(inbuf); free(outbuf);
+
+ }/* if(image->numcomps */
+
+ cmsDeleteTransform(transform);
+
+#ifdef HAVE_LIBLCMS1
+ cmsCloseProfile(in_prof);
+ cmsCloseProfile(out_prof);
+#endif
+}/* color_apply_icc_profile() */
+
+#endif /* HAVE_LIBLCMS2 || HAVE_LIBLCMS1 */
+
diff --git a/src/bin/common/color.h b/src/bin/common/color.h
new file mode 100644
index 00000000..26117b02
--- /dev/null
+++ b/src/bin/common/color.h
@@ -0,0 +1,38 @@
+/*
+ * 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 _OPJ_COLOR_H_
+#define _OPJ_COLOR_H_
+
+extern void color_sycc_to_rgb(opj_image_t *img);
+extern void color_apply_icc_profile(opj_image_t *image);
+
+#endif /* _OPJ_COLOR_H_ */
diff --git a/src/bin/common/format_defs.h b/src/bin/common/format_defs.h
new file mode 100644
index 00000000..e82986cc
--- /dev/null
+++ b/src/bin/common/format_defs.h
@@ -0,0 +1,49 @@
+/*
+ * 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 _OPJ_FORMAT_DEFS_H_
+#define _OPJ_FORMAT_DEFS_H_
+
+#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 PNG_DFMT 17
+#define RAWL_DFMT 18
+
+#endif /* _OPJ_FORMAT_DEFS_H_ */
diff --git a/src/bin/common/opj_getopt.c b/src/bin/common/opj_getopt.c
new file mode 100644
index 00000000..252d8359
--- /dev/null
+++ b/src/bin/common/opj_getopt.c
@@ -0,0 +1,254 @@
+/*
+ * 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[] = "@(#)opj_getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "opj_getopt.h"
+
+int opj_opterr = 1, /* if error message should be printed */
+ opj_optind = 1, /* index into parent argv vector */
+ opj_optopt, /* character checked for validity */
+ opj_optreset; /* reset getopt */
+ char *opj_optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+static char EMSG[]={""};
+
+/* As this class remembers its values from one Java call to the other, reset the values before each use */
+void reset_options_reading(void) {
+ opj_opterr = 1;
+ opj_optind = 1;
+}
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int opj_getopt(int nargc, char *const *nargv, const char *ostr) {
+# define __progname nargv[0]
+ static char *place = EMSG; /* option letter processing */
+ char *oli = NULL; /* option letter list index */
+
+ if (opj_optreset || !*place) { /* update scanning pointer */
+ opj_optreset = 0;
+ if (opj_optind >= nargc || *(place = nargv[opj_optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++opj_optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+ if ((opj_optopt = (int) *place++) == (int) ':' ||
+ !(oli = strchr(ostr, opj_optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (opj_optopt == (int) '-')
+ return (-1);
+ if (!*place)
+ ++opj_optind;
+ if (opj_opterr && *ostr != ':') {
+ fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, opj_optopt);
+ return (BADCH);
+ }
+ }
+ if (*++oli != ':') { /* don't need argument */
+ opj_optarg = NULL;
+ if (!*place)
+ ++opj_optind;
+ } else { /* need an argument */
+ if (*place) /* no white space */
+ opj_optarg = place;
+ else if (nargc <= ++opj_optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opj_opterr) {
+ fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, opj_optopt);
+ return (BADCH);
+ }
+ } else /* white space */
+ opj_optarg = nargv[opj_optind];
+ place = EMSG;
+ ++opj_optind;
+ }
+ return (opj_optopt); /* dump back option letter */
+}
+
+
+int opj_getopt_long(int argc, char * const argv[], const char *optstring,
+const opj_option_t *longopts, int totlen) {
+ static int lastidx,lastofs;
+ char *tmp;
+ int i,len;
+ char param = 1;
+
+again:
+ if (opj_optind >= argc || !argv[opj_optind] || *argv[opj_optind]!='-')
+ return -1;
+
+ if (argv[opj_optind][0]=='-' && argv[opj_optind][1]==0) {
+ if(opj_optind >= (argc - 1)){ /* no more input parameters */
+ param = 0;
+ }
+ else{ /* more input parameters */
+ if(argv[opj_optind + 1][0] == '-'){
+ param = 0; /* Missing parameter after '-' */
+ }
+ else{
+ param = 2;
+ }
+ }
+ }
+
+ if (param == 0) {
+ ++opj_optind;
+ return (BADCH);
+ }
+
+ if (argv[opj_optind][0]=='-') { /* long option */
+ char* arg=argv[opj_optind]+1;
+ const opj_option_t* o;
+ o=longopts;
+ len=sizeof(longopts[0]);
+
+ if (param > 1){
+ arg = argv[opj_optind+1];
+ opj_optind++;
+ }
+ else
+ arg = argv[opj_optind]+1;
+
+ if(strlen(arg)>1){
+ for (i=0;i<totlen;i=i+len,o++) {
+ if (!strcmp(o->name,arg)) { /* match */
+ if (o->has_arg == 0) {
+ if ((argv[opj_optind+1])&&(!(argv[opj_optind+1][0]=='-'))){
+ fprintf(stderr,"%s: option does not require an argument. Ignoring %s\n",arg,argv[opj_optind+1]);
+ ++opj_optind;
+ }
+ }else{
+ opj_optarg=argv[opj_optind+1];
+ if(opj_optarg){
+ if (opj_optarg[0] == '-'){ /* Has read next input parameter: No arg for current parameter */
+ if (opj_opterr) {
+ fprintf(stderr,"%s: option requires an argument\n",arg);
+ return (BADCH);
+ }
+ }
+ }
+ if (!opj_optarg && o->has_arg==1) { /* no argument there */
+ if (opj_opterr) {
+ fprintf(stderr,"%s: option requires an argument \n",arg);
+ return (BADCH);
+ }
+ }
+ ++opj_optind;
+ }
+ ++opj_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);
+ ++opj_optind;
+ return (BADCH);
+ }else{ /*Single character input parameter*/
+ if (*optstring==':') return ':';
+ if (lastidx!=opj_optind) {
+ lastidx=opj_optind; lastofs=0;
+ }
+ opj_optopt=argv[opj_optind][lastofs+1];
+ if ((tmp=strchr(optstring,opj_optopt))) {/*Found input parameter in list*/
+ if (*tmp==0) { /* apparently, we looked for \0, i.e. end of argument */
+ ++opj_optind;
+ goto again;
+ }
+ if (tmp[1]==':') { /* argument expected */
+ if (tmp[2]==':' || argv[opj_optind][lastofs+2]) { /* "-foo", return "oo" as opj_optarg */
+ if (!*(opj_optarg=argv[opj_optind]+lastofs+2)) opj_optarg=0;
+ goto found;
+ }
+ opj_optarg=argv[opj_optind+1];
+ if(opj_optarg){
+ if (opj_optarg[0] == '-'){ /* Has read next input parameter: No arg for current parameter */
+ if (opj_opterr) {
+ fprintf(stderr,"%s: option requires an argument\n",arg);
+ return (BADCH);
+ }
+ }
+ }
+ if (!opj_optarg) { /* missing argument */
+ if (opj_opterr) {
+ fprintf(stderr,"%s: option requires an argument\n",arg);
+ return (BADCH);
+ }
+ }
+ ++opj_optind;
+ }else {/*Argument not expected*/
+ ++lastofs;
+ return opj_optopt;
+ }
+found:
+ ++opj_optind;
+ return opj_optopt;
+ } else { /* not found */
+ fprintf(stderr,"Invalid option %s\n",arg);
+ ++opj_optind;
+ return (BADCH);
+ }/*end of not found*/
+
+ }/* end of single character*/
+ }/*end '-'*/
+ fprintf(stderr,"Invalid option\n");
+ ++opj_optind;
+ return (BADCH);;
+}/*end function*/
diff --git a/src/bin/common/opj_getopt.h b/src/bin/common/opj_getopt.h
new file mode 100644
index 00000000..e1f41a56
--- /dev/null
+++ b/src/bin/common/opj_getopt.h
@@ -0,0 +1,29 @@
+/* last review : october 29th, 2002 */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+typedef struct opj_option
+{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+}opj_option_t;
+
+#define NO_ARG 0
+#define REQ_ARG 1
+#define OPT_ARG 2
+
+extern int opj_opterr;
+extern int opj_optind;
+extern int opj_optopt;
+extern int opj_optreset;
+extern char *opj_optarg;
+
+extern int opj_getopt(int nargc, char *const *nargv, const char *ostr);
+extern int opj_getopt_long(int argc, char * const argv[], const char *optstring,
+ const opj_option_t *longopts, int totlen);
+extern void reset_options_reading(void);
+
+#endif /* _GETOPT_H_ */
diff --git a/src/bin/jp2/CMakeLists.txt b/src/bin/jp2/CMakeLists.txt
new file mode 100644
index 00000000..5e77765e
--- /dev/null
+++ b/src/bin/jp2/CMakeLists.txt
@@ -0,0 +1,113 @@
+# Build the demo app, small examples
+
+# First thing define the common source:
+set(common_SRCS
+ convert.c
+ index.c
+ ${OPENJPEG_SOURCE_DIR}/src/bin/common/color.c
+ ${OPENJPEG_SOURCE_DIR}/src/bin/common/opj_getopt.c
+ )
+
+# Headers file are located here:
+include_directories(
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2
+ ${LCMS_INCLUDE_DIRNAME}
+ ${OPENJPEG_SOURCE_DIR}/src/bin/common
+ ${Z_INCLUDE_DIRNAME}
+ ${PNG_INCLUDE_DIRNAME}
+ ${TIFF_INCLUDE_DIRNAME}
+ )
+
+if(WIN32)
+ if(BUILD_SHARED_LIBS)
+ add_definitions(-DOPJ_EXPORTS)
+ else()
+ add_definitions(-DOPJ_STATIC)
+ endif()
+endif()
+
+# Loop over all executables:
+foreach(exe j2k_to_image image_to_j2k j2k_dump)
+ add_executable(${exe} ${exe}.c ${common_SRCS})
+ target_link_libraries(${exe} ${OPENJPEG_LIBRARY_NAME}
+ ${PNG_LIBNAME} ${TIFF_LIBNAME} ${LCMS_LIBNAME}
+ )
+ # To support universal exe:
+ if(ZLIB_FOUND AND APPLE)
+ target_link_libraries(${exe} z)
+ ELSe(ZLIB_FOUND AND APPLE)
+ target_link_libraries(${exe} ${Z_LIBNAME})
+ endif()
+
+ # On unix you need to link to the math library:
+ if(UNIX)
+ target_link_libraries(${exe} m)
+ endif()
+ # Install exe
+ install(TARGETS ${exe}
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ )
+endforeach()
+
+# Install man pages
+install(
+ FILES ${OPENJPEG_SOURCE_DIR}/doc/man/man1/image_to_j2k.1
+ ${OPENJPEG_SOURCE_DIR}/doc/man/man1/j2k_dump.1
+ ${OPENJPEG_SOURCE_DIR}/doc/man/man1/j2k_to_image.1
+ DESTINATION ${OPENJPEG_INSTALL_MAN_DIR}/man1)
+#
+
+if(BUILD_JPWL)
+ add_executable(JPWL_j2k_to_image
+ j2k_to_image.c
+ ${common_SRCS}
+ )
+
+ set_property(
+ TARGET JPWL_j2k_to_image
+ APPEND PROPERTY COMPILE_DEFINITIONS USE_JPWL
+ )
+
+ target_link_libraries(JPWL_j2k_to_image ${OPENJPEG_LIBRARY_NAME}_JPWL
+ ${LCMS_LIBNAME} ${PNG_LIBNAME} ${TIFF_LIBNAME})
+
+ # To support universal exe:
+ if(ZLIB_FOUND AND APPLE)
+ target_link_libraries(JPWL_j2k_to_image z)
+ ELSe(ZLIB_FOUND AND APPLE)
+ target_link_libraries(JPWL_j2k_to_image ${Z_LIBNAME})
+ endif()
+
+ if(UNIX)
+ target_link_libraries(JPWL_j2k_to_image m)
+ endif()
+
+ add_executable(JPWL_image_to_j2k
+ image_to_j2k.c
+ ${common_SRCS}
+ )
+
+ set_property(
+ TARGET JPWL_image_to_j2k
+ APPEND PROPERTY COMPILE_DEFINITIONS USE_JPWL
+ )
+
+ target_link_libraries(JPWL_image_to_j2k ${OPENJPEG_LIBRARY_NAME}_JPWL
+ ${LCMS_LIBNAME} ${PNG_LIBNAME} ${TIFF_LIBNAME})
+
+ # To support universal exe:
+ if(ZLIB_FOUND AND APPLE)
+ target_link_libraries(JPWL_image_to_j2k z)
+ ELSe(ZLIB_FOUND AND APPLE)
+ target_link_libraries(JPWL_image_to_j2k ${Z_LIBNAME})
+ endif()
+
+ if(UNIX)
+ target_link_libraries(JPWL_image_to_j2k m)
+ endif()
+
+ install(TARGETS JPWL_image_to_j2k JPWL_j2k_to_image
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ )
+endif()
diff --git a/src/bin/jp2/Makefile.am b/src/bin/jp2/Makefile.am
new file mode 100644
index 00000000..17be3b88
--- /dev/null
+++ b/src/bin/jp2/Makefile.am
@@ -0,0 +1,118 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+bin_PROGRAMS = j2k_to_image image_to_j2k j2k_dump
+
+if WANT_JPWL
+bin_PROGRAMS += JPWL_j2k_to_image JPWL_image_to_j2k
+endif
+
+j2k_to_image_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/codec \
+-I$(top_builddir)/applications/codec \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+@PNG_CFLAGS@ \
+@TIFF_CFLAGS@ \
+@LCMS1_CFLAGS@ \
+@LCMS2_CFLAGS@
+j2k_to_image_CFLAGS =
+j2k_to_image_LDADD = $(top_builddir)/libopenjpeg/libopenjpeg.la @LCMS1_LIBS@ @LCMS2_LIBS@ @TIFF_LIBS@ @PNG_LIBS@ -lm
+j2k_to_image_SOURCES = \
+../common/color.c \
+../common/opj_getopt.c \
+convert.c \
+index.c \
+j2k_to_image.c \
+../common/color.h
+
+image_to_j2k_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/codec \
+-I$(top_builddir)/applications/codec \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+@PNG_CFLAGS@ \
+@TIFF_CFLAGS@
+image_to_j2k_CFLAGS =
+image_to_j2k_LDADD = $(top_builddir)/libopenjpeg/libopenjpeg.la @TIFF_LIBS@ @PNG_LIBS@ -lm
+image_to_j2k_SOURCES = \
+../common/opj_getopt.c \
+convert.c \
+index.c \
+image_to_j2k.c \
+convert.h \
+../common/format_defs.h \
+index.h
+
+j2k_dump_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/codec \
+-I$(top_builddir)/applications/codec \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg
+j2k_dump_CFLAGS =
+j2k_dump_LDADD = $(top_builddir)/libopenjpeg/libopenjpeg.la -lm
+j2k_dump_SOURCES = \
+../common/opj_getopt.c \
+index.c \
+j2k_dump.c \
+../common/opj_getopt.h \
+index.h
+
+JPWL_j2k_to_image_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-DUSE_JPWL \
+@TIFF_CFLAGS@ \
+@PNG_CFLAGS@ \
+@LCMS1_CFLAGS@ \
+@LCMS2_CFLAGS@
+JPWL_j2k_to_image_CFLAGS =
+JPWL_j2k_to_image_LDADD = $(top_builddir)/libopenjpeg/jpwl/libopenjpeg_JPWL.la @LCMS1_LIBS@ @LCMS2_LIBS@ @TIFF_LIBS@ @PNG_LIBS@
+JPWL_j2k_to_image_SOURCES = \
+../common/color.c \
+../common/opj_getopt.c \
+index.c \
+convert.c \
+j2k_to_image.c
+
+JPWL_image_to_j2k_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-DUSE_JPWL \
+@TIFF_CFLAGS@ \
+@PNG_CFLAGS@
+JPWL_image_to_j2k_CFLAGS =
+JPWL_image_to_j2k_LDADD = $(top_builddir)/libopenjpeg/jpwl/libopenjpeg_JPWL.la @TIFF_LIBS@ @PNG_LIBS@
+
+JPWL_image_to_j2k_SOURCES = \
+../common/opj_getopt.c \
+index.c \
+convert.c \
+image_to_j2k.c
+
+EXTRA_DIST = \
+CMakeLists.txt \
+windirent.h
+
+install-data-hook:
+ @echo -e " (B)\t$(bindir)/j2k_to_image$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/image_to_j2k$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/j2k_dump$(EXEEXT)" >> $(top_builddir)/report.txt
+if WANT_JPWL
+ @echo -e " (B)\t$(bindir)/JPWL_j2k_to_image$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/JPWL_image_to_j2k$(EXEEXT)" >> $(top_builddir)/report.txt
+endif
diff --git a/src/bin/jp2/README b/src/bin/jp2/README
new file mode 100644
index 00000000..80049980
--- /dev/null
+++ b/src/bin/jp2/README
@@ -0,0 +1,8 @@
+Simple codec compilation
+------------------------
+Once you've built the library, you might want to test it with a basic codec. To do this, go to the codec directory and either use the provided Makefile or use one of the following commands to build an encoder and decoder respectively:
+
+gcc index.c convert.c image_to_j2k.c -o image_to_j2k -lopenjpeg -I ../libopenjpeg/ -lm -ltiff
+gcc index.c convert.c j2k_to_image.c -o j2k_to_image -lopenjpeg -I ../libopenjpeg/ -lm -ltiff
+
+You should add '-L..' to those lines if you did not use the 'install' target when building the library. \ No newline at end of file
diff --git a/src/bin/jp2/convert.c b/src/bin/jp2/convert.c
new file mode 100644
index 00000000..59af469b
--- /dev/null
+++ b/src/bin/jp2/convert.c
@@ -0,0 +1,3621 @@
+/*
+ * 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 "opj_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef HAVE_LIBTIFF
+#include <tiffio.h>
+#endif /* HAVE_LIBTIFF */
+
+#ifdef HAVE_LIBPNG
+#include <zlib.h>
+#include <png.h>
+#endif /* HAVE_LIBPNG */
+
+#include "openjpeg.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;
+}
+
+/* -->> -->> -->> -->>
+
+ TGA IMAGE FORMAT
+
+ <<-- <<-- <<-- <<-- */
+
+#ifdef INFORMATION_ONLY
+/* TGA header definition. */
+struct tga_header
+{
+ unsigned char id_length; /* Image id field length */
+ unsigned char colour_map_type; /* Colour map type */
+ unsigned char image_type; /* Image type */
+ /*
+ ** Colour map specification
+ */
+ unsigned short colour_map_index; /* First entry index */
+ unsigned short colour_map_length; /* Colour map length */
+ unsigned char colour_map_entry_size; /* Colour map entry size */
+ /*
+ ** Image specification
+ */
+ unsigned short x_origin; /* x origin of image */
+ unsigned short y_origin; /* u origin of image */
+ unsigned short image_width; /* Image width */
+ unsigned short image_height; /* Image height */
+ unsigned char pixel_depth; /* Pixel depth */
+ unsigned char image_desc; /* Image descriptor */
+};
+#endif /* INFORMATION_ONLY */
+
+static unsigned short get_ushort(unsigned short val) {
+
+#ifdef WORDS_BIGENDIAN
+ return( ((val & 0xff) << 8) + (val >> 8) );
+#else
+ return( val );
+#endif
+
+}
+
+#define TGA_HEADER_SIZE 18
+
+static int tga_readheader(FILE *fp, unsigned int *bits_per_pixel,
+ unsigned int *width, unsigned int *height, int *flip_image)
+{
+ int palette_size;
+ unsigned char *tga ;
+ unsigned char id_len, cmap_type, image_type;
+ unsigned char pixel_depth, image_desc;
+ unsigned short cmap_index, cmap_len, cmap_entry_size;
+ unsigned short x_origin, y_origin, image_w, image_h;
+
+ if (!bits_per_pixel || !width || !height || !flip_image)
+ return 0;
+ tga = (unsigned char*)malloc(18);
+
+ if ( fread(tga, TGA_HEADER_SIZE, 1, fp) != 1 )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0 ;
+ }
+ id_len = (unsigned char)tga[0];
+ cmap_type = (unsigned char)tga[1];
+ image_type = (unsigned char)tga[2];
+ cmap_index = get_ushort(*(unsigned short*)(&tga[3]));
+ cmap_len = get_ushort(*(unsigned short*)(&tga[5]));
+ cmap_entry_size = (unsigned char)tga[7];
+
+
+ x_origin = get_ushort(*(unsigned short*)(&tga[8]));
+ y_origin = get_ushort(*(unsigned short*)(&tga[10]));
+ image_w = get_ushort(*(unsigned short*)(&tga[12]));
+ image_h = get_ushort(*(unsigned short*)(&tga[14]));
+ pixel_depth = (unsigned char)tga[16];
+ image_desc = (unsigned char)tga[17];
+
+ free(tga);
+
+ *bits_per_pixel = (unsigned int)pixel_depth;
+ *width = (unsigned int)image_w;
+ *height = (unsigned int)image_h;
+
+ /* Ignore tga identifier, if present ... */
+ if (id_len)
+ {
+ unsigned char *id = (unsigned char *) malloc(id_len);
+ if ( !fread(id, id_len, 1, fp) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ free(id);
+ return 0 ;
+ }
+ free(id);
+ }
+
+ /* Test for compressed formats ... not yet supported ...
+ // Note :- 9 - RLE encoded palettized.
+ // 10 - RLE encoded RGB. */
+ if (image_type > 8)
+ {
+ fprintf(stderr, "Sorry, compressed tga files are not currently supported.\n");
+ return 0 ;
+ }
+
+ *flip_image = !(image_desc & 32);
+
+ /* Palettized formats are not yet supported, skip over the palette, if present ... */
+ palette_size = cmap_len * (cmap_entry_size/8);
+
+ if (palette_size>0)
+ {
+ fprintf(stderr, "File contains a palette - not yet supported.");
+ fseek(fp, palette_size, SEEK_CUR);
+ }
+ return 1;
+}
+
+#if WORDS_BIGENDIAN == 1
+
+static inline int16_t swap16(int16_t x)
+{
+ return((((u_int16_t)x & 0x00ffU) << 8) |
+ (((u_int16_t)x & 0xff00U) >> 8));
+}
+
+#endif
+
+static int tga_writeheader(FILE *fp, int bits_per_pixel, int width, int height,
+ opj_bool flip_image)
+{
+ unsigned short image_w, image_h, us0;
+ unsigned char uc0, image_type;
+ unsigned char pixel_depth, image_desc;
+
+ if (!bits_per_pixel || !width || !height)
+ return 0;
+
+ pixel_depth = 0;
+
+ if ( bits_per_pixel < 256 )
+ pixel_depth = (unsigned char)bits_per_pixel;
+ else{
+ fprintf(stderr,"ERROR: Wrong bits per pixel inside tga_header");
+ return 0;
+ }
+ uc0 = 0;
+
+ if(fwrite(&uc0, 1, 1, fp) != 1) goto fails; /* id_length */
+ if(fwrite(&uc0, 1, 1, fp) != 1) goto fails; /* colour_map_type */
+
+ image_type = 2; /* Uncompressed. */
+ if(fwrite(&image_type, 1, 1, fp) != 1) goto fails;
+
+ us0 = 0;
+ if(fwrite(&us0, 2, 1, fp) != 1) goto fails; /* colour_map_index */
+ if(fwrite(&us0, 2, 1, fp) != 1) goto fails; /* colour_map_length */
+ if(fwrite(&uc0, 1, 1, fp) != 1) goto fails; /* colour_map_entry_size */
+
+ if(fwrite(&us0, 2, 1, fp) != 1) goto fails; /* x_origin */
+ if(fwrite(&us0, 2, 1, fp) != 1) goto fails; /* y_origin */
+
+ image_w = (unsigned short)width;
+ image_h = (unsigned short) height;
+
+#if WORDS_BIGENDIAN == 0
+ if(fwrite(&image_w, 2, 1, fp) != 1) goto fails;
+ if(fwrite(&image_h, 2, 1, fp) != 1) goto fails;
+#else
+ image_w = swap16(image_w);
+ image_h = swap16(image_h);
+ if(fwrite(&image_w, 2, 1, fp) != 1) goto fails;
+ if(fwrite(&image_h, 2, 1, fp) != 1) goto fails;
+#endif
+
+ if(fwrite(&pixel_depth, 1, 1, fp) != 1) goto fails;
+
+ image_desc = 8; /* 8 bits per component. */
+
+ if (flip_image)
+ image_desc |= 32;
+ if(fwrite(&image_desc, 1, 1, fp) != 1) goto fails;
+
+ return 1;
+
+fails:
+ fputs("\nwrite_tgaheader: write ERROR\n", stderr);
+ return 0;
+}
+
+opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters) {
+ FILE *f;
+ opj_image_t *image;
+ unsigned int image_width, image_height, pixel_bit_depth;
+ unsigned int x, y;
+ int flip_image=0;
+ opj_image_cmptparm_t cmptparm[4]; /* maximum 4 components */
+ int numcomps;
+ OPJ_COLOR_SPACE color_space;
+ opj_bool mono ;
+ opj_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;x<image_width;x++)
+ {
+ unsigned char r,g,b;
+
+ if( !fread(&b, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ if ( !fread(&g, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ if ( !fread(&r, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+
+ image->comps[0].data[index]=r;
+ image->comps[1].data[index]=g;
+ image->comps[2].data[index]=b;
+ index++;
+ }
+ }
+ else if (numcomps==4)
+ {
+ for (x=0;x<image_width;x++)
+ {
+ unsigned char r,g,b,a;
+ if ( !fread(&b, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ if ( !fread(&g, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ if ( !fread(&r, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ if ( !fread(&a, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+
+ image->comps[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;
+ opj_bool write_alpha;
+ int i, adjustR, adjustG, adjustB;
+ unsigned int alpha_channel;
+ float r,g,b,a;
+ unsigned char value;
+ float scale;
+ FILE *fdest;
+ size_t res;
+
+ 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, OPJ_TRUE))
+ return 1;
+
+ alpha_channel = image->numcomps-1;
+
+ scale = 255.0f / (float)((1<<image->comps[0].prec)-1);
+
+ adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+ adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+ adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ for (y=0; y < height; y++) {
+ unsigned int index=y*width;
+
+ for (x=0; x < width; x++, index++) {
+ r = (float)(image->comps[0].data[index] + adjustR);
+
+ if (image->numcomps>2) {
+ g = (float)(image->comps[1].data[index] + adjustG);
+ b = (float)(image->comps[2].data[index] + adjustB);
+ }
+ else {/* Greyscale ... */
+ g = r;
+ b = r;
+ }
+
+ /* TGA format writes BGR ... */
+ value = (unsigned char)(b*scale);
+ res = fwrite(&value,1,1,fdest);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+
+ value = (unsigned char)(g*scale);
+ res = fwrite(&value,1,1,fdest);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+
+ value = (unsigned char)(r*scale);
+ res = fwrite(&value,1,1,fdest);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+
+ if (write_alpha) {
+ a = (float)(image->comps[alpha_channel].data[index]);
+ value = (unsigned char)(a*scale);
+ res = fwrite(&value,1,1,fdest);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* -->> -->> -->> -->>
+
+ BMP IMAGE FORMAT
+
+ <<-- <<-- <<-- <<-- */
+
+/* WORD defines a two byte word */
+typedef unsigned short int WORD;
+
+/* DWORD defines a four byte word */
+typedef unsigned 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;
+ int has_color;
+ DWORD W, H;
+
+ IN = fopen(filename, "rb");
+ if (!IN)
+ {
+ fprintf(stderr, "Failed to open %s for reading !!\n", filename);
+ return NULL;
+ }
+
+ 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");
+ fclose(IN);
+ return NULL;
+ }
+ /* 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;
+
+ if(Info_h.biSize != 40)
+ {
+ fprintf(stderr,"Error, unknown BMP header size %d\n", Info_h.biSize);
+ fclose(IN);
+ return NULL;
+ }
+ 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));
+
+ if ( fread(RGB, sizeof(unsigned char), (3 * W + PAD) * H, IN) != (3 * W + PAD) * H )
+ {
+ free(RGB);
+ opj_image_destroy(image);
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return NULL;
+ }
+
+ 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);
+ }/* if (Info_h.biBitCount == 24) */
+ else
+ if (Info_h.biBitCount == 8 && Info_h.biCompression == 0)/*RGB */
+ {
+ if(Info_h.biClrUsed == 0) Info_h.biClrUsed = 256;
+ else
+ if(Info_h.biClrUsed > 256) Info_h.biClrUsed = 256;
+
+ 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));
+
+ has_color = 0;
+ for (j = 0; j < Info_h.biClrUsed; j++)
+ {
+ table_B[j] = (unsigned char)getc(IN);
+ table_G[j] = (unsigned char)getc(IN);
+ table_R[j] = (unsigned char)getc(IN);
+ getc(IN);
+ has_color +=
+ !(table_R[j] == table_G[j] && table_R[j] == table_B[j]);
+ }
+ if(has_color) 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);
+ free(table_R); free(table_G); free(table_B);
+ 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));
+
+ if ( fread(RGB, sizeof(unsigned char), W * H, IN) != W * H )
+ {
+ free(table_R);
+ free(table_G);
+ free(table_B);
+ free(RGB);
+ opj_image_destroy(image);
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return NULL;
+ }
+ 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);
+ }/* RGB8 */
+ else
+ if (Info_h.biBitCount == 8 && Info_h.biCompression == 1)/*RLE8*/
+ {
+ unsigned char *pix, *beyond;
+ int *gray, *red, *green, *blue;
+ unsigned int x, y, max;
+ int i, c, c1;
+ unsigned char uc;
+
+ if (Info_h.biClrUsed == 0)
+ Info_h.biClrUsed = 256;
+ else if (Info_h.biClrUsed > 256)
+ Info_h.biClrUsed = 256;
+
+ 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));
+
+ has_color = 0;
+ for (j = 0; j < Info_h.biClrUsed; j++)
+ {
+ table_B[j] = (unsigned char)getc(IN);
+ table_G[j] = (unsigned char)getc(IN);
+ table_R[j] = (unsigned char)getc(IN);
+ getc(IN);
+ has_color += !(table_R[j] == table_G[j] && table_R[j] == table_B[j]);
+ }
+
+ if (has_color)
+ 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);
+ free(table_R);
+ free(table_G);
+ free(table_B);
+ 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;
+ RGB = (unsigned char *) calloc(1, W * H * sizeof(unsigned char));
+ beyond = RGB + W * H;
+ pix = beyond - W;
+ x = y = 0;
+
+ while (y < H)
+ {
+ c = getc(IN);
+
+ if (c)
+ {
+ c1 = getc(IN);
+
+ for (i = 0; i < c && x < W && pix < beyond; i++, x++, pix++)
+ *pix = (unsigned char)c1;
+ }
+ else
+ {
+ c = getc(IN);
+
+ if (c == 0x00) /* EOL */
+ {
+ x = 0;
+ ++y;
+ pix = RGB + x + (H - y - 1) * W;
+ }
+ else if (c == 0x01) /* EOP */
+ break;
+ else if (c == 0x02) /* MOVE by dxdy */
+ {
+ c = getc(IN);
+ x += c;
+ c = getc(IN);
+ y += c;
+ pix = RGB + (H - y - 1) * W + x;
+ }
+ else /* 03 .. 255 */
+ {
+ i = 0;
+ for (; i < c && x < W && pix < beyond; i++, x++, pix++)
+ {
+ c1 = getc(IN);
+ *pix = (unsigned char)c1;
+ }
+ if (c & 1) /* skip padding byte */
+ getc(IN);
+ }
+ }
+ }/* while() */
+
+ if (gray_scale)
+ {
+ gray = image->comps[0].data;
+ pix = RGB;
+ max = W * H;
+
+ while (max--)
+ {
+ uc = *pix++;
+
+ *gray++ = table_R[uc];
+ }
+ }
+ else
+ {
+ /*int *red, *green, *blue;*/
+
+ red = image->comps[0].data;
+ green = image->comps[1].data;
+ blue = image->comps[2].data;
+ pix = RGB;
+ max = W * H;
+
+ while (max--)
+ {
+ uc = *pix++;
+
+ *red++ = table_R[uc];
+ *green++ = table_G[uc];
+ *blue++ = table_B[uc];
+ }
+ }
+ free(RGB);
+ free(table_R);
+ free(table_G);
+ free(table_B);
+ }/* RLE8 */
+ 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->comps[0].prec < 8) {
+ fprintf(stderr, "Unsupported number of components: %d\n", image->comps[0].prec);
+ return 1;
+ }
+ 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);
+ r = ((r >> adjustR)+((r >> (adjustR-1))%2));
+ if(r > 255) r = 255; else if(r < 0) r = 0;
+ rc = (unsigned char)r;
+
+ 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);
+ g = ((g >> adjustG)+((g >> (adjustG-1))%2));
+ if(g > 255) g = 255; else if(g < 0) g = 0;
+ gc = (unsigned char)g;
+
+ 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);
+ b = ((b >> adjustB)+((b >> (adjustB-1))%2));
+ if(b > 255) b = 255; else if(b < 0) b = 0;
+ bc = (unsigned char)b;
+
+ 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);
+ }else
+ adjustR = 0;
+
+ for (i = 0; i < 256; i++) {
+ fprintf(fdest, "%c%c%c%c", i, i, i, 0);
+ }
+
+ for (i = 0; i < w * h; i++) {
+ 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);
+ r = ((r >> adjustR)+((r >> (adjustR-1))%2));
+ if(r > 255) r = 255; else if(r < 0) r = 0;
+
+ fprintf(fdest, "%c", (unsigned char)r);
+
+ 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
+
+<<-- <<-- <<-- <<-- */
+
+
+static unsigned char readuchar(FILE * f)
+{
+ unsigned char c1;
+ if ( !fread(&c1, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ return c1;
+}
+
+static unsigned short readushort(FILE * f, int bigendian)
+{
+ unsigned char c1, c2;
+ if ( !fread(&c1, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ if ( !fread(&c2, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ if (bigendian)
+ return (c1 << 8) + c2;
+ else
+ return (c2 << 8) + c1;
+}
+
+static unsigned int readuint(FILE * f, int bigendian)
+{
+ unsigned char c1, c2, c3, c4;
+ if ( !fread(&c1, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ if ( !fread(&c2, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ if ( !fread(&c3, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ if ( !fread(&c4, 1, 1, f) )
+ {
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ return 0;
+ }
+ 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;
+ int adjustS, ushift, dshift, force8;
+
+ 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);
+ if( fscanf(f, "PG%[ \t]%c%c%[ \t+-]%d%[ \t]%d%[ \t]%d",temp,&endian1,&endian2,signtmp,&prec,temp,&w,temp,&h) != 9){
+ fprintf(stderr, "ERROR: Failed to read the right number of element from the fscanf() function!\n");
+ return NULL;
+ }
+
+ 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;
+ }
+ if(prec < 8)
+ {
+ force8 = 1;
+ ushift = 8 - prec; dshift = prec - ushift;
+ if(cmptparm.sgnd) adjustS = (1<<(prec - 1)); else adjustS = 0;
+ cmptparm.sgnd = 0;
+ prec = 8;
+ }
+ else ushift = dshift = force8 = adjustS = 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(force8)
+ {
+ v = readuchar(f) + adjustS;
+ v = (v<<ushift) + (v>>dshift);
+ comp->data[i] = (unsigned char)v;
+
+ if(v > max) max = v;
+
+ continue;
+ }
+ 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;
+ size_t res;
+ 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));
+ res = fwrite(&byte, 1, 1, fdest);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", name);
+ return 1;
+ }
+ }
+ }
+ fclose(fdest);
+ }
+
+ return 0;
+}
+
+/* -->> -->> -->> -->>
+
+PNM IMAGE FORMAT
+
+<<-- <<-- <<-- <<-- */
+
+struct pnm_header
+{
+ int width, height, maxval, depth, format;
+ char rgb, rgba, gray, graya, bw;
+ char ok;
+};
+
+static char *skip_white(char *s)
+{
+ while(*s)
+ {
+ if(*s == '\n' || *s == '\r') return NULL;
+ if(isspace(*s)) { ++s; continue; }
+ return s;
+ }
+ return NULL;
+}
+
+static char *skip_int(char *start, int *out_n)
+{
+ char *s;
+ char c;
+
+ *out_n = 0; s = start;
+
+ s = skip_white(start);
+ if(s == NULL) return NULL;
+ start = s;
+
+ while(*s)
+ {
+ if( !isdigit(*s)) break;
+ ++s;
+ }
+ c = *s; *s = 0; *out_n = atoi(start); *s = c;
+ return s;
+}
+
+static char *skip_idf(char *start, char out_idf[256])
+{
+ char *s;
+ char c;
+
+ s = skip_white(start);
+ if(s == NULL) return NULL;
+ start = s;
+
+ while(*s)
+ {
+ if(isalpha(*s) || *s == '_') { ++s; continue; }
+ break;
+ }
+ c = *s; *s = 0; strncpy(out_idf, start, 255); *s = c;
+ return s;
+}
+
+static void read_pnm_header(FILE *reader, struct pnm_header *ph)
+{
+ char *s;
+ int format, have_wh, end, ttype;
+ char idf[256], type[256];
+ char line[256];
+
+ if (fgets(line, 250, reader) == NULL)
+ {
+ fprintf(stderr,"\nWARNING: fgets return a NULL value");
+ return;
+ }
+
+ if(line[0] != 'P')
+ {
+ fprintf(stderr,"read_pnm_header:PNM:magic P missing\n"); return;
+ }
+ format = atoi(line + 1);
+ if(format < 1 || format > 7)
+ {
+ fprintf(stderr,"read_pnm_header:magic format %d invalid\n", format);
+ return;
+ }
+ ph->format = format;
+ ttype = end = have_wh = 0;
+
+ while(fgets(line, 250, reader))
+ {
+ if(*line == '#') continue;
+
+ s = line;
+
+ if(format == 7)
+ {
+ s = skip_idf(s, idf);
+
+ if(s == NULL || *s == 0) return;
+
+ if(strcmp(idf, "ENDHDR") == 0)
+ {
+ end = 1; break;
+ }
+ if(strcmp(idf, "WIDTH") == 0)
+ {
+ s = skip_int(s, &ph->width);
+ if(s == NULL || *s == 0) return;
+
+ continue;
+ }
+ if(strcmp(idf, "HEIGHT") == 0)
+ {
+ s = skip_int(s, &ph->height);
+ if(s == NULL || *s == 0) return;
+
+ continue;
+ }
+ if(strcmp(idf, "DEPTH") == 0)
+ {
+ s = skip_int(s, &ph->depth);
+ if(s == NULL || *s == 0) return;
+
+ continue;
+ }
+ if(strcmp(idf, "MAXVAL") == 0)
+ {
+ s = skip_int(s, &ph->maxval);
+ if(s == NULL || *s == 0) return;
+
+ continue;
+ }
+ if(strcmp(idf, "TUPLTYPE") == 0)
+ {
+ s = skip_idf(s, type);
+ if(s == NULL || *s == 0) return;
+
+ if(strcmp(type, "BLACKANDWHITE") == 0)
+ {
+ ph->bw = 1; ttype = 1; continue;
+ }
+ if(strcmp(type, "GRAYSCALE") == 0)
+ {
+ ph->gray = 1; ttype = 1; continue;
+ }
+ if(strcmp(type, "GRAYSCALE_ALPHA") == 0)
+ {
+ ph->graya = 1; ttype = 1; continue;
+ }
+ if(strcmp(type, "RGB") == 0)
+ {
+ ph->rgb = 1; ttype = 1; continue;
+ }
+ if(strcmp(type, "RGB_ALPHA") == 0)
+ {
+ ph->rgba = 1; ttype = 1; continue;
+ }
+ fprintf(stderr,"read_pnm_header:unknown P7 TUPLTYPE %s\n",type);
+ return;
+ }
+ fprintf(stderr,"read_pnm_header:unknown P7 idf %s\n",idf);
+ return;
+ } /* if(format == 7) */
+
+ if( !have_wh)
+ {
+ s = skip_int(s, &ph->width);
+
+ s = skip_int(s, &ph->height);
+
+ have_wh = 1;
+
+ if(format == 1 || format == 4) break;
+
+ continue;
+ }
+ if(format == 2 || format == 3 || format == 5 || format == 6)
+ {
+/* P2, P3, P5, P6: */
+ s = skip_int(s, &ph->maxval);
+
+ if(ph->maxval > 65535) return;
+ }
+ break;
+ }/* while(fgets( ) */
+ if(format == 2 || format == 3 || format > 4)
+ {
+ if(ph->maxval < 1 || ph->maxval > 65535) return;
+ }
+ if(ph->width < 1 || ph->height < 1) return;
+
+ if(format == 7)
+ {
+ if(!end)
+ {
+ fprintf(stderr,"read_pnm_header:P7 without ENDHDR\n"); return;
+ }
+ if(ph->depth < 1 || ph->depth > 4) return;
+
+ if(ph->width && ph->height && ph->depth & ph->maxval && ttype)
+ ph->ok = 1;
+ }
+ else
+ {
+ if(format != 1 && format != 4)
+ {
+ if(ph->width && ph->height && ph->maxval) ph->ok = 1;
+ }
+ else
+ {
+ if(ph->width && ph->height) ph->ok = 1;
+ ph->maxval = 255;
+ }
+ }
+}
+
+static int has_prec(int val)
+{
+ if(val < 2) return 1;
+ if(val < 4) return 2;
+ if(val < 8) return 3;
+ if(val < 16) return 4;
+ if(val < 32) return 5;
+ if(val < 64) return 6;
+ if(val < 128) return 7;
+ if(val < 256) return 8;
+ if(val < 512) return 9;
+ if(val < 1024) return 10;
+ if(val < 2048) return 11;
+ if(val < 4096) return 12;
+ if(val < 8192) return 13;
+ if(val < 16384) return 14;
+ if(val < 32768) return 15;
+ return 16;
+}
+
+opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters) {
+ int subsampling_dx = parameters->subsampling_dx;
+ int subsampling_dy = parameters->subsampling_dy;
+
+ FILE *fp = NULL;
+ int i, compno, numcomps, w, h, prec, format;
+ OPJ_COLOR_SPACE color_space;
+ opj_image_cmptparm_t cmptparm[4]; /* RGBA: max. 4 components */
+ opj_image_t * image = NULL;
+ struct pnm_header header_info;
+
+ if((fp = fopen(filename, "rb")) == NULL)
+ {
+ fprintf(stderr, "pnmtoimage:Failed to open %s for reading!\n",filename);
+ return NULL;
+ }
+ memset(&header_info, 0, sizeof(struct pnm_header));
+
+ read_pnm_header(fp, &header_info);
+
+ if(!header_info.ok) { fclose(fp); return NULL; }
+
+ format = header_info.format;
+
+ switch(format)
+ {
+ case 1: /* ascii bitmap */
+ case 4: /* raw bitmap */
+ numcomps = 1;
+ break;
+
+ case 2: /* ascii greymap */
+ case 5: /* raw greymap */
+ numcomps = 1;
+ break;
+
+ case 3: /* ascii pixmap */
+ case 6: /* raw pixmap */
+ numcomps = 3;
+ break;
+
+ case 7: /* arbitrary map */
+ numcomps = header_info.depth;
+ break;
+
+ default: fclose(fp); return NULL;
+ }
+ if(numcomps < 3)
+ color_space = CLRSPC_GRAY;/* GRAY, GRAYA */
+ else
+ color_space = CLRSPC_SRGB;/* RGB, RGBA */
+
+ prec = has_prec(header_info.maxval);
+
+ if(prec < 8) prec = 8;
+
+ w = header_info.width;
+ h = header_info.height;
+ subsampling_dx = parameters->subsampling_dx;
+ subsampling_dy = parameters->subsampling_dy;
+
+ memset(&cmptparm[0], 0, numcomps * sizeof(opj_image_cmptparm_t));
+
+ for(i = 0; i < numcomps; i++)
+ {
+ cmptparm[i].prec = prec;
+ cmptparm[i].bpp = prec;
+ cmptparm[i].sgnd = 0;
+ cmptparm[i].dx = subsampling_dx;
+ cmptparm[i].dy = subsampling_dy;
+ cmptparm[i].w = w;
+ cmptparm[i].h = h;
+ }
+ image = opj_image_create(numcomps, &cmptparm[0], color_space);
+
+ if(!image) { fclose(fp); 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((format == 2) || (format == 3)) /* ascii pixmap */
+ {
+ unsigned int index;
+
+ for (i = 0; i < w * h; i++)
+ {
+ for(compno = 0; compno < numcomps; compno++)
+ {
+ index = 0;
+ if (fscanf(fp, "%u", &index) != 1)
+ fprintf(stderr, "\nWARNING: fscanf return a number of element different from the expected.\n");
+
+ image->comps[compno].data[i] = (index * 255)/header_info.maxval;
+ }
+ }
+ }
+ else
+ if((format == 5)
+ || (format == 6)
+ ||((format == 7)
+ && ( header_info.gray || header_info.graya
+ || header_info.rgb || header_info.rgba)))/* binary pixmap */
+ {
+ unsigned char c0, c1, one;
+
+ one = (prec < 9);
+
+ for (i = 0; i < w * h; i++)
+ {
+ for(compno = 0; compno < numcomps; compno++)
+ {
+ if ( !fread(&c0, 1, 1, fp) )
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ if(one)
+ {
+ image->comps[compno].data[i] = c0;
+ }
+ else
+ {
+ if ( !fread(&c1, 1, 1, fp) )
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+/* netpbm: */
+ image->comps[compno].data[i] = ((c0<<8) | c1);
+ }
+ }
+ }
+ }
+ else
+ if(format == 1) /* ascii bitmap */
+ {
+ for (i = 0; i < w * h; i++)
+ {
+ unsigned int index;
+
+ if ( fscanf(fp, "%u", &index) != 1)
+ fprintf(stderr, "\nWARNING: fscanf return a number of element different from the expected.\n");
+
+ image->comps[0].data[i] = (index?0:255);
+ }
+ }
+ else
+ if(format == 4)
+ {
+ int x, y, bit;
+ unsigned char uc;
+
+ i = 0;
+ for(y = 0; y < h; ++y)
+ {
+ bit = -1; uc = 0;
+
+ for(x = 0; x < w; ++x)
+ {
+ if(bit == -1)
+ {
+ bit = 7;
+ uc = (unsigned char)getc(fp);
+ }
+ image->comps[0].data[i] = (((uc>>bit) & 1)?0:255);
+ --bit; ++i;
+ }
+ }
+ }
+ else
+ if((format == 7 && header_info.bw)) /*MONO*/
+ {
+ unsigned char uc;
+
+ for(i = 0; i < w * h; ++i)
+ {
+ if ( !fread(&uc, 1, 1, fp) )
+ fprintf(stderr, "\nError: fread return a number of element different from the expected.\n");
+ image->comps[0].data[i] = (uc & 1)?0:255;
+ }
+ }
+ fclose(fp);
+
+ return image;
+}/* pnmtoimage() */
+
+int imagetopnm(opj_image_t * image, const char *outfile)
+{
+ int *red, *green, *blue, *alpha;
+ int wr, hr, max;
+ int i, compno, ncomp;
+ int adjustR, adjustG, adjustB, adjustA;
+ int fails, two, want_gray, has_alpha, triple;
+ int prec, v;
+ FILE *fdest = NULL;
+ const char *tmp = outfile;
+ char *destname;
+ alpha = NULL;
+ if((prec = image->comps[0].prec) > 16)
+ {
+ fprintf(stderr,"%s:%d:imagetopnm\n\tprecision %d is larger than 16"
+ "\n\t: refused.\n",__FILE__,__LINE__,prec);
+ return 1;
+ }
+ two = has_alpha = 0; fails = 1;
+ ncomp = image->numcomps;
+
+ while (*tmp) ++tmp; tmp -= 2;
+ want_gray = (*tmp == 'g' || *tmp == 'G');
+ ncomp = image->numcomps;
+
+ if(want_gray) ncomp = 1;
+
+ if (ncomp == 2 /* GRAYA */
+ || (ncomp > 2 /* RGB, RGBA */
+ && 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
+ ))
+ {
+ fdest = fopen(outfile, "wb");
+
+ if (!fdest)
+ {
+ fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
+ return fails;
+ }
+ two = (prec > 8);
+ triple = (ncomp > 2);
+ wr = image->comps[0].w; hr = image->comps[0].h;
+ max = (1<<prec) - 1; has_alpha = (ncomp == 4 || ncomp == 2);
+
+ red = image->comps[0].data;
+
+ if(triple)
+ {
+ green = image->comps[1].data;
+ blue = image->comps[2].data;
+ }
+ else green = blue = NULL;
+
+ if(has_alpha)
+ {
+ const char *tt = (triple?"RGB_ALPHA":"GRAYSCALE_ALPHA");
+
+ fprintf(fdest, "P7\n# OpenJPEG-%s\nWIDTH %d\nHEIGHT %d\nDEPTH %d\n"
+ "MAXVAL %d\nTUPLTYPE %s\nENDHDR\n", opj_version(),
+ wr, hr, ncomp, max, tt);
+ alpha = image->comps[ncomp - 1].data;
+ adjustA = (image->comps[ncomp - 1].sgnd ?
+ 1 << (image->comps[ncomp - 1].prec - 1) : 0);
+ }
+ else
+ {
+ fprintf(fdest, "P6\n# OpenJPEG-%s\n%d %d\n%d\n",
+ opj_version(), wr, hr, max);
+ adjustA = 0;
+ }
+ adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ if(triple)
+ {
+ adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+ adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+ }
+ else adjustG = adjustB = 0;
+
+ for(i = 0; i < wr * hr; ++i)
+ {
+ if(two)
+ {
+ v = *red + adjustR; ++red;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+
+ if(triple)
+ {
+ v = *green + adjustG; ++green;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+
+ v = *blue + adjustB; ++blue;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+
+ }/* if(triple) */
+
+ if(has_alpha)
+ {
+ v = *alpha + adjustA; ++alpha;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+ }
+ continue;
+
+ } /* if(two) */
+
+/* prec <= 8: */
+
+ fprintf(fdest, "%c", (unsigned char)*red++);
+ if(triple)
+ fprintf(fdest, "%c%c",(unsigned char)*green++, (unsigned char)*blue++);
+
+ if(has_alpha)
+ fprintf(fdest, "%c", (unsigned char)*alpha++);
+
+ } /* for(i */
+
+ fclose(fdest); return 0;
+ }
+
+/* YUV or MONO: */
+
+ if (image->numcomps > ncomp)
+ {
+ fprintf(stderr,"WARNING -> [PGM file] Only the first component\n");
+ fprintf(stderr," is written to the file\n");
+ }
+ destname = (char*)malloc(strlen(outfile) + 8);
+
+ for (compno = 0; compno < ncomp; compno++)
+ {
+ if (ncomp > 1)
+ sprintf(destname, "%d.%s", compno, outfile);
+ else
+ sprintf(destname, "%s", outfile);
+
+ fdest = fopen(destname, "wb");
+ if (!fdest)
+ {
+ fprintf(stderr, "ERROR -> failed to open %s for writing\n", destname);
+ free(destname);
+ return 1;
+ }
+ wr = image->comps[compno].w; hr = image->comps[compno].h;
+ prec = image->comps[compno].prec;
+ max = (1<<prec) - 1;
+
+ fprintf(fdest, "P5\n#OpenJPEG-%s\n%d %d\n%d\n",
+ opj_version(), wr, hr, max);
+
+ red = image->comps[compno].data;
+ adjustR =
+ (image->comps[compno].sgnd ? 1 << (image->comps[compno].prec - 1) : 0);
+
+ if(prec > 8)
+ {
+ for (i = 0; i < wr * hr; i++)
+ {
+ v = *red + adjustR; ++red;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+
+ if(has_alpha)
+ {
+ v = *alpha++;
+/* netpbm: */
+ fprintf(fdest, "%c%c",(unsigned char)(v>>8), (unsigned char)v);
+ }
+ }/* for(i */
+ }
+ else /* prec <= 8 */
+ {
+ for(i = 0; i < wr * hr; ++i)
+ {
+ fprintf(fdest, "%c", (unsigned char)(*red + adjustR)); ++red;
+ }
+ }
+ fclose(fdest);
+ } /* for (compno */
+ free(destname);
+
+ return 0;
+}/* imagetopnm() */
+
+#ifdef HAVE_LIBTIFF
+/* -->> -->> -->> -->>
+
+ TIFF IMAGE FORMAT
+
+ <<-- <<-- <<-- <<-- */
+
+int imagetotif(opj_image_t * image, const char *outfile)
+{
+ int width, height, imgsize;
+ int bps,index,adjust, sgnd;
+ int ushift, dshift, has_alpha, force16;
+ TIFF *tif;
+ tdata_t buf;
+ tstrip_t strip;
+ tsize_t strip_size;
+
+ ushift = dshift = force16 = has_alpha = 0;
+ bps = image->comps[0].prec;
+
+ if(bps > 8 && bps < 16)
+ {
+ ushift = 16 - bps; dshift = bps - ushift;
+ bps = 16; force16 = 1;
+ }
+
+ if(bps != 8 && bps != 16)
+ {
+ fprintf(stderr,"imagetotif: Bits=%d, Only 8 and 16 bits implemented\n",
+ bps);
+ fprintf(stderr,"\tAborting\n");
+ return 1;
+ }
+ tif = TIFFOpen(outfile, "wb");
+
+ if (!tif)
+ {
+ fprintf(stderr, "imagetotif:failed to open %s for writing\n", outfile);
+ return 1;
+ }
+ sgnd = image->comps[0].sgnd;
+ adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0;
+
+ 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)
+ {
+ has_alpha = (image->numcomps == 4);
+
+ width = image->comps[0].w;
+ height = image->comps[0].h;
+ imgsize = width * height ;
+
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3 + has_alpha);
+ 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);
+ strip_size = TIFFStripSize(tif);
+ buf = _TIFFmalloc(strip_size);
+ index=0;
+
+ for(strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
+ {
+ unsigned char *dat8;
+ tsize_t i, ssize, last_i = 0;
+ int step, restx;
+ ssize = TIFFStripSize(tif);
+ dat8 = (unsigned char*)buf;
+
+ if(bps == 8)
+ {
+ step = 3 + has_alpha;
+ restx = step - 1;
+
+ for(i=0; i < ssize - restx; i += step)
+ {
+ int r, g, b, a = 0;
+
+ if(index < imgsize)
+ {
+ r = image->comps[0].data[index];
+ g = image->comps[1].data[index];
+ b = image->comps[2].data[index];
+ if(has_alpha) a = image->comps[3].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ g += adjust;
+ b += adjust;
+ if(has_alpha) a += adjust;
+ }
+ dat8[i+0] = r ;
+ dat8[i+1] = g ;
+ dat8[i+2] = b ;
+ if(has_alpha) dat8[i+3] = a;
+
+ index++;
+ last_i = i + step;
+ }
+ else
+ break;
+ }/*for(i = 0;)*/
+
+ if(last_i < ssize)
+ {
+ for(i = last_i; i < ssize; i += step)
+ {
+ int r, g, b, a = 0;
+
+ if(index < imgsize)
+ {
+ r = image->comps[0].data[index];
+ g = image->comps[1].data[index];
+ b = image->comps[2].data[index];
+ if(has_alpha) a = image->comps[3].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ g += adjust;
+ b += adjust;
+ if(has_alpha) a += adjust;
+ }
+ dat8[i+0] = r ;
+ if(i+1 < ssize) dat8[i+1] = g ; else break;
+ if(i+2 < ssize) dat8[i+2] = b ; else break;
+ if(has_alpha)
+ {
+ if(i+3 < ssize) dat8[i+3] = a ; else break;
+ }
+ index++;
+ }
+ else
+ break;
+ }/*for(i)*/
+ }/*if(last_i < ssize)*/
+
+ } /*if(bps == 8)*/
+ else
+ if(bps == 16)
+ {
+ step = 6 + has_alpha + has_alpha;
+ restx = step - 1;
+
+ for(i = 0; i < ssize - restx ; i += step)
+ {
+ int r, g, b, a = 0;
+
+ if(index < imgsize)
+ {
+ r = image->comps[0].data[index];
+ g = image->comps[1].data[index];
+ b = image->comps[2].data[index];
+ if(has_alpha) a = image->comps[3].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ g += adjust;
+ b += adjust;
+ if(has_alpha) a += adjust;
+ }
+ if(force16)
+ {
+ r = (r<<ushift) + (r>>dshift);
+ g = (g<<ushift) + (g>>dshift);
+ b = (b<<ushift) + (b>>dshift);
+ if(has_alpha) a = (a<<ushift) + (a>>dshift);
+ }
+ 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);
+ if(has_alpha)
+ {
+ dat8[i+6] = a;
+ dat8[i+7] = (a >> 8);
+ }
+ index++;
+ last_i = i + step;
+ }
+ else
+ break;
+ }/*for(i = 0;)*/
+
+ if(last_i < ssize)
+ {
+ for(i = last_i ; i < ssize ; i += step)
+ {
+ int r, g, b, a = 0;
+
+ if(index < imgsize)
+ {
+ r = image->comps[0].data[index];
+ g = image->comps[1].data[index];
+ b = image->comps[2].data[index];
+ if(has_alpha) a = image->comps[3].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ g += adjust;
+ b += adjust;
+ if(has_alpha) a += adjust;
+ }
+ if(force16)
+ {
+ r = (r<<ushift) + (r>>dshift);
+ g = (g<<ushift) + (g>>dshift);
+ b = (b<<ushift) + (b>>dshift);
+ if(has_alpha) a = (a<<ushift) + (a>>dshift);
+ }
+ dat8[i+0] = r;/*LSB*/
+ if(i+1 < ssize) dat8[i+1] = (r >> 8);else break;/*MSB*/
+ if(i+2 < ssize) dat8[i+2] = g; else break;
+ if(i+3 < ssize) dat8[i+3] = (g >> 8);else break;
+ if(i+4 < ssize) dat8[i+4] = b; else break;
+ if(i+5 < ssize) dat8[i+5] = (b >> 8);else break;
+
+ if(has_alpha)
+ {
+ if(i+6 < ssize) dat8[i+6] = a; else break;
+ if(i+7 < ssize) dat8[i+7] = (a >> 8); else break;
+ }
+ index++;
+ }
+ else
+ break;
+ }/*for(i)*/
+ }/*if(last_i < ssize)*/
+
+ }/*if(bps == 16)*/
+ (void)TIFFWriteEncodedStrip(tif, strip, (void*)buf, strip_size);
+ }/*for(strip = 0; )*/
+
+ _TIFFfree((void*)buf);
+ TIFFClose(tif);
+
+ return 0;
+ }/*RGB(A)*/
+
+ if(image->numcomps == 1 /* GRAY */
+ || ( image->numcomps == 2 /* GRAY_ALPHA */
+ && image->comps[0].dx == image->comps[1].dx
+ && image->comps[0].dy == image->comps[1].dy
+ && image->comps[0].prec == image->comps[1].prec))
+ {
+ int step;
+
+ has_alpha = (image->numcomps == 2);
+
+ width = image->comps[0].w;
+ height = image->comps[0].h;
+ imgsize = width * height;
+
+/* Set tags */
+ TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1 + has_alpha);
+ 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;
+ tsize_t i, ssize = TIFFStripSize(tif);
+ dat8 = (unsigned char*)buf;
+
+ if(bps == 8)
+ {
+ step = 1 + has_alpha;
+
+ for(i=0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+ int r, a = 0;
+
+ r = image->comps[0].data[index];
+ if(has_alpha) a = image->comps[1].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ if(has_alpha) a += adjust;
+ }
+ dat8[i+0] = r;
+ if(has_alpha) dat8[i+1] = a;
+ index++;
+ }
+ else
+ break;
+ }/*for(i )*/
+ }/*if(bps == 8*/
+ else
+ if(bps == 16)
+ {
+ step = 2 + has_alpha + has_alpha;
+
+ for(i=0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+ int r, a = 0;
+
+ r = image->comps[0].data[index];
+ if(has_alpha) a = image->comps[1].data[index];
+
+ if(sgnd)
+ {
+ r += adjust;
+ if(has_alpha) a += adjust;
+ }
+ if(force16)
+ {
+ r = (r<<ushift) + (r>>dshift);
+ if(has_alpha) a = (a<<ushift) + (a>>dshift);
+ }
+ dat8[i+0] = r;/*LSB*/
+ dat8[i+1] = r >> 8;/*MSB*/
+ if(has_alpha)
+ {
+ dat8[i+2] = a;
+ dat8[i+3] = a >> 8;
+ }
+ index++;
+ }/*if(index < imgsize)*/
+ else
+ break;
+ }/*for(i )*/
+ }
+ (void)TIFFWriteEncodedStrip(tif, strip, (void*)buf, strip_size);
+ }/*for(strip*/
+
+ _TIFFfree(buf);
+ TIFFClose(tif);
+
+ return 0;
+ }
+
+ TIFFClose(tif);
+
+ fprintf(stderr,"imagetotif: Bad color format.\n"
+ "\tOnly RGB(A) and GRAY(A) has been implemented\n");
+ fprintf(stderr,"\tFOUND: numcomps(%d)\n\tAborting\n",
+ image->numcomps);
+
+ return 1;
+}/* imagetotif() */
+
+/*
+ * libtiff/tif_getimage.c : 1,2,4,8,16 bitspersample accepted
+ * CINEMA : 12 bit precision
+*/
+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;
+ 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[4]; /* RGBA */
+ opj_image_t *image = NULL;
+ int imgsize = 0;
+ int has_alpha = 0;
+ unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC;
+ unsigned int tiWidth, tiHeight;
+
+ tif = TIFFOpen(filename, "r");
+
+ if(!tif)
+ {
+ fprintf(stderr, "tiftoimage:Failed to open %s for reading\n", filename);
+ return 0;
+ }
+ tiBps = tiPhoto = tiSf = tiSpp = tiPC = 0;
+ tiWidth = tiHeight = 0;
+
+ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &tiWidth);
+ TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &tiHeight);
+ TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &tiBps);
+ TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &tiSf);
+ TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &tiSpp);
+ TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &tiPhoto);
+ TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &tiPC);
+ w= tiWidth;
+ h= tiHeight;
+
+ if(tiBps != 8 && tiBps != 16 && tiBps != 12) tiBps = 0;
+ if(tiPhoto != 1 && tiPhoto != 2) tiPhoto = 0;
+
+ if( !tiBps || !tiPhoto)
+ {
+ if( !tiBps)
+ fprintf(stderr,"imagetotif: Bits=%d, Only 8 and 16 bits"
+ " implemented\n",tiBps);
+ else
+ if( !tiPhoto)
+ fprintf(stderr,"tiftoimage: Bad color format %d.\n\tOnly RGB(A)"
+ " and GRAY(A) has been implemented\n",(int) tiPhoto);
+
+ fprintf(stderr,"\tAborting\n");
+ TIFFClose(tif);
+
+ return NULL;
+ }
+
+ {/* From: tiff-4.0.x/libtiff/tif_getimage.c : */
+ uint16* sampleinfo;
+ uint16 extrasamples;
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
+ &extrasamples, &sampleinfo);
+
+ if(extrasamples >= 1)
+ {
+ switch(sampleinfo[0])
+ {
+ case EXTRASAMPLE_UNSPECIFIED:
+/* Workaround for some images without correct info about alpha channel
+*/
+ if(tiSpp > 3)
+ has_alpha = 1;
+ break;
+
+ case EXTRASAMPLE_ASSOCALPHA: /* data pre-multiplied */
+ case EXTRASAMPLE_UNASSALPHA: /* data not pre-multiplied */
+ has_alpha = 1;
+ break;
+ }
+ }
+ else /* extrasamples == 0 */
+ if(tiSpp == 4 || tiSpp == 2) has_alpha = 1;
+ }
+
+/* initialize image components
+*/
+ memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
+
+ if(tiPhoto == PHOTOMETRIC_RGB) /* RGB(A) */
+ {
+ numcomps = 3 + has_alpha;
+ color_space = CLRSPC_SRGB;
+
+/*#define USETILEMODE*/
+ for(j = 0; j < numcomps; j++)
+ {
+ if(parameters->cp_cinema)
+ {
+ cmptparm[j].prec = 12;
+ cmptparm[j].bpp = 12;
+ }
+ else
+ {
+ cmptparm[j].prec = tiBps;
+ cmptparm[j].bpp = tiBps;
+ }
+ cmptparm[j].dx = subsampling_dx;
+ cmptparm[j].dy = subsampling_dy;
+ cmptparm[j].w = w;
+ cmptparm[j].h = h;
+#ifdef USETILEMODE
+ cmptparm[j].x0 = 0;
+ cmptparm[j].y0 = 0;
+#endif
+ }
+
+#ifdef USETILEMODE
+ image = opj_image_tile_create(numcomps,&cmptparm[0],color_space);
+#else
+ image = opj_image_create(numcomps, &cmptparm[0], color_space);
+#endif
+
+ 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=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 step;
+ tsize_t i, ssize;
+ ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size);
+ dat8 = (unsigned char*)buf;
+
+ if(tiBps == 16)
+ {
+ step = 6 + has_alpha + has_alpha;
+
+ for(i = 0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+ image->comps[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(has_alpha)
+ image->comps[3].data[index] = ( dat8[i+7] << 8 ) | dat8[i+6];
+
+ if(parameters->cp_cinema)
+ {
+/* Rounding 16 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 ;
+ if(has_alpha)
+ image->comps[3].data[index] =
+ (image->comps[3].data[index] + 0x08) >> 4 ;
+ }
+ index++;
+ }
+ else
+ break;
+ }/*for(i = 0)*/
+ }/*if(tiBps == 16)*/
+ else
+ if(tiBps == 8)
+ {
+ step = 3 + has_alpha;
+
+ for(i = 0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+#ifndef USETILEMODE
+ image->comps[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(has_alpha)
+ image->comps[3].data[index] = dat8[i+3];
+#endif
+
+ if(parameters->cp_cinema)
+ {
+/* Rounding 8 to 12 bits
+*/
+#ifndef USETILEMODE
+ 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 ;
+ if(has_alpha)
+ image->comps[3].data[index] = image->comps[3].data[index] << 4 ;
+#endif
+ }
+ index++;
+ }/*if(index*/
+ else
+ break;
+ }/*for(i )*/
+ }/*if( tiBps == 8)*/
+ else
+ if(tiBps == 12)/* CINEMA file */
+ {
+ step = 9;
+
+ for(i = 0; i < ssize; i += step)
+ {
+ if((index < imgsize)&(index+1 < imgsize))
+ {
+ image->comps[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;
+ }/*for(i )*/
+ }
+ }/*for(strip = 0; )*/
+
+ _TIFFfree(buf);
+ TIFFClose(tif);
+
+ return image;
+ }/*RGB(A)*/
+
+ if(tiPhoto == PHOTOMETRIC_MINISBLACK) /* GRAY(A) */
+ {
+ numcomps = 1 + has_alpha;
+ color_space = CLRSPC_GRAY;
+
+ for(j = 0; j < numcomps; ++j)
+ {
+ cmptparm[j].prec = tiBps;
+ cmptparm[j].bpp = tiBps;
+ cmptparm[j].dx = subsampling_dx;
+ cmptparm[j].dy = subsampling_dy;
+ cmptparm[j].w = w;
+ cmptparm[j].h = h;
+ }
+#ifdef USETILEMODE
+ image = opj_image_tile_create(numcomps,&cmptparm[0],color_space);
+#else
+ image = opj_image_create(numcomps, &cmptparm[0], color_space);
+#endif
+
+ 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 = 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;
+ tsize_t i, ssize;
+ int step;
+
+ ssize = TIFFReadEncodedStrip(tif, strip, buf, strip_size);
+ dat8 = (unsigned char*)buf;
+
+ if(tiBps == 16)
+ {
+ step = 2 + has_alpha + has_alpha;
+
+ for(i = 0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+ image->comps[0].data[index] = ( dat8[i+1] << 8 ) | dat8[i+0];
+ if(has_alpha)
+ image->comps[1].data[index] = ( dat8[i+3] << 8 ) | dat8[i+2];
+ index++;
+ }
+ else
+ break;
+ }/*for(i )*/
+ }
+ else
+ if(tiBps == 8)
+ {
+ step = 1 + has_alpha;
+
+ for(i = 0; i < ssize; i += step)
+ {
+ if(index < imgsize)
+ {
+ image->comps[0].data[index] = dat8[i+0];
+ if(has_alpha)
+ image->comps[1].data[index] = dat8[i+1];
+ index++;
+ }
+ else
+ break;
+ }/*for(i )*/
+ }
+ }/*for(strip = 0;*/
+
+ _TIFFfree(buf);
+ TIFFClose(tif);
+
+ }/*GRAY(A)*/
+
+ return image;
+
+}/* tiftoimage() */
+
+#endif /* HAVE_LIBTIFF */
+
+/* -->> -->> -->> -->>
+
+ RAW IMAGE FORMAT
+
+ <<-- <<-- <<-- <<-- */
+static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp, opj_bool big_endian) {
+ 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 if(raw_cp->rawBitDepth <= 16)
+ {
+ unsigned short value;
+ for(compno = 0; compno < numcomps; compno++) {
+ for (i = 0; i < w * h; i++) {
+ unsigned char temp1;
+ unsigned char temp2;
+ if (!fread(&temp1, 1, 1, f)) {
+ fprintf(stderr,"Error reading raw file. End of file probably reached.\n");
+ return NULL;
+ }
+ if (!fread(&temp2, 1, 1, f)) {
+ fprintf(stderr,"Error reading raw file. End of file probably reached.\n");
+ return NULL;
+ }
+ if( big_endian )
+ {
+ value = temp1 << 8;
+ value += temp2;
+ }
+ else
+ {
+ value = temp2 << 8;
+ value += temp1;
+ }
+ image->comps[compno].data[i] = raw_cp->rawSigned?(short)value:value;
+ }
+ }
+ }
+ else {
+ fprintf(stderr,"OpenJPEG cannot encode raw components with bit depth higher than 16 bits.\n");
+ return NULL;
+ }
+
+ if (fread(&ch, 1, 1, f)) {
+ fprintf(stderr,"Warning. End of raw file not reached... processing anyway\n");
+ }
+ fclose(f);
+
+ return image;
+}
+
+opj_image_t* rawltoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) {
+ return rawtoimage_common(filename, parameters, raw_cp, OPJ_FALSE);
+}
+
+opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) {
+ return rawtoimage_common(filename, parameters, raw_cp, OPJ_TRUE);
+}
+
+int imagetoraw_common(opj_image_t * image, const char *outfile, opj_bool big_endian)
+{
+ FILE *rawFile = NULL;
+ size_t res;
+ 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);
+ res = fwrite(&curr, sizeof(signed char), 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ 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);
+ res = fwrite(&curr, sizeof(unsigned char), 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ 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++) {
+ unsigned char temp1;
+ unsigned char temp2;
+ curr = (signed short int) (*ptr & mask);
+ if( big_endian )
+ {
+ temp1 = (unsigned char) (curr >> 8);
+ temp2 = (unsigned char) curr;
+ }
+ else
+ {
+ temp2 = (unsigned char) (curr >> 8);
+ temp1 = (unsigned char) curr;
+ }
+ res = fwrite(&temp1, 1, 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ res = fwrite(&temp2, 1, 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ 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++) {
+ unsigned char temp1;
+ unsigned char temp2;
+ curr = (unsigned short int) (*ptr & mask);
+ if( big_endian )
+ {
+ temp1 = (unsigned char) (curr >> 8);
+ temp2 = (unsigned char) curr;
+ }
+ else
+ {
+ temp2 = (unsigned char) (curr >> 8);
+ temp1 = (unsigned char) curr;
+ }
+ res = fwrite(&temp1, 1, 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ res = fwrite(&temp2, 1, 1, rawFile);
+ if( res < 1 ) {
+ fprintf(stderr, "failed to write 1 byte for %s\n", outfile);
+ return 1;
+ }
+ 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;
+}
+
+int imagetoraw(opj_image_t * image, const char *outfile)
+{
+ return imagetoraw_common(image, outfile, OPJ_TRUE);
+}
+
+int imagetorawl(opj_image_t * image, const char *outfile)
+{
+ return imagetoraw_common(image, outfile, OPJ_FALSE);
+}
+
+#ifdef HAVE_LIBPNG
+
+#define PNG_MAGIC "\x89PNG\x0d\x0a\x1a\x0a"
+#define MAGIC_SIZE 8
+/* PNG allows bits per sample: 1, 2, 4, 8, 16 */
+
+opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
+{
+ png_structp png;
+ png_infop info;
+ double gamma, display_exponent;
+ int bit_depth, interlace_type,compression_type, filter_type;
+ int unit;
+ png_uint_32 resx, resy;
+ unsigned int i, j;
+ png_uint_32 width, height;
+ int color_type, has_alpha, is16;
+ unsigned char *s;
+ FILE *reader;
+ unsigned char **rows;
+/* j2k: */
+ opj_image_t *image;
+ opj_image_cmptparm_t cmptparm[4];
+ int sub_dx, sub_dy;
+ unsigned int nr_comp;
+ int *r, *g, *b, *a;
+ unsigned char sigbuf[8];
+
+ if((reader = fopen(read_idf, "rb")) == NULL)
+ {
+ fprintf(stderr,"pngtoimage: can not open %s\n",read_idf);
+ return NULL;
+ }
+ image = NULL; png = NULL; rows = NULL;
+
+ if(fread(sigbuf, 1, MAGIC_SIZE, reader) != MAGIC_SIZE
+ || memcmp(sigbuf, PNG_MAGIC, MAGIC_SIZE) != 0)
+ {
+ fprintf(stderr,"pngtoimage: %s is no valid PNG file\n",read_idf);
+ goto fin;
+ }
+/* libpng-VERSION/example.c:
+ * PC : screen_gamma = 2.2;
+ * Mac: screen_gamma = 1.7 or 1.0;
+*/
+ display_exponent = 2.2;
+
+ if((png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL)) == NULL)
+ goto fin;
+ if((info = png_create_info_struct(png)) == NULL)
+ goto fin;
+
+ if(setjmp(png_jmpbuf(png)))
+ goto fin;
+
+ png_init_io(png, reader);
+ png_set_sig_bytes(png, MAGIC_SIZE);
+
+ png_read_info(png, info);
+
+ if(png_get_IHDR(png, info, &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_type) == 0)
+ goto fin;
+
+/* png_set_expand():
+ * expand paletted images to RGB, expand grayscale images of
+ * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
+ * to alpha channels.
+*/
+ if(color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png);
+ else
+ if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand(png);
+
+ if(png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_expand(png);
+
+ is16 = (bit_depth == 16);
+
+/* GRAY => RGB; GRAY_ALPHA => RGBA
+*/
+ if(color_type == PNG_COLOR_TYPE_GRAY
+ || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ png_set_gray_to_rgb(png);
+ color_type =
+ (color_type == PNG_COLOR_TYPE_GRAY? PNG_COLOR_TYPE_RGB:
+ PNG_COLOR_TYPE_RGB_ALPHA);
+ }
+ if( !png_get_gAMA(png, info, &gamma))
+ gamma = 0.45455;
+
+ png_set_gamma(png, display_exponent, gamma);
+
+ png_read_update_info(png, info);
+
+ png_get_pHYs(png, info, &resx, &resy, &unit);
+
+ color_type = png_get_color_type(png, info);
+
+ has_alpha = (color_type == PNG_COLOR_TYPE_RGB_ALPHA);
+
+ nr_comp = 3 + has_alpha;
+
+ bit_depth = png_get_bit_depth(png, info);
+
+ rows = (unsigned char**)calloc(height+1, sizeof(unsigned char*));
+ for(i = 0; i < height; ++i)
+ rows[i] = (unsigned char*)malloc(png_get_rowbytes(png,info));
+
+ png_read_image(png, rows);
+
+ memset(&cmptparm, 0, 4 * sizeof(opj_image_cmptparm_t));
+
+ sub_dx = params->subsampling_dx; sub_dy = params->subsampling_dy;
+
+ for(i = 0; i < nr_comp; ++i)
+ {
+ cmptparm[i].prec = bit_depth;
+/* bits_per_pixel: 8 or 16 */
+ cmptparm[i].bpp = bit_depth;
+ cmptparm[i].sgnd = 0;
+ cmptparm[i].dx = sub_dx;
+ cmptparm[i].dy = sub_dy;
+ cmptparm[i].w = width;
+ cmptparm[i].h = height;
+ }
+
+ image = opj_image_create(nr_comp, &cmptparm[0], CLRSPC_SRGB);
+
+ if(image == NULL) goto fin;
+
+ image->x0 = params->image_offset_x0;
+ image->y0 = params->image_offset_y0;
+ image->x1 = image->x0 + (width - 1) * sub_dx + 1 + image->x0;
+ image->y1 = image->y0 + (height - 1) * sub_dy + 1 + image->y0;
+
+ r = image->comps[0].data;
+ g = image->comps[1].data;
+ b = image->comps[2].data;
+ a = image->comps[3].data;
+
+ for(i = 0; i < height; ++i)
+ {
+ s = rows[i];
+
+ for(j = 0; j < width; ++j)
+ {
+ if(is16)
+ {
+ *r++ = s[0]<<8|s[1]; s += 2;
+
+ *g++ = s[0]<<8|s[1]; s += 2;
+
+ *b++ = s[0]<<8|s[1]; s += 2;
+
+ if(has_alpha) { *a++ = s[0]<<8|s[1]; s += 2; }
+
+ continue;
+ }
+ *r++ = *s++; *g++ = *s++; *b++ = *s++;
+
+ if(has_alpha) *a++ = *s++;
+ }
+ }
+fin:
+ if(rows)
+ {
+ for(i = 0; i < height; ++i)
+ free(rows[i]);
+ free(rows);
+ }
+ if(png)
+ png_destroy_read_struct(&png, &info, NULL);
+
+ fclose(reader);
+
+ return image;
+
+}/* pngtoimage() */
+
+int imagetopng(opj_image_t * image, const char *write_idf)
+{
+ FILE *writer;
+ png_structp png;
+ png_infop info;
+ int *red, *green, *blue, *alpha;
+ unsigned char *row_buf, *d;
+ int has_alpha, width, height, nr_comp, color_type;
+ int adjustR, adjustG, adjustB, adjustA, x, y, fails;
+ int prec, ushift, dshift, is16, force16, force8;
+ unsigned short mask = 0xffff;
+ png_color_8 sig_bit;
+
+ is16 = force16 = force8 = ushift = dshift = 0; fails = 1;
+ prec = image->comps[0].prec;
+ nr_comp = image->numcomps;
+
+ if(prec > 8 && prec < 16)
+ {
+ ushift = 16 - prec; dshift = prec - ushift;
+ prec = 16; force16 = 1;
+ }
+ else
+ if(prec < 8 && nr_comp > 1)/* GRAY_ALPHA, RGB, RGB_ALPHA */
+ {
+ ushift = 8 - prec; dshift = 8 - ushift;
+ prec = 8; force8 = 1;
+ }
+
+ if(prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16)
+ {
+ fprintf(stderr,"imagetopng: can not create %s"
+ "\n\twrong bit_depth %d\n", write_idf, prec);
+ return fails;
+ }
+ writer = fopen(write_idf, "wb");
+
+ if(writer == NULL) return fails;
+
+ info = NULL; has_alpha = 0;
+
+/* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+*/
+ png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+/*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */
+
+ if(png == NULL) goto fin;
+
+/* Allocate/initialize the image information data. REQUIRED
+*/
+ info = png_create_info_struct(png);
+
+ if(info == NULL) goto fin;
+
+/* Set error handling. REQUIRED if you are not supplying your own
+ * error handling functions in the png_create_write_struct() call.
+*/
+ if(setjmp(png_jmpbuf(png))) goto fin;
+
+/* I/O initialization functions is REQUIRED
+*/
+ png_init_io(png, writer);
+
+/* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
+ * REQUIRED
+ *
+ * ERRORS:
+ *
+ * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8
+ * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8
+ * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8
+ * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8
+ *
+*/
+ png_set_compression_level(png, Z_BEST_COMPRESSION);
+
+ if(prec == 16) mask = 0xffff;
+ else
+ if(prec == 8) mask = 0x00ff;
+ else
+ if(prec == 4) mask = 0x000f;
+ else
+ if(prec == 2) mask = 0x0003;
+ else
+ if(prec == 1) mask = 0x0001;
+
+ if(nr_comp >= 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)
+ {
+ int v;
+
+ has_alpha = (nr_comp > 3);
+
+ is16 = (prec == 16);
+
+ width = image->comps[0].w;
+ height = image->comps[0].h;
+
+ red = image->comps[0].data;
+ green = image->comps[1].data;
+ blue = image->comps[2].data;
+
+ sig_bit.red = sig_bit.green = sig_bit.blue = prec;
+
+ if(has_alpha)
+ {
+ sig_bit.alpha = prec;
+ alpha = image->comps[3].data;
+ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ adjustA = (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
+ }
+ else
+ {
+ sig_bit.alpha = 0; alpha = NULL;
+ color_type = PNG_COLOR_TYPE_RGB;
+ adjustA = 0;
+ }
+ png_set_sBIT(png, info, &sig_bit);
+
+ png_set_IHDR(png, info, width, height, prec,
+ color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+/*=============================*/
+ png_write_info(png, info);
+/*=============================*/
+ if(prec < 8)
+ {
+ png_set_packing(png);
+ }
+ adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+ adjustG = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+ adjustB = (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ row_buf = (unsigned char*)malloc(width * nr_comp * 2);
+
+ for(y = 0; y < height; ++y)
+ {
+ d = row_buf;
+
+ for(x = 0; x < width; ++x)
+ {
+ if(is16)
+ {
+ v = *red + adjustR; ++red;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+
+ v = *green + adjustG; ++green;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+
+ v = *blue + adjustB; ++blue;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+
+ if(has_alpha)
+ {
+ v = *alpha + adjustA; ++alpha;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+ }
+ continue;
+ }/* if(is16) */
+
+ v = *red + adjustR; ++red;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+
+ v = *green + adjustG; ++green;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+
+ v = *blue + adjustB; ++blue;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+
+ if(has_alpha)
+ {
+ v = *alpha + adjustA; ++alpha;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+ }
+ } /* for(x) */
+
+ png_write_row(png, row_buf);
+
+ } /* for(y) */
+ free(row_buf);
+
+ }/* nr_comp >= 3 */
+ else
+ if(nr_comp == 1 /* GRAY */
+ || ( nr_comp == 2 /* GRAY_ALPHA */
+ && image->comps[0].dx == image->comps[1].dx
+ && image->comps[0].dy == image->comps[1].dy
+ && image->comps[0].prec == image->comps[1].prec))
+ {
+ int v;
+
+ red = image->comps[0].data;
+
+ sig_bit.gray = prec;
+ sig_bit.red = sig_bit.green = sig_bit.blue = sig_bit.alpha = 0;
+ alpha = NULL; adjustA = 0;
+ color_type = PNG_COLOR_TYPE_GRAY;
+
+ if(nr_comp == 2)
+ {
+ has_alpha = 1; sig_bit.alpha = prec;
+ alpha = image->comps[1].data;
+ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ adjustA = (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+ }
+ width = image->comps[0].w;
+ height = image->comps[0].h;
+
+ png_set_IHDR(png, info, width, height, sig_bit.gray,
+ color_type,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_set_sBIT(png, info, &sig_bit);
+/*=============================*/
+ png_write_info(png, info);
+/*=============================*/
+ adjustR = (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ if(prec < 8)
+ {
+ png_set_packing(png);
+ }
+
+ if(prec > 8)
+ {
+ row_buf = (unsigned char*)
+ malloc(width * nr_comp * sizeof(unsigned short));
+
+ for(y = 0; y < height; ++y)
+ {
+ d = row_buf;
+
+ for(x = 0; x < width; ++x)
+ {
+ v = *red + adjustR; ++red;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+
+ if(has_alpha)
+ {
+ v = *alpha++;
+
+ if(force16) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v>>8); *d++ = (unsigned char)v;
+ }
+ }/* for(x) */
+ png_write_row(png, row_buf);
+
+ } /* for(y) */
+ free(row_buf);
+ }
+ else /* prec <= 8 */
+ {
+ row_buf = (unsigned char*)calloc(width, nr_comp * 2);
+
+ for(y = 0; y < height; ++y)
+ {
+ d = row_buf;
+
+ for(x = 0; x < width; ++x)
+ {
+ v = *red + adjustR; ++red;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+
+ if(has_alpha)
+ {
+ v = *alpha + adjustA; ++alpha;
+
+ if(force8) { v = (v<<ushift) + (v>>dshift); }
+
+ *d++ = (unsigned char)(v & mask);
+ }
+ }/* for(x) */
+
+ png_write_row(png, row_buf);
+
+ } /* for(y) */
+ free(row_buf);
+ }
+ }
+ else
+ {
+ fprintf(stderr,"imagetopng: can not create %s\n",write_idf);
+ goto fin;
+ }
+ png_write_end(png, info);
+
+ fails = 0;
+
+fin:
+
+ if(png)
+ {
+ png_destroy_write_struct(&png, &info);
+ }
+ fclose(writer);
+
+ if(fails) remove(write_idf);
+
+ return fails;
+}/* imagetopng() */
+#endif /* HAVE_LIBPNG */
diff --git a/src/bin/jp2/convert.h b/src/bin/jp2/convert.h
new file mode 100644
index 00000000..72ed981d
--- /dev/null
+++ b/src/bin/jp2/convert.h
@@ -0,0 +1,84 @@
+/*
+ * 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 */
+ opj_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 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);
+int imagetorawl(opj_image_t * image, const char *outfile);
+opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp);
+opj_image_t* rawltoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp);
+
+/* PNG conversion*/
+extern int imagetopng(opj_image_t *image, const char *write_idf);
+extern opj_image_t* pngtoimage(const char *filename, opj_cparameters_t *parameters);
+
+#endif /* __J2K_CONVERT_H */
+
diff --git a/src/bin/jp2/image_to_j2k.c b/src/bin/jp2/image_to_j2k.c
new file mode 100644
index 00000000..343ea557
--- /dev/null
+++ b/src/bin/jp2/image_to_j2k.c
@@ -0,0 +1,1901 @@
+/*
+ * 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 <jerome.fimes@c-s.fr>
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
+
+#ifdef _WIN32
+#include "windirent.h"
+#else
+#include <dirent.h>
+#endif /* _WIN32 */
+
+#ifdef _WIN32
+#include <windows.h>
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#else
+#include <strings.h>
+#endif /* _WIN32 */
+
+#include "opj_config.h"
+#include "openjpeg.h"
+#include "opj_getopt.h"
+#include "convert.h"
+#include "index.h"
+
+#include "format_defs.h"
+
+#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
+#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
+#define COMP_24_CS 1041666 /*Maximum size per color component for 2K & 4K @ 24fps*/
+#define COMP_48_CS 520833 /*Maximum size per color component for 2K @ 48fps*/
+
+typedef 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(void) {
+ fprintf(stdout,"HELP for image_to_j2k\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");
+/* <<UniPG */
+ fprintf(stdout,"\n");
+ fprintf(stdout,"REMARKS:\n");
+ fprintf(stdout,"---------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"The markers written to the main_header are : SOC SIZ COD QCD COM.\n");
+ fprintf(stdout,"COD and QCD never appear in the tile_header.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"By default:\n");
+ fprintf(stdout,"------------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout," * Lossless\n");
+ fprintf(stdout," * 1 tile\n");
+ fprintf(stdout," * Size of precinct : 2^15 x 2^15 (means 1 precinct)\n");
+ fprintf(stdout," * Size of code-block : 64 x 64\n");
+ fprintf(stdout," * Number of resolutions: 6\n");
+ fprintf(stdout," * No SOP marker in the codestream\n");
+ fprintf(stdout," * No EPH marker in the codestream\n");
+ fprintf(stdout," * No sub-sampling in x or y direction\n");
+ fprintf(stdout," * No mode switch activated\n");
+ fprintf(stdout," * Progression order: LRCP\n");
+ fprintf(stdout," * No index file\n");
+ fprintf(stdout," * No ROI upshifted\n");
+ fprintf(stdout," * No offset of the origin of the image\n");
+ fprintf(stdout," * No offset of the origin of the tiles\n");
+ fprintf(stdout," * Reversible DWT 5-3\n");
+/* UniPG>> */
+#ifdef USE_JPWL
+ fprintf(stdout," * No JPWL protection\n");
+#endif /* USE_JPWL */
+/* <<UniPG */
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Parameters:\n");
+ fprintf(stdout,"------------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Required Parameters (except with -h):\n");
+ fprintf(stdout,"One of the two options -ImgDir or -i must be used\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"-ImgDir : Image file Directory path (example ../Images) \n");
+ fprintf(stdout," When using this option -OutFor must be used\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"-OutFor \n");
+ fprintf(stdout," REQUIRED only if -ImgDir is used\n");
+ fprintf(stdout," Need to specify only format without filename <BMP> \n");
+ fprintf(stdout," Currently accepts PBM, PGM, PPM, PNM, PAM, PGX, PNG, BMP, TIF, RAW, RAWL and TGA formats\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"-i : source file (-i source.pnm also *pbm, *.pgm, *.ppm, *.pam, *.pgx, *png, *.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,"-TP : devide packets of every tile into tile-parts (-TP R) [R, L, C]\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,"-F : characteristics of the raw input image\n");
+ fprintf(stdout," -F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n");
+ fprintf(stdout," Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\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,"-jpip : write jpip codestream index box in JP2 output file\n");
+ fprintf(stdout," NOTICE: currently supports only RPCL order\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<tilepart><=type>,s<tilepart><=method>,a=<addr>,...\n");
+ fprintf(stdout," ...,z=<size>,g=<range>,p<tilepart:pack><=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: <range> 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: <addr> 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: <size> 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 */
+/* <<UniPG */
+ fprintf(stdout,"IMPORTANT:\n");
+ fprintf(stdout,"-----------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"The index file has the structure below:\n");
+ fprintf(stdout,"---------------------------------------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Image_height Image_width\n");
+ fprintf(stdout,"progression order\n");
+ fprintf(stdout,"Tiles_size_X Tiles_size_Y\n");
+ fprintf(stdout,"Tiles_nb_X Tiles_nb_Y\n");
+ fprintf(stdout,"Components_nb\n");
+ fprintf(stdout,"Layers_nb\n");
+ fprintf(stdout,"decomposition_levels\n");
+ fprintf(stdout,"[Precincts_size_X_res_Nr Precincts_size_Y_res_Nr]...\n");
+ fprintf(stdout," [Precincts_size_X_res_0 Precincts_size_Y_res_0]\n");
+ fprintf(stdout,"Main_header_start_position\n");
+ fprintf(stdout,"Main_header_end_position\n");
+ fprintf(stdout,"Codestream_size\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"INFO ON TILES\n");
+ fprintf(stdout,"tileno start_pos end_hd end_tile nbparts disto nbpix disto/nbpix\n");
+ fprintf(stdout,"Tile_0 start_pos end_Theader end_pos NumParts TotalDisto NumPix MaxMSE\n");
+ fprintf(stdout,"Tile_1 '' '' '' '' '' '' ''\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"Tile_Nt '' '' '' '' '' '' ''\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"TILE 0 DETAILS\n");
+ fprintf(stdout,"part_nb tileno num_packs start_pos end_tph_pos end_pos\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"Progression_string\n");
+ fprintf(stdout,"pack_nb tileno layno resno compno precno start_pos end_ph_pos end_pos disto\n");
+ fprintf(stdout,"Tpacket_0 Tile layer res. comp. prec. start_pos end_pos disto\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"Tpacket_Np '' '' '' '' '' '' '' ''\n");
+
+ fprintf(stdout,"MaxDisto\n");
+
+ fprintf(stdout,"TotalDisto\n\n");
+}
+
+OPJ_PROG_ORDER give_progression(char progression[4]) {
+ if(strncmp(progression, "LRCP", 4) == 0) {
+ return LRCP;
+ }
+ if(strncmp(progression, "RLCP", 4) == 0) {
+ return RLCP;
+ }
+ if(strncmp(progression, "RPCL", 4) == 0) {
+ return RPCL;
+ }
+ if(strncmp(progression, "PCRL", 4) == 0) {
+ return PCRL;
+ }
+ if(strncmp(progression, "CPRL", 4) == 0) {
+ return CPRL;
+ }
+
+ return PROG_UNKNOWN;
+}
+
+int get_num_images(char *imgdirpath){
+ DIR *dir;
+ struct dirent* content;
+ int num_images = 0;
+
+ /*Reading the input images from given input directory*/
+
+ dir= opendir(imgdirpath);
+ if(!dir){
+ fprintf(stderr,"Could not open Folder %s\n",imgdirpath);
+ return 0;
+ }
+
+ num_images=0;
+ while((content=readdir(dir))!=NULL){
+ if(strcmp(".",content->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", "pbm", "pam", "bmp", "tif", "raw", "rawl", "tga", "png", "j2k", "jp2", "j2c", "jpc"
+ };
+ static const int format[] = {
+ PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, J2K_CFMT, J2K_CFMT
+ };
+ char * ext = strrchr(filename, '.');
+ if (ext == NULL)
+ return -1;
+ ext++;
+ for(i = 0; i < sizeof(format)/sizeof(*format); i++) {
+ if(strcasecmp(ext, extension[i]) == 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 = OPJ_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;
+
+ 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 ; i<parameters->tcp_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 ; i<parameters->tcp_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, c;
+ opj_option_t long_option[]={
+ {"cinema2K",REQ_ARG, NULL ,'w'},
+ {"cinema4K",NO_ARG, NULL ,'y'},
+ {"ImgDir",REQ_ARG, NULL ,'z'},
+ {"TP",REQ_ARG, NULL ,'u'},
+ {"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'},
+ {"jpip",NO_ARG, NULL, 'J'}
+ };
+
+ /* parse the command line */
+ const char optlist[] = "i:o:r:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:u:J"
+#ifdef USE_JPWL
+ "W:"
+#endif /* USE_JPWL */
+ "h";
+
+ totlen=sizeof(long_option);
+ img_fol->set_out_format=0;
+ raw_cp->rawWidth = 0;
+
+ do{
+ c = opj_getopt_long(argc, argv, optlist,long_option,totlen);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i': /* input file */
+ {
+ char *infile = opj_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 RAWL_DFMT:
+ case TGA_DFMT:
+ case PNG_DFMT:
+ break;
+ default:
+ fprintf(stderr,
+ "!! Unrecognized format for infile : %s "
+ "[accept only *.pnm, *.pgm, *.ppm, *.pgx, *png, *.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 = opj_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 = opj_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 = opj_optarg;
+ break;
+ default:
+ fprintf(stderr, "Unknown output format image [only j2k, j2c, jp2]!! \n");
+ return 1;
+ }
+ }
+ break;
+
+
+ /* ----------------------------------------------------- */
+
+
+ case 'r': /* rates rates/distorsion */
+ {
+ char *s = opj_optarg;
+ parameters->tcp_numlayers = 0;
+ while (sscanf(s, "%f", &parameters->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 = opj_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 = OPJ_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 = OPJ_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 = opj_optarg;
+ while (sscanf(s, "%f", &parameters->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 = opj_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 = &parameters->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(opj_optarg, "%d,%d", &parameters->cp_tdx, &parameters->cp_tdy);
+ parameters->tile_size_on = OPJ_TRUE;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'n': /* resolution */
+ {
+ sscanf(opj_optarg, "%d", &parameters->numresolution);
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'c': /* precinct dimension */
+ {
+ char sep;
+ int res_spec = 0;
+
+ char *s = opj_optarg;
+ do {
+ sep = 0;
+ sscanf(s, "[%d,%d]%c", &parameters->prcw_init[res_spec],
+ &parameters->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(opj_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 = opj_optarg;
+ strncpy(indexfilename, index, OPJ_PATH_LEN);
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'p': /* progression order */
+ {
+ char progression[4];
+
+ strncpy(progression, opj_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(opj_optarg, "%d,%d", &parameters->subsampling_dx,
+ &parameters->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(opj_optarg, "%d,%d", &parameters->image_offset_x0,
+ &parameters->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 = opj_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(opj_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(opj_optarg, "c=%d,U=%d", &parameters->roi_compno,
+ &parameters->roi_shift) != 2) {
+ fprintf(stderr, "ROI error !! [-ROI c='compno',U='shift']\n");
+ return 1;
+ }
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
+ case 'T': /* Tile offset */
+ {
+ if (sscanf(opj_optarg, "%d,%d", &parameters->cp_tx0, &parameters->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(opj_optarg) + 1);
+ if(parameters->cp_comment) {
+ strcpy(parameters->cp_comment, opj_optarg);
+ }
+ }
+ break;
+
+
+ /* ------------------------------------------------------ */
+
+ case 'I': /* reversible or not */
+ {
+ parameters->irreversible = 1;
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
+ case 'u': /* Tile part generation*/
+ {
+ parameters->tp_flag = opj_optarg[0];
+ parameters->tp_on = 1;
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
+ case 'z': /* Image Directory path */
+ {
+ img_fol->imgdirpath = (char*)malloc(strlen(opj_optarg) + 1);
+ strcpy(img_fol->imgdirpath,opj_optarg);
+ img_fol->set_imgdir=1;
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
+ case 'w': /* Digital Cinema 2K profile compliance*/
+ {
+ int fps=0;
+ sscanf(opj_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': /* mct input file */
+ {
+ char *lFilename = opj_optarg;
+ char *lMatrix;
+ char *lCurrentPtr ;
+ float *lCurrentDoublePtr;
+ float *lSpace;
+ int *l_int_ptr;
+ int lNbComp = 0, lTotalComp, lMctComp, i, lStrLen;
+
+ /* Open file */
+ FILE * lFile = fopen(lFilename,"r");
+ if (lFile == NULL) {
+ return 1;
+ }
+
+ /* Set size of file and read its content*/
+ 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<lMctComp;++i) {
+ lStrLen = strlen(lCurrentPtr) + 1;
+ *lCurrentDoublePtr++ = (float) atof(lCurrentPtr);
+ lCurrentPtr += lStrLen;
+ }
+
+ l_int_ptr = (int*) lCurrentDoublePtr;
+ for (i=0;i<lNbComp;++i) {
+ lStrLen = strlen(lCurrentPtr) + 1;
+ *l_int_ptr++ = atoi(lCurrentPtr);
+ lCurrentPtr += lStrLen;
+ }
+
+ /* TODO should not be here ! */
+ opj_set_MCT(parameters, lSpace, (int *)(lSpace + lMctComp), lNbComp);
+
+ /* Free memory*/
+ free(lSpace);
+ free(lMatrix);
+ }
+ break;
+
+
+ /* ------------------------------------------------------ */
+
+/* UniPG>> */
+#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 || !*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(opj_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;
+
+ 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') {
+
+
+ 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') {
+
+
+ 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') {
+
+
+ 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 = OPJ_TRUE;
+
+ }
+ break;
+#endif /* USE_JPWL */
+/* <<UniPG */
+/* ------------------------------------------------------ */
+
+ case 'J': /* jpip on */
+ {
+ parameters->jpip_on = OPJ_TRUE;
+ }
+ break;
+ /* ------------------------------------------------------ */
+
+
+ default:
+ fprintf(stderr, "ERROR -> Command line not valid\n");
+ return 1;
+ }
+ }while(c != -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 <FORMAT> 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<FORMAT> !!\n");
+ return 1;
+ }
+ }else{
+ if((parameters->infile[0] == 0) || (parameters->outfile[0] == 0)) {
+ fprintf(stderr, "Example: %s -i image.ppm -o image.j2k\n",argv[0]);
+ fprintf(stderr, " Try: %s -h\n",argv[0]);
+ return 1;
+ }
+ }
+
+ if ( (parameters->decod_format == RAW_DFMT && raw_cp->rawWidth == 0)
+ || (parameters->decod_format == RAWL_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_file_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_file_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_file_callback(const char *msg, void *client_data) {
+ FILE *stream = (FILE*)client_data;
+ fprintf(stream, "[INFO] %s", msg);
+}
+
+/**
+sample error debug callback expecting no client object
+*/
+void error_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[ERROR] %s", msg);
+}
+/**
+sample warning debug callback expecting no client object
+*/
+void warning_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[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);
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+ * IMAGE_TO_J2K MAIN
+ */
+/* -------------------------------------------------------------------------- */
+int main(int argc, char **argv) {
+ FILE *fout = NULL;
+
+ opj_cparameters_t parameters; /* compression parameters */
+
+ opj_stream_t *l_stream = 00;
+ opj_codec_t* l_codec = 00;
+ opj_image_t *image = NULL;
+ raw_cparameters_t raw_cp;
+
+ char indexfilename[OPJ_PATH_LEN]; /* index file name */
+
+ int i, num_images, imageno;
+ img_fol_t img_fol;
+ dircnt_t *dirptr = NULL;
+
+ opj_bool bSuccess;
+ opj_bool bUseTiles = OPJ_FALSE; /* OPJ_TRUE */
+ OPJ_UINT32 l_nb_tiles = 4;
+
+ /* set encoding parameters to default values */
+ opj_set_default_encoder_parameters(&parameters);
+
+ /* 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, &parameters,&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(&parameters);
+ }
+
+ /* 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
+/* <<UniPG */
+ }
+
+ /* Read directory if necessary */
+ 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;i<num_images;i++){
+ dirptr->filename[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, &parameters)) {
+ fprintf(stderr,"skipping file...\n");
+ continue;
+ }
+ }
+
+ switch(parameters.decod_format) {
+ case PGX_DFMT:
+ break;
+ case PXM_DFMT:
+ break;
+ case BMP_DFMT:
+ break;
+ case TIF_DFMT:
+ break;
+ case RAW_DFMT:
+ case RAWL_DFMT:
+ break;
+ case TGA_DFMT:
+ break;
+ case PNG_DFMT:
+ break;
+ default:
+ fprintf(stderr,"skipping file...\n");
+ continue;
+ }
+
+ /* decode the source image */
+ /* ----------------------- */
+
+ switch (parameters.decod_format) {
+ case PGX_DFMT:
+ image = pgxtoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load pgx file\n");
+ return 1;
+ }
+ break;
+
+ case PXM_DFMT:
+ image = pnmtoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load pnm file\n");
+ return 1;
+ }
+ break;
+
+ case BMP_DFMT:
+ image = bmptoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load bmp file\n");
+ return 1;
+ }
+ break;
+
+#ifdef HAVE_LIBTIFF
+ case TIF_DFMT:
+ image = tiftoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load tiff file\n");
+ return 1;
+ }
+ break;
+#endif /* HAVE_LIBTIFF */
+
+ case RAW_DFMT:
+ image = rawtoimage(parameters.infile, &parameters, &raw_cp);
+ if (!image) {
+ fprintf(stderr, "Unable to load raw file\n");
+ return 1;
+ }
+ break;
+
+ case RAWL_DFMT:
+ image = rawltoimage(parameters.infile, &parameters, &raw_cp);
+ if (!image) {
+ fprintf(stderr, "Unable to load raw file\n");
+ return 1;
+ }
+ break;
+
+ case TGA_DFMT:
+ image = tgatoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load tga file\n");
+ return 1;
+ }
+ break;
+
+#ifdef HAVE_LIBPNG
+ case PNG_DFMT:
+ image = pngtoimage(parameters.infile, &parameters);
+ if (!image) {
+ fprintf(stderr, "Unable to load png file\n");
+ return 1;
+ }
+ break;
+#endif /* HAVE_LIBPNG */
+ }
+
+/* Can happen if input file is TIFF or PNG
+ * and HAVE_LIBTIF or HAVE_LIBPNG is undefined
+*/
+ if( !image) {
+ fprintf(stderr, "Unable to load file: got no image\n");
+ return 1;
+ }
+
+ /* Decide if MCT should be used */
+ parameters.tcp_mct = image->numcomps == 3 ? 1 : 0;
+
+ if(parameters.cp_cinema){
+ cinema_setup_encoder(&parameters,image,&img_fol);
+ }
+
+ /* encode the destination image */
+ /* ---------------------------- */
+
+ switch(parameters.cod_format) {
+ case J2K_CFMT: /* JPEG-2000 codestream */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_compress(CODEC_J2K);
+ break;
+ }
+ case JP2_CFMT: /* JPEG 2000 compressed image data */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_compress(CODEC_JP2);
+ break;
+ }
+ default:
+ fprintf(stderr, "skipping file..\n");
+ opj_stream_destroy(l_stream);
+ continue;
+ }
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_info_handler(l_codec, info_callback,00);
+ opj_set_warning_handler(l_codec, warning_callback,00);
+ opj_set_error_handler(l_codec, error_callback,00);
+
+ if( bUseTiles ) {
+ parameters.cp_tx0 = 0;
+ parameters.cp_ty0 = 0;
+ parameters.tile_size_on = OPJ_TRUE;
+ parameters.cp_tdx = 512;
+ parameters.cp_tdy = 512;
+ }
+ opj_setup_encoder(l_codec, &parameters, image);
+
+ /* Open the output file*/
+ fout = fopen(parameters.outfile, "wb");
+ if (! fout) {
+ fprintf(stderr, "Not enable to create output file!\n");
+ opj_stream_destroy(l_stream);
+ return 1;
+ }
+
+ /* open a byte stream for writing and allocate memory for all tiles */
+ l_stream = opj_stream_create_default_file_stream(fout,OPJ_FALSE);
+ if (! l_stream){
+ return 1;
+ }
+
+ /* encode the image */
+ bSuccess = opj_start_compress(l_codec,image,l_stream);
+ if (!bSuccess) {
+ fprintf(stderr, "failed to encode image: opj_start_compress\n");
+ }
+ if( bUseTiles ) {
+ OPJ_BYTE *l_data;
+ OPJ_UINT32 l_data_size = 512*512*3;
+ l_data = (OPJ_BYTE*) malloc( l_data_size * sizeof(OPJ_BYTE));
+ memset(l_data, 0, l_data_size );
+ assert( l_data );
+ for (i=0;i<l_nb_tiles;++i) {
+ if (! opj_write_tile(l_codec,i,l_data,l_data_size,l_stream)) {
+ fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",i);
+ opj_stream_destroy(l_stream);
+ fclose(fout);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ return 1;
+ }
+ }
+ free(l_data);
+ }
+ else {
+ bSuccess = bSuccess && opj_encode(l_codec, l_stream);
+ if (!bSuccess) {
+ fprintf(stderr, "failed to encode image: opj_encode\n");
+ }
+ }
+ bSuccess = bSuccess && opj_end_compress(l_codec, l_stream);
+ if (!bSuccess) {
+ fprintf(stderr, "failed to encode image: opj_end_compress\n");
+ }
+
+ if (!bSuccess) {
+ opj_stream_destroy(l_stream);
+ fclose(fout);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ 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(l_stream);
+ fclose(fout);
+
+ /* free remaining compression structures */
+ opj_destroy_codec(l_codec);
+
+ /* 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);
+ if(parameters.cp_cinema) free(img_fol.rates);
+
+ return 0;
+}
diff --git a/src/bin/jp2/index.c b/src/bin/jp2/index.c
new file mode 100644
index 00000000..c71730fe
--- /dev/null
+++ b/src/bin/jp2/index.c
@@ -0,0 +1,392 @@
+/*
+ * 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 <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "openjpeg.h"
+#include "index.h"
+#include "opj_inttypes.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 */
+/* <<UniPG */
+
+ if (!cstr_info)
+ return 1;
+
+ stream = fopen(index, "w");
+ if (!stream) {
+ fprintf(stderr, "failed to open index file [%s] for writing\n", index);
+ return 1;
+ }
+
+ if (cstr_info->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[0]); /* based on component 0 */
+
+ 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);
+/* <<UniPG */
+ fprintf(stream, "%d\n", cstr_info->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++) {
+ OPJ_OFF_T 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 %6" PRId64 " %6" PRId64 " %7" PRId64,
+ 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 %9" PRId64 " %9" PRId64 " %7" PRId64,
+ 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 %9" PRId64 " %9" PRId64 " %7" PRId64,
+ 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 %9" PRId64 " %9" PRId64 " %7" PRId64,
+ 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 %9" PRId64 " %9" PRId64 " %7" PRId64,
+ 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%9" PRId64 " %9d\n", cstr_info->marker[x].type, cstr_info->marker[x].pos, cstr_info->marker[x].len);
+ }
+/* <<UniPG */
+ fclose(stream);
+
+ fprintf(stderr,"Generated index file %s\n", index);
+
+ return 0;
+}
diff --git a/src/bin/jp2/index.h b/src/bin/jp2/index.h
new file mode 100644
index 00000000..6c2231dd
--- /dev/null
+++ b/src/bin/jp2/index.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef __J2K_INDEX_H
+#define __J2K_INDEX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __J2K_INDEX_H */
+
diff --git a/src/bin/jp2/j2k_dump.c b/src/bin/jp2/j2k_dump.c
new file mode 100644
index 00000000..6c63c2ca
--- /dev/null
+++ b/src/bin/jp2/j2k_dump.c
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 2010, Mathieu Malaterre, GDCM
+ * Copyright (c) 2011, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
+ * 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_config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef _WIN32
+#include "windirent.h"
+#else
+#include <dirent.h>
+#endif /* _WIN32 */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <strings.h>
+#define _stricmp strcasecmp
+#define _strnicmp strncasecmp
+#endif /* _WIN32 */
+
+#include "openjpeg.h"
+#include "opj_getopt.h"
+#include "convert.h"
+#include "index.h"
+
+#include "format_defs.h"
+
+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*/
+ const char *out_format;
+ /** Enable option*/
+ char set_imgdir;
+ /** Enable Cod Format for output*/
+ char set_out_format;
+
+}img_fol_t;
+
+/* -------------------------------------------------------------------------- */
+/* Declarations */
+int get_num_images(char *imgdirpath);
+int load_images(dircnt_t *dirptr, char *imgdirpath);
+int get_file_format(const char *filename);
+char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters);
+static int infile_format(const char *fname);
+
+int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol);
+int parse_DA_values( char* inArg, unsigned int *DA_x0, unsigned int *DA_y0, unsigned int *DA_x1, unsigned int *DA_y1);
+
+/* -------------------------------------------------------------------------- */
+void decode_help_display(void) {
+ fprintf(stdout,"HELP for j2k_dump\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");
+/* <<UniPG */
+ fprintf(stdout,"\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout," -ImgDir \n");
+ fprintf(stdout," Image file Directory path \n");
+ fprintf(stdout," -i <compressed file>\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 <output file>\n");
+ fprintf(stdout," OPTIONAL\n");
+ fprintf(stdout," Output file where file info will be dump.\n");
+ fprintf(stdout," By default it will be in the stdout.\n");
+ fprintf(stdout," -v "); /* FIXME WIP_MSD */
+ fprintf(stdout," OPTIONAL\n");
+ fprintf(stdout," Activate or not the verbose mode (display info and warning message)\n");
+ fprintf(stdout," By default verbose mode is off.\n");
+ fprintf(stdout,"\n");
+}
+
+/* -------------------------------------------------------------------------- */
+int get_num_images(char *imgdirpath){
+ DIR *dir;
+ struct dirent* content;
+ int num_images = 0;
+
+ /*Reading the input images from given input directory*/
+
+ dir= opendir(imgdirpath);
+ if(!dir){
+ fprintf(stderr,"Could not open Folder %s\n",imgdirpath);
+ return 0;
+ }
+
+ while((content=readdir(dir))!=NULL){
+ if(strcmp(".",content->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(const char *filename) {
+ unsigned int i;
+ static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "tga", "png", "j2k", "jp2", "jpt", "j2c", "jpc" };
+ static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_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;
+}
+
+/* -------------------------------------------------------------------------- */
+#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
+#define JP2_MAGIC "\x0d\x0a\x87\x0a"
+/* position 45: "\xff\x52" */
+#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
+
+static int infile_format(const char *fname)
+{
+ FILE *reader;
+ const char *s, *magic_s;
+ int ext_format, magic_format;
+ unsigned char buf[12];
+ unsigned int l_nb_read;
+
+ reader = fopen(fname, "rb");
+
+ if (reader == NULL)
+ return -1;
+
+ memset(buf, 0, 12);
+ l_nb_read = fread(buf, 1, 12, reader);
+ fclose(reader);
+ if (l_nb_read != 12)
+ return -1;
+
+
+
+ ext_format = get_file_format(fname);
+
+ if (ext_format == JPT_CFMT)
+ return JPT_CFMT;
+
+ if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
+ magic_format = JP2_CFMT;
+ magic_s = ".jp2";
+ }
+ else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
+ magic_format = J2K_CFMT;
+ magic_s = ".j2k or .jpc or .j2c";
+ }
+ else
+ return -1;
+
+ if (magic_format == ext_format)
+ return ext_format;
+
+ s = fname + strlen(fname) - 4;
+
+ fputs("\n===========================================\n", stderr);
+ fprintf(stderr, "The extension of this file is incorrect.\n"
+ "FOUND %s. SHOULD BE %s\n", s, magic_s);
+ fputs("===========================================\n", stderr);
+
+ return magic_format;
+}
+/* -------------------------------------------------------------------------- */
+/**
+ * Parse the command line
+ */
+/* -------------------------------------------------------------------------- */
+int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol) {
+ int totlen, c;
+ opj_option_t long_option[]={
+ {"ImgDir",REQ_ARG, NULL ,'y'},
+ };
+ const char optlist[] = "i:o:hv";
+
+ totlen=sizeof(long_option);
+ img_fol->set_out_format = 0;
+ do {
+ c = opj_getopt_long(argc, argv,optlist,long_option,totlen);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i': /* input file */
+ {
+ char *infile = opj_optarg;
+ parameters->decod_format = infile_format(infile);
+ switch(parameters->decod_format) {
+ case J2K_CFMT:
+ break;
+ case JP2_CFMT:
+ break;
+ 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 = opj_optarg;
+ strncpy(parameters->outfile, outfile, sizeof(parameters->outfile)-1);
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'h': /* display an help description */
+ decode_help_display();
+ return 1;
+
+ /* ------------------------------------------------------ */
+
+ case 'y': /* Image Directory path */
+ {
+ img_fol->imgdirpath = (char*)malloc(strlen(opj_optarg) + 1);
+ strcpy(img_fol->imgdirpath,opj_optarg);
+ img_fol->set_imgdir=1;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'v': /* Verbose mode */
+ {
+ parameters->m_verbose = 1;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+ default:
+ fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, opj_optarg);
+ break;
+ }
+ }while(c != -1);
+
+ /* 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 <FORMAT> 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) {
+ fprintf(stderr, "Example: %s -i image.j2k\n",argv[0]);
+ fprintf(stderr, " Try: %s -h\n",argv[0]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+sample error debug callback expecting no client object
+*/
+void error_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[ERROR] %s", msg);
+}
+/**
+sample warning debug callback expecting no client object
+*/
+void warning_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[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);
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+ * J2K_DUMP MAIN
+ */
+/* -------------------------------------------------------------------------- */
+int main(int argc, char *argv[])
+{
+ FILE *fsrc = NULL, *fout = NULL;
+
+ opj_dparameters_t parameters; /* Decompression parameters */
+ opj_image_t* image = NULL; /* Image structure */
+ opj_codec_t* l_codec = NULL; /* Handle to a decompressor */
+ opj_stream_t *l_stream = NULL; /* Stream */
+ opj_codestream_info_v2_t* cstr_info = NULL;
+ opj_codestream_index_t* cstr_index = NULL;
+
+ OPJ_INT32 num_images, imageno;
+ img_fol_t img_fol;
+ dircnt_t *dirptr = NULL;
+
+#ifdef MSD
+ opj_bool l_go_on = OPJ_TRUE;
+ OPJ_UINT32 l_max_data_size = 1000;
+ OPJ_BYTE * l_data = (OPJ_BYTE *) malloc(1000);
+#endif
+
+ /* Set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* Initialize img_fol */
+ memset(&img_fol,0,sizeof(img_fol_t));
+
+ /* Parse input and get user encoding parameters */
+ if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol) == 1) {
+ return EXIT_FAILURE;
+ }
+
+ /* Initialize reading of directory */
+ if(img_fol.set_imgdir==1){
+ int it_image;
+ 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 EXIT_FAILURE;
+ }
+
+ for(it_image=0;it_image<num_images;it_image++){
+ dirptr->filename[it_image] = dirptr->filename_buf + it_image*OPJ_PATH_LEN;
+ }
+ }
+ if(load_images(dirptr,img_fol.imgdirpath)==1){
+ return EXIT_FAILURE;
+ }
+
+ if (num_images==0){
+ fprintf(stdout,"Folder is empty\n");
+ return EXIT_FAILURE;
+ }
+ }else{
+ num_images=1;
+ }
+
+ /* Try to open for writing the output file if necessary */
+ if (parameters.outfile[0] != 0){
+ fout = fopen(parameters.outfile,"w");
+ if (!fout){
+ fprintf(stderr, "ERROR -> failed to open %s for writing\n", parameters.outfile);
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ fout = stdout;
+
+ /* Read the header of each image one by one */
+ for(imageno = 0; imageno < num_images ; imageno++){
+
+ fprintf(stderr,"\n");
+
+ if(img_fol.set_imgdir==1){
+ if (get_next_file(imageno, dirptr,&img_fol, &parameters)) {
+ 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 EXIT_FAILURE;
+ }
+
+ l_stream = opj_stream_create_default_file_stream(fsrc,1);
+ if (!l_stream){
+ fclose(fsrc);
+ fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Read the JPEG2000 stream */
+ /* ------------------------ */
+
+ switch(parameters.decod_format) {
+ case J2K_CFMT: /* JPEG-2000 codestream */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_J2K);
+ break;
+ }
+ case JP2_CFMT: /* JPEG 2000 compressed image data */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_JP2);
+ break;
+ }
+ case JPT_CFMT: /* JPEG 2000, JPIP */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_JPT);
+ break;
+ }
+ default:
+ fprintf(stderr, "skipping file..\n");
+ opj_stream_destroy(l_stream);
+ continue;
+ }
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_info_handler(l_codec, info_callback,00);
+ opj_set_warning_handler(l_codec, warning_callback,00);
+ opj_set_error_handler(l_codec, error_callback,00);
+
+ /* Setup the decoder decoding parameters using user parameters */
+ if ( !opj_setup_decoder(l_codec, &parameters) ){
+ fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n");
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+ opj_destroy_codec(l_codec);
+ fclose(fout);
+ return EXIT_FAILURE;
+ }
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if(! opj_read_header(l_stream, l_codec, &image)){
+ fprintf(stderr, "ERROR -> j2k_dump: failed to read the header\n");
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ fclose(fout);
+ return EXIT_FAILURE;
+ }
+
+ opj_dump_codec(l_codec, OPJ_IMG_INFO | OPJ_J2K_MH_INFO | OPJ_J2K_MH_IND, fout );
+
+ cstr_info = opj_get_cstr_info(l_codec);
+
+ cstr_index = opj_get_cstr_index(l_codec);
+
+ /* close the byte stream */
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+
+ /* free remaining structures */
+ if (l_codec) {
+ opj_destroy_codec(l_codec);
+ }
+
+ /* destroy the image header */
+ opj_image_destroy(image);
+
+ /* destroy the codestream index */
+ opj_destroy_cstr_index(&cstr_index);
+
+ /* destroy the codestream info */
+ opj_destroy_cstr_info(&cstr_info);
+
+ }
+
+ /* Close the output file */
+ fclose(fout);
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/bin/jp2/j2k_to_image.c b/src/bin/jp2/j2k_to_image.c
new file mode 100644
index 00000000..7edb3c9b
--- /dev/null
+++ b/src/bin/jp2/j2k_to_image.c
@@ -0,0 +1,975 @@
+/*
+ * 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 "opj_config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef _WIN32
+#include "windirent.h"
+#else
+#include <dirent.h>
+#endif /* _WIN32 */
+
+#ifdef _WIN32
+#include <windows.h>
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#else
+#include <strings.h>
+#endif /* _WIN32 */
+
+#include "openjpeg.h"
+#include "opj_getopt.h"
+#include "convert.h"
+#include "index.h"
+
+#ifdef HAVE_LIBLCMS2
+#include <lcms2.h>
+#endif
+#ifdef HAVE_LIBLCMS1
+#include <lcms.h>
+#endif
+#include "color.h"
+
+#include "format_defs.h"
+
+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*/
+ const char *out_format;
+ /** Enable option*/
+ char set_imgdir;
+ /** Enable Cod Format for output*/
+ char set_out_format;
+
+}img_fol_t;
+
+/* -------------------------------------------------------------------------- */
+/* Declarations */
+int get_num_images(char *imgdirpath);
+int load_images(dircnt_t *dirptr, char *imgdirpath);
+int get_file_format(const char *filename);
+char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters);
+static int infile_format(const char *fname);
+
+int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol, char *indexfilename);
+int parse_DA_values( char* inArg, unsigned int *DA_x0, unsigned int *DA_y0, unsigned int *DA_x1, unsigned int *DA_y1);
+
+/* -------------------------------------------------------------------------- */
+void decode_help_display(void) {
+ fprintf(stdout,"HELP for j2k_to_image\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");
+/* <<UniPG */
+ fprintf(stdout,"\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout," -ImgDir \n");
+ fprintf(stdout," Image file Directory path \n");
+ fprintf(stdout," -OutFor \n");
+ fprintf(stdout," REQUIRED only if -ImgDir is used\n");
+ fprintf(stdout," Need to specify only format without filename <BMP> \n");
+ fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, PNG, BMP, TIF, RAW and TGA formats\n");
+ fprintf(stdout," -i <compressed file>\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 <decompressed file>\n");
+ fprintf(stdout," REQUIRED\n");
+ fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, PNG, 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 <reduce factor>\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 <number of quality layers to decode>\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," -d <x0,y0,x1,y1>\n");
+ fprintf(stdout," OPTIONAL\n");
+ fprintf(stdout," Decoding area\n");
+ fprintf(stdout," By default all the image is decoded.\n");
+ fprintf(stdout," -t <tile_number>\n");
+ fprintf(stdout," OPTIONAL\n");
+ fprintf(stdout," Set the tile number of the decoded tile. Follow the JPEG2000 convention from left-up to bottom-up\n");
+ fprintf(stdout," By default all tiles are decoded.\n");
+ fprintf(stdout,"\n");
+/* UniPG>> */
+#ifdef USE_JPWL
+ fprintf(stdout," -W <options>\n");
+ fprintf(stdout," Activates the JPWL correction capability, if the codestream complies.\n");
+ fprintf(stdout," Options can be a comma separated list of <param=val> 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 */
+/* <<UniPG */
+ fprintf(stdout,"\n");
+}
+
+/* -------------------------------------------------------------------------- */
+
+int get_num_images(char *imgdirpath){
+ DIR *dir;
+ struct dirent* content;
+ int num_images = 0;
+
+ /*Reading the input images from given input directory*/
+
+ dir= opendir(imgdirpath);
+ if(!dir){
+ fprintf(stderr,"Could not open Folder %s\n",imgdirpath);
+ return 0;
+ }
+
+ while((content=readdir(dir))!=NULL){
+ if(strcmp(".",content->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(const char *filename) {
+ unsigned int i;
+ static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "rawl", "tga", "png", "j2k", "jp2", "jpt", "j2c", "jpc" };
+ static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_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(strcasecmp(ext, extension[i]) == 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 = infile_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;
+}
+
+/* -------------------------------------------------------------------------- */
+#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
+#define JP2_MAGIC "\x0d\x0a\x87\x0a"
+/* position 45: "\xff\x52" */
+#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
+
+static int infile_format(const char *fname)
+{
+ FILE *reader;
+ const char *s, *magic_s;
+ int ext_format, magic_format;
+ unsigned char buf[12];
+ unsigned int l_nb_read;
+
+ reader = fopen(fname, "rb");
+
+ if (reader == NULL)
+ return -2;
+
+ memset(buf, 0, 12);
+ l_nb_read = fread(buf, 1, 12, reader);
+ fclose(reader);
+ if (l_nb_read != 12)
+ return -1;
+
+
+
+ ext_format = get_file_format(fname);
+
+ if (ext_format == JPT_CFMT)
+ return JPT_CFMT;
+
+ if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
+ magic_format = JP2_CFMT;
+ magic_s = ".jp2";
+ }
+ else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
+ magic_format = J2K_CFMT;
+ magic_s = ".j2k or .jpc or .j2c";
+ }
+ else
+ return -1;
+
+ if (magic_format == ext_format)
+ return ext_format;
+
+ s = fname + strlen(fname) - 4;
+
+ fputs("\n===========================================\n", stderr);
+ fprintf(stderr, "The extension of this file is incorrect.\n"
+ "FOUND %s. SHOULD BE %s\n", s, magic_s);
+ fputs("===========================================\n", stderr);
+
+ return magic_format;
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+ * Parse the command line
+ */
+/* -------------------------------------------------------------------------- */
+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, c;
+ opj_option_t long_option[]={
+ {"ImgDir",REQ_ARG, NULL ,'y'},
+ {"OutFor",REQ_ARG, NULL ,'O'},
+ };
+
+ const char optlist[] = "i:o:r:l:x:d:t:"
+
+/* UniPG>> */
+#ifdef USE_JPWL
+ "W:"
+#endif /* USE_JPWL */
+/* <<UniPG */
+ "h" ;
+ totlen=sizeof(long_option);
+ img_fol->set_out_format = 0;
+ do {
+ c = opj_getopt_long(argc, argv,optlist,long_option,totlen);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i': /* input file */
+ {
+ char *infile = opj_optarg;
+ parameters->decod_format = infile_format(infile);
+ switch(parameters->decod_format) {
+ case J2K_CFMT:
+ break;
+ case JP2_CFMT:
+ break;
+ case JPT_CFMT:
+ break;
+ case -2:
+ fprintf(stderr,
+ "!! infile cannot be read: %s !!\n\n",
+ infile);
+ return 1;
+ 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 = opj_optarg;
+ parameters->cod_format = get_file_format(outfile);
+ switch(parameters->cod_format) {
+ case PGX_DFMT:
+ break;
+ case PXM_DFMT:
+ break;
+ case BMP_DFMT:
+ break;
+ case TIF_DFMT:
+ break;
+ case RAW_DFMT:
+ break;
+ case RAWL_DFMT:
+ break;
+ case TGA_DFMT:
+ break;
+ case PNG_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 = opj_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 RAWL_DFMT:
+ img_fol->out_format = "rawl";
+ break;
+ case TGA_DFMT:
+ img_fol->out_format = "raw";
+ break;
+ case PNG_DFMT:
+ img_fol->out_format = "png";
+ 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(opj_optarg, "%d", &parameters->cp_reduce);
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+
+ case 'l': /* layering option */
+ {
+ sscanf(opj_optarg, "%d", &parameters->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(opj_optarg) + 1);
+ strcpy(img_fol->imgdirpath,opj_optarg);
+ img_fol->set_imgdir=1;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'd': /* Input decode ROI */
+ {
+ int size_optarg = (int)strlen(opj_optarg) + 1;
+ char *ROI_values = (char*) malloc(size_optarg);
+ ROI_values[0] = '\0';
+ strncpy(ROI_values, opj_optarg, strlen(opj_optarg));
+ ROI_values[strlen(opj_optarg)] = '\0';
+ /*printf("ROI_values = %s [%d / %d]\n", ROI_values, strlen(ROI_values), size_optarg ); */
+ parse_DA_values( ROI_values, &parameters->DA_x0, &parameters->DA_y0, &parameters->DA_x1, &parameters->DA_y1);
+
+ free(ROI_values);
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 't': /* Input tile index */
+ {
+ sscanf(opj_optarg, "%d", &parameters->tile_index);
+ parameters->nb_tile_to_decode = 1;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+
+ case 'x': /* Creation of index file */
+ {
+ char *index = opj_optarg;
+ strncpy(indexfilename, index, OPJ_PATH_LEN);
+ }
+ break;
+ /* ----------------------------------------------------- */
+ /* UniPG>> */
+#ifdef USE_JPWL
+
+ case 'W': /* activate JPWL correction */
+ {
+ char *token = NULL;
+
+ token = strtok(opj_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 = OPJ_TRUE;
+ fprintf(stdout, "JPWL correction capability activated\n");
+ fprintf(stdout, "- expecting %d components\n", parameters->jpwl_exp_comps);
+ }
+ break;
+#endif /* USE_JPWL */
+/* <<UniPG */
+
+ /* ----------------------------------------------------- */
+
+ default:
+ fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, opj_optarg);
+ break;
+ }
+ }while(c != -1);
+
+ /* 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 <FORMAT> 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, "Example: %s -i image.j2k -o image.pgm\n",argv[0]);
+ fprintf(stderr, " Try: %s -h\n",argv[0]);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+ * Parse decoding area input values
+ * separator = ","
+ */
+/* -------------------------------------------------------------------------- */
+int parse_DA_values( char* inArg, unsigned int *DA_x0, unsigned int *DA_y0, unsigned int *DA_x1, unsigned int *DA_y1)
+{
+ int it = 0;
+ int values[4];
+ char delims[] = ",";
+ char *result = NULL;
+ result = strtok( inArg, delims );
+
+ while( (result != NULL) && (it < 4 ) ) {
+ values[it] = atoi(result);
+ result = strtok( NULL, delims );
+ it++;
+ }
+
+ if (it != 4) {
+ return EXIT_FAILURE;
+ }
+ else{
+ *DA_x0 = values[0]; *DA_y0 = values[1];
+ *DA_x1 = values[2]; *DA_y1 = values[3];
+ return EXIT_SUCCESS;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+/**
+sample error callback expecting a FILE* client object
+*/
+void error_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[ERROR] %s", msg);
+}
+/**
+sample warning callback expecting a FILE* client object
+*/
+void warning_callback(const char *msg, void *client_data) {
+ (void)client_data;
+ fprintf(stdout, "[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);
+}
+
+/* -------------------------------------------------------------------------- */
+/**
+ * J2K_TO_IMAGE MAIN
+ */
+/* -------------------------------------------------------------------------- */
+int main(int argc, char **argv)
+{
+ FILE *fsrc = NULL;
+
+ opj_dparameters_t parameters; /* decompression parameters */
+ opj_image_t* image = NULL;
+ opj_stream_t *l_stream = NULL; /* Stream */
+ opj_codec_t* l_codec = NULL; /* Handle to a decompressor */
+ opj_codestream_index_t* cstr_index = NULL;
+
+ char indexfilename[OPJ_PATH_LEN]; /* index file name */
+
+ OPJ_INT32 num_images, imageno;
+ img_fol_t img_fol;
+ dircnt_t *dirptr = NULL;
+
+ /* set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* FIXME Initialize indexfilename and img_fol */
+ *indexfilename = 0;
+
+ /* Initialize img_fol */
+ memset(&img_fol,0,sizeof(img_fol_t));
+
+ /* parse input and get user encoding parameters */
+ if(parse_cmdline_decoder(argc, argv, &parameters,&img_fol, indexfilename) == 1) {
+ return EXIT_FAILURE;
+ }
+
+ /* Initialize reading of directory */
+ if(img_fol.set_imgdir==1){
+ int it_image;
+ 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 EXIT_FAILURE;
+ }
+ for(it_image=0;it_image<num_images;it_image++){
+ dirptr->filename[it_image] = dirptr->filename_buf + it_image*OPJ_PATH_LEN;
+ }
+ }
+ if(load_images(dirptr,img_fol.imgdirpath)==1){
+ return EXIT_FAILURE;
+ }
+ if (num_images==0){
+ fprintf(stdout,"Folder is empty\n");
+ return EXIT_FAILURE;
+ }
+ }else{
+ num_images=1;
+ }
+
+ /*Decoding image one by one*/
+ for(imageno = 0; imageno < num_images ; imageno++) {
+
+ fprintf(stderr,"\n");
+
+ if(img_fol.set_imgdir==1){
+ if (get_next_file(imageno, dirptr,&img_fol, &parameters)) {
+ 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 EXIT_FAILURE;
+ }
+
+ l_stream = opj_stream_create_default_file_stream(fsrc,1);
+ if (!l_stream){
+ fclose(fsrc);
+ fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
+ return EXIT_FAILURE;
+ }
+
+ /* decode the JPEG2000 stream */
+ /* ---------------------- */
+
+ switch(parameters.decod_format) {
+ case J2K_CFMT: /* JPEG-2000 codestream */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_J2K);
+ break;
+ }
+ case JP2_CFMT: /* JPEG 2000 compressed image data */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_JP2);
+ break;
+ }
+ case JPT_CFMT: /* JPEG 2000, JPIP */
+ {
+ /* Get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_JPT);
+ break;
+ }
+ default:
+ fprintf(stderr, "skipping file..\n");
+ opj_stream_destroy(l_stream);
+ continue;
+ }
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_info_handler(l_codec, info_callback,00);
+ opj_set_warning_handler(l_codec, warning_callback,00);
+ opj_set_error_handler(l_codec, error_callback,00);
+
+ /* Setup the decoder decoding parameters using user parameters */
+ if ( !opj_setup_decoder(l_codec, &parameters) ){
+ fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n");
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+ opj_destroy_codec(l_codec);
+ return EXIT_FAILURE;
+ }
+
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if(! opj_read_header(l_stream, l_codec, &image)){
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to read the header\n");
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ return EXIT_FAILURE;
+ }
+
+ if (!parameters.nb_tile_to_decode) {
+ /* Optional if you want decode the entire image */
+ if (!opj_set_decode_area(l_codec, image, parameters.DA_x0,
+ parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ fclose(fsrc);
+ return EXIT_FAILURE;
+ }
+
+ /* Get the decoded image */
+ if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec, l_stream))) {
+ fprintf(stderr,"ERROR -> j2k_to_image: failed to decode image!\n");
+ opj_destroy_codec(l_codec);
+ opj_stream_destroy(l_stream);
+ opj_image_destroy(image);
+ fclose(fsrc);
+ return EXIT_FAILURE;
+ }
+ }
+ else {
+
+ /* It is just here to illustrate how to use the resolution after set parameters */
+ /*if (!opj_set_decoded_resolution_factor(l_codec, 5)) {
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to set the resolution factor tile!\n");
+ opj_destroy_codec(l_codec);
+ opj_stream_destroy(l_stream);
+ opj_image_destroy(image);
+ fclose(fsrc);
+ return EXIT_FAILURE;
+ }*/
+
+ if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to decode tile!\n");
+ opj_destroy_codec(l_codec);
+ opj_stream_destroy(l_stream);
+ opj_image_destroy(image);
+ fclose(fsrc);
+ return EXIT_FAILURE;
+ }
+ fprintf(stdout, "tile %d is decoded!\n\n", parameters.tile_index);
+ }
+
+ /* Close the byte stream */
+ opj_stream_destroy(l_stream);
+ fclose(fsrc);
+
+ if(image->color_space == CLRSPC_SYCC){
+ color_sycc_to_rgb(image); /* FIXME */
+ }
+
+ if(image->icc_profile_buf) {
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ color_apply_icc_profile(image); /* FIXME */
+#endif
+ free(image->icc_profile_buf);
+ image->icc_profile_buf = NULL; image->icc_profile_len = 0;
+ }
+
+ /* 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;
+#ifdef HAVE_LIBTIFF
+ 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;
+#endif /* HAVE_LIBTIFF */
+ 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 RAWL_DFMT: /* RAWL */
+ if(imagetorawl(image, parameters.outfile)){
+ fprintf(stdout,"Error generating rawl 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;
+#ifdef HAVE_LIBPNG
+ case PNG_DFMT: /* PNG */
+ if(imagetopng(image, parameters.outfile)){
+ fprintf(stdout,"Error generating png file. Outfile %s not generated\n",parameters.outfile);
+ }
+ else {
+ fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile);
+ }
+ break;
+#endif /* HAVE_LIBPNG */
+/* Can happen if output file is TIFF or PNG
+ * and HAVE_LIBTIF or HAVE_LIBPNG is undefined
+*/
+ default:
+ fprintf(stderr,"Outfile %s not generated\n",parameters.outfile);
+ }
+
+ /* free remaining structures */
+ if (l_codec) {
+ opj_destroy_codec(l_codec);
+ }
+
+
+ /* free image data structure */
+ opj_image_destroy(image);
+
+ /* destroy the codestream index */
+ opj_destroy_cstr_index(&cstr_index);
+
+ }
+ return EXIT_SUCCESS;
+}
+/*end main*/
+
+
+
+
diff --git a/src/bin/jp2/windirent.h b/src/bin/jp2/windirent.h
new file mode 100644
index 00000000..944b7d71
--- /dev/null
+++ b/src/bin/jp2/windirent.h
@@ -0,0 +1,679 @@
+
+/*
+ * 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 <tronkko@messi.uku.fi>
+ *
+ * $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(__MINGW32__) /* MinGW */
+ /* 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__)) && !defined(__linux__) /* 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 <dirent.h>
+# 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 <ndir.h>
+# define NAMLEN(dp) ((int)((dp)->d_namlen))
+
+#elif defined(HAVE_SYS_NDIR_H)
+# include <sys/ndir.h>
+# define NAMLEN(dp) ((int)((dp)->d_namlen))
+
+#elif defined(HAVE_DIRECT_H)
+# include <direct.h>
+# define NAMLEN(dp) ((int)((dp)->d_namlen))
+
+#elif defined(HAVE_DIR_H)
+# include <dir.h>
+# define NAMLEN(dp) ((int)((dp)->d_namlen))
+
+#elif defined(HAVE_SYS_DIR_H)
+# include <sys/types.h>
+# include <sys/dir.h>
+# 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 <windows.h>
+# if !defined(DIRENT_MAXNAMLEN)
+# define DIRENT_MAXNAMLEN (MAX_PATH)
+# endif
+
+
+ /*** MS-DOS specifics ***/
+# elif defined(DIRENT_MSDOS_INTERFACE)
+# include <dos.h>
+
+ /* Borland defines file length macros in dir.h */
+# if defined(__BORLANDC__)
+# include <dir.h>
+# 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 <dir.h>
+# 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+/* 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);
+
+/*
+ * <function name="opendir">
+ * <intro>open directory stream for reading
+ * <syntax>DIR *opendir (const char *dirname);
+ *
+ * <desc>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.
+ *
+ * <ret>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:
+ *
+ * <table>
+ * [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.]
+ * </table>
+ * </function>
+ */
+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;
+}
+
+
+/*
+ * <function name="readdir">
+ * <intro>read a directory entry
+ * <syntax>struct dirent *readdir (DIR *dirp);
+ *
+ * <desc>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.
+ *
+ * <ret>
+ * 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:
+ *
+ * <table>
+ * [EBADF |dir parameter refers to an invalid directory stream. This value
+ * is not set reliably on all implementations.]
+ * </table>
+ * </function>
+ */
+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;
+}
+
+
+/*
+ * <function name="closedir">
+ * <intro>close directory stream.
+ * <syntax>int closedir (DIR *dirp);
+ *
+ * <desc>Close directory stream opened by the `opendir' function. Close of
+ * directory stream invalidates the DIR structure as well as previously read
+ * dirent entry.
+ *
+ * <ret>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.
+ * </function>
+ */
+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;
+}
+
+
+/*
+ * <function name="rewinddir">
+ * <intro>rewind directory stream to the beginning
+ * <syntax>void rewinddir (DIR *dirp);
+ *
+ * <desc>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.
+ *
+ * <ret>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/src/bin/jpip/CMakeLists.txt b/src/bin/jpip/CMakeLists.txt
new file mode 100644
index 00000000..5a3fc0ff
--- /dev/null
+++ b/src/bin/jpip/CMakeLists.txt
@@ -0,0 +1,150 @@
+# Headers file are located here:
+include_directories(
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2 # opj_stdint.h
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjpip
+ ${FCGI_INCLUDE_DIRS}
+)
+
+# Tool to embed metadata into JP2 file
+add_executable(addXMLinJP2 addXMLinJP2.c)
+# Install exe
+install(TARGETS addXMLinJP2
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ )
+
+if(BUILD_JPIP_SERVER)
+
+ set(OPJ_SERVER_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_server.c
+ )
+
+ # Build executable
+ add_executable(opj_server ${OPJ_SERVER_SRCS})
+ target_link_libraries(opj_server openjpip_server)
+ set_property(
+ TARGET opj_server
+ APPEND PROPERTY
+ COMPILE_DEFINITIONS SERVER QUIT_SIGNAL="quitJPIP"
+ )
+
+ # On unix you need to link to the math library:
+ if(UNIX)
+ target_link_libraries(opj_server m)
+ endif()
+
+ # Install exe
+ install(TARGETS opj_server
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ )
+endif()
+
+set(EXES
+ opj_dec_server
+ jpip_to_jp2
+ jpip_to_j2k
+ test_index
+ )
+foreach(exe ${EXES})
+ add_executable(${exe} ${exe}.c)
+ target_link_libraries(${exe} openjpip_local)
+ install(TARGETS ${exe}
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ )
+endforeach()
+
+# Build the two java clients:
+find_package(Java 1.5 COMPONENTS Development) # javac, jar
+
+# Only build the java viewer if dev is found:
+if(Java_Development_FOUND AND Java_JAVAC_EXECUTABLE)
+ set(jflags $ENV{JFLAGS})
+ # 1. opj_viewer
+ # build dep list:
+ file(GLOB java1_srcs "opj_viewer/src/*.java")
+
+ # make sure target javac dir exists:
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/classes1)
+ # Build java
+ add_custom_command(
+ OUTPUT ${LIBRARY_OUTPUT_PATH}/opj_viewer.jar
+ COMMAND ${Java_JAVAC_EXECUTABLE} ${jflags}
+ ${java1_srcs} -d ${CMAKE_CURRENT_BINARY_DIR}/classes1
+ COMMAND ${Java_JAR_EXECUTABLE} cfm ${LIBRARY_OUTPUT_PATH}/opj_viewer.jar
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/dist/manifest.txt -C
+ ${CMAKE_CURRENT_BINARY_DIR}/classes1 .
+ DEPENDS ${java1_srcs}
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/dist/manifest.txt
+ COMMENT "javac *.java; jar cvf -> opj_viewer.jar"
+ )
+
+ # name the target
+ add_custom_target(OPJViewerJar ALL
+ DEPENDS ${LIBRARY_OUTPUT_PATH}/opj_viewer.jar
+ COMMENT "building opj_viewer.jar"
+ )
+
+ install(FILES ${LIBRARY_OUTPUT_PATH}/opj_viewer.jar
+ DESTINATION ${OPENJPEG_INSTALL_SHARE_DIR} COMPONENT JavaModule
+ )
+
+ # 2. opj_viewer_xerces
+ # search for package org.apache.xerces.parsers
+ find_file(APACHE_XERCES_JAR
+ NAMES xerces-j2.jar xercesImpl.jar
+ PATHS /usr/share/java/
+ NO_DEFAULT_PATH
+ )
+ mark_as_advanced(APACHE_XERCES_JAR)
+
+ if(EXISTS ${APACHE_XERCES_JAR})
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer_xerces/dist/manifest.txt.in
+ ${CMAKE_CURRENT_BINARY_DIR}/opj_viewer_xerces/dist/manifest.txt
+ @ONLY
+ )
+ # build dep list:
+ file(GLOB java2_srcs "opj_viewer_xerces/src/*.java")
+
+ # Need some common files:
+ list(APPEND java2_srcs
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/ImageManager.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/ImgdecClient.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/JPIPHttpClient.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/MML.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/PnmImage.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/RegimViewer.java
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer/src/ResizeListener.java
+ )
+
+ # make sure target javac dir exists:
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/classes2)
+ # Build java
+ add_custom_command(
+ OUTPUT ${LIBRARY_OUTPUT_PATH}/opj_viewer_xerces.jar
+ COMMAND ${Java_JAVAC_EXECUTABLE} ${jflags}
+ -classpath ${APACHE_XERCES_JAR}
+ ${java2_srcs} -d ${CMAKE_CURRENT_BINARY_DIR}/classes2
+ COMMAND ${Java_JAR_EXECUTABLE} cfm ${LIBRARY_OUTPUT_PATH}/opj_viewer_xerces.jar
+ ${CMAKE_CURRENT_BINARY_DIR}/opj_viewer_xerces/dist/manifest.txt
+ -C ${CMAKE_CURRENT_BINARY_DIR}/classes2 .
+ DEPENDS ${java2_srcs}
+ ${CMAKE_CURRENT_SOURCE_DIR}/opj_viewer_xerces/dist/manifest.txt.in
+ COMMENT "javac *.java; jar cvf -> opj_viewer_xerces.jar"
+ )
+
+ # name the target
+ add_custom_target(OPJViewerXercesJar ALL
+ DEPENDS ${LIBRARY_OUTPUT_PATH}/opj_viewer_xerces.jar
+ COMMENT "building opj_viewer_xerces.jar"
+ )
+
+ install(FILES ${LIBRARY_OUTPUT_PATH}/opj_viewer_xerces.jar
+ DESTINATION ${OPENJPEG_INSTALL_SHARE_DIR} COMPONENT JavaModule
+ )
+ endif()
+else()
+ message(WARNING "No java compiler found. Wont be able to build java viewer")
+endif()
diff --git a/src/bin/jpip/Makefile.am b/src/bin/jpip/Makefile.am
new file mode 100644
index 00000000..0e98b71e
--- /dev/null
+++ b/src/bin/jpip/Makefile.am
@@ -0,0 +1,85 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+bin_PROGRAMS =
+
+if WANT_JPIP
+bin_PROGRAMS += opj_dec_server test_index jpip_to_j2k jpip_to_jp2
+endif
+
+if WANT_JPIP_SERVER
+bin_PROGRAMS += opj_server
+endif
+
+opj_server_CPPFLAGS = \
+@FCGI_CFLAGS@ \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip \
+-DSERVER \
+-DQUIT_SIGNAL=\"quitJPIP\"
+#
+opj_server_LDADD = $(top_builddir)/applications/jpip/libopenjpip/libopenjpip_server.la @FCGI_LIBS@ -lm
+#
+opj_server_SOURCES = opj_server.c
+
+#-------------
+opj_dec_server_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip
+#
+opj_dec_server_CFLAGS =
+opj_dec_server_LDADD = $(top_builddir)/applications/jpip/libopenjpip/libopenjpip_local.la
+opj_dec_server_SOURCES = opj_dec_server.c
+
+#-------------
+jpip_to_jp2_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip
+#
+jpip_to_jp2_CFLAGS =
+jpip_to_jp2_LDADD = $(top_builddir)/applications/jpip/libopenjpip/libopenjpip_local.la
+jpip_to_jp2_SOURCES = jpip_to_jp2.c
+
+#-------------
+jpip_to_j2k_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip
+#
+jpip_to_j2k_CFLAGS =
+jpip_to_j2k_LDADD = $(top_builddir)/applications/jpip/libopenjpip/libopenjpip_local.la
+jpip_to_j2k_SOURCES = jpip_to_j2k.c
+
+#-------------
+test_index_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip
+#
+test_index_CFLAGS =
+test_index_LDADD = $(top_builddir)/applications/jpip/libopenjpip/libopenjpip_local.la
+test_index_SOURCES = test_index.c
+
+#-------------
+install-data-hook:
+if WANT_JPIP_SERVER
+ @echo -e " (B)\t$(bindir)/opj_server$(EXEEXT)" >> $(top_builddir)/report.txt
+endif
+if WANT_JPIP
+ @echo -e " (B)\t$(bindir)/opj_dec_server$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/jpip_to_jp2$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/jpip_to_j2k$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/test_index$(EXEEXT)" >> $(top_builddir)/report.txt
+endif
diff --git a/src/bin/jpip/addXMLinJP2.c b/src/bin/jpip/addXMLinJP2.c
new file mode 100644
index 00000000..f136e913
--- /dev/null
+++ b/src/bin/jpip/addXMLinJP2.c
@@ -0,0 +1,181 @@
+/*
+ * $Id: addXMLinJP2.c 46 2011-02-17 14:50:55Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief addXMLinJP2 is a program to embed metadata into JP2 file
+ *
+ * \section impinst Implementing instructions
+ * This program takes two arguments. \n
+ * -# Input/output image file in JP2 format, this JP2 file is being modified
+ * -# Input XML file with metadata contents\n
+ * % ./addXMLinJP2 image.jp2 metadata.xml\n
+ *
+ * Currently, this program does not parse XML file, and the XML file contents is directly embedded as a XML Box.\n
+ * The following is an example of XML file contents specifying Region Of Interests with target names.\n
+ * <xmlbox>\n
+ * <roi name="island" x="1890" y="1950" w="770" h="310"/>\n
+ * <roi name="ship" x="750" y="330" w="100" h="60"/>\n
+ * <roi name="airport" x="650" y="1800" w="650" h="800"/>\n
+ * <roi name="harbor" x="4200" y="1650" w="130" h="130"/>\n
+ * </xmlbox>
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/**
+ * Open JP2 file with the check of JP2 header
+ *
+ * @param[in] filename file name string
+ * @return file descriptor
+ */
+FILE * open_jp2file( const char filename[]);
+
+
+/**
+ * read xml file without any format check for the moment
+ *
+ * @param[in] filename file name string
+ * @param[out] fsize file byte size
+ * @return pointer to the xml file content buffer
+ */
+char * read_xmlfile( const char filename[], long *fsize);
+
+int main(int argc, char *argv[])
+{
+ FILE *fp;
+ char *xmldata, type[]="xml ";
+ long fsize, boxsize;
+
+ if( argc<3){
+ fprintf( stderr, "USAGE: ./addXMLinJP2 modifing.jp2 adding.xml\n");
+ return -1;
+ }
+
+ fp = open_jp2file( argv[1]);
+ if( !fp)
+ return -1;
+
+ xmldata = read_xmlfile( argv[2], &fsize);
+ boxsize = fsize + 8;
+
+ fputc( (boxsize>>24)&0xff, fp);
+ fputc( (boxsize>>16)&0xff, fp);
+ fputc( (boxsize>>8)&0xff, fp);
+ fputc( boxsize&0xff, fp);
+ fwrite( type, 4, 1, fp);
+ fwrite( xmldata, fsize, 1, fp);
+
+ free( xmldata);
+ fclose(fp);
+
+ return 0;
+}
+
+FILE * open_jp2file( const char filename[])
+{
+ FILE *fp;
+ char *data;
+
+ if( !(fp = fopen( filename, "a+b"))){
+ fprintf( stderr, "Original JP2 %s not found\n", filename);
+ return NULL;
+ }
+ /* Check resource is a JP family file. */
+ if( fseek( fp, 0, SEEK_SET)==-1){
+ fclose(fp);
+ fprintf( stderr, "Original JP2 %s broken (fseek error)\n", filename);
+ return NULL;
+ }
+
+ data = (char *)malloc( 12); /* size of header */
+ if( fread( data, 12, 1, fp) != 1){
+ free( data);
+ fclose(fp);
+ fprintf( stderr, "Original JP2 %s broken (read error)\n", filename);
+ return NULL;
+ }
+
+ if( *data || *(data + 1) || *(data + 2) ||
+ *(data + 3) != 12 || strncmp (data + 4, "jP \r\n\x87\n", 8)){
+ free( data);
+ fclose(fp);
+ fprintf( stderr, "No JPEG 2000 Signature box in target %s\n", filename);
+ return NULL;
+ }
+ free( data);
+ return fp;
+}
+
+char * read_xmlfile( const char filename[], long *fsize)
+{
+ FILE *fp;
+ char *data;
+
+ /* fprintf( stderr, "open %s\n", filename);*/
+ if(!(fp = fopen( filename, "r"))){
+ fprintf( stderr, "XML file %s not found\n", filename);
+ return NULL;
+ }
+
+ if( fseek( fp, 0, SEEK_END) == -1){
+ fprintf( stderr, "XML file %s broken (seek error)\n", filename);
+ fclose( fp);
+ return NULL;
+ }
+
+ if( (*fsize = ftell( fp)) == -1){
+ fprintf( stderr, "XML file %s broken (seek error)\n", filename);
+ fclose( fp);
+ return NULL;
+ }
+
+ if( fseek( fp, 0, SEEK_SET) == -1){
+ fprintf( stderr, "XML file %s broken (seek error)\n", filename);
+ fclose( fp);
+ return NULL;
+ }
+
+ data = (char *)malloc( *fsize);
+
+ if( fread( data, *fsize, 1, fp) != 1){
+ fprintf( stderr, "XML file %s broken (read error)\n", filename);
+ free( data);
+ fclose(fp);
+ return NULL;
+ }
+
+ fclose( fp);
+
+ return data;
+}
diff --git a/src/bin/jpip/jpip_to_j2k.c b/src/bin/jpip/jpip_to_j2k.c
new file mode 100644
index 00000000..d8b2e2b0
--- /dev/null
+++ b/src/bin/jpip/jpip_to_j2k.c
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief jpip_to_j2k is a program to convert JPT- JPP- stream to J2K file
+ *
+ * \section impinst Implementing instructions
+ * This program takes two arguments. \n
+ * -# Input JPT or JPP file
+ * -# Output J2K file\n
+ * % ./jpip_to_j2k input.jpt output.j2k
+ * or
+ * % ./jpip_to_j2k input.jpp output.j2k
+ */
+
+#include <stdio.h>
+#include "openjpip.h"
+
+int main(int argc,char *argv[])
+{
+ jpip_dec_param_t *dec;
+
+ if( argc < 3){
+ fprintf( stderr, "Too few arguments:\n");
+ fprintf( stderr, " - input jpt or jpp file\n");
+ fprintf( stderr, " - output j2k file\n");
+ return -1;
+ }
+
+ dec = init_jpipdecoder( false);
+
+ if(!( fread_jpip( argv[1], dec)))
+ return -1;
+
+ decode_jpip( dec);
+
+ if(!( fwrite_jp2k( argv[2], dec)))
+ return -1;
+
+ /* output_log( true, false, false, dec); */
+
+ destroy_jpipdecoder( &dec);
+
+ return 0;
+}
diff --git a/src/bin/jpip/jpip_to_jp2.c b/src/bin/jpip/jpip_to_jp2.c
new file mode 100644
index 00000000..d667ed9d
--- /dev/null
+++ b/src/bin/jpip/jpip_to_jp2.c
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief jpip_to_jp2 is a program to convert JPT- JPP- stream to JP2 file
+ *
+ * \section impinst Implementing instructions
+ * This program takes two arguments. \n
+ * -# Input JPT or JPP file
+ * -# Output JP2 file\n
+ * % ./jpip_to_jp2 input.jpt output.jp2
+ * or
+ * % ./jpip_to_jp2 input.jpp output.jp2
+ */
+
+#include <stdio.h>
+#include "openjpip.h"
+
+int main(int argc,char *argv[])
+{
+ jpip_dec_param_t *dec;
+
+ if( argc < 3){
+ fprintf( stderr, "Too few arguments:\n");
+ fprintf( stderr, " - input jpt or jpp file\n");
+ fprintf( stderr, " - output jp2 file\n");
+ return -1;
+ }
+
+ dec = init_jpipdecoder( true);
+
+ if(!( fread_jpip( argv[1], dec)))
+ return -1;
+
+ decode_jpip( dec);
+
+ if(!(fwrite_jp2k( argv[2], dec)))
+ return -1;
+
+ output_log( true, false, true, dec);
+
+ destroy_jpipdecoder( &dec);
+
+ return 0;
+}
diff --git a/src/bin/jpip/opj_dec_server.c b/src/bin/jpip/opj_dec_server.c
new file mode 100644
index 00000000..b41ef0c9
--- /dev/null
+++ b/src/bin/jpip/opj_dec_server.c
@@ -0,0 +1,92 @@
+/*
+ * $Id: opj_dec_server.c 54 2011-05-10 13:22:47Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief opj_dec_server is a server to decode JPT-stream and communicate locally with JPIP client, which is coded in java.
+ *
+ * \section impinst Implementing instructions
+ * Launch opj_dec_server from a terminal in the same machine as JPIP client image viewers. \n
+ * % ./opj_dec_server [portnumber]\n
+ * ( portnumber=50000 by default)\n
+ * Keep it alive as long as image viewers are open.\n
+ *
+ * To quite the opj_dec_server, send a message "quit" through the telnet.\n
+ * % telnet localhost 50000\n
+ * quit\n
+ * Be sure all image viewers are closed.\n
+ * Cache file in JPT format is stored in the working directly before it quites.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "openjpip.h"
+
+#ifdef _WIN32
+WSADATA initialisation_win32;
+#endif
+
+int main(int argc, char *argv[]){
+
+ dec_server_record_t *server_record;
+ client_t client;
+ int port = 50000;
+ int erreur;
+ (void)erreur;
+
+ if( argc > 1)
+ port = atoi( argv[1]);
+
+#ifdef _WIN32
+ erreur = WSAStartup(MAKEWORD(2,2),&initialisation_win32);
+ if( erreur!=0)
+ fprintf( stderr, "Erreur initialisation Winsock error : %d %d\n",erreur,WSAGetLastError());
+ else
+ printf( "Initialisation Winsock\n");
+#endif /*_WIN32*/
+
+ server_record = init_dec_server( port);
+
+ while(( client = accept_connection( server_record)) != -1 )
+ if(!handle_clientreq( client, server_record))
+ break;
+
+ terminate_dec_server( &server_record);
+
+#ifdef _WIN32
+ if( WSACleanup() != 0){
+ printf("\nError in WSACleanup : %d %d",erreur,WSAGetLastError());
+ }else{
+ printf("\nWSACleanup OK\n");
+ }
+#endif
+
+ return 0;
+}
diff --git a/src/bin/jpip/opj_server.c b/src/bin/jpip/opj_server.c
new file mode 100644
index 00000000..1666a94f
--- /dev/null
+++ b/src/bin/jpip/opj_server.c
@@ -0,0 +1,127 @@
+/*
+ * $Id: opj_server.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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.
+ */
+
+/*! \file
+ * \brief opj_server is a JPIP server program, which supports HTTP connection, JPT-stream, session, channels, and cache model managements.
+ *
+ * \section req Requirements
+ * FastCGI development kit (http://www.fastcgi.com).
+ *
+ * \section impinst Implementing instructions
+ * Launch opj_server from the server terminal:\n
+ * % spawn-fcgi -f ./opj_server -p 3000 -n
+ *
+ * Note: JP2 files are stored in the working directory of opj_server\n
+ * Check README for the JP2 Encoding\n
+ *
+ * We tested this software with a virtual server running on the same Linux machine as the clients.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "openjpip.h"
+
+#ifndef QUIT_SIGNAL
+#define QUIT_SIGNAL "quitJPIP"
+#endif
+
+#ifdef _WIN32
+WSADATA initialisation_win32;
+#endif /*_WIN32*/
+
+int main(void)
+{
+ server_record_t *server_record;
+#ifdef SERVER
+ char *query_string;
+#endif
+
+#ifdef _WIN32
+ int erreur = WSAStartup(MAKEWORD(2,2),&initialisation_win32);
+ if( erreur!=0)
+ fprintf( stderr, "Erreur initialisation Winsock error : %d %d\n",erreur,WSAGetLastError());
+ else
+ fprintf( stderr, "Initialisation Winsock\n");
+#endif /*_WIN32*/
+
+ server_record = init_JPIPserver( 60000, 0);
+
+#ifdef SERVER
+ while(FCGI_Accept() >= 0)
+#else
+
+ char query_string[128];
+ while( fgets( query_string, 128, stdin) && query_string[0]!='\n')
+#endif
+ {
+ QR_t *qr;
+ bool parse_status;
+
+#ifdef SERVER
+ query_string = getenv("QUERY_STRING");
+#endif /*SERVER*/
+
+ if( strcmp( query_string, QUIT_SIGNAL) == 0)
+ break;
+
+ qr = parse_querystring( query_string);
+
+ parse_status = process_JPIPrequest( server_record, qr);
+
+#ifndef SERVER
+ local_log( true, true, parse_status, false, qr, server_record);
+#endif
+
+ if( parse_status)
+ send_responsedata( server_record, qr);
+ else{
+ fprintf( FCGI_stderr, "Error: JPIP request failed\n");
+ fprintf( FCGI_stdout, "\r\n");
+ }
+
+ end_QRprocess( server_record, &qr);
+ }
+
+ fprintf( FCGI_stderr, "JPIP server terminated by a client request\n");
+
+ terminate_JPIPserver( &server_record);
+
+#ifdef _WIN32
+ if( WSACleanup() != 0){
+ fprintf( stderr, "\nError in WSACleanup : %d %d",erreur,WSAGetLastError());
+ }else{
+ fprintf( stderr, "\nWSACleanup OK\n");
+ }
+#endif
+
+ return 0;
+}
diff --git a/src/bin/jpip/opj_viewer/dist/manifest.txt b/src/bin/jpip/opj_viewer/dist/manifest.txt
new file mode 100644
index 00000000..537c33dd
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/dist/manifest.txt
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Ant-Version: Apache Ant 1.7.0
+Created-By: Kaori Hagihara
+Main-Class: ImageWindow
diff --git a/src/bin/jpip/opj_viewer/src/ImageManager.java b/src/bin/jpip/opj_viewer/src/ImageManager.java
new file mode 100644
index 00000000..aad3ffaa
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/ImageManager.java
@@ -0,0 +1,136 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.Image;
+
+public class ImageManager extends JPIPHttpClient
+{
+ private PnmImage pnmimage;
+ private int origwidth;
+ private int origheight;
+ private ImgdecClient imgdecoder;
+
+ public ImageManager( String uri, String host, int port)
+ {
+ super( uri);
+ imgdecoder = new ImgdecClient( host, port);
+ pnmimage = null;
+ origwidth = 0;
+ origheight = 0;
+ }
+
+ public int getOrigWidth(){
+ if( origwidth == 0){
+ if( cid != null || tid != null){
+ java.awt.Dimension dim = imgdecoder.query_imagesize( cid, tid);
+ if( dim != null){
+ origwidth = dim.width;
+ origheight = dim.height;
+ }
+ }
+ else
+ System.err.println("Neither cid or tid obtained before to get Original Image Dimension");
+ }
+ return origwidth;
+ }
+ public int getOrigHeight(){ return origheight;}
+
+ public Image getImage( String j2kfilename, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ System.err.println();
+
+ String refcid = null;
+ byte[] jpipstream;
+
+ // Todo: check if the cid is for the same stream type
+ if( reqcnew)
+ refcid = imgdecoder.query_cid( j2kfilename);
+
+ if( refcid == null){
+ String reftid = imgdecoder.query_tid( j2kfilename);
+ if( reftid == null)
+ jpipstream = super.requestViewWindow( j2kfilename, reqfw, reqfh, reqcnew, reqaux, reqJPP, reqJPT);
+ else
+ jpipstream = super.requestViewWindow( j2kfilename, reftid, reqfw, reqfh, reqcnew, reqaux, reqJPP, reqJPT);
+ }
+ else
+ jpipstream = super.requestViewWindow( reqfw, reqfh, refcid, reqcnew, reqaux, reqJPP, reqJPT);
+
+ System.err.println( "decoding to PNM image");
+ if((pnmimage = imgdecoder.decode_jpipstream( jpipstream, j2kfilename, tid, cid, fw, fh))!=null){
+ System.err.println( " done");
+ return pnmimage.createROIImage( rx, ry, rw, rh);
+ }
+ else{
+ System.err.println( " failed");
+ return null;
+ }
+ }
+
+ public Image getImage( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh)
+ {
+ System.err.println();
+
+ byte[] jpipstream = super.requestViewWindow( reqfw, reqfh, reqrx, reqry, reqrw, reqrh);
+
+ System.err.println( "decoding to PNM image");
+ if((pnmimage = imgdecoder.decode_jpipstream( jpipstream, tid, cid, fw, fh)) != null){
+ System.err.println( " done");
+ return pnmimage.createROIImage( rx, ry, rw, rh);
+ }
+ else{
+ System.err.println( " failed");
+ return null;
+ }
+ }
+
+ public byte[] getXML()
+ {
+ System.err.println();
+
+ byte []xmldata = null;
+ byte[] jpipstream = super.requestXML();
+
+ if( jpipstream != null){
+ imgdecoder.send_JPIPstream( jpipstream);
+
+ xmldata = imgdecoder.get_XMLstream( cid);
+ }
+ return xmldata;
+ }
+
+ public void closeChannel()
+ {
+ if( cid != null){
+ imgdecoder.destroy_cid( cid);
+ super.closeChannel();
+ }
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/ImageViewer.java b/src/bin/jpip/opj_viewer/src/ImageViewer.java
new file mode 100644
index 00000000..163193b9
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/ImageViewer.java
@@ -0,0 +1,266 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.awt.image.*;
+import java.awt.geom.*;
+import java.net.URL;
+import javax.swing.border.*;
+import java.util.*;
+import java.io.*;
+
+public class ImageViewer extends JPanel
+{
+ private ImageManager imgmanager;
+ private int vw, vh;
+ private int iw, ih;
+ private int selected = 0;
+ private Image img;
+
+ private String cmdline = new String();
+ private boolean fullRefresh = false;
+ private Point offset = new Point(0,0);
+ private Rectangle rect = new Rectangle();
+ private Rectangle roirect[] = null;
+ private String roiname[] = null;
+
+ public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream, int aux)
+ {
+ String str;
+ MML myMML;
+
+ this.setSize( 170, 170);
+ Dimension asz = this.getSize();
+
+ vw = asz.width;
+ vh = asz.height;
+
+ setBackground(Color.black);
+ myMML = new MML(this);
+
+ imgmanager = manager;
+
+ img = imgmanager.getImage( j2kfilename, vw, vh, session, aux, jppstream, !jppstream);
+
+ addMouseListener(myMML);
+ addMouseMotionListener(myMML);
+ addComponentListener( new ResizeListener(this));
+ }
+
+ public Image getImage()
+ {
+ return img;
+ }
+
+ public void zoomIn()
+ {
+ roirect = null;
+ roiname = null;
+
+ double scalex = (double)vw/(double)rect.width;
+ double scaley = (double)vh/(double)rect.height;
+
+ int fw = (int)(imgmanager.getFw()*scalex);
+ int fh = (int)(imgmanager.getFh()*scaley);
+ int rx = (int)((imgmanager.getRx()+rect.x)*scalex);
+ int ry = (int)((imgmanager.getRy()+rect.y)*scaley);
+
+ img = imgmanager.getImage( fw, fh, rx, ry, vw, vh);
+
+ rect.x = rect.y = rect.width = rect.height = 0;
+
+ selected = 0;
+ fullRefresh = true;
+ repaint();
+ }
+
+ public void enlarge()
+ {
+ roirect = null;
+ roiname = null;
+
+ Dimension asz = this.getSize();
+
+ vw = asz.width;
+ vh = asz.height;
+
+ double scalex = vw/(double)imgmanager.getRw();
+ double scaley = vh/(double)imgmanager.getRh();
+
+ int fw = (int)(imgmanager.getFw()*scalex);
+ int fh = (int)(imgmanager.getFh()*scaley);
+ int rx = (int)(imgmanager.getRx()*scalex);
+ int ry = (int)(imgmanager.getRy()*scaley);
+
+ img = imgmanager.getImage( fw, fh, rx, ry, vw, vh);
+
+ fullRefresh = true;
+ repaint();
+ }
+
+ public void setSelected(int state)
+ {
+ roirect = null;
+ roiname = null;
+
+ if (state != selected) {
+
+ selected = state;
+ repaint();
+ }
+ }
+
+ public boolean isInsideRect(int x, int y)
+ {
+ return rect.contains(x - offset.x, y - offset.y);
+ }
+
+ public void setRGeom(int x1, int y1, int x2, int y2)
+ {
+ rect.x = Math.min(x1,x2) - offset.x;
+ rect.y = Math.min(y1,y2) - offset.y;
+ rect.width = Math.abs(x2-x1);
+ rect.height = Math.abs(y2-y1);
+ }
+
+ // public void annotate( JP2XMLparser.ROIparams roi[])
+ // {
+ // int numofroi = roi.length;
+
+ // roirect = new Rectangle [numofroi];
+ // roiname = new String [numofroi];
+
+ // double scale_x = imgmanager.getFw()/(double)imgmanager.getOrigWidth();
+ // double scale_y = imgmanager.getFh()/(double)imgmanager.getOrigHeight();
+ // int rx = imgmanager.getRx();
+ // int ry = imgmanager.getRy();
+ // int rw = imgmanager.getRw();
+ // int rh = imgmanager.getRh();
+
+ // for( int i=0; i<numofroi ; i++){
+ // int x = (int)(roi[i].x*scale_x) - rx;
+ // int y = (int)(roi[i].y*scale_y) - ry;
+ // int w = (int)(roi[i].w*scale_x);
+ // int h = (int)(roi[i].h*scale_y);
+ // if( 0<=x && 0<=y && x+w<=rw && y+h<=rh){ // can be optimized
+ // roirect[i] = new Rectangle( x, y, w, h);
+ // roiname[i] = new String( roi[i].name);
+ // }
+ // else{
+ // roirect[i] = null;
+ // roiname[i] = null;
+ // }
+ // }
+ // repaint();
+ // }
+
+ public boolean hasAnnotation()
+ {
+ if( roirect == null)
+ return false;
+ else
+ return true;
+ }
+
+ public boolean isInsideROIRect(int x, int y)
+ {
+ for( int i=0; i<roirect.length; i++)
+ if( roirect[i] != null)
+ if( roirect[i].contains(x - offset.x, y - offset.y)){
+ rect = roirect[i];
+ return true;
+ }
+ return false;
+ }
+
+ public void paint(Graphics g)
+ {
+ BufferedImage bi;
+ Graphics2D big;
+ Graphics2D g2 = (Graphics2D) g;
+
+ if (fullRefresh) {
+ g2.clearRect(0, 0, vw, vh);
+ fullRefresh = false;
+ }
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+
+ offset.x = 0;
+ offset.y = 0;
+
+ iw = img.getWidth(this);
+ ih = img.getHeight(this);
+
+ bi = new BufferedImage( iw, ih, BufferedImage.TYPE_INT_RGB);
+ big = bi.createGraphics();
+
+ big.drawImage(img, 0, 0, this);
+ big.setPaint(Color.red);
+ if ((rect.width > 0) && (rect.height > 0))
+ big.draw(rect);
+
+ if( roirect != null){
+ for( int i=0; i<roirect.length; i++)
+ if( roirect[i] != null){
+ big.draw( roirect[i]);
+ big.drawString( roiname[i], roirect[i].x+3, roirect[i].y+roirect[i].height*2/3);
+ }
+ }
+ if (selected == 1)
+ shadeExt(big, 0, 0, 0, 64);
+ else if (selected == 2) {
+ shadeExt(big, 0, 0, 0, 255);
+ selected = 1;
+ }
+ g2.drawImage(bi, offset.x, offset.y, this);
+ }
+
+ private void shadeRect(Graphics2D g2, int r, int g, int b, int a)
+ {
+ g2.setPaint(new Color(r, g, b, a));
+ g2.fillRect(rect.x + 1, rect.y + 1, rect.width - 1, rect.height - 1);
+ }
+
+ private void shadeExt(Graphics2D g2, int r, int g, int b, int a)
+ {
+ g2.setPaint(new Color(r, g, b, a));
+ g2.fillRect(0, 0, iw, rect.y); /* _N_ */
+ g2.fillRect(rect.x + rect.width + 1, rect.y,
+ iw - rect.x - rect.width - 1, rect.height + 1); /* E */
+ g2.fillRect(0, rect.y, rect.x, rect.height + 1); /* W */
+ g2.fillRect(0, rect.y + rect.height + 1,
+ iw, ih - rect.y - rect.height - 1); /* _S_ */
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/ImageWindow.java b/src/bin/jpip/opj_viewer/src/ImageWindow.java
new file mode 100644
index 00000000..9a236e4a
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/ImageWindow.java
@@ -0,0 +1,120 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+
+public class ImageWindow extends JFrame
+{
+ private ImageViewer imgviewer;
+ private ImageManager imgmanager;
+
+ public ImageWindow( String uri, String j2kfilename, String host, int port, boolean session, boolean jppstream, int aux)
+ {
+ super( j2kfilename);
+
+ imgmanager = new ImageManager( uri, host, port);
+
+ imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream, aux);
+ imgviewer.setOpaque(true); //content panes must be opaque
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.add( imgviewer, BorderLayout.CENTER);
+
+ setContentPane( panel);
+
+ addWindowListener(new WindowMyAdapter());
+ }
+
+ class WindowMyAdapter extends WindowAdapter
+ {
+ public void windowClosing(WindowEvent arg)
+ {
+ imgmanager.closeChannel();
+ System.exit(0);
+ }
+ }
+
+ public static void main(String s[])
+ {
+ String j2kfilename, uri, host;
+ boolean session, jppstream;
+ int port, aux; // 0: none, 1: tcp, 2: udp
+
+ if(s.length >= 2){
+ uri = s[0];
+ j2kfilename = s[1];
+
+ if( s.length > 2)
+ host = s[2];
+ else
+ host = "localhost";
+
+ if( s.length > 3)
+ port = Integer.valueOf( s[3]).intValue();
+ else
+ port = 50000;
+
+ if( s.length > 4)
+ session = !s[4].equalsIgnoreCase( "stateless");
+ else
+ session = true;
+
+ if( s.length > 5)
+ jppstream = !s[5].equalsIgnoreCase( "JPT");
+ else
+ jppstream = true;
+
+ if( s.length > 6){
+ if( s[6].equalsIgnoreCase("udp"))
+ aux = 2;
+ else
+ aux = 1;
+ }
+ else
+ aux = 0;
+ }
+ else{
+ System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [hostname] [portnumber] [stateless/session] [JPT/JPP] [tcp/udp]");
+ return;
+ }
+ ImageWindow frame = new ImageWindow( uri, j2kfilename, host, port, session, jppstream, aux);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ //Display the window.
+ frame.pack();
+ frame.setSize(new Dimension(400,200));
+ frame.setLocation( 0, 50);
+ frame.setVisible(true);
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/ImgdecClient.java b/src/bin/jpip/opj_viewer/src/ImgdecClient.java
new file mode 100644
index 00000000..edb64ded
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/ImgdecClient.java
@@ -0,0 +1,350 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class ImgdecClient{
+
+ private String hostname;
+ private int portNo;
+
+ public ImgdecClient( String host, int port)
+ {
+ hostname = host;
+ portNo = port;
+ }
+
+ public PnmImage decode_jpipstream( byte[] jpipstream, String tid, String cid, int fw, int fh)
+ {
+ if( jpipstream != null)
+ send_JPIPstream( jpipstream);
+ return get_PNMstream( cid, tid, fw, fh);
+ }
+
+ public PnmImage decode_jpipstream( byte[] jpipstream, String j2kfilename, String tid, String cid, int fw, int fh)
+ {
+ send_JPIPstream( jpipstream, j2kfilename, tid, cid);
+ return get_PNMstream( cid, tid, fw, fh);
+ }
+
+ public void send_JPIPstream( byte[] jpipstream)
+ {
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+
+ System.err.println("Sending " + jpipstream.length + "Data Bytes to decodingServer");
+
+ os.writeBytes("JPIP-stream\n");
+ os.writeBytes("version 1.2\n");
+ os.writeBytes( jpipstream.length + "\n");
+ os.write( jpipstream, 0, jpipstream.length);
+
+ byte signal = is.readByte();
+
+ if( signal == 0)
+ System.err.println(" failed");
+ } catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ }
+
+ public void send_JPIPstream( byte[] jpipstream, String j2kfilename, String tid, String cid)
+ {
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+ int length = 0;
+
+ if( jpipstream != null)
+ length = jpipstream.length;
+
+ System.err.println("Sending " + length + "Data Bytes to decodingServer");
+
+ os.writeBytes("JPIP-stream\n");
+ os.writeBytes("version 1.2\n");
+ os.writeBytes( j2kfilename + "\n");
+ if( tid == null)
+ os.writeBytes( "0\n");
+ else
+ os.writeBytes( tid + "\n");
+ if( cid == null)
+ os.writeBytes( "0\n");
+ else
+ os.writeBytes( cid + "\n");
+ os.writeBytes( length + "\n");
+ os.write( jpipstream, 0, length);
+
+ byte signal = is.readByte();
+
+ if( signal == 0)
+ System.err.println(" failed");
+ } catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ }
+
+ public PnmImage get_PNMstream( String cid, String tid, int fw, int fh)
+ {
+ PnmImage pnmstream = null;
+
+ try {
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+ byte []header = new byte[7];
+
+ os.writeBytes("PNM request\n");
+ if( cid != null)
+ os.writeBytes( cid + "\n");
+ else
+ if( tid != null)
+ os.writeBytes( tid + "\n");
+ else
+ os.writeBytes( "0\n");
+ os.writeBytes( fw + "\n");
+ os.writeBytes( fh + "\n");
+
+ read_stream( is, header, 7);
+
+ if( header[0] == 80){
+ // P5: gray, P6: color
+ byte magicknum = header[1];
+ if( magicknum == 5 || magicknum == 6){
+ int c = magicknum==6 ? 3: 1;
+ int w = (header[2]&0xff)<<8 | (header[3]&0xff);
+ int h = (header[4]&0xff)<<8 | (header[5]&0xff);
+ int maxval = header[6]&0xff;
+ int length = w*h*c;
+
+ if( maxval == 255 && length != 0){
+ pnmstream = new PnmImage( c, w, h);
+ read_stream( is, pnmstream.get_data(), length);
+ }
+ else
+ System.err.println("Error in get_PNMstream(), only 255 is accepted");
+ }
+ else
+ System.err.println("Error in get_PNMstream(), wrong magick number" + header[1]);
+ }
+ else
+ System.err.println("Error in get_PNMstream(), Not starting with P");
+
+ os.close();
+ is.close();
+ imgdecSocket.close();
+ } catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ return pnmstream;
+ }
+
+ public byte [] get_XMLstream( String cid)
+ {
+ byte []xmldata = null;
+
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+ byte []header = new byte[5];
+
+ os.writeBytes("XML request\n");
+ os.writeBytes( cid + "\n");
+
+ read_stream( is, header, 5);
+
+ if( header[0] == 88 && header[1] == 77 && header[2] == 76){
+ int length = (header[3]&0xff)<<8 | (header[4]&0xff);
+
+ xmldata = new byte[ length];
+ read_stream( is, xmldata, length);
+ }
+ else
+ System.err.println("Error in get_XMLstream(), not starting with XML");
+ } catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ return xmldata;
+ }
+
+ public String query_cid( String j2kfilename)
+ {
+ int []retmsglabel = new int[3];
+ retmsglabel[0] = 67;
+ retmsglabel[1] = 73;
+ retmsglabel[2] = 68;
+
+ return query_id( "CID request", j2kfilename, retmsglabel);
+ }
+
+ public String query_tid( String j2kfilename)
+ {
+ int []retmsglabel = new int[3];
+ retmsglabel[0] = 84;
+ retmsglabel[1] = 73;
+ retmsglabel[2] = 68;
+
+ return query_id( "TID request", j2kfilename, retmsglabel);
+ }
+
+ public String query_id( String reqmsghead, String j2kfilename, int[] retmsglabel)
+ {
+ String id = null;
+
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+ byte []header = new byte[4];
+
+ os.writeBytes( reqmsghead + "\n");
+ os.writeBytes( j2kfilename + "\n");
+
+ read_stream( is, header, 4);
+
+ if( header[0] == retmsglabel[0] && header[1] == retmsglabel[1] && header[2] == retmsglabel[2]){
+ int length = header[3]&0xff;
+
+ if( length > 0){
+
+ byte []iddata = new byte[ length];
+ read_stream( is, iddata, length);
+ id = new String( iddata);
+ }
+ }
+ else
+ System.err.println("Error in query_id("+ reqmsghead + "), wrong to start with " + header);
+ }
+ catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+
+ return id;
+ }
+
+ public java.awt.Dimension query_imagesize( String cid, String tid)
+ {
+ java.awt.Dimension dim = null;
+
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+ byte []header = new byte[3];
+
+ os.writeBytes( "SIZ request\n");
+ if( tid == null)
+ os.writeBytes( "0\n");
+ else
+ os.writeBytes( tid + "\n");
+ if( cid == null)
+ os.writeBytes( "0\n");
+ else
+ os.writeBytes( cid + "\n");
+
+ read_stream( is, header, 3);
+
+ if( header[0] == 83 && header[1] == 73 && header[2] == 90){
+
+ byte []data = new byte[ 3];
+ read_stream( is, data, 3);
+ int w = (data[0]&0xff)<<16 | (data[1]&0xff)<<8 | (data[2]&0xff);
+ read_stream( is, data, 3);
+ int h = (data[0]&0xff)<<16 | (data[1]&0xff)<<8 | (data[2]&0xff);
+ dim = new java.awt.Dimension( w, h);
+ }
+ else
+ System.err.println("Error in query_imagesize("+ cid + ", " + tid + "), wrong to start with " + header);
+ }
+ catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+
+ return dim;
+ }
+
+ private static void read_stream( DataInputStream is, byte []stream, int length)
+ {
+ int remlen = length;
+ int off = 0;
+
+ try{
+ while( remlen > 0){
+ int redlen = is.read( stream, off, remlen);
+
+ if( redlen == -1){
+ System.err.println(" failed to read_stream()");
+ break;
+ }
+ off += redlen;
+ remlen -= redlen;
+ }
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ }
+
+ public void destroy_cid( String cid)
+ {
+ try{
+ Socket imgdecSocket = new Socket( hostname, portNo);
+ DataOutputStream os = new DataOutputStream( imgdecSocket.getOutputStream());
+ DataInputStream is = new DataInputStream( imgdecSocket.getInputStream());
+
+ os.writeBytes("CID destroy\n");
+ os.writeBytes( cid + "\n");
+
+ byte signal = is.readByte();
+
+ if( signal == 0)
+ System.err.println(" failed");
+ } catch (UnknownHostException e) {
+ System.err.println("Trying to connect to unknown host: " + e);
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/JPIPHttpClient.java b/src/bin/jpip/opj_viewer/src/JPIPHttpClient.java
new file mode 100644
index 00000000..ce9a301d
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/JPIPHttpClient.java
@@ -0,0 +1,503 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+
+
+public class JPIPHttpClient
+{
+ private String comURL;
+ protected int fw, fh;
+ protected int rx, ry;
+ protected int rw, rh;
+ protected String cid;
+ protected String tid;
+ private boolean JPTstream;
+ private boolean JPPstream;
+ private boolean aux;
+ private boolean tcp; // true: tcp, false: udp
+ private int port;
+
+ public JPIPHttpClient( String URI)
+ {
+ comURL = URI + "?";
+ fw = fh = -1;
+ rx = ry = -1;
+ rw = rh = -1;
+ cid = null;
+ tid = null;
+ JPTstream = JPPstream = aux = false;
+ port = 0;
+ }
+
+ public int getFw(){ return fw;}
+ public int getFh(){ return fh;}
+ public int getRx(){ return rx;}
+ public int getRy(){ return ry;}
+ public int getRw(){ return rw;}
+ public int getRh(){ return rh;}
+
+ public byte[] requestViewWindow( int reqfw, int reqfh)
+ {
+ if( cid != null)
+ return requestViewWindow( reqfw, reqfh, cid);
+ else
+ return null;
+ }
+
+ public byte[] requestViewWindow( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh)
+ {
+ if( cid != null)
+ return requestViewWindow( reqfw, reqfh, reqrx, reqry, reqrw, reqrh, cid);
+ else
+ if( tid != null)
+ return requestViewWindow( null, tid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false);
+ else
+ return null;
+ }
+
+ public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid)
+ {
+ return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, false, 0, false, false);
+ }
+
+ public byte[] requestViewWindow( int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh, String reqcid)
+ {
+ return requestViewWindow( null, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, false, 0, false, false);
+ }
+
+ public byte[] requestViewWindow( String target, int reqfw, int reqfh)
+ {
+ return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, false, 0, false, false);
+ }
+
+ public byte[] requestViewWindow( String target, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ if( cid == null) // 1 channel allocation only
+ return requestViewWindow( target, null, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT);
+ else
+ return null;
+ }
+
+ public byte[] requestViewWindow( String target, String reqtid, int reqfw, int reqfh, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ if( cid == null) // 1 channel allocation only
+ return requestViewWindow( target, reqtid, reqfw, reqfh, -1, -1, -1, -1, null, reqcnew, reqaux, reqJPP, reqJPT);
+ else
+ return null;
+ }
+
+ public byte[] requestViewWindow( String target, int reqfw, int reqfh, int reqrx, int reqry, int reqrw, int reqrh)
+ {
+ return requestViewWindow( target, null, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, null, false, 0, false, false);
+ }
+
+ public byte[] requestViewWindow( int reqfw, int reqfh, String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ return requestViewWindow( null, null, reqfw, reqfh, -1, -1, -1, -1, reqcid, reqcnew, reqaux, reqJPP, reqJPT);
+ }
+
+ public byte[] requestViewWindow( String target,
+ String reqtid,
+ int reqfw, int reqfh,
+ int reqrx, int reqry,
+ int reqrw, int reqrh,
+ String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ if( reqtid != null)
+ tid = reqtid;
+
+ String urlstring = const_urlstring( target, reqtid, reqfw, reqfh, reqrx, reqry, reqrw, reqrh, reqcid, reqcnew, reqaux, reqJPP, reqJPT);
+ return GETrequest( urlstring);
+ }
+
+ public byte[] requestXML()
+ {
+ String urlstring = comURL;
+
+ if( cid == null)
+ return null;
+
+ urlstring = urlstring.concat( "cid=" + cid);
+ urlstring = urlstring.concat( "&metareq=[xml_]");
+
+ return GETrequest( urlstring);
+ }
+
+ private byte[] GETrequest( String urlstring)
+ {
+ URL url = null;
+ HttpURLConnection urlconn = null;
+ byte[] jpipstream = null;
+
+ try{
+ url = new URL( urlstring);
+
+ System.err.println("Requesting: " + url);
+
+ urlconn = (HttpURLConnection)url.openConnection();
+ urlconn.setRequestMethod("GET");
+ urlconn.setInstanceFollowRedirects(false);
+ urlconn.connect();
+
+ set_responseheader( urlconn);
+
+ if( !aux){
+ jpipstream = receive_httpchunk( urlconn);
+ urlconn.disconnect();
+ }
+ else{
+ urlconn.disconnect();
+ jpipstream = receive_tcpaux( comURL.substring( 7, comURL.indexOf('/', 7)), port, cid);
+ }
+ }
+ catch ( MalformedURLException e){
+ e.printStackTrace();
+ }
+ catch ( ProtocolException e){
+ e.printStackTrace();
+ }
+ catch( ClassCastException e){
+ e.printStackTrace();
+ }
+ catch( NullPointerException e){
+ e.printStackTrace();
+ }
+ catch( UnknownServiceException e){
+ e.printStackTrace();
+ }
+ catch ( IOException e){
+ e.printStackTrace();
+ }
+
+ return jpipstream;
+ }
+
+ private void set_responseheader( HttpURLConnection urlconn)
+ {
+ Map<String,java.util.List<String>> headers = urlconn.getHeaderFields();
+ java.util.List<String> hvaluelist;
+ String hvalueline;
+
+ String status = headers.get(null).get(0);
+
+ System.err.println( status);
+ if( !status.contains("OK"))
+ System.err.println( headers.get("Reason"));
+
+ if(( hvaluelist = headers.get("Content-type")) == null)
+ hvaluelist = headers.get("Content-Type");
+ hvalueline = hvaluelist.get(0);
+ System.err.println( hvalueline);
+
+ if( hvalueline.endsWith("jpt-stream"))
+ JPTstream = true;
+ else if( hvalueline.endsWith("jpp-stream"))
+ JPPstream = true;
+
+ if(( hvaluelist = headers.get("JPIP-fsiz")) != null){
+ hvalueline = hvaluelist.get(0);
+ fw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
+ fh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
+
+ System.err.println("fw,fh: " + fw + "," + fh);
+ }
+
+ if(( hvaluelist = headers.get("JPIP-roff")) != null){
+ hvalueline = hvaluelist.get(0);
+ rx = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
+ ry = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
+ System.err.println("rx,ry: " + rx + "," + ry);
+ }
+
+ if(( hvaluelist = headers.get("JPIP-rsiz")) != null){
+ hvalueline = hvaluelist.get(0);
+ rw = Integer.valueOf( hvalueline.substring( 0, hvalueline.indexOf(','))).intValue();
+ rh = Integer.valueOf( hvalueline.substring( hvalueline.indexOf(',')+1 )).intValue();
+ System.err.println("rw,rh: " + rw + "," + rh);
+ }
+
+ if(( hvaluelist = headers.get("JPIP-cnew")) != null){
+ hvalueline = hvaluelist.get(0);
+ cid = hvalueline.substring( hvalueline.indexOf('=')+1, hvalueline.indexOf(','));
+
+ int idxOfcid = hvalueline.indexOf("transport")+10;
+ int idxOfcid2 = hvalueline.indexOf(',', idxOfcid);
+ String transport;
+ if( idxOfcid2 != -1)
+ transport = hvalueline.substring( idxOfcid, idxOfcid2);
+ else
+ transport = hvalueline.substring( idxOfcid);
+
+ if( transport.matches("http-tcp")){
+ aux = true;
+ tcp = true;
+ }
+ else if( transport.matches("http-udp")){
+ aux = true;
+ tcp = false;
+ }
+ else
+ aux = false;
+
+ if( aux){
+ idxOfcid = hvalueline.indexOf("auxport")+8;
+ port = Integer.valueOf( hvalueline.substring( idxOfcid)).intValue();
+ System.err.println("cid: " + cid + ", transport: " + transport + ", auxport: " + port);
+ }
+ else
+ System.err.println("cid: " + cid + ", transport: " + transport);
+ }
+
+ if(( hvaluelist = headers.get("JPIP-tid")) != null){
+ hvalueline = hvaluelist.get(0);
+ tid = hvalueline.substring( hvalueline.indexOf('=')+1);
+ System.err.println("tid: " + tid);
+ }
+ }
+
+ private static byte[] receive_httpchunk( HttpURLConnection urlconn)
+ {
+ byte[] chunk = null;
+ InputStream input;
+
+ try{
+ input = urlconn.getInputStream();
+
+ if( input.available() > 0){
+ ByteArrayOutputStream tmpstream = new ByteArrayOutputStream();
+ byte[] buf = new byte[ 1024];
+ int redlen, buflen;
+
+ System.err.println("reading jpipstream...");
+
+ do{
+ redlen = input.read( buf);
+
+ if( redlen == -1)
+ break;
+ tmpstream.write( buf, 0, redlen);
+ }while( redlen > 0);
+
+ buflen = tmpstream.size();
+ chunk = tmpstream.toByteArray();
+
+ buf = null;
+ tmpstream = null;
+
+ System.err.println("jpiplen: " + buflen);
+ System.err.println(" succeeded");
+ }
+ else{
+ System.err.println("No new jpipstream");
+ }
+ input.close();
+ }
+ catch ( IOException e){
+ e.printStackTrace();
+ }
+
+ return chunk;
+ }
+
+ private static byte[] receive_tcpaux( String host, int port, String cid)
+ {
+ Socket jpipsocket;
+ DataOutputStream os;
+ DataInputStream is;
+ byte []auxheader;
+ byte []chunkbody = null;
+ byte []stream = null;
+ int chunkbodylen, streamlen, headlen = 8;
+ ByteArrayOutputStream tmpstream;
+
+ try{
+ jpipsocket = new Socket( host, port);
+ os = new DataOutputStream( jpipsocket.getOutputStream());
+ is = new DataInputStream( jpipsocket.getInputStream());
+ auxheader = new byte[headlen];
+ tmpstream = new ByteArrayOutputStream();
+
+ os.writeBytes( cid + "\r\n");
+
+ do{
+ read_stream( is, auxheader, headlen);
+
+ chunkbodylen = ((auxheader[0]&0xff)<<8 | (auxheader[1]&0xff)) - headlen;
+
+ chunkbody = new byte [ chunkbodylen];
+ read_stream( is, chunkbody, chunkbodylen);
+ tmpstream.write( chunkbody, 0, chunkbodylen);
+
+ os.write( auxheader, 0, headlen);
+ }while( !(chunkbody[chunkbodylen-3]==0x00 && ( chunkbody[chunkbodylen-2]==0x01 || chunkbody[chunkbodylen-2]== 0x02)));
+
+ streamlen = tmpstream.size();
+ stream = tmpstream.toByteArray();
+
+ System.err.println("jpiplen: " + streamlen);
+ System.err.println(" succeeded");
+
+ chunkbody = null;
+ tmpstream = null;
+
+ os.close();
+ is.close();
+
+ jpipsocket.close();
+ }
+ catch ( IOException e){
+ e.printStackTrace();
+ }
+
+ return stream;
+ }
+
+ private static void read_stream( InputStream is, byte []stream, int length)
+ {
+ int remlen = length;
+ int off = 0;
+
+ try{
+ while( remlen > 0){
+ int redlen = is.read( stream, off, remlen);
+
+ if( redlen == -1){
+ System.err.println(" failed to read_stream()");
+ break;
+ }
+ off += redlen;
+ remlen -= redlen;
+ }
+ } catch (IOException e) {
+ System.err.println("IOException: " + e);
+ }
+ }
+
+ private String const_urlstring( String target,
+ String reqtid,
+ int reqfw, int reqfh,
+ int reqrx, int reqry,
+ int reqrw, int reqrh,
+ String reqcid, boolean reqcnew, int reqaux, boolean reqJPP, boolean reqJPT)
+ {
+ String urlstring = comURL;
+
+ // C.7.3 Image Return Type
+ // add type=jpp-stream(;ptype=ext) or type=jpt-stream;ttype=ext
+
+ if( target != null){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "target=" + target);
+ }
+ if( reqtid != null){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "tid=" + reqtid);
+ }
+ if( reqfw != -1 && reqfh != -1){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "fsiz=" + reqfw + "," + reqfh);
+ }
+ if( reqrx != -1 && reqry != -1){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "roff=" + reqrx + "," + reqry);
+ }
+ if( reqrw != -1 && reqrh != -1){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "rsiz=" + reqrw + "," + reqrh);
+ }
+ if( reqcid != null){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "cid=" + reqcid);
+ }
+ if( reqcnew){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ if( reqaux == 1)
+ urlstring = urlstring.concat( "cnew=http-tcp");
+ else if( reqaux == 2)
+ urlstring = urlstring.concat( "cnew=http-udp");
+ else
+ urlstring = urlstring.concat( "cnew=http");
+ }
+ if( reqJPP && !JPTstream){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "type=jpp-stream");
+ }
+ else if( reqJPT && !JPPstream){
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ urlstring = urlstring.concat( "type=jpt-stream");
+ }
+ else{ // remove this option later
+ if( !urlstring.endsWith("?"))
+ urlstring = urlstring.concat( "&");
+ if( JPTstream)
+ urlstring = urlstring.concat( "type=jpt-stream");
+ else if( JPPstream)
+ urlstring = urlstring.concat( "type=jpp-stream");
+ }
+
+ return urlstring;
+ }
+
+ public void closeChannel()
+ {
+ if( cid == null)
+ return;
+
+ try{
+ URL url = new URL( comURL + "cclose=" + cid);
+ System.err.println( "closing cid: " + cid);
+
+ HttpURLConnection urlconn = (HttpURLConnection)url.openConnection();
+ urlconn.setRequestMethod("GET");
+ urlconn.setInstanceFollowRedirects(false);
+ urlconn.connect();
+
+ Map headers = urlconn.getHeaderFields();
+
+ urlconn.disconnect();
+ } catch ( MalformedURLException e){
+ e.printStackTrace();
+ } catch ( IOException e){
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/MML.java b/src/bin/jpip/opj_viewer/src/MML.java
new file mode 100644
index 00000000..983ff200
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/MML.java
@@ -0,0 +1,116 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.event.*;
+
+class MML implements MouseMotionListener, MouseListener
+{
+ public void mouseExited(MouseEvent e) {}
+ public void mouseEntered(MouseEvent e) {}
+ public void mouseClicked(MouseEvent e) {}
+
+ private ImageViewer iv;
+ private int x1, y1, x2, y2, zf, btn;
+ private boolean zoomrq;
+
+ public MML(ImageViewer imageviewer)
+ {
+ x1 = y1 = -1;
+ iv = imageviewer;
+ zoomrq = false;
+ zf = 0;
+ }
+
+ private boolean isInside(int x, int y)
+ {
+ x -= iv.getX();
+ y -= iv.getY();
+ return (x >= 0) && (x < iv.getWidth())
+ && (y >= 0) && (y < iv.getHeight());
+ }
+
+ public void mousePressed(MouseEvent e)
+ {
+ btn = e.getButton();
+
+ if( iv.hasAnnotation()){
+ if( iv.isInsideROIRect(e.getX(), e.getY())){
+ iv.zoomIn();
+ System.out.println("annotation click");
+ return;
+ }
+ }
+ if (iv.isInsideRect(e.getX(), e.getY())) {
+ iv.setSelected(2);
+ iv.repaint();
+ zoomrq = true;
+ } else {
+ iv.setRGeom(0, 0, 0, 0);
+ iv.setSelected(0);
+ iv.repaint();
+ x1 = y1 = -1;
+ }
+ }
+
+ public void mouseReleased(MouseEvent e)
+ {
+ if(e.getButton() == 1) {
+ if (zoomrq) {
+ iv.zoomIn();
+ zoomrq = false;
+ }
+ }
+ }
+
+ public void mouseMoved(MouseEvent e)
+ {
+ }
+
+ public void mouseDragged(MouseEvent e)
+ {
+ if (btn == 1) {
+ x2 = e.getX();
+ y2 = e.getY();
+
+ iv.setSelected(0);
+ zoomrq = false;
+
+ if (isInside(x2, y2)) {
+ if (x1 == -1) {
+ x1 = x2;
+ y1 = y2;
+ } else {
+ iv.setRGeom(x1, y1, x2, y2);
+ iv.repaint();
+ }
+ }
+ }
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/PnmImage.java b/src/bin/jpip/opj_viewer/src/PnmImage.java
new file mode 100644
index 00000000..092acecb
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/PnmImage.java
@@ -0,0 +1,154 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.image.*;
+import java.io.*;
+import java.util.regex.*;
+
+public class PnmImage extends Component
+{
+ private byte[] data = null;
+ private int width = 0;
+ private int height = 0;
+ private int channel = 0;
+
+ public PnmImage( int c, int w, int h)
+ {
+ channel = c;
+ width = w;
+ height = h;
+ data = new byte [ w*h*c];
+ }
+
+ public PnmImage( String filename)
+ {
+ String str;
+ Pattern pat;
+ Matcher mat;
+ int bytes;
+ int r, offset = 0;
+
+ try {
+ FileInputStream fis = new FileInputStream( new File(filename));
+ DataInputStream is = new DataInputStream( fis);
+
+ pat = Pattern.compile("^P([56])$");
+ mat = pat.matcher(str = is.readLine());
+ if( !mat.matches()){
+ System.out.println("PNM header format error");
+ return;
+ }
+
+ if( (mat.group(1)).compareTo("5") == 0)
+ channel = 1;
+ else
+ channel = 3;
+
+ pat = Pattern.compile("^(\\d+) (\\d+)$");
+ mat = pat.matcher(str = is.readLine());
+ if( !mat.matches()){
+ System.out.println("PNM header format error");
+ return;
+ }
+ width = Integer.parseInt( mat.group(1));
+ height = Integer.parseInt( mat.group(2));
+
+ str = is.readLine(); // 255
+
+ bytes = width*height*channel;
+ data = new byte[bytes];
+
+ while( bytes > 0){
+ try {
+ r = is.read(data, offset, bytes);
+ if( r == -1){
+ System.err.println(" failed to read()");
+ break;
+ }
+ offset += r;
+ bytes -= r;
+ }
+ catch (IOException e) { e.printStackTrace(); }
+ }
+ fis.close();
+ } catch (IOException e) { e.printStackTrace(); }
+ }
+
+ public byte [] get_data(){ return data;}
+ public int get_width() { return width;}
+ public int get_height(){ return height;}
+
+ public Image createROIImage( int rx, int ry, int rw, int rh)
+ {
+ int []pix = new int[ rw*rh];
+
+ for( int i=0; i<rh; i++)
+ for( int j=0; j<rw; j++){
+ pix[i*rw+j] = 0xFF << 24; // transparency
+ if( channel == 1){
+ Byte lum = data[(ry+i)*width+rx+j];
+ short slum;
+
+ if( lum < 0)
+ slum = (short)(2*128+lum);
+ else
+ slum = (short)lum;
+
+ for( int c=0; c<3; c++){
+ pix[i*rw+j] = pix[i*rw+j] | slum << (8*c);
+ }
+ }
+ else
+ for( int c=0; c<3; c++){
+ Byte lum = data[ ((ry+i)*width+rx+j)*channel+(2-c)];
+ short slum;
+
+ if( lum < 0)
+ slum = (short)(2*128+lum);
+ else
+ slum = (short)lum;
+
+ pix[i*rw+j] = pix[i*rw+j] | slum << (8*c);
+ }
+ }
+
+ return createImage(new MemoryImageSource( rw, rh, pix, 0, rw));
+ }
+
+ public Image createScaleImage( double scale)
+ {
+ Image src = createROIImage( 0, 0, width, height);
+ ImageFilter replicate = new ReplicateScaleFilter( (int)(width*scale), (int)(height*scale));
+ ImageProducer prod = new FilteredImageSource( src.getSource(), replicate);
+
+ return createImage(prod);
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/RegimViewer.java b/src/bin/jpip/opj_viewer/src/RegimViewer.java
new file mode 100644
index 00000000..57c54c57
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/RegimViewer.java
@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.geom.AffineTransform;
+
+public class RegimViewer extends JPanel
+{
+ private PnmImage refpnm;
+ private int vw, vh;
+ private Image refimg;
+ private Image jpipImg;
+ private double[] affine_matrix;
+ private AffineTransform affine;
+
+ public RegimViewer( String refname, double[] mat)
+ {
+ refpnm = new PnmImage( refname.replaceFirst("jp2", "pgm")); // decoding not realized
+ affine_matrix = new double[6];
+
+ affine_matrix[0] = mat[0];
+ affine_matrix[1] = mat[3];
+ affine_matrix[2] = mat[1];
+ affine_matrix[3] = mat[4];
+ affine_matrix[4] = mat[2];
+ affine_matrix[5] = mat[5];
+
+ affine = new AffineTransform();
+
+ for( int i=0; i<3; i++){
+ for( int j=0; j<3; j++)
+ System.out.print( mat[i*3+j] + " ");
+ System.out.println();
+ }
+ }
+
+ public void projection( Image jpipimg, double scale)
+ {
+ jpipImg = jpipimg;
+ refimg = refpnm.createScaleImage( scale);
+ vw = refimg.getWidth(this);
+ vh = refimg.getHeight(this);
+ this.setSize( vw, vh);
+
+ affine.setTransform( affine_matrix[0], affine_matrix[1], affine_matrix[2], affine_matrix[3], affine_matrix[4], affine_matrix[5]);
+ repaint();
+ }
+
+ public void paint(Graphics g)
+ {
+ int iw, ih;
+ BufferedImage bi, bi2;
+ Graphics2D big, big2;
+ Graphics2D g2 = (Graphics2D) g;
+
+ g2.clearRect(0, 0, vw, vh);
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+
+ iw = refimg.getWidth(this);
+ ih = refimg.getHeight(this);
+
+ bi = new BufferedImage( iw, ih, BufferedImage.TYPE_INT_RGB);
+ big = bi.createGraphics();
+ big.drawImage(refimg, 0, 0, this);
+
+ g2.drawImage(bi, 0, 0, this);
+
+ bi2 = new BufferedImage( jpipImg.getWidth(this), jpipImg.getHeight(this), BufferedImage.TYPE_INT_RGB);
+ big2 = bi2.createGraphics();
+ big2.drawImage( jpipImg, 0, 0, this);
+
+ g2.setTransform(affine);
+
+ g2.drawImage(bi2, 0, 0, this);
+ }
+
+ public Dimension get_imsize()
+ {
+ return (new Dimension( vw, vh));
+ }
+}
diff --git a/src/bin/jpip/opj_viewer/src/ResizeListener.java b/src/bin/jpip/opj_viewer/src/ResizeListener.java
new file mode 100644
index 00000000..fce8a4ff
--- /dev/null
+++ b/src/bin/jpip/opj_viewer/src/ResizeListener.java
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+class ResizeListener implements ComponentListener
+{
+ private ImageViewer iv;
+ private Dimension largest;
+
+ public ResizeListener( ImageViewer _iv)
+ {
+ iv = _iv;
+ largest = iv.getSize();
+ }
+
+ public void componentHidden(ComponentEvent e) {}
+
+ public void componentMoved(ComponentEvent e) {}
+
+ public void componentResized(ComponentEvent e) {
+ Dimension cursize = iv.getSize();
+ if( largest.getWidth() < cursize.getWidth() || largest.getHeight() < cursize.getHeight()){
+ update_largest( cursize);
+ iv.enlarge();
+ }
+ }
+
+ private void update_largest( Dimension cursize)
+ {
+ if( largest.getWidth() < cursize.getWidth())
+ largest.setSize( cursize.getWidth(), largest.getHeight());
+ if( largest.getHeight() < cursize.getHeight())
+ largest.setSize( largest.getWidth(), cursize.getHeight());
+ }
+
+ public void componentShown(ComponentEvent e) {}
+}
diff --git a/src/bin/jpip/opj_viewer_xerces/dist/manifest.txt.in b/src/bin/jpip/opj_viewer_xerces/dist/manifest.txt.in
new file mode 100644
index 00000000..c7ba9f36
--- /dev/null
+++ b/src/bin/jpip/opj_viewer_xerces/dist/manifest.txt.in
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Ant-Version: Apache Ant 1.7.0
+Created-By: Kaori Hagihara
+Main-Class: ImageWindow
+Class-Path: @APACHE_XERCES_JAR@
diff --git a/src/bin/jpip/opj_viewer_xerces/src/ImageViewer.java b/src/bin/jpip/opj_viewer_xerces/src/ImageViewer.java
new file mode 100644
index 00000000..52f0522a
--- /dev/null
+++ b/src/bin/jpip/opj_viewer_xerces/src/ImageViewer.java
@@ -0,0 +1,266 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import java.awt.image.*;
+import java.awt.geom.*;
+import java.net.URL;
+import javax.swing.border.*;
+import java.util.*;
+import java.io.*;
+
+public class ImageViewer extends JPanel
+{
+ private ImageManager imgmanager;
+ private int vw, vh;
+ private int iw, ih;
+ private int selected = 0;
+ private Image img;
+
+ private String cmdline = new String();
+ private boolean fullRefresh = false;
+ private Point offset = new Point(0,0);
+ private Rectangle rect = new Rectangle();
+ private Rectangle roirect[] = null;
+ private String roiname[] = null;
+
+ public ImageViewer( String j2kfilename, ImageManager manager, boolean session, boolean jppstream, int aux)
+ {
+ String str;
+ MML myMML;
+
+ this.setSize( 170, 170);
+ Dimension asz = this.getSize();
+
+ vw = asz.width;
+ vh = asz.height;
+
+ setBackground(Color.black);
+ myMML = new MML(this);
+
+ imgmanager = manager;
+
+ img = imgmanager.getImage( j2kfilename, vw, vh, session, aux, jppstream, !jppstream);
+
+ addMouseListener(myMML);
+ addMouseMotionListener(myMML);
+ addComponentListener( new ResizeListener(this));
+ }
+
+ public Image getImage()
+ {
+ return img;
+ }
+
+ public void zoomIn()
+ {
+ roirect = null;
+ roiname = null;
+
+ double scalex = (double)vw/(double)rect.width;
+ double scaley = (double)vh/(double)rect.height;
+
+ int fw = (int)(imgmanager.getFw()*scalex);
+ int fh = (int)(imgmanager.getFh()*scaley);
+ int rx = (int)((imgmanager.getRx()+rect.x)*scalex);
+ int ry = (int)((imgmanager.getRy()+rect.y)*scaley);
+
+ img = imgmanager.getImage( fw, fh, rx, ry, vw, vh);
+
+ rect.x = rect.y = rect.width = rect.height = 0;
+
+ selected = 0;
+ fullRefresh = true;
+ repaint();
+ }
+
+ public void enlarge()
+ {
+ roirect = null;
+ roiname = null;
+
+ Dimension asz = this.getSize();
+
+ vw = asz.width;
+ vh = asz.height;
+
+ double scalex = vw/(double)imgmanager.getRw();
+ double scaley = vh/(double)imgmanager.getRh();
+
+ int fw = (int)(imgmanager.getFw()*scalex);
+ int fh = (int)(imgmanager.getFh()*scaley);
+ int rx = (int)(imgmanager.getRx()*scalex);
+ int ry = (int)(imgmanager.getRy()*scaley);
+
+ img = imgmanager.getImage( fw, fh, rx, ry, vw, vh);
+
+ fullRefresh = true;
+ repaint();
+ }
+
+ public void setSelected(int state)
+ {
+ roirect = null;
+ roiname = null;
+
+ if (state != selected) {
+
+ selected = state;
+ repaint();
+ }
+ }
+
+ public boolean isInsideRect(int x, int y)
+ {
+ return rect.contains(x - offset.x, y - offset.y);
+ }
+
+ public void setRGeom(int x1, int y1, int x2, int y2)
+ {
+ rect.x = Math.min(x1,x2) - offset.x;
+ rect.y = Math.min(y1,y2) - offset.y;
+ rect.width = Math.abs(x2-x1);
+ rect.height = Math.abs(y2-y1);
+ }
+
+ public void annotate( JP2XMLparser.ROIparams roi[])
+ {
+ int numofroi = roi.length;
+
+ roirect = new Rectangle [numofroi];
+ roiname = new String [numofroi];
+
+ double scale_x = imgmanager.getFw()/(double)imgmanager.getOrigWidth();
+ double scale_y = imgmanager.getFh()/(double)imgmanager.getOrigHeight();
+ int rx = imgmanager.getRx();
+ int ry = imgmanager.getRy();
+ int rw = imgmanager.getRw();
+ int rh = imgmanager.getRh();
+
+ for( int i=0; i<numofroi ; i++){
+ int x = (int)(roi[i].x*scale_x) - rx;
+ int y = (int)(roi[i].y*scale_y) - ry;
+ int w = (int)(roi[i].w*scale_x);
+ int h = (int)(roi[i].h*scale_y);
+ if( 0<=x && 0<=y && x+w<=rw && y+h<=rh){ // can be optimized
+ roirect[i] = new Rectangle( x, y, w, h);
+ roiname[i] = new String( roi[i].name);
+ }
+ else{
+ roirect[i] = null;
+ roiname[i] = null;
+ }
+ }
+ repaint();
+ }
+
+ public boolean hasAnnotation()
+ {
+ if( roirect == null)
+ return false;
+ else
+ return true;
+ }
+
+ public boolean isInsideROIRect(int x, int y)
+ {
+ for( int i=0; i<roirect.length; i++)
+ if( roirect[i] != null)
+ if( roirect[i].contains(x - offset.x, y - offset.y)){
+ rect = roirect[i];
+ return true;
+ }
+ return false;
+ }
+
+ public void paint(Graphics g)
+ {
+ BufferedImage bi;
+ Graphics2D big;
+ Graphics2D g2 = (Graphics2D) g;
+
+ if (fullRefresh) {
+ g2.clearRect(0, 0, vw, vh);
+ fullRefresh = false;
+ }
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+
+ offset.x = 0;
+ offset.y = 0;
+
+ iw = img.getWidth(this);
+ ih = img.getHeight(this);
+
+ bi = new BufferedImage( iw, ih, BufferedImage.TYPE_INT_RGB);
+ big = bi.createGraphics();
+
+ big.drawImage(img, 0, 0, this);
+ big.setPaint(Color.red);
+ if ((rect.width > 0) && (rect.height > 0))
+ big.draw(rect);
+
+ if( roirect != null){
+ for( int i=0; i<roirect.length; i++)
+ if( roirect[i] != null){
+ big.draw( roirect[i]);
+ big.drawString( roiname[i], roirect[i].x+3, roirect[i].y+roirect[i].height*2/3);
+ }
+ }
+ if (selected == 1)
+ shadeExt(big, 0, 0, 0, 64);
+ else if (selected == 2) {
+ shadeExt(big, 0, 0, 0, 255);
+ selected = 1;
+ }
+ g2.drawImage(bi, offset.x, offset.y, this);
+ }
+
+ private void shadeRect(Graphics2D g2, int r, int g, int b, int a)
+ {
+ g2.setPaint(new Color(r, g, b, a));
+ g2.fillRect(rect.x + 1, rect.y + 1, rect.width - 1, rect.height - 1);
+ }
+
+ private void shadeExt(Graphics2D g2, int r, int g, int b, int a)
+ {
+ g2.setPaint(new Color(r, g, b, a));
+ g2.fillRect(0, 0, iw, rect.y); /* _N_ */
+ g2.fillRect(rect.x + rect.width + 1, rect.y,
+ iw - rect.x - rect.width - 1, rect.height + 1); /* E */
+ g2.fillRect(0, rect.y, rect.x, rect.height + 1); /* W */
+ g2.fillRect(0, rect.y + rect.height + 1,
+ iw, ih - rect.y - rect.height - 1); /* _S_ */
+ }
+}
diff --git a/src/bin/jpip/opj_viewer_xerces/src/ImageWindow.java b/src/bin/jpip/opj_viewer_xerces/src/ImageWindow.java
new file mode 100644
index 00000000..ae3f54c5
--- /dev/null
+++ b/src/bin/jpip/opj_viewer_xerces/src/ImageWindow.java
@@ -0,0 +1,124 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import javax.swing.*;
+import java.awt.event.*;
+import java.awt.*;
+
+public class ImageWindow extends JFrame
+{
+ private ImageViewer imgviewer;
+ private OptionPanel optpanel;
+ private ImageManager imgmanager;
+
+ public ImageWindow( String uri, String j2kfilename, String host, int port, boolean session, boolean jppstream, int aux)
+ {
+ super( j2kfilename);
+
+ imgmanager = new ImageManager( uri, host, port);
+
+ imgviewer = new ImageViewer( j2kfilename, imgmanager, session, jppstream, aux);
+ imgviewer.setOpaque(true); //content panes must be opaque
+
+ optpanel = new OptionPanel( imgmanager, imgviewer);
+
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.add( imgviewer, BorderLayout.CENTER);
+ panel.add( optpanel, BorderLayout.EAST);
+
+ setContentPane( panel);
+
+ addWindowListener(new WindowMyAdapter());
+ }
+
+ class WindowMyAdapter extends WindowAdapter
+ {
+ public void windowClosing(WindowEvent arg)
+ {
+ imgmanager.closeChannel();
+ System.exit(0);
+ }
+ }
+
+ public static void main(String s[])
+ {
+ String j2kfilename, uri, host;
+ boolean session, jppstream;
+ int port, aux; // 0: none, 1: tcp, 2: udp
+
+ if(s.length >= 2){
+ uri = s[0];
+ j2kfilename = s[1];
+
+ if( s.length > 2)
+ host = s[2];
+ else
+ host = "localhost";
+
+ if( s.length > 3)
+ port = Integer.valueOf( s[3]).intValue();
+ else
+ port = 50000;
+
+ if( s.length > 4)
+ session = !s[4].equalsIgnoreCase( "stateless");
+ else
+ session = true;
+
+ if( s.length > 5)
+ jppstream = !s[5].equalsIgnoreCase( "JPT");
+ else
+ jppstream = true;
+
+ if( s.length > 6){
+ if( s[6].equalsIgnoreCase("udp"))
+ aux = 2;
+ else
+ aux = 1;
+ }
+ else
+ aux = 0;
+ }
+ else{
+ System.out.println("Usage: java -jar opj_viewer.jar HTTP_server_URI imagefile.jp2 [hostname] [portnumber] [stateless/session] [JPT/JPP] [tcp/udp]");
+ return;
+ }
+ ImageWindow frame = new ImageWindow( uri, j2kfilename, host, port, session, jppstream, aux);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ //Display the window.
+ frame.pack();
+ frame.setSize(new Dimension(400,200));
+ frame.setLocation( 0, 50);
+ frame.setVisible(true);
+ }
+}
diff --git a/src/bin/jpip/opj_viewer_xerces/src/JP2XMLparser.java b/src/bin/jpip/opj_viewer_xerces/src/JP2XMLparser.java
new file mode 100644
index 00000000..bec1d4db
--- /dev/null
+++ b/src/bin/jpip/opj_viewer_xerces/src/JP2XMLparser.java
@@ -0,0 +1,122 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ErrorHandler;
+import org.apache.xerces.parsers.DOMParser;
+import org.xml.sax.InputSource;
+import java.io.*;
+import java.lang.Integer;
+
+public class JP2XMLparser
+{
+ Document document;
+
+ public static class ROIparams{
+ public String name = null;
+ public int x = 0;
+ public int y = 0;
+ public int w = 0;
+ public int h = 0;
+ }
+
+ public static class IRTparams{
+ public String refimg = null;
+ public double []mat = { 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
+ }
+
+ public JP2XMLparser( byte[] buf)
+ {
+ try{
+ InputSource source = new InputSource( new ByteArrayInputStream( buf));
+ DOMParser parser = new DOMParser();
+ parser.setErrorHandler(new MyHandler());
+ parser.parse( source);
+ document = parser.getDocument();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ROIparams [] getROIparams()
+ {
+ ROIparams roi[];
+ NodeList elements = document.getElementsByTagName("roi");
+ int elementCount = elements.getLength();
+
+ roi = new ROIparams [elementCount];
+
+ for( int i = 0; i < elementCount; i++) {
+ Element element = (Element)elements.item(i);
+
+ roi[i] = new ROIparams();
+ roi[i].name = element.getAttribute( "name");
+ roi[i].x = Integer.parseInt( element.getAttribute( "x")) ;
+ roi[i].y = Integer.parseInt( element.getAttribute( "y")) ;
+ roi[i].w = Integer.parseInt( element.getAttribute( "w")) ;
+ roi[i].h = Integer.parseInt( element.getAttribute( "h")) ;
+ }
+ return roi;
+ }
+
+ public IRTparams getIRTparams()
+ {
+ IRTparams irt = new IRTparams();
+ NodeList elements = document.getElementsByTagName("irt");
+ int elementCount = elements.getLength();
+
+ Element element = (Element)elements.item(0);
+ irt.refimg = element.getAttribute( "refimg");
+ for( int i=1; i<=9; i++)
+ irt.mat[i-1] = Double.parseDouble( element.getAttribute("m" + i));
+
+ return irt;
+ }
+}
+
+class MyHandler implements ErrorHandler {
+ public void warning(SAXParseException e) {
+ System.out.println("Warning: line" + e.getLineNumber());
+ System.out.println(e.getMessage());
+ }
+ public void error(SAXParseException e) {
+ System.out.println("Error: line" + e.getLineNumber());
+ System.out.println(e.getMessage());
+ }
+ public void fatalError(SAXParseException e) {
+ System.out.println("Critical error: line" + e.getLineNumber());
+ System.out.println(e.getMessage());
+ }
+} \ No newline at end of file
diff --git a/src/bin/jpip/opj_viewer_xerces/src/OptionPanel.java b/src/bin/jpip/opj_viewer_xerces/src/OptionPanel.java
new file mode 100644
index 00000000..822e2dd8
--- /dev/null
+++ b/src/bin/jpip/opj_viewer_xerces/src/OptionPanel.java
@@ -0,0 +1,98 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+
+public class OptionPanel extends JPanel implements ActionListener
+{
+ private JButton roibutton;
+ private JButton imregbutton;
+ private ImageManager imgmanager;
+ private ImageViewer iv;
+ private JP2XMLparser xmlparser;
+ private JFrame regimwindow;
+ private RegimViewer regimgviewer;
+
+ public OptionPanel( ImageManager manager, ImageViewer imgviewer)
+ {
+ this.setLayout(new BoxLayout( this, BoxLayout.Y_AXIS));
+
+ roibutton = new JButton("Region Of Interest");
+ imregbutton = new JButton("Image Registration");
+
+ roibutton.setAlignmentX( Component.CENTER_ALIGNMENT);
+ imregbutton.setAlignmentX( Component.CENTER_ALIGNMENT);
+
+ add( roibutton);
+ add( imregbutton);
+ roibutton.addActionListener(this);
+ imregbutton.addActionListener(this);
+
+ imgmanager = manager;
+ iv = imgviewer;
+ xmlparser = null;
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ if( xmlparser == null){
+ byte []xmldata = imgmanager.getXML();
+ if( xmldata != null)
+ xmlparser = new JP2XMLparser( xmldata);
+ }
+ if( e.getSource() == roibutton){
+ if( xmlparser != null){
+ JP2XMLparser.ROIparams roi[] = xmlparser.getROIparams();
+ iv.annotate( roi);
+ }
+ }
+ if( e.getSource() == imregbutton){
+ if( xmlparser != null){
+ if( regimwindow == null){
+ JP2XMLparser.IRTparams irt = xmlparser.getIRTparams();
+
+ regimgviewer = new RegimViewer( irt.refimg, irt.mat);
+ regimgviewer.setOpaque(false);
+
+ regimwindow = new JFrame("Registered Image");
+ regimwindow.getContentPane().add("Center", regimgviewer);
+ regimwindow.pack();
+ regimwindow.setLocation( 500, 50);
+ regimwindow.setVisible(true);
+ }
+ regimgviewer.projection( iv.getImage(), (double)imgmanager.getRw()/(double)imgmanager.getOrigWidth());
+ regimwindow.setSize( regimgviewer.get_imsize());
+ regimwindow.show();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/bin/jpip/test_index.c b/src/bin/jpip/test_index.c
new file mode 100644
index 00000000..1a22c1eb
--- /dev/null
+++ b/src/bin/jpip/test_index.c
@@ -0,0 +1,73 @@
+/*
+ * $Id: test_index.c 46 2011-02-17 14:50:55Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief test_index is a program to test the index code format of a JP2 file
+ *
+ * \section impinst Implementing instructions
+ * This program takes one argument, and print out text type index information to the terminal. \n
+ * -# Input JP2 file\n
+ * % ./test_index input.jp2\n
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include "openjpip.h"
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ index_t *jp2idx;
+ if( argc < 2 ) return 1;
+
+ if( (fd = open( argv[1], O_RDONLY)) == -1){
+ fprintf( stderr, "Error: Target %s not found\n", argv[1]);
+ return -1;
+ }
+
+ if( !(jp2idx = get_index_from_JP2file( fd))){
+ fprintf( stderr, "JP2 file broken\n");
+ return -1;
+ }
+
+ output_index( jp2idx);
+ destroy_index( &jp2idx);
+ close(fd);
+
+ return 0;
+} /* main */
diff --git a/src/bin/mj2/CMakeLists.txt b/src/bin/mj2/CMakeLists.txt
new file mode 100644
index 00000000..44514c54
--- /dev/null
+++ b/src/bin/mj2/CMakeLists.txt
@@ -0,0 +1,94 @@
+# Makefile for the MJ2 codecs of the OpenJPEG library: frames_to_mj2, mj2_to_frames, extract_j2k_from_mj2 and wrap_j2k_in_mj2
+
+set(common_SRCS ${OPENJPEG_SOURCE_DIR}/src/bin/common/opj_getopt.c)
+
+# While mj2 executables do not use the API correctly, we do not link with the library but rather compile the sources files.
+set(OPJ_SRCS
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/bio.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/cio.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/dwt.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/event.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/image.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/j2k.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/j2k_lib.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/jp2.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/jpt.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/mct.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/mqc.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/openjpeg.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/pi.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/raw.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/t1.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/t2.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tcd.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tgt.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/cidx_manager.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/phix_manager.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/ppix_manager.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/thix_manager.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tpix_manager.c
+${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/function_list.c
+)
+
+set(MJ2_SRCS mj2.c mj2_convert.c)
+
+if(WIN32)
+ add_definitions(-DOPJ_STATIC)
+endif()
+
+# Headers file are located here:
+include_directories(
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2
+ ${OPENJPEG_SOURCE_DIR}/src/bin/common
+ ${LCMS_INCLUDE_DIRNAME}
+ )
+
+add_executable(frames_to_mj2
+ frames_to_mj2.c
+ ${common_SRCS}
+ ${OPJ_SRCS}
+ ${MJ2_SRCS}
+ )
+target_link_libraries(frames_to_mj2 ${LCMS_LIBNAME})
+
+if(UNIX)
+ target_link_libraries(frames_to_mj2 m)
+endif()
+
+add_executable(mj2_to_frames
+ mj2_to_frames.c
+ ${common_SRCS}
+ ${OPJ_SRCS}
+ ${MJ2_SRCS}
+ ${OPENJPEG_SOURCE_DIR}/src/bin/common/color.c
+ )
+target_link_libraries(mj2_to_frames ${LCMS_LIBNAME})
+
+if(UNIX)
+ target_link_libraries(mj2_to_frames m)
+endif()
+
+add_executable(extract_j2k_from_mj2
+ extract_j2k_from_mj2.c
+ ${OPJ_SRCS}
+ ${MJ2_SRCS}
+ )
+target_link_libraries(extract_j2k_from_mj2 ${LCMS_LIBNAME})
+
+if(UNIX)
+ target_link_libraries(extract_j2k_from_mj2 m)
+endif()
+
+add_executable(wrap_j2k_in_mj2
+ wrap_j2k_in_mj2.c
+ ${OPJ_SRCS}
+ ${MJ2_SRCS}
+ )
+target_link_libraries(wrap_j2k_in_mj2 ${LCMS_LIBNAME})
+
+if(UNIX)
+ target_link_libraries(wrap_j2k_in_mj2 m)
+endif()
+
+install(TARGETS frames_to_mj2 mj2_to_frames extract_j2k_from_mj2 wrap_j2k_in_mj2
+ DESTINATION ${OPENJPEG_INSTALL_BIN_DIR})
diff --git a/src/bin/mj2/Makefile.am b/src/bin/mj2/Makefile.am
new file mode 100644
index 00000000..cff65660
--- /dev/null
+++ b/src/bin/mj2/Makefile.am
@@ -0,0 +1,111 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+OPJ_SRC = \
+../../libopenjpeg/bio.c \
+../../libopenjpeg/cio.c \
+../../libopenjpeg/dwt.c \
+../../libopenjpeg/event.c \
+../../libopenjpeg/image.c \
+../../libopenjpeg/j2k.c \
+../../libopenjpeg/j2k_lib.c \
+../../libopenjpeg/jp2.c \
+../../libopenjpeg/jpt.c \
+../../libopenjpeg/mct.c \
+../../libopenjpeg/mqc.c \
+../../libopenjpeg/openjpeg.c \
+../../libopenjpeg/pi.c \
+../../libopenjpeg/raw.c \
+../../libopenjpeg/t1.c \
+../../libopenjpeg/t2.c \
+../../libopenjpeg/tcd.c \
+../../libopenjpeg/tgt.c \
+../../libopenjpeg/cidx_manager.c \
+../../libopenjpeg/phix_manager.c \
+../../libopenjpeg/ppix_manager.c \
+../../libopenjpeg/thix_manager.c \
+../../libopenjpeg/tpix_manager.c \
+../../libopenjpeg/function_list.c
+
+bin_PROGRAMS = \
+frames_to_mj2 \
+mj2_to_frames \
+extract_j2k_from_mj2 \
+wrap_j2k_in_mj2
+
+frames_to_mj2_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-DOPJ_STATIC
+frames_to_mj2_CFLAGS =
+frames_to_mj2_LDADD = -lm
+frames_to_mj2_SOURCES = \
+$(OPJ_SRC) \
+../common/opj_getopt.c \
+mj2_convert.c \
+mj2.c \
+frames_to_mj2.c \
+mj2.h \
+mj2_convert.h
+
+mj2_to_frames_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+@LCMS2_CFLAGS@ \
+@LCMS1_CFLAGS@ \
+-DOPJ_STATIC
+mj2_to_frames_CFLAGS =
+mj2_to_frames_LDADD = @LCMS2_LIBS@ @LCMS1_LIBS@ -lm
+mj2_to_frames_SOURCES = \
+$(OPJ_SRC) \
+../common/color.c \
+../common/opj_getopt.c \
+mj2_convert.c \
+mj2.c \
+mj2_to_frames.c \
+mj2.h \
+mj2_convert.h
+
+extract_j2k_from_mj2_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-DOPJ_STATIC
+extract_j2k_from_mj2_CFLAGS =
+extract_j2k_from_mj2_LDADD = -lm
+extract_j2k_from_mj2_SOURCES = \
+$(OPJ_SRC) \
+mj2.c \
+extract_j2k_from_mj2.c \
+mj2.h
+
+wrap_j2k_in_mj2_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/applications/common \
+-I$(top_builddir)/applications/common \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-DOPJ_STATIC
+wrap_j2k_in_mj2_CFLAGS =
+wrap_j2k_in_mj2_LDADD = -lm
+wrap_j2k_in_mj2_SOURCES = \
+$(OPJ_SRC) \
+mj2.c \
+wrap_j2k_in_mj2.c \
+mj2.h
+
+EXTRA_DIST = \
+CMakeLists.txt
+
+install-data-hook:
+ @echo -e " (B)\t$(bindir)/frames_to_mj2$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/mj2_to_frames$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/extract_j2k_from_mj2$(EXEEXT)" >> $(top_builddir)/report.txt
+ @echo -e " (B)\t$(bindir)/wrap_j2k_in_mj2$(EXEEXT)" >> $(top_builddir)/report.txt
diff --git a/src/bin/mj2/extract_j2k_from_mj2.c b/src/bin/mj2/extract_j2k_from_mj2.c
new file mode 100644
index 00000000..f694d531
--- /dev/null
+++ b/src/bin/mj2/extract_j2k_from_mj2.c
@@ -0,0 +1,150 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openjpeg.h"
+#include "cio.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "mj2.h"
+
+/* -------------------------------------------------------------------------- */
+
+/**
+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[]) {
+ opj_dinfo_t* dinfo;
+ opj_event_mgr_t event_mgr; /* event manager */
+ int tnum;
+ unsigned int snum;
+ opj_mj2_t *movie;
+ mj2_tk_t *track;
+ mj2_sample_t *sample;
+ unsigned char* frame_codestream;
+ FILE *file, *outfile;
+ char outfilename[50];
+ mj2_dparameters_t parameters;
+
+ if (argc != 3) {
+ printf("Usage: %s mj2filename output_location\n",argv[0]);
+ printf("Example: %s foreman.mj2 output/foreman\n",argv[0]);
+ return 1;
+ }
+
+ file = fopen(argv[1], "rb");
+
+ if (!file) {
+ fprintf(stderr, "failed to open %s for reading\n", argv[1]);
+ return 1;
+ }
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = info_callback;
+
+ /* get a MJ2 decompressor handle */
+ dinfo = mj2_create_decompress();
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using user parameters */
+ memset(&parameters, 0, sizeof(mj2_dparameters_t));
+ movie = (opj_mj2_t*) dinfo->mj2_handle;
+ mj2_setup_decoder(movie, &parameters);
+
+ if (mj2_read_struct(file, movie)) /* Creating the movie structure*/
+ return 1;
+
+ /* Decode first video track */
+ tnum = 0;
+ while (movie->tk[tnum].track_type != 0)
+ tnum ++;
+
+ track = &movie->tk[tnum];
+
+ fprintf(stdout,"Extracting %d frames from file...\n",track->num_samples);
+
+ for (snum=0; snum < track->num_samples; snum++)
+ {
+ sample = &track->sample[snum];
+ frame_codestream = (unsigned char*) malloc (sample->sample_size-8); /* Skipping JP2C marker*/
+ fseek(file,sample->offset+8,SEEK_SET);
+ fread(frame_codestream,sample->sample_size-8,1, file); /* Assuming that jp and ftyp markers size do*/
+
+ sprintf(outfilename,"%s_%05d.j2k",argv[2],snum);
+ outfile = fopen(outfilename, "wb");
+ if (!outfile) {
+ fprintf(stderr, "failed to open %s for writing\n",outfilename);
+ return 1;
+ }
+ fwrite(frame_codestream,sample->sample_size-8,1,outfile);
+ fclose(outfile);
+ free(frame_codestream);
+ }
+ fclose(file);
+ fprintf(stdout, "%d frames correctly extracted\n", snum);
+
+ /* free remaining structures */
+ if(dinfo) {
+ mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
+ }
+
+ return 0;
+}
diff --git a/src/bin/mj2/frames_to_mj2.c b/src/bin/mj2/frames_to_mj2.c
new file mode 100644
index 00000000..dff34ab7
--- /dev/null
+++ b/src/bin/mj2/frames_to_mj2.c
@@ -0,0 +1,843 @@
+/*
+* Copyright (c) 2003-2004, Francois-Olivier Devaux
+* Copyright (c) 2002-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openjpeg.h"
+#include "j2k_lib.h"
+#include "cio.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "mj2.h"
+#include "mj2_convert.h"
+#include "opj_getopt.h"
+
+/**
+Size of memory first allocated for MOOV box
+*/
+#define TEMP_BUF 10000
+
+#define ENUMCS_GRAY 16
+#define ENUMCS_SRGB 17
+#define ENUMCS_SYCC 18
+
+/* -------------------------------------------------------------------------- */
+
+/**
+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);
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+void help_display()
+{
+ fprintf(stdout,"HELP for frames_to_mj2\n----\n\n");
+ fprintf(stdout,"- the -h option displays this help information on screen\n\n");
+
+
+ fprintf(stdout,"List of parameters for the MJ2 encoder:\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"REMARKS:\n");
+ fprintf(stdout,"---------\n");
+ fprintf(stdout,"\n");
+ fprintf
+ (stdout,"The markers written to the main_header are : SOC SIZ COD QCD COM.\n");
+ fprintf
+ (stdout,"COD and QCD never appear in the tile_header.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"By default:\n");
+ fprintf(stdout,"------------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout," * Lossless\n");
+ fprintf(stdout," * 1 tile\n");
+ fprintf(stdout," * Size of precinct : 2^15 x 2^15 (means 1 precinct)\n");
+ fprintf(stdout," * Size of code-block : 64 x 64\n");
+ fprintf(stdout," * Number of resolutions: 6\n");
+ fprintf(stdout," * No SOP marker in the codestream\n");
+ fprintf(stdout," * No EPH marker in the codestream\n");
+ fprintf(stdout," * No sub-sampling in x or y direction\n");
+ fprintf(stdout," * No mode switch activated\n");
+ fprintf(stdout," * Progression order: LRCP\n");
+ fprintf(stdout," * No index file\n");
+ fprintf(stdout," * No ROI upshifted\n");
+ fprintf(stdout," * No offset of the origin of the image\n");
+ fprintf(stdout," * No offset of the origin of the tiles\n");
+ fprintf(stdout," * Reversible DWT 5-3\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Parameters:\n");
+ fprintf(stdout,"------------\n");
+ fprintf(stdout,"\n");
+ fprintf
+ (stdout,"Required Parameters (except with -h):\n");
+ fprintf
+ (stdout,"-i : source file (-i source.yuv) \n");
+ fprintf
+ (stdout,"-o : destination file (-o dest.mj2) \n");
+ fprintf
+ (stdout,"Optional Parameters:\n");
+ fprintf(stdout,"-h : display the help information \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," (options -r and -q cannot be used together)\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 : number of resolutions (-n 3) \n");
+ fprintf(stdout,"-b : size of code block (-b 32,32) \n");
+ fprintf(stdout,"-c : size of precinct (-c 128,128) \n");
+ fprintf(stdout,"-t : size of tile (-t 512,512) \n");
+ fprintf
+ (stdout,"-p : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \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,"-S : write SOP marker before each packet \n");
+ fprintf
+ (stdout,"-E : write EPH marker after each header packet \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," Example: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
+ fprintf
+ (stdout,"-R : 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,"-d : offset of the origin of the image (-d 150,300) \n");
+ fprintf
+ (stdout,"-T : offset of the origin of the tiles (-T 100,75) \n");
+ fprintf(stdout,"-I : use the irreversible DWT 9-7 (-I) \n");
+ fprintf(stdout,"-W : image width, height and the dx and dy subsampling \n");
+ fprintf(stdout," of the Cb and Cr components for YUV files \n");
+ fprintf(stdout," (default is '352,288,2,2' for CIF format's 352x288 and 4:2:0)\n");
+ fprintf(stdout,"-F : video frame rate (set to 25 by default)\n");
+ fprintf(stdout,"-D : depth, precision in bits [8 .. 16]; default:8\n");
+ fprintf(stdout,"-C : comment\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"IMPORTANT:\n");
+ fprintf(stdout,"-----------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"The index file has the structure below:\n");
+ fprintf(stdout,"---------------------------------------\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Image_height Image_width\n");
+ fprintf(stdout,"progression order\n");
+ fprintf(stdout,"Tiles_size_X Tiles_size_Y\n");
+ fprintf(stdout,"Components_nb\n");
+ fprintf(stdout,"Layers_nb\n");
+ fprintf(stdout,"decomposition_levels\n");
+ fprintf(stdout,"[Precincts_size_X_res_Nr Precincts_size_Y_res_Nr]...\n");
+ fprintf(stdout," [Precincts_size_X_res_0 Precincts_size_Y_res_0]\n");
+ fprintf(stdout,"Main_header_end_position\n");
+ fprintf(stdout,"Codestream_size\n");
+ fprintf(stdout,"Tile_0 start_pos end_Theader end_pos TotalDisto NumPix MaxMSE\n");
+ fprintf(stdout,"Tile_1 '' '' '' '' '' ''\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"Tile_Nt '' '' '' '' '' ''\n");
+ fprintf(stdout,"Tpacket_0 Tile layer res. comp. prec. start_pos end_pos disto\n");
+ fprintf(stdout,"...\n");
+ fprintf(stdout,"Tpacket_Np '' '' '' '' '' '' '' ''\n");
+
+ fprintf(stdout,"MaxDisto\n");
+
+ fprintf(stdout,"TotalDisto\n\n");
+}
+
+OPJ_PROG_ORDER give_progression(char progression[5])
+{
+ if (progression[0] == 'L' && progression[1] == 'R'
+ && progression[2] == 'C' && progression[3] == 'P') {
+ return LRCP;
+ } else {
+ if (progression[0] == 'R' && progression[1] == 'L'
+ && progression[2] == 'C' && progression[3] == 'P') {
+ return RLCP;
+ } else {
+ if (progression[0] == 'R' && progression[1] == 'P'
+ && progression[2] == 'C' && progression[3] == 'L') {
+ return RPCL;
+ } else {
+ if (progression[0] == 'P' && progression[1] == 'C'
+ && progression[2] == 'R' && progression[3] == 'L') {
+ return PCRL;
+ } else {
+ if (progression[0] == 'C' && progression[1] == 'P'
+ && progression[2] == 'R' && progression[3] == 'L') {
+ return CPRL;
+ } else {
+ return PROG_UNKNOWN;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+int main(int argc, char **argv)
+{
+ mj2_cparameters_t mj2_parameters; /* MJ2 compression parameters */
+ opj_cparameters_t *j2k_parameters; /* J2K compression parameters */
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_cio_t *cio;
+ int value;
+ opj_mj2_t *movie;
+ opj_image_t *img;
+ int i, j;
+ char *s, S1, S2, S3;
+ unsigned char *buf;
+ int x1, y1, len;
+ long mdat_initpos, offset;
+ FILE *mj2file;
+ int sampleno;
+ opj_cinfo_t* cinfo;
+ opj_bool bSuccess;
+ int numframes;
+ int prec = 8;/* DEFAULT */
+ double total_time = 0;
+
+ memset(&mj2_parameters, 0, sizeof(mj2_cparameters_t));
+ /* default value */
+ /* ------------- */
+ mj2_parameters.w = 352; // CIF default value
+ mj2_parameters.h = 288; // CIF default value
+ mj2_parameters.CbCr_subsampling_dx = 2; // CIF default value
+ mj2_parameters.CbCr_subsampling_dy = 2; // CIF default value
+ mj2_parameters.frame_rate = 25;
+ mj2_parameters.prec = 8; /* DEFAULT */
+ mj2_parameters.enumcs = ENUMCS_SYCC; /* FIXME: ENUMCS_YUV420 */
+ mj2_parameters.meth = 1; /* enumerated color space */
+
+/*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+*/
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = NULL;
+
+ /* set J2K encoding parameters to default values */
+ opj_set_default_encoder_parameters(&mj2_parameters.j2k_parameters);
+ j2k_parameters = &mj2_parameters.j2k_parameters;
+
+ /* Create comment for codestream */
+ if(j2k_parameters->cp_comment == NULL) {
+ const char comment[] = "Created by OpenJPEG version ";
+ const size_t clen = strlen(comment);
+ const char *version = opj_version();
+ j2k_parameters->cp_comment = (char*)malloc(clen+strlen(version)+1);
+ sprintf(j2k_parameters->cp_comment,"%s%s", comment, version);
+ }
+
+ while (1) {
+ int c = opj_getopt(argc, argv,
+ "i:o:r:q:f:t:n:c:b:p:s:d:P:S:E:M:R:T:C:I:W:F:D:h");
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i': /* IN fill */
+ {
+ char *infile = opj_optarg;
+ s = opj_optarg;
+ while (*s) {
+ s++;
+ }
+ s--;
+ S3 = *s;
+ s--;
+ S2 = *s;
+ s--;
+ S1 = *s;
+
+ if ((S1 == 'y' && S2 == 'u' && S3 == 'v')
+ || (S1 == 'Y' && S2 == 'U' && S3 == 'V')) {
+ mj2_parameters.decod_format = YUV_DFMT;
+ }
+ else {
+ fprintf(stderr,
+ "!! Unrecognized format for infile : %c%c%c [accept only *.yuv] !!\n\n",
+ S1, S2, S3);
+ return 1;
+ }
+ strncpy(mj2_parameters.infile, infile, sizeof(mj2_parameters.infile)-1);
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 'o': /* OUT fill */
+ {
+ char *outfile = opj_optarg;
+ while (*outfile) {
+ outfile++;
+ }
+ outfile--;
+ S3 = *outfile;
+ outfile--;
+ S2 = *outfile;
+ outfile--;
+ S1 = *outfile;
+
+ outfile = opj_optarg;
+
+ if ((S1 == 'm' && S2 == 'j' && S3 == '2')
+ || (S1 == 'M' && S2 == 'J' && S3 == '2'))
+ mj2_parameters.cod_format = MJ2_CFMT;
+ else {
+ fprintf(stderr,
+ "Unknown output format image *.%c%c%c [only *.mj2]!! \n",
+ S1, S2, S3);
+ return 1;
+ }
+ strncpy(mj2_parameters.outfile, outfile, sizeof(mj2_parameters.outfile)-1);
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 'r': /* rates rates/distorsion */
+ {
+ float rate;
+ s = opj_optarg;
+ while (sscanf(s, "%f", &rate) == 1) {
+ j2k_parameters->tcp_rates[j2k_parameters->tcp_numlayers] = rate * 2;
+ j2k_parameters->tcp_numlayers++;
+ while (*s && *s != ',') {
+ s++;
+ }
+ if (!*s)
+ break;
+ s++;
+ }
+ j2k_parameters->cp_disto_alloc = 1;
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 'q': /* add fixed_quality */
+ s = opj_optarg;
+ while (sscanf(s, "%f", &j2k_parameters->tcp_distoratio[j2k_parameters->tcp_numlayers]) == 1) {
+ j2k_parameters->tcp_numlayers++;
+ while (*s && *s != ',') {
+ s++;
+ }
+ if (!*s)
+ break;
+ s++;
+ }
+ j2k_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;
+
+ s = opj_optarg;
+ sscanf(s, "%d", &numlayers);
+ s++;
+ if (numlayers > 9)
+ s++;
+
+ j2k_parameters->tcp_numlayers = numlayers;
+ numresolution = j2k_parameters->numresolution;
+ matrix_width = numresolution * 3;
+ j2k_parameters->cp_matrice = (int *) malloc(numlayers * matrix_width * sizeof(int));
+ s = s + 2;
+
+ for (i = 0; i < numlayers; i++) {
+ row = &j2k_parameters->cp_matrice[i * matrix_width];
+ col = row;
+ j2k_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++;
+ }
+ j2k_parameters->cp_fixed_alloc = 1;
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 't': /* tiles */
+ sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tdx, &j2k_parameters->cp_tdy);
+ j2k_parameters->tile_size_on = OPJ_TRUE;
+ break;
+ /* ----------------------------------------------------- */
+ case 'n': /* resolution */
+ sscanf(opj_optarg, "%d", &j2k_parameters->numresolution);
+ break;
+ /* ----------------------------------------------------- */
+ case 'c': /* precinct dimension */
+ {
+ char sep;
+ int res_spec = 0;
+
+ char *s = opj_optarg;
+ do {
+ sep = 0;
+ sscanf(s, "[%d,%d]%c", &j2k_parameters->prcw_init[res_spec],
+ &j2k_parameters->prch_init[res_spec], &sep);
+ j2k_parameters->csty |= 0x01;
+ res_spec++;
+ s = strpbrk(s, "]") + 2;
+ }
+ while (sep == ',');
+ j2k_parameters->res_spec = res_spec;
+ }
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'b': /* code-block dimension */
+ {
+ int cblockw_init = 0, cblockh_init = 0;
+ sscanf(opj_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;
+ }
+ j2k_parameters->cblockw_init = cblockw_init;
+ j2k_parameters->cblockh_init = cblockh_init;
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 'p': /* progression order */
+ {
+ char progression[5];
+
+ strncpy(progression, opj_optarg, 5);
+ j2k_parameters->prog_order = give_progression(progression);
+ if (j2k_parameters->prog_order == -1) {
+ fprintf(stderr, "Unrecognized progression order "
+ "[LRCP, RLCP, RPCL, PCRL, CPRL] !!\n");
+ return 1;
+ }
+ }
+ break;
+ /* ----------------------------------------------------- */
+ case 's': /* subsampling factor */
+ {
+ if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->subsampling_dx,
+ &j2k_parameters->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(opj_optarg, "%d,%d", &j2k_parameters->image_offset_x0,
+ &j2k_parameters->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 */
+ help_display();
+ return 0;
+ break;
+ /* ----------------------------------------------------- */
+ 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 = opj_optarg;
+ POC = j2k_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++;
+ }
+ j2k_parameters->numpocs = numpocs;
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'S': /* SOP marker */
+ j2k_parameters->csty |= 0x02;
+ break;
+ /* ------------------------------------------------------ */
+ case 'E': /* EPH marker */
+ j2k_parameters->csty |= 0x04;
+ break;
+ /* ------------------------------------------------------ */
+ case 'M': /* Mode switch pas tous au point !! */
+ if (sscanf(opj_optarg, "%d", &value) == 1) {
+ for (i = 0; i <= 5; i++) {
+ int cache = value & (1 << i);
+ if (cache)
+ j2k_parameters->mode |= (1 << i);
+ }
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'R': /* ROI */
+ {
+ if (sscanf(opj_optarg, "OI:c=%d,U=%d", &j2k_parameters->roi_compno,
+ &j2k_parameters->roi_shift) != 2) {
+ fprintf(stderr, "ROI error !! [-ROI:c='compno',U='shift']\n");
+ return 1;
+ }
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'T': /* Tile offset */
+ {
+ if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tx0, &j2k_parameters->cp_ty0) != 2) {
+ fprintf(stderr, "-T 'tile offset' argument error !! [-T X0,Y0]");
+ return 1;
+ }
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'C': /* Add a comment */
+ {
+ j2k_parameters->cp_comment = (char*)malloc(strlen(opj_optarg) + 1);
+ if(j2k_parameters->cp_comment) {
+ strcpy(j2k_parameters->cp_comment, opj_optarg);
+ }
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'I': /* reversible or not */
+ {
+ j2k_parameters->irreversible = 1;
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'W': /* Width and Height and Cb and Cr subsampling in case of YUV format files */
+ if (sscanf
+ (opj_optarg, "%d,%d,%d,%d", &mj2_parameters.w, &mj2_parameters.h, &mj2_parameters.CbCr_subsampling_dx,
+ &mj2_parameters.CbCr_subsampling_dy) != 4) {
+ fprintf(stderr, "-W argument error");
+ return 1;
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'F': /* Video frame rate */
+ if (sscanf(opj_optarg, "%d", &mj2_parameters.frame_rate) != 1) {
+ fprintf(stderr, "-F argument error");
+ return 1;
+ }
+ break;
+ /* ------------------------------------------------------ */
+ case 'D': /* Depth: the precision */
+ if(sscanf(opj_optarg, "%d", &prec) != 1) prec = 0;
+ break;
+
+ default:
+ return 1;
+ }
+ }
+
+ /* Error messages */
+ /* -------------- */
+ if (!mj2_parameters.cod_format || !mj2_parameters.decod_format) {
+ fprintf(stderr,
+ "Usage: %s -i yuv-file -o mj2-file (+ options)\n",argv[0]);
+ return 1;
+ }
+ if(prec < 1 || prec > 16)
+ {
+ fprintf(stderr, "Error: Depth %d must be in the range 8 .. 16\n",prec);
+ return 1;
+ }
+ if ((j2k_parameters->cp_disto_alloc || j2k_parameters->cp_fixed_alloc || j2k_parameters->cp_fixed_quality)
+ && (!(j2k_parameters->cp_disto_alloc ^ j2k_parameters->cp_fixed_alloc ^ j2k_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 (j2k_parameters->tcp_numlayers == 0) {
+ j2k_parameters->tcp_rates[0] = 0; /* MOD antonin : losslessbug */
+ j2k_parameters->tcp_numlayers++;
+ j2k_parameters->cp_disto_alloc = 1;
+ }
+
+ if((j2k_parameters->cp_tx0 > j2k_parameters->image_offset_x0) || (j2k_parameters->cp_ty0 > j2k_parameters->image_offset_y0)) {
+ fprintf(stderr,
+ "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n",
+ j2k_parameters->cp_tx0, j2k_parameters->image_offset_x0, j2k_parameters->cp_ty0, j2k_parameters->image_offset_y0);
+ return 1;
+ }
+
+ for (i = 0; i < j2k_parameters->numpocs; i++) {
+ if (j2k_parameters->POC[i].prg == -1) {
+ fprintf(stderr,
+ "Unrecognized progression order in option -P (POC n %d) [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n",
+ i + 1);
+ }
+ }
+
+ if (j2k_parameters->cp_tdx > mj2_parameters.Dim[0] || j2k_parameters->cp_tdy > mj2_parameters.Dim[1]) {
+ fprintf(stderr,
+ "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n",
+ j2k_parameters->cp_tdx, mj2_parameters.Dim[0], j2k_parameters->cp_tdy, mj2_parameters.Dim[1]);
+ return 1;
+ }
+
+ /* to respect profile - 0 */
+ /* ---------------------- */
+
+ x1 = !mj2_parameters.Dim[0] ? (mj2_parameters.w - 1) * j2k_parameters->subsampling_dx
+ + 1 : mj2_parameters.Dim[0] + (mj2_parameters.w - 1) * j2k_parameters->subsampling_dx + 1;
+ y1 = !mj2_parameters.Dim[1] ? (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy
+ + 1 : mj2_parameters.Dim[1] + (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy + 1;
+ mj2_parameters.numcomps = 3; /* YUV files only have 3 components */
+
+ mj2_parameters.prec = prec;
+
+ j2k_parameters->tcp_mct = 0;
+
+ mj2file = fopen(mj2_parameters.outfile, "wb");
+
+ if (!mj2file) {
+ fprintf(stderr, "failed to open %s for writing\n", argv[2]);
+ return 1;
+ }
+
+ /* get a MJ2 decompressor handle */
+ cinfo = mj2_create_compress();
+ movie = (opj_mj2_t*)cinfo->mj2_handle;
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+
+ /* setup encoder parameters */
+ mj2_setup_encoder(movie, &mj2_parameters);
+
+ movie->tk[0].num_samples =
+ yuv_num_frames(&movie->tk[0],mj2_parameters.infile);
+
+ if (movie->tk[0].num_samples == 0) {
+ return 1;
+ }
+
+ // One sample per chunk
+ movie->tk[0].chunk = (mj2_chunk_t*)
+ malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t));
+ movie->tk[0].sample = (mj2_sample_t*)
+ malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t));
+
+ if (mj2_init_stdmovie(movie)) {
+ fprintf(stderr, "Error with movie initialization");
+ return 1;
+ }
+
+// Writing JP, FTYP and MDAT boxes
+// Assuming that the JP and FTYP boxes won't be longer than 300 bytes:
+ buf = (unsigned char*)
+ malloc (300 * sizeof(unsigned char));
+
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, 300);
+
+ mj2_write_jp(cio);
+ mj2_write_ftyp(movie, cio);
+
+ mdat_initpos = cio_tell(cio);
+ cio_skip(cio, 4);
+
+ cio_write(cio, MJ2_MDAT, 4);
+
+ fwrite(buf,cio_tell(cio),1,mj2file);
+
+ offset = cio_tell(cio);
+ opj_cio_close(cio);
+ free(buf);
+
+ for(i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++)
+ {
+ if(movie->tk[i].track_type != 0)
+ {
+ fprintf(stderr, "Unable to write sound or hint tracks\n");
+ }
+ else
+ {
+ mj2_tk_t *tk;
+ int buflen = 0;
+
+ tk = &movie->tk[i];
+ tk->num_chunks = tk->num_samples;
+ numframes = tk->num_samples;
+ tk->depth = prec;
+
+ fprintf(stderr, "Video Track number %d\n", i);
+
+ img = mj2_image_create(tk, j2k_parameters);
+
+ buflen = 2 * (tk->w * tk->h * 8);
+ buf = (unsigned char *) malloc(buflen*sizeof(unsigned char));
+
+ for(sampleno = 0; sampleno < numframes; sampleno++)
+ {
+ double init_time = opj_clock();
+ double elapsed_time;
+
+ if(yuvtoimage(tk, img, sampleno, j2k_parameters,
+ mj2_parameters.infile))
+ {
+ fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno);
+ return 1;
+ }
+
+/* setup the encoder parameters using the current image and user parameters */
+ opj_setup_encoder(cinfo, j2k_parameters, img);
+
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen);
+
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_JP2C, 4); // JP2C
+
+/* encode the image */
+ bSuccess = opj_encode(cinfo, cio, img, NULL);
+
+ if (!bSuccess) {
+ opj_cio_close(cio);
+ fprintf(stderr, "failed to encode image\n");
+ return 1;
+ }
+
+ len = cio_tell(cio) - 8;
+ cio_seek(cio, 0);
+ cio_write(cio, len+8,4);
+ opj_cio_close(cio);
+
+ tk->sample[sampleno].sample_size = len+8;
+ tk->sample[sampleno].offset = offset;
+ tk->chunk[sampleno].offset = offset; // There is one sample per chunk
+ fwrite(buf, 1, len+8, mj2file);
+ offset += len+8;
+
+ elapsed_time = opj_clock()-init_time;
+ fprintf(stderr, "Frame number %d/%d encoded in %.2f mseconds\n",
+ sampleno + 1, numframes, elapsed_time*1000);
+ total_time += elapsed_time;
+ } /* for(sampleno */
+
+ free(buf);
+ opj_image_destroy(img);
+ }
+ }/* for(i */
+
+ fseek(mj2file, mdat_initpos, SEEK_SET);
+
+ buf = (unsigned char*) malloc(4*sizeof(unsigned char));
+
+// Init a cio to write box length variable in a little endian way
+ cio = opj_cio_open(NULL, buf, 4);
+ cio_write(cio, offset - mdat_initpos, 4);
+ fwrite(buf, 4, 1, mj2file);
+ fseek(mj2file,0,SEEK_END);
+ free(buf);
+
+// Writing MOOV box
+ buf = (unsigned char*)
+ malloc ((TEMP_BUF+numframes*20) * sizeof(unsigned char));
+ cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+numframes*20));
+ mj2_write_moov(movie, cio);
+ fwrite(buf,cio_tell(cio),1,mj2file);
+ free(buf);
+
+ fprintf(stdout,"Total encoding time: %.2f s for %d frames (%.1f fps)\n",
+ total_time, numframes, (float)numframes/total_time);
+
+ // Ending program
+
+ fclose(mj2file);
+/* free remaining compression structures */
+ mj2_destroy_compress(movie);
+ free(cinfo);
+
+ if(j2k_parameters->cp_comment) free(j2k_parameters->cp_comment);
+ if(j2k_parameters->cp_matrice) free(j2k_parameters->cp_matrice);
+ opj_cio_close(cio);
+
+ return 0;
+}
diff --git a/src/bin/mj2/meta_out.c b/src/bin/mj2/meta_out.c
new file mode 100644
index 00000000..b6795045
--- /dev/null
+++ b/src/bin/mj2/meta_out.c
@@ -0,0 +1,2181 @@
+/* meta_out.c */
+/* Dump MJ2, JP2 metadata (partial so far) to xml file */
+/* Callable from mj2_to_metadata */
+/* Contributed to Open JPEG by Glenn Pearson, contract software developer, U.S. National Library of Medicine.
+
+The base code in this file was developed by the author as part of a video archiving
+project for the U.S. National Library of Medicine, Bethesda, MD.
+It is the policy of NLM (and U.S. government) to not assert copyright.
+
+A non-exclusive copy of this code has been contributed to the Open JPEG project.
+Except for copyright, inclusion of the code within Open JPEG for distribution and use
+can be bound by the Open JPEG open-source license and disclaimer, expressed elsewhere.
+*/
+
+#include <windows.h> /* for time functions */
+
+#include "opj_includes.h"
+#include "mj2.h"
+
+#include <time.h>
+#include "meta_out.h"
+
+static BOOL notes = TRUE;
+static BOOL sampletables = FALSE;
+static BOOL raw = TRUE;
+static BOOL derived = TRUE;
+
+opj_tcp_t *j2k_default_tcp;
+
+/* Forwards */
+int xml_write_overall_header(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
+int xml_write_moov(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
+
+void uint_to_chars(unsigned int value, char* buf);
+
+void xml_write_trak(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum, unsigned int sampleframe, opj_event_mgr_t *event_mgr);
+void xml_write_tkhd(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
+void xml_write_udta(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
+void xml_write_mdia(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
+void xml_write_stbl(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum);
+
+void UnixTimeToFileTime(time_t t, LPFILETIME pft);
+void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst);
+void xml_time_out(FILE* xmlout, time_t t);
+
+void int16_to_3packedchars(short int value, char* buf);
+
+void xml_write_moov_udta(FILE* xmlout, opj_mj2_t * movie);
+void xml_write_free_and_skip(FILE* xmlout, opj_mj2_t * movie);
+void xml_write_uuid(FILE* xmlout, opj_mj2_t * movie);
+
+int xml_out_frame(FILE* file, FILE* xmlout, mj2_sample_t *sample, unsigned int snum, opj_event_mgr_t *event_mgr);
+
+void xml_out_frame_siz(FILE* xmlout, opj_image_t *img, opj_cp_t *cp);
+void xml_out_frame_cod(FILE* xmlout, opj_tcp_t *tcp);
+void xml_out_frame_coc(FILE* xmlout, opj_tcp_t *tcp, int numcomps); /* opj_image_t *img); */
+BOOL same_component_style(opj_tccp_t *tccp1, opj_tccp_t *tccp2);
+void xml_out_frame_qcd(FILE* xmlout, opj_tcp_t *tcp);
+void xml_out_frame_qcc(FILE* xmlout, opj_tcp_t *tcp, int numcomps); /* opj_image_t *img); */
+BOOL same_component_quantization(opj_tccp_t *tccp1, opj_tccp_t *tccp2);
+void xml_out_frame_rgn(FILE* xmlout, opj_tcp_t *tcp, int numcomps);/* opj_image_t *img);*/
+void xml_out_frame_poc(FILE* xmlout, opj_tcp_t *tcp);
+void xml_out_frame_ppm(FILE* xmlout, opj_cp_t *cp);
+void xml_out_frame_ppt(FILE* xmlout, opj_tcp_t *tcp);
+void xml_out_frame_tlm(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* NO-OP. TLM NOT SAVED IN DATA STRUCTURE */
+void xml_out_frame_plm(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE. opt in main; can be used in conjunction with PLT */
+void xml_out_frame_plt(FILE* xmlout, opj_tcp_t *tcp); /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE. opt in main; can be used in conjunction with PLT */
+void xml_out_frame_crg(FILE* xmlout); /* j2k_default_tcp is passed globally */ /* opt in main; */
+void xml_out_frame_com(FILE* xmlout, opj_tcp_t *tcp); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
+void xml_out_dump_hex(FILE* xmlout, char *data, int data_len, char* s);
+void xml_out_dump_hex_and_ascii(FILE* xmlout, char *data, int data_len, char* s);
+void xml_out_frame_jp2h(FILE* xmlout, opj_jp2_t *jp2_struct);
+#ifdef NOTYET
+/* Shown with cp, extended, as data structure... but it could be a new different one */
+void xml_out_frame_jp2i(FILE* xmlout, opj_cp_t *cp);/* IntellectualProperty 'jp2i' (no restrictions on location) */
+void xml_out_frame_xml(FILE* xmlout, opj_cp_t *cp); /* XML 'xml\040' (0x786d6c20). Can appear multiply */
+void xml_out_frame_uuid(FILE* xmlout, opj_cp_t *cp); /* UUID 'uuid' (top level only) */
+void xml_out_frame_uinf(FILE* xmlout, opj_cp_t *cp); /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
+void xml_out_frame_unknown_type(FILE* xmlout, opj_cp_t *cp);
+#endif
+
+
+void xml_write_init(BOOL n, BOOL t, BOOL r, BOOL d)
+{
+ /* Init file globals */
+ notes = n;
+ sampletables = t;
+ raw = r;
+ derived = d;
+}
+
+int xml_write_struct(FILE* file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, char* stringDTD, opj_event_mgr_t *event_mgr) {
+
+ if(stringDTD != NULL)
+ {
+ fprintf(xmlout,"<?xml version=\"1.0\" standalone=\"no\"?>\n");
+ /* stringDTD is known to start with "SYSTEM " or "PUBLIC " */
+ /* typical: SYSTEM mj2_to_metadata.dtd */
+ stringDTD[6] = '\0'; /* Break into two strings at space, so quotes can be inserted. */
+ fprintf(xmlout,"<!DOCTYPE MJ2_File %s \"%s\">\n", stringDTD, stringDTD+7);
+ stringDTD[6] = ' '; /* restore for sake of debugger or memory allocator */
+ } else
+ fprintf(xmlout,"<?xml version=\"1.0\" standalone=\"yes\"?>\n");
+
+ fprintf(xmlout, "<MJ2_File>\n");
+ xml_write_overall_header(file, xmlout, movie, sampleframe, event_mgr);
+ fprintf(xmlout, "</MJ2_File>");
+ return 0;
+}
+
+/* ------------- */
+
+int xml_write_overall_header(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
+{
+ int i;
+ char buf[5];
+ buf[4] = '\0';
+
+ fprintf(xmlout, " <JP2 BoxType=\"jP[space][space]\" Signature=\"0x0d0a870a\" />\n");
+ // Called after structure initialized by mj2_read_ftyp
+ fprintf(xmlout, " <FileType BoxType=\"ftyp\">\n");
+ uint_to_chars(movie->brand, buf);
+ fprintf(xmlout, " <Brand>%s</Brand>\n", buf); /* 4 character; BR */
+ fprintf(xmlout, " <MinorVersion>%u</MinorVersion>\n", movie->minversion); /* 4 char; MinV */
+ fprintf(xmlout, " <CompatibilityList Count=\"%d\">\n",movie->num_cl);
+ for (i = movie->num_cl - 1; i > -1; i--) /* read routine stored in reverse order, so let's undo damage */
+ {
+ uint_to_chars(movie->cl[i], buf);
+ fprintf(xmlout, " <CompatibleBrand>%s</CompatibleBrand>\n", buf); /*4 characters, each CLi */
+ }
+ fprintf(xmlout, " </CompatibilityList>\n");
+ fprintf(xmlout, " </FileType>\n");
+ xml_write_moov(file, xmlout, movie, sampleframe, event_mgr);
+ // To come? <mdat> // This is the container for media data that can also be accessed through track structures,
+ // so is redundant, and simply not of interest as metadata
+ // <moof> // Allows incremental build up of movie. Probably not in Simple Profile
+ xml_write_free_and_skip(xmlout, movie); /* NO OP so far */ /* May be a place where user squirrels metadata */
+ xml_write_uuid(xmlout, movie); /* NO OP so far */ /* May be a place where user squirrels metadata */
+ return 0;
+}
+
+/* ------------- */
+
+int xml_write_moov(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
+{
+ unsigned int tnum;
+ mj2_tk_t *track;
+
+ fprintf(xmlout, " <MovieBox BoxType=\"moov\">\n");
+ fprintf(xmlout, " <MovieHeader BoxType=\"mvhd\">\n");
+ fprintf(xmlout, " <CreationTime>\n");
+ if(raw)
+ fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", movie->creation_time);
+ if(notes)
+ fprintf(xmlout, " <!-- Seconds since start of Jan. 1, 1904 UTC (Greenwich) -->\n");
+ /* 2082844800 = seconds between 1/1/04 and 1/1/70 */
+ /* There's still a time zone offset problem not solved... but spec is ambigous as to whether stored time
+ should be local or UTC */
+ if(derived) {
+ fprintf(xmlout, " <AsLocalTime>");
+ xml_time_out(xmlout, movie->creation_time - 2082844800);
+ fprintf(xmlout,"</AsLocalTime>\n");
+ }
+ fprintf(xmlout, " </CreationTime>\n");
+ fprintf(xmlout, " <ModificationTime>\n");
+ if(raw)
+ fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", movie->modification_time);
+ if(derived) {
+ fprintf(xmlout, " <AsLocalTime>");
+ xml_time_out(xmlout, movie->modification_time - 2082844800);
+ fprintf(xmlout,"</AsLocalTime>\n");
+ }
+ fprintf(xmlout, " </ModificationTime>\n");
+ fprintf(xmlout, " <Timescale>%d</Timescale>\n", movie->timescale);
+ if(notes)
+ fprintf(xmlout, " <!-- Timescale defines time units in one second -->\n");
+ fprintf(xmlout, " <Rate>\n"); /* Rate to play presentation (default = 0x00010000) */
+ if(notes) {
+ fprintf(xmlout, " <!-- Rate to play presentation is stored as fixed-point binary 16.16 value. Decimal value is approximation. -->\n");
+ fprintf(xmlout, " <!-- Rate is expressed relative to normal (default) value of 0x00010000 (1.0) -->\n");
+ }
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", movie->rate);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)movie->rate/(double)0x00010000);
+ fprintf(xmlout, " </Rate>\n");
+ fprintf(xmlout, " <Duration>\n");
+ if(raw)
+ fprintf(xmlout, " <InTimeUnits>%u</InTimeUnits>\n", movie->duration);
+ if(derived)
+ fprintf(xmlout, " <InSeconds>%12.3f</InSeconds>\n", (double)movie->duration/(double)movie->timescale); // Make this double later to get fractional seconds
+ fprintf(xmlout, " </Duration>\n");
+#ifdef CURRENTSTRUCT
+ movie->volume = movie->volume << 8;
+#endif
+ fprintf(xmlout, " <Volume>\n");
+ if(notes) {
+ fprintf(xmlout, " <!-- Audio volume stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
+ fprintf(xmlout, " <!-- Full, normal (default) value is 0x0100 (1.0) -->\n");
+ }
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%04x</AsHex>\n", movie->volume);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%6.3f</AsDecimal>\n", (double)movie->volume/(double)0x0100);
+ fprintf(xmlout, " </Volume>\n");
+#ifdef CURRENTSTRUCT
+ if(notes)
+ fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
+ movie->volume = movie->volume >> 8;
+#endif
+ /* Transformation matrix for video */
+ fprintf(xmlout, " <TransformationMatrix>\n");
+ if(notes) {
+ fprintf(xmlout, " <!-- 3 x 3 Video Transformation Matrix {a,b,u,c,d,v,x,y,w}. Required: u=0, v=0, w=1 -->\n");
+ fprintf(xmlout, " <!-- Maps decompressed point (p,q) to rendered point (ap + cq + x, bp + dq + y) -->\n");
+ fprintf(xmlout, " <!-- Stored as Fixed Point Hex: all are binary 16.16, except u,v,w are 2.30 -->\n");
+ fprintf(xmlout, " <!-- Unity = 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 -->\n");
+ }
+ fprintf(xmlout, " <TMa>0x%08x</TMa>\n", movie->trans_matrix[0]);
+ fprintf(xmlout, " <TMb>0x%08x</TMb>\n", movie->trans_matrix[1]);
+ fprintf(xmlout, " <TMu>0x%08x</TMu>\n", movie->trans_matrix[2]);
+ fprintf(xmlout, " <TMc>0x%08x</TMc>\n", movie->trans_matrix[3]);
+ fprintf(xmlout, " <TMd>0x%08x</TMd>\n", movie->trans_matrix[4]);
+ fprintf(xmlout, " <TMv>0x%08x</TMv>\n", movie->trans_matrix[5]);
+ fprintf(xmlout, " <TMx>0x%08x</TMx>\n", movie->trans_matrix[6]);
+ fprintf(xmlout, " <TMy>0x%08x</TMy>\n", movie->trans_matrix[7]);
+ fprintf(xmlout, " <TMw>0x%08x</TMw>\n", movie->trans_matrix[8]);
+ fprintf(xmlout, " </TransformationMatrix>\n");
+ fprintf(xmlout, " </MovieHeader>\n");
+
+ fprintf(xmlout, " <Statistics>\n");
+ fprintf(xmlout, " <TracksFound>\n");
+ fprintf(xmlout, " <Video>%d</Video>\n", movie->num_vtk);
+ fprintf(xmlout, " <Audio>%d</Audio>\n", movie->num_stk);
+ fprintf(xmlout, " <Hint>%d</Hint>\n", movie->num_htk);
+ if(notes)
+ fprintf(xmlout, " <!-- Hint tracks for streaming video are not part of MJ2, but are a defined extension. -->\n");
+ /* See Part 3 Amend 2 Section 4.2 for relation of MJ2 to Part 12 Sections 7 and 10 hints */
+ fprintf(xmlout, " </TracksFound>\n");
+ fprintf(xmlout, " </Statistics>\n");
+ /* Idea for the future: It would be possible to add code to verify that the file values:
+ 1) are legal and self-consistent
+ 2) comply with particular JP2 and/or MJ2 profiles.
+ This could be reported here as additional XML elements */
+
+ // Find first video track
+ tnum = 0;
+ while (movie->tk[tnum].track_type != 0)
+ tnum ++;
+
+ track = &(movie->tk[tnum]);
+ // For now, output info on first video track
+ xml_write_trak(file, xmlout, track, tnum, sampleframe, event_mgr);
+
+ // to come: <MovieExtends mvek> // possibly not in Simple Profile
+ xml_write_moov_udta(xmlout, movie); /* NO OP so far */ /* <UserDataBox udta> contains <CopyrightBox cprt> */
+ fprintf(xmlout, " </MovieBox>\n");
+ return 0;
+}
+
+/* --------------- */
+
+void uint_to_chars(unsigned int value, char* buf)
+{
+ /* buf is at least char[5] */
+ int i;
+ for (i = 3; i >= 0; i--)
+ {
+ buf[i] = (value & 0x000000ff);
+ value = (value >> 8);
+ }
+ buf[4] = '\0'; /* Precautionary */
+}
+
+/* ------------- */
+
+/* WINDOWS SPECIFIC */
+
+void UnixTimeToFileTime(time_t t, LPFILETIME pft)
+{
+ /* Windows specific. From MS Q167296 */
+ /* 'time_t' represents seconds since midnight January 1, 1970 UTC (coordinated universal time). */
+ /* 64-bit FILETIME structure represents the number of 100-nanosecond intervals since January 1, 1601 UTC (coordinate universal time). */
+ LONGLONG ll; /* LONGLONG is a 64-bit value. */
+ ll = Int32x32To64(t, 10000000) + 116444736000000000;
+ pft->dwLowDateTime = (DWORD)ll;
+ /* pft->dwLowDateTime = (DWORD)(0x00000000ffffffff & ll); */
+ pft->dwHighDateTime = (DWORD)(ll >> 32);
+}
+// Once the UNIX time is converted to a FILETIME structure,
+// other Win32 time formats can be easily obtained by using Win32 functions such
+// as FileTimeToSystemTime() and FileTimeToDosDateTime().
+
+/* ------------- */
+
+void UnixTimeToSystemTime(time_t t, LPSYSTEMTIME pst)
+{
+ /* Windows specific */
+ FILETIME ft;
+ UnixTimeToFileTime(t, &ft);
+ FileTimeToLocalFileTime( &ft, &ft ); /* Adjust from UTC to local time zone */
+ FileTimeToSystemTime(&ft, pst);
+}
+
+/* ------------- */
+
+void xml_time_out(FILE* xmlout, time_t t)
+{
+ /* Windows specific */
+ SYSTEMTIME st;
+ char szLocalDate[255], szLocalTime[255];
+ UnixTimeToSystemTime( t, &st );
+ GetDateFormat( LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szLocalDate, 255 );
+ GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, NULL, szLocalTime, 255 );
+ fprintf(xmlout, "%s %s", szLocalDate, szLocalTime );
+}
+
+/* END WINDOWS SPECIFIC */
+
+/* ------------- */
+
+void xml_write_moov_udta(FILE* xmlout, opj_mj2_t * movie) {
+ /* Compare with xml_write_udta */
+#ifdef NOTYET
+ /* NO-OP so far. Optional UserData 'udta' (zero or one in moov or each trak)
+ can contain multiple Copyright 'cprt' with different language codes */
+ /* There may be nested non-standard boxes within udta */
+ IMAGINE movie->udta, movie->copyright_count, movie->copyright_language[i] (array of 16bit ints), movie->copyright_notice[i] (array of buffers)
+ PROBABLY ALSO NEED movie->udta_len or special handler for non-standard boxes
+ char buf[5];
+ int i;
+
+ if(movie->udta != 1)
+ return; /* Not present */
+
+ fprintf(xmlout, " <UserData BoxType=\"udta\">\n");
+ for(i = 0; i < movie->copyright_count; i++) {
+ fprintf(xmlout, " <Copyright BoxType=\"cprt\"> Instance=\"%d\">\n", i+1);
+ int16_to_3packedchars((short int)movie->copyright_languages[i], buf);
+ fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
+ fprintf(xmlout, " <Notice>%s</Notice>\n",movie->copyright_notices[i]);
+ fprintf(xmlout, " </Copyright>\n", i+1);
+ }
+ /* TO DO: Non-standard boxes */
+ fprintf(xmlout, " </UserData>\n");
+#endif
+}
+
+void xml_write_free_and_skip(FILE* xmlout, opj_mj2_t * movie) {
+#ifdef NOTYET
+ /* NO-OP so far. There can be zero or more instances of free and/or skip
+ at the top level of the file. This may be a place where the user squirrel's metadata.
+ Let's assume unstructured, and do a dump */
+ IMAGINE movie->free_and_skip, movie->free_and_skip_count, movie->free_and_skip_content[i] (array of buffers),
+ movie->free_and_skip_len[i] (array of ints), movie->is_skip[i] (array of BOOL)
+ int i;
+
+ if(movie->free_and_skip != 1)
+ return; /* Not present */
+
+ for(i = 0; i < movie->free_and_skip_count; i++) {
+ if(movie->is_skip[i])
+ fprintf(xmlout, " <Skip BoxType=\"skip\">\n");
+ else
+ fprintf(xmlout, " <Free BoxType=\"free\">\n");
+
+ xml_out_dump_hex_and_ascii(xmlout, movie->free_and_skip_contents[i], movie->free_and_skip_len[i]);
+
+ if(movie->is_skip[i])
+ fprintf(xmlout, " </Skip>\n");
+ else
+ fprintf(xmlout, " </Free>\n");
+ }
+#endif
+}
+
+void xml_write_uuid(FILE* xmlout, opj_mj2_t * movie) {
+/* Univeral Unique IDs of 16 bytes. */
+#ifdef NOTYET
+ /* NO-OP so far. There can be zero or more instances of private uuid boxes in a file.
+ This function supports the top level of the file, but uuid may be elsewhere [not yet supported].
+ This may be a place where the user squirrel's metadata. Let's assume unstructured, and do a dump */
+ IMAGINE movie->uuid, movie->uuid_count, movie->uuid_content[i] (array of buffers),
+ movie->uuid_len[i] (array of ints), movie->uuid_type[i] (array of 17-byte (16+null termination) buffers)
+ int i;
+
+ if(movie->uuid != 1)
+ return; /* Not present */
+
+ for(i = 0; i < movie->uuid_count; i++) {
+ fprintf(xmlout, " <PrivateExtension BoxType=\"uuid\" UUID=\"%s\">\n", movie->uuid_type[i]);
+ // See Part III section 5.2.1, 6.1, 6.2
+ xml_out_dump_hex_and_ascii(xmlout, movie->uuid_contents[i], movie->uuid_len[i]);
+ fprintf(xmlout, " </PrivateExtension>\n");
+ }
+#endif
+}
+
+/* ------------- */
+
+void xml_write_trak(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum, unsigned int sampleframe, opj_event_mgr_t *event_mgr)
+{
+ fprintf(xmlout, " <Track BoxType=\"trak\" Instance=\"%d\">\n", tnum);
+ xml_write_tkhd(file, xmlout, track, tnum);
+ // TO DO: TrackReferenceContainer 'tref' just used in hint track
+ // TO DO: EditListContainer 'edts', contains EditList 'elst' with media-time, segment-duration, media-rate
+ xml_write_mdia(file, xmlout, track, tnum);
+ xml_write_udta(file, xmlout, track, tnum); // NO-OP so far. Optional UserData 'udta', can contain multiple Copyright 'cprt'
+
+ if(track->track_type==0) { /* Only do for visual track */
+ /* sampleframe is from user option -f. 1 = first frame */
+ /* sampleframe of 0 is a user requests: no jp2 header */
+ /* Treat out-of-bounds values in the same way */
+ if(sampleframe > 0 && sampleframe <= track->num_samples)
+ {
+ mj2_sample_t *sample;
+ unsigned int snum;
+
+ snum = sampleframe-1;
+ // Someday maybe do a smart range scan... for (snum=0; snum < track->num_samples; snum++){
+ // fprintf(stdout,"Frame %d: ",snum+1);
+ sample = &track->sample[snum];
+ if(xml_out_frame(file, xmlout, sample, snum, event_mgr))
+ return; /* Not great error handling here */
+ }
+ }
+ fprintf(xmlout, " </Track>\n");
+}
+
+/* ------------- */
+
+void xml_write_tkhd(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
+{
+ fprintf(xmlout, " <TrackHeader BoxType=\"tkhd\">\n");
+ if(notes) {
+ fprintf(xmlout, " <!-- Not shown here: CreationTime, ModificationTime, Duration. -->\n");
+ fprintf(xmlout, " <!-- These 3 fields are reported under MediaHeader below. When reading these 3, -->\n");
+ fprintf(xmlout, " <!-- m2j_to_metadata currently doesn't distinguish between TrackHeader and MediaHeader source. -->\n");
+ fprintf(xmlout, " <!-- If both found, value read from MediaHeader is used. -->\n");
+ }
+ fprintf(xmlout, " <TrackID>%u</TrackID>\n", track->track_ID);
+ if(track->track_type==0) /* For visual track */
+ {
+ fprintf(xmlout, " <TrackLayer>%d</TrackLayer>\n", track->layer);
+ if(notes)
+ fprintf(xmlout," <!-- front-to-back ordering of video tracks. 0 = normal, -1 is closer, etc. -->\n");
+ }
+ if(track->track_type!=0) /* volume irrelevant for visual track */
+ {
+#ifdef CURRENTSTRUCT
+ track->volume = track->volume << 8;
+#endif
+ fprintf(xmlout, " <Volume>\n");
+ if(notes) {
+ fprintf(xmlout," <!-- Track audio volume stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
+ fprintf(xmlout," <!-- Full, normal (default) value is 0x0100 (1.0) -->\n");
+ }
+ if(raw)
+ fprintf(xmlout," <AsHex>0x%04x</AsHex>\n", track->volume);
+ if(derived)
+ fprintf(xmlout," <AsDecimal>%6.3f</AsDecimal>\n", (double)track->volume/(double)0x0100);
+ fprintf(xmlout, " </Volume>\n");
+#ifdef CURRENTSTRUCT
+ if(notes)
+ fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
+ track->volume = track->volume >> 8;
+#endif
+ }
+ if(track->track_type==0)
+ {
+ /* Transformation matrix for video */
+ fprintf(xmlout, " <TransformationMatrix>\n");
+ if(notes) {
+ fprintf(xmlout," <!-- Comments about matrix in MovieHeader apply here as well. -->\n");
+ fprintf(xmlout," <!-- This matrix is applied before MovieHeader one. -->\n");
+ }
+ fprintf(xmlout, " <TMa>0x%08x</TMa>\n", track->trans_matrix[0]);
+ fprintf(xmlout, " <TMb>0x%08x</TMb>\n", track->trans_matrix[1]);
+ fprintf(xmlout, " <TMu>0x%08x</TMu>\n", track->trans_matrix[2]);
+ fprintf(xmlout, " <TMc>0x%08x</TMc>\n", track->trans_matrix[3]);
+ fprintf(xmlout, " <TMd>0x%08x</TMd>\n", track->trans_matrix[4]);
+ fprintf(xmlout, " <TMv>0x%08x</TMv>\n", track->trans_matrix[5]);
+ fprintf(xmlout, " <TMx>0x%08x</TMx>\n", track->trans_matrix[6]);
+ fprintf(xmlout, " <TMy>0x%08x</TMy>\n", track->trans_matrix[7]);
+ fprintf(xmlout, " <TMw>0x%08x</TMw>\n", track->trans_matrix[8]);
+ fprintf(xmlout, " </TransformationMatrix>\n");
+ }
+#ifdef CURRENTSTRUCT
+ track->w = track->w << 16;
+ track->h = track->h << 16;
+#endif
+ if(notes) {
+ fprintf(xmlout, " <!-- Width and Height in pixels are for the presentation; frames will be scaled to this. -->\n");
+ fprintf(xmlout, " <!-- Both stored as fixed-point binary 16.16 values. Decimal values are approximations. -->\n");
+ }
+ fprintf(xmlout, " <Width>\n");
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->w);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->w/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
+ fprintf(xmlout, " </Width>\n");
+ fprintf(xmlout, " <Height>\n");
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->h);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->h/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
+ fprintf(xmlout, " </Height>\n");
+#ifdef CURRENTSTRUCT
+ if(notes) {
+ fprintf(xmlout, " <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
+ fprintf(xmlout, " <!-- Also, width and height values shown here will actually be those read from track's <VisualSampleEntry> if given. -->\n");
+ }
+ track->w = track->w >> 16;
+ track->h = track->h >> 16;
+#endif
+ fprintf(xmlout, " </TrackHeader>\n");
+}
+
+/* ------------- */
+
+void xml_write_udta(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum) {
+ /* NO-OP so far. Optional UserData 'udta' (zero or one in moov or each trak)
+ can contain multiple Copyright 'cprt' with different language codes */
+ /* There may be nested non-standard boxes within udta */
+#ifdef NOTYET
+ IMAGINE track->udta, track->copyright_count, track->copyright_language[i] (array of 16bit ints), track->copyright_notice[i] (array of buffers)
+ PROBABLY ALSO NEED track->udta_len or special handler for non-standard boxes
+ char buf[5];
+ int i;
+
+ if(track->udta != 1)
+ return; /* Not present */
+
+ fprintf(xmlout, " <UserData BoxType=\"udta\">\n");
+ for(i = 0; i < track->copyright_count; i++) {
+ fprintf(xmlout, " <Copyright BoxType=\"cprt\"> Instance=\"%d\">\n", i+1);
+ int16_to_3packedchars((short int)track->copyright_languages[i], buf);
+ fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
+ fprintf(xmlout, " <Notice>%s</Notice>\n",track->copyright_notices[i]);
+ fprintf(xmlout, " </Copyright>\n", i+1);
+ }
+ /* TO DO: Non-standard boxes */
+ fprintf(xmlout, " </UserData>\n");
+#endif
+}
+
+/* ------------- */
+
+void xml_write_mdia(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
+{
+ char buf[5];
+ int i, k;
+ buf[4] = '\0';
+
+ fprintf(xmlout, " <Media BoxType=\"mdia\">\n");
+ fprintf(xmlout, " <MediaHeader BoxType=\"mdhd\">\n");
+ fprintf(xmlout, " <CreationTime>\n");
+ if(raw)
+ fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", track->creation_time);
+ if(notes)
+ fprintf(xmlout, " <!-- Seconds since start of Jan. 1, 1904 UTC (Greenwich) -->\n");
+ /* 2082844800 = seconds between 1/1/04 and 1/1/70 */
+ /* There's still a time zone offset problem not solved... but spec is ambigous as to whether stored time
+ should be local or UTC */
+ if(derived) {
+ fprintf(xmlout, " <AsLocalTime>");
+ xml_time_out(xmlout, track->creation_time - 2082844800);
+ fprintf(xmlout,"</AsLocalTime>\n");
+ }
+ fprintf(xmlout, " </CreationTime>\n");
+ fprintf(xmlout, " <ModificationTime>\n");
+ if(raw)
+ fprintf(xmlout, " <InSeconds>%u</InSeconds>\n", track->modification_time);
+ if(derived) {
+ fprintf(xmlout, " <AsLocalTime>");
+ xml_time_out(xmlout, track->modification_time - 2082844800);
+ fprintf(xmlout,"</AsLocalTime>\n");
+ }
+ fprintf(xmlout, " </ModificationTime>\n");
+ fprintf(xmlout, " <Timescale>%d</Timescale>\n", track->timescale);
+ if(notes)
+ fprintf(xmlout, " <!-- Timescale defines time units in one second -->\n");
+ fprintf(xmlout, " <Duration>\n");
+ if(raw)
+ fprintf(xmlout, " <InTimeUnits>%u</InTimeUnits>\n", track->duration);
+ if(derived)
+ fprintf(xmlout, " <InSeconds>%12.3f</InSeconds>\n", (double)track->duration/(double)track->timescale); // Make this double later to get fractional seconds
+ fprintf(xmlout, " </Duration>\n");
+ int16_to_3packedchars((short int)track->language, buf);
+ fprintf(xmlout, " <Language>%s</Language>\n", buf); /* 3 chars */
+ fprintf(xmlout, " </MediaHeader>\n");
+ fprintf(xmlout, " <HandlerReference BoxType=\"hdlr\">\n");
+ switch(track->track_type)
+ {
+ case 0:
+ fprintf(xmlout, " <HandlerType Code=\"vide\">video media track</HandlerType>\n"); break;
+ case 1:
+ fprintf(xmlout, " <HandlerType Code=\"soun\">Sound</HandlerType>\n"); break;
+ case 2:
+ fprintf(xmlout, " <HandlerType Code=\"hint\">Hint</HandlerType>\n"); break;
+ }
+ if(notes) {
+ fprintf(xmlout, " <!-- String value shown is not actually read from file. -->\n");
+ fprintf(xmlout, " <!-- Shown value is one used for our encode. -->\n");
+ }
+ fprintf(xmlout, " </HandlerReference>\n");
+ fprintf(xmlout, " <MediaInfoContainer BoxType=\"minf\">\n");
+ switch(track->track_type)
+ {
+ case 0:
+ fprintf(xmlout, " <VideoMediaHeader BoxType=\"vmhd\">\n");
+ fprintf(xmlout, " <GraphicsMode>0x%02x</GraphicsMode>\n", track->graphicsmode);
+ if(notes) {
+ fprintf(xmlout," <!-- Enumerated values of graphics mode: -->\n");
+ fprintf(xmlout," <!-- 0x00 = copy (over existing image); -->\n");
+ fprintf(xmlout," <!-- 0x24 = transparent; 'blue-screen' this image using opcolor; -->\n");
+ fprintf(xmlout," <!-- 0x100 = alpha; alpha-blend this image -->\n");
+/* fprintf(xmlout," <!-- 0x101 = whitealpha; alpha-blend this image, which has been blended with white; -->\n"); This was evidently dropped upon amendment */
+ fprintf(xmlout," <!-- 0x102 = pre-multiplied black alpha; image has been already been alpha-blended with black. -->\n");
+ fprintf(xmlout," <!-- 0x110 = component alpha; blend alpha channel(s) and color channels individually. -->\n");
+ }
+ fprintf(xmlout, " <Opcolor>\n");
+ fprintf(xmlout, " <Red>0x%02x</Red>\n", track->opcolor[0]);
+ fprintf(xmlout, " <Green>0x%02x</Green>\n",track->opcolor[1]);
+ fprintf(xmlout, " <Blue>0x%02x</Blue>\n",track->opcolor[2]);
+ fprintf(xmlout, " </Opcolor>\n");
+ fprintf(xmlout, " </VideoMediaHeader>\n");
+ break;
+ case 1:
+ fprintf(xmlout, " <SoundMediaHeader BoxType=\"smhd\">\n");
+#ifdef CURRENTSTRUCT
+ track->balance = track->balance << 8;
+#endif
+ fprintf(xmlout, " <Balance>\n");
+ if(notes) {
+ fprintf(xmlout," <!-- Track audio balance fixes mono track in stereo space. -->\n");
+ fprintf(xmlout," <!-- Stored as fixed-point binary 8.8 value. Decimal value is approximation. -->\n");
+ fprintf(xmlout," <!-- 0.0 = center, -1.0 = full left, 1.0 = full right -->\n");
+ }
+ if(raw)
+ fprintf(xmlout," <AsHex>0x%04x</AsHex>\n", track->balance);
+ if(derived)
+ fprintf(xmlout," <AsDecimal>%6.3f</AsDecimal>\n", (double)track->balance/(double)0x0100);
+ fprintf(xmlout, " </Balance>\n");
+#ifdef CURRENTSTRUCT
+ if(notes)
+ fprintf(xmlout," <!-- Current m2j_to_metadata implementation always shows bits to right of decimal as zeroed. -->\n");
+ track->balance = track->balance >> 8;
+#endif
+ fprintf(xmlout, " </SoundMediaHeader>\n");
+ break;
+ case 2:
+ fprintf(xmlout, " <HintMediaHeader BoxType=\"hmhd\">\n");
+ fprintf(xmlout, " <MaxPDU_Size>%d</MaxPDU_Size>\n", track->maxPDUsize);
+ if(notes)
+ fprintf(xmlout," <!-- Size in bytes of largest PDU in this hint stream. -->\n");
+ fprintf(xmlout, " <AvgPDU_Size>%d</AvgPDU_Size>\n", track->avgPDUsize);
+ if(notes)
+ fprintf(xmlout," <!-- Average size in bytes of a PDU over the entire presentation. -->\n");
+ fprintf(xmlout, " <MaxBitRate>%d</MaxBitRate>\n", track->maxbitrate);
+ if(notes)
+ fprintf(xmlout," <!-- Maximum rate in bits per second over any window of 1 second. -->\n");
+ fprintf(xmlout, " <AvgBitRate>%d</AvgBitRate>\n", track->avgbitrate);
+ if(notes)
+ fprintf(xmlout," <!-- Averate rate in bits per second over the entire presentation. -->\n");
+ fprintf(xmlout, " <SlidingAvgBit>%d</SlidingAvgBitRate>\n", track->slidingavgbitrate);
+ if(notes)
+ fprintf(xmlout," <!-- Maximum rate in bits per second over any window of one minute. -->\n");
+ fprintf(xmlout, " </HintMediaHeader>\n");
+ break;
+ }
+ fprintf(xmlout, " <DataInfo BoxType=\"dinf\">\n");
+ fprintf(xmlout, " <DataReference BoxType=\"dref\" URL_Count=\"%d\" URN_Count=\"%d\">\n", track->num_url, track->num_urn); // table w. flags, URLs, URNs
+ // Data structure does not distinguish between single URL, single URN, or DREF table or URLs & URNs.
+ // We could infer those, but for now just present everything as a DREF table.
+ if(notes)
+ fprintf(xmlout, " <!-- No entries here mean that file is self-contained, as required by Simple Profile. -->\n");
+ for(k = 0; k < track->num_url; k++) {
+ fprintf(xmlout, " <DataEntryUrlBox BoxType=\"url[space]\">\n"); // table w. flags, URLs, URNs
+ if(notes)
+ fprintf(xmlout," <!-- Only the first 16 bytes of URL location are recorded in mj2_to_metadata data structure. -->\n");
+ for(i = 0; i < 4; i++) {
+ uint_to_chars(track->url[track->num_url].location[i], buf);
+ fprintf(xmlout, " <Location>%s</Location>\n");
+ }
+ fprintf(xmlout, " </DataEntryUrlBox>\n"); // table w. flags, URLs, URNs
+ }
+ for(k = 0; k < track->num_urn; k++) {
+ fprintf(xmlout," <DataEntryUrnBox BoxType=\"urn[space]\">\n"); // table w. flags, URLs, URNs
+ // Only the first 16 bytes are recorded in the data structure currently.
+ if(notes)
+ fprintf(xmlout," <!-- Only the first 16 bytes each of URN name and optional location are recorded in mj2_to_metadata data structure. -->\n");
+ fprintf(xmlout, " <Name>");
+ for(i = 0; i < 4; i++) {
+ uint_to_chars(track->urn[track->num_urn].name[i], buf);
+ fprintf(xmlout,"%s", buf);
+ }
+ fprintf(xmlout, "</Name>\n");
+ fprintf(xmlout, " <Location>");
+ for(i = 0; i < 4; i++) {
+ uint_to_chars(track->urn[track->num_urn].location[i], buf);
+ fprintf(xmlout,"%s");
+ }
+ fprintf(xmlout, "</Location>\n");
+ fprintf(xmlout, " </DataEntryUrnBox>\n");
+ }
+ fprintf(xmlout, " </DataReference>\n");
+ fprintf(xmlout, " </DataInfo>\n");
+
+ xml_write_stbl(file, xmlout, track, tnum); /* SampleTable */
+
+ fprintf(xmlout, " </MediaInfoContainer>\n");
+ fprintf(xmlout, " </Media>\n");
+}
+
+/* ------------- */
+
+void xml_write_stbl(FILE* file, FILE* xmlout, mj2_tk_t *track, unsigned int tnum)
+{
+ char buf[5], buf33[33];
+ int i, len;
+ buf[4] = '\0';
+
+ fprintf(xmlout, " <SampleTable BoxType=\"stbl\">\n");
+ if(notes)
+ fprintf(xmlout, " <!-- What follows are specific instances of generic SampleDescription BoxType=\"stsd\" -->\n");
+ switch(track->track_type)
+ {
+ case 0:
+ // There could be multiple instances of this, but "entry_count" is just a local at read-time.
+ // And it's used wrong, too, as count of just visual type, when it's really all 3 types.
+ // This is referred to as "smj2" within mj2.c
+ fprintf(xmlout, " <VisualSampleEntry BoxType=\"mjp2\">\n");
+ if(notes) {
+ fprintf(xmlout, " <!-- If multiple instances of this box, only first is shown here. -->\n");
+ fprintf(xmlout, " <!-- Width and Height are in pixels. Unlike the Track Header, there is no fractional part. -->\n");
+ fprintf(xmlout, " <!-- In mj2_to_metadata implementation, the values are not represented separately from Track Header's values. -->\n");
+ }
+ /* No shifting required. If CURRENTSTRUCT gets changed, then may need to revisit treatment of these */
+ fprintf(xmlout, " <WidthAsInteger>%d</WidthAsInteger>\n", track->w);
+ fprintf(xmlout, " <HeightAsInteger>%d</HeightAsInteger>\n", track->h);
+// Horizresolution and vertresolution don't require shifting, already stored right in CURRENTSTRUCT
+ if(notes) {
+ fprintf(xmlout, " <!-- Resolutions are in pixels per inch, for the highest-resolution component (typically luminance). -->\n");
+ fprintf(xmlout, " <!-- Both stored as fixed-point binary 16.16 values. Decimal values are approximations. -->\n");
+ fprintf(xmlout, " <!-- Typical value for both resolutions is 0x00480000 (72.0) -->\n");
+ }
+ fprintf(xmlout, " <HorizontalRes>\n");
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->horizresolution);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->horizresolution/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
+ fprintf(xmlout, " </HorizontalRes>\n");
+ fprintf(xmlout, " <VerticalRes>\n");
+ if(raw)
+ fprintf(xmlout, " <AsHex>0x%08x</AsHex>\n", track->vertresolution);
+ if(derived)
+ fprintf(xmlout, " <AsDecimal>%12.6f</AsDecimal>\n", (double)track->vertresolution/(double)0x00010000); /* Rate to play presentation (default = 0x00010000) */
+ fprintf(xmlout, " </VerticalRes>\n");
+
+ buf33[0] = '\0';
+ for(i = 0; i < 8; i++) {
+ uint_to_chars((unsigned int)track->compressorname[i], buf);
+ strcat(buf33, buf); /* This loads up (4 * 8) + 1 chars, but trailing ones are usually junk */
+ }
+ len = (int)buf33[0]; /* First byte has string length in bytes. There may be garbage beyond it. */
+ buf33[len+1] = '\0'; /* Suppress it */
+ fprintf(xmlout, " <CompressorName>%s</CompressorName>\n", buf33+1); /* Start beyond first byte */
+ if(notes) {
+ fprintf(xmlout, " <!-- Compressor name for debugging. Standard restricts max length to 31 bytes. -->\n");
+ fprintf(xmlout, " <!-- Usually blank or \"Motion JPEG2000\" -->\n");
+ }
+ fprintf(xmlout, " <Depth>0x%02x</Depth>\n",track->depth);
+ if(notes) {
+ fprintf(xmlout, " <!-- Depth is: -->\n");
+ fprintf(xmlout, " <!-- 0x20: alpha channels present (color or grayscale) -->\n");
+ fprintf(xmlout, " <!-- 0x28: grayscale without alpha -->\n");
+ fprintf(xmlout, " <!-- 0x18: color without alpha -->\n");
+ }
+
+ xml_out_frame_jp2h(xmlout, &(track->jp2_struct)); /* JP2 Header */
+
+ /* Following subboxes are optional */
+ fprintf(xmlout, " <FieldCoding BoxType=\"fiel\">\n");
+ fprintf(xmlout, " <FieldCount>%d</FieldCount>\n", (unsigned int)track->fieldcount); /* uchar as 1 byte uint */
+ if(notes)
+ fprintf(xmlout, " <!-- Must be either 1 or 2 -->\n");
+ fprintf(xmlout, " <FieldOrder>%d</FieldOrder>\n", (unsigned int)track->fieldorder); /* uchar as 1 byte uint */
+ if(notes) {
+ fprintf(xmlout, " <!-- When FieldCount=2, FieldOrder means: -->\n");
+ fprintf(xmlout, " <!-- 0: Field coding unknown -->\n");
+ fprintf(xmlout, " <!-- 1: Field with topmost line is stored first in sample; fields are in temporal order -->\n");
+ fprintf(xmlout, " <!-- 6: Field with topmost line is stored second in sample; fields are in temporal order -->\n");
+ fprintf(xmlout, " <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->\n");
+ fprintf(xmlout, " <!-- Current implementation doesn't retain whether box was actually present. -->\n");
+ }
+ fprintf(xmlout, " </FieldCoding>\n");
+
+ fprintf(xmlout, " <MJP2_Profile BoxType=\"jp2p\" Count=\"%d\">\n",track->num_br);
+ for (i = 0; i < track->num_br; i++) /* read routine stored in reverse order, so let's undo damage */
+ {
+ uint_to_chars(track->br[i], buf);
+ fprintf(xmlout, " <CompatibleBrand>%s</CompatibleBrand>\n", buf); /*4 characters, each CLi */
+ }
+ fprintf(xmlout, " </MJP2_Profile>\n");
+
+ fprintf(xmlout, " <MJP2_Prefix BoxType=\"jp2x\" Count=\"%d\">\n",track->num_jp2x);
+ for (i = 0; i < track->num_jp2x; i++)
+ { // We'll probably need better formatting than this
+ fprintf(xmlout, " <Data>0x%02x</Data>\n", track->jp2xdata[i]); /* Each entry is single byte */
+ }
+ fprintf(xmlout, " </MJP2_Prefix>\n");
+
+ fprintf(xmlout, " <MJP2_SubSampling BoxType=\"jsub\">\n"); /* These values are all 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- Typical subsample value is 2 for 4:2:0 -->\n");
+ fprintf(xmlout, " <HorizontalSub>%d</HorizontalSub>\n", track->hsub);
+ fprintf(xmlout, " <VerticalSub>%d</VerticalSub>\n", track->vsub);
+ fprintf(xmlout, " <HorizontalOffset>%d</HorizontalOffset>\n", track->hoff);
+ fprintf(xmlout, " <VerticalOffset>%d</VerticalOffset>\n", track->voff);
+ if(notes) {
+ fprintf(xmlout, " <!-- Typical {horizontal, vertical} chroma offset values: -->\n");
+ fprintf(xmlout, " <!-- 4:2:2 format (CCIR601, H.262, MPEG2, MPEG4, recom. Exif): {0, 0} -->\n");
+ fprintf(xmlout, " <!-- 4:2:2 format (JFIF): {1, 0} -->\n");
+ fprintf(xmlout, " <!-- 4:2:0 format (H.262, MPEG2, MPEG4): {0, 1} -->\n");
+ fprintf(xmlout, " <!-- 4:2:0 format (MPEG1, H.261, JFIF, recom. Exif): {1, 1} -->\n");
+ }
+ fprintf(xmlout, " </MJP2_SubSampling>\n"); /* These values are all 1 byte */
+
+ fprintf(xmlout, " <MJP2_OriginalFormat BoxType=\"orfo\">\n"); /* Part III Appx. 2 */
+ fprintf(xmlout, " <OriginalFieldCount>%u</OriginalFieldCount>\n", (unsigned int)track->or_fieldcount); /* uchar as 1-byte uint */
+ if(notes)
+ fprintf(xmlout, " <!-- In original material before encoding. Must be either 1 or 2 -->\n");
+ fprintf(xmlout, " <OriginalFieldOrder>%u</OriginalFieldOrder>\n", (unsigned int)track->or_fieldorder); /* uchar as 1-byte uint */
+ if(notes) {
+ fprintf(xmlout, " <!-- When FieldCount=2, FieldOrder means: -->\n");
+ fprintf(xmlout, " <!-- 0: Field coding unknown -->\n");
+ fprintf(xmlout, " <!-- 11: Topmost line came from the earlier field; -->\n");
+ fprintf(xmlout, " <!-- 16: Topmost line came form the later field. -->\n");
+ fprintf(xmlout, " <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->\n");
+ fprintf(xmlout, " <!-- Current implementation doesn't retain whether box was actually present. -->\n");
+ }
+ fprintf(xmlout, " </MJP2_OriginalFormat>\n");
+ fprintf(xmlout, " </VisualSampleEntry>\n");
+ break;
+ case 1: case 2:
+ if(notes)
+ fprintf(xmlout, " <!-- mj2_to_metadata's data structure doesn't record this currently. -->\n"); break;
+ }
+ fprintf(xmlout, " <TimeToSample BoxType=\"stts\">\n");
+ fprintf(xmlout, " <SampleStatistics>\n");
+ fprintf(xmlout, " <TotalSamples>%d</TotalSamples>\n", track->num_samples);
+ if(notes)
+ fprintf(xmlout, " <!-- For video, gives the total frames in the track, by summing all entries in the Sample Table -->\n");
+ fprintf(xmlout, " </SampleStatistics>\n");
+ fprintf(xmlout, " <SampleEntries EntryCount=\"%d\">\n", track->num_tts);
+ for (i = 0; i < track->num_tts; i++) {
+ fprintf(xmlout, " <Table Entry=\"%u\" SampleCount=\"%d\" SampleDelta=\"%u\" />\n",
+ i+1, track->tts[i].sample_count, track->tts[i].sample_delta);
+ }
+ fprintf(xmlout, " </SampleEntries>\n");
+ fprintf(xmlout, " </TimeToSample>\n");
+
+ fprintf(xmlout, " <SampleToChunk BoxType=\"stsc\" Count=\"%d\">\n", track->num_samplestochunk);
+ for (i = 0; i < track->num_samplestochunk; i++) {
+ fprintf(xmlout, " <FirstChunk>%u</FirstChunk>\n",track->sampletochunk[i].first_chunk); /* 4 bytes */
+ fprintf(xmlout, " <SamplesPerChunk>%u</SamplesPerChunk>\n",track->sampletochunk[i].samples_per_chunk); /* 4 bytes */
+ fprintf(xmlout, " <SampleDescrIndex>%u</SampleDescrIndex>\n",track->sampletochunk[i].sample_descr_idx); /* 4 bytes */
+ }
+ fprintf(xmlout, " </SampleToChunk>\n");
+ // After reading this info in, track->num_chunks is calculated and a decompressed table established internally.
+
+ fprintf(xmlout, " <SampleSize BoxType=\"stsz\">\n");
+ if(track->same_sample_size) {
+ // all values in track->sample[i].sample_size are equal. Grab the first one.
+ fprintf(xmlout, " <Sample_Size>%u</Sample_Size>\n", track->sample[0].sample_size);
+ if(notes) {
+ fprintf(xmlout, " <!-- Non-zero value means all samples have that size. -->\n");
+ fprintf(xmlout, " <!-- So <Sample_Count> (aka Entry_Count in std.) has no meaning, is suppressed from this output, and no table follows. -->\n");
+ }
+ } else {
+ fprintf(xmlout, " <Sample_Size>0</Sample_Size>\n");
+ if(notes)
+ if(sampletables)
+ fprintf(xmlout," <!-- Zero value means samples have different sizes, given in table next of length Sample_Count (aka Entry_Count in std). -->\n");
+ else
+ fprintf(xmlout," <!-- Zero value means samples have different sizes, given in table (not shown) of length Sample_Count (aka Entry_Count in std). -->\n");
+ fprintf(xmlout, " <Sample_Count>%u</Sample_Count>\n", track->num_samples);
+ if(sampletables)
+ for (i = 0; i < (int)track->num_samples; i++) {
+ fprintf(xmlout, " <EntrySize Num=\"%u\">%u</EntrySize>\n", i+1, track->sample[i].sample_size);
+ }
+ }
+ fprintf(xmlout, " </SampleSize>\n");
+
+ fprintf(xmlout, " <ChunkOffset BoxType=\"stco\">\n");
+ // Structure not yet - Variant ChunkLargeOffset 'co64'
+ fprintf(xmlout, " <EntryCount>%u</EntryCount>\n", track->num_chunks);
+ if(notes) {
+ fprintf(xmlout, " <!-- For this implementation, EntryCount shown is one calculated during file read of <SampleToChunk> data. -->\n");
+ fprintf(xmlout, " <!-- Implementation will report failure during file read of <ChunkOffset> data if read entry-count disagrees. -->\n");
+ }
+ if(sampletables)
+ for (i = 0; i < (int)track->num_chunks; i++)
+ fprintf(xmlout, " <Chunk_Offset Num=\"%d\">%u</Chunk_Offset>\n", i+1, track->chunk[i].offset);
+ fprintf(xmlout, " </ChunkOffset>\n");
+
+ fprintf(xmlout, " </SampleTable>\n");
+}
+
+/* ------------- */
+
+int xml_out_frame(FILE* file, FILE* xmlout, mj2_sample_t *sample, unsigned int snum, opj_event_mgr_t *event_mgr)
+{
+ opj_dparameters_t parameters; /* decompression parameters */
+ opj_image_t *img;
+ opj_cp_t *cp;
+ int i;
+ int numcomps;
+ unsigned char* frame_codestream;
+ opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
+ opj_cio_t *cio = NULL;
+ opj_j2k_t *j2k;
+
+ /* JPEG 2000 compressed image data */
+
+ /* get a decoder handle */
+ dinfo = opj_create_decompress(CODEC_J2K);
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using the current image and user parameters */
+ parameters.cp_limit_decoding = DECODE_ALL_BUT_PACKETS;
+ opj_setup_decoder(dinfo, &parameters);
+
+ frame_codestream = (unsigned char*) malloc (sample->sample_size-8); /* Skipping JP2C marker */
+ if(frame_codestream == NULL)
+ return 1;
+
+ fseek(file,sample->offset+8,SEEK_SET);
+ fread(frame_codestream,sample->sample_size-8,1, file); /* Assuming that jp and ftyp markers size do */
+
+ /* open a byte stream */
+ cio = opj_cio_open((opj_common_ptr)dinfo, frame_codestream, sample->sample_size-8);
+
+ /* Decode J2K to image: */
+ img = opj_decode(dinfo, cio);
+ if (!img) {
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
+ opj_destroy_decompress(dinfo);
+ opj_cio_close(cio);
+ return 1;
+ }
+
+ j2k = (opj_j2k_t*)dinfo->j2k_handle;
+ j2k_default_tcp = j2k->default_tcp;
+ cp = j2k->cp;
+
+ numcomps = img->numcomps;
+ /* Alignments: " < To help maintain xml pretty-printing */
+ fprintf(xmlout, " <JP2_Frame Num=\"%d\">\n", snum+1);
+ fprintf(xmlout, " <MainHeader>\n");
+ /* There can be multiple codestreams; a particular image is entirely within a single codestream */
+ /* TO DO: A frame can be represented by two I-guess-contigious codestreams if its interleaved. */
+ fprintf(xmlout, " <StartOfCodestream Marker=\"SOC\" />\n");
+ /* "cp" stands for "coding parameter"; "tcp" is tile coding parameters, "tccp" is tile-component coding parameters */
+ xml_out_frame_siz(xmlout, img, cp); /* reqd in main */
+ xml_out_frame_cod(xmlout, j2k_default_tcp); /* reqd in main */
+ xml_out_frame_coc(xmlout, j2k_default_tcp, numcomps); /* opt in main, at most 1 per component */
+ xml_out_frame_qcd(xmlout, j2k_default_tcp); /* reqd in main */
+ xml_out_frame_qcc(xmlout, j2k_default_tcp, numcomps); /* opt in main, at most 1 per component */
+ xml_out_frame_rgn(xmlout, j2k_default_tcp, numcomps); /* opt, at most 1 per component */
+ xml_out_frame_poc(xmlout, j2k_default_tcp); /* opt (but reqd in main or tile for any progression order changes) */
+ /* Next four get j2k_default_tcp passed globally: */
+#ifdef SUPPRESS_FOR_NOW
+ xml_out_frame_ppm(xmlout, cp); /* opt (but either PPM or PPT [distributed in tile headers] or codestream packet header reqd) */
+#endif
+ xml_out_frame_tlm(xmlout); /* NO-OP. TLM NOT SAVED IN DATA STRUCTURE */ /* opt */
+ xml_out_frame_plm(xmlout); /* NO-OP. PLM NOT SAVED IN DATA STRUCTURE */ /* opt in main; can be used in conjunction with PLT */
+ xml_out_frame_crg(xmlout); /* NO-OP. CRG NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
+ xml_out_frame_com(xmlout, j2k_default_tcp); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main; */
+
+ fprintf(xmlout, " </MainHeader>\n");
+
+ /* TO DO: all the tile headers (sigh) */
+ fprintf(xmlout, " <TilePartHeaders Count=\"%d\">\n", cp->tileno_size); /* size of the vector tileno */
+ for(i = 0; i < cp->tileno_size; i++) { /* I think cp->tileno_size will be same number as (cp->tw * cp->th) or as global j2k_curtileno */
+ // Standard seems to use zero-based # for tile-part.
+ fprintf(xmlout, " <TilePartHeader Num=\"%d\" ID=\"%d\">\n", i, cp->tileno[i]); /* ID number of the tiles present in the codestream */
+ fprintf(xmlout, " <StartOfTilePart Marker=\"SOT\" />\n");
+ /* All markers in tile-part headers (between SOT and SOD) are optional, unless structure requires. */
+ if(i == 0) {
+ xml_out_frame_cod(xmlout, &(cp->tcps[i])); /* No more than 1 per tile */
+ xml_out_frame_coc(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
+ xml_out_frame_qcd(xmlout, &(cp->tcps[i])); /* No more than 1 per tile */
+ xml_out_frame_qcc(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
+ xml_out_frame_rgn(xmlout, &(cp->tcps[i]), numcomps); /* No more than 1 per component */
+ }
+ xml_out_frame_poc(xmlout, &(cp->tcps[i])); /* Reqd only if any progression order changes different from main POC */
+#ifdef SUPPRESS_FOR_NOW
+ xml_out_frame_ppt(xmlout, &(cp->tcps[i])); /* Either PPT [distributed in tile headers] or PPM or codestream packet header reqd. */
+#endif
+ xml_out_frame_plt(xmlout, &(cp->tcps[i])); /* NO-OP. PLT NOT SAVED IN DATA STRUCTURE */ /* Can be used in conjunction with main's PLM */
+ xml_out_frame_com(xmlout, &(cp->tcps[i])); /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */
+ /* opj_tcp_t * cp->tcps; "tile coding parameters" */
+ /* Maybe not: fprintf(xmlout, " <>%d</>, cp->matrice[i]; */ /* Fixed layer */
+ fprintf(xmlout, " <StartOfData Marker=\"SOD\" />\n");
+ if(notes)
+ fprintf(xmlout, " <!-- Tile-part bitstream, not shown, follows tile-part header and SOD marker. -->\n");
+ fprintf(xmlout, " </TilePartHeader>\n");
+ }
+ fprintf(xmlout, " </TilePartHeaders>\n"); /* size of the vector tileno */
+
+#ifdef NOTYET
+ IMAGINE the cp object has data to support the following... but we could use an new different data structure instead
+ /* I'm unclear if the span of the original fread(frame_codestream...) included the following items if they're trailing. */
+ /* ALSO TO DO, BUT DATA STRUCTURE DOESN'T HANDLE YET: boxes (anywhere in file except before the Filetype box): */
+ xml_out_frame_jp2i(xmlout, &cp); /* IntellectualProperty 'jp2i' (no restrictions on location) */
+ xml_out_frame_xml(xmlout, &cp); /* XML 'xml\040' (0x786d6c20). Can appear multiply */
+ xml_out_frame_uuid(xmlout, &cp); /* UUID 'uuid' (top level only) */
+ xml_out_frame_uinf(xmlout, &cp); /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
+#endif
+
+ fprintf(xmlout, " </JP2_Frame>\n");
+
+ /* Extra commentary: */
+ if(notes) {
+ fprintf(xmlout, " <!-- Given the number and size of components, mj2_to_frame would try to convert this -->\n");
+ if (((img->numcomps == 3) && (img->comps[0].dx == img->comps[1].dx / 2)
+ && (img->comps[0].dx == img->comps[2].dx / 2 ) && (img->comps[0].dx == 1))
+ || (img->numcomps == 1)) {
+ fprintf(xmlout, " <!-- file to a YUV movie in the normal manner. -->\n");
+ }
+ else if ((img->numcomps == 3) &&
+ (img->comps[0].dx == 1) && (img->comps[1].dx == 1)&&
+ (img->comps[2].dx == 1)) {// If YUV 4:4:4 input --> to bmp
+ fprintf(xmlout, " <!-- YUV 4:4:4 file to a series of .bmp files. -->\n");
+ }
+ else {
+ fprintf(xmlout, " <!-- file whose image component dimension are unknown, to a series of .j2k files. -->\n");
+ }
+ }
+
+ opj_destroy_decompress(dinfo);
+ opj_cio_close(cio);
+ free(frame_codestream);
+
+ return 0;
+}
+
+/* ------------- */
+
+void int16_to_3packedchars(short int value, char* buf)
+{
+ /* This is to retrieve the 3-letter ASCII language code */
+ /* Each char is packed into 5 bits, as difference from 0x60 */
+ int i;
+ for (i = 2; i >= 0; i--)
+ {
+ buf[i] = (value & 0x001f) + 0x60;
+ value = (value >>5);
+ }
+ buf[3] = '\0';
+}
+
+/* ------------- */
+
+void xml_out_frame_siz(FILE* xmlout, opj_image_t *img, opj_cp_t *cp)
+{
+ opj_image_comp_t *comp;
+ int i;
+
+ fprintf(xmlout, " <ImageAndFileSize Marker=\"SIZ\">\n");
+ // This is similar to j2k.c's j2k_dump_image.
+ // Not of interest: Lsiz, Rsiz
+ fprintf(xmlout, " <Xsiz>%d</Xsiz>\n", img->x1);
+ fprintf(xmlout, " <Ysiz>%d</Ysiz>\n", img->y1);
+ if(notes)
+ fprintf(xmlout, " <!-- Xsiz, Ysiz is the size of the reference grid. -->\n");
+ fprintf(xmlout, " <XOsiz>%d</XOsiz>\n", img->x0);
+ fprintf(xmlout, " <YOsiz>%d</YOsiz>\n", img->y0);
+ if(notes)
+ fprintf(xmlout, " <!-- XOsiz, YOsiz are offsets from grid origin to image origin. -->\n");
+ fprintf(xmlout, " <XTsiz>%d</XTsiz>\n", cp->tdx);
+ fprintf(xmlout, " <YTsiz>%d</YTsiz>\n", cp->tdy);
+ if(notes)
+ fprintf(xmlout, " <!-- XTsiz, YTsiz is the size of one tile with respect to the grid. -->\n");
+ fprintf(xmlout, " <XTOsiz>%d</XTOsiz>\n", cp->tx0);
+ fprintf(xmlout, " <YTOsiz>%d</YTOsiz>\n", cp->ty0);
+ if(notes)
+ fprintf(xmlout, " <!-- XTOsiz, YTOsiz are offsets from grid origin to first tile origin. -->\n");
+ fprintf(xmlout, " <Csiz>%d</Csiz>\n", img->numcomps);
+ if(notes) {
+ fprintf(xmlout, " <!-- Csiz is the number of components in the image. -->\n");
+ fprintf(xmlout, " <!-- For image components next: -->\n");
+ fprintf(xmlout, " <!-- XRsiz, YRsiz denote pixel-sample-spacing on the grid, per Part I Annex B. -->\n");
+ //fprintf(xmlout," <!-- XO, YO is offset of the component compared to the whole image. -->\n");
+ fprintf(xmlout, " <!-- Bits per pixel (bpp) is the pixel depth. -->\n");
+ fprintf(xmlout, " <!-- WidthOfData and HeightOfData are calculated values, e.g.: w = roundup((Xsiz - XOsiz)/ XRsiz) -->\n");
+ }
+
+ for (i = 0; i < img->numcomps; i++) {/* image-components */
+ comp = &(img->comps[i]);
+ fprintf(xmlout, " <Component Num=\"%d\">\n", i+1);
+ fprintf(xmlout, " <Ssiz>\n");
+ if(raw)
+ fprintf(xmlout," <AsHex>0x%02x</AsHex>\n", (comp->sgnd << 7) & (comp->prec - 1));
+ if(derived) {
+ fprintf(xmlout," <Signed>%d</Signed>\n", comp->sgnd);
+ fprintf(xmlout," <PrecisionInBits>%d</PrecisionInBits>\n", comp->prec);
+ }
+ fprintf(xmlout, " </Ssiz>\n");
+ fprintf(xmlout, " <XRsiz>%d</XRsiz>\n", comp->dx);
+ fprintf(xmlout, " <YRsiz>%d</YRsiz>\n", comp->dy);
+ fprintf(xmlout, " <WidthOfData>%d</WidthOfData>\n", comp->w);
+ fprintf(xmlout, " <HeightOfData>%d</HeightOfData>\n", comp->h);
+ /* Rest of these aren't calculated when SIZ is read:
+ fprintf(xmlout, " <XO>%d</XO>\n", comp->x0);
+ fprintf(xmlout, " <YO>%d</YO>\n", comp->y0);
+ if(notes)
+ fprintf(xmlout," <!-- XO, YO is offset of the component compared to the whole image. -->\n");
+ fprintf(xmlout, " <BitsPerPixel>%d</BitsPerPixel>\n", comp->bpp);
+ fprintf(xmlout, " <NumberOfDecodedResolution>%d</NumberOfDecodedResolution>\n", comp->resno_decoded); */
+ // SUPPRESS: n/a to mj2_to_metadata. fprintf(xmlout," <Factor>%d</Factor\n", comp->factor);
+ /* factor = number of division by 2 of the out image compare to the original size of image */
+ // TO DO comp->data: int *data; /* image-component data */
+
+ fprintf(xmlout, " </Component>\n");
+ }
+ fprintf(xmlout, " </ImageAndFileSize>\n");
+}
+
+/* ------------- */
+
+void xml_out_frame_cod(FILE* xmlout, opj_tcp_t *tcp)
+{
+/* Could be called with tcp = &j2k_default_tcp;
+/* Or, for tile-part header, with &j2k_cp->tcps[j2k_curtileno]
+/* Alignment for main:" < < < < To help maintain xml pretty-printing */
+/* Alignment for tile:" < < < To help maintain xml pretty-printing */
+ opj_tccp_t *tccp;
+ int i;
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+ tccp = &(tcp->tccps[0]);
+
+ fprintf(xmlout, "%s<CodingStyleDefault Marker=\"COD\">\n",s); /* Required in main header */
+ /* Not retained or of interest: Lcod */
+ fprintf(xmlout, "%s <Scod>0x%02x</Scod>\n", s, tcp->csty); /* 1 byte */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- For Scod, specific bits mean (where bit 0 is lowest or rightmost): -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 0: Defines entropy coder precincts -->\n",s);
+ fprintf(xmlout, "%s <!-- 0 = (PPx=15, PPy=15); 1 = precincts defined below. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 1: 1 = SOP marker may be used; 0 = not. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 2: 1 = EPH marker may be used; 0 = not. -->\n",s);
+ }
+ fprintf(xmlout, "%s <SGcod>\n",s);
+ fprintf(xmlout, "%s <ProgressionOrder>%d</ProgressionOrder>\n", s, tcp->prg); /* 1 byte, SGcod (A) */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Defined Progression Order Values are: -->\n",s);
+ fprintf(xmlout, "%s <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->\n",s);
+ fprintf(xmlout, "%s <!-- where L = \"layer\", R = \"resolution level\", C = \"component\", P = \"position\". -->\n",s);
+ }
+ fprintf(xmlout, "%s <NumberOfLayers>%d</NumberOfLayers>\n", s, tcp->numlayers); /* 2 bytes, SGcod (B) */
+ fprintf(xmlout, "%s <MultipleComponentTransformation>%d</MultipleComponentTransformation>\n", s, tcp->mct); /* 1 byte, SGcod (C). More or less boolean */
+ if(notes)
+ fprintf(xmlout, "%s <!-- For MCT, 0 = none, 1 = transform first 3 components for efficiency, per Part I Annex G -->\n",s);
+ fprintf(xmlout, "%s </SGcod>\n",s);
+ /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
+ fprintf(xmlout, "%s <SPcod>\n",s);
+ /* Internal data structure tccp defines separate defaults for each component, but they all get the same values */
+ /* So we only have to report the first component's values here. */
+ /* Compare j2k_read_cox(...) */
+ fprintf(xmlout, "%s <NumberOfDecompositionLevels>%d</NumberOfDecompositionLevels>\n", s, tccp->numresolutions - 1); /* 1 byte, SPcox (D) */
+ fprintf(xmlout, "%s <CodeblockWidth>%d</CodeblockWidth>\n", s, tccp->cblkw - 2); /* 1 byte, SPcox (E) */
+ fprintf(xmlout, "%s <CodeblockHeight>%d</CodeblockHeight>\n", s, tccp->cblkh - 2); /* 1 byte, SPcox (F) */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->\n",s);
+ fprintf(xmlout, "%s <!-- Codeblock dimension is 2^(value + 2) -->\n", s);
+ }
+ fprintf(xmlout, "%s <CodeblockStyle>0x%02x</CodeblockStyle>\n", s, tccp->cblksty); /* 1 byte, SPcox (G) */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 0: Selective arithmetic coding bypass. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 1: Reset context probabilities on coding pass boundaries. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 2: Termination on each coding pass. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 3: Vertically causal context. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 4: Predictable termination. -->\n",s);
+ fprintf(xmlout, "%s <!-- bit 5: Segmentation symbols are used. -->\n",s);
+ }
+ fprintf(xmlout, "%s <Transformation>%d</Transformation>\n", s, tccp->qmfbid); /* 1 byte, SPcox (H) */
+ if(notes)
+ fprintf(xmlout, "%s <!-- For Transformation, 0=\"9-7 irreversible filter\", 1=\"5-3 reversible filter\" -->\n",s);
+ if (tccp->csty & J2K_CP_CSTY_PRT) {
+ fprintf(xmlout, "%s <PrecinctSize>\n",s); /* 1 byte, SPcox (I_i) */
+ if(notes)
+ fprintf(xmlout, "%s <!-- These are size exponents PPx and PPy. May be zero only for first level (aka N(L)LL subband)-->\n",s);
+ for (i = 0; i < tccp->numresolutions; i++) {
+ fprintf(xmlout, "%s <PrecinctHeightAndWidth ResolutionLevel=\"%d\">\n", s, i);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->prch[i] << 4) | tccp->prcw[i]); /* packed into 1 byte, SPcox (G) */
+ if(derived) {
+ fprintf(xmlout,"%s <WidthAsDecimal>%d</WidthAsDecimal>\n", s, tccp->prcw[i]);
+ fprintf(xmlout,"%s <HeightAsDecimal>%d</HeightAsDecimal>\n", s, tccp->prch[i]);
+ }
+ fprintf(xmlout, "%s </PrecinctHeightAndWidth>\n", s, i);
+ }
+ fprintf(xmlout, "%s </PrecinctSize>\n",s); /* 1 byte, SPcox (I_i) */
+ }
+ fprintf(xmlout, "%s </SPcod>\n",s);
+ fprintf(xmlout, "%s</CodingStyleDefault>\n",s);
+}
+
+/* ------------- */
+
+void xml_out_frame_coc(FILE* xmlout, opj_tcp_t *tcp, int numcomps) /* Optional in main & tile-part headers */
+{
+/* Uses global j2k_default_tcp */
+ opj_tccp_t *tccp, *firstcomp_tccp;
+ int i, compno;
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+
+ firstcomp_tccp = &(tcp->tccps[0]);
+ /* Internal data structure tccp defines separate defaults for each component, set from main */
+ /* default, then selectively overwritten. */
+ /* Compare j2k_read_cox(...) */
+ /* We don't really know which was the default, and which were not */
+ /* Let's pretend that [0] is the default and all others are not */
+ if(notes) {
+ fprintf(xmlout, "%s<!-- mj2_to_metadata implementation always reports component[0] as using default COD, -->\n", s);
+ if(tcp == j2k_default_tcp)
+ fprintf(xmlout, "%s<!-- and any other component, with main-header style values different from [0], as COC. -->\n", s);
+ else
+ fprintf(xmlout, "%s<!-- and any other component, with tile-part-header style values different from [0], as COC. -->\n", s);
+ }
+ for (compno = 1; compno < numcomps; compno++) /* spec says components are zero-based */
+ {
+ tccp = &tcp->tccps[compno];
+ if(same_component_style(firstcomp_tccp, tccp))
+ continue;
+
+/* Alignments: " < < < < < To help maintain xml pretty-printing */
+ fprintf(xmlout, "%s<CodingStyleComponent Marker=\"COC\">\n", s); /* Optional in main header, at most 1 per component */
+ if(notes)
+ fprintf(xmlout, "%s <!-- See Ccoc below for zero-based component number. -->\n", s);
+ /* Overrides the main COD for the specific component */
+ /* Not retained or of interest: Lcod */
+ fprintf(xmlout, "%s <Scoc>0x%02x</Scoc>\n", s, tccp->csty); /* 1 byte */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Scoc defines entropy coder precincts: -->\n", s);
+ fprintf(xmlout, "%s <!-- 0 = maximum, namely (PPx=15, PPy=15); 1 = precincts defined below. -->\n", s);
+ }
+ fprintf(xmlout, "%s <Ccoc>%d</Ccoc>\n", s, compno); /* 1 or 2 bytes */
+ /* Unfortunately compo isn't retained in j2k_read_coc: compno = cio_read(j2k_img->numcomps <= 256 ? 1 : 2); /* Ccoc */
+ /*if(j2k_img_numcomps <=256)
+ component is 1 byte
+ else
+ compno is 2 byte */
+
+ /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
+ fprintf(xmlout, "%s <SPcoc>\n", s);
+ fprintf(xmlout, "%s <NumberOfDecompositionLevels>%d</NumberOfDecompositionLevels>\n", s, tccp->numresolutions - 1); /* 1 byte, SPcox (D) */
+ fprintf(xmlout, "%s <CodeblockWidth>%d</CodeblockWidth>\n", s, tccp->cblkw - 2); /* 1 byte, SPcox (E) */
+ fprintf(xmlout, "%s <CodeblockHeight>%d</CodeblockHeight>\n", s, tccp->cblkh - 2); /* 1 byte, SPcox (F) */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->\n", s);
+ fprintf(xmlout, "%s <!-- Codeblock dimension is 2^(value + 2) -->\n", s);
+ }
+ fprintf(xmlout, "%s <CodeblockStyle>0x%02x</CodeblockStyle>\n", s, tccp->cblksty); /* 1 byte, SPcox (G) */
+ if(notes) {
+ fprintf(xmlout, "%s <!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 0: Selective arithmetic coding bypass. -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 1: Reset context probabilities on coding pass boundaries. -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 2: Termination on each coding pass. -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 3: Vertically causal context. -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 4: Predictable termination. -->\n", s);
+ fprintf(xmlout, "%s <!-- bit 5: Segmentation symbols are used. -->\n", s);
+ }
+ fprintf(xmlout, "%s <Transformation>%d</Transformation>\n", s, tccp->qmfbid); /* 1 byte, SPcox (H) */
+ if(notes)
+ fprintf(xmlout, "%s <!-- For Transformation, 0=\"9-7 irreversible filter\", 1=\"5-3 reversible filter\" -->\n", s);
+ if (tccp->csty & J2K_CP_CSTY_PRT) {
+ fprintf(xmlout, "%s <PrecinctSize>\n", s); /* 1 byte, SPcox (I_i) */
+ if(notes)
+ fprintf(xmlout, "%s <!-- These are size exponents PPx and PPy. May be zero only for first level (aka N(L)LL subband)-->\n", s);
+ for (i = 0; i < tccp->numresolutions-1; i++) { /* subtract 1 to get # of decomposition levels */
+ fprintf(xmlout, "%s <PrecinctHeightAndWidth ResolutionLevel=\"%d\">\n", s, i);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->prch[i] << 4) | tccp->prcw[i]); /* packed into 1 byte, SPcox (G) */
+ if(derived) {
+ fprintf(xmlout,"%s <WidthAsDecimal>%d</WidthAsDecimal>\n", s, tccp->prcw[i]);
+ fprintf(xmlout,"%s <HeightAsDecimal>%d</HeightAsDecimal>\n", s, tccp->prch[i]);
+ }
+ fprintf(xmlout, "%s </PrecinctHeightAndWidth>\n", s, i);
+ }
+ fprintf(xmlout, "%s </PrecinctSize>\n", s); /* 1 byte, SPcox (I_i) */
+ }
+ fprintf(xmlout, "%s </SPcoc>\n", s);
+ fprintf(xmlout, "%s</CodingStyleComponent>\n", s);
+ }
+}
+
+/* ------------- */
+
+BOOL same_component_style(opj_tccp_t *tccp1, opj_tccp_t *tccp2)
+{
+ int i;
+
+ if(tccp1->numresolutions != tccp2->numresolutions)
+ return FALSE;
+ if(tccp1->cblkw != tccp2->cblkw)
+ return FALSE;
+ if(tccp1->cblkh != tccp2->cblkh)
+ return FALSE;
+ if(tccp1->cblksty != tccp2->cblksty)
+ return FALSE;
+ if(tccp1->csty != tccp2->csty)
+ return FALSE;
+
+ if (tccp1->csty & J2K_CP_CSTY_PRT) {
+ for (i = 0; i < tccp1->numresolutions; i++) {
+ if(tccp1->prcw[i] != tccp2->prcw[i] || tccp1->prch[i] != tccp2->prch[i])
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/* ------------- */
+
+void xml_out_frame_qcd(FILE* xmlout, opj_tcp_t *tcp)
+{
+ /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
+ opj_tccp_t *tccp;
+ int bandno, numbands;
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+
+ /* Compare j2k_read_qcx */
+ fprintf(xmlout, "%s<QuantizationDefault Marker=\"QCD\">\n", s); /* Required in main header, single occurrence */
+ tccp = &(tcp->tccps[0]);
+ /* Not retained or of interest: Lqcd */
+ fprintf(xmlout, "%s <Sqcd>\n", s); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, "%s <!-- Default quantization style for all components. -->\n", s);
+ if(raw)
+ fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->numgbits) << 5 | tccp->qntsty);
+ if(derived)
+ fprintf(xmlout, "%s <QuantizationStyle>%d</QuantizationStyle>\n", s, tccp->qntsty);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Quantization style (in Sqcd's low 5 bits) may be: -->\n", s);
+ fprintf(xmlout, "%s <!-- 0 = No quantization. SPqcd size = 8 bits-->\n", s);
+ fprintf(xmlout, "%s <!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcd size = 16. -->\n", s);
+ fprintf(xmlout, "%s <!-- 2 = Scalar expounded (values signaled for each subband). SPqcd size = 16. -->\n", s);
+ }
+ if(derived)
+ fprintf(xmlout, "%s <NumberOfGuardBits>%d</NumberOfGuardBits>\n", s, tccp->numgbits);
+ if(notes)
+ fprintf(xmlout, "%s <!-- 0-7 guard bits allowed (stored in Sqcd's high 3 bits) -->\n", s);
+ fprintf(xmlout, "%s </Sqcd>\n", s);
+
+ /* Problem: numbands in some cases is calculated from len, which is not retained or available here at this time */
+ /* So we'll just dump all internal values */
+ /* We could calculate it, but I'm having trouble believing the length equations in the standard */
+
+ fprintf(xmlout, "%s <SPqcd>\n", s);
+ switch(tccp->qntsty) {
+ case J2K_CCP_QNTSTY_NOQNT: /* no quantization */
+ /* This is what standard says, but I don't believe it: len = 4 + (3*decomp); */
+ numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
+ /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
+ /* Instead look for first zero exponent, quit there. Adequate? */
+ fprintf(xmlout, "%s <ReversibleStepSizeValue>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until an exponent with zero value is reached. -->\n", s);
+ fprintf(xmlout, "%s <!-- Exponent epsilon(b) of reversible dynamic range. -->\n", s);
+ fprintf(xmlout, "%s <!-- Hex value is as stored, in high-order 5 bits. -->\n", s);
+ }
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0)
+ break; /* Remove when we have real numbands */
+ fprintf(xmlout, "%s <DynamicRangeExponent Subband=\"%d\">\n", s, bandno);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, tccp->stepsizes[bandno].expn << 3);
+ if(derived)
+ fprintf(xmlout,"%s <AsDecimal>%d</AsDecimal>\n", s, tccp->stepsizes[bandno].expn);
+ fprintf(xmlout, "%s </DynamicRangeExponent>\n", s);
+ }
+ fprintf(xmlout, "%s </ReversibleStepSizeValue>\n", s);
+ break;
+ case J2K_CCP_QNTSTY_SIQNT: /* scalar quantization derived */
+ /* This is what standard says. Should I believe it:: len = 5;
+ /* numbands = 1; */
+ fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
+ if(notes)
+ fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
+ fprintf(xmlout, "%s <QuantizationValues Subband=\"0\">\n", s);
+ if(notes)
+ fprintf(xmlout, "%s <!-- For N(L)LL subband: >\n", s);
+ if(raw)
+ fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[0].expn << 11) | tccp->stepsizes[0].mant);
+ if(derived) {
+ fprintf(xmlout, "%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[0].expn);
+ fprintf(xmlout, "%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[0].mant);
+ }
+ fprintf(xmlout, "%s </QuantizationValues>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Exponents for subbands beyond 0 are not from header, but calculated per Eq. E.5 -->\n", s);
+ fprintf(xmlout, "%s <!-- The mantissa for all subbands is the same, given by the value above. -->\n", s);
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until a subband with exponent of zero value is reached. -->\n", s);
+ }
+
+ for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0)
+ break;
+
+ fprintf(xmlout, "%s <CalculatedExponent Subband=\"%d\">%d</CalculatedExponent>\n", s, bandno, tccp->stepsizes[bandno].expn);
+ }
+
+ fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
+ break;
+
+ default: /* J2K_CCP_QNTSTY_SEQNT */ /* scalar quantization expounded */
+ /* This is what standard says, but should I believe it: len = 5 + 6*decomp; */
+ numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
+ /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
+ fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until a subband with mantissa and exponent of zero values is reached. -->\n", s);
+ }
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0 && tccp->stepsizes[bandno].mant == 0)
+ break; /* Remove when we have real numbands */
+
+ fprintf(xmlout, "%s <QuantizationValues Subband=\"%d\">\n", s, bandno);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[bandno].expn << 11) | tccp->stepsizes[bandno].mant);
+ if(derived) {
+ fprintf(xmlout,"%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[bandno].expn);
+ fprintf(xmlout,"%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[bandno].mant);
+ }
+ fprintf(xmlout, "%s </QuantizationValues>\n", s);
+ }
+ fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
+ break;
+ } /* switch */
+ fprintf(xmlout, "%s </SPqcd>\n", s);
+ fprintf(xmlout, "%s</QuantizationDefault>\n", s);
+
+/* Alignments: " < < < < < To help maintain xml pretty-printing */
+}
+
+/* ------------- */
+
+void xml_out_frame_qcc(FILE* xmlout, opj_tcp_t *tcp, int numcomps)
+{
+/* Uses global j2k_default_tcp */
+ /* This code will compile only if declaration of j2k_default_tcp is changed from static (to implicit extern) in j2k.c */
+ opj_tccp_t *tccp, *firstcomp_tccp;
+ int bandno, numbands;
+ int compno;
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+
+ firstcomp_tccp = &(tcp->tccps[0]);
+ /* Internal data structure tccp defines separate defaults for each component, set from main */
+ /* default, then selectively overwritten. */
+ /* Compare j2k_read_qcx(...) */
+ /* We don't really know which was the default, and which were not */
+ /* Let's pretend that [0] is the default and all others are not */
+ if(notes) {
+ fprintf(xmlout, "%s<!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->\n", s);
+ if(tcp == j2k_default_tcp)
+ fprintf(xmlout, "%s<!-- and any other component, with main-header quantization values different from [0], as QCC. -->\n", s);
+ else
+ fprintf(xmlout, "%s<!-- and any other component, with tile-part-header quantization values different from [0], as QCC. -->\n", s);
+ }
+ for (compno = 1; compno < numcomps; compno++) /* spec says components are zero-based */
+ {
+ tccp = &(tcp->tccps[compno]);
+ if(same_component_quantization(firstcomp_tccp, tccp))
+ continue;
+
+ /* Compare j2k_read_qcx */
+ fprintf(xmlout, "%s<QuantizationComponent Marker=\"QCC\" Component=\"%d\">\n", s, compno); /* Required in main header, single occurrence */
+ tccp = &j2k_default_tcp->tccps[0];
+ /* Not retained or perhaps of interest: Lqcd It maybe can be calculated. */
+ fprintf(xmlout, "%s <Sqcc>\n", s); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, "%s <!-- Quantization style for this component. -->\n", s);
+ if(raw)
+ fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->numgbits) << 5 | tccp->qntsty);
+ if(derived)
+ fprintf(xmlout, "%s <QuantizationStyle>%d</QuantizationStyle>\n", s, tccp->qntsty);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Quantization style (in Sqcc's low 5 bits) may be: -->\n", s);
+ fprintf(xmlout, "%s <!-- 0 = No quantization. SPqcc size = 8 bits-->\n", s);
+ fprintf(xmlout, "%s <!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcc size = 16. -->\n", s);
+ fprintf(xmlout, "%s <!-- 2 = Scalar expounded (values signaled for each subband). SPqcc size = 16. -->\n", s);
+ }
+ if(derived)
+ fprintf(xmlout, "%s <NumberOfGuardBits>%d</NumberOfGuardBits>\n", s, tccp->numgbits);
+ if(notes)
+ fprintf(xmlout, "%s <!-- 0-7 guard bits allowed (stored in Sqcc's high 3 bits) -->\n", s);
+ fprintf(xmlout, "%s </Sqcc>\n", s);
+
+ /* Problem: numbands in some cases is calculated from len, which is not retained or available here at this time */
+ /* So we'll just dump all internal values */
+ fprintf(xmlout, "%s <SPqcc>\n", s);
+ switch(tccp->qntsty) {
+ case J2K_CCP_QNTSTY_NOQNT:
+ numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
+ /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
+
+ /* Instead look for first zero exponent, quit there. Adequate? */
+ fprintf(xmlout, "%s <ReversibleStepSizeValue>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until an exponent with zero value is reached. -->\n", s);
+ fprintf(xmlout, "%s <!-- Exponent epsilon(b) of reversible dynamic range. -->\n", s);
+ fprintf(xmlout, "%s <!-- Hex value is as stored, in high-order 5 bits. -->\n", s);
+ }
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0)
+ break; /* Remove this once we have real numbands */
+ fprintf(xmlout, "%s <Exponent Subband=\"%d\">\n", s, bandno);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, tccp->stepsizes[bandno].expn << 3);
+ if(derived)
+ fprintf(xmlout,"%s <AsDecimal>%d</AsDecimal>\n", s, tccp->stepsizes[bandno].expn);
+ fprintf(xmlout, "%s </Exponent>\n", s);
+ }
+ fprintf(xmlout, "%s </ReversibleStepSizeValue>\n", s);
+ break;
+ case J2K_CCP_QNTSTY_SIQNT:
+ /* numbands = 1; */
+ fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
+ if(notes)
+ fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
+ fprintf(xmlout, "%s <QuantizationValuesForSubband0>\n", s);
+ if(notes)
+ fprintf(xmlout, "%s <!-- For N(L)LL subband: >\n", s);
+ if(raw)
+ fprintf(xmlout, "%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[0].expn << 11) | tccp->stepsizes[0].mant);
+ if(derived) {
+ fprintf(xmlout, "%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[0].expn);
+ fprintf(xmlout, "%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[0].mant);
+ }
+ fprintf(xmlout, "%s </QuantizationValuesForSubband0>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- Exponents for subbands beyond 0 are not from header, but calculated per Eq. E.5 -->\n", s);
+ fprintf(xmlout, "%s <!-- The mantissa for all subbands is the same, given by the value above. -->\n", s);
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until a subband with exponent of zero value is reached. -->\n", s);
+ }
+
+ for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0)
+ break;
+
+ fprintf(xmlout, "%s <CalculatedExponent Subband=\"%d\">%d</CalculatedExponent>\n", s, bandno, tccp->stepsizes[bandno].expn);
+ }
+ fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
+ break;
+
+ default: /* J2K_CCP_QNTSTY_SEQNT */
+ numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
+ /* Better: IMAGINE numbands = tccp->stepsize_numbands; */
+ fprintf(xmlout, "%s <QuantizationStepSizeValues>\n", s);
+ if(notes) {
+ fprintf(xmlout, "%s <!-- For irreversible transformation only. See Part I Annex E Equation E.3 -->\n", s);
+ fprintf(xmlout, "%s <!-- Current mj2_to_metadata implementation dumps entire internal table, -->\n", s);
+ fprintf(xmlout, "%s <!-- until a subband with mantissa and exponent of zero values is reached. -->\n", s);
+ }
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp->stepsizes[bandno].expn == 0 && tccp->stepsizes[bandno].mant == 0)
+ break; /* Remove this once we have real numbands count */
+ fprintf(xmlout, "%s <QuantizationValues Subband=\"%d\">\n", s, bandno);
+ if(raw)
+ fprintf(xmlout,"%s <AsHex>0x%02x</AsHex>\n", s, (tccp->stepsizes[bandno].expn << 11) | tccp->stepsizes[bandno].mant);
+ if(derived) {
+ fprintf(xmlout,"%s <Exponent>%d</Exponent>\n", s, tccp->stepsizes[bandno].expn);
+ fprintf(xmlout,"%s <Mantissa>%d</Mantissa>\n", s, tccp->stepsizes[bandno].mant);
+ }
+ fprintf(xmlout, "%s </QuantizationValues>\n", s);
+ }
+ fprintf(xmlout, "%s </QuantizationStepSizeValues>\n", s);
+ break;
+ } /* switch */
+ fprintf(xmlout, "%s </SPqcc>\n", s);
+ fprintf(xmlout, "%s</QuantizationComponent>\n", s);
+ }
+/* Alignments: " < < < < < To help maintain xml pretty-printing */
+}
+
+/* ------------- */
+
+BOOL same_component_quantization(opj_tccp_t *tccp1, opj_tccp_t *tccp2)
+{
+ int bandno, numbands;
+
+ if(tccp1->qntsty != tccp2->qntsty)
+ return FALSE;
+ if(tccp1->numgbits != tccp2->numgbits)
+ return FALSE;
+
+ switch(tccp1->qntsty) {
+ case J2K_CCP_QNTSTY_NOQNT:
+ numbands = J2K_MAXBANDS; /* should be: numbands = len - 1; */
+ /* Instead look for first zero exponent, quit there. Adequate? */
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp1->stepsizes[bandno].expn == 0)
+ break;
+ if(tccp1->stepsizes[bandno].expn != tccp2->stepsizes[bandno].expn)
+ return FALSE;
+ }
+ break;
+ case J2K_CCP_QNTSTY_SIQNT:
+ /* numbands = 1; */
+ if(tccp1->stepsizes[0].expn != tccp2->stepsizes[0].expn || tccp1->stepsizes[0].mant != tccp2->stepsizes[0].mant)
+ return FALSE;
+ /* Don't need to check remainder, since they are calculated from [0] */
+ break;
+
+ default: /* J2K_CCP_QNTSTY_SEQNT */
+ numbands = J2K_MAXBANDS; /* should be: (len - 1) / 2;*/
+ /* This comparison may cause us problems with trailing junk values. */
+ for (bandno = 0; bandno < numbands; bandno++) {
+ if(tccp1->stepsizes[bandno].expn != tccp2->stepsizes[bandno].expn || tccp1->stepsizes[bandno].mant != tccp2->stepsizes[bandno].mant);
+ return FALSE;
+ }
+ break;
+ } /* switch */
+ return TRUE;
+}
+
+/* ------------- */
+
+void xml_out_frame_rgn(FILE* xmlout, opj_tcp_t *tcp, int numcomps)
+{
+ int compno, SPrgn;
+ /* MJ2 files can have regions of interest if hybridized with JPX Part II */
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+
+ for(compno = 0; compno < numcomps; compno++) {
+ SPrgn = tcp->tccps[compno].roishift; /* 1 byte; SPrgn */
+ if(SPrgn == 0)
+ continue; /* Yet another kludge */
+
+ fprintf(xmlout, "%s<RegionOfInterest Marker=\"RGN\">\n", s); /* Optional in main header, at most 1 per component */
+ if(notes)
+ fprintf(xmlout, "%s<!-- See Crgn below for zero-based component number. -->\n", s);
+ /* Not retained or of interest: Lrgd */
+ fprintf(xmlout, "%s <Srgn>0</Srgn>\n", s); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, "%s <!-- Srgn is ROI style. Only style=0 defined: Implicit ROI (max. shift) -->\n", s);
+ fprintf(xmlout, "%s <Crgn>%d</Crgn>\n", s, compno); /* 1 or 2 bytes */
+ fprintf(xmlout, "%s <SPrgn>%d</SPrgn>\n", s, SPrgn); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, "%s <!-- SPrgn is implicit ROI shift, i.e., binary shifting of ROI coefficients above background. -->\n", s);
+ fprintf(xmlout, "</RegionOfInterest\n", s); /* Optional in main header, at most 1 per component */
+ }
+}
+
+/* ------------- */
+
+void xml_out_frame_poc(FILE* xmlout, opj_tcp_t *tcp) { /* Progression Order Change */
+ /* Compare j2k_read_poc() */
+ int i;
+ opj_poc_t *poc;
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+
+ if(tcp->POC != 1)
+ return; /* Not present */
+
+ fprintf(xmlout, "%s<ProgressionOrderChange Marker=\"POC\">\n", s); /* Optional in main header, at most 1 per component */
+ /* j2k_read_poc seems to allow accumulation of default pocs from multiple POC segments, but does
+ the spec really allow that? */
+ /* 2 bytes, not retained; Lpoc */
+ /* I probably didn't get this dump precisely right. */
+ for (i = 0; i < tcp->numpocs; i++) {
+ poc = &tcp->pocs[i];
+ fprintf(xmlout, "%s <Progression Num=\"%d\">\n", s, i+1);
+ fprintf(xmlout, "%S <RSpoc>%d</RSpoc>\n", s, poc->resno0); /* 1 byte, RSpoc_i */
+ if(notes)
+ fprintf(xmlout,"%s <!-- Resolution level index (inclusive) for progression start. Range: 0 to 33 -->\n", s);
+ fprintf(xmlout, "%s <CSpoc>%d</CSpoc>\n", s, poc->compno0);/* j2k_img->numcomps <= 256 ? 1 byte : 2 bytes; CSpoc_i */
+ if(notes)
+ fprintf(xmlout,"%s <!-- Component index (inclusive) for progression start. -->\n", s);
+ fprintf(xmlout, "%s <LYEpoc>%d</LYEpoc>\n", s, poc->layno1); /* int_min(cio_read(2), tcp->numlayers); /* 2 bytes; LYEpoc_i */
+ if(notes)
+ fprintf(xmlout,"%s <!-- Layer index (exclusive) for progression end. -->\n", s);
+ fprintf(xmlout, "%s <REpoc>%d</REpoc>\n", s, poc->resno1); /*int_min(cio_read(1), tccp->numresolutions); /* REpoc_i */
+ if(notes)
+ fprintf(xmlout,"%s <!-- Resolution level index (exclusive) for progression end. Range: RSpoc to 33 -->\n", s);
+ fprintf(xmlout, "%s <CEpoc>%d</CEpoc>\n", s, poc->compno1); /* int_min(cio_read(j2k_img->numcomps <= 256 ? 1 : 2), j2k_img->numcomps); /* CEpoc_i */
+ if(notes)
+ fprintf(xmlout,"%s <!-- Component index (exclusive) for progression end. Minimum: CSpoc -->\n", s);
+ fprintf(xmlout, "%s <Ppoc>%d</Ppoc>\n", s, poc->prg); /* 1 byte Ppoc_i */
+ if(notes) {
+ fprintf(xmlout,"%s <!-- Defined Progression Order Values are: -->\n", s);
+ fprintf(xmlout,"%s <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->\n", s);
+ fprintf(xmlout,"%s <!-- where L = \"layer\", R = \"resolution level\", C = \"component\", P = \"position\". -->\n", s);
+ }
+ fprintf(xmlout, "%s </Progression>\n", s);
+ }
+ fprintf(xmlout, "%s</ProgressionOrderChange\n", s);
+}
+
+/* ------------- */
+
+#ifdef SUPPRESS_FOR_NOW
+/* Suppress PPM and PPT since we're not showing data from the third option, namely within the codestream, and
+that's evidently what frames_to_mj2 uses. And a hex dump isn't so useful anyway */
+
+void xml_out_frame_ppm(FILE *xmlout, opj_cp_t *cp) { /* For main header, not tile-part (which uses PPT instead). */
+/* Either the PPM or PPT is required if the packet headers are not distributed in the bit stream */
+/* Use of PPM and PPT are mutually exclusive. */
+/* Compare j2k_read_ppm() */
+ int j;
+
+ if(cp->ppm != 1)
+ return; /* Not present */
+/* Main header uses indent of 10 spaces */
+ fprintf(xmlout, " <PackedPacketHeadersMainHeader Marker=\"PPM\">\n"); /* Optional in main header, but if not, must be in PPT or codestream */
+ /* 2 bytes Lppm not saved */
+ if(notes) {
+ fprintf(xmlout, " <!-- If there are multiple PPM marker segments in the main header, -->\n");
+ fprintf(xmlout, " <!-- this mj2_to_metadata implementation will report them as a single consolidated PPM header. -->\n");
+ fprintf(xmlout, " <!-- The implementation can't currently segregate by tile-part. -->\n");
+ fprintf(xmlout, " <!-- TO DO? further map the packet headers to xml. -->\n");
+ }
+
+ /* 1 byte, not retained ; Zppm is sequence # of this PPM header */
+ /* 4 bytes, possibly overwritten multiple times in j2k_cp->ppm_previous: Nppm */
+ /* Use j symbol for index instead of i, to make comparable with j2k_read_ppm */
+ /* Not real clear whether to use ppm->store or ppm_len as upper bound */
+ fprintf(xmlout, " <PackedData>\n");
+ xml_out_dump_hex(xmlout, cp->ppm_data, cp->ppm_len);
+ /* Dump packet headers 1 byte at a time: lppm[i][j] */
+ fprintf(xmlout, " </PackedData>\n");
+ fprintf(xmlout, " </PackedPacketHeadersMainHeader>\n"); /* Optional in main header, but if not, must be in PPT or codestream */
+}
+
+/* ------------- */
+
+void xml_out_frame_ppt(FILE *xmlout, opj_tcp_t *tcp) { /* For tile-part header, not main (which uses PPM instead). */
+/* Either the PPM or PPT is required if the packet headers are not distributed in the bit stream */
+/* Use of PPM and PPT are mutually exclusive. */
+/* Compare j2k_read_ppt() */
+ int j;
+
+ if(tcp->ppt != 1)
+ return; /* Not present */
+
+ /* Tile-part indents are 12 spaces */
+ fprintf(xmlout, " <PackedPacketHeadersTilePartHeader Marker=\"PPT\">\n"); /* Optional in main header, but if not, must be in PPT or codestream */
+ /* 2 bytes Lppm not saved */
+ if(notes) {
+ fprintf(xmlout, " <!-- If there are multiple PPT marker segments in the tile-part header, -->\n");
+ fprintf(xmlout, " <!-- this mj2_to_metadata implementation will report them as a single consolidated PPT header. -->\n");
+ fprintf(xmlout, " <!-- The implementation can't currently segregate by tile-part. -->\n");
+ fprintf(xmlout, " <!-- TO DO? further map the packet headers to xml. -->\n");
+ }
+
+ /* 1 byte, not retained ; Zppt is sequence # of this PPT header */
+ /* 4 bytes, possibly overwritten multiple times in j2k_cp->ppt_previous: Nppt */
+ /* Use j symbol for index instead of i, to make comparable with j2k_read_ppt */
+ /* Not real clear whether to use ppt->store or ppt_len as upper bound */
+ fprintf(xmlout, " <PackedData>\n");
+ xml_out_dump_hex(xmlout, tcp->ppt_data, tcp->ppt_len);
+ /* Dump packet headers 1 byte at a time: lppt[i][j] */
+ fprintf(xmlout, " </PackedData>\n");
+ fprintf(xmlout, " </PackedPacketHeadersTileHeader>\n"); /* Optional in tile-part header, but if not, must be in PPM or codestream */
+}
+#endif SUPPRESS_FOR_NOW
+
+/* ------------- */
+
+void xml_out_frame_tlm(FILE* xmlout) { /* opt, main header only. May be multiple. */
+/* Compare j2k_read_tlm()... which doesn't retain anything! */
+/* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
+/* Main header indents are 10 spaces */
+}
+
+/* ------------- */
+
+void xml_out_frame_plm(FILE* xmlout) { /* opt, main header only; can be used in conjunction with tile-part's PLT */
+/* NO-OP. PLM NOT SAVED IN DATA STRUCTURE */
+ /* Compare j2k_read_plm()... which doesn't retain anything! */
+/* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
+/* Main header indents are 10 spaces */
+}
+
+/* ------------- */
+
+void xml_out_frame_plt(FILE* xmlout, opj_tcp_t *tcp) { /* opt, tile-part headers only; can be used in conjunction with main header's PLM */
+/* NO-OP. PLT NOT SAVED IN DATA STRUCTURE */
+ /* Compare j2k_read_plt()... which doesn't retain anything! */
+/* Tile-part header indents are 12 spaces */
+}
+
+/* ------------- */
+
+void xml_out_frame_crg(FILE* xmlout) { /* NO-OP. CRG NOT SAVED IN DATA STRUCTURE */ /* opt, main header only; */
+/* Compare j2k_read_crg()... which doesn't retain anything! */
+/* Plan: Since this is only called from main header, not tilepart, use global j2k_default_tcp rather than parameter */
+#ifdef NOTYET
+ THIS PSEUDOCODE IMAGINES THESE EXIST: j2k_default_tcp->crg, j2k_default_tcp->crg_i, j2k_default_tcp->crg_xcrg*, j2k_default_tcp->crg_ycrg*
+ (POSSIBLY DON'T NEED crg_i, CAN GET NUMBER OR COMPONENTS FROM ELSEWHERE)
+ if(j2k_default_tcp->crg != 1 || j2k_default_tcp->crg_i == 0)
+ return; /* Not present */
+
+/* Main header indents are 10 spaces */
+ fprintf(xmlout, " <ComponentRegistration Marker=\"RG\" Count=\"%d\">\n", j2k_default_tcp->crg_i);
+ if(notes) {
+ fprintf(xmlout, " <!-- Fine tuning of registration of components with respect to each other, -->\n");
+ fprintf(xmlout, " <!-- not required but potentially helpful for decoder. -->\n");
+ fprintf(xmlout, " <!-- These supplementary fractional offsets are in units of 1/65536 of the horizontal -->\n");
+ fprintf(xmlout, " <!-- or vertical separation (e.g., XRsiz[i] or YRsiz[i] for component i). -->\n");
+ }
+ /* This isn't the most compact form of table, but is OK when number of components is small, as is likely. */
+ for (i = 0; i < j2k_default_tcp->crg_i; i++) {
+ fprintf(xmlout, " <Component Num=\"%d\">\n", i+1);
+ fprintf(xmlout, " <Xcrg>\n");
+ if(raw)
+ fprintf(xmlout," <AsNumerator>%d</AsNumerator>\n", j2k_default_tcp->crg_xcrg[i]);
+ if(derived) {
+ /* Calculate n * 100%/65536; 4 digits after decimal point is sufficiently accurate */
+ fprintf(xmlout," <AsPercentage>%.4f</AsPercentage>\n", ((double)j2k_default_tcp->crg_xcrg[i])/655.36);
+ /* We could do another calculation that include XRsiz[i]; maybe later. */
+ }
+ fprintf(xmlout, " </Xcrg>\n");
+ fprintf(xmlout, " <Ycrg>\n");
+ if(raw)
+ fprintf(xmlout," <AsNumerator>%d</AsNumerator>\n", j2k_default_tcp->crg_ycrg[i]);
+ if(derived) {
+ fprintf(xmlout," <AsPercentage>%f</AsPercentage>\n", ((double)j2k_default_tcp->crg_ycrg[i])/655.36);
+ }
+ fprintf(xmlout, " </Ycrg>\n");
+ fprintf(xmlout, " </Component>\n");
+ }
+
+ fprintf(xmlout, " </ComponentRegistration>\n");
+
+#endif
+}
+
+/* ------------- */
+
+/* Regrettably from a metadata point of view, j2k_read_com() skips over any comments in main header or tile-part-header */
+void xml_out_frame_com(FILE* xmlout, opj_tcp_t *tcp) { /* NO-OP. COM NOT SAVED IN DATA STRUCTURE */ /* opt in main or tile-part headers; */
+/* Compare j2k_read_com()... which doesn't retain anything! */
+#ifdef NOTYET
+ char spaces[13] = " "; /* 12 spaces if tilepart*/
+ char* s = spaces;
+ if(tcp == &j2k_default_tcp) {
+ s++;s++; /* shorten s to 10 spaces if main */
+ }
+ THIS PSEUDOCODE IMAGINES THESE EXIST: tcp->com, tcp->com_len, tcp->com_data array
+ if(tcp->com != 1)
+ return; /* Not present */
+
+ fprintf(xmlout, "%s<Comment Marker=\"COM\">\n", s); /* Optional in main or tile-part header */
+ xml_out_dump_hex_and_ascii(tcp->com_data, tcp->com_len, s);
+ fprintf(xmlout, "%s</Comment>\n", s);
+#endif
+}
+
+void xml_out_dump_hex(FILE* xmlout, char *data, int data_len, char* s) {
+ /* s is a string of spaces for indent */
+ int i;
+
+ /* This is called when raw is true, or there is no appropriate derived form */
+ fprintf(xmlout, "%s<AsHex>\n", s);
+ fprintf(xmlout, "%s ", s); /* Inadequate for pretty printing */
+ for (i = 0; i < data_len; i++) { /* Dump packet headers */
+ fprintf(xmlout, "%02x", data[i]);
+ }
+ fprintf(xmlout, "%s</AsHex>\n", s);
+}
+
+/* Define this as an even number: */
+#define BYTES_PER_DUMP_LINE 40
+/* Current total width for Hex and ASCII is : 11 spaces lead + (3 * BPDL) + 2 spaces + BPDL */
+void xml_out_dump_hex_and_ascii(FILE* xmlout, char *data, int data_len, char* s) {
+ /* s is a string of spaces for indent */
+ int i,j;
+
+ if(raw)
+ xml_out_dump_hex(xmlout, data, data_len, s);
+
+ if(derived) {
+ fprintf(xmlout, "%s<AsHexAndASCII>\n", s);
+ for (i = 0; i < data_len; ) {
+ fprintf(xmlout,"%s ", s); /* Additional leading space added in loop */
+ /* First column: hex */
+ for (j = 0; j < BYTES_PER_DUMP_LINE; j++) /* Dump bytes */
+ fprintf(xmlout," %02x", data[i+j]);
+ /* Space between columns... */ fprintf(xmlout, " ");
+ /* Second column: ASCII */
+ for (j = 0; j < BYTES_PER_DUMP_LINE; j++, i++) {
+ if(isprint((int)data[i]) && i < data_len)
+ fprintf(xmlout,"%c", data[i]);
+ else
+ fprintf(xmlout," ");
+ }
+ /* If we also wanted to output UCS-2 Unicode as a third column, then entire document
+ must use fwprintf. Forget about it for now. As it stands, if data is UCS-2 format but still
+ the ASCII set, then we'll be able to read every other byte as ASCII in column 2. If
+ data is UTF-8 format but still ASCII, then we'll be able to read every byte as ASCII
+ in column 2. */
+ }
+ fprintf(xmlout, "%s</AsHexAndASCII>\n", s);
+ }
+}
+
+
+/* ------------- */
+
+void xml_out_frame_jp2h(FILE* xmlout, opj_jp2_t *jp2_struct) { /* JP2 Header */
+/* Compare jp2_read_jp2h(opj_jp2_t * jp2_struct) */
+ int i;
+
+ fprintf(xmlout, " <JP2Header BoxType=\"jp2h\">\n");
+
+/* Compare jp2_read_ihdr(jp2_struct)) */
+ fprintf(xmlout, " <ImageHeader BoxType=\"ihdr\">\n");
+ fprintf(xmlout, " <HEIGHT>%d</HEIGHT>\n", jp2_struct->h); /* 4 bytes */
+ fprintf(xmlout, " <WIDTH>%d</WIDTH>\n", jp2_struct->w); /* 4 bytes */
+ if(notes)
+ fprintf(xmlout, " <!-- HEIGHT here, if 2 fields per image, is of total deinterlaced height. -->\n");
+ fprintf(xmlout, " <NC>%d</NC>\n", jp2_struct->numcomps); /* 2 bytes */
+ if(notes)
+ fprintf(xmlout, " <!-- NC is number of components -->\n"); /* 2 bytes */
+ fprintf(xmlout, " <BPC>\n"); /* 1 byte */
+ if(jp2_struct->bpc == 255) {
+ fprintf(xmlout, " <AsHex>0x%02x</AsHex>\n", jp2_struct->bpc); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- BPC = 0xff means bits per pixel varies with component; see table below. -->\n");
+ } else { /* Not 0xff */
+ if(raw) {
+ fprintf(xmlout, " <AsHex>0x%02x</AsHex>\n", jp2_struct->bpc); /* 1 byte */
+ if(notes)
+ fprintf(xmlout," <!-- BPC = 0xff means bits per pixel varies with component; see table below. -->\n");
+ }
+ if(derived) {
+ fprintf(xmlout, " <BitsPerPixel>%d</BitsPerPixel>\n", jp2_struct->bpc & 0x7f);
+ fprintf(xmlout, " <Signed>%d</Signed>\n", jp2_struct->bpc >> 7);
+ }
+ }
+ fprintf(xmlout, " </BPC>\n");
+ fprintf(xmlout, " <C>%d</C>\n", jp2_struct->C); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- C is compression type. Only \"7\" is allowed to date. -->\n"); /* 2 bytes */
+ fprintf(xmlout, " <UnkC>%d</UnkC>\n", jp2_struct->UnkC); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- Colourspace Unknown. 1 = unknown, 0 = known (e.g., colourspace spec is accurate) -->\n"); /* 1 byte */
+ fprintf(xmlout, " <IPR>%d</IPR>\n", jp2_struct->IPR); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- IPR is 1 if frame contains an Intellectual Property box; 0 otherwise. -->\n"); /* 2 bytes */
+ fprintf(xmlout, " </ImageHeader>\n");
+
+ if (jp2_struct->bpc == 255)
+ {
+ fprintf(xmlout, " <BitsPerComponent BoxType=\"bpcc\">\n");
+ if(notes)
+ fprintf(xmlout, " <!-- Pixel depth (range 1 to 38) is low 7 bits of hex value + 1 -->\n");
+ /* Bits per pixel varies with components */
+ /* Compare jp2_read_bpcc(jp2_struct) */
+ for (i = 0; i < (int)jp2_struct->numcomps; i++) {
+ if(raw)
+ fprintf(xmlout," <AsHex>0x%02x</AsHex>\n", jp2_struct->comps[i].bpcc); /* 1 byte */
+ if(derived) {
+ fprintf(xmlout," <BitsPerPixel>%d</BitsPerPixel>\n", (jp2_struct->comps[i].bpcc & 0x7f)+1);
+ fprintf(xmlout," <Signed>%d</Signed>\n", jp2_struct->comps[i].bpcc >> 7);
+ }
+ }
+ fprintf(xmlout, " </BitsPerComponent>\n");
+ }
+
+ /* Compare jp2_read_colr(jp2_struct) */
+ fprintf(xmlout, " <ColourSpecification BoxType=\"colr\">\n");
+ fprintf(xmlout, " <METH>%d</METH>\n", jp2_struct->meth); /* 1 byte */
+ if(notes) {
+ fprintf(xmlout, " <!-- Valid values of specification method so far: -->\n");
+ fprintf(xmlout, " <!-- 1 = Enumerated colourspace, in EnumCS field -->\n");
+ fprintf(xmlout, " <!-- 2 = Restricted ICC Profile, in PROFILE field -->\n");
+ }
+ fprintf(xmlout, " <PREC>%d</PREC>\n", jp2_struct->precedence); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- 0 is only valid value of precedence so far. -->\n");
+ fprintf(xmlout, " <APPROX>%d</APPROX>\n", jp2_struct->approx); /* 1 byte */
+ if(notes)
+ fprintf(xmlout, " <!-- 0 is only valid value of colourspace approximation so far. -->\n");
+
+ if (jp2_struct->meth == 1) {
+ fprintf(xmlout, " <EnumCS>%d</EnumCS>\n", jp2_struct->enumcs); /* 4 bytes */
+ if(notes) {
+ fprintf(xmlout, " <!-- Valid values of enumerated MJ2 colourspace so far: -->\n");
+ fprintf(xmlout, " <!-- 16: sRGB as defined by IEC 61966-2-1. -->\n");
+ fprintf(xmlout, " <!-- 17: greyscale (related to sRGB). -->\n");
+ fprintf(xmlout, " <!-- 18: sRGB YCC (from JPEG 2000 Part II). -->\n");
+ fprintf(xmlout, " <!-- (Additional JPX values are defined in Part II). -->\n");
+ }
+ }
+ else
+ if(notes)
+ fprintf(xmlout, " <!-- PROFILE is not handled by current OpenJPEG implementation. -->\n");
+ /* only 1 byte is read and nothing stored */
+ fprintf(xmlout, " </ColourSpecification>\n");
+
+ /* TO DO? No OpenJPEG support.
+ Palette 'pclr'
+ ComponentMapping 'cmap'
+ ChannelDefinition 'cdef'
+ Resolution 'res'
+ */
+ fprintf(xmlout, " </JP2Header>\n");
+}
+/* ------------- */
+
+#ifdef NOTYET
+IMAGE these use cp structure, extended... but we could use a new data structure instead
+void xml_out_frame_jp2i(FILE* xmlout, opj_cp_t *cp) {
+ /* IntellectualProperty 'jp2i' (no restrictions on location) */
+ int i;
+ IMAGE cp->jp2i, cp->jp2i_count, cp->jp2i_data (array of chars), cp->cp2i_len (array of ints)
+ if(cp->jp2i != 1)
+ return; /* Not present */
+
+ for(i = 0; i < cp->jp2i_count; i++)
+ {
+ fprintf(xmlout, " <IntellectualProperty BoxType=\"jp2i\">\n");
+ /* I think this can be anything, including binary, so do a dump */
+ /* Is it better to indent or not indent this content? Indent is better for reading, but
+ worse for cut/paste. */
+ xml_out_dump_hex_and_ascii(xmlout, cp->jp2i_data[i], cp->jp2i_len[i]);
+ fprintf(xmlout, " </IntellectualProperty>\n");
+ }
+}
+
+void xml_out_frame_xml(FILE* xmlout, opj_cp_t *cp) {
+ /* XML 'xml\040' (0x786d6c20). Can appear multiply, before or after jp2c codestreams */
+ IMAGE cp->xml, cp->xml_count, cp->xml_data (array of chars)
+ MAYBE WE DON'T NEED cp->xml_len (array of ints) IF WE ASSUME xml_data IS NULL-TERMINATED.
+ ASSUME ASSUME EACH LINE IS ENDED BY \n.
+ int i;
+ if(cp->xml != 1)
+ return; /* Not present */
+
+ for(i = 0; i < cp->xml_count; i++)
+ {
+ fprintf(xmlout, " <TextFormXML BoxType=\"xml[space]" Instance=\"%d\">\n", i+1);
+ /* Is it better to indent or not indent this content? Indent is better for reading, but
+ worse for cut/paste. Being lazy, didn't indent here. */
+ fprintf(xmlout,cp->xml_data[i]); /* May be multiple lines */ /* Could check if this is well-formed */
+ fprintf(xmlout, " </TextFormXML>\n");
+ }
+}
+
+void xml_out_frame_uuid(FILE* xmlout, opj_cp_t *cp) {
+ /* UUID 'uuid' (top level only) */
+ /* Part I 1.7.2 says: may appear multiply in JP2 file, anywhere except before File Type box */
+ /* Part III 5.2.1 says: Private extensions shall be achieved through the 'uuid' type. */
+ /* A UUID is a 16-byte value. There is a conventional string representation for it:
+ "0x12345678-9ABC-DEF0-1234-567890ABCDEF". Let's assume that is what is stored in uuid_value */
+
+ /* Part III 6.1 Any other MJ2 box type could be alternatively written as a 'uuid' box, with value given
+ as : 0xXXXXXXXX-0011-0010-8000-00AA00389B71, where the Xs are the boxtype in hex. However,
+ such a file is "not compliant; systems may choose to read [such] objects ... as equivalent to the box of
+ the same type, or not." Here, we choose not to. */
+ int i;
+ IMAGE cp->uuid, cp->uuid_count, cp->uuid_value (array of uuids... let's say fixed-length strings) cp->uuid_data (array of char buffers), cp->uuid_len (array of ints)
+ if(cp->juuid != 1)
+ return; /* Not present */
+
+ for(i = 0; i < cp->uuid_count; i++)
+ {
+ fprintf(xmlout, " <UniversalUniqueID BoxType=\"uuid\">
+ fprintf(xmlout, " <UUID>%s</UUDI>\n", cp->uuid_value[i]);
+ fprintf(xmlout, " <Data>\n");
+ /* I think this can be anything, including binary, so do a dump */
+ /* Is it better to indent or not indent this content? Indent is better for reading, but
+ worse for cut/paste. */
+ xml_out_dump_hex_and_ascii(xmlout, cp->uuid_data[i], cp->uuid_len[i]);
+ fprintf(xmlout, " </Data>\n");
+ fprintf(xmlout, " </UniversalUniqueID>\n");
+ }
+}
+
+void xml_out_frame_uinf(FILE* xmlout, opj_cp_t *cp) {
+ /* UUIDInfo 'uinf', includes UUIDList 'ulst' and URL 'url\40' */
+ /* Part I 1.7.3 says: may appear multiply in JP2 file, anywhere at the top level except before File Type box */
+ /* So there may be multiple ulst's, and each can have multiple UUIDs listed (with a single URL) */
+ /* This is not quite as vendor-specific as UUIDs, or at least is meant to be generally readable */
+ /* Assume UUIDs stored in canonical string format */
+ int i, j;
+ IMAGE cp->uinf, cp->uinf_count, cp->uinf_ulst_nu (array of ints)
+ cp->uinf_uuid (2 dimensional array of uuids... let's say fixed-length strings),
+ cp->uinf_url (array of char buffers)
+
+ if(cp->uinf != 1)
+ return; /* Not present */
+
+ for(i = 0; i < cp->uuid_count; i++)
+ {
+ fprintf(xmlout, " <UUIDInfo BoxType=\"uinf\">\n");
+ fprintf(xmlout, " <UUIDList BoxType=\"ulst\" Count=\"%d\">\n",cp->cp->uinf_ulst_nu[i]);
+ for(j = 0; j < cp->uinf_ulst_nu[i]; j++)
+ fprintf(xmlout, " <ID Instance=\"%s\">%s</ID>\n", cp->uuif_uuid[i][j], j+1);
+ fprintf(xmlout, " </UUIDList>\n");
+ fprintf(xmlout, " <DataEntryURL>\n");
+ /* Could add VERS and FLAG here */
+ fprintf(xmlout, " <LOC>\n");
+ fprintf(xmlout, " %s",cp->uinf_url[i]); /* Probably single line, so indent works */ /* In theory, could check if this is well-formed, or good live link */
+ fprintf(xmlout, " </LOC>\n");
+ fprintf(xmlout, " </DataEntryURL>\n");
+ fprintf(xmlout, " </UUIDInfo>\n");
+ }
+}
+
+IMAGE these use cp structure, extended... but we could use a new data structure instead
+void xml_out_frame_unknown_type(FILE* xmlout, opj_cp_t *cp) {
+ /* Part III 5.2.1 says "Type fields not defined here are reserved. Private extensions
+ shall be acieved through the 'uuid' type." [This implies an unknown
+ type would be an error, but then...] "Boxes not explicitly defined in this standard,
+ or otherwise unrecognized by a reader, may be ignored."
+ Also, it says "the following types are not and will not be used, or used only in
+ their existing sense, in future versions of this specification, to avoid conflict
+ with existing content using earlier pre-standard versions of this format:
+ clip, crgn, matt, kmat, pnot, ctab, load, imap;
+ track reference types tmcd, chap, sync,scpt, ssrc"
+ [But good luck figuring out the mapping.]
+ Part III Amend. 2 4.1 is stronger: "All these specifications [of this family, e.g.,
+ JP2 Part I, ISO Base format (Part 12) leading to MP4, Quicktime, and possibly including
+ MJ2] require that readers ignore objects that are unrecognizable to them".
+ */
+ int i;
+ IMAGE cp->unknown_type, cp->unknown_type_count, cp->unknown_type_boxtype (array of buf[5]s), cp->unknown_type_data (array of chars), cp->unknown_type_len (array of ints)
+ if(cp->unknown_type != 1)
+ return; /* Not present */
+
+ for(i = 0; i < cp->unknown_type_count; i++)
+ {
+ fprintf(xmlout, " <UnknownType BoxType=\"%s\">\n", cp->unknown_type_boxtype[i]);
+ /* Can be anything, including binary, so do a dump */
+ /* Is it better to indent or not indent this content? Indent is better for reading, but
+ worse for cut/paste. */
+ xml_out_dump_hex_and_ascii(xmlout, cp->unknown_type_data[i], cp->unknown_type_len[i]);
+ fprintf(xmlout, " </UnknownType>\n");
+ }
+}
+
+#endif
diff --git a/src/bin/mj2/meta_out.h b/src/bin/mj2/meta_out.h
new file mode 100644
index 00000000..293316d1
--- /dev/null
+++ b/src/bin/mj2/meta_out.h
@@ -0,0 +1,13 @@
+/* meta_out.h */
+/* Dump MJ2, JP2 metadata (partial so far) to xml file */
+/* Callable from mj2_to_metadata */
+/* Contributed to Open JPEG by Glenn Pearson, U.S. National Library of Medicine */
+
+#define BOOL int
+#define FALSE 0
+#define TRUE 1
+
+void xml_write_init(BOOL n, BOOL t, BOOL r, BOOL d);
+
+int xml_write_struct(FILE *file, FILE *xmlout, opj_mj2_t * movie, unsigned int sampleframe, char* stringDTD, opj_event_mgr_t *event_mgr);
+
diff --git a/src/bin/mj2/mj2.c b/src/bin/mj2/mj2.c
new file mode 100644
index 00000000..f5ab5f3f
--- /dev/null
+++ b/src/bin/mj2/mj2.c
@@ -0,0 +1,2915 @@
+/*
+ * 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 "opj_includes.h"
+#include "mj2.h"
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/*
+*
+* Read box headers
+*
+*/
+
+int mj2_read_boxhdr(mj2_box_t * box, opj_cio_t *cio)
+{
+ box->init_pos = cio_tell(cio);
+ box->length = cio_read(cio, 4);
+ box->type = cio_read(cio, 4);
+ if (box->length == 1) {
+ if (cio_read(cio, 4) != 0) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Cannot handle box sizes higher than 2^32\n");
+ return 1;
+ };
+ box->length = cio_read(cio, 4);
+ if (box->length == 0)
+ box->length = cio_numbytesleft(cio) + 12;
+ }
+ else if (box->length == 0) {
+ box->length = cio_numbytesleft(cio) + 8;
+ }
+ return 0;
+}
+
+/*
+*
+* Initialisation of a Standard Movie, given a simple movie structure defined by the user
+* The movie will have one sample per chunk
+*
+* Arguments: opj_mj2_t * movie
+* Several variables of "movie" must be defined in order to enable a correct execution of
+* this function:
+* - The number of tracks of each type (movie->num_vtk, movie->num_stk, movie->num_htk)
+* - The memory for each must be allocated (movie->tk)
+* - For each track:
+* The track type (tk->track_type)
+* The number of sample (tk->num_samples)
+* The sample rate (tk->sample_rate)
+*
+*/
+
+int mj2_init_stdmovie(opj_mj2_t * movie)
+{
+ mj2_tk_t *tk0;
+ int i, w, h, prec;
+ unsigned int j;
+ time_t ltime;
+
+ movie->brand = MJ2_MJ2;
+ movie->minversion = 0;
+ movie->num_cl = 2;
+ movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
+
+ movie->cl[0] = MJ2_MJ2;
+ movie->cl[1] = MJ2_MJ2S;
+ time(&ltime); /* Time since 1/1/70 */
+ movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
+ movie->timescale = 1000;
+
+ movie->rate = 1 << 16; /* Rate to play presentation (default = 0x00010000) */
+ movie->volume = 1 << 8; /* Movie volume (default = 0x0100) */
+ movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
+ movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
+ movie->trans_matrix[2] = 0;
+ movie->trans_matrix[3] = 0;
+ movie->trans_matrix[4] = 0x00010000;
+ movie->trans_matrix[5] = 0;
+ movie->trans_matrix[6] = 0;
+ movie->trans_matrix[7] = 0;
+ movie->trans_matrix[8] = 0x40000000;
+ movie->next_tk_id = 1;
+
+ tk0 = &movie->tk[0];
+ w = tk0->w; h = tk0->h; prec = tk0->depth;
+
+ for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++)
+ {
+ mj2_tk_t *tk = &movie->tk[i];
+
+ movie->next_tk_id++;
+ tk->jp2_struct.comps = NULL;
+ tk->jp2_struct.cl = NULL;
+
+ if (tk->track_type == 0) /* no sound or hint track */
+ {
+ if (tk->num_samples == 0)
+ return 1;
+
+ tk->w = w; tk->h = h; tk->depth = prec;
+ tk->Dim[0] = 0;
+ tk->Dim[1] = 0;
+
+ tk->timescale = 1000; /* Timescale = 1 ms */
+
+ tk->chunk[0].num_samples = 1;
+ tk->chunk[0].sample_descr_idx = 1;
+
+ tk->same_sample_size = 0;
+
+ tk->num_samplestochunk = 1; /* One sample per chunk */
+ tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
+ tk->sampletochunk[0].first_chunk = 1;
+ tk->sampletochunk[0].samples_per_chunk = 1;
+ tk->sampletochunk[0].sample_descr_idx = 1;
+
+ if (tk->sample_rate == 0)
+ {
+ opj_event_msg(tk->cinfo, EVT_ERROR,
+ "Error while initializing MJ2 movie: Sample rate of track"
+ " %d must be different from zero\n", tk->track_ID);
+ return 1;
+ }
+
+ for (j = 0; j < tk->num_samples; j++)
+ {
+ tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
+ }
+
+ tk->num_tts = 1;
+ tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
+ tk->tts[0].sample_count = tk->num_samples;
+ tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
+
+ tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
+ tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
+ tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
+ tk->compressorname[1] = 0x696f6e20;
+ tk->compressorname[2] = 0x4a504547;
+ tk->compressorname[3] = 0x32303030;
+ tk->compressorname[4] = 0x00120000;
+ tk->compressorname[5] = 0;
+ tk->compressorname[6] = 0x00000042;
+ tk->compressorname[7] = 0x000000DC;
+ tk->num_url = 0; /* Number of URL */
+ tk->num_urn = 0; /* Number of URN */
+ tk->graphicsmode = 0; /* Graphicsmode */
+ tk->opcolor[0] = 0; /* OpColor */
+ tk->opcolor[1] = 0; /* OpColor */
+ tk->opcolor[2] = 0; /* OpColor */
+ tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
+ tk->language = 0; /* Language (undefined) */
+ tk->layer = 0;
+ tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
+ tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
+ tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
+ tk->trans_matrix[2] = 0;
+ tk->trans_matrix[3] = 0;
+ tk->trans_matrix[4] = 0x00010000;
+ tk->trans_matrix[5] = 0;
+ tk->trans_matrix[6] = 0;
+ tk->trans_matrix[7] = 0;
+ tk->trans_matrix[8] = 0x40000000;
+ tk->fieldcount = 1;
+ tk->fieldorder = 0;
+ tk->or_fieldcount = 1;
+ tk->or_fieldorder = 0;
+ tk->num_br = 2;
+ tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
+ tk->br[0] = MJ2_JP2;
+ tk->br[1] = MJ2_J2P0;
+ tk->num_jp2x = 0;
+ tk->hsub = 2; /* 4:2:0 */
+ tk->vsub = 2; /* 4:2:0 */
+ tk->hoff = 0;
+ tk->voff = 0;
+ tk->visual_w = tk->w << 16;
+ tk->visual_h = tk->h << 16;
+ }
+ else {
+ tk->num_br = 0;
+ tk->jp2xdata = NULL;
+ }
+ }
+ return 0;
+}
+
+/*
+* Time To Sample box Decompact
+*
+*/
+void mj2_tts_decompact(mj2_tk_t * tk)
+{
+ int i, j;
+ tk->num_samples = 0;
+ for (i = 0; i < tk->num_tts; i++) {
+ tk->num_samples += tk->tts[i].sample_count;
+ }
+
+ tk->sample = (mj2_sample_t*) opj_malloc(tk->num_samples * sizeof(mj2_sample_t));
+
+ for (i = 0; i < tk->num_tts; i++) {
+ for (j = 0; j < tk->tts[i].sample_count; j++) {
+ tk->sample[j].sample_delta = tk->tts[i].sample_delta;
+ }
+ }
+}
+
+/*
+* Sample To Chunk box Decompact
+*
+*/
+void mj2_stsc_decompact(mj2_tk_t * tk)
+{
+ unsigned int i, j, k, sampleno = 0;
+
+ if (tk->num_samplestochunk == 1) {
+ tk->num_chunks =
+ (unsigned int) ceil((double) tk->num_samples /
+ (double) tk->sampletochunk[0].samples_per_chunk);
+ tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_chunks * sizeof(mj2_chunk_t));
+ for (k = 0; k < tk->num_chunks; k++) {
+ tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
+ }
+
+ } else {
+ tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_samples * sizeof(mj2_chunk_t));
+ tk->num_chunks = 0;
+ for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
+ for (j = tk->sampletochunk[i].first_chunk - 1;
+ j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
+ tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
+ tk->num_chunks++;
+ sampleno += tk->chunk[j].num_samples;
+ }
+ }
+ tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
+ for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
+ k < tk->num_chunks; k++) {
+ tk->chunk[k].num_samples =
+ tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
+ }
+ tk->chunk = (mj2_chunk_t*)
+ opj_realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
+ }
+
+}
+
+
+/*
+* Chunk offset box Decompact
+*
+*/
+void mj2_stco_decompact(mj2_tk_t * tk)
+{
+ unsigned int i, j, k = 0;
+ unsigned int intra_chunk_offset;
+
+ for (i = 0; i < tk->num_chunks; i++) {
+ intra_chunk_offset = 0;
+ for (j = 0; j < tk->chunk[i].num_samples; j++) {
+ tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
+ intra_chunk_offset += tk->sample[k].sample_size;
+ k++;
+ }
+ }
+}
+
+/*
+* Write the JP box
+*
+* JP Signature box
+*
+*/
+void mj2_write_jp(opj_cio_t *cio)
+{
+ mj2_box_t box;
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+
+ cio_write(cio, MJ2_JP, 4); /* JP */
+ cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4);
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+/*
+* Read the JP box
+*
+* JPEG 2000 signature
+*
+*/
+int mj2_read_jp(opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_JP != box.type) { /* Check Marker */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP Marker\n");
+ return 1;
+ }
+ if (0x0d0a870a != cio_read(cio, 4)) { /* read the 0x0d0a870a required in a JP box */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Marker\n");
+ return 1;
+ }
+ if (cio_tell(cio) - box.init_pos != box.length) { /* Check box length */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Box size \n");
+ return 1;
+ }
+ return 0;
+
+}
+
+/*
+* Write the FTYP box
+*
+* File type box
+*
+*/
+void mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+
+ cio_write(cio, MJ2_FTYP, 4); /* FTYP */
+ cio_write(cio, movie->brand, 4); /* BR */
+ cio_write(cio, movie->minversion, 4); /* MinV */
+
+ for (i = 0; i < movie->num_cl; i++)
+ cio_write(cio, movie->cl[i], 4); /* CL */
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* Length */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+/*
+* Read the FTYP box
+*
+* File type box
+*
+*/
+int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio); /* Box Size */
+ if (MJ2_FTYP != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FTYP Marker\n");
+ return 1;
+ }
+
+ movie->brand = cio_read(cio, 4); /* BR */
+ movie->minversion = cio_read(cio, 4); /* MinV */
+ movie->num_cl = (box.length - 16) / 4;
+ movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
+
+ for (i = movie->num_cl - 1; i > -1; i--)
+ movie->cl[i] = cio_read(cio, 4); /* CLi */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+* Write the STCO box
+*
+* Chunk Offset Box
+*
+*/
+void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+ unsigned int i;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STCO, 4); /* STCO */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->num_chunks, 4); /* Entry Count */
+
+ for (i = 0; i < tk->num_chunks; i++) {
+ cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
+ }
+
+ 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);
+}
+
+/*
+* Read the STCO box
+*
+* Chunk Offset Box
+*
+*/
+int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ unsigned int i;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio); /* Box Size */
+ if (MJ2_STCO != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STCO Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STCO box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n");
+ return 1;
+ }
+
+
+ if (cio_read(cio, 4) != tk->num_chunks) {
+ opj_event_msg(cio->cinfo, EVT_ERROR,
+ "Error in STCO box: expecting same amount of entry-count as chunks \n");
+ } else {
+ for (i = 0; i < tk->num_chunks; i++) {
+ tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
+ }
+ }
+
+ mj2_stco_decompact(tk);
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the STSZ box
+*
+* Sample size box
+*
+*/
+void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+ unsigned int i;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STSZ, 4); /* STSZ */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ if (tk->same_sample_size == 1) { /* If they all have the same size */
+ cio_write(cio, tk->sample[0].sample_size, 4); /* Size */
+
+ cio_write(cio, 1, 4); /* Entry count = 1 */
+ }
+
+ else {
+ cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
+
+ cio_write(cio, tk->num_samples, 4); /* Sample Count */
+
+ for (i = 0; i < tk->num_samples; i++) {
+ cio_write(cio, tk->sample[i].sample_size, 4);
+ }
+ }
+
+ 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);
+}
+
+/*
+* Read the STSZ box
+*
+* Sample size box
+*
+*/
+int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int sample_size;
+ unsigned int i;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio); /* Box Size */
+ if (MJ2_STSZ != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSZ Marker\n");
+ return 1;
+ }
+
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n");
+ return 1;
+ }
+
+ sample_size = cio_read(cio, 4);
+
+ if (sample_size != 0) { /* Samples do have the same size */
+ tk->same_sample_size = 1;
+ for (i = 0; i < tk->num_samples; i++) {
+ tk->sample[i].sample_size = sample_size;
+ }
+ cio_skip(cio,4); /* Sample count = 1 */
+ } else {
+ tk->same_sample_size = 0;
+ if (tk->num_samples != cio_read(cio, 4)) { /* Sample count */
+ opj_event_msg(cio->cinfo, EVT_ERROR,
+ "Error in STSZ box. Expected that sample-count is number of samples in track\n");
+ return 1;
+ }
+ for (i = 0; i < tk->num_samples; i++) {
+ tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
+ return 1;
+ }
+ }
+ return 0;
+
+}
+
+/*
+* Write the STSC box
+*
+* Sample to Chunk
+*
+*/
+void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ unsigned int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STSC, 4); /* STSC */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
+
+ for (i = 0; i < tk->num_samplestochunk; i++) {
+ cio_write(cio, tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
+ cio_write(cio, tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
+ cio_write(cio, tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
+ }
+
+
+ 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);
+}
+
+/*
+* Read the STSC box
+*
+* Sample to Chunk
+*
+*/
+int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ unsigned int i;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio); /* Box Size */
+ if (MJ2_STSC != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSC Marker\n");
+ return 1;
+ }
+
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSC box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n");
+ return 1;
+ }
+
+ tk->num_samplestochunk = cio_read(cio, 4);
+
+ tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
+
+ for (i = 0; i < tk->num_samplestochunk; i++) {
+ tk->sampletochunk[i].first_chunk = cio_read(cio, 4);
+ tk->sampletochunk[i].samples_per_chunk = cio_read(cio, 4);
+ tk->sampletochunk[i].sample_descr_idx = cio_read(cio, 4);
+ }
+
+ mj2_stsc_decompact(tk); /* decompact sample to chunk box */
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the STTS box
+*
+* Time to Sample Box
+*
+*/
+void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STTS, 4); /* STTS */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->num_tts, 4); /* entry_count */
+ for (i = 0; i < tk->num_tts; i++) {
+ cio_write(cio, tk->tts[i].sample_count, 4); /* Sample-count */
+ cio_write(cio, tk->tts[i].sample_delta, 4); /* Sample-Delta */
+ }
+
+ 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);
+}
+
+/*
+* Read the STTS box
+*
+*
+*
+*/
+int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int i;
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_STTS != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STTS Marker\n");
+ return 1;
+ }
+
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STTS box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n");
+ return 1;
+ }
+
+ tk->num_tts = cio_read(cio, 4);
+
+ tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
+
+ for (i = 0; i < tk->num_tts; i++) {
+ tk->tts[i].sample_count = cio_read(cio, 4);
+ tk->tts[i].sample_delta = cio_read(cio, 4);
+ }
+
+ mj2_tts_decompact(tk);
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the FIEL box
+*
+* Field coding Box
+*
+*/
+void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_FIEL, 4); /* STTS */
+
+ cio_write(cio, tk->fieldcount, 1); /* Field count */
+ cio_write(cio, tk->fieldorder, 1); /* Field order */
+
+
+ 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);
+}
+
+/*
+* Read the FIEL box
+*
+* Field coding Box
+*
+*/
+int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_FIEL != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FIEL Marker\n");
+ return 1;
+ }
+
+
+ tk->fieldcount = cio_read(cio, 1);
+ tk->fieldorder = cio_read(cio, 1);
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the ORFO box
+*
+* Original Format Box
+*
+*/
+void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_ORFO, 4);
+
+ cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
+ cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
+
+
+ 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);
+}
+
+/*
+* Read the ORFO box
+*
+* Original Format Box
+*
+*/
+int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_ORFO != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected ORFO Marker\n");
+ return 1;
+ }
+
+
+ tk->or_fieldcount = cio_read(cio, 1);
+ tk->or_fieldorder = cio_read(cio, 1);
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the JP2P box
+*
+* MJP2 Profile Box
+*
+*/
+void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_JP2P, 4);
+
+ cio_write(cio, 0, 4); /* Version 0, flags =0 */
+
+ for (i = 0; i < tk->num_br; i++) {
+ cio_write(cio, tk->br[i], 4);
+ }
+
+ 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);
+}
+
+/*
+* Read the JP2P box
+*
+* MJP2 Profile Box
+*
+*/
+int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int i;
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_JP2P != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2P Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
+ return 1;
+ }
+
+
+ tk->num_br = (box.length - 12) / 4;
+ tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
+
+ for (i = 0; i < tk->num_br; i++) {
+ tk->br[i] = cio_read(cio, 4);
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the JP2X box
+*
+* MJP2 Prefix Box
+*
+*/
+void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_JP2X, 4);
+
+ for (i = 0; i < tk->num_jp2x; i++) {
+ cio_write(cio, tk->jp2xdata[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);
+}
+
+/*
+* Read the JP2X box
+*
+* MJP2 Prefix Box
+*
+*/
+int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ unsigned int i;
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_JP2X != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2X Marker\n");
+ return 1;
+ }
+
+
+ tk->num_jp2x = (box.length - 8);
+ tk->jp2xdata = (unsigned char*) opj_malloc(tk->num_jp2x * sizeof(unsigned char));
+
+ for (i = 0; i < tk->num_jp2x; i++) {
+ tk->jp2xdata[i] = cio_read(cio, 1);
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the JSUB box
+*
+* MJP2 Subsampling Box
+*
+*/
+void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_JSUB, 4);
+
+ cio_write(cio, tk->hsub, 1);
+ cio_write(cio, tk->vsub, 1);
+ cio_write(cio, tk->hoff, 1);
+ cio_write(cio, tk->voff, 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);
+}
+
+/*
+* Read the JSUB box
+*
+* MJP2 Subsampling Box
+*
+*/
+int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_JSUB != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JSUB Marker\n");
+ return 1;
+ }
+
+ tk->hsub = cio_read(cio, 1);
+ tk->vsub = cio_read(cio, 1);
+ tk->hoff = cio_read(cio, 1);;
+ tk->voff = cio_read(cio, 1);
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the SMJ2 box
+*
+* Visual Sample Entry Description
+*
+*/
+void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, 1, 4);
+
+ cio_write(cio, 0, 2); /* Pre-defined */
+
+ cio_write(cio, 0, 2); /* Reserved */
+
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+
+ cio_write(cio, tk->w, 2); /* Width */
+ cio_write(cio, tk->h, 2); /* Height */
+
+ cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
+ cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
+
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, 1, 2); /* Pre-defined = 1 */
+
+ cio_write(cio, tk->compressorname[0], 4); /* Compressor Name */
+ cio_write(cio, tk->compressorname[1], 4);
+ cio_write(cio, tk->compressorname[2], 4);
+ cio_write(cio, tk->compressorname[3], 4);
+ cio_write(cio, tk->compressorname[4], 4);
+ cio_write(cio, tk->compressorname[5], 4);
+ cio_write(cio, tk->compressorname[6], 4);
+ cio_write(cio, tk->compressorname[7], 4);
+
+ cio_write(cio, tk->depth, 2); /* Depth */
+
+ cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
+
+ jp2_write_jp2h(&tk->jp2_struct, cio);
+
+ mj2_write_fiel(tk, cio);
+
+ if (tk->num_br != 0)
+ mj2_write_jp2p(tk, cio);
+ if (tk->num_jp2x != 0)
+ mj2_write_jp2x(tk, cio);
+
+ mj2_write_jsub(tk, cio);
+ mj2_write_orfo(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the SMJ2 box
+*
+* Visual Sample Entry Description
+*
+*/
+int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+ mj2_box_t box2;
+ opj_jp2_color_t color;
+ int i;
+ opj_bool ok;
+
+ mj2_read_boxhdr(&box, cio);
+
+ if (MJ2_MJ2 != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
+ return 1;
+ }
+
+ cio_skip(cio,4);
+
+ cio_skip(cio,2); /* Pre-defined */
+
+ cio_skip(cio,2); /* Reserved */
+
+ cio_skip(cio,4); /* Pre-defined */
+ cio_skip(cio,4); /* Pre-defined */
+ cio_skip(cio,4); /* Pre-defined */
+
+ tk->w = cio_read(cio, 2); /* Width */
+ tk->h = cio_read(cio, 2); /* Height */
+
+ tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
+ tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
+
+ cio_skip(cio,4); /* Reserved */
+
+ cio_skip(cio,2); /* Pre-defined = 1 */
+
+ tk->compressorname[0] = cio_read(cio, 4); /* Compressor Name */
+ tk->compressorname[1] = cio_read(cio, 4);
+ tk->compressorname[2] = cio_read(cio, 4);
+ tk->compressorname[3] = cio_read(cio, 4);
+ tk->compressorname[4] = cio_read(cio, 4);
+ tk->compressorname[5] = cio_read(cio, 4);
+ tk->compressorname[6] = cio_read(cio, 4);
+ tk->compressorname[7] = cio_read(cio, 4);
+
+ tk->depth = cio_read(cio, 2); /* Depth */
+
+ /* Init std value */
+ tk->num_jp2x = 0;
+ tk->fieldcount = 1;
+ tk->fieldorder = 0;
+ tk->or_fieldcount = 1;
+ tk->or_fieldorder = 0;
+
+ cio_skip(cio,2); /* Pre-defined = -1 */
+ memset(&color, 0, sizeof(opj_jp2_color_t));
+ tk->jp2_struct.cinfo = tk->cinfo;
+
+ ok = jp2_read_jp2h(&tk->jp2_struct, cio, &color);
+
+ tk->jp2_struct.cinfo = NULL;
+
+ if(ok == OPJ_FALSE)
+ {
+ opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
+ return 1;
+ }
+
+ tk->jp2_struct.comps = (opj_jp2_comps_t*) opj_malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
+ tk->jp2_struct.cl = (unsigned int*) opj_malloc(sizeof(unsigned int));
+
+ tk->num_br = 0;
+ tk->num_jp2x = 0;
+
+ for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
+ mj2_read_boxhdr(&box2, cio);
+ cio_seek(cio, box2.init_pos);
+ switch (box2.type) {
+ case MJ2_FIEL:
+ if (mj2_read_fiel(tk, cio))
+ return 1;
+ break;
+
+ case MJ2_JP2P:
+ if (mj2_read_jp2p(tk, cio))
+ return 1;
+ break;
+
+ case MJ2_JP2X:
+ if (mj2_read_jp2x(tk, cio))
+ return 1;
+ break;
+
+ case MJ2_JSUB:
+ if (mj2_read_jsub(tk, cio))
+ return 1;
+ break;
+
+ case MJ2_ORFO:
+ if (mj2_read_orfo(tk, cio))
+ return 1;
+ break;
+
+ default:
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
+ return 1;
+ break;
+
+ }
+ }
+ return 0;
+}
+
+
+/*
+* Write the STSD box
+*
+* Sample Description
+*
+*/
+void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STSD, 4); /* STSD */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
+
+ if (tk->track_type == 0) {
+ mj2_write_smj2(tk, cio);
+ } else if (tk->track_type == 1) {
+ /* Not implemented*/
+ }
+ if (tk->track_type == 2) {
+ /* Not implemented*/
+ }
+
+
+ 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);
+}
+
+/*
+* Read the STSD box
+*
+* Sample Description
+*
+*/
+int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
+{
+ int i;
+ int entry_count, len_2skip;
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+
+ if (MJ2_STSD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
+ return 1;
+ }
+
+ entry_count = cio_read(cio, 4);
+
+ if (tk->track_type == 0) {
+ for (i = 0; i < entry_count; i++) {
+ if (mj2_read_smj2(img, tk, cio))
+ return 1;
+ }
+ } else if (tk->track_type == 1) {
+ len_2skip = cio_read(cio, 4); /* Not implemented -> skipping box*/
+ cio_skip(cio,len_2skip - 4);
+ } else if (tk->track_type == 2) {
+ len_2skip = cio_read(cio, 4); /* Not implemented -> skipping box*/
+ cio_skip(cio,len_2skip - 4);
+ }
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the STBL box
+*
+* Sample table box box
+*
+*/
+void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_STBL, 4); /* STBL */
+
+ mj2_write_stsd(tk, cio);
+ mj2_write_stts(tk, cio);
+ mj2_write_stsc(tk, cio);
+ mj2_write_stsz(tk, cio);
+ mj2_write_stco(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the STBL box
+*
+* Sample table box box
+*
+*/
+int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_STBL != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
+ return 1;
+ }
+
+ if (mj2_read_stsd(tk, img, cio))
+ return 1;
+ if (mj2_read_stts(tk, cio))
+ return 1;
+ if (mj2_read_stsc(tk, cio))
+ return 1;
+ if (mj2_read_stsz(tk, cio))
+ return 1;
+ if (mj2_read_stco(tk, cio))
+ return 1;
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the URL box
+*
+* URL box
+*
+*/
+void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_URL, 4); /* URL */
+
+ if (url_num == 0)
+ cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
+ else {
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+ cio_write(cio, tk->url[url_num - 1].location[0], 4);
+ cio_write(cio, tk->url[url_num - 1].location[1], 4);
+ cio_write(cio, tk->url[url_num - 1].location[2], 4);
+ cio_write(cio, tk->url[url_num - 1].location[3], 4);
+ }
+
+ 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);
+}
+
+/*
+* Read the URL box
+*
+* URL box
+*
+*/
+int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_URL != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
+ return 1;
+ }
+
+ if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
+ tk->url[urn_num].location[0] = cio_read(cio, 4);
+ tk->url[urn_num].location[1] = cio_read(cio, 4);
+ tk->url[urn_num].location[2] = cio_read(cio, 4);
+ tk->url[urn_num].location[3] = cio_read(cio, 4);
+ } else {
+ tk->num_url--;
+ }
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the URN box
+*
+* URN box
+*
+*/
+void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_URN, 4); /* URN */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->urn[urn_num].name[0], 4);
+ cio_write(cio, tk->urn[urn_num].name[1], 4);
+ cio_write(cio, tk->urn[urn_num].name[2], 4);
+ cio_write(cio, tk->urn[urn_num].name[3], 4);
+ cio_write(cio, tk->urn[urn_num].location[0], 4);
+ cio_write(cio, tk->urn[urn_num].location[1], 4);
+ cio_write(cio, tk->urn[urn_num].location[2], 4);
+ cio_write(cio, tk->urn[urn_num].location[3], 4);
+
+ 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);
+}
+
+/*
+* Read the URN box
+*
+* URN box
+*
+*/
+int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
+{
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_URN != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
+ return 1;
+ }
+
+ if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
+ tk->urn[urn_num].name[0] = cio_read(cio, 4);
+ tk->urn[urn_num].name[1] = cio_read(cio, 4);
+ tk->urn[urn_num].name[2] = cio_read(cio, 4);
+ tk->urn[urn_num].name[3] = cio_read(cio, 4);
+ tk->urn[urn_num].location[0] = cio_read(cio, 4);
+ tk->urn[urn_num].location[1] = cio_read(cio, 4);
+ tk->urn[urn_num].location[2] = cio_read(cio, 4);
+ tk->urn[urn_num].location[3] = cio_read(cio, 4);
+ }
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+* Write the DREF box
+*
+* Data reference box
+*
+*/
+void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_DREF, 4); /* DREF */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
+ cio_write(cio, 1, 4); /* entry_count = 1 */
+ mj2_write_url(tk, 0, cio);
+ } else {
+ cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
+
+ for (i = 0; i < tk->num_url; i++)
+ mj2_write_url(tk, i + 1, cio);
+
+ for (i = 0; i < tk->num_urn; i++)
+ mj2_write_urn(tk, i, cio);
+ }
+
+ 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);
+}
+
+/*
+* Read the DREF box
+*
+* Data reference box
+*
+*/
+int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
+{
+
+ int i;
+ int entry_count, marker;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_DREF != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
+ return 1;
+ }
+
+ entry_count = cio_read(cio, 4);
+ tk->num_url = 0;
+ tk->num_urn = 0;
+
+ for (i = 0; i < entry_count; i++) {
+ cio_skip(cio,4);
+ marker = cio_read(cio, 4);
+ if (marker == MJ2_URL) {
+ cio_skip(cio,-8);
+ tk->num_url++;
+ if (mj2_read_url(tk, tk->num_url, cio))
+ return 1;
+ } else if (marker == MJ2_URN) {
+ cio_skip(cio,-8);
+ tk->num_urn++;
+ if (mj2_read_urn(tk, tk->num_urn, cio))
+ return 1;
+ } else {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
+ return 1;
+ }
+
+ }
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the DINF box
+*
+* Data information box
+*
+*/
+void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_DINF, 4); /* DINF */
+
+ mj2_write_dref(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the DINF box
+*
+* Data information box
+*
+*/
+int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_DINF != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
+ return 1;
+ }
+
+ if (mj2_read_dref(tk, cio))
+ return 1;
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the VMHD box
+*
+* Video Media information box
+*
+*/
+void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_VMHD, 4); /* VMHD */
+
+ cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
+
+ cio_write(cio, tk->graphicsmode, 2);
+ cio_write(cio, tk->opcolor[0], 2);
+ cio_write(cio, tk->opcolor[1], 2);
+ cio_write(cio, tk->opcolor[2], 2);
+
+ 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);
+}
+
+/*
+* Read the VMHD box
+*
+* Video Media information box
+*
+*/
+int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_VMHD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
+ return 1;
+ }
+
+ if (1 != cio_read(cio, 3)) { /* Flags = 1 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
+ return 1;
+ }
+
+ tk->track_type = 0;
+ tk->graphicsmode = cio_read(cio, 2);
+ tk->opcolor[0] = cio_read(cio, 2);
+ tk->opcolor[1] = cio_read(cio, 2);
+ tk->opcolor[2] = cio_read(cio, 2);
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the SMHD box
+*
+* Sound Media information box
+*
+*/
+void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_SMHD, 4); /* SMHD */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->balance, 2);
+
+ cio_write(cio, 0, 2); /* Reserved */
+
+ 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);
+}
+
+/*
+* Read the SMHD box
+*
+* Sound Media information box
+*
+*/
+int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_SMHD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
+ return 1;
+ }
+
+ tk->track_type = 1;
+ tk->balance = cio_read(cio, 2);
+
+ /* Init variables to zero to avoid problems when freeeing memory
+ The values will possibly be overidded when decoding the track structure */
+ tk->num_br = 0;
+ tk->num_url = 0;
+ tk->num_urn = 0;
+ tk->num_chunks = 0;
+ tk->num_tts = 0;
+ tk->num_samplestochunk = 0;
+ tk->num_samples = 0;
+
+ cio_skip(cio,2); /* Reserved */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the HMHD box
+*
+* Hint Media information box
+*
+*/
+void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_HMHD, 4); /* HMHD */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->maxPDUsize, 2);
+ cio_write(cio, tk->avgPDUsize, 2);
+ cio_write(cio, tk->maxbitrate, 4);
+ cio_write(cio, tk->avgbitrate, 4);
+ cio_write(cio, tk->slidingavgbitrate, 4);
+
+ 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);
+}
+
+/*
+* Read the HMHD box
+*
+* Hint Media information box
+*
+*/
+int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_HMHD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
+ return 1;
+ }
+
+ tk->track_type = 2;
+ tk->maxPDUsize = cio_read(cio, 2);
+ tk->avgPDUsize = cio_read(cio, 2);
+ tk->maxbitrate = cio_read(cio, 4);
+ tk->avgbitrate = cio_read(cio, 4);
+ tk->slidingavgbitrate = cio_read(cio, 4);
+
+ /* Init variables to zero to avoid problems when freeeing memory
+ The values will possibly be overidded when decoding the track structure */
+ tk->num_br = 0;
+ tk->num_url = 0;
+ tk->num_urn = 0;
+ tk->num_chunks = 0;
+ tk->num_tts = 0;
+ tk->num_samplestochunk = 0;
+ tk->num_samples = 0;
+
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the MINF box
+*
+* Media information box
+*
+*/
+void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MINF, 4); /* MINF */
+
+ if (tk->track_type == 0) {
+ mj2_write_vmhd(tk, cio);
+ } else if (tk->track_type == 1) {
+ mj2_write_smhd(tk, cio);
+ } else if (tk->track_type == 2) {
+ mj2_write_hmhd(tk, cio);
+ }
+
+ mj2_write_dinf(tk, cio);
+ mj2_write_stbl(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the MINF box
+*
+* Media information box
+*
+*/
+int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
+{
+
+ unsigned int box_type;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_MINF != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
+ return 1;
+ }
+
+ cio_skip(cio,4);
+ box_type = cio_read(cio, 4);
+ cio_skip(cio,-8);
+
+ if (box_type == MJ2_VMHD) {
+ if (mj2_read_vmhd(tk, cio))
+ return 1;
+ } else if (box_type == MJ2_SMHD) {
+ if (mj2_read_smhd(tk, cio))
+ return 1;
+ } else if (box_type == MJ2_HMHD) {
+ if (mj2_read_hmhd(tk, cio))
+ return 1;
+ } else {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
+ return 1;
+ }
+
+ if (mj2_read_dinf(tk, cio))
+ return 1;
+
+ if (mj2_read_stbl(tk, img, cio))
+ return 1;
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the HDLR box
+*
+* Handler reference box
+*
+*/
+void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_HDLR, 4); /* HDLR */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, 0, 4); /* Predefine */
+
+ tk->name = 0; /* The track name is immediately determined by the track type */
+
+ if (tk->track_type == 0) {
+ tk->handler_type = 0x76696465; /* Handler type: vide */
+ cio_write(cio, tk->handler_type, 4);
+
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, 0x76696465, 4);
+ cio_write(cio, 0x6F206d65, 4);
+ cio_write(cio, 0x64696120, 4);
+ cio_write(cio, 0x74726163, 4);
+ cio_write(cio, 0x6b00, 2); /* String: video media track */
+ } else if (tk->track_type == 1) {
+ tk->handler_type = 0x736F756E; /* Handler type: soun */
+ cio_write(cio, tk->handler_type, 4);
+
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, 0x536F756E, 4);
+ cio_write(cio, 0x6400, 2); /* String: Sound */
+ } else if (tk->track_type == 2) {
+ tk->handler_type = 0x68696E74; /* Handler type: hint */
+ cio_write(cio, tk->handler_type, 4);
+
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4);
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, 0x48696E74, 4);
+ cio_write(cio, 0, 2); /* String: Hint */
+ }
+
+ 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);
+}
+
+/*
+* Read the HDLR box
+*
+* Handler reference box
+*
+*/
+int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_HDLR != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
+ return 1;
+ }
+
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
+ return 1;
+ }
+
+ cio_skip(cio,4); /* Reserved */
+
+ tk->handler_type = cio_read(cio, 4);
+ cio_skip(cio,12); /* Reserved */
+
+ tk->name_size = box.length - 32;
+
+ tk->name = (char*) opj_malloc(tk->name_size * sizeof(char));
+ for (i = 0; i < tk->name_size; i++) {
+ tk->name[i] = cio_read(cio, 1); /* Name */
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the MDHD box
+*
+* Media Header Box
+*
+*/
+void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+ unsigned int i;
+ time_t ltime;
+ unsigned int modification_time;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MDHD, 4); /* MDHD */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ cio_write(cio, tk->creation_time, 4); /* Creation Time */
+
+ time(&ltime); /* Time since 1/1/70 */
+ modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
+
+ cio_write(cio, modification_time, 4); /* Modification Time */
+
+ cio_write(cio, tk->timescale, 4); /* Timescale */
+
+ tk->duration = 0;
+
+ for (i = 0; i < tk->num_samples; i++)
+ tk->duration += tk->sample[i].sample_delta;
+
+ cio_write(cio, tk->duration, 4); /* Duration */
+
+ cio_write(cio, tk->language, 2); /* Language */
+
+ cio_write(cio, 0, 2); /* Predefined */
+
+ 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);
+}
+
+/*
+* Read the MDHD box
+*
+* Media Header Box
+*
+*/
+int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { /* Kakadu writes MHDR instead of MDHD*/
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 3)) { /* Flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
+ return 1;
+ }
+
+
+ tk->creation_time = cio_read(cio, 4); /* Creation Time */
+
+ tk->modification_time = cio_read(cio, 4); /* Modification Time */
+
+ tk->timescale = cio_read(cio, 4); /* Timescale */
+
+ tk->duration = cio_read(cio, 4); /* Duration */
+
+ tk->language = cio_read(cio, 2); /* Language */
+
+ cio_skip(cio,2); /* Predefined */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the MDIA box
+*
+* Media box
+*
+*/
+void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MDIA, 4); /* MDIA */
+
+ mj2_write_mdhd(tk, cio);
+ mj2_write_hdlr(tk, cio);
+ mj2_write_minf(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the MDIA box
+*
+* Media box
+*
+*/
+int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_MDIA != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
+ return 1;
+ }
+
+ if (mj2_read_mdhd(tk, cio))
+ return 1;
+ if (mj2_read_hdlr(tk, cio))
+ return 1;
+ if (mj2_read_minf(tk, img, cio))
+ return 1;
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the TKHD box
+*
+* Track Header box
+*
+*/
+void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+ unsigned int i;
+ time_t ltime;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+
+ cio_write(cio, MJ2_TKHD, 4); /* TKHD */
+
+ cio_write(cio, 3, 4); /* Version=0, flags=3 */
+
+ time(&ltime); /* Time since 1/1/70 */
+ tk->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
+
+ cio_write(cio, tk->creation_time, 4); /* Creation Time */
+
+ cio_write(cio, tk->modification_time, 4); /* Modification Time */
+
+ cio_write(cio, tk->track_ID, 4); /* Track ID */
+
+ cio_write(cio, 0, 4); /* Reserved */
+
+ tk->duration = 0;
+
+ for (i = 0; i < tk->num_samples; i++)
+ tk->duration += tk->sample[i].sample_delta;
+
+ cio_write(cio, tk->duration, 4); /* Duration */
+
+ cio_write(cio, 0, 4); /* Reserved */
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, tk->layer, 2); /* Layer */
+
+ cio_write(cio, 0, 2); /* Predefined */
+
+ cio_write(cio, tk->volume, 2); /* Volume */
+
+ cio_write(cio, 0, 2); /* Reserved */
+
+ cio_write(cio, tk->trans_matrix[0], 4); /* Transformation matrix for track */
+ cio_write(cio, tk->trans_matrix[1], 4);
+ cio_write(cio, tk->trans_matrix[2], 4);
+ cio_write(cio, tk->trans_matrix[3], 4);
+ cio_write(cio, tk->trans_matrix[4], 4);
+ cio_write(cio, tk->trans_matrix[5], 4);
+ cio_write(cio, tk->trans_matrix[6], 4);
+ cio_write(cio, tk->trans_matrix[7], 4);
+ cio_write(cio, tk->trans_matrix[8], 4);
+
+ cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
+
+ cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
+
+ 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);
+}
+
+/*
+* Read the TKHD box
+*
+* Track Header box
+*
+*/
+int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ int flag;
+
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+
+ if (MJ2_TKHD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
+ return 1;
+ }
+
+ if (0 != cio_read(cio, 1)) { /* Version = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
+ return 1;
+ }
+
+ flag = cio_read(cio, 3);
+
+ if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
+ opj_event_msg(cio->cinfo, EVT_ERROR,
+ "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
+ return 1;
+ }
+
+ tk->creation_time = cio_read(cio, 4); /* Creation Time */
+
+ tk->modification_time = cio_read(cio, 4); /* Modification Time */
+
+ tk->track_ID = cio_read(cio, 4); /* Track ID */
+
+ cio_skip(cio,4); /* Reserved */
+
+ tk->duration = cio_read(cio, 4); /* Duration */
+
+ cio_skip(cio,8); /* Reserved */
+
+ tk->layer = cio_read(cio, 2); /* Layer */
+
+ cio_read(cio, 2); /* Predefined */
+
+ tk->volume = cio_read(cio, 2); /* Volume */
+
+ cio_skip(cio,2); /* Reserved */
+
+ tk->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for track */
+ tk->trans_matrix[1] = cio_read(cio, 4);
+ tk->trans_matrix[2] = cio_read(cio, 4);
+ tk->trans_matrix[3] = cio_read(cio, 4);
+ tk->trans_matrix[4] = cio_read(cio, 4);
+ tk->trans_matrix[5] = cio_read(cio, 4);
+ tk->trans_matrix[6] = cio_read(cio, 4);
+ tk->trans_matrix[7] = cio_read(cio, 4);
+ tk->trans_matrix[8] = cio_read(cio, 4);
+
+ tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
+
+ tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the TRAK box
+*
+* Track box
+*
+*/
+void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+
+ cio_write(cio, MJ2_TRAK, 4); /* TRAK */
+
+ mj2_write_tkhd(tk, cio);
+ mj2_write_mdia(tk, cio);
+
+ 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);
+}
+
+/*
+* Read the TRAK box
+*
+* Track box
+*
+*/
+int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_TRAK != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
+ return 1;
+ }
+ if (mj2_read_tkhd(tk, cio))
+ return 1;
+ if (mj2_read_mdia(tk, img, cio))
+ return 1;
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+* Write the MVHD box
+*
+* Movie header Box
+*
+*/
+void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+ unsigned j;
+ time_t ltime;
+ int max_tk_num = 0;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MVHD, 4); /* MVHD */
+
+ cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
+
+ time(&ltime); /* Time since 1/1/70 */
+ movie->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
+
+ cio_write(cio, movie->creation_time, 4); /* Creation Time */
+
+ cio_write(cio, movie->modification_time, 4); /* Modification Time */
+
+ cio_write(cio, movie->timescale, 4); /* Timescale */
+
+ movie->duration = 0;
+
+ for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
+ mj2_tk_t *tk = &movie->tk[i];
+
+ for (j = 0; j < tk->num_samples; j++) {
+ movie->duration += tk->sample[j].sample_delta;
+ }
+ }
+
+ cio_write(cio, movie->duration, 4);
+
+ cio_write(cio, movie->rate, 4); /* Rate to play presentation */
+
+ cio_write(cio, movie->volume, 2); /* Volume */
+
+ cio_write(cio, 0, 2); /* Reserved */
+ cio_write(cio, 0, 4); /* Reserved */
+ cio_write(cio, 0, 4); /* Reserved */
+
+ cio_write(cio, movie->trans_matrix[0], 4); /* Transformation matrix for video */
+ cio_write(cio, movie->trans_matrix[1], 4);
+ cio_write(cio, movie->trans_matrix[2], 4);
+ cio_write(cio, movie->trans_matrix[3], 4);
+ cio_write(cio, movie->trans_matrix[4], 4);
+ cio_write(cio, movie->trans_matrix[5], 4);
+ cio_write(cio, movie->trans_matrix[6], 4);
+ cio_write(cio, movie->trans_matrix[7], 4);
+ cio_write(cio, movie->trans_matrix[8], 4);
+
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+ cio_write(cio, 0, 4); /* Pre-defined */
+
+
+ for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
+ if (max_tk_num < movie->tk[i].track_ID)
+ max_tk_num = movie->tk[i].track_ID;
+ }
+
+ movie->next_tk_id = max_tk_num + 1;
+
+ cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
+
+ 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);
+}
+
+/*
+* Read the MVHD box
+*
+* Movie header Box
+*
+*/
+int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
+{
+ mj2_box_t box;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_MVHD != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
+ return 1;
+ }
+
+
+ if (0 != cio_read(cio, 4)) { /* Version = 0, flags = 0 */
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
+ }
+
+ movie->creation_time = cio_read(cio, 4); /* Creation Time */
+
+ movie->modification_time = cio_read(cio, 4); /* Modification Time */
+
+ movie->timescale = cio_read(cio, 4); /* Timescale */
+
+ movie->duration = cio_read(cio, 4); /* Duration */
+
+ movie->rate = cio_read(cio, 4); /* Rate to play presentation */
+
+ movie->volume = cio_read(cio, 2); /* Volume */
+
+ cio_skip(cio,10); /* Reserved */
+
+ movie->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for video */
+ movie->trans_matrix[1] = cio_read(cio, 4);
+ movie->trans_matrix[2] = cio_read(cio, 4);
+ movie->trans_matrix[3] = cio_read(cio, 4);
+ movie->trans_matrix[4] = cio_read(cio, 4);
+ movie->trans_matrix[5] = cio_read(cio, 4);
+ movie->trans_matrix[6] = cio_read(cio, 4);
+ movie->trans_matrix[7] = cio_read(cio, 4);
+ movie->trans_matrix[8] = cio_read(cio, 4);
+
+ cio_skip(cio,24); /* Pre-defined */
+
+ movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+* Write the MOOV box
+*
+* Movie Box
+*
+*/
+void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
+{
+ int i;
+ mj2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio,4);
+ cio_write(cio, MJ2_MOOV, 4); /* MOOV */
+
+ mj2_write_mvhd(movie, cio);
+
+ for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
+ mj2_write_trak(&movie->tk[i], cio);
+ }
+
+ 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);
+}
+
+/*
+* Read the MOOV box
+*
+* Movie Box
+*
+*/
+int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
+{
+ unsigned int i;
+ mj2_box_t box;
+ mj2_box_t box2;
+
+ mj2_read_boxhdr(&box, cio);
+ if (MJ2_MOOV != box.type) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
+ return 1;
+ }
+
+ if (mj2_read_mvhd(movie, cio))
+ return 1;
+
+ movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
+
+ for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
+ mj2_tk_t *tk = &movie->tk[i];
+ tk->cinfo = movie->cinfo;
+ mj2_read_boxhdr(&box2, cio);
+ if (box2.type == MJ2_TRAK) {
+ cio_seek(cio, box2.init_pos);
+ if (mj2_read_trak(tk, img, cio))
+ return 1;
+
+ if (tk->track_type == 0) {
+ movie->num_vtk++;
+ } else if (tk->track_type == 1) {
+ movie->num_stk++;
+ } else if (tk->track_type == 2) {
+ movie->num_htk++;
+ }
+ } else if (box2.type == MJ2_MVEX) {
+ cio_seek(cio, box2.init_pos);
+ cio_skip(cio,box2.length);
+ i--;
+ } else {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
+ mj2_box_t box;
+ opj_image_t img;
+ unsigned char * src;
+ int fsresult;
+ int foffset;
+ opj_cio_t *cio;
+
+ /* open a byte stream for reading */
+ src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char));
+
+ /* Assuming that jp and ftyp markers size do
+ not exceed 300 bytes */
+ fread(src,300,1, file);
+
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
+
+ if (mj2_read_jp(cio))
+ return 1;
+ if (mj2_read_ftyp(movie, cio))
+ return 1;
+
+ fsresult = fseek(file,cio_tell(cio),SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
+ return 1;
+ }
+
+ foffset = cio_tell(cio);
+
+ box.type = 0;
+
+ fread(src,30,1,file);
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
+ mj2_read_boxhdr(&box, cio);
+
+ while(box.type != MJ2_MOOV) {
+
+ switch(box.type)
+ {
+ case MJ2_MDAT:
+ fsresult = fseek(file,foffset+box.length,SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
+ return 1;
+ }
+ foffset += box.length;
+ break;
+
+ case MJ2_MOOF:
+ fsresult = fseek(file,foffset+box.length,SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
+ return 1;
+ }
+ foffset += box.length;
+ break;
+ case MJ2_FREE:
+ fsresult = fseek(file,foffset+box.length,SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
+ return 1;
+ }
+ foffset += box.length;
+ break;
+ case MJ2_SKIP:
+ fsresult = fseek(file,foffset+box.length,SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
+ return 1;
+ }
+ foffset += box.length;
+ break;
+ default:
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
+ fsresult = fseek(file,foffset+box.length,SEEK_SET);
+ if( fsresult ) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
+ return 1;
+ }
+ foffset += box.length;
+ break;
+ }
+ fsresult = fread(src,8,1,file);
+ if (fsresult != 1) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n");
+ return 1;
+ }
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
+ mj2_read_boxhdr(&box, cio);
+ }
+
+ fseek(file,foffset,SEEK_SET);
+ src = (unsigned char*)opj_realloc(src,box.length);
+ fsresult = fread(src,box.length,1,file);
+ if (fsresult != 1) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n");
+ return 1;
+ }
+
+ cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
+
+ if (mj2_read_moov(movie, &img, cio))
+ return 1;
+
+ opj_free(src);
+ return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/* MJ2 decoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_dinfo_t* mj2_create_decompress() {
+ opj_mj2_t* mj2;
+ opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
+ if(!dinfo) return NULL;
+
+ dinfo->is_decompressor = OPJ_TRUE;
+
+ mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
+ dinfo->mj2_handle = mj2;
+ if(mj2) {
+ mj2->cinfo = (opj_common_ptr)dinfo;
+ }
+ mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
+ dinfo->j2k_handle = mj2->j2k;
+
+ return dinfo;
+}
+
+void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
+ movie->num_vtk=0;
+ movie->num_stk=0;
+ movie->num_htk=0;
+
+ /* setup the J2K decoder parameters */
+ j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle,
+ &mj2_parameters->j2k_parameters);
+
+}
+
+void mj2_destroy_decompress(opj_mj2_t *movie) {
+ if(movie) {
+ int i;
+ mj2_tk_t *tk=NULL;
+
+ if (movie->cinfo->j2k_handle)
+ j2k_destroy_compress(movie->j2k);
+
+ if (movie->num_cl != 0)
+ opj_free(movie->cl);
+
+ for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
+ tk = &movie->tk[i];
+ if (tk->name_size != 0)
+ opj_free(tk->name);
+ if (tk->track_type == 0) {/* Video track*/
+ if (tk->jp2_struct.comps != NULL)
+ opj_free(tk->jp2_struct.comps);
+ if (tk->jp2_struct.cl != NULL)
+ opj_free(tk->jp2_struct.cl);
+ if (tk->num_jp2x != 0)
+ opj_free(tk->jp2xdata);
+
+ }
+ if (tk->num_url != 0)
+ opj_free(tk->url);
+ if (tk->num_urn != 0)
+ opj_free(tk->urn);
+ if (tk->num_br != 0)
+ opj_free(tk->br);
+ if (tk->num_tts != 0)
+ opj_free(tk->tts);
+ if (tk->num_chunks != 0)
+ opj_free(tk->chunk);
+ if (tk->num_samplestochunk != 0)
+ opj_free(tk->sampletochunk);
+ if (tk->num_samples != 0)
+ opj_free(tk->sample);
+ }
+
+ opj_free(movie->tk);
+ }
+ opj_free(movie);
+}
+
+/* ----------------------------------------------------------------------- */
+/* MJ2 encoder interface */
+/* ----------------------------------------------------------------------- */
+
+
+opj_cinfo_t* mj2_create_compress() {
+ opj_mj2_t* mj2;
+ opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
+ if(!cinfo) return NULL;
+
+ mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
+ cinfo->mj2_handle = mj2;
+ if(mj2) {
+ mj2->cinfo = (opj_common_ptr)cinfo;
+ }
+
+ mj2->j2k = j2k_create_compress(mj2->cinfo);
+ cinfo->j2k_handle = mj2->j2k;
+
+ return cinfo;
+}
+
+void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
+ if(movie && parameters) {
+ opj_jp2_t *jp2_struct;
+
+ movie->num_htk = 0; /* No hint tracks*/
+ movie->num_stk = 0; /* No sound tracks*/
+ movie->num_vtk = 1; /* One video track*/
+
+ movie->brand = MJ2_MJ2; /* One brand: MJ2*/
+ movie->num_cl = 2; /* Two compatible brands: MJ2 and MJ2S*/
+ movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
+ movie->cl[0] = MJ2_MJ2;
+ movie->cl[1] = MJ2_MJ2S;
+ movie->minversion = 0; /* Minimum version: 0 */
+
+ movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); /*Memory allocation for the video track*/
+ movie->tk[0].track_ID = 1; /* Track ID = 1 */
+ movie->tk[0].track_type = 0; /* Video track */
+ movie->tk[0].Dim[0] = parameters->Dim[0];
+ movie->tk[0].Dim[1] = parameters->Dim[1];
+ movie->tk[0].w = parameters->w;
+ movie->tk[0].h = parameters->h;
+ movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
+ movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
+ movie->tk[0].sample_rate = parameters->frame_rate;
+ movie->tk[0].name_size = 0;
+ movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));
+ movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
+ movie->tk[0].depth = parameters->prec;
+
+ jp2_struct = &movie->tk[0].jp2_struct;
+ jp2_struct->numcomps = parameters->numcomps; /* NC */
+ jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
+ jp2_struct->precedence = 0; /* PRECEDENCE*/
+ jp2_struct->approx = 0; /* APPROX*/
+ jp2_struct->brand = JP2_JP2; /* BR */
+ jp2_struct->minversion = 0; /* MinV */
+ jp2_struct->numcl = 1;
+ jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
+ jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
+ jp2_struct->C = 7; /* C : Always 7*/
+ jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
+ jp2_struct->IPR = 0; /* IPR, no intellectual property*/
+ jp2_struct->w = parameters->w;
+ jp2_struct->h = parameters->h;
+ jp2_struct->bpc = 7;
+ jp2_struct->meth = parameters->meth;
+ jp2_struct->enumcs = parameters->enumcs;
+ }
+}
+
+void mj2_destroy_compress(opj_mj2_t *movie) {
+ if(movie) {
+ int i;
+ mj2_tk_t *tk=NULL;
+
+ if (movie->cinfo->j2k_handle) {
+ j2k_destroy_compress(movie->j2k);
+ }
+
+ if (movie->num_cl != 0)
+ opj_free(movie->cl);
+
+ for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
+ tk = &movie->tk[i];
+ if (tk->name_size != 0)
+ opj_free(tk->name);
+ if (tk->track_type == 0) {/* Video track*/
+ if (tk->jp2_struct.comps != NULL)
+ opj_free(tk->jp2_struct.comps);
+ if (tk->jp2_struct.cl != NULL)
+ opj_free(tk->jp2_struct.cl);
+ if (tk->num_jp2x != 0)
+ opj_free(tk->jp2xdata);
+
+ }
+ if (tk->num_url != 0)
+ opj_free(tk->url);
+ if (tk->num_urn != 0)
+ opj_free(tk->urn);
+ if (tk->num_br != 0)
+ opj_free(tk->br);
+ if (tk->num_tts != 0)
+ opj_free(tk->tts);
+ if (tk->num_chunks != 0)
+ opj_free(tk->chunk);
+ if (tk->num_samplestochunk != 0)
+ opj_free(tk->sampletochunk);
+ if (tk->num_samples != 0)
+ opj_free(tk->sample);
+ }
+
+ opj_free(movie->tk);
+ }
+ opj_free(movie);
+}
diff --git a/src/bin/mj2/mj2.h b/src/bin/mj2/mj2.h
new file mode 100644
index 00000000..c0255707
--- /dev/null
+++ b/src/bin/mj2/mj2.h
@@ -0,0 +1,393 @@
+/*
+* Copyright (c) 2003-2004, Francois-Olivier Devaux
+* Copyright (c) 2003-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+* 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 __MJ2_H
+#define __MJ2_H
+/**
+@file mj2.h
+@brief The Motion JPEG 2000 file format Reader/Writer (MJ22)
+
+*/
+
+/** @defgroup MJ2 MJ2 - Motion JPEG 2000 file format reader/writer */
+/*@{*/
+
+#define MJ2_JP 0x6a502020
+#define MJ2_FTYP 0x66747970
+#define MJ2_MJ2 0x6d6a7032
+#define MJ2_MJ2S 0x6d6a3273
+#define MJ2_MDAT 0x6d646174
+#define MJ2_MOOV 0x6d6f6f76
+#define MJ2_MVHD 0x6d766864
+#define MJ2_TRAK 0x7472616b
+#define MJ2_TKHD 0x746b6864
+#define MJ2_MDIA 0x6d646961
+#define MJ2_MDHD 0x6d646864
+#define MJ2_MHDR 0x6d686472
+#define MJ2_HDLR 0x68646C72
+#define MJ2_MINF 0x6d696e66
+#define MJ2_VMHD 0x766d6864
+#define MJ2_SMHD 0x736d6864
+#define MJ2_HMHD 0x686d6864
+#define MJ2_DINF 0x64696e66
+#define MJ2_DREF 0x64726566
+#define MJ2_URL 0x75726c20
+#define MJ2_URN 0x75726e20
+#define MJ2_STBL 0x7374626c
+#define MJ2_STSD 0x73747364
+#define MJ2_STTS 0x73747473
+#define MJ2_STSC 0x73747363
+#define MJ2_STSZ 0x7374737a
+#define MJ2_STCO 0x7374636f
+#define MJ2_MOOF 0x6d6f6f66
+#define MJ2_FREE 0x66726565
+#define MJ2_SKIP 0x736b6970
+#define MJ2_JP2C 0x6a703263
+#define MJ2_FIEL 0x6669656c
+#define MJ2_JP2P 0x6a703270
+#define MJ2_JP2X 0x6a703278
+#define MJ2_JSUB 0x6a737562
+#define MJ2_ORFO 0x6f72666f
+#define MJ2_MVEX 0x6d766578
+#define MJ2_JP2 0x6a703220
+#define MJ2_J2P0 0x4a325030
+
+/**
+Decompressed format used in parameters
+YUV = 0
+*/
+#define YUV_DFMT 1
+
+/**
+Compressed format used in parameters
+MJ2 = 0
+*/
+#define MJ2_CFMT 2
+
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Time To Sample
+*/
+typedef struct mj2_tts {
+ int sample_count;
+ int sample_delta;
+} mj2_tts_t;
+
+/**
+Chunk
+*/
+typedef struct mj2_chunk {
+ unsigned int num_samples;
+ int sample_descr_idx;
+ int offset;
+} mj2_chunk_t;
+
+/**
+Sample to chunk
+*/
+typedef struct mj2_sampletochunk {
+ unsigned int first_chunk;
+ unsigned int samples_per_chunk;
+ int sample_descr_idx;
+} mj2_sampletochunk_t;
+
+/**
+Sample
+*/
+typedef struct mj2_sample {
+ unsigned int sample_size;
+ unsigned int offset;
+ unsigned int sample_delta;
+} mj2_sample_t;
+
+/**
+URL
+*/
+typedef struct mj2_url {
+ int location[4];
+} mj2_url_t;
+
+/**
+URN
+*/
+typedef struct mj2_urn {
+ int name[2];
+ int location[4];
+} mj2_urn_t;
+
+/**
+Video Track Parameters
+*/
+typedef struct mj2_tk {
+ /** codec context */
+ opj_common_ptr cinfo;
+ int track_ID;
+ int track_type;
+ unsigned int creation_time;
+ unsigned int modification_time;
+ int duration;
+ int timescale;
+ int layer;
+ int volume;
+ int language;
+ int balance;
+ int maxPDUsize;
+ int avgPDUsize;
+ int maxbitrate;
+ int avgbitrate;
+ int slidingavgbitrate;
+ int graphicsmode;
+ int opcolor[3];
+ int num_url;
+ mj2_url_t *url;
+ int num_urn;
+ mj2_urn_t *urn;
+ int Dim[2];
+ int w;
+ int h;
+ int visual_w;
+ int visual_h;
+ int CbCr_subsampling_dx;
+ int CbCr_subsampling_dy;
+ int sample_rate;
+ int sample_description;
+ int horizresolution;
+ int vertresolution;
+ int compressorname[8];
+ int depth;
+ unsigned char fieldcount;
+ unsigned char fieldorder;
+ unsigned char or_fieldcount;
+ unsigned char or_fieldorder;
+ int num_br;
+ unsigned int *br;
+ unsigned char num_jp2x;
+ unsigned char *jp2xdata;
+ unsigned char hsub;
+ unsigned char vsub;
+ unsigned char hoff;
+ unsigned char voff;
+ int trans_matrix[9];
+ /** Number of samples */
+ unsigned int num_samples;
+ int transorm;
+ int handler_type;
+ int name_size;
+ unsigned char same_sample_size;
+ int num_tts;
+ /** Time to sample */
+ mj2_tts_t *tts;
+ unsigned int num_chunks;
+ mj2_chunk_t *chunk;
+ unsigned int num_samplestochunk;
+ mj2_sampletochunk_t *sampletochunk;
+ char *name;
+ opj_jp2_t jp2_struct;
+ /** Sample parameters */
+ mj2_sample_t *sample;
+} mj2_tk_t;
+
+/**
+MJ2 box
+*/
+typedef struct mj2_box {
+ int length;
+ int type;
+ int init_pos;
+} mj2_box_t;
+
+/**
+MJ2 Movie
+*/
+typedef struct opj_mj2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+ /** handle to the J2K codec */
+ opj_j2k_t *j2k;
+ unsigned int brand;
+ unsigned int minversion;
+ int num_cl;
+ unsigned int *cl;
+ unsigned int creation_time;
+ unsigned int modification_time;
+ int timescale;
+ unsigned int duration;
+ int rate;
+ int num_vtk;
+ int num_stk;
+ int num_htk;
+ int volume;
+ int trans_matrix[9];
+ int next_tk_id;
+ /** Track Parameters */
+ mj2_tk_t *tk;
+} opj_mj2_t;
+
+/**
+Decompression parameters
+*/
+typedef struct mj2_dparameters {
+ /**@name command line encoder parameters (not used inside the library) */
+ /*@{*/
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** J2K decompression parameters */
+ opj_dparameters_t j2k_parameters;
+} mj2_dparameters_t;
+
+/**
+Compression parameters
+*/
+typedef struct mj2_cparameters {
+ /**@name command line encoder parameters (not used inside the library) */
+ /*@{*/
+ /** J2K compression parameters */
+ opj_cparameters_t j2k_parameters;
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** input file format 0:MJ2 */
+ int decod_format;
+ /** output file format 0:YUV */
+ int cod_format;
+ /** Portion of the image coded */
+ int Dim[2];
+ /** YUV Frame width */
+ int w;
+ /** YUV Frame height */
+ int h;
+ /* Sample rate of YUV 4:4:4, 4:2:2 or 4:2:0 */
+ int CbCr_subsampling_dx;
+ /* Sample rate of YUV 4:4:4, 4:2:2 or 4:2:0 */
+ int CbCr_subsampling_dy;
+ /* Video Frame Rate */
+ int frame_rate;
+ /* In YUV files, numcomps always considered as 3 */
+ int numcomps;
+ /* In YUV files, precision always considered as 8 */
+ int prec;
+ unsigned int meth;
+ unsigned int enumcs;
+} mj2_cparameters_t;
+
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Write the JP box
+*/
+void mj2_write_jp(opj_cio_t *cio);
+/**
+Write the FTYP box
+@param movie MJ2 movie
+@param cio Output buffer stream
+*/
+void mj2_write_ftyp(opj_mj2_t *movie, opj_cio_t *cio);
+/**
+Creates an MJ2 decompression structure
+@return Returns a handle to a MJ2 decompressor if successful, returns NULL otherwise
+*/
+opj_dinfo_t* mj2_create_decompress();
+/**
+Destroy a MJ2 decompressor handle
+@param movie MJ2 decompressor handle to destroy
+*/
+void mj2_destroy_decompress(opj_mj2_t *movie);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in mj2->j2k->cp.
+@param movie MJ2 decompressor handle
+@param parameters decompression parameters
+*/
+void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters);
+/**
+Decode an image from a JPEG-2000 file stream
+@param movie MJ2 decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* mj2_decode(opj_mj2_t *movie, opj_cio_t *cio);
+/**
+Creates a MJ2 compression structure
+@return Returns a handle to a MJ2 compressor if successful, returns NULL otherwise
+*/
+opj_cinfo_t* mj2_create_compress();
+/**
+Destroy a MJ2 compressor handle
+@param movie MJ2 compressor handle to destroy
+*/
+void mj2_destroy_compress(opj_mj2_t *movie);
+/**
+Setup the encoder parameters using the current image and using user parameters.
+Coding parameters are returned in mj2->j2k->cp.
+@param movie MJ2 compressor handle
+@param parameters compression parameters
+*/
+void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters);
+/**
+Encode an image into a JPEG-2000 file stream
+@param movie MJ2 compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Name of the index file if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+opj_bool mj2_encode(opj_mj2_t *movie, opj_cio_t *cio, opj_image_t *image, char *index);
+
+/**
+Init a Standard MJ2 movie
+@param movie MJ2 Movie
+@return Returns 0 if successful, returns 1 otherwise
+*/
+int mj2_init_stdmovie(opj_mj2_t *movie);
+/**
+Read the structure of an MJ2 file
+@param File MJ2 input File
+@param movie J2 movie structure
+@return Returns 0 if successful, returns 1 otherwise
+*/
+int mj2_read_struct(FILE *file, opj_mj2_t *mj2);
+/**
+Write the the MOOV box to an output buffer stream
+@param movie MJ2 movie structure
+@param cio Output buffer stream
+*/
+void mj2_write_moov(opj_mj2_t *movie, opj_cio_t *cio);
+
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MJ2_H */
diff --git a/src/bin/mj2/mj2_convert.c b/src/bin/mj2/mj2_convert.c
new file mode 100644
index 00000000..ed823f8b
--- /dev/null
+++ b/src/bin/mj2/mj2_convert.c
@@ -0,0 +1,372 @@
+/*
+* 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
+* 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 "mj2.h"
+
+/* ----------------------- */
+/* */
+/* */
+/* Count the number of frames */
+/* in a YUV file */
+/* */
+/* ----------------------- */
+
+unsigned int yuv_num_frames(mj2_tk_t * tk, char *infile)
+{
+ unsigned int prec_size;
+ long end_of_f, frame_size;
+ FILE *f;
+
+ f = fopen(infile,"rb");
+ if (!f) {
+ fprintf(stderr, "failed to open %s for reading\n",infile);
+ return 0;
+ }
+ prec_size = (tk->depth + 7)/8;/* bytes of precision */
+
+ frame_size = (long) (tk->w * tk->h * (1.0 + (double) 2 / (double) (tk->CbCr_subsampling_dx * tk->CbCr_subsampling_dy))); /* Calculate frame size */
+ frame_size *= prec_size;
+
+ fseek(f, 0, SEEK_END);
+ end_of_f = ftell(f); /* Calculate file size */
+
+ if (end_of_f < frame_size) {
+ fprintf(stderr,
+ "YUV does not contains any frame of %d x %d size\n", tk->w,
+ tk->h);
+ return 0;
+ }
+ fclose(f);
+
+ return (unsigned int)(end_of_f / frame_size);
+}
+
+/* ----------------------- */
+/* */
+/* */
+/* YUV to IMAGE */
+/* */
+/* ----------------------- */
+
+opj_image_t *mj2_image_create(mj2_tk_t * tk, opj_cparameters_t *parameters)
+{
+ opj_image_cmptparm_t cmptparm[3];
+ opj_image_t * img;
+ int i;
+ int numcomps = 3;
+ int subsampling_dx = parameters->subsampling_dx;
+ int subsampling_dy = parameters->subsampling_dy;
+
+ /* initialize image components */
+ memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
+ for(i = 0; i < numcomps; i++) {
+ cmptparm[i].prec = tk->depth;
+ cmptparm[i].bpp = tk->depth;
+ cmptparm[i].sgnd = 0;
+ cmptparm[i].dx = i ? subsampling_dx * tk->CbCr_subsampling_dx : subsampling_dx;
+ cmptparm[i].dy = i ? subsampling_dy * tk->CbCr_subsampling_dy : subsampling_dy;
+ cmptparm[i].w = tk->w;
+ cmptparm[i].h = tk->h;
+ }
+ /* create the image */
+ img = opj_image_create(numcomps, cmptparm, CLRSPC_SRGB);
+ return img;
+}
+
+char yuvtoimage(mj2_tk_t * tk, opj_image_t * img, int frame_num, opj_cparameters_t *parameters, char* infile)
+{
+ int i, compno;
+ int offset, size, max, prec_bytes, is_16, v;
+ long end_of_f, position;
+ int numcomps = 3;
+ int subsampling_dx = parameters->subsampling_dx;
+ int subsampling_dy = parameters->subsampling_dy;
+ FILE *yuvfile;
+ int *data;
+ unsigned char uc;
+
+ yuvfile = fopen(infile,"rb");
+ if (!yuvfile) {
+ fprintf(stderr, "failed to open %s for readings\n",parameters->infile);
+ return 1;
+ }
+ is_16 = (tk->depth > 8);
+ prec_bytes = (is_16?2:1);
+
+ offset = (int) ((double) (frame_num * tk->w * tk->h) * (1.0 +
+ 1.0 * (double) 2 / (double) (tk->CbCr_subsampling_dx * tk->CbCr_subsampling_dy)));
+ offset *= prec_bytes;
+
+ fseek(yuvfile, 0, SEEK_END);
+ end_of_f = ftell(yuvfile);
+ fseek(yuvfile, sizeof(unsigned char) * offset, SEEK_SET);
+ position = ftell(yuvfile);
+ if (position >= end_of_f) {
+ fprintf(stderr, "Cannot reach frame number %d in yuv file !!\n",
+ frame_num);
+ fclose(yuvfile);
+ return 1;
+ }
+
+ img->x0 = tk->Dim[0];
+ img->y0 = tk->Dim[1];
+ img->x1 = !tk->Dim[0] ? (tk->w - 1) * subsampling_dx + 1 : tk->Dim[0] +
+ (tk->w - 1) * subsampling_dx + 1;
+ img->y1 = !tk->Dim[1] ? (tk->h - 1) * subsampling_dy + 1 : tk->Dim[1] +
+ (tk->h - 1) * subsampling_dy + 1;
+
+ size = tk->w * tk->h * prec_bytes;
+
+ for(compno = 0; compno < numcomps; compno++)
+ {
+ max = size/(img->comps[compno].dx * img->comps[compno].dy);
+ data = img->comps[compno].data;
+
+ for (i = 0; i < max && !feof(yuvfile); i++)
+ {
+ v = 0;
+ fread(&uc, 1, 1, yuvfile);
+ v = uc;
+
+ if(is_16)
+ {
+ fread(&uc, 1, 1, yuvfile);
+ v |= (uc<<8);
+ }
+ *data++ = v;
+ }
+ }
+ fclose(yuvfile);
+
+ return 0;
+}
+
+
+
+/* ----------------------- */
+/* */
+/* */
+/* IMAGE to YUV */
+/* */
+/* ----------------------- */
+
+
+opj_bool imagetoyuv(opj_image_t * img, char *outfile)
+{
+ FILE *f;
+ int *data;
+ int i, v, is_16, prec_bytes;
+ unsigned char buf[2];
+
+ if (img->numcomps == 3) {
+ if (img->comps[0].dx != img->comps[1].dx / 2
+ || img->comps[1].dx != img->comps[2].dx) {
+ fprintf(stderr,
+ "Error with the input image components size: cannot create yuv file)\n");
+ return OPJ_FALSE;
+ }
+ } else if (!(img->numcomps == 1)) {
+ fprintf(stderr,
+ "Error with the number of image components(must be one or three)\n");
+ return OPJ_FALSE;
+ }
+
+ f = fopen(outfile, "a+b");
+ if (!f) {
+ fprintf(stderr, "failed to open %s for writing\n", outfile);
+ return OPJ_FALSE;
+ }
+ is_16 = (img->comps[0].prec > 8);
+ prec_bytes = (is_16?2:1);
+ data = img->comps[0].data;
+
+ for (i = 0; i < (img->comps[0].w * img->comps[0].h); i++) {
+ v = *data++;
+ buf[0] = (unsigned char)v;
+
+ if(is_16) buf[1] = (unsigned char)(v>>8);
+
+ fwrite(buf, 1, prec_bytes, f);
+ }
+
+
+ if (img->numcomps == 3) {
+ data = img->comps[1].data;
+
+ for (i = 0; i < (img->comps[1].w * img->comps[1].h); i++) {
+ v = *data++;
+ buf[0] = (unsigned char)v;
+
+ if(is_16) buf[1] = (unsigned char)(v>>8);
+
+ fwrite(buf, 1, prec_bytes, f);
+ }
+ data = img->comps[2].data;
+
+ for (i = 0; i < (img->comps[2].w * img->comps[2].h); i++) {
+ v = *data++;
+ buf[0] = (unsigned char)v;
+
+ if(is_16) buf[1] = (unsigned char)(v>>8);
+
+ fwrite(buf, 1, prec_bytes, f);
+ }
+ } else if (img->numcomps == 1) {
+/* fake CbCr values */
+ if(is_16)
+ {
+ buf[0] = 255;
+ if(img->comps[0].prec == 10) buf[1] = 1;
+ else
+ if(img->comps[0].prec == 12) buf[1] = 3;
+ else
+ buf[1] = 125;
+ }
+ else buf[0] = 125;
+
+ for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
+ fwrite(buf, 1, prec_bytes, f);
+ }
+
+
+ for (i = 0; i < (img->comps[0].w * img->comps[0].h * 0.25); i++) {
+ fwrite(buf, 1, prec_bytes, f);
+ }
+ }
+ fclose(f);
+ return OPJ_TRUE;
+}
+
+/* ----------------------- */
+/* */
+/* */
+/* IMAGE to BMP */
+/* */
+/* ----------------------- */
+
+int imagetobmp(opj_image_t * img, char *outfile) {
+ int w,wr,h,hr,i,pad;
+ FILE *f;
+
+ if (img->numcomps == 3 && img->comps[0].dx == img->comps[1].dx
+ && img->comps[1].dx == img->comps[2].dx
+ && img->comps[0].dy == img->comps[1].dy
+ && img->comps[1].dy == img->comps[2].dy
+ && img->comps[0].prec == img->comps[1].prec
+ && img->comps[1].prec == img->comps[2].prec) {
+ /* -->> -->> -->> -->>
+
+ 24 bits color
+
+ <<-- <<-- <<-- <<-- */
+
+ f = fopen(outfile, "wb");
+ if (!f) {
+ fprintf(stderr, "failed to open %s for writing\n", outfile);
+ return 1;
+ }
+
+ w = img->comps[0].w;
+ wr = int_ceildivpow2(img->comps[0].w, img->comps[0].factor);
+
+ h = img->comps[0].h;
+ hr = int_ceildivpow2(img->comps[0].h, img->comps[0].factor);
+
+ fprintf(f, "BM");
+
+ /* FILE HEADER */
+ /* ------------- */
+ fprintf(f, "%c%c%c%c",
+ (unsigned char) (hr * wr * 3 + 3 * hr * (wr % 2) +
+ 54) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
+ >> 8) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
+ >> 16) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2) + 54)
+ >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
+ ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (54) & 0xff, ((54) >> 8) & 0xff,
+ ((54) >> 16) & 0xff, ((54) >> 24) & 0xff);
+
+ /* INFO HEADER */
+ /* ------------- */
+ fprintf(f, "%c%c%c%c", (40) & 0xff, ((40) >> 8) & 0xff,
+ ((40) >> 16) & 0xff, ((40) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (unsigned char) ((wr) & 0xff),
+ (unsigned char) ((wr) >> 8) & 0xff,
+ (unsigned char) ((wr) >> 16) & 0xff,
+ (unsigned char) ((wr) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (unsigned char) ((hr) & 0xff),
+ (unsigned char) ((hr) >> 8) & 0xff,
+ (unsigned char) ((hr) >> 16) & 0xff,
+ (unsigned char) ((hr) >> 24) & 0xff);
+ fprintf(f, "%c%c", (1) & 0xff, ((1) >> 8) & 0xff);
+ fprintf(f, "%c%c", (24) & 0xff, ((24) >> 8) & 0xff);
+ fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
+ ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c",
+ (unsigned char) (3 * hr * wr +
+ 3 * hr * (wr % 2)) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
+ 8) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
+ 16) & 0xff,
+ (unsigned char) ((hr * wr * 3 + 3 * hr * (wr % 2)) >>
+ 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
+ ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (7834) & 0xff, ((7834) >> 8) & 0xff,
+ ((7834) >> 16) & 0xff, ((7834) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
+ ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
+ fprintf(f, "%c%c%c%c", (0) & 0xff, ((0) >> 8) & 0xff,
+ ((0) >> 16) & 0xff, ((0) >> 24) & 0xff);
+
+ for (i = 0; i < wr * hr; i++) {
+ unsigned char R, G, B;
+ /* a modifier */
+ /* R = img->comps[0].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
+ R = img->comps[0].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+ /* G = img->comps[1].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
+ G = img->comps[1].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+ /* B = img->comps[2].data[w * h - ((i) / (w) + 1) * w + (i) % (w)];*/
+ B = img->comps[2].data[w * hr - ((i) / (wr) + 1) * w + (i) % (wr)];
+ fprintf(f, "%c%c%c", B, G, R);
+
+ if ((i + 1) % wr == 0) {
+ for (pad = (3 * wr) % 4 ? 4 - (3 * wr) % 4 : 0; pad > 0; pad--) /* ADD */
+ fprintf(f, "%c", 0);
+ }
+ }
+ fclose(f);
+ }
+ return 0;
+}
diff --git a/src/bin/mj2/mj2_convert.h b/src/bin/mj2/mj2_convert.h
new file mode 100644
index 00000000..736ef80c
--- /dev/null
+++ b/src/bin/mj2/mj2_convert.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (c) 2003-2004, Francois-Olivier Devaux
+* Copyright (c) 2002-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+* 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 "mj2.h"
+
+#ifndef __MJ2_CONVERT_H
+#define __MJ2_CONVERT_H
+
+int imagetoyuv(opj_image_t * img, char *outfile);
+
+int imagetobmp(opj_image_t * img, char *outfile);
+
+opj_image_t *mj2_image_create(mj2_tk_t * tk, opj_cparameters_t *parameters);
+
+char yuvtoimage(mj2_tk_t * tk, opj_image_t * img, int frame_num, opj_cparameters_t *parameters, char* infile);
+
+unsigned int yuv_num_frames(mj2_tk_t * tk, char *infile);
+
+
+#endif
diff --git a/src/bin/mj2/mj2_to_frames.c b/src/bin/mj2/mj2_to_frames.c
new file mode 100644
index 00000000..32679198
--- /dev/null
+++ b/src/bin/mj2/mj2_to_frames.c
@@ -0,0 +1,252 @@
+/*
+* Copyright (c) 2003-2004, Francois-Olivier Devaux
+* Copyright (c) 2002-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "opj_config.h"
+#include "openjpeg.h"
+#include "j2k_lib.h"
+#include "cio.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "mj2.h"
+#include "mj2_convert.h"
+
+#ifdef HAVE_LIBLCMS2
+#include <lcms2.h>
+#endif
+#ifdef HAVE_LIBLCMS1
+#include <lcms.h>
+#endif
+#include "color.h"
+/* -------------------------------------------------------------------------- */
+
+/**
+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[]) {
+ mj2_dparameters_t mj2_parameters; /* decompression parameters */
+ opj_dinfo_t* dinfo;
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_cio_t *cio = NULL;
+ unsigned int tnum, snum;
+ opj_mj2_t *movie;
+ mj2_tk_t *track;
+ mj2_sample_t *sample;
+ unsigned char* frame_codestream;
+ FILE *file, *outfile;
+ char outfilename[50];
+ opj_image_t *img = NULL;
+ unsigned int max_codstrm_size = 0;
+ double total_time = 0;
+ unsigned int numframes = 0;
+
+ if (argc != 3) {
+ printf("Usage: %s inputfile.mj2 outputfile.yuv\n",argv[0]);
+ return 1;
+ }
+
+ file = fopen(argv[1], "rb");
+
+ if (!file) {
+ fprintf(stderr, "failed to open %s for reading\n", argv[1]);
+ return 1;
+ }
+
+ // Checking output file
+ outfile = fopen(argv[2], "w");
+ if (!file) {
+ fprintf(stderr, "failed to open %s for writing\n", argv[2]);
+ return 1;
+ }
+ fclose(outfile);
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = NULL;
+
+ /* get a MJ2 decompressor handle */
+ dinfo = mj2_create_decompress();
+ movie = (opj_mj2_t*)dinfo->mj2_handle;
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ memset(&mj2_parameters, 0, sizeof(mj2_dparameters_t));
+ /* set J2K decoding parameters to default values */
+ opj_set_default_decoder_parameters(&mj2_parameters.j2k_parameters);
+
+ /* setup the decoder decoding parameters using user parameters */
+ mj2_setup_decoder(movie, &mj2_parameters);
+
+ if (mj2_read_struct(file, movie)) // Creating the movie structure
+ return 1;
+
+ // Decode first video track
+ for (tnum=0; tnum < (unsigned int)(movie->num_htk + movie->num_stk + movie->num_vtk); tnum++) {
+ if (movie->tk[tnum].track_type == 0)
+ break;
+ }
+
+ if (movie->tk[tnum].track_type != 0) {
+ printf("Error. Movie does not contain any video track\n");
+ return 1;
+ }
+
+ track = &movie->tk[tnum];
+
+ // Output info on first video tracl
+ fprintf(stdout,"The first video track contains %d frames.\nWidth: %d, Height: %d \n\n",
+ track->num_samples, track->w, track->h);
+
+ max_codstrm_size = track->sample[0].sample_size-8;
+ frame_codestream = (unsigned char*) malloc(max_codstrm_size * sizeof(unsigned char));
+
+ numframes = track->num_samples;
+
+ for (snum=0; snum < numframes; snum++)
+ {
+ double init_time = opj_clock();
+ double elapsed_time;
+
+ sample = &track->sample[snum];
+ if (sample->sample_size-8 > max_codstrm_size) {
+ max_codstrm_size = sample->sample_size-8;
+ if ((frame_codestream = (unsigned char*)
+ realloc(frame_codestream, max_codstrm_size)) == NULL) {
+ printf("Error reallocation memory\n");
+ return 1;
+ };
+ }
+ fseek(file,sample->offset+8,SEEK_SET);
+ fread(frame_codestream, sample->sample_size-8, 1, file); // Assuming that jp and ftyp markers size do
+
+ /* open a byte stream */
+ cio = opj_cio_open((opj_common_ptr)dinfo, frame_codestream, sample->sample_size-8);
+
+ img = opj_decode(dinfo, cio); // Decode J2K to image
+
+#ifdef WANT_SYCC_TO_RGB
+ if(img->color_space == CLRSPC_SYCC)
+ {
+ color_sycc_to_rgb(img);
+ }
+#endif
+
+ if(img->icc_profile_buf)
+ {
+#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
+ color_apply_icc_profile(img);
+#endif
+
+ free(img->icc_profile_buf);
+ img->icc_profile_buf = NULL; img->icc_profile_len = 0;
+ }
+
+ if (((img->numcomps == 3) && (img->comps[0].dx == img->comps[1].dx / 2)
+ && (img->comps[0].dx == img->comps[2].dx / 2 ) && (img->comps[0].dx == 1))
+ || (img->numcomps == 1)) {
+
+ if (!imagetoyuv(img, argv[2])) // Convert image to YUV
+ return 1;
+ }
+ else if ((img->numcomps == 3) &&
+ (img->comps[0].dx == 1) && (img->comps[1].dx == 1)&&
+ (img->comps[2].dx == 1))// If YUV 4:4:4 input --> to bmp
+ {
+ fprintf(stdout,"The frames will be output in a bmp format (output_1.bmp, ...)\n");
+ sprintf(outfilename,"output_%d.bmp",snum);
+ if (imagetobmp(img, outfilename)) // Convert image to BMP
+ return 1;
+
+ }
+ else {
+ fprintf(stdout,"Image component dimensions are unknown. Unable to output image\n");
+ fprintf(stdout,"The frames will be output in a j2k file (output_1.j2k, ...)\n");
+
+ sprintf(outfilename,"output_%d.j2k",snum);
+ outfile = fopen(outfilename, "wb");
+ if (!outfile) {
+ fprintf(stderr, "failed to open %s for writing\n",outfilename);
+ return 1;
+ }
+ fwrite(frame_codestream,sample->sample_size-8,1,outfile);
+ fclose(outfile);
+ }
+ /* close the byte stream */
+ opj_cio_close(cio);
+ /* free image data structure */
+ opj_image_destroy(img);
+ elapsed_time = opj_clock()-init_time;
+ fprintf(stderr, "Frame number %d/%d decoded in %.2f mseconds\n", snum + 1, numframes, elapsed_time*1000);
+ total_time += elapsed_time;
+
+ }
+
+ free(frame_codestream);
+ fclose(file);
+
+ /* free remaining structures */
+ if(dinfo) {
+ mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
+ }
+ free(dinfo);
+
+ fprintf(stdout, "%d frame(s) correctly decompressed\n", snum);
+ fprintf(stdout,"Total decoding time: %.2f seconds (%.1f fps)\n", total_time, (float)numframes/total_time);
+
+ return 0;
+}
diff --git a/src/bin/mj2/mj2_to_metadata.c b/src/bin/mj2/mj2_to_metadata.c
new file mode 100644
index 00000000..489f19cb
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata.c
@@ -0,0 +1,312 @@
+/* mj2_to_metadata.c */
+/* Dump MJ2, JP2 metadata (partial so far) to xml file */
+/* Contributed to Open JPEG by Glenn Pearson, contract software developer, U.S. National Library of Medicine.
+
+The base code in this file was developed by the author as part of a video archiving
+project for the U.S. National Library of Medicine, Bethesda, MD.
+It is the policy of NLM (and U.S. government) to not assert copyright.
+
+A non-exclusive copy of this code has been contributed to the Open JPEG project.
+Except for copyright, inclusion of the code within Open JPEG for distribution and use
+can be bound by the Open JPEG open-source license and disclaimer, expressed elsewhere.
+*/
+
+#include "opj_includes.h"
+#include "mj2.h"
+
+#include "mj2_to_metadata.h"
+#include <string.h>
+#include "opj_getopt.h"
+
+/* -------------------------------------------------------------------------- */
+
+/**
+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);
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+
+/* ------------- */
+
+void help_display()
+{
+ /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
+ fprintf(stdout," Help for the 'mj2_to_metadata' Program\n");
+ fprintf(stdout," ======================================\n");
+ fprintf(stdout,"The -h option displays this information on screen.\n\n");
+
+ fprintf(stdout,"mj2_to_metadata generates an XML file from a Motion JPEG 2000 file.\n");
+ fprintf(stdout,"The generated XML shows the structural, but not (yet) curatorial,\n");
+ fprintf(stdout,"metadata from the movie header and from the JPEG 2000 image and tile\n");
+ fprintf(stdout,"headers of a sample frame. Excluded: low-level packed-bits image data.\n\n");
+
+ fprintf(stdout,"By Default\n");
+ fprintf(stdout,"----------\n");
+ fprintf(stdout,"The metadata includes the jp2 image and tile headers of the first frame.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Metadata values are shown in 'raw' form (e.g., hexidecimal) as stored in the\n");
+ fprintf(stdout,"file, and, if apt, in a 'derived' form that is more quickly grasped.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Notes explaining the XML are embedded as terse comments. These include\n");
+ fprintf(stdout," meaning of non-obvious tag abbreviations;\n");
+ fprintf(stdout," range and precision of valid values;\n");
+ fprintf(stdout," interpretations of values, such as enumerations; and\n");
+ fprintf(stdout," current implementation limitations.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"The sample-size and chunk-offset tables, each with 1 row per frame, are not reported.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"The file is self-contained and no verification (e.g., against a DTD) is requested.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Required Parameters (except with -h)\n");
+ fprintf(stdout,"------------------------------------\n");
+ fprintf(stdout,"[Caution: file strings that contain spaces should be wrapped with quotes.]\n");
+ fprintf(stdout,"-i input.mj2 : where 'input' is any source file name or path.\n");
+ fprintf(stdout," MJ2 files created with 'frames_to_mj2' are supported so far.\n");
+ fprintf(stdout," These are silent, single-track, 'MJ2 Simple Profile' videos.\n");
+ fprintf(stdout,"-o output.xml : where 'output' is any destination file name or path.\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"Optional Parameters\n");
+ fprintf(stdout,"-------------------\n");
+ fprintf(stdout,"-h : Display this help information.\n");
+ fprintf(stdout,"-n : Suppress all mj2_to_metadata notes.\n");
+ fprintf(stdout,"-t : Include sample-size and chunk-offset tables.\n");
+ fprintf(stdout,"-f n : where n > 0. Include jp2 header info for frame n [default=1].\n");
+ fprintf(stdout,"-f 0 : No jp2 header info.\n");
+ fprintf(stdout,"-r : Suppress all 'raw' data for which a 'derived' form exists.\n");
+ fprintf(stdout,"-d : Suppress all 'derived' data.\n");
+ fprintf(stdout," (If both -r and -d given, -r will be ignored.)\n");
+ fprintf(stdout,"-v string : Verify against the DTD file located by the string.\n");
+ fprintf(stdout," Prepend quoted 'string' with either SYSTEM or PUBLIC keyword.\n");
+ fprintf(stdout," Thus, for the distributed DTD placed in the same directory as\n");
+ fprintf(stdout," the output file: -v \"SYSTEM mj2_to_metadata.dtd\"\n");
+ fprintf(stdout," \"PUBLIC\" is used with an access protocol (e.g., http:) + URL.\n");
+ /* More to come */
+ fprintf(stdout,"\n");
+ /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
+}
+
+/* ------------- */
+
+int main(int argc, char *argv[]) {
+
+ opj_dinfo_t* dinfo;
+ opj_event_mgr_t event_mgr; /* event manager */
+
+ FILE *file, *xmlout;
+/* char xmloutname[50]; */
+ opj_mj2_t *movie;
+
+ char* infile = 0;
+ char* outfile = 0;
+ char* s, S1, S2, S3;
+ int len;
+ unsigned int sampleframe = 1; /* First frame */
+ char* stringDTD = NULL;
+ BOOL notes = TRUE;
+ BOOL sampletables = FALSE;
+ BOOL raw = TRUE;
+ BOOL derived = TRUE;
+ mj2_dparameters_t parameters;
+
+ while (TRUE) {
+ /* ':' after letter means it takes an argument */
+ int c = getopt(argc, argv, "i:o:f:v:hntrd");
+ /* FUTURE: Reserve 'p' for pruning file (which will probably make -t redundant) */
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'i': /* IN file */
+ infile = optarg;
+ s = optarg;
+ while (*s) { s++; } /* Run to filename end */
+ s--;
+ S3 = *s;
+ s--;
+ S2 = *s;
+ s--;
+ S1 = *s;
+
+ if ((S1 == 'm' && S2 == 'j' && S3 == '2')
+ || (S1 == 'M' && S2 == 'J' && S3 == '2')) {
+ break;
+ }
+ fprintf(stderr, "Input file name must have .mj2 extension, not .%c%c%c.\n", S1, S2, S3);
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'o': /* OUT file */
+ outfile = optarg;
+ while (*outfile) { outfile++; } /* Run to filename end */
+ outfile--;
+ S3 = *outfile;
+ outfile--;
+ S2 = *outfile;
+ outfile--;
+ S1 = *outfile;
+
+ outfile = optarg;
+
+ if ((S1 == 'x' && S2 == 'm' && S3 == 'l')
+ || (S1 == 'X' && S2 == 'M' && S3 == 'L'))
+ break;
+
+ fprintf(stderr,
+ "Output file name must have .xml extension, not .%c%c%c\n", S1, S2, S3);
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'f': /* Choose sample frame. 0 = none */
+ sscanf(optarg, "%u", &sampleframe);
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'v': /* Verification by DTD. */
+ stringDTD = optarg;
+ /* We will not insist upon last 3 chars being "dtd", since non-file
+ access protocol may be used. */
+ if(strchr(stringDTD,'"') != NULL) {
+ fprintf(stderr, "-D's string must not contain any embedded double-quote characters.\n");
+ return 1;
+ }
+
+ if (strncmp(stringDTD,"PUBLIC ",7) == 0 || strncmp(stringDTD,"SYSTEM ",7) == 0)
+ break;
+
+ fprintf(stderr, "-D's string must start with \"PUBLIC \" or \"SYSTEM \"\n");
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'n': /* Suppress comments */
+ notes = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 't': /* Show sample size and chunk offset tables */
+ sampletables = TRUE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'h': /* Display an help description */
+ help_display();
+ return 0;
+
+ /* ----------------------------------------------------- */
+ case 'r': /* Suppress raw data */
+ raw = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'd': /* Suppress derived data */
+ derived = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ default:
+ return 1;
+ } /* switch */
+ } /* while */
+
+ if(!raw && !derived)
+ raw = TRUE; /* At least one of 'raw' and 'derived' must be true */
+
+ /* Error messages */
+ /* -------------- */
+ if (!infile || !outfile) {
+ fprintf(stderr,"Correct usage: mj2_to_metadata -i mj2-file -o xml-file (plus options)\n");
+ return 1;
+ }
+
+/* was:
+ if (argc != 3) {
+ printf("Bad syntax: Usage: MJ2_to_metadata inputfile.mj2 outputfile.xml\n");
+ printf("Example: MJ2_to_metadata foreman.mj2 foreman.xml\n");
+ return 1;
+ }
+*/
+ len = strlen(infile);
+ if(infile[0] == ' ')
+ {
+ infile++; /* There may be a leading blank if user put space after -i */
+ }
+
+ file = fopen(infile, "rb"); /* was: argv[1] */
+
+ if (!file) {
+ fprintf(stderr, "Failed to open %s for reading.\n", infile); /* was: argv[1] */
+ return 1;
+ }
+
+ len = strlen(outfile);
+ if(outfile[0] == ' ')
+ {
+ outfile++; /* There may be a leading blank if user put space after -o */
+ }
+
+ // Checking output file
+ xmlout = fopen(outfile, "w"); /* was: argv[2] */
+ if (!xmlout) {
+ fprintf(stderr, "Failed to open %s for writing.\n", outfile); /* was: argv[2] */
+ return 1;
+ }
+ // Leave it open
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = info_callback;
+
+ /* get a MJ2 decompressor handle */
+ dinfo = mj2_create_decompress();
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using user parameters */
+ movie = (opj_mj2_t*) dinfo->mj2_handle;
+ mj2_setup_decoder(dinfo->mj2_handle, &parameters);
+
+ if (mj2_read_struct(file, movie)) // Creating the movie structure
+ {
+ fclose(xmlout);
+ return 1;
+ }
+
+ xml_write_init(notes, sampletables, raw, derived);
+ xml_write_struct(file, xmlout, movie, sampleframe, stringDTD, &event_mgr);
+ fclose(xmlout);
+
+ fprintf(stderr,"Metadata correctly extracted to XML file \n");;
+
+ /* free remaining structures */
+ if(dinfo) {
+ mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
+ }
+
+ return 0;
+}
+
+
diff --git a/src/bin/mj2/mj2_to_metadata.dtd b/src/bin/mj2/mj2_to_metadata.dtd
new file mode 100644
index 00000000..249de1a0
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata.dtd
@@ -0,0 +1,425 @@
+<!--
+Preliminary DTD for Open JPEG "mj2_to_metadata" function.
+Last revised: April 20, 2005
+Author: Glenn Pearson, at U.S. National Library of Medicine.
+See mj2_to_metadata.c regarding copyright, license, disclaimer status.
+
+While the vocabulary of this DTD is based on the relevant portions of the
+ISO/IEC JPEG 200 standard, the detailed representation is the author's own.
+It is neither an ISO/IEC nor NLM official or consensus representation.
+Furthermore, it deviates from a pure representation of the ISO/IEC standard
+in these aspects:
+
+ - it is incomplete in a number of ways (which to some extent may be
+ addressed over time);
+ - it has extensions for "derived" data and "statistics";
+ - it is more flexible. That is, some elements are marked as optional
+ not because they are optional in an MJ2 file, but because reporting
+ of them is optional based on current or projected mj2_to_metadata
+ command-line flags.
+-->
+<!ELEMENT MJ2_File (JP2?, FileType?, MovieBox?)>
+<!ELEMENT JP2 EMPTY>
+<!ATTLIST JP2 BoxType CDATA #FIXED "jP[space][space]">
+<!ATTLIST JP2 Signature CDATA #FIXED "0x0d0a870a">
+<!ELEMENT FileType (Brand, MinorVersion, CompatibilityList)>
+<!ATTLIST FileType BoxType CDATA #FIXED "ftyp">
+<!ELEMENT Brand (#PCDATA)> <!-- 4 characters max -->
+<!ELEMENT MinorVersion (#PCDATA)> <!-- 4 chararcters max -->
+<!ELEMENT CompatibilityList (CompatibleBrand)*>
+<!ATTLIST CompatibilityList Count CDATA #REQUIRED> <!-- Count >= 0 -->
+<!ELEMENT CompatibleBrand (#PCDATA)> <!-- 4 characters max -->
+<!ELEMENT MovieBox (MovieHeader, Statistics?, Track*)>
+<!ATTLIST MovieBox BoxType CDATA #FIXED "moov">
+<!ELEMENT MovieHeader (CreationTime, ModificationTime, Timescale, Rate, Duration, Volume, TransformationMatrix)>
+<!ATTLIST MovieHeader BoxType CDATA #FIXED "mvhd">
+<!ELEMENT CreationTime (InSeconds?,AsLocalTime?)>
+<!ELEMENT InSeconds (#PCDATA)>
+<!ELEMENT AsLocalTime (#PCDATA)>
+<!ELEMENT ModificationTime (InSeconds?,AsLocalTime?)>
+<!ELEMENT Timescale (#PCDATA)> <!-- Timescale defines time units in one second -->
+<!ELEMENT Rate (AsHex | (AsHex, AsDecimal) | AsDecimal)> <!-- Decimal is Approximation; Optional on input. -->
+<!ELEMENT AsHex (#PCDATA)>
+<!ELEMENT AsDecimal (#PCDATA)>
+<!ELEMENT Duration (InTimeUnits | (InTimeUnits, InSeconds) | InSeconds)> <!-- InSeconds Optional on input. -->
+<!ELEMENT InTimeUnits (#PCDATA)>
+<!ELEMENT Volume (AsHex | (AsHex, AsDecimal) | AsDecimal)> <!-- hex default = 0x0100 -->
+<!-- Fixed 8.8 value of audio volume. Full, normal value is 1.0 (0x0100) -->
+<!ELEMENT TransformationMatrix (TMa,TMb,TMu,TMc,TMd,TMv,TMx,TMy,TMw)> <!-- for video -->
+<!-- 3 x 3 Video Transformation Matrix {a,b,u,c,d,v,x,y,w}. Required: u=0, v=0, w=1 -->
+<!-- Maps decompressed point (p,q) to rendered point (ap + cq + x, bp + dq + y) -->
+<!-- Stored as Fixed Point Hex: all are 16.16, except u,v,w are 2.30 -->
+<!-- Unity = 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 -->
+<!ELEMENT TMa (#PCDATA)>
+<!ELEMENT TMb (#PCDATA)>
+<!ELEMENT TMu (#PCDATA)> <!--Always "0x00000000" -->
+<!ELEMENT TMc (#PCDATA)>
+<!ELEMENT TMd (#PCDATA)>
+<!ELEMENT TMv (#PCDATA)> <!--Always "0x00000000" -->
+<!ELEMENT TMx (#PCDATA)>
+<!ELEMENT TMy (#PCDATA)>
+<!ELEMENT TMw (#PCDATA)> <!--Always "0x40000000" -->
+
+<!ELEMENT Statistics (TracksFound)>
+<!ELEMENT TracksFound (Video,Audio,Hint)>
+<!ELEMENT Video (#PCDATA)>
+<!ELEMENT Audio (#PCDATA)>
+<!ELEMENT Hint (#PCDATA)>
+
+
+<!-- For now, output info on at most one video track -->
+
+
+<!ELEMENT Track (TrackHeader, TrackReferenceContainer?, EditListContainer?, Media, JP2_Frame?)> <!-- JP2_Frame is mj2_to_metadata extension -->
+<!ATTLIST Track BoxType CDATA #FIXED "trak">
+<!ATTLIST Track Instance CDATA #REQUIRED>
+<!ELEMENT TrackHeader (TrackID, TrackLayer?, Volume?, TransformationMatrix?, Width?, Height?)>
+<!ATTLIST TrackHeader BoxType CDATA #FIXED "tkhd">
+<!-- Not shown here: CreationTime, ModificationTime, Duration. -->
+<!-- These 3 fields are reported under MediaHeader below. When reading these 3, -->
+<!-- m2j_to_metadata currently doesn't distinguish between TrackHeader and MediaHeader source. -->
+<!-- If both found, value read from MediaHeader is used. -->
+<!ELEMENT TrackID (#PCDATA)>
+<!ELEMENT TrackLayer (#PCDATA)> <!-- front-to-back ordering of video tracks. 0 = normal, -1 is closer, etc. -->
+<!-- "Volume" element described above; here it is for particular audio track. Full, normal (default = 0x0100) -->
+<!-- "TransformationMatrix" element described above; matrix here is applied before MovieHeader one. -->
+<!ELEMENT Width (AsHex | (AsHex, AsDecimal) | AsDecimal)>
+<!ELEMENT Height (AsHex | (AsHex, AsDecimal) | AsDecimal)>
+<!-- AsHex, AsDecimal already defined above -->
+ <!-- Width and Height are for the presentation; frames will be scaled to this -->
+<!-- /TrackHeader -->
+<!ELEMENT TrackReferenceContainer ANY> <!-- TO DO: TrackReferenceContainer 'tref' just used in hint track -->
+<!ELEMENT EditListContainer ANY> <!-- TO DO: EditListContainer 'edts', contains EditList 'elst' with media-time, segment-duration, media-rate -->
+<!ELEMENT Media (MediaHeader, HandlerReference,MediaInfoContainer)>
+<!ATTLIST Media BoxType CDATA #FIXED "mdia">
+<!ELEMENT MediaHeader (CreationTime,ModificationTime,Timescale,Duration,Language)>
+<!ATTLIST MediaHeader BoxType CDATA #FIXED "mdhd">
+<!-- Elements already defined above: CreationTime, ModificationTime, Timescale, Duration -->
+<!ELEMENT Language (#PCDATA)> <!-- 3 chars max. There's an enumeration available -->
+<!ELEMENT HandlerReference (HandlerType)>
+<!ATTLIST HandlerReference BoxType CDATA #FIXED "hdlr">
+<!ELEMENT HandlerType (#PCDATA)>
+<!ATTLIST HandlerType Code ( vide | soun | hint ) "vide">
+
+<!-- make the media headers multiple? -->
+<!ELEMENT MediaInfoContainer ((VideoMediaHeader | SoundMediaHeader | HintMediaHeader), DataInfo, SampleTable)>
+<!ATTLIST MediaInfoContainer BoxType CDATA #FIXED "minf">
+<!ELEMENT VideoMediaHeader (GraphicsMode, Opcolor)>
+<!ATTLIST VideoMediaHeader BoxType CDATA #FIXED "vmhd">
+<!ELEMENT GraphicsMode (#PCDATA)>
+ <!-- Enumerated values of graphics mode: -->
+ <!-- 0x00 = copy (over existing image); -->
+ <!-- 0x24 = transparent; 'blue-screen' this image using opcolor; -->
+ <!-- 0x100 = alpha; alpha-blend this image -->
+ <!-- 0x101 = whitealpha; alpha-blend this image, which has been blended with white; -->
+ <!-- 0x102 = blackalpha; alpha-blend this image, which has been blended with black. -->
+<!ELEMENT Opcolor (Red,Green,Blue)>
+<!ELEMENT Red (#PCDATA)>
+<!ELEMENT Green (#PCDATA)>
+<!ELEMENT Blue (#PCDATA)>
+<!ELEMENT SoundMediaHeader (Balance)>
+<!ATTLIST SoundMediaHeader BoxType CDATA #FIXED "smhd">
+<!ELEMENT Balance (#PCDATA)>
+ <!-- Fixed Point 8.8, fixes mono track in stereo space. -->
+ <!-- 0.0 = center, -1.0 = full left, 1.0 = full right -->
+<!ELEMENT HintMediaHeader (MaxPDU_Size, AvgPDU_Size, MaxBitRate, AvgBitRate, SlidingAvgBitRate)>
+<!ATTLIST HintMediaHeader BoxType CDATA #FIXED "hmhd">
+<!ELEMENT MaxPDU_Size (#PCDATA)>
+ <!-- Size in bytes of largest PDU in this hint stream. -->
+<!ELEMENT AvgPDU_Size (#PCDATA)>
+ <!-- Average size in bytes of a PDU over the entire presentation. -->
+<!ELEMENT MaxBitRate (#PCDATA)>
+ <!-- Maximum rate in bits per second over any window of 1 second. -->
+<!ELEMENT AvgBitRate (#PCDATA)>
+ <!-- Averate rate in bits per second over the entire presentation. -->
+<!ELEMENT SlidingAvgBit (#PCDATA)>
+ <!-- Maximum rate in bits per second over any window of one minute. -->
+
+<!ELEMENT DataInfo (DataReference)>
+<!ATTLIST DataInfo BoxType CDATA #FIXED "dinf">
+<!ELEMENT DataReference (DataEntryUrlBox | DataEntryUrnBox )*>
+<!ATTLIST DataReference BoxType CDATA #FIXED "dref">
+<!ATTLIST DataReference URL_Count CDATA #REQUIRED>
+<!ATTLIST DataReference URN_Count CDATA #REQUIRED> <!-- table w. flags, URLs, URNs -->
+<!-- // Data structure does not distinguish between single URL, single URN, or DREF table or URLs & URNs.
+ // We could infer those, but for now just present everything as a DREF table.
+-->
+ <!-- No entries here mean that file is self-contained, as required by Simple Profile. -->
+
+<!ELEMENT DataEntryUrlBox (Location)>
+<!ATTLIST DataEntryUrlBox BoxType CDATA #FIXED "url[space]"> <!-- table w. flags, URLs, URNs -->
+ <!-- Only the first 16 bytes of URL location are recorded in mj2_to_metadata data structure. -->
+<!ELEMENT DataEntryUrnBox (Name, Location?)>
+<!ATTLIST DataEntryUrnBox BoxType CDATA #FIXED "urn[space]\">
+ <!-- Only the first 16 bytes each of URN name and optional location are recorded in mj2_to_metadata data structure. -->
+
+<!ELEMENT SampleTable (VisualSampleEntry,TimeToSample,SampleToChunk,SampleSize,ChunkOffset)> <!-- structure doesn't do non-visual sample entry yet -->
+<!ATTLIST SampleTable BoxType CDATA #FIXED "stbl"> <!-- to add: entry count -->
+ <!-- Next are instances of generic SampleDescription BoxType=\"stsd\" -->
+
+ <!-- There could be multiple instances of this, but "entry_count" is just a local at read-time.
+ And it's used wrong, too, as count of just visual type, when it's really all 3 types.
+ This is referred to as "smj2" within mj2.c -->
+<!ELEMENT VisualSampleEntry (WidthAsInteger, HeightAsInteger, HorizontalRes, VerticalRes, CompressorName, Depth, JP2Header?, FieldCoding?, MJP2_Profile?, MJP2_Prefix?, MJP2_SubSampling?, MJP2_OriginalFormat?)>
+<!ATTLIST VisualSampleEntry BoxType CDATA #FIXED "mjp2">
+ <!-- If multiple instances of this, only first is shown here. -->
+<!ELEMENT WidthAsInteger (#PCDATA)>
+<!ELEMENT HeightAsInteger (#PCDATA)>
+<!ELEMENT HorizontalRes (AsHex | (AsHex, AsDecimal) | AsDecimal)>
+<!ELEMENT VerticalRes (AsHex | (AsHex, AsDecimal) | AsDecimal)>
+<!-- Typical value for both resolution is 72 (0x00480000) -->
+<!ELEMENT CompressorName (#PCDATA)>
+ <!-- Compressor name for debugging. Standard restricts max length to 31 bytes. -->
+ <!-- Usually blank or \"Motion JPEG2000\" -->
+<!ELEMENT Depth (#PCDATA)>
+ <!-- Depth is: -->
+ <!-- 0x20: alpha channels present (color or grayscale) -->
+ <!-- 0x28: grayscale without alpha -->
+ <!-- 0x18: color without alpha -->
+
+<!-- TODO somewhere: tk->jp2_struct.numcomps -->
+<!ELEMENT JP2Header (ImageHeader, ColourSpecification)>
+<!ATTLIST JP2Header BoxType CDATA #FIXED "jp2h">
+<!ELEMENT ImageHeader (HEIGHT, WIDTH, NC, BPC, C, UnkC, IPR)>
+<!ATTLIST ImageHeader BoxType CDATA #FIXED "ihdr">
+<!ELEMENT HEIGHT (#PCDATA)> <!-- If 2 fields/frame, total deinterlaced height -->
+<!ELEMENT WIDTH (#PCDATA)>
+<!ELEMENT NC (#PCDATA)> <!-- number of components -->
+<!ELEMENT BPC (AsHex | (AsHex,BitsPerPixel,Signed) | (BitsPerPixel,Signed))>
+<!ELEMENT BitsPerPixel (#PCDATA)>
+<!ELEMENT Signed (#PCDATA)>
+<!ELEMENT C (#PCDATA)> <!-- Compression type. Only "7" defined -->
+<!ELEMENT UnkC (#PCDATA)> <!-- Colourspace Unknown. 1 = unknown, 0 = known -->
+<!ELEMENT IPR (#PCDATA)> <!-- 1 = frame has Intellectual Prop. box; otherwise 0 -->
+<!ELEMENT ColourSpecification (METH, PREC, APPROX, EnumCS)>
+<!ATTLIST ColourSpecification BoxType CDATA #FIXED "colr">
+<!ELEMENT METH (#PCDATA)> <!-- 1 = EnumCS field; 2 = PROFILE field (not yet generated) -->
+<!ELEMENT PREC (#PCDATA)> <!-- precedence must be 0 so far -->
+<!ELEMENT APPROX (#PCDATA)> <!-- colourspace approximation must be 0 so far -->
+<!ELEMENT EnumCS (#PCDATA)> <!-- Valid enumerated MJ2 colourspaces: 16 (sRGB), 17 (grey sRGB), 18 (YCC) -->
+
+<!-- Following subboxes are optional -->
+<!ELEMENT FieldCoding (FieldCount, FieldOrder)>
+<!ATTLIST FieldCoding BoxType CDATA #FIXED "fiel">
+<!ELEMENT FieldCount (#PCDATA)>
+ <!-- Must be either 1 or 2 -->
+<!ELEMENT FieldOrder (#PCDATA)>
+ <!-- When FieldCount=2, FieldOrder means: -->
+ <!-- 0: Field coding unknown -->
+ <!-- 1: Field with topmost line is stored first in sample; fields are in temporal order -->
+ <!-- 6: Field with topmost line is stored second in sample; fields are in temporal order -->
+ <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->
+ <!-- Current implementation doesn't retain whether box was actually present. -->
+
+<!ELEMENT MJP2_Profile (CompatibleBrand*)>
+<!ATTLIST MJP2_Profile BoxType CDATA #FIXED "jp2p">
+<!ATTLIST MJP2_Profile Count CDATA #REQUIRED>
+
+<!ELEMENT MJP2_Prefix (Data*)>
+<!ATTLIST MJP2_Prefix BoxType CDATA #FIXED "jp2x">
+<!ATTLIST MJP2_Prefix Count CDATA #REQUIRED>
+<!-- We'll probably need better formatting than this -->
+<!ELEMENT Data (#PCDATA)> <!-- Multiple. Each entry is single byte -->
+
+<!ELEMENT MJP2_SubSampling (HorizontalSub, VerticalSub, HorizontalOffset, VerticalOffset)>
+<!ATTLIST MJP2_SubSampling BoxType CDATA #FIXED "jsub">
+<!-- These values are all 1 byte -->
+ <!-- Typical subsample value is 2 for 4:2:0 -->
+<!ELEMENT HorizontalSub (#PCDATA)>
+<!ELEMENT VerticalSub (#PCDATA)>
+<!ELEMENT HorizontalOffset (#PCDATA)>
+<!ELEMENT VerticalOffset (#PCDATA)>
+
+<!ELEMENT MJP2_OriginalFormat (OriginalFieldCount, OriginalFieldOrder)>
+<!ATTLIST MJP2_OriginalFormat BoxType CDATA #FIXED "orfo"> <!-- Part III Appx. 2 -->
+<!ELEMENT OriginalFieldCount (#PCDATA)>
+ <!-- In original material before encoding. Must be either 1 or 2 -->
+<!ELEMENT OriginalFieldOrder (#PCDATA)>
+ <!-- When FieldCount=2, FieldOrder means: -->
+ <!-- 0: Field coding unknown -->
+ <!-- 11: Topmost line came from the earlier field; -->
+ <!-- 16: Topmost line came form the later field. -->
+ <!-- Defaults: FieldCount=1, FieldOrder=0 if FieldCoding box not present -->
+ <!-- Current implementation doesn't retain whether box was actually present. -->
+
+
+ <!-- mj2_to_metadata's data structure doesn't record Audio and Hint sample data currently. -->
+
+<!-- Within SampleTable: -->
+<!ELEMENT TimeToSample (SampleStatistics, SampleEntries)>
+<!ATTLIST TimeToSample BoxType CDATA #FIXED "stts">
+<!ELEMENT SampleStatistics (TotalSamples)> <!-- Not part of standard -->
+<!ELEMENT TotalSamples (#PCDATA)>
+ <!-- For video, gives the total frames in the track, by summing all entries in the Sample Table -->
+
+<!ELEMENT SampleEntries (Table*)>
+<!ATTLIST SampleEntries EntryCount CDATA #REQUIRED>
+<!ELEMENT Table EMPTY> <!-- Multiple. Attributes have values -->
+<!ATTLIST Table Entry CDATA #REQUIRED>
+<!ATTLIST Table SampleCount CDATA #REQUIRED>
+<!ATTLIST Table SampleDelta CDATA #REQUIRED>
+
+<!-- Within SampleTable: -->
+<!ELEMENT SampleToChunk (FirstChunk,SamplesPerChunk,SampleDescrIndex)>
+<!ATTLIST SampleToChunk BoxType CDATA #FIXED "stsc">
+<!ATTLIST SampleToChunk Count CDATA #REQUIRED>
+<!ELEMENT FirstChunk (#PCDATA)>
+<!ELEMENT SamplesPerChunk (#PCDATA)>
+<!ELEMENT SampleDescrIndex (#PCDATA)>
+<!ELEMENT SampleSize (Sample_Size,Sample_Count,EntrySize*)>
+<!ATTLIST SampleSize BoxType CDATA #FIXED "stsz">
+<!ELEMENT Sample_Size (#PCDATA)>
+<!ELEMENT Sample_Count (#PCDATA)>
+<!ELEMENT EntrySize (#PCDATA)> <!-- appears multiply, but only with mj2_to_metadata option -t -->
+<!ATTLIST EntrySize Num CDATA #REQUIRED>
+<!ELEMENT ChunkOffset (EntryCount, Chunk_Offset*)>
+<!ATTLIST ChunkOffset BoxType CDATA #FIXED "stco">
+<!ELEMENT EntryCount (#PCDATA)>
+<!ELEMENT Chunk_Offset (#PCDATA)> <!-- appears multiply, but only with mj2_to_metadata option -t -->
+<!ATTLIST Chunk_Offset Num CDATA #REQUIRED>
+<!-- </SampleTable> </MediaInfoContainer> </Media> -->
+
+<!-- TO DO: optional UserData 'udat', can contain multiple Copyright 'cprt' -->
+
+
+<!-- Optional, and only for Visual Track: given individual frame -->
+<!ELEMENT JP2_Frame (MainHeader, TilePartHeaders)>
+<!ATTLIST JP2_Frame Num CDATA #REQUIRED>
+<!ELEMENT MainHeader (StartOfCodestream,ImageAndFileSize,CodingStyleDefault,QuantizationDefault,QuantizationComponent*,RegionOfInterest?,ProgressionOrderChange*)>
+<!ELEMENT StartOfCodestream EMPTY>
+<!ATTLIST StartOfCodestream Marker CDATA #FIXED "SOC">
+<!ELEMENT ImageAndFileSize (Xsiz,Ysiz,XOsiz,YOsiz,XTsiz,YTsiz,XTOsiz,YTOsiz,Csiz,Component+)>
+<!ATTLIST ImageAndFileSize Marker CDATA #FIXED "SIZ">
+<!ELEMENT Xsiz (#PCDATA)>
+<!ELEMENT Ysiz (#PCDATA)> <!-- Xsiz, Ysiz is the size of the reference grid. -->
+<!ELEMENT XOsiz (#PCDATA)>
+<!ELEMENT YOsiz (#PCDATA)> <!-- XOsiz, YOsiz are offsets from grid origin to image origin. -->
+<!ELEMENT XTsiz (#PCDATA)>
+<!ELEMENT YTsiz (#PCDATA)> <!-- XTsiz, YTsiz is the size of one tile with respect to the grid. -->
+<!ELEMENT XTOsiz (#PCDATA)>
+<!ELEMENT YTOsiz (#PCDATA)> <!-- XTOsiz, YTOsiz are offsets from grid origin to first tile origin. -->
+<!ELEMENT Csiz (#PCDATA)> <!-- Csiz is the number of components in the image. -->
+<!-- For image components next -->
+<!ELEMENT Component (Ssiz,XRsiz,YRsiz,WidthOfData,HeightOfData)>
+<!ATTLIST Component Num CDATA #REQUIRED>
+<!ELEMENT Ssiz (AsHex | (AsHex,Signed,PrecisionInBits) | (Signed,PrecisionInBits))>
+<!-- Signed already defined -->
+<!ELEMENT PrecisionInBits (#PCDATA)> <!-- Bits per pixel (bpp) or pixel depth. -->
+<!ELEMENT XRsiz (#PCDATA)>
+<!ELEMENT YRsiz (#PCDATA)> <!-- XRsiz, YRsiz denote pixel-sample-spacing on the grid, per Part I Annex B. -->
+<!ELEMENT WidthOfData (#PCDATA)>
+<!ELEMENT HeightOfData (#PCDATA)> <!-- WidthOfData and HeightOfData are calculated values, e.g.: w = roundup((Xsiz - XOsiz)/ XRsiz) -->
+<!-- -->
+<!ELEMENT CodingStyleDefault (Scod,SGcod,SPcod)>
+<!ATTLIST CodingStyleDefault Marker CDATA #FIXED "COD">
+<!ELEMENT Scod (#PCDATA)>
+ <!-- For Scod, specific bits mean (where bit 0 is lowest or rightmost): -->
+ <!-- bit 0: Defines entropy coder precincts -->
+ <!-- 0 = (PPx=15, PPy=15); 1 = precincts defined below. -->
+ <!-- bit 1: 1 = SOP marker may be used; 0 = not. -->
+ <!-- bit 2: 1 = EPH marker may be used; 0 = not. -->
+<!ELEMENT SGcod (ProgressionOrder,NumberOfLayers,MultipleComponentTransformation)>
+<!ELEMENT ProgressionOrder (#PCDATA)>
+ <!-- Defined Progression Order Values are: -->
+ <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->
+ <!-- where L = "layer", R = "resolution level", C = "component", P = "position". -->
+<!ELEMENT NumberOfLayers (#PCDATA)>
+<!ELEMENT MultipleComponentTransformation (#PCDATA)>
+ <!-- For MCT, 0 = none, 1 = transform first 3 components for efficiency, per Part I Annex G -->
+<!ELEMENT SPcod (NumberOfDecompositionLevels,CodeblockWidth,CodeblockHeight,CodeblockStyle,Transformation)>
+<!ELEMENT NumberOfDecompositionLevels (#PCDATA)>
+<!ELEMENT CodeblockWidth (#PCDATA)> <!-- CBW and CBH are non-negative, and summed cannot exceed 8 -->
+<!ELEMENT CodeblockHeight (#PCDATA)> <!-- Codeblock dimension is 2^(value + 2) -->
+<!ELEMENT CodeblockStyle (#PCDATA)>
+ <!-- For CodeblockStyle, bits mean (with value 1=feature on, 0=off): -->
+ <!-- bit 0: Selective arithmetic coding bypass. -->
+ <!-- bit 1: Reset context probabilities on coding pass boundaries. -->
+ <!-- bit 2: Termination on each coding pass. -->
+ <!-- bit 3: Vertically causal context. -->
+ <!-- bit 4: Predictable termination. -->
+ <!-- bit 5: Segmentation symbols are used. -->
+<!ELEMENT Transformation (#PCDATA)> <!-- For Transformation, 0="9-7 irreversible filter", 1="5-3 reversible filter" -->
+ <!-- mj2_to_metadata implementation always reports component[0] as using default COD, -->
+ <!-- and any other component, with main-header style values different from [0], as COC. -->
+<!ELEMENT QuantizationDefault (Sqcd,SPqcd)>
+<!ATTLIST QuantizationDefault Marker CDATA #FIXED "QCD">
+<!ELEMENT Sqcd (AsHex | (AsHex,QuantizationStyle,NumberOfGuardBits) | (QuantizationStyle,NumberOfGuardBits))>
+<!ELEMENT QuantizationStyle (#PCDATA)> <!-- Default quantization style for all components. -->
+ <!-- Quantization style (in Sqcd's low 5 bits) may be: -->
+ <!-- 0 = No quantization. SPqcd size = 8 bits-->
+ <!-- 1 = Scalar derived (values signaled for N(L)LL subband only). Use Eq. E.5. SPqcd size = 16. -->
+ <!-- 2 = Scalar expounded (values signaled for each subband). SPqcd size = 16. -->
+<!ELEMENT NumberOfGuardBits (#PCDATA)> <!-- 0-7 guard bits allowed (stored in Sqcd's high 3 bits) -->
+<!ELEMENT SPqcd (ReversibleStepSizeValue | QuantizationStepSizeValues )> <!-- TO DO: Irreversible choices -->
+<!ELEMENT ReversibleStepSizeValue (DynamicRangeExponent+)>
+ <!-- Current mj2_to_metadata implementation dumps entire internal table, -->
+ <!-- until an exponent with zero value is reached. -->
+ <!-- Exponent epsilon(b) of reversible dynamic range. -->
+ <!-- Hex value is as stored, in high-order 5 bits. -->
+<!ELEMENT DynamicRangeExponent (AsHex | (AsHex, AsDecimal) | AsDecimal)>
+<!ATTLIST DynamicRangeExponent Subband CDATA #REQUIRED>
+<!ELEMENT QuantizationStepSizeValues (QuantizationValues+, CalculatedExponent*)> <!-- Calculated exponents iff only subband 0 reported -->
+<!ELEMENT QuantizationValues (AsHex | (AsHex,Exponent,Mantissa) | (Exponent,Mantissa))>
+<!ATTLIST QuantizationValues Subband CDATA #REQUIRED>
+<!ELEMENT Exponent (#PCDATA)>
+<!ELEMENT Mantissa (#PCDATA)>
+<!ELEMENT CalculatedExponent (#PCDATA)>
+<!ATTLIST CalculatedExponent Subband CDATA #REQUIRED>
+<!-- /QuantizationDefault -->
+ <!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->
+ <!-- and any other component, with main-header quantization values different from [0], as QCC. -->
+<!ELEMENT QuantizationComponent (Sqcc,SPqcc)>
+<!ATTLIST QuantizationComponent Marker CDATA #FIXED "QCC">
+<!ATTLIST QuantizationComponent Component CDATA #REQUIRED>
+<!ELEMENT Sqcc (AsHex | (AsHex,QuantizationStyle,NumberOfGuardBits) | (QuantizationStyle,NumberOfGuardBits))>
+<!ELEMENT SPqcc (ReversibleStepSizeValue | QuantizationStepSizeValues )> <!-- TO DO: Irreversible choices -->
+<!-- /QuantizationComponent -->
+<!-- Don't know if MJ2 files can have regions of interest. Assume yes -->
+<!ELEMENT RegionOfInterest (Srgn,Crgn,Sprgn)> <!-- Optional in main header, at most 1 per component -->
+<!ATTLIST RegionOfInterest Marker CDATA #FIXED "RGN">
+<!ELEMENT Srgn (#PCDATA)> <!-- ROI style. Only style=0 defined: Implicit ROI (max. shift) -->
+<!ELEMENT Crgn (#PCDATA)> <!-- Zero-based component number. -->
+<!ELEMENT SPrgn (#PCDATA)> <!-- Implicit ROI shift, i.e., binary shifting of ROI coefficients above background. -->
+<!-- </RegionOfInterest> -->
+<!ELEMENT ProgressionOrderChange (Progression+)> <!-- Optional in main header, at most 1 per component (but impl allows more?) -->
+<!ATTLIST ProgressionOrderChange Marker CDATA #REQUIRED>
+<!ELEMENT Progression (RSpoc,CSpoc,LYEpoc,REpoc,CEpoc,Ppoc)>
+<!ATTLIST Progression Num CDATA #REQUIRED>
+<!ELEMENT RSpoc (#PCDATA)> <!-- Resolution level index (inclusive) for progression start. Range: 0 to 33 -->
+<!ELEMENT CSpoc (#PCDATA)> <!-- Component index (inclusive) for progression start. -->
+<!ELEMENT LYEpoc (#PCDATA)> <!-- Layer index (exclusive) for progression end. -->
+<!ELEMENT REpoc (#PCDATA)> <!-- Resolution level index (exclusive) for progression end. Range: RSpoc to 33 -->
+<!ELEMENT CEpoc (#PCDATA)> <!-- Component index (exclusive) for progression end. Minimum: CSpoc -->
+<!ELEMENT Ppoc (#PCDATA)> <!-- Defined Progression Order Values are: -->
+ <!-- 0 = LRCP; 1 = RLCP; 2 = RPCL; 3 = PCRL; 4 = CPRL -->
+ <!-- where L = "layer", R = "resolution level", C = "component", P = "position". -->
+<!-- </Progression>, </ProgressionOrderChange -->
+<!-- /MainHeader -->
+<!ELEMENT TilePartHeaders (TilePartHeader+)>
+<!ATTLIST TilePartHeaders Count CDATA #REQUIRED>
+<!ELEMENT TilePartHeader (StartOfTilePart,CodingStyleDefault,QuantizationDefault,QuantizationComponent*,RegionOfInterest?,ProgressionOrderChange*,StartOfData)>
+<!ATTLIST TilePartHeader Num CDATA #REQUIRED>
+<!ATTLIST TilePartHeader ID CDATA #REQUIRED>
+<!ELEMENT StartOfTilePart EMPTY>
+<!ATTLIST StartOfTilePart Marker CDATA #FIXED "SOT">
+<!-- CodingStyleDefault, QuantizationDefault, QuantizationComponent already defined -->
+ <!-- mj2_to_metadata implementation always reports component[0] as using default QCD, -->
+ <!-- and any other component, with tile-part-header quantization values different from [0], as QCC. -->
+<!ELEMENT StartOfData EMPTY> <!-- always empty for now -->
+<!ATTLIST StartOfData Marker CDATA #FIXED "SOD">
+ <!-- Tile-part bitstream, not shown, follows tile-part header and SOD marker. -->
+<!-- /TilePartHeader, /TilePartHeaders, /JP2_Frame -->
+<!-- </Track> -->
+
+<!-- to come:
+ <MovieExtends mvek> // possibly not in Simple Profile
+ <UserDataBox udat> contains <CopyrightBox cprt>
+ -->
+<!-- /MovieBox -->
+<!-- To come:
+ <mdat>
+ <moof> // probably not in Simple Profile
+ <free>
+ <skip>
+ -->
+<!-- </MJ2_File> --> \ No newline at end of file
diff --git a/src/bin/mj2/mj2_to_metadata.h b/src/bin/mj2/mj2_to_metadata.h
new file mode 100644
index 00000000..f4c34919
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata.h
@@ -0,0 +1,9 @@
+/* mj2_to_metadata.h */
+/* Dump MJ2, JP2 metadata (partial so far) to xml file */
+/* Contributed to Open JPEG by Glenn Pearson, U.S. National Library of Medicine */
+
+#define BOOL int
+#define FALSE 0
+#define TRUE 1
+
+#include "meta_out.h"
diff --git a/src/bin/mj2/mj2_to_metadata.sln b/src/bin/mj2/mj2_to_metadata.sln
new file mode 100644
index 00000000..32b926d4
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mj2_to_metadata", "mj2_to_metadata.vcproj", "{69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD} = {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibOpenJPEG", "..\LibOpenJPEG.vcproj", "{0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}.Debug|Win32.Build.0 = Debug|Win32
+ {69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}.Release|Win32.ActiveCfg = Release|Win32
+ {69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}.Release|Win32.Build.0 = Release|Win32
+ {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}.Debug|Win32.Build.0 = Debug|Win32
+ {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}.Release|Win32.ActiveCfg = Release|Win32
+ {0B1B7713-35B6-40A7-9BFF-A7D0EB06A8BD}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/bin/mj2/mj2_to_metadata.vcproj b/src/bin/mj2/mj2_to_metadata.vcproj
new file mode 100644
index 00000000..b280bfe5
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata.vcproj
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="mj2_to_metadata"
+ ProjectGUID="{69BE42AB-E7CE-4DA1-BBD2-39FEA2C91E0B}"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\mj2_to_metadata___Win32_Debug0"
+ IntermediateDirectory=".\mj2_to_metadata___Win32_Debug0"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../libopenjpeg"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.pch"
+ AssemblerListingLocation=".\mj2_to_metadata___Win32_Debug0/"
+ ObjectFile=".\mj2_to_metadata___Win32_Debug0/"
+ ProgramDataBaseFileName=".\mj2_to_metadata___Win32_Debug0/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.exe"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="LIBCMT"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\mj2_to_metadata___Win32_Debug0/mj2_to_metadata.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/mj2_to_metadata.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../libopenjpeg"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Release/mj2_to_metadata.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/mj2_to_metadata.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ IgnoreDefaultLibraryNames="libcmtd"
+ ProgramDatabaseFile=".\Release/mj2_to_metadata.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Release/mj2_to_metadata.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="MJ2"
+ >
+ <Filter
+ Name="MJ2 Header Files"
+ >
+ <File
+ RelativePath="compat\opj_getopt.h"
+ >
+ </File>
+ <File
+ RelativePath="meta_out.h"
+ >
+ </File>
+ <File
+ RelativePath="mj2.h"
+ >
+ </File>
+ <File
+ RelativePath="mj2_convert.h"
+ >
+ </File>
+ <File
+ RelativePath="mj2_to_metadata.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MJ2 Source Files"
+ >
+ <File
+ RelativePath="compat\opj_getopt.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="meta_out.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mj2.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mj2_convert.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mj2_to_metadata.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/bin/mj2/mj2_to_metadata_Notes.doc b/src/bin/mj2/mj2_to_metadata_Notes.doc
new file mode 100644
index 00000000..05ccec20
--- /dev/null
+++ b/src/bin/mj2/mj2_to_metadata_Notes.doc
Binary files differ
diff --git a/src/bin/mj2/readme.txt b/src/bin/mj2/readme.txt
new file mode 100644
index 00000000..9419d2a2
--- /dev/null
+++ b/src/bin/mj2/readme.txt
@@ -0,0 +1,3 @@
+Attention : the motion jpeg 2000 files currently only work with OpenJPEG v0.97 that you can find here :
+
+http://www.openjpeg.org/openjpeg_v097.tar.gz \ No newline at end of file
diff --git a/src/bin/mj2/wrap_j2k_in_mj2.c b/src/bin/mj2/wrap_j2k_in_mj2.c
new file mode 100644
index 00000000..7ce88677
--- /dev/null
+++ b/src/bin/mj2/wrap_j2k_in_mj2.c
@@ -0,0 +1,523 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openjpeg.h"
+#include "cio.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "mj2.h"
+
+static int int_ceildiv(int a, int b) {
+ return (a + b - 1) / b;
+}
+
+/**
+Size of memory first allocated for MOOV box
+*/
+#define TEMP_BUF 10000
+
+#define ENUMCS_GRAY 16
+#define ENUMCS_SRGB 17
+#define ENUMCS_SYCC 18
+
+#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
+
+/* -------------------------------------------------------------------------- */
+
+static int test_image(const char *fname, mj2_cparameters_t *cp)
+{
+ FILE *reader;
+ opj_image_t *image;
+ unsigned char *src;
+ opj_dinfo_t *dinfo;
+ opj_cio_t *cio;
+ opj_dparameters_t dparameters;
+ int success;
+ long src_len;
+
+ success = 0;
+
+ if((reader = fopen(fname, "rb")) == NULL) return success;
+
+ fseek(reader, 0, SEEK_END);
+ src_len = ftell(reader);
+ fseek(reader, 0, SEEK_SET);
+ src = (unsigned char*) malloc(src_len);
+ fread(src, 1, src_len, reader);
+ fclose(reader);
+
+ if(memcmp(src, J2K_CODESTREAM_MAGIC, 4) != 0)
+ {
+ free(src); return success;
+ }
+ memset(&dparameters, 0, sizeof(opj_dparameters_t));
+
+ opj_set_default_decoder_parameters(&dparameters);
+
+ dinfo = opj_create_decompress(CODEC_J2K);
+
+ opj_setup_decoder(dinfo, &dparameters);
+
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, src_len);
+
+ image = opj_decode(dinfo, cio);
+
+ free(src); cio->buffer = NULL;
+ opj_cio_close(cio);
+
+ if(image == NULL) goto fin;
+
+ cp->numcomps = image->numcomps;
+ cp->w = image->comps[0].w;
+ cp->h = image->comps[0].h;
+ cp->prec = image->comps[0].prec;
+
+ if(image->numcomps > 2 )
+ {
+ if((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 2)
+ && (image->comps[2].dx == 2)
+ && (image->comps[0].dy == 1)
+ && (image->comps[1].dy == 2)
+ && (image->comps[2].dy == 2))// horizontal and vertical
+ {
+// Y420
+ cp->enumcs = ENUMCS_SYCC;
+ cp->CbCr_subsampling_dx = 2;
+ cp->CbCr_subsampling_dy = 2;
+ }
+ else
+ if((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 2)
+ && (image->comps[2].dx == 2)
+ && (image->comps[0].dy == 1)
+ && (image->comps[1].dy == 1)
+ && (image->comps[2].dy == 1))// horizontal only
+ {
+// Y422
+ cp->enumcs = ENUMCS_SYCC;
+ cp->CbCr_subsampling_dx = 2;
+ cp->CbCr_subsampling_dy = 1;
+ }
+ else
+ if((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 1)
+ && (image->comps[2].dx == 1)
+ && (image->comps[0].dy == 1)
+ && (image->comps[1].dy == 1)
+ && (image->comps[2].dy == 1))
+ {
+// Y444 or RGB
+
+ if(image->color_space == CLRSPC_SRGB)
+ {
+ cp->enumcs = ENUMCS_SRGB;
+
+// cp->CbCr_subsampling_dx = 0;
+// cp->CbCr_subsampling_dy = 0;
+ }
+ else
+ {
+ cp->enumcs = ENUMCS_SYCC;
+
+ cp->CbCr_subsampling_dx = 1;
+ cp->CbCr_subsampling_dy = 1;
+ }
+ }
+ else
+ {
+ goto fin;
+ }
+ }
+ else
+ {
+ cp->enumcs = ENUMCS_GRAY;
+// cp->CbCr_subsampling_dx = 0;
+// cp->CbCr_subsampling_dy = 0;
+ }
+ if(image->icc_profile_buf)
+ {
+ cp->meth = 2;
+ free(image->icc_profile_buf); image->icc_profile_buf = NULL;
+ }
+ else cp->meth = 1;
+
+ success = 1;
+fin:
+ if(dinfo)
+ opj_destroy_decompress(dinfo);
+
+ if(image)
+ opj_image_destroy(image);
+
+ return success;
+}
+
+/**
+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);
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+
+static void read_siz_marker(FILE *file, opj_image_t *image)
+{
+ int len,i;
+ char buf, buf2[2];
+ unsigned char *siz_buffer;
+ opj_cio_t *cio;
+
+ fseek(file, 0, SEEK_SET);
+ do {
+ fread(&buf,1,1, file);
+ if (buf==(char)0xff)
+ fread(&buf,1,1, file);
+ }
+ while (!(buf==(char)0x51));
+
+ fread(buf2,2,1,file); /* Lsiz */
+ len = ((buf2[0])<<8) + buf2[1];
+
+ siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char));
+ fread(siz_buffer,len, 1, file);
+ cio = opj_cio_open(NULL, siz_buffer, len);
+
+ cio_read(cio, 2); /* Rsiz (capabilities) */
+ image->x1 = cio_read(cio, 4); /* Xsiz */
+ image->y1 = cio_read(cio, 4); /* Ysiz */
+ image->x0 = cio_read(cio, 4); /* X0siz */
+ image->y0 = cio_read(cio, 4); /* Y0siz */
+ cio_skip(cio, 16); /* XTsiz, YTsiz, XT0siz, YT0siz */
+
+ image->numcomps = cio_read(cio,2); /* Csiz */
+ image->comps =
+ (opj_image_comp_t *) malloc(image->numcomps * sizeof(opj_image_comp_t));
+
+ for (i = 0; i < image->numcomps; i++) {
+ int tmp;
+ tmp = cio_read(cio,1); /* Ssiz_i */
+ image->comps[i].prec = (tmp & 0x7f) + 1;
+ image->comps[i].sgnd = tmp >> 7;
+ image->comps[i].dx = cio_read(cio,1); /* XRsiz_i */
+ image->comps[i].dy = cio_read(cio,1); /* YRsiz_i */
+ image->comps[i].resno_decoded = 0; /* number of resolution decoded */
+ image->comps[i].factor = 0; /* reducing factor by component */
+ }
+ fseek(file, 0, SEEK_SET);
+ opj_cio_close(cio);
+ free(siz_buffer);
+}
+
+static void setparams(opj_mj2_t *movie, opj_image_t *image) {
+ int i, depth_0, depth, sign;
+
+ movie->tk[0].w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
+ movie->tk[0].h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
+ mj2_init_stdmovie(movie);
+
+ movie->tk[0].depth = image->comps[0].prec;
+
+ if (image->numcomps==3) {
+ if ((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 1)
+ && (image->comps[2].dx == 1))
+ movie->tk[0].CbCr_subsampling_dx = 1;
+ else
+ if ((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 2)
+ && (image->comps[2].dx == 2))
+ movie->tk[0].CbCr_subsampling_dx = 2;
+ else
+ fprintf(stderr,"Image component sizes are incoherent\n");
+
+ if ((image->comps[0].dy == 1)
+ && (image->comps[1].dy == 1)
+ && (image->comps[2].dy == 1))
+ movie->tk[0].CbCr_subsampling_dy = 1;
+ else
+ if ((image->comps[0].dy == 1)
+ && (image->comps[1].dy == 2)
+ && (image->comps[2].dy == 2))
+ movie->tk[0].CbCr_subsampling_dy = 2;
+ else
+ fprintf(stderr,"Image component sizes are incoherent\n");
+ }
+
+ movie->tk[0].sample_rate = 25;
+
+ movie->tk[0].jp2_struct.numcomps = image->numcomps; // NC
+
+ /* Init Standard jp2 structure */
+
+ movie->tk[0].jp2_struct.comps =
+ (opj_jp2_comps_t *) malloc(movie->tk[0].jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
+ movie->tk[0].jp2_struct.precedence = 0; /* PRECEDENCE*/
+ movie->tk[0].jp2_struct.approx = 0; /* APPROX*/
+ movie->tk[0].jp2_struct.brand = JP2_JP2; /* BR */
+ movie->tk[0].jp2_struct.minversion = 0; /* MinV */
+ movie->tk[0].jp2_struct.numcl = 1;
+ movie->tk[0].jp2_struct.cl = (unsigned int *) malloc(movie->tk[0].jp2_struct.numcl * sizeof(int));
+ movie->tk[0].jp2_struct.cl[0] = JP2_JP2; /* CL0 : JP2 */
+ movie->tk[0].jp2_struct.C = 7; /* C : Always 7*/
+ movie->tk[0].jp2_struct.UnkC = 0; /* UnkC, colorspace specified in colr box*/
+ movie->tk[0].jp2_struct.IPR = 0; /* IPR, no intellectual property*/
+ movie->tk[0].jp2_struct.w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
+ movie->tk[0].jp2_struct.h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
+
+ depth_0 = image->comps[0].prec - 1;
+ sign = image->comps[0].sgnd;
+ movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7);
+
+ for (i = 1; i < image->numcomps; i++) {
+ depth = image->comps[i].prec - 1;
+ sign = image->comps[i].sgnd;
+ if (depth_0 != depth)
+ movie->tk[0].jp2_struct.bpc = 255;
+ }
+
+ for (i = 0; i < image->numcomps; i++)
+ movie->tk[0].jp2_struct.comps[i].bpcc =
+ image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
+
+ if ((image->numcomps == 1 || image->numcomps == 3)
+ && (movie->tk[0].jp2_struct.bpc != 255))
+ movie->tk[0].jp2_struct.meth = 1;
+ else
+ movie->tk[0].jp2_struct.meth = 2;
+
+ if (image->numcomps == 1)
+ movie->tk[0].jp2_struct.enumcs = 17; // Grayscale
+
+ else
+ if ((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 1)
+ && (image->comps[2].dx == 1)
+ && (image->comps[0].dy == 1)
+ && (image->comps[1].dy == 1)
+ && (image->comps[2].dy == 1))
+ movie->tk[0].jp2_struct.enumcs = 16; // RGB
+
+ else
+ if ((image->comps[0].dx == 1)
+ && (image->comps[1].dx == 2)
+ && (image->comps[2].dx == 2)
+ && (image->comps[0].dy == 1)
+ && (image->comps[1].dy == 2)
+ && (image->comps[2].dy == 2))
+ movie->tk[0].jp2_struct.enumcs = 18; // YUV
+
+ else
+ movie->tk[0].jp2_struct.enumcs = 0; // Unkown profile */
+}
+
+int main(int argc, char *argv[]) {
+ opj_cinfo_t* cinfo;
+ opj_event_mgr_t event_mgr; /* event manager */
+ unsigned int snum;
+ opj_mj2_t *movie;
+ mj2_sample_t *sample;
+ unsigned char* frame_codestream;
+ FILE *mj2file, *j2kfile;
+ char *j2kfilename;
+ unsigned char *buf;
+ int offset, mdat_initpos;
+ opj_image_t img;
+ opj_cio_t *cio;
+ mj2_cparameters_t parameters;
+
+ if (argc != 3) {
+ printf("Usage: %s source_location mj2_filename\n",argv[0]);
+ printf("Example: %s input/input output.mj2\n",argv[0]);
+ return 1;
+ }
+
+ mj2file = fopen(argv[2], "wb");
+
+ if (!mj2file) {
+ fprintf(stderr, "failed to open %s for writing\n", argv[2]);
+ return 1;
+ }
+ memset(&img, 0, sizeof(opj_image_t));
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = info_callback;
+
+ /* get a MJ2 decompressor handle */
+ cinfo = mj2_create_compress();
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+
+ /* setup the decoder encoding parameters using user parameters */
+ memset(&parameters, 0, sizeof(mj2_cparameters_t));
+ movie = (opj_mj2_t*) cinfo->mj2_handle;
+
+ j2kfilename = (char*)malloc(strlen(argv[1]) + 12);/* max. '%6d' */
+ sprintf(j2kfilename, "%s_00001.j2k",argv[1]);
+
+ if(test_image(j2kfilename, &parameters) == 0) goto fin;
+
+ parameters.frame_rate = 25; /* DEFAULT */
+
+ mj2_setup_encoder(movie, &parameters);
+
+
+ /* Writing JP, FTYP and MDAT boxes
+ Assuming that the JP and FTYP boxes won't be longer than 300 bytes */
+
+ buf = (unsigned char*) malloc (300 * sizeof(unsigned char));
+ cio = opj_cio_open(movie->cinfo, buf, 300);
+ mj2_write_jp(cio);
+ mj2_write_ftyp(movie, cio);
+ mdat_initpos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio,MJ2_MDAT, 4);
+ fwrite(buf,cio_tell(cio),1,mj2file);
+ free(buf);
+
+ // Insert each j2k codestream in a JP2C box
+ snum=0;
+ offset = 0;
+ while(1)
+ {
+ sample = &movie->tk[0].sample[snum];
+ sprintf(j2kfilename,"%s_%05d.j2k",argv[1],snum);
+ j2kfile = fopen(j2kfilename, "rb");
+ if (!j2kfile) {
+ if (snum==0) { // Could not open a single codestream
+ fprintf(stderr, "failed to open %s for reading\n",j2kfilename);
+ return 1;
+ }
+ else { // Tried to open a inexistant codestream
+ fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum);
+ break;
+ }
+ }
+
+ // Calculating offset for samples and chunks
+ offset += cio_tell(cio);
+ sample->offset = offset;
+ movie->tk[0].chunk[snum].offset = offset; // There will be one sample per chunk
+
+ // Calculating sample size
+ fseek(j2kfile,0,SEEK_END);
+ sample->sample_size = ftell(j2kfile) + 8; // Sample size is codestream + JP2C box header
+ fseek(j2kfile,0,SEEK_SET);
+
+ // Reading siz marker of j2k image for the first codestream
+ if (snum==0)
+ read_siz_marker(j2kfile, &img);
+
+ // Writing JP2C box header
+ frame_codestream = (unsigned char*) malloc (sample->sample_size+8);
+ cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size);
+ cio_write(cio,sample->sample_size, 4); // Sample size
+ cio_write(cio,JP2_JP2C, 4); // JP2C
+
+ // Writing codestream from J2K file to MJ2 file
+ fread(frame_codestream+8,sample->sample_size-8,1,j2kfile);
+ fwrite(frame_codestream,sample->sample_size,1,mj2file);
+ cio_skip(cio, sample->sample_size-8);
+
+ // Ending loop
+ fclose(j2kfile);
+ snum++;
+ mj2_sample_t * new_sample = (mj2_sample_t*)
+ realloc(movie->tk[0].sample, (snum+1) * sizeof(mj2_sample_t));
+ mj2_chunk_t * new_chunk = (mj2_chunk_t*)
+ realloc(movie->tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t));
+ if (new_sample && new_chunk) {
+ movie->tk[0].sample = new_sample;
+ movie->tk[0].chunk = new_chunk;
+ } else {
+ fprintf(stderr, "Failed to allocate enough memory to read %s\n", j2kfilename);
+ return 1;
+ }
+ free(frame_codestream);
+ }
+
+ // Writing the MDAT box length in header
+ offset += cio_tell(cio);
+ buf = (unsigned char*) malloc (4 * sizeof(unsigned char));
+ cio = opj_cio_open(movie->cinfo, buf, 4);
+ cio_write(cio,offset-mdat_initpos,4);
+ fseek(mj2file,(long)mdat_initpos,SEEK_SET);
+ fwrite(buf,4,1,mj2file);
+ fseek(mj2file,0,SEEK_END);
+ free(buf);
+
+ // Setting movie parameters
+ movie->tk[0].num_samples=snum;
+ movie->tk[0].num_chunks=snum;
+ setparams(movie, &img);
+
+ // Writing MOOV box
+ buf = (unsigned char*) malloc ((TEMP_BUF+snum*20) * sizeof(unsigned char));
+ cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+snum*20));
+ mj2_write_moov(movie, cio);
+ fwrite(buf,cio_tell(cio),1,mj2file);
+
+ // Ending program
+ free(img.comps);
+ opj_cio_close(cio);
+
+fin:
+ fclose(mj2file);
+ mj2_destroy_compress(movie);
+ free(j2kfilename);
+
+ return 0;
+}
diff --git a/src/bin/wx/CMakeLists.txt b/src/bin/wx/CMakeLists.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/bin/wx/CMakeLists.txt
diff --git a/src/bin/wx/OPJViewer/CMakeLists.txt b/src/bin/wx/OPJViewer/CMakeLists.txt
new file mode 100644
index 00000000..34442848
--- /dev/null
+++ b/src/bin/wx/OPJViewer/CMakeLists.txt
@@ -0,0 +1,25 @@
+project(viewer CXX)
+
+find_package(wxWidgets REQUIRED)
+include(${wxWidgets_USE_FILE})
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ )
+
+# original flags:
+# -DUSE_JPWL -DwxUSE_LIBOPENJPEG -DwxUSE_GUI=1 -DOPJ_STATIC -DOPJ_HTMLABOUT -DOPJ_INICONFIG -DUSE_JPSEC -DOPJ_MANYFORMATS
+add_definitions(-DwxUSE_LIBOPENJPEG -DOPENJPEG_VERSION="1.5.0")
+set(OPJV_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/imagjpeg2000.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/wxj2kparser.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/OPJViewer.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/wxjp2parser.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/OPJDialogs.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/OPJThreads.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/source/OPJAbout.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../codec/index.c
+ )
+add_executable(opjviewer ${OPJV_SRCS})
+target_link_libraries(opjviewer ${wxWidgets_LIBRARIES} openjpeg)
diff --git a/src/bin/wx/OPJViewer/OPJViewer.iss b/src/bin/wx/OPJViewer/OPJViewer.iss
new file mode 100644
index 00000000..0cf20da9
--- /dev/null
+++ b/src/bin/wx/OPJViewer/OPJViewer.iss
@@ -0,0 +1,48 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+[Setup]
+AppName=OPJViewer
+AppVerName=OPJViewer 0.4 beta
+AppPublisher=OpenJPEG
+AppPublisherURL=http://www.openjpeg.org
+AppSupportURL=http://www.openjpeg.org
+AppUpdatesURL=http://www.openjpeg.org
+DefaultDirName={pf}\OPJViewer
+DefaultGroupName=OPJViewer
+OutputDir=setup
+OutputBaseFilename=OPJViewer04beta_setup
+Compression=lzma
+SolidCompression=true
+InfoBeforeFile=source\readmebefore.txt
+InfoAfterFile=source\readmeafter.txt
+LicenseFile=source\license.txt
+VersionInfoVersion=0.4.0.0
+VersionInfoCompany=OpenJPEG
+VersionInfoDescription=JPEG 2000 viewer
+ShowLanguageDialog=yes
+SetupIconFile=source\OPJViewer.ico
+
+[Languages]
+Name: english; MessagesFile: compiler:Default.isl
+
+[Tasks]
+Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked
+
+[Files]
+Source: Release\OPJViewer.exe; DestDir: {app}; Flags: ignoreversion
+;Source: about\about.htm; DestDir: {app}/about; Flags: ignoreversion
+;Source: about\opj_logo.png; DestDir: {app}/about; Flags: ignoreversion
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: {group}\OPJViewer; Filename: {app}\OPJViewer.exe; WorkingDir: {app}; IconIndex: 0
+Name: {group}\{cm:UninstallProgram,OPJViewer}; Filename: {uninstallexe}
+Name: {userdesktop}\OPJViewer; Filename: {app}\OPJViewer.exe; Tasks: desktopicon; WorkingDir: {app}; IconIndex: 0
+
+[Run]
+Filename: {app}\OPJViewer.exe; Description: {cm:LaunchProgram,OPJViewer}; Flags: nowait postinstall skipifsilent; WorkingDir: {app}
+
+[Registry]
+Root: HKCU; Subkey: Software\OpenJPEG; ValueType: none; ValueData: 1; Flags: uninsdeletekey; Tasks: ; Languages:
+Root: HKCU; Subkey: Software\OpenJPEG\OPJViewer; ValueType: none; ValueData: 1; Flags: uninsdeletekey; Tasks: ; Languages:
diff --git a/src/bin/wx/OPJViewer/Readme.txt b/src/bin/wx/OPJViewer/Readme.txt
new file mode 100644
index 00000000..fe104bbf
--- /dev/null
+++ b/src/bin/wx/OPJViewer/Readme.txt
@@ -0,0 +1,100 @@
+===============================================================================
+ JPEG2000 Visualization Software - OPJViewer
+
+ Version 0.4 beta
+===============================================================================
+
+
+1. Scope
+=============
+
+This document describes the installation and use of the OPJViewer in the framework of OpenJPEG library.
+
+This implementation has been developed using the OpenJPEG library as decoding engine and wxWidgets 2.8 as GUI engine.
+
+If you find some bugs or if you have problems using the viewer, please send an e-mail to jpwl@diei.unipg.it
+
+2. Installing the viewer
+==========================
+
+There are two options available, at the moment:
+
+a) compile from source code
+b) download a precompiled binary.
+
+In order to use option a), it is mandatory to have compiled and built the LibOpenJPEG_JPWL library and the wxWidgets 2.8 framework (you have to download it from http://www.wxwidgets.org/ and compile the wx* libraries).
+
+2.1. Compiling the source code in Windows
+-------------------------------------------
+
+The steps required to compile the viewer under windows are:
+
+a) Download at least the libopenjpeg, jpwl, and opjviewer folders from the SVN trunk.
+b) Open the OPJViewer.dsw workspace with Visual C++ 6 and activate the "OPJViewer - Win32 Release" configuration.
+c) In the configuration settings, go to the C++ tab and modify the wxWidgets paths in order to reflect your wx* install configuration (Preprocessor -> Additional include directories): simply update each instance of the two wx paths, do not remove or add them.
+d) In the configuration settings, go to the Link tab and modify the wxWidgets path in order to reflect your wx* install configuration (Input -> Additional library path): simply update the wx path.
+e) In the configuration settings, go to the Resources tab and modify the wxWidgets path in order to reflect your wx* install configuration (Additional resource include directories): simply update the wx path.
+f) Build!
+g) Run!
+h) (OPTIONAL) Prepare an installer by compiling the InnoSetup script OPJViewer.iss (you need to download InnoSetup from http://www.jrsoftware.org/isinfo.php).
+
+2.1.1 Additional libraries
+----------------------------
+
+Since we are also working on the Digital Cinema JPEG 2000, we are integrating the viewer with the MXF library, which is used to prepare the DCPs for digital movies. You can enable its linking in the code by specifying the USE_MXF preprocessor directive but, remember, the integration is at a very early stage.
+
+2.2. Compiling the source code in Unix-like systems
+-----------------------------------------------------
+
+The porting is possible and under way.
+
+
+3. General information on the viewer
+====================================
+
+This viewer is conceived to open and display information and image content of J2K, JP2, and MJ2 files.
+The viewer application interface is divided into three main panels:
+- a browsing pane;
+- a viewing pane;
+- a log/peek pane.
+
+The browsing pane will present the markers or boxes hierarchy, with position (byte number where marker/box starts and stops) and length information (i.e., inner length as signalled by marker/box and total length, with marker/box sign included), in the following form:
+
+filename
+|
+|_ #000: Marker/Box short name (Hex code)
+| |
+| |_ *** Marker/Box long name ***
+| |_ startbyte > stopbyte, inner_length + marker/box sign length (total length)
+| |_ Additional info, depending on the marker/box type
+| |_ ...
+|
+|_ #001: Marker/Box short name (Hex code)
+| |
+| |_ ...
+|
+...
+
+
+The viewing pane will display the decoded image contained in the JPEG 2000 file.
+It should display correctly images as large as 4000x2000, provided that a couple of GB of RAM are available. Nothing is known about the display of larger sizes: let us know if you manage to get it working.
+
+
+The log/peek pane is shared among two different subpanels:
+
+- the log panel will report a lot of debugging info coming out from the wx GUI as well as from the openjpeg library
+- the peek pane tries to give a peek on the codestream/file portion which is currently selected in the browsing pane. It shows both hex and ascii values corresponding to the marker/box section.
+
+
+4. Known bugs and limitations
+===============================
+
+4.1. Bugs
+-----------
+
+*
+
+4.2. Limitations
+------------------
+
+* For mj2 files, rendering is only in B/W
diff --git a/src/bin/wx/OPJViewer/about/about.htm b/src/bin/wx/OPJViewer/about/about.htm
new file mode 100644
index 00000000..cdde9773
--- /dev/null
+++ b/src/bin/wx/OPJViewer/about/about.htm
@@ -0,0 +1,36 @@
+<html>
+<body bgcolor="#FFFFFF">
+<table cellspacing=7 cellpadding=1 border=0 width="100%">
+<tr>
+<td rowspan=3 valign=top align=center width=70>
+<img src="opj_logo.png"><br><br>
+</td>
+<td align=center>
+<font size=+2 color="#000000"><b>OPJViewer v0.2 alpha</b></font><br>
+<font size=+0 color="#000000"><b>A JPEG 2000 image viewer</b></font>
+</td>
+</tr>
+<tr height=3 valign=center>
+<td valign=center bgcolor=#cc3300></td>
+</tr>
+<tr>
+<td align=justify>
+<center><font size=+0 color="#000000"><a href="http://www.openjpeg.org/">OpenJPEG</a></font></center>
+<font size=-1 color="#000000">The OpenJPEG library is an open-source JPEG 2000 codec written in C language.
+In addition to the basic codec, various other features are under development,
+among them the JP2 and MJ2 (Motion JPEG 2000) file formats, an indexing tool
+useful for the JPIP protocol, JPWL-tools for error-resilience, ...</font>
+</td>
+</tr>
+<tr>
+<td colspan=2 bgcolor="#CC3300" height=3 valign=center></td>
+</tr>
+<tr>
+<td colspan=2>
+<font size=-2 color="#444444">OpenJPEG is &copy; 2002-2007 <a href="http://www.tele.ucl.ac.be/">TELE</a> - <a href="http://www.uclouvain.be/">Université Catholique de Louvain</a></font><br>
+<font size=-2 color="#444444">OPJViewer is also &copy; 2005-2007 <a href="http://dsplab.diei.unipg.it/">DSPLab</a> - <a href="http://www.unipg.it/">Università degli studi di Perugia</a></font>
+</td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/src/bin/wx/OPJViewer/about/opj_logo.png b/src/bin/wx/OPJViewer/about/opj_logo.png
new file mode 100644
index 00000000..0f43840a
--- /dev/null
+++ b/src/bin/wx/OPJViewer/about/opj_logo.png
Binary files differ
diff --git a/src/bin/wx/OPJViewer/source/OPJAbout.cpp b/src/bin/wx/OPJViewer/source/OPJAbout.cpp
new file mode 100644
index 00000000..f988c727
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJAbout.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita'  degli studi di Perugia (UPG), Italy
+ * 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 USE_MXF
+#include "mxflib/mxflib.h"
+#endif // USE_MXF
+
+#include "OPJViewer.h"
+
+// about window for the frame
+void OPJFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+#ifdef OPJ_HTMLABOUT
+#include "about_htm.h"
+#include "opj_logo.xpm"
+
+ wxBoxSizer *topsizer;
+ wxHtmlWindow *html;
+ wxDialog dlg(this, wxID_ANY, wxString(_("About")));
+
+ wxMemoryFSHandler::AddFile(wxT("opj_logo.xpm"), wxBitmap(opj_logo), wxBITMAP_TYPE_XPM);
+
+ topsizer = new wxBoxSizer(wxVERTICAL);
+
+ html = new wxHtmlWindow(&dlg, wxID_ANY, wxDefaultPosition, wxSize(320, 250), wxHW_SCROLLBAR_NEVER);
+ html->SetBorders(0);
+ //html->LoadPage(wxT("about/about.htm"));
+ //html->SetPage("<html><body>Hello, world!</body></html>");
+ html->SetPage(htmlaboutpage);
+ html->SetSize(html->GetInternalRepresentation()->GetWidth(),
+ html->GetInternalRepresentation()->GetHeight());
+
+ topsizer->Add(html, 1, wxALL, 10);
+
+ topsizer->Add(new wxStaticLine(&dlg, wxID_ANY), 0, wxEXPAND | wxLEFT | wxRIGHT, 10);
+
+ wxButton *bu1 = new wxButton(&dlg, wxID_OK, wxT("OK"));
+ bu1->SetDefault();
+
+ topsizer->Add(bu1, 0, wxALL | wxALIGN_RIGHT, 15);
+
+ dlg.SetSizer(topsizer);
+ topsizer->Fit(&dlg);
+
+ dlg.ShowModal();
+
+#else
+
+ wxMessageBox(wxString::Format(OPJ_APPLICATION_TITLEBAR
+ wxT("\n\n")
+ wxT("Built with %s and OpenJPEG ")
+ wxT(OPENJPEG_VERSION)
+ wxT("\non ") wxT(__DATE__) wxT(", ") wxT(__TIME__)
+ wxT("\nRunning under %s\n\n")
+ OPJ_APPLICATION_COPYRIGHT,
+ wxVERSION_STRING,
+ wxGetOsDescription().c_str()),
+ wxT("About ") OPJ_APPLICATION_NAME,
+ wxOK | wxICON_INFORMATION,
+ this
+ );
+
+#endif
+
+}
diff --git a/src/bin/wx/OPJViewer/source/OPJChild.ico b/src/bin/wx/OPJViewer/source/OPJChild.ico
new file mode 100644
index 00000000..7a127189
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJChild.ico
Binary files differ
diff --git a/src/bin/wx/OPJViewer/source/OPJChild16.xpm b/src/bin/wx/OPJViewer/source/OPJChild16.xpm
new file mode 100644
index 00000000..99b7b2cf
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJChild16.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *OPJChild16[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 6 1",
+" c black",
+". c #008000",
+"X c red",
+"o c #800080",
+"O c gray100",
+"+ c None",
+/* pixels */
+"++++++++++++++++",
+"+OOOOOOOOOOOOOO+",
+"+OooooooooooooO+",
+"+OooooooooooooO+",
+"+OooOOOOOOOOOoO+",
+"+OooO.......OoO+",
+"+OooO.......OoO+",
+"+OooO..OOO..OoO+",
+"+OooO..OXO..OoO+",
+"+OooO..OOO..OoO+",
+"+OooO.......OoO+",
+"+OooO.......OoO+",
+"+OooOOOOOOOOOoO+",
+"+OooooooooooooO+",
+"+OOOOOOOOOOOOOO+",
+"++++++++++++++++"
+};
diff --git a/src/bin/wx/OPJViewer/source/OPJDialogs.cpp b/src/bin/wx/OPJViewer/source/OPJDialogs.cpp
new file mode 100644
index 00000000..ff96da9c
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJDialogs.cpp
@@ -0,0 +1,1373 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita'  degli studi di Perugia (UPG), Italy
+ * 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 "OPJViewer.h"
+
+// ----------------------------------------------------------------------------
+// OPJDecoderDialog
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(OPJDecoderDialog, wxPropertySheetDialog)
+
+BEGIN_EVENT_TABLE(OPJDecoderDialog, wxPropertySheetDialog)
+ EVT_CHECKBOX(OPJDECO_ENABLEDECO, OPJDecoderDialog::OnEnableDeco)
+#ifdef USE_JPWL
+ EVT_CHECKBOX(OPJDECO_ENABLEJPWL, OPJDecoderDialog::OnEnableJPWL)
+#endif // USE_JPWL
+END_EVENT_TABLE()
+
+OPJDecoderDialog::OPJDecoderDialog(wxWindow* win, int dialogType)
+{
+ SetExtraStyle(wxDIALOG_EX_CONTEXTHELP|wxWS_EX_VALIDATE_RECURSIVELY);
+
+ Create(win, wxID_ANY, wxT("Decoder settings"),
+ wxDefaultPosition, wxDefaultSize,
+ wxDEFAULT_DIALOG_STYLE| (int) wxPlatform::IfNot(wxOS_WINDOWS_CE, wxRESIZE_BORDER)
+ );
+
+ CreateButtons(wxOK | wxCANCEL | (int)wxPlatform::IfNot(wxOS_WINDOWS_CE, wxHELP));
+
+ m_settingsNotebook = GetBookCtrl();
+
+ wxPanel* mainSettings = CreateMainSettingsPage(m_settingsNotebook);
+ wxPanel* jpeg2000Settings = CreatePart1SettingsPage(m_settingsNotebook);
+ if (!wxGetApp().m_enabledeco)
+ jpeg2000Settings->Enable(false);
+ wxPanel* mjpeg2000Settings = CreatePart3SettingsPage(m_settingsNotebook);
+ if (!wxGetApp().m_enabledeco)
+ mjpeg2000Settings->Enable(false);
+#ifdef USE_JPWL
+ wxPanel* jpwlSettings = CreatePart11SettingsPage(m_settingsNotebook);
+ if (!wxGetApp().m_enabledeco)
+ jpwlSettings->Enable(false);
+#endif // USE_JPWL
+
+ m_settingsNotebook->AddPage(mainSettings, wxT("Display"), false);
+ m_settingsNotebook->AddPage(jpeg2000Settings, wxT("JPEG 2000"), false);
+ m_settingsNotebook->AddPage(mjpeg2000Settings, wxT("MJPEG 2000"), false);
+#ifdef USE_JPWL
+ m_settingsNotebook->AddPage(jpwlSettings, wxT("JPWL"), false);
+#endif // USE_JPWL
+
+ LayoutDialog();
+}
+
+OPJDecoderDialog::~OPJDecoderDialog()
+{
+}
+
+wxPanel* OPJDecoderDialog::CreateMainSettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // sub top sizer
+ wxBoxSizer *subtopSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add decoding enabling check box
+ subtopSizer->Add(
+ m_enabledecoCheck = new wxCheckBox(panel, OPJDECO_ENABLEDECO, wxT("Enable decoding"), wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 5);
+ m_enabledecoCheck->SetValue(wxGetApp().m_enabledeco);
+
+ // add parsing enabling check box
+ subtopSizer->Add(
+ m_enableparseCheck = new wxCheckBox(panel, OPJDECO_ENABLEPARSE, wxT("Enable parsing"), wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 5);
+ m_enableparseCheck->SetValue(wxGetApp().m_enableparse);
+
+ // resize settings, column
+ wxString choices[] = {wxT("Don't resize"), wxT("Low quality"), wxT("High quality")};
+ m_resizeBox = new wxRadioBox(panel, OPJDECO_RESMETHOD,
+ wxT("Resize method"),
+ wxDefaultPosition, wxDefaultSize,
+ WXSIZEOF(choices),
+ choices,
+ 1,
+ wxRA_SPECIFY_ROWS);
+ m_resizeBox->SetSelection(wxGetApp().m_resizemethod + 1);
+
+ subtopSizer->Add(m_resizeBox, 0, wxGROW | wxALL, 5);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+wxPanel* OPJDecoderDialog::CreatePart3SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add some space
+ //topSizer->AddSpacer(5);
+
+ // sub top sizer
+ wxBoxSizer *subtopSizer = new wxBoxSizer(wxVERTICAL);
+
+ // frame settings, column
+ wxStaticBox* frameBox = new wxStaticBox(panel, wxID_ANY, wxT("Frame"));
+ wxBoxSizer* frameSizer = new wxStaticBoxSizer(frameBox, wxVERTICAL);
+
+ // selected frame number, row
+ wxBoxSizer* framenumSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ framenumSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Displayed frame:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ framenumSizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ framenumSizer->Add(
+ m_framenumCtrl = new wxSpinCtrl(panel, OPJDECO_FRAMENUM,
+ wxString::Format(wxT("%d"), wxGetApp().m_framenum),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 1, 100000, wxGetApp().m_framenum),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+
+ frameSizer->Add(framenumSizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(frameSizer, 0, wxGROW | wxALL, 5);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+wxPanel* OPJDecoderDialog::CreatePart1SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add some space
+ //topSizer->AddSpacer(5);
+
+ // sub top sizer
+ wxBoxSizer *subtopSizer = new wxBoxSizer(wxVERTICAL);
+
+ // resolutions settings, column
+ wxStaticBox* resolutionBox = new wxStaticBox(panel, wxID_ANY, wxT("Resolutions"));
+ wxBoxSizer* resolutionSizer = new wxStaticBoxSizer(resolutionBox, wxVERTICAL);
+
+ // reduce factor sizer, row
+ wxBoxSizer* reduceSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ reduceSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Reduce factor:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ reduceSizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ reduceSizer->Add(
+ m_reduceCtrl = new wxSpinCtrl(panel, OPJDECO_REDUCEFACTOR,
+ wxString::Format(wxT("%d"), wxGetApp().m_reducefactor),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 10000, wxGetApp().m_reducefactor),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+
+ resolutionSizer->Add(reduceSizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(resolutionSizer, 0, wxGROW | wxALL, 5);
+
+ // quality layer settings, column
+ wxStaticBox* layerBox = new wxStaticBox(panel, wxID_ANY, wxT("Layers"));
+ wxBoxSizer* layerSizer = new wxStaticBoxSizer(layerBox, wxVERTICAL);
+
+ // quality layers sizer, row
+ wxBoxSizer* qualitySizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ qualitySizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Quality layers:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ qualitySizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ qualitySizer->Add(
+ m_layerCtrl = new wxSpinCtrl(panel, OPJDECO_QUALITYLAYERS,
+ wxString::Format(wxT("%d"), wxGetApp().m_qualitylayers),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 100000, wxGetApp().m_qualitylayers),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+
+ layerSizer->Add(qualitySizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(layerSizer, 0, wxGROW | wxALL, 5);
+
+ // component settings, column
+ wxStaticBox* compoBox = new wxStaticBox(panel, wxID_ANY, wxT("Components"));
+ wxBoxSizer* compoSizer = new wxStaticBoxSizer(compoBox, wxVERTICAL);
+
+ // quality layers sizer, row
+ wxBoxSizer* numcompsSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ numcompsSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Component displayed:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ numcompsSizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ numcompsSizer->Add(
+ m_numcompsCtrl = new wxSpinCtrl(panel, OPJDECO_NUMCOMPS,
+ wxString::Format(wxT("%d"), wxGetApp().m_components),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 100000, wxGetApp().m_components),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+ m_numcompsCtrl->Enable(true);
+
+ compoSizer->Add(numcompsSizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(compoSizer, 0, wxGROW | wxALL, 5);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+#ifdef USE_JPWL
+wxPanel* OPJDecoderDialog::CreatePart11SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add some space
+ //topSizer->AddSpacer(5);
+
+ // sub top sizer
+ wxBoxSizer *subtopSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add JPWL enabling check box
+ subtopSizer->Add(
+ m_enablejpwlCheck = new wxCheckBox(panel, OPJDECO_ENABLEJPWL, wxT("Enable JPWL"), wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 5);
+ m_enablejpwlCheck->SetValue(wxGetApp().m_enablejpwl);
+
+ // component settings, column
+ wxStaticBox* compoBox = new wxStaticBox(panel, wxID_ANY, wxT("Components"));
+ wxBoxSizer* compoSizer = new wxStaticBoxSizer(compoBox, wxVERTICAL);
+
+ // expected components sizer, row
+ wxBoxSizer* expcompsSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ expcompsSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Expected comps.:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ expcompsSizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ expcompsSizer->Add(
+ m_expcompsCtrl = new wxSpinCtrl(panel, OPJDECO_EXPCOMPS,
+ wxString::Format(wxT("%d"), wxGetApp().m_expcomps),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 1, 100000, wxGetApp().m_expcomps),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+ m_expcompsCtrl->Enable(wxGetApp().m_enablejpwl);
+
+ compoSizer->Add(expcompsSizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(compoSizer, 0, wxGROW | wxALL, 5);
+
+ // tiles settings, column
+ wxStaticBox* tileBox = new wxStaticBox(panel, wxID_ANY, wxT("Tiles"));
+ wxBoxSizer* tileSizer = new wxStaticBoxSizer(tileBox, wxVERTICAL);
+
+ // maximum tiles sizer, row
+ wxBoxSizer* maxtileSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ maxtileSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Max. no. of tiles:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+
+ // add some horizontal space
+ maxtileSizer->Add(5, 5, 1, wxALL, 0);
+
+ // add the value control
+ maxtileSizer->Add(
+ m_maxtilesCtrl = new wxSpinCtrl(panel, OPJDECO_MAXTILES,
+ wxString::Format(wxT("%d"), wxGetApp().m_maxtiles),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 1, 100000, wxGetApp().m_maxtiles),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
+ m_maxtilesCtrl->Enable(wxGetApp().m_enablejpwl);
+
+ tileSizer->Add(maxtileSizer, 0, wxGROW | wxALL, 5);
+
+ subtopSizer->Add(tileSizer, 0, wxGROW | wxALL, 5);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+void OPJDecoderDialog::OnEnableJPWL(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("JPWL enabled"));
+ m_expcompsCtrl->Enable(true);
+ m_maxtilesCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("JPWL disabled"));
+ m_expcompsCtrl->Enable(false);
+ m_maxtilesCtrl->Enable(false);
+ }
+
+}
+
+#endif // USE_JPWL
+
+void OPJDecoderDialog::OnEnableDeco(wxCommandEvent& event)
+{
+ size_t pp;
+
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("Decoding enabled"));
+ m_resizeBox->Enable(true);
+ // enable all tabs except ourselves
+ for (pp = 0; pp < m_settingsNotebook->GetPageCount(); pp++) {
+ if (m_settingsNotebook->GetPageText(pp) != wxT("Display"))
+ m_settingsNotebook->GetPage(pp)->Enable(true);
+ }
+ } else {
+ wxLogMessage(wxT("Decoding disabled"));
+ m_resizeBox->Enable(false);
+ // disable all tabs except ourselves
+ for (pp = 0; pp < m_settingsNotebook->GetPageCount(); pp++) {
+ if (m_settingsNotebook->GetPageText(pp) != wxT("Display"))
+ m_settingsNotebook->GetPage(pp)->Enable(false);
+ }
+ }
+
+}
+
+
+
+
+// ----------------------------------------------------------------------------
+// OPJEncoderDialog
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_CLASS(OPJEncoderDialog, wxPropertySheetDialog)
+
+BEGIN_EVENT_TABLE(OPJEncoderDialog, wxPropertySheetDialog)
+ EVT_CHECKBOX(OPJENCO_ENABLECOMM, OPJEncoderDialog::OnEnableComm)
+ EVT_CHECKBOX(OPJENCO_ENABLEINDEX, OPJEncoderDialog::OnEnableIdx)
+ EVT_CHECKBOX(OPJENCO_ENABLEPOC, OPJEncoderDialog::OnEnablePoc)
+ EVT_RADIOBUTTON(OPJENCO_RATERADIO, OPJEncoderDialog::OnRadioQualityRate)
+ EVT_RADIOBUTTON(OPJENCO_QUALITYRADIO, OPJEncoderDialog::OnRadioQualityRate)
+#ifdef USE_JPWL
+ EVT_CHECKBOX(OPJENCO_ENABLEJPWL, OPJEncoderDialog::OnEnableJPWL)
+ EVT_CHOICE(OPJENCO_HPROT, OPJEncoderDialog::OnHprotSelect)
+ EVT_CHOICE(OPJENCO_PPROT, OPJEncoderDialog::OnPprotSelect)
+ EVT_CHOICE(OPJENCO_SENSI, OPJEncoderDialog::OnSensiSelect)
+#endif // USE_JPWL
+END_EVENT_TABLE()
+
+OPJEncoderDialog::OPJEncoderDialog(wxWindow* win, int dialogType)
+{
+ SetExtraStyle(wxDIALOG_EX_CONTEXTHELP|wxWS_EX_VALIDATE_RECURSIVELY);
+
+ Create(win, wxID_ANY, wxT("Encoder settings"),
+ wxDefaultPosition, wxDefaultSize,
+ wxDEFAULT_DIALOG_STYLE| (int) wxPlatform::IfNot(wxOS_WINDOWS_CE, wxRESIZE_BORDER)
+ );
+
+ CreateButtons(wxOK | wxCANCEL | (int)wxPlatform::IfNot(wxOS_WINDOWS_CE, wxHELP));
+
+ m_settingsNotebook = GetBookCtrl();
+
+ wxPanel* jpeg2000_1Settings = CreatePart1_1SettingsPage(m_settingsNotebook);
+ wxPanel* jpeg2000_2Settings = CreatePart1_2SettingsPage(m_settingsNotebook);
+ wxPanel* mainSettings = CreateMainSettingsPage(m_settingsNotebook);
+#ifdef USE_JPWL
+ wxPanel* jpwlSettings = CreatePart11SettingsPage(m_settingsNotebook);
+#endif // USE_JPWL
+
+#ifdef USE_JPWL
+ m_settingsNotebook->AddPage(jpwlSettings, wxT("JPWL"), false);
+#endif // USE_JPWL
+ m_settingsNotebook->AddPage(jpeg2000_1Settings, wxT("JPEG 2000 - 1"), false);
+ m_settingsNotebook->AddPage(jpeg2000_2Settings, wxT("JPEG 2000 - 2"), false);
+ m_settingsNotebook->AddPage(mainSettings, wxT("General"), false);
+
+ LayoutDialog();
+}
+
+OPJEncoderDialog::~OPJEncoderDialog()
+{
+}
+
+wxPanel* OPJEncoderDialog::CreateMainSettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // sub top sizer
+ wxBoxSizer *subtopSizer = new wxBoxSizer(wxVERTICAL);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+#ifdef USE_JPWL
+wxPanel* OPJEncoderDialog::CreatePart11SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+ int specno;
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add JPWL enabling check box
+ topSizer->Add(
+ m_enablejpwlCheck = new wxCheckBox(panel, OPJENCO_ENABLEJPWL, wxT("Enable JPWL"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL | wxALIGN_CENTER, 5);
+ m_enablejpwlCheck->SetValue(wxGetApp().m_enablejpwle);
+
+ // sub top sizer
+ wxFlexGridSizer *subtopSizer = new wxFlexGridSizer(2, 3, 3);
+
+ // header settings, column
+ wxStaticBox* headerBox = new wxStaticBox(panel, wxID_ANY, wxT("Header protection"));
+ wxBoxSizer* headerSizer = new wxStaticBoxSizer(headerBox, wxVERTICAL);
+
+ // info sizer, row
+ wxBoxSizer* info1Sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ info1Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Type")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ // add some horizontal space
+ info1Sizer->Add(3, 3, 1, wxALL, 0);
+
+ // add some text
+ info1Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Tile part")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ headerSizer->Add(info1Sizer, 0, wxGROW | wxALL, 0);
+
+ // specify specs
+ wxString hprotvalues[] = {wxT("None"), wxT("Pred."), wxT("CRC16"), wxT("CRC32"),
+ wxT("RS37"), wxT("RS38"), wxT("RS40"), wxT("RS43"), wxT("RS45"), wxT("RS48"),
+ wxT("RS51"), wxT("RS53"), wxT("RS56"), wxT("RS64"), wxT("RS75"), wxT("RS80"),
+ wxT("RS85"), wxT("RS96"), wxT("RS112"), wxT("RS128")};
+ for (specno = 0; specno < MYJPWL_MAX_NO_TILESPECS; specno++) {
+
+ // tile+hprot sizer, row
+ wxBoxSizer* tilehprotSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add the value selection
+ tilehprotSizer->Add(
+ m_hprotChoice[specno] = new wxChoice(panel, OPJENCO_HPROT,
+ wxDefaultPosition, wxSize(60, wxDefaultCoord),
+ WXSIZEOF(hprotvalues), hprotvalues),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+ m_hprotChoice[specno]->SetSelection(wxGetApp().m_hprotsel[specno]);
+
+ // add some horizontal space
+ tilehprotSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilehprotSizer->Add(
+ m_htileCtrl[specno] = new wxSpinCtrl(panel, OPJENCO_HTILE,
+ wxString::Format(wxT("%d"), wxGetApp().m_htileval[specno]),
+ wxDefaultPosition, wxSize(45, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, JPWL_MAXIMUM_TILES - 1, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+
+ headerSizer->Add(tilehprotSizer, 0, wxGROW | wxALL, 0);
+ }
+
+ wxCommandEvent event1;
+ OnHprotSelect(event1);
+
+ subtopSizer->Add(headerSizer, 0, wxGROW | wxALL, 3);
+
+ // packet settings, column
+ wxStaticBox* packetBox = new wxStaticBox(panel, wxID_ANY, wxT("Packet protection"));
+ wxBoxSizer* packetSizer = new wxStaticBoxSizer(packetBox, wxVERTICAL);
+
+ // info sizer, row
+ wxBoxSizer* info2Sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ info2Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Type")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ // add some horizontal space
+ info2Sizer->Add(3, 3, 1, wxALL, 0);
+
+ // add some text
+ info2Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Tile part")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ // add some horizontal space
+ info2Sizer->Add(3, 3, 1, wxALL, 0);
+
+ // add some text
+ info2Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Packet")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ packetSizer->Add(info2Sizer, 0, wxGROW | wxALL, 0);
+
+ // specify specs
+ wxString pprotvalues[] = {wxT("None"), wxT("Pred."), wxT("CRC16"), wxT("CRC32"),
+ wxT("RS37"), wxT("RS38"), wxT("RS40"), wxT("RS43"), wxT("RS45"), wxT("RS48"),
+ wxT("RS51"), wxT("RS53"), wxT("RS56"), wxT("RS64"), wxT("RS75"), wxT("RS80"),
+ wxT("RS85"), wxT("RS96"), wxT("RS112"), wxT("RS128")};
+ for (specno = 0; specno < MYJPWL_MAX_NO_TILESPECS; specno++) {
+
+ // tile+pprot sizer, row
+ wxBoxSizer* tilepprotSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add the value selection
+ tilepprotSizer->Add(
+ m_pprotChoice[specno] = new wxChoice(panel, OPJENCO_PPROT,
+ wxDefaultPosition, wxSize(60, wxDefaultCoord),
+ WXSIZEOF(pprotvalues), pprotvalues),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+ m_pprotChoice[specno]->SetSelection(wxGetApp().m_pprotsel[specno]);
+
+ // add some horizontal space
+ tilepprotSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilepprotSizer->Add(
+ m_ptileCtrl[specno] = new wxSpinCtrl(panel, OPJENCO_PTILE,
+ wxString::Format(wxT("%d"), wxGetApp().m_ptileval[specno]),
+ wxDefaultPosition, wxSize(45, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, JPWL_MAXIMUM_TILES - 1, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+
+ // add some horizontal space
+ tilepprotSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilepprotSizer->Add(
+ m_ppackCtrl[specno] = new wxSpinCtrl(panel, OPJENCO_PPACK,
+ wxString::Format(wxT("%d"), wxGetApp().m_ppackval[specno]),
+ wxDefaultPosition, wxSize(50, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 2047, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+
+ packetSizer->Add(tilepprotSizer, 0, wxGROW | wxALL, 0);
+ }
+
+ wxCommandEvent event2;
+ OnPprotSelect(event2);
+
+ subtopSizer->Add(packetSizer, 0, wxGROW | wxALL, 3);
+
+ // sensitivity settings, column
+ wxStaticBox* sensiBox = new wxStaticBox(panel, wxID_ANY, wxT("Sensitivity"));
+ wxBoxSizer* sensiSizer = new wxStaticBoxSizer(sensiBox, wxVERTICAL);
+
+ // info sizer, row
+ wxBoxSizer* info3Sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ info3Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Type")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ // add some horizontal space
+ info3Sizer->Add(3, 3, 1, wxALL, 0);
+
+ // add some text
+ info3Sizer->Add(new wxStaticText(panel, wxID_ANY,
+ wxT("Tile part")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 1);
+
+ sensiSizer->Add(info3Sizer, 0, wxGROW | wxALL, 0);
+
+ // specify specs
+ wxString sensivalues[] = {wxT("None"), wxT("RELATIVE ERROR"), wxT("MSE"),
+ wxT("MSE REDUCTION"), wxT("PSNR INCREMENT"), wxT("MAXERR"), wxT("TSE")};
+ for (specno = 0; specno < MYJPWL_MAX_NO_TILESPECS; specno++) {
+
+ // tile+sensi sizer, row
+ wxBoxSizer* tilesensiSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add the value selection
+ tilesensiSizer->Add(
+ m_sensiChoice[specno] = new wxChoice(panel, OPJENCO_SENSI,
+ wxDefaultPosition, wxSize(110, wxDefaultCoord),
+ WXSIZEOF(sensivalues), sensivalues),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+ m_sensiChoice[specno]->SetSelection(wxGetApp().m_sensisel[specno]);
+
+ // add some horizontal space
+ tilesensiSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilesensiSizer->Add(
+ m_stileCtrl[specno] = new wxSpinCtrl(panel, OPJENCO_STILE,
+ wxString::Format(wxT("%d"), wxGetApp().m_stileval[specno]),
+ wxDefaultPosition, wxSize(45, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, JPWL_MAXIMUM_TILES - 1, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 1);
+
+ sensiSizer->Add(tilesensiSizer, 0, wxGROW | wxALL, 0);
+ }
+
+ wxCommandEvent event3;
+ OnSensiSelect(event3);
+
+ subtopSizer->Add(sensiSizer, 0, wxGROW | wxALL, 3);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+#endif // USE_JPWL
+
+wxPanel* OPJEncoderDialog::CreatePart1_1SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add some space
+ //topSizer->AddSpacer(5);
+
+ // sub top sizer
+ wxFlexGridSizer *subtopSizer = new wxFlexGridSizer(2, 3, 3);
+
+ // image settings, column
+ wxStaticBox* imageBox = new wxStaticBox(panel, wxID_ANY, wxT("Image"));
+ wxBoxSizer* imageSizer = new wxStaticBoxSizer(imageBox, wxVERTICAL);
+
+ // subsampling factor sizer, row
+ wxBoxSizer* subsSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ subsSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Subsampling:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ subsSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ subsSizer->Add(
+ m_subsamplingCtrl = new wxTextCtrl(panel, OPJENCO_SUBSAMPLING,
+ wxGetApp().m_subsampling,
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ imageSizer->Add(subsSizer, 0, wxGROW | wxALL, 3);
+
+ // origin sizer, row
+ wxBoxSizer* imorigSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ imorigSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Origin:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ imorigSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ imorigSizer->Add(
+ m_originCtrl = new wxTextCtrl(panel, OPJENCO_IMORIG,
+ wxGetApp().m_origin,
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ imageSizer->Add(imorigSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(imageSizer, 0, wxGROW | wxALL, 3);
+
+ // layer settings, column
+ wxStaticBox* layerBox = new wxStaticBox(panel, wxID_ANY, wxT("Layers/compression"));
+ wxBoxSizer* layerSizer = new wxStaticBoxSizer(layerBox, wxVERTICAL);
+
+ // rate factor sizer, row
+ wxBoxSizer* rateSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ /*rateSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Rate values:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);*/
+
+ // add the radio button
+ rateSizer->Add(
+ m_rateRadio = new wxRadioButton(panel, OPJENCO_RATERADIO, wxT("&Rate values"),
+ wxDefaultPosition, wxDefaultSize,
+ wxRB_GROUP),
+ 0, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
+ );
+ m_rateRadio->SetValue(!(wxGetApp().m_enablequality));
+
+ // add some horizontal space
+ rateSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ rateSizer->Add(
+ m_rateCtrl = new wxTextCtrl(panel, OPJENCO_RATEFACTOR,
+ wxGetApp().m_rates,
+ wxDefaultPosition, wxSize(100, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ if (wxGetApp().m_enablequality == true)
+ m_rateCtrl->Enable(false);
+
+ layerSizer->Add(rateSizer, 0, wxGROW | wxALL, 3);
+
+ // quality factor sizer, row
+ wxBoxSizer* qualitySizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ /*qualitySizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Quality values:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);*/
+
+ // add the radio button
+ qualitySizer->Add(
+ m_qualityRadio = new wxRadioButton(panel, OPJENCO_QUALITYRADIO, wxT("&Quality values"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxALL | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
+ );
+ m_qualityRadio->SetValue(wxGetApp().m_enablequality);
+
+ // add some horizontal space
+ qualitySizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ qualitySizer->Add(
+ m_qualityCtrl = new wxTextCtrl(panel, OPJENCO_QUALITYFACTOR,
+ wxGetApp().m_quality,
+ wxDefaultPosition, wxSize(100, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ if (wxGetApp().m_enablequality == false)
+ m_qualityCtrl->Enable(false);
+
+ layerSizer->Add(qualitySizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(layerSizer, 0, wxGROW | wxALL, 3);
+
+ // wavelet settings, column
+ wxStaticBox* transformBox = new wxStaticBox(panel, wxID_ANY, wxT("Transforms"));
+ wxBoxSizer* transformSizer = new wxStaticBoxSizer(transformBox, wxVERTICAL);
+
+ // multiple component check box
+ transformSizer->Add(
+ m_mctCheck = new wxCheckBox(panel, OPJENCO_ENABLEMCT, wxT("Multiple component"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_mctCheck->SetValue(wxGetApp().m_multicomp);
+
+ // irreversible wavelet check box
+ transformSizer->Add(
+ m_irrevCheck = new wxCheckBox(panel, OPJENCO_ENABLEIRREV, wxT("Irreversible wavelet"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_irrevCheck->SetValue(wxGetApp().m_irreversible);
+
+ // resolution number sizer, row
+ wxBoxSizer* resnumSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ resnumSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Resolutions:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ resnumSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ resnumSizer->Add(
+ m_resolutionsCtrl = new wxSpinCtrl(panel, OPJENCO_RESNUMBER,
+ wxString::Format(wxT("%d"), wxGetApp().m_resolutions),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 1, 256, 6),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ transformSizer->Add(resnumSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(transformSizer, 0, wxGROW | wxALL, 3);
+
+ // codestream settings, column
+ wxStaticBox* codestreamBox = new wxStaticBox(panel, wxID_ANY, wxT("Codestream"));
+ wxBoxSizer* codestreamSizer = new wxStaticBoxSizer(codestreamBox, wxVERTICAL);
+
+ // codeblock sizer, row
+ wxBoxSizer* codeblockSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ codeblockSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Codeblocks size:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ codeblockSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ codeblockSizer->Add(
+ m_cbsizeCtrl = new wxTextCtrl(panel, OPJENCO_CODEBLOCKSIZE,
+ wxGetApp().m_cbsize,
+ wxDefaultPosition, wxSize(100, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ codestreamSizer->Add(codeblockSizer, 0, wxGROW | wxALL, 3);
+
+ // precinct sizer, row
+ wxBoxSizer* precinctSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ precinctSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Precincts size:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ precinctSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ precinctSizer->Add(
+ m_prsizeCtrl = new wxTextCtrl(panel, OPJENCO_PRECINCTSIZE,
+ wxGetApp().m_prsize,
+ wxDefaultPosition, wxSize(100, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ codestreamSizer->Add(precinctSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(codestreamSizer, 0, wxGROW | wxALL, 3);
+
+ // tile settings, column
+ wxStaticBox* tileBox = new wxStaticBox(panel, wxID_ANY, wxT("Tiles"));
+ wxBoxSizer* tileSizer = new wxStaticBoxSizer(tileBox, wxVERTICAL);
+
+ // tile size sizer, row
+ wxBoxSizer* tilesizeSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ tilesizeSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Size:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ tilesizeSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilesizeSizer->Add(
+ m_tsizeCtrl = new wxTextCtrl(panel, OPJENCO_TILESIZE,
+ wxGetApp().m_tsize,
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ tileSizer->Add(tilesizeSizer, 0, wxGROW | wxALL, 3);
+
+ // tile origin sizer, row
+ wxBoxSizer* tilorigSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ tilorigSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Origin:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ tilorigSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ tilorigSizer->Add(
+ m_toriginCtrl = new wxTextCtrl(panel, OPJENCO_TILORIG,
+ wxGetApp().m_torigin,
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ tileSizer->Add(tilorigSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(tileSizer, 0, wxGROW | wxALL, 3);
+
+ // progression and profile settings, column
+ wxString choices[] = {wxT("LRCP"), wxT("RLCP"), wxT("RPCL"), wxT("PCRL"), wxT("CPRL"),
+ wxT("DCI2K24"), wxT("DCI2K48"), wxT("DCI4K")};
+ progressionBox = new wxRadioBox(panel, OPJENCO_PROGRESSION,
+ wxT("Progression order/profile"),
+ wxDefaultPosition, wxDefaultSize,
+ WXSIZEOF(choices),
+ choices,
+ 3,
+ wxRA_SPECIFY_COLS);
+ progressionBox->SetSelection(wxGetApp().m_progression);
+
+ subtopSizer->Add(progressionBox, 0, wxGROW | wxALL, 3);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+wxPanel* OPJEncoderDialog::CreatePart1_2SettingsPage(wxWindow* parent)
+{
+ wxPanel* panel = new wxPanel(parent, wxID_ANY);
+
+ // top sizer
+ wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // add some space
+ //topSizer->AddSpacer(5);
+
+ // sub top sizer
+ wxFlexGridSizer *subtopSizer = new wxFlexGridSizer(2, 3, 3);
+
+ // resilience settings, column
+ wxStaticBox* resilBox = new wxStaticBox(panel, wxID_ANY, wxT("Error resilience"));
+ wxBoxSizer* resilSizer = new wxStaticBoxSizer(resilBox, wxVERTICAL);
+
+ // resil2 sizer, row
+ wxBoxSizer* resil2Sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // SOP check box
+ resil2Sizer->Add(
+ m_sopCheck = new wxCheckBox(panel, OPJENCO_ENABLESOP, wxT("SOP"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_sopCheck->SetValue(wxGetApp().m_enablesop);
+
+ // EPH check box
+ resil2Sizer->Add(
+ m_ephCheck = new wxCheckBox(panel, OPJENCO_ENABLEEPH, wxT("EPH"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_ephCheck->SetValue(wxGetApp().m_enableeph);
+
+ resilSizer->Add(resil2Sizer, 0, wxGROW | wxALL, 3);
+
+ // separation
+ resilSizer->Add(new wxStaticLine(panel, wxID_ANY), 0, wxEXPAND | wxLEFT | wxRIGHT, 3);
+
+ // resil3 sizer, row
+ wxFlexGridSizer* resil3Sizer = new wxFlexGridSizer(3, 3, 3);
+
+ // BYPASS check box
+ resil3Sizer->Add(
+ m_enablebypassCheck = new wxCheckBox(panel, OPJENCO_ENABLEBYPASS, wxT("BYPASS"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablebypassCheck->SetValue(wxGetApp().m_enablebypass);
+
+ // RESET check box
+ resil3Sizer->Add(
+ m_enableresetCheck = new wxCheckBox(panel, OPJENCO_ENABLERESET, wxT("RESET"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enableresetCheck->SetValue(wxGetApp().m_enablereset);
+
+ // RESTART check box
+ resil3Sizer->Add(
+ m_enablerestartCheck = new wxCheckBox(panel, OPJENCO_ENABLERESTART, wxT("RESTART"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablerestartCheck->SetValue(wxGetApp().m_enablerestart);
+
+ // VSC check box
+ resil3Sizer->Add(
+ m_enablevscCheck = new wxCheckBox(panel, OPJENCO_ENABLEVSC, wxT("VSC"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablevscCheck->SetValue(wxGetApp().m_enablevsc);
+
+ // ERTERM check box
+ resil3Sizer->Add(
+ m_enableertermCheck = new wxCheckBox(panel, OPJENCO_ENABLEERTERM, wxT("ERTERM"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enableertermCheck->SetValue(wxGetApp().m_enableerterm);
+
+ // SEGMARK check box
+ resil3Sizer->Add(
+ m_enablesegmarkCheck = new wxCheckBox(panel, OPJENCO_ENABLESEGMARK, wxT("SEGMARK"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablesegmarkCheck->SetValue(wxGetApp().m_enablesegmark);
+
+ resilSizer->Add(resil3Sizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(resilSizer, 0, wxGROW | wxALL, 3);
+
+ // ROI settings, column
+ wxStaticBox* roiBox = new wxStaticBox(panel, wxID_ANY, wxT("Region Of Interest"));
+ wxBoxSizer* roiSizer = new wxStaticBoxSizer(roiBox, wxVERTICAL);
+
+ // component number sizer, row
+ wxBoxSizer* roicompSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ roicompSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Component:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ roicompSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ roicompSizer->Add(
+ /*m_layerCtrl =*/ new wxSpinCtrl(panel, OPJENCO_ROICOMP,
+ wxT("0"),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 256, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ roiSizer->Add(roicompSizer, 0, wxGROW | wxALL, 3);
+
+ // upshift sizer, row
+ wxBoxSizer* roishiftSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ roishiftSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Upshift:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ roishiftSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ roishiftSizer->Add(
+ /*m_layerCtrl =*/ new wxSpinCtrl(panel, OPJENCO_ROISHIFT,
+ wxT("0"),
+ wxDefaultPosition, wxSize(80, wxDefaultCoord),
+ wxSP_ARROW_KEYS,
+ 0, 37, 0),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+
+ roiSizer->Add(roishiftSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(roiSizer, 0, wxGROW | wxALL, 3);
+
+ // POC settings, column
+ wxStaticBox* pocBox = new wxStaticBox(panel, wxID_ANY, wxT("POC"));
+ wxBoxSizer* pocSizer = new wxStaticBoxSizer(pocBox, wxVERTICAL);
+
+ // POC check box
+ pocSizer->Add(
+ m_enablepocCheck = new wxCheckBox(panel, OPJENCO_ENABLEPOC, wxT("Enabled (tn=rs,cs,le,re,ce,pr)"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablepocCheck->SetValue(wxGetApp().m_enablepoc);
+
+ // POC sizer, row
+ wxBoxSizer* pocspecSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ pocspecSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Changes:")),
+ 0, wxALL | wxALIGN_TOP, 3);
+
+ // add some horizontal space
+ pocspecSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ pocspecSizer->Add(
+ m_pocCtrl = new wxTextCtrl(panel, OPJENCO_POCSPEC,
+ wxGetApp().m_poc,
+ wxDefaultPosition, wxSize(140, 60),
+ wxTE_LEFT | wxTE_MULTILINE),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ m_pocCtrl->Enable(wxGetApp().m_enablepoc);
+
+ pocSizer->Add(pocspecSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(pocSizer, 0, wxGROW | wxALL, 3);
+
+ // Comment settings, column
+ wxStaticBox* commentBox = new wxStaticBox(panel, wxID_ANY, wxT("Comment"));
+ wxBoxSizer* commentSizer = new wxStaticBoxSizer(commentBox, wxVERTICAL);
+
+ // commenting check box
+ commentSizer->Add(
+ m_enablecommCheck = new wxCheckBox(panel, OPJENCO_ENABLECOMM, wxT("Enabled (empty to reset)"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablecommCheck->SetValue(wxGetApp().m_enablecomm);
+
+ // add some horizontal space
+ commentSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ commentSizer->Add(
+ m_commentCtrl = new wxTextCtrl(panel, OPJENCO_COMMENTTEXT,
+ wxGetApp().m_comment,
+ wxDefaultPosition, wxSize(wxDefaultCoord, 60),
+ wxTE_LEFT | wxTE_MULTILINE),
+ 0, wxGROW | wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ m_commentCtrl->Enable(wxGetApp().m_enablecomm);
+
+ subtopSizer->Add(commentSizer, 0, wxGROW | wxALL, 3);
+
+ // Index file settings, column
+ wxStaticBox* indexBox = new wxStaticBox(panel, wxID_ANY, wxT("Indexing"));
+ wxBoxSizer* indexSizer = new wxStaticBoxSizer(indexBox, wxVERTICAL);
+
+ // indexing check box
+ indexSizer->Add(
+ m_enableidxCheck = new wxCheckBox(panel, OPJENCO_ENABLEINDEX, wxT("Enabled"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enableidxCheck->SetValue(wxGetApp().m_enableidx);
+
+ // index file sizer, row
+ wxBoxSizer* indexnameSizer = new wxBoxSizer(wxHORIZONTAL);
+
+ // add some text
+ indexnameSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&File name:")),
+ 0, wxALL | wxALIGN_CENTER_VERTICAL, 3);
+
+ // add some horizontal space
+ indexnameSizer->Add(3, 3, 1, wxALL, 0);
+
+ // add the value control
+ indexnameSizer->Add(
+ m_indexCtrl = new wxTextCtrl(panel, OPJENCO_INDEXNAME,
+ wxGetApp().m_index,
+ wxDefaultPosition, wxSize(120, wxDefaultCoord),
+ wxTE_LEFT),
+ 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ m_indexCtrl->Enable(wxGetApp().m_enableidx);
+
+ indexSizer->Add(indexnameSizer, 0, wxGROW | wxALL, 3);
+
+ subtopSizer->Add(indexSizer, 0, wxGROW | wxALL, 3);
+
+ topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
+
+ // assign top and fit it
+ panel->SetSizer(topSizer);
+ topSizer->Fit(panel);
+
+ return panel;
+}
+
+void OPJEncoderDialog::OnEnableComm(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("Comment enabled"));
+ m_commentCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("Comment disabled"));
+ m_commentCtrl->Enable(false);
+ }
+
+}
+
+void OPJEncoderDialog::OnEnableIdx(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("Index enabled"));
+ m_indexCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("Index disabled"));
+ m_indexCtrl->Enable(false);
+ }
+
+}
+
+void OPJEncoderDialog::OnEnablePoc(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("POC enabled"));
+ m_pocCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("POC disabled"));
+ m_pocCtrl->Enable(false);
+ }
+
+}
+
+void OPJEncoderDialog::OnRadioQualityRate(wxCommandEvent& event)
+{
+ if (event.GetId() == OPJENCO_QUALITYRADIO) {
+ wxLogMessage(wxT("Quality selected"));
+ m_rateCtrl->Enable(false);
+ m_qualityCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("Rate selected"));
+ m_rateCtrl->Enable(true);
+ m_qualityCtrl->Enable(false);
+ }
+}
+
+#ifdef USE_JPWL
+void OPJEncoderDialog::OnEnableJPWL(wxCommandEvent& event)
+{
+ int specno;
+
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("JPWL enabled"));
+ for (specno = 0; specno < MYJPWL_MAX_NO_TILESPECS; specno++) {
+ m_hprotChoice[specno]->Enable(true);
+ m_htileCtrl[specno]->Enable(true);
+ m_pprotChoice[specno]->Enable(true);
+ m_ptileCtrl[specno]->Enable(true);
+ m_ppackCtrl[specno]->Enable(true);
+ m_sensiChoice[specno]->Enable(true);
+ m_stileCtrl[specno]->Enable(true);
+ }
+ OnHprotSelect(event);
+ OnPprotSelect(event);
+ OnSensiSelect(event);
+ } else {
+ wxLogMessage(wxT("JPWL disabled"));
+ for (specno = 0; specno < MYJPWL_MAX_NO_TILESPECS; specno++) {
+ m_hprotChoice[specno]->Enable(false);
+ m_htileCtrl[specno]->Enable(false);
+ m_pprotChoice[specno]->Enable(false);
+ m_ptileCtrl[specno]->Enable(false);
+ m_ppackCtrl[specno]->Enable(false);
+ m_sensiChoice[specno]->Enable(false);
+ m_stileCtrl[specno]->Enable(false);
+ }
+ }
+
+}
+
+void OPJEncoderDialog::OnHprotSelect(wxCommandEvent& event)
+{
+ int specno;
+
+ // deactivate properly
+ for (specno = MYJPWL_MAX_NO_TILESPECS - 1; specno >= 0; specno--) {
+ if (!m_hprotChoice[specno]->GetSelection()) {
+ m_hprotChoice[specno]->Enable(false);
+ m_htileCtrl[specno]->Enable(false);
+ } else
+ break;
+ }
+ if (specno < (MYJPWL_MAX_NO_TILESPECS - 1)) {
+ m_hprotChoice[specno + 1]->Enable(true);
+ m_htileCtrl[specno + 1]->Enable(true);
+ }
+
+ //wxLogMessage(wxT("hprot changed: %d"), specno);
+}
+
+void OPJEncoderDialog::OnPprotSelect(wxCommandEvent& event)
+{
+ int specno;
+
+ // deactivate properly
+ for (specno = MYJPWL_MAX_NO_TILESPECS - 1; specno >= 0; specno--) {
+ if (!m_pprotChoice[specno]->GetSelection()) {
+ m_pprotChoice[specno]->Enable(false);
+ m_ptileCtrl[specno]->Enable(false);
+ m_ppackCtrl[specno]->Enable(false);
+ } else
+ break;
+ }
+ if (specno < (MYJPWL_MAX_NO_TILESPECS - 1)) {
+ m_pprotChoice[specno + 1]->Enable(true);
+ m_ptileCtrl[specno + 1]->Enable(true);
+ m_ppackCtrl[specno + 1]->Enable(true);
+ }
+
+ //wxLogMessage(wxT("pprot changed: %d"), specno);
+}
+
+void OPJEncoderDialog::OnSensiSelect(wxCommandEvent& event)
+{
+ int specno;
+
+ // deactivate properly
+ for (specno = MYJPWL_MAX_NO_TILESPECS - 1; specno >= 0; specno--) {
+ if (!m_sensiChoice[specno]->GetSelection()) {
+ m_sensiChoice[specno]->Enable(false);
+ m_stileCtrl[specno]->Enable(false);
+ } else
+ break;
+ }
+ if (specno < (MYJPWL_MAX_NO_TILESPECS - 1)) {
+ m_sensiChoice[specno + 1]->Enable(true);
+ m_stileCtrl[specno + 1]->Enable(true);
+ }
+
+ //wxLogMessage(wxT("sprot changed: %d"), specno);
+}
+
+
+#endif // USE_JPWL
+
diff --git a/src/bin/wx/OPJViewer/source/OPJThreads.cpp b/src/bin/wx/OPJViewer/source/OPJThreads.cpp
new file mode 100644
index 00000000..14159ac9
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJThreads.cpp
@@ -0,0 +1,1268 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita'  degli studi di Perugia (UPG), Italy
+ * 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 "OPJViewer.h"
+
+
+/////////////////////////////////////////////////////////////////////
+// Encoding thread class
+/////////////////////////////////////////////////////////////////////
+
+OPJEncoThread::OPJEncoThread(OPJCanvas *canvas)
+ : wxThread()
+{
+ m_count = 0;
+ m_canvas = canvas;
+}
+
+void OPJEncoThread::WriteText(const wxString& text)
+{
+ wxString msg;
+
+ // before doing any GUI calls we must ensure that this thread is the only
+ // one doing it!
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif // __WXGTK__
+
+ msg << text;
+ m_canvas->WriteText(msg);
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif // __WXGTK__
+}
+
+void OPJEncoThread::OnExit()
+{
+ wxCriticalSectionLocker locker(wxGetApp().m_enco_critsect);
+
+ wxArrayThread& ethreads = wxGetApp().m_enco_threads;
+ ethreads.Remove(this);
+
+ if (ethreads.IsEmpty() )
+ {
+ // signal the main thread that there are no more threads left if it is
+ // waiting for us
+ if (wxGetApp().m_enco_waitingUntilAllDone) {
+ wxGetApp().m_enco_waitingUntilAllDone = false;
+ wxGetApp().m_enco_semAllDone.Post();
+ }
+ }
+}
+
+void *OPJEncoThread::Entry()
+{
+ wxString text;
+
+ srand(GetId());
+ //int m_countnum = rand() % 9;
+ //text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."),
+ // GetId(), GetPriority(), m_countnum);
+ text.Printf(wxT("Enco thread %d started"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+
+ // set handler properties
+ wxJPEG2000Handler *jpeg2000handler = (wxJPEG2000Handler *) wxImage::FindHandler(wxBITMAP_TYPE_JPEG2000);
+ jpeg2000handler->m_subsampling = wxGetApp().m_subsampling;
+ jpeg2000handler->m_origin = wxGetApp().m_origin;
+ jpeg2000handler->m_rates = wxGetApp().m_rates;
+ jpeg2000handler->m_quality = wxGetApp().m_quality;
+ jpeg2000handler->m_enablequality = wxGetApp().m_enablequality;
+ jpeg2000handler->m_multicomp = wxGetApp().m_multicomp;
+ jpeg2000handler->m_irreversible = wxGetApp().m_irreversible;
+ jpeg2000handler->m_resolutions = wxGetApp().m_resolutions;
+ jpeg2000handler->m_progression = wxGetApp().m_progression;
+ jpeg2000handler->m_cbsize = wxGetApp().m_cbsize;
+ jpeg2000handler->m_prsize = wxGetApp().m_prsize;
+ jpeg2000handler->m_tsize = wxGetApp().m_tsize;
+ jpeg2000handler->m_torigin = wxGetApp().m_torigin;
+ jpeg2000handler->m_enablesop = wxGetApp().m_enablesop;
+ jpeg2000handler->m_enableeph = wxGetApp().m_enableeph;
+ jpeg2000handler->m_enablebypass = wxGetApp().m_enablebypass;
+ jpeg2000handler->m_enablerestart = wxGetApp().m_enablerestart;
+ jpeg2000handler->m_enablereset = wxGetApp().m_enablereset;
+ jpeg2000handler->m_enablesegmark = wxGetApp().m_enablesegmark;
+ jpeg2000handler->m_enableerterm = wxGetApp().m_enableerterm;
+ jpeg2000handler->m_enablevsc = wxGetApp().m_enablevsc;
+ jpeg2000handler->m_enableidx = wxGetApp().m_enableidx;
+ jpeg2000handler->m_index = m_canvas->m_savename.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxGetApp().m_index;
+ jpeg2000handler->m_enablecomm = wxGetApp().m_enablecomm;
+ jpeg2000handler->m_comment = wxGetApp().m_comment;
+ jpeg2000handler->m_enablepoc = wxGetApp().m_enablepoc;
+ jpeg2000handler->m_poc = wxGetApp().m_poc;
+
+ // save the file
+ if (!m_canvas->m_image100.SaveFile(m_canvas->m_savename.GetFullPath(), (wxBitmapType) wxBITMAP_TYPE_JPEG2000)) {
+ WriteText(wxT("Can't save image"));
+ return NULL;
+ }
+
+ text.Printf(wxT("Enco thread %d finished"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+ return NULL;
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Decoding thread class
+/////////////////////////////////////////////////////////////////////
+OPJDecoThread::OPJDecoThread(OPJCanvas *canvas)
+ : wxThread()
+{
+ m_count = 0;
+ m_canvas = canvas;
+}
+
+void OPJDecoThread::WriteText(const wxString& text)
+{
+ wxString msg;
+
+ // we use a fake event and post it for inter-thread gui communication
+ wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_THREADLOGMSG);
+ event.SetInt(-1);
+ msg << text;
+ event.SetString(msg);
+ wxPostEvent(this->m_canvas->m_childframe->m_frame, event);
+
+/*
+ // before doing any GUI calls we must ensure that this thread is the only
+ // one doing it!
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif // __WXGTK__
+
+ msg << text;
+ m_canvas->WriteText(msg);
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif // __WXGTK__
+*/
+}
+
+void OPJDecoThread::OnExit()
+{
+ wxCriticalSectionLocker locker(wxGetApp().m_deco_critsect);
+
+ wxArrayThread& dthreads = wxGetApp().m_deco_threads;
+ dthreads.Remove(this);
+
+ if (dthreads.IsEmpty() )
+ {
+ // signal the main thread that there are no more threads left if it is
+ // waiting for us
+ if (wxGetApp().m_deco_waitingUntilAllDone) {
+ wxGetApp().m_deco_waitingUntilAllDone = false;
+ wxGetApp().m_deco_semAllDone.Post();
+ }
+ }
+}
+
+void *OPJDecoThread::Entry()
+{
+
+ wxString text;
+
+ //srand(GetId());
+ //int m_countnum = rand() % 9;
+ //text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."),
+ // GetId(), GetPriority(), m_countnum);
+
+ // we have started
+ text.Printf(wxT("Deco thread %d started"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+
+ // prepare dummy wximage
+ wxBitmap bitmap(100, 100);
+ wxImage image(100, 100, true); //= bitmap.ConvertToImage();
+ image.Destroy();
+
+ // show image full name
+ WriteText(m_canvas->m_fname.GetFullPath());
+
+ // set handler properties
+ wxJPEG2000Handler *jpeg2000handler = (wxJPEG2000Handler *) wxImage::FindHandler(wxBITMAP_TYPE_JPEG2000);
+ jpeg2000handler->m_reducefactor = wxGetApp().m_reducefactor;
+ jpeg2000handler->m_qualitylayers = wxGetApp().m_qualitylayers;
+ jpeg2000handler->m_components = wxGetApp().m_components;
+ jpeg2000handler->m_framenum = wxGetApp().m_framenum;
+#ifdef USE_JPWL
+ jpeg2000handler->m_enablejpwl = wxGetApp().m_enablejpwl;
+ jpeg2000handler->m_expcomps = wxGetApp().m_expcomps;
+ jpeg2000handler->m_maxtiles = wxGetApp().m_maxtiles;
+#endif // USE_JPWL
+
+#ifdef USE_MXF
+ wxMXFHandler *mxfffhandler = (wxMXFHandler *) wxImage::FindHandler(wxBITMAP_TYPE_MXF);
+ mxfffhandler->m_reducefactor = wxGetApp().m_reducefactor;
+ mxfffhandler->m_qualitylayers = wxGetApp().m_qualitylayers;
+ mxfffhandler->m_components = wxGetApp().m_components;
+ mxfffhandler->m_framenum = wxGetApp().m_framenum;
+ mxfffhandler->m_filename = m_canvas->m_fname;
+#ifdef USE_JPWL
+ mxfffhandler->m_enablejpwl = wxGetApp().m_enablejpwl;
+ mxfffhandler->m_expcomps = wxGetApp().m_expcomps;
+ mxfffhandler->m_maxtiles = wxGetApp().m_maxtiles;
+#endif // USE_JPWL
+#endif // USE_MXF
+
+ // if decoding is enabled...
+ if (wxGetApp().m_enabledeco) {
+
+ // load the file
+ if (!image.LoadFile(m_canvas->m_fname.GetFullPath(), wxBITMAP_TYPE_ANY, 0)) {
+ WriteText(wxT("Can't load image!"));
+ return NULL;
+ }
+
+ } else {
+
+ // display a warning
+ if (!image.Create(300, 5, false)) {
+ WriteText(wxT("Can't create image!"));
+ return NULL;
+ }
+
+ }
+
+ // assign 100% image
+ m_canvas->m_image100 = wxBitmap(image);
+
+ // signal the frame to refresh the canvas
+ wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_VIEWFIT);
+ event.SetString(wxT("Fit me"));
+ event.SetInt(m_canvas->m_childframe->m_winnumber);
+ wxPostEvent(m_canvas->m_childframe->m_frame, event);
+
+ // find a fit-to-width zoom
+ /*int zooml, wzooml, hzooml;
+ wxSize clientsize = m_canvas->GetClientSize();
+ wzooml = (int) floor(100.0 * (double) clientsize.GetWidth() / (double) (2 * OPJ_CANVAS_BORDER + image.GetWidth()));
+ hzooml = (int) floor(100.0 * (double) clientsize.GetHeight() / (double) (2 * OPJ_CANVAS_BORDER + image.GetHeight()));
+ zooml = wxMin(100, wxMin(wzooml, hzooml));*/
+
+ // fit to width
+#ifndef __WXGTK__
+ //m_canvas->m_childframe->m_frame->Rescale(zooml, m_canvas->m_childframe);
+#endif // __WXGTK__
+
+ //m_canvas->m_image = m_canvas->m_image100;
+ //m_canvas->Refresh();
+ //m_canvas->SetScrollbars(20, 20, (int)(0.5 + (double) image.GetWidth() / 20.0), (int)(0.5 + (double) image.GetHeight() / 20.0));
+
+ //text.Printf(wxT("Deco thread 0x%lx finished."), GetId());
+ text.Printf(wxT("Deco thread %d finished"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+ return NULL;
+
+}
+
+/////////////////////////////////////////////////////////////////////
+// Parsing thread class
+/////////////////////////////////////////////////////////////////////
+
+OPJParseThread::OPJParseThread(OPJMarkerTree *tree, wxTreeItemId parentid)
+ : wxThread()
+{
+ m_count = 0;
+ m_tree = tree;
+ m_parentid = parentid;
+}
+
+void OPJParseThread::WriteText(const wxString& text)
+{
+ wxString msg;
+
+ // we use a fake event and post it for inter-thread gui communication
+ wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, OPJFRAME_THREADLOGMSG);
+ event.SetInt(-1);
+ msg << text;
+ event.SetString(msg);
+ wxPostEvent(this->m_tree->m_childframe->m_frame, event);
+
+/* // before doing any GUI calls we must ensure that this thread is the only
+ // one doing it!
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif // __WXGTK
+
+ msg << text;
+ m_tree->WriteText(msg);
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif // __WXGTK*/
+}
+
+void OPJParseThread::OnExit()
+{
+ wxCriticalSectionLocker locker(wxGetApp().m_parse_critsect);
+
+ wxArrayThread& threads = wxGetApp().m_parse_threads;
+ threads.Remove(this);
+
+ if (threads.IsEmpty()) {
+ // signal the main thread that there are no more threads left if it is
+ // waiting for us
+ if (wxGetApp().m_parse_waitingUntilAllDone) {
+ wxGetApp().m_parse_waitingUntilAllDone = false;
+ wxGetApp().m_parse_semAllDone.Post();
+ }
+ }
+}
+
+void *OPJParseThread::Entry()
+{
+
+ printf("Entering\n\n");
+
+ wxString text;
+
+ srand(GetId());
+ int m_countnum = rand() % 9;
+ text.Printf(wxT("Parse thread 0x%lx started (priority = %u, time = %d)."),
+ GetId(), GetPriority(), m_countnum);
+ WriteText(text);
+ LoadFile(m_tree->m_fname);
+ text.Printf(wxT("Parse thread 0x%lx finished."), GetId());
+ WriteText(text);
+
+
+ //wxLogMessage(wxT("Entering\n")); //test wxLog thread safeness
+
+ //wxBusyCursor wait;
+ //wxBusyInfo wait(wxT("Decoding image ..."));
+
+
+ /*for ( m_count = 0; m_count < m_countnum; m_count++ )
+ {
+ // check if we were asked to exit
+ if ( TestDestroy() )
+ break;
+
+ text.Printf(wxT("[%u] Parse thread 0x%lx here."), m_count, GetId());
+ WriteText(text);
+
+ // wxSleep() can't be called from non-GUI thread!
+ wxThread::Sleep(10);
+ }*/
+
+ // wxLogMessage(text); -- test wxLog thread safeness
+
+ printf("Exiting\n\n");
+
+ return NULL;
+}
+
+
+///////////////////////////////////////////
+// Parsing hread and related
+///////////////////////////////////////////
+
+#if USE_GENERIC_TREECTRL
+BEGIN_EVENT_TABLE(OPJMarkerTree, wxGenericTreeCtrl)
+#else
+BEGIN_EVENT_TABLE(OPJMarkerTree, wxTreeCtrl)
+#endif
+ /*EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginDrag)
+ EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginRDrag)
+ EVT_TREE_END_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnEndDrag)*/
+ /*EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnBeginLabelEdit)
+ EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnEndLabelEdit)*/
+ /*EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, OPJMarkerTree::OnDeleteItem)*/
+#if 0 // there are so many of those that logging them causes flicker
+ /*EVT_TREE_GET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnGetInfo)*/
+#endif
+ /*EVT_TREE_SET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnSetInfo)
+ EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanded)*/
+ EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanding)
+ /*EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsed)
+ EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsing)*/
+
+ EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, OPJMarkerTree::OnSelChanged)
+ /*EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, OPJMarkerTree::OnSelChanging)*/
+ /*EVT_TREE_KEY_DOWN(TreeTest_Ctrl, OPJMarkerTree::OnTreeKeyDown)*/
+ /*EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, OPJMarkerTree::OnItemActivated)*/
+
+ // so many differents ways to handle right mouse button clicks...
+ /*EVT_CONTEXT_MENU(OPJMarkerTree::OnContextMenu)*/
+ // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
+ // on a tree control, because it includes the point of the click or item,
+ // meaning that no additional placement calculations are required.
+ EVT_TREE_ITEM_MENU(TreeTest_Ctrl, OPJMarkerTree::OnItemMenu)
+ /*EVT_TREE_ITEM_RIGHT_CLICK(TreeTest_Ctrl, OPJMarkerTree::OnItemRClick)*/
+
+ /*EVT_RIGHT_DOWN(OPJMarkerTree::OnRMouseDown)
+ EVT_RIGHT_UP(OPJMarkerTree::OnRMouseUp)
+ EVT_RIGHT_DCLICK(OPJMarkerTree::OnRMouseDClick)*/
+END_EVENT_TABLE()
+
+// OPJMarkerTree implementation
+#if USE_GENERIC_TREECTRL
+IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxGenericTreeCtrl)
+#else
+IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxTreeCtrl)
+#endif
+
+OPJMarkerTree::OPJMarkerTree(wxWindow *parent, OPJChildFrame *subframe, wxFileName fname, wxString name, const wxWindowID id,
+ const wxPoint& pos, const wxSize& size, long style)
+ : wxTreeCtrl(parent, id, pos, size, style)
+{
+ m_reverseSort = false;
+ m_fname = fname;
+
+ m_peektextCtrl = ((OPJFrame *) (parent->GetParent()->GetParent()))->m_textCtrlbrowse;
+ CreateImageList();
+
+ // Add some items to the tree
+ //AddTestItemsToTree(5, 5);
+ int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1;
+ wxTreeItemId rootId = AddRoot(name,
+ image, image,
+ new OPJMarkerData(name));
+
+ OPJParseThread *pthread = CreateParseThread(0x00, subframe);
+ if (pthread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start parse thread!"));
+ else
+ wxLogMessage(wxT("New parse thread started."));
+
+ m_childframe = subframe;
+}
+
+void OPJMarkerTree::CreateImageList(int size)
+{
+ if (size == -1) {
+ SetImageList(NULL);
+ return;
+ }
+ if (size == 0)
+ size = m_imageSize;
+ else
+ m_imageSize = size;
+
+ // Make an image list containing small icons
+ wxImageList *images = new wxImageList(size, size, true);
+
+ // should correspond to TreeCtrlIcon_xxx enum
+ wxBusyCursor wait;
+ wxIcon icons[5];
+ icons[0] = wxIcon(icon1_xpm);
+ icons[1] = wxIcon(icon2_xpm);
+ icons[2] = wxIcon(icon3_xpm);
+ icons[3] = wxIcon(icon4_xpm);
+ icons[4] = wxIcon(icon5_xpm);
+
+ int sizeOrig = icons[0].GetWidth();
+ for (size_t i = 0; i < WXSIZEOF(icons); i++) {
+ if (size == sizeOrig) {
+ images->Add(icons[i]);
+ } else {
+ images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
+ }
+ }
+
+ AssignImageList(images);
+}
+
+#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
+void OPJMarkerTree::CreateButtonsImageList(int size)
+{
+ if ( size == -1 ) {
+ SetButtonsImageList(NULL);
+ return;
+ }
+
+ // Make an image list containing small icons
+ wxImageList *images = new wxImageList(size, size, true);
+
+ // should correspond to TreeCtrlIcon_xxx enum
+ wxBusyCursor wait;
+ wxIcon icons[4];
+ icons[0] = wxIcon(icon3_xpm); // closed
+ icons[1] = wxIcon(icon3_xpm); // closed, selected
+ icons[2] = wxIcon(icon5_xpm); // open
+ icons[3] = wxIcon(icon5_xpm); // open, selected
+
+ for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) {
+ int sizeOrig = icons[i].GetWidth();
+ if ( size == sizeOrig ) {
+ images->Add(icons[i]);
+ } else {
+ images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
+ }
+ }
+
+ AssignButtonsImageList(images);
+#else
+void OPJMarkerTree::CreateButtonsImageList(int WXUNUSED(size))
+{
+#endif
+}
+
+void OPJParseThread::LoadFile(wxFileName fname)
+{
+ wxTreeItemId rootid;
+
+ // this is the root node
+ int image = wxGetApp().ShowImages() ? m_tree->TreeCtrlIcon_Folder : -1;
+
+ if (this->m_parentid) {
+ // leaf of a tree
+ rootid = m_parentid;
+ m_tree->SetItemText(rootid, wxT("Parsing..."));
+
+ } else {
+
+ // delete the existing tree hierarchy
+ m_tree->DeleteAllItems();
+
+ // new tree
+ rootid = m_tree->AddRoot(wxT("Parsing..."),
+ image,
+ image,
+ new OPJMarkerData(fname.GetFullPath())
+ );
+ //m_tree->SetItemFont(rootid, *wxITALIC_FONT);
+ m_tree->SetItemBold(rootid);
+ }
+
+ // open the file
+ wxFile m_file(fname.GetFullPath().c_str(), wxFile::read);
+
+ // parsing enabled?
+ if (wxGetApp().m_enableparse) {
+
+ // what is the extension?
+ if ((fname.GetExt() == wxT("j2k")) || (fname.GetExt() == wxT("j2c"))) {
+
+ // parse the file
+ ParseJ2KFile(&m_file, 0, m_file.Length(), rootid);
+
+ } else if ((fname.GetExt() == wxT("jp2")) || (fname.GetExt() == wxT("mj2"))) {
+
+ // parse the file
+ if (this->m_parentid) {
+ //WriteText(wxT("Only a subsection of jp2"));
+ OPJMarkerData *data = (OPJMarkerData *) m_tree->GetItemData(rootid);
+ ParseJ2KFile(&m_file, data->m_start, data->m_length, rootid);
+ m_tree->Expand(rootid);
+
+ } else {
+ // as usual
+ ParseJP2File(&m_file, 0, m_file.Length(), rootid);
+ }
+
+ } else {
+
+ // unknown extension
+ WriteText(wxT("Unknown file format!"));
+
+ }
+
+ }
+
+ // this is the root node
+ if (this->m_parentid)
+ m_tree->SetItemText(rootid, wxT("Codestream"));
+ else
+ //m_tree->SetItemText(rootid, wxString::Format(wxT("%s (%d B)"), fname.GetFullName(), m_file.Length()));
+ m_tree->SetItemText(rootid, fname.GetFullName());
+
+ // close the file
+ m_file.Close();
+
+ WriteText(wxT("Parsing finished!"));
+}
+
+/*int OPJMarkerTree::OnCompareItems(const wxTreeItemId& item1,
+ const wxTreeItemId& item2)
+{
+ if ( m_reverseSort )
+ {
+ // just exchange 1st and 2nd items
+ return wxTreeCtrl::OnCompareItems(item2, item1);
+ }
+ else
+ {
+ return wxTreeCtrl::OnCompareItems(item1, item2);
+ }
+}*/
+
+/*void OPJMarkerTree::AddItemsRecursively(const wxTreeItemId& idParent,
+ size_t numChildren,
+ size_t depth,
+ size_t folder)
+{
+ if ( depth > 0 )
+ {
+ bool hasChildren = depth > 1;
+
+ wxString str;
+ for ( size_t n = 0; n < numChildren; n++ )
+ {
+ // at depth 1 elements won't have any more children
+ if ( hasChildren )
+ str.Printf(wxT("%s child %u"), wxT("Folder"), unsigned(n + 1));
+ else
+ str.Printf(wxT("%s child %u.%u"), wxT("File"), unsigned(folder), unsigned(n + 1));
+
+ // here we pass to AppendItem() normal and selected item images (we
+ // suppose that selected image follows the normal one in the enum)
+ int image, imageSel;
+ if ( wxGetApp().ShowImages() )
+ {
+ image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+ }
+ else
+ {
+ image = imageSel = -1;
+ }
+ wxTreeItemId id = AppendItem(idParent, str, image, imageSel,
+ new OPJMarkerData(str));
+
+ // and now we also set the expanded one (only for the folders)
+ if ( hasChildren && wxGetApp().ShowImages() )
+ {
+ SetItemImage(id, TreeCtrlIcon_FolderOpened,
+ wxTreeItemIcon_Expanded);
+ }
+
+ // remember the last child for OnEnsureVisible()
+ if ( !hasChildren && n == numChildren - 1 )
+ {
+ m_lastItem = id;
+ }
+
+ AddItemsRecursively(id, numChildren, depth - 1, n + 1);
+ }
+ }
+ //else: done!
+}*/
+
+/*void OPJMarkerTree::AddTestItemsToTree(size_t numChildren,
+ size_t depth)
+{
+ int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1;
+ wxTreeItemId rootId = AddRoot(wxT("Root"),
+ image, image,
+ new OPJMarkerData(wxT("Root item")));
+ if ( image != -1 )
+ {
+ SetItemImage(rootId, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded);
+ }
+
+ AddItemsRecursively(rootId, numChildren, depth, 0);
+
+ // set some colours/fonts for testing
+ SetItemFont(rootId, *wxITALIC_FONT);
+
+ wxTreeItemIdValue cookie;
+ wxTreeItemId id = GetFirstChild(rootId, cookie);
+ SetItemTextColour(id, *wxBLUE);
+
+ id = GetNextChild(rootId, cookie);
+ id = GetNextChild(rootId, cookie);
+ SetItemTextColour(id, *wxRED);
+ SetItemBackgroundColour(id, *wxLIGHT_GREY);
+}*/
+
+/*void OPJMarkerTree::GetItemsRecursively(const wxTreeItemId& idParent,
+ wxTreeItemIdValue cookie)
+{
+ wxTreeItemId id;
+
+ if ( !cookie )
+ id = GetFirstChild(idParent, cookie);
+ else
+ id = GetNextChild(idParent, cookie);
+
+ if ( !id.IsOk() )
+ return;
+
+ wxString text = GetItemText(id);
+ wxLogMessage(text);
+
+ if (ItemHasChildren(id))
+ GetItemsRecursively(id);
+
+ GetItemsRecursively(idParent, cookie);
+}*/
+
+/*void OPJMarkerTree::DoToggleIcon(const wxTreeItemId& item)
+{
+ int image = (GetItemImage(item) == TreeCtrlIcon_Folder)
+ ? TreeCtrlIcon_File
+ : TreeCtrlIcon_Folder;
+ SetItemImage(item, image, wxTreeItemIcon_Normal);
+
+ image = (GetItemImage(item) == TreeCtrlIcon_FolderSelected)
+ ? TreeCtrlIcon_FileSelected
+ : TreeCtrlIcon_FolderSelected;
+ SetItemImage(item, image, wxTreeItemIcon_Selected);
+}*/
+
+void OPJMarkerTree::LogEvent(const wxChar *name, const wxTreeEvent& event)
+{
+ wxTreeItemId item = event.GetItem();
+ wxString text;
+ if ( item.IsOk() )
+ text << wxT('"') << GetItemText(item).c_str() << wxT('"');
+ else
+ text = wxT("invalid item");
+ wxLogMessage(wxT("%s(%s)"), name, text.c_str());
+}
+
+OPJParseThread *OPJMarkerTree::CreateParseThread(wxTreeItemId parentid, OPJChildFrame *subframe)
+{
+ OPJParseThread *pthread = new OPJParseThread(this, parentid);
+
+ if (pthread->Create() != wxTHREAD_NO_ERROR)
+ wxLogError(wxT("Can't create parse thread!"));
+
+ wxCriticalSectionLocker enter(wxGetApp().m_parse_critsect);
+ wxGetApp().m_parse_threads.Add(pthread);
+
+ return pthread;
+}
+
+
+/*// avoid repetition
+#define TREE_EVENT_HANDLER(name) \
+void OPJMarkerTree::name(wxTreeEvent& event) \
+{ \
+ LogEvent(_T(#name), event); \
+ SetLastItem(wxTreeItemId()); \
+ event.Skip(); \
+}*/
+
+/*TREE_EVENT_HANDLER(OnBeginRDrag)*/
+/*TREE_EVENT_HANDLER(OnDeleteItem)*/
+/*TREE_EVENT_HANDLER(OnGetInfo)
+TREE_EVENT_HANDLER(OnSetInfo)*/
+/*TREE_EVENT_HANDLER(OnItemExpanded)
+TREE_EVENT_HANDLER(OnItemExpanding)*/
+/*TREE_EVENT_HANDLER(OnItemCollapsed)*/
+/*TREE_EVENT_HANDLER(OnSelChanged)
+TREE_EVENT_HANDLER(OnSelChanging)*/
+
+/*#undef TREE_EVENT_HANDLER*/
+
+void OPJMarkerTree::OnItemExpanding(wxTreeEvent& event)
+{
+ wxTreeItemId item = event.GetItem();
+ OPJMarkerData* data = (OPJMarkerData *) GetItemData(item);
+ wxString text;
+
+ if (item.IsOk())
+ text << wxT('"') << GetItemText(item).c_str() << wxT('"');
+ else
+ text = wxT("invalid item");
+
+ if (wxStrcmp(data->GetDesc1(), wxT("INFO-CSTREAM")))
+ return;
+
+ wxLogMessage(wxT("Expanding... (%s -> %s, %s, %d, %d)"),
+ text.c_str(), data->GetDesc1(), data->GetDesc2(),
+ data->m_start, data->m_length);
+
+ // the codestream box is being asked for expansion
+ wxTreeItemIdValue cookie;
+ if (!GetFirstChild(item, cookie).IsOk()) {
+ OPJParseThread *pthread = CreateParseThread(item);
+ if (pthread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start parse thread!"));
+ else
+ wxLogMessage(wxT("New parse thread started."));
+ }
+}
+
+void OPJMarkerTree::OnSelChanged(wxTreeEvent& event)
+{
+ int bunch_linesize = 16;
+ int bunch_numlines = 7;
+
+ wxTreeItemId item = event.GetItem();
+ OPJMarkerData* data = (OPJMarkerData *) GetItemData(item);
+ wxString text;
+ int l, c, pos = 0, pre_pos;
+
+ m_peektextCtrl->Clear();
+
+ /*text << wxString::Format(wxT("Selected... (%s -> %s, %s, %d, %d)"),
+ text.c_str(), data->GetDesc1(), data->GetDesc2(),
+ data->m_start, data->m_length) << wxT("\n");*/
+
+ // open the file and browse a little
+ wxFile *fp = new wxFile(m_fname.GetFullPath().c_str(), wxFile::read);
+
+ // go to position claimed
+ fp->Seek(data->m_start, wxFromStart);
+
+ // read a bunch
+ int max_read = wxMin(wxFileOffset(bunch_linesize * bunch_numlines), data->m_length - data->m_start + 1);
+ if (data->m_desc == wxT("MARK (65380)")) {
+ /*wxLogMessage(data->m_desc);*/
+ max_read = data->m_length - data->m_start + 1;
+ bunch_numlines = (int) ceil((float) max_read / (float) bunch_linesize);
+ }
+ unsigned char *buffer = new unsigned char[bunch_linesize * bunch_numlines];
+ fp->Read(buffer, max_read);
+
+ // write the file data between start and stop
+ pos = 0;
+ for (l = 0; l < bunch_numlines; l++) {
+
+ text << wxString::Format(wxT("%010d:"), data->m_start + pos);
+
+ pre_pos = pos;
+
+ // add hex browsing text
+ for (c = 0; c < bunch_linesize; c++) {
+
+ if (!(c % 8))
+ text << wxT(" ");
+
+ if (pos < max_read) {
+ text << wxString::Format(wxT("%02X "), buffer[pos]);
+ } else
+ text << wxT(" ");
+ pos++;
+ }
+
+ text << wxT(" ");
+
+ // add char browsing text
+ for (c = 0; c < bunch_linesize; c++) {
+
+ if (pre_pos < max_read) {
+ if ((buffer[pre_pos] == '\n') ||
+ (buffer[pre_pos] == '\t') ||
+ (buffer[pre_pos] == '\0') ||
+ (buffer[pre_pos] == 0x0D) ||
+ (buffer[pre_pos] == 0x0B))
+ buffer[pre_pos] = ' ';
+ text << wxString::FromAscii((char) buffer[pre_pos]) << wxT(".");
+ } else
+ text << wxT(" ");
+ pre_pos++;
+ }
+
+ text << wxT("\n");
+
+ }
+
+ // close the file
+ fp->Close();
+
+ m_peektextCtrl->WriteText(text);
+
+ delete buffer;
+}
+
+/*void LogKeyEvent(const wxChar *name, const wxKeyEvent& event)
+{
+ wxString key;
+ long keycode = event.GetKeyCode();
+ {
+ switch ( keycode )
+ {
+ case WXK_BACK: key = wxT("BACK"); break;
+ case WXK_TAB: key = wxT("TAB"); break;
+ case WXK_RETURN: key = wxT("RETURN"); break;
+ case WXK_ESCAPE: key = wxT("ESCAPE"); break;
+ case WXK_SPACE: key = wxT("SPACE"); break;
+ case WXK_DELETE: key = wxT("DELETE"); break;
+ case WXK_START: key = wxT("START"); break;
+ case WXK_LBUTTON: key = wxT("LBUTTON"); break;
+ case WXK_RBUTTON: key = wxT("RBUTTON"); break;
+ case WXK_CANCEL: key = wxT("CANCEL"); break;
+ case WXK_MBUTTON: key = wxT("MBUTTON"); break;
+ case WXK_CLEAR: key = wxT("CLEAR"); break;
+ case WXK_SHIFT: key = wxT("SHIFT"); break;
+ case WXK_ALT: key = wxT("ALT"); break;
+ case WXK_CONTROL: key = wxT("CONTROL"); break;
+ case WXK_MENU: key = wxT("MENU"); break;
+ case WXK_PAUSE: key = wxT("PAUSE"); break;
+ case WXK_CAPITAL: key = wxT("CAPITAL"); break;
+ case WXK_END: key = wxT("END"); break;
+ case WXK_HOME: key = wxT("HOME"); break;
+ case WXK_LEFT: key = wxT("LEFT"); break;
+ case WXK_UP: key = wxT("UP"); break;
+ case WXK_RIGHT: key = wxT("RIGHT"); break;
+ case WXK_DOWN: key = wxT("DOWN"); break;
+ case WXK_SELECT: key = wxT("SELECT"); break;
+ case WXK_PRINT: key = wxT("PRINT"); break;
+ case WXK_EXECUTE: key = wxT("EXECUTE"); break;
+ case WXK_SNAPSHOT: key = wxT("SNAPSHOT"); break;
+ case WXK_INSERT: key = wxT("INSERT"); break;
+ case WXK_HELP: key = wxT("HELP"); break;
+ case WXK_NUMPAD0: key = wxT("NUMPAD0"); break;
+ case WXK_NUMPAD1: key = wxT("NUMPAD1"); break;
+ case WXK_NUMPAD2: key = wxT("NUMPAD2"); break;
+ case WXK_NUMPAD3: key = wxT("NUMPAD3"); break;
+ case WXK_NUMPAD4: key = wxT("NUMPAD4"); break;
+ case WXK_NUMPAD5: key = wxT("NUMPAD5"); break;
+ case WXK_NUMPAD6: key = wxT("NUMPAD6"); break;
+ case WXK_NUMPAD7: key = wxT("NUMPAD7"); break;
+ case WXK_NUMPAD8: key = wxT("NUMPAD8"); break;
+ case WXK_NUMPAD9: key = wxT("NUMPAD9"); break;
+ case WXK_MULTIPLY: key = wxT("MULTIPLY"); break;
+ case WXK_ADD: key = wxT("ADD"); break;
+ case WXK_SEPARATOR: key = wxT("SEPARATOR"); break;
+ case WXK_SUBTRACT: key = wxT("SUBTRACT"); break;
+ case WXK_DECIMAL: key = wxT("DECIMAL"); break;
+ case WXK_DIVIDE: key = wxT("DIVIDE"); break;
+ case WXK_F1: key = wxT("F1"); break;
+ case WXK_F2: key = wxT("F2"); break;
+ case WXK_F3: key = wxT("F3"); break;
+ case WXK_F4: key = wxT("F4"); break;
+ case WXK_F5: key = wxT("F5"); break;
+ case WXK_F6: key = wxT("F6"); break;
+ case WXK_F7: key = wxT("F7"); break;
+ case WXK_F8: key = wxT("F8"); break;
+ case WXK_F9: key = wxT("F9"); break;
+ case WXK_F10: key = wxT("F10"); break;
+ case WXK_F11: key = wxT("F11"); break;
+ case WXK_F12: key = wxT("F12"); break;
+ case WXK_F13: key = wxT("F13"); break;
+ case WXK_F14: key = wxT("F14"); break;
+ case WXK_F15: key = wxT("F15"); break;
+ case WXK_F16: key = wxT("F16"); break;
+ case WXK_F17: key = wxT("F17"); break;
+ case WXK_F18: key = wxT("F18"); break;
+ case WXK_F19: key = wxT("F19"); break;
+ case WXK_F20: key = wxT("F20"); break;
+ case WXK_F21: key = wxT("F21"); break;
+ case WXK_F22: key = wxT("F22"); break;
+ case WXK_F23: key = wxT("F23"); break;
+ case WXK_F24: key = wxT("F24"); break;
+ case WXK_NUMLOCK: key = wxT("NUMLOCK"); break;
+ case WXK_SCROLL: key = wxT("SCROLL"); break;
+ case WXK_PAGEUP: key = wxT("PAGEUP"); break;
+ case WXK_PAGEDOWN: key = wxT("PAGEDOWN"); break;
+ case WXK_NUMPAD_SPACE: key = wxT("NUMPAD_SPACE"); break;
+ case WXK_NUMPAD_TAB: key = wxT("NUMPAD_TAB"); break;
+ case WXK_NUMPAD_ENTER: key = wxT("NUMPAD_ENTER"); break;
+ case WXK_NUMPAD_F1: key = wxT("NUMPAD_F1"); break;
+ case WXK_NUMPAD_F2: key = wxT("NUMPAD_F2"); break;
+ case WXK_NUMPAD_F3: key = wxT("NUMPAD_F3"); break;
+ case WXK_NUMPAD_F4: key = wxT("NUMPAD_F4"); break;
+ case WXK_NUMPAD_HOME: key = wxT("NUMPAD_HOME"); break;
+ case WXK_NUMPAD_LEFT: key = wxT("NUMPAD_LEFT"); break;
+ case WXK_NUMPAD_UP: key = wxT("NUMPAD_UP"); break;
+ case WXK_NUMPAD_RIGHT: key = wxT("NUMPAD_RIGHT"); break;
+ case WXK_NUMPAD_DOWN: key = wxT("NUMPAD_DOWN"); break;
+ case WXK_NUMPAD_PAGEUP: key = wxT("NUMPAD_PAGEUP"); break;
+ case WXK_NUMPAD_PAGEDOWN: key = wxT("NUMPAD_PAGEDOWN"); break;
+ case WXK_NUMPAD_END: key = wxT("NUMPAD_END"); break;
+ case WXK_NUMPAD_BEGIN: key = wxT("NUMPAD_BEGIN"); break;
+ case WXK_NUMPAD_INSERT: key = wxT("NUMPAD_INSERT"); break;
+ case WXK_NUMPAD_DELETE: key = wxT("NUMPAD_DELETE"); break;
+ case WXK_NUMPAD_EQUAL: key = wxT("NUMPAD_EQUAL"); break;
+ case WXK_NUMPAD_MULTIPLY: key = wxT("NUMPAD_MULTIPLY"); break;
+ case WXK_NUMPAD_ADD: key = wxT("NUMPAD_ADD"); break;
+ case WXK_NUMPAD_SEPARATOR: key = wxT("NUMPAD_SEPARATOR"); break;
+ case WXK_NUMPAD_SUBTRACT: key = wxT("NUMPAD_SUBTRACT"); break;
+ case WXK_NUMPAD_DECIMAL: key = wxT("NUMPAD_DECIMAL"); break;
+
+ default:
+ {
+ if ( keycode < 128 && wxIsprint((int)keycode) )
+ key.Printf(wxT("'%c'"), (char)keycode);
+ else if ( keycode > 0 && keycode < 27 )
+ key.Printf(_("Ctrl-%c"), wxT('A') + keycode - 1);
+ else
+ key.Printf(wxT("unknown (%ld)"), keycode);
+ }
+ }
+ }
+
+ wxLogMessage(wxT("%s event: %s (flags = %c%c%c%c)"),
+ name,
+ key.c_str(),
+ event.ControlDown() ? wxT('C') : wxT('-'),
+ event.AltDown() ? wxT('A') : wxT('-'),
+ event.ShiftDown() ? wxT('S') : wxT('-'),
+ event.MetaDown() ? wxT('M') : wxT('-'));
+}
+
+void OPJMarkerTree::OnTreeKeyDown(wxTreeEvent& event)
+{
+ LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
+
+ event.Skip();
+}*/
+
+/*void OPJMarkerTree::OnBeginDrag(wxTreeEvent& event)
+{
+ // need to explicitly allow drag
+ if ( event.GetItem() != GetRootItem() )
+ {
+ m_draggedItem = event.GetItem();
+
+ wxLogMessage(wxT("OnBeginDrag: started dragging %s"),
+ GetItemText(m_draggedItem).c_str());
+
+ event.Allow();
+ }
+ else
+ {
+ wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
+ }
+}
+
+void OPJMarkerTree::OnEndDrag(wxTreeEvent& event)
+{
+ wxTreeItemId itemSrc = m_draggedItem,
+ itemDst = event.GetItem();
+ m_draggedItem = (wxTreeItemId)0l;
+
+ // where to copy the item?
+ if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
+ {
+ // copy to the parent then
+ itemDst = GetItemParent(itemDst);
+ }
+
+ if ( !itemDst.IsOk() )
+ {
+ wxLogMessage(wxT("OnEndDrag: can't drop here."));
+
+ return;
+ }
+
+ wxString text = GetItemText(itemSrc);
+ wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
+ text.c_str(), GetItemText(itemDst).c_str());
+
+ // just do append here - we could also insert it just before/after the item
+ // on which it was dropped, but this requires slightly more work... we also
+ // completely ignore the client data and icon of the old item but could
+ // copy them as well.
+ //
+ // Finally, we only copy one item here but we might copy the entire tree if
+ // we were dragging a folder.
+ int image = wxGetApp().ShowImages() ? TreeCtrlIcon_File : -1;
+ AppendItem(itemDst, text, image);
+}*/
+
+/*void OPJMarkerTree::OnBeginLabelEdit(wxTreeEvent& event)
+{
+ wxLogMessage(wxT("OnBeginLabelEdit"));
+
+ // for testing, prevent this item's label editing
+ wxTreeItemId itemId = event.GetItem();
+ if ( IsTestItem(itemId) )
+ {
+ wxMessageBox(wxT("You can't edit this item."));
+
+ event.Veto();
+ }
+ else if ( itemId == GetRootItem() )
+ {
+ // test that it is possible to change the text of the item being edited
+ SetItemText(itemId, _T("Editing root item"));
+ }
+}
+
+void OPJMarkerTree::OnEndLabelEdit(wxTreeEvent& event)
+{
+ wxLogMessage(wxT("OnEndLabelEdit"));
+
+ // don't allow anything except letters in the labels
+ if ( !event.GetLabel().IsWord() )
+ {
+ wxMessageBox(wxT("The new label should be a single word."));
+
+ event.Veto();
+ }
+}*/
+
+/*void OPJMarkerTree::OnItemCollapsing(wxTreeEvent& event)
+{
+ wxLogMessage(wxT("OnItemCollapsing"));
+
+ // for testing, prevent the user from collapsing the first child folder
+ wxTreeItemId itemId = event.GetItem();
+ if ( IsTestItem(itemId) )
+ {
+ wxMessageBox(wxT("You can't collapse this item."));
+
+ event.Veto();
+ }
+}*/
+
+/*void OPJMarkerTree::OnItemActivated(wxTreeEvent& event)
+{
+ // show some info about this item
+ wxTreeItemId itemId = event.GetItem();
+ OPJMarkerData *item = (OPJMarkerData *)GetItemData(itemId);
+
+ if ( item != NULL )
+ {
+ item->ShowInfo(this);
+ }
+
+ wxLogMessage(wxT("OnItemActivated"));
+}*/
+
+void OPJMarkerTree::OnItemMenu(wxTreeEvent& event)
+{
+ /*wxTreeItemId itemId = event.GetItem();
+ OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId)
+ : NULL;
+
+ wxLogMessage(wxT("OnItemMenu for item \"%s\""), item ? item->GetDesc()
+ : _T(""));*/
+
+ //wxLogMessage(wxT("EEEEEEEEEE"));
+
+ //event.Skip();
+}
+
+/*void OPJMarkerTree::OnContextMenu(wxContextMenuEvent& event)
+{
+ wxPoint pt = event.GetPosition();
+ wxTreeItemId item;
+ wxLogMessage(wxT("OnContextMenu at screen coords (%i, %i)"), pt.x, pt.y);
+
+ // check if event was generated by keyboard (MSW-specific?)
+ if ( pt.x == -1 && pt.y == -1 ) //(this is how MSW indicates it)
+ {
+ if ( !HasFlag(wxTR_MULTIPLE) )
+ item = GetSelection();
+
+ // attempt to guess where to show the menu
+ if ( item.IsOk() )
+ {
+ // if an item was clicked, show menu to the right of it
+ wxRect rect;
+ GetBoundingRect(item, rect, true );// only the label
+ pt = wxPoint(rect.GetRight(), rect.GetTop());
+ }
+ else
+ {
+ pt = wxPoint(0, 0);
+ }
+ }
+ else // event was generated by mouse, use supplied coords
+ {
+ pt = ScreenToClient(pt);
+ item = HitTest(pt);
+ }
+
+ ShowMenu(item, pt);
+}*/
+
+/*void OPJMarkerTree::ShowMenu(wxTreeItemId id, const wxPoint& pt)
+{
+ wxString title;
+ if ( id.IsOk() )
+ {
+ title << wxT("Menu for ") << GetItemText(id);
+ }
+ else
+ {
+ title = wxT("Menu for no particular item");
+ }
+
+#if wxUSE_MENUS
+ wxMenu menu(title);
+ menu.Append(TreeTest_About, wxT("&About..."));
+ menu.AppendSeparator();
+ menu.Append(TreeTest_Highlight, wxT("&Highlight item"));
+ menu.Append(TreeTest_Dump, wxT("&Dump"));
+
+ PopupMenu(&menu, pt);
+#endif // wxUSE_MENUS
+}*/
+
+/*void OPJMarkerTree::OnItemRClick(wxTreeEvent& event)
+{
+ wxTreeItemId itemId = event.GetItem();
+ OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId)
+ : NULL;
+
+ wxLogMessage(wxT("Item \"%s\" right clicked"), item ? item->GetDesc()
+ : _T(""));
+
+ event.Skip();
+}*/
+
+/*
+void OPJMarkerTree::OnRMouseDown(wxMouseEvent& event)
+{
+ wxLogMessage(wxT("Right mouse button down"));
+
+ event.Skip();
+}
+
+void OPJMarkerTree::OnRMouseUp(wxMouseEvent& event)
+{
+ wxLogMessage(wxT("Right mouse button up"));
+
+ event.Skip();
+}
+
+void OPJMarkerTree::OnRMouseDClick(wxMouseEvent& event)
+{
+ wxTreeItemId id = HitTest(event.GetPosition());
+ if ( !id )
+ wxLogMessage(wxT("No item under mouse"));
+ else
+ {
+ OPJMarkerData *item = (OPJMarkerData *)GetItemData(id);
+ if ( item )
+ wxLogMessage(wxT("Item '%s' under mouse"), item->GetDesc());
+ }
+
+ event.Skip();
+}
+*/
+
+static inline const wxChar *Bool2String(bool b)
+{
+ return b ? wxT("") : wxT("not ");
+}
+
+void OPJMarkerData::ShowInfo(wxTreeCtrl *tree)
+{
+ wxLogMessage(wxT("Item '%s': %sselected, %sexpanded, %sbold,\n")
+ wxT("%u children (%u immediately under this item)."),
+ m_desc.c_str(),
+ Bool2String(tree->IsSelected(GetId())),
+ Bool2String(tree->IsExpanded(GetId())),
+ Bool2String(tree->IsBold(GetId())),
+ unsigned(tree->GetChildrenCount(GetId())),
+ unsigned(tree->GetChildrenCount(GetId(), false)));
+}
+
+
diff --git a/src/bin/wx/OPJViewer/source/OPJViewer.cpp b/src/bin/wx/OPJViewer/source/OPJViewer.cpp
new file mode 100644
index 00000000..8476d919
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJViewer.cpp
@@ -0,0 +1,1666 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita' degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashtest.cpp
+// Purpose: Layout/sash sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id: sashtest.cpp,v 1.18 2005/08/23 15:54:35 ABX Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: treetest.cpp
+// Purpose: wxTreeCtrl sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id: treetest.cpp,v 1.110 2006/11/04 11:26:51 VZ Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: dialogs.cpp
+// Purpose: Common dialogs demo
+// Author: Julian Smart
+// Modified by: ABX (2004) - adjustements for conditional building + new menu
+// Created: 04/01/98
+// RCS-ID: $Id: dialogs.cpp,v 1.163 2006/11/04 10:57:24 VZ Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: thread.cpp
+// Purpose: wxWidgets thread sample
+// Author: Guilhem Lavaux, Vadim Zeitlin
+// Modified by:
+// Created: 06/16/98
+// RCS-ID: $Id: thread.cpp,v 1.26 2006/10/02 05:36:28 PC Exp $
+// Copyright: (c) 1998-2002 wxWidgets team
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// Name: samples/image/image.cpp
+// Purpose: sample showing operations with wxImage
+// Author: Robert Roebling
+// Modified by:
+// Created: 1998
+// RCS-ID: $Id: image.cpp,v 1.120 2006/12/06 17:13:11 VZ Exp $
+// Copyright: (c) 1998-2005 Robert Roebling
+// License: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: samples/console/console.cpp
+// Purpose: A sample console (as opposed to GUI) program using wxWidgets
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 04.10.99
+// RCS-ID: $Id: console.cpp,v 1.206 2006/11/12 19:55:19 VZ Exp $
+// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: samples/notebook/notebook.cpp
+// Purpose: a sample demonstrating notebook usage
+// Author: Julian Smart
+// Modified by: Dimitri Schoolwerth
+// Created: 26/10/98
+// RCS-ID: $Id: notebook.cpp,v 1.49 2006/11/04 18:24:07 RR Exp $
+// Copyright: (c) 1998-2002 wxWidgets team
+// License: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: dialogs.cpp
+// Purpose: Common dialogs demo
+// Author: Julian Smart
+// Modified by: ABX (2004) - adjustements for conditional building + new menu
+// Created: 04/01/98
+// RCS-ID: $Id: dialogs.cpp,v 1.163 2006/11/04 10:57:24 VZ Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: dnd.cpp
+// Purpose: Drag and drop sample
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id: dnd.cpp,v 1.107 2006/10/30 20:23:41 VZ Exp $
+// Copyright:
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: test.cpp
+// Purpose: wxHtml testing example
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "OPJViewer.h"
+
+IMPLEMENT_APP(OPJViewerApp)
+
+// For drawing lines in a canvas
+long xpos = -1;
+long ypos = -1;
+
+int winNumber = 1;
+
+// Initialise this in OnInit, not statically
+bool OPJViewerApp::OnInit(void)
+{
+ int n;
+#if wxUSE_UNICODE
+
+ wxChar **wxArgv = new wxChar *[argc + 1];
+
+ for (n = 0; n < argc; n++ ) {
+ wxMB2WXbuf warg = wxConvertMB2WX((char *) argv[n]);
+ wxArgv[n] = wxStrdup(warg);
+ }
+
+ wxArgv[n] = NULL;
+
+#else // !wxUSE_UNICODE
+
+ #define wxArgv argv
+
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+#if wxUSE_CMDLINE_PARSER
+
+ static const wxCmdLineEntryDesc cmdLineDesc[] =
+ {
+ { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show this help message"),
+ wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
+
+ { wxCMD_LINE_PARAM, NULL, NULL, _T("input file"),
+ wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE },
+
+ { wxCMD_LINE_NONE }
+ };
+
+ wxCmdLineParser parser(cmdLineDesc, argc, wxArgv);
+
+ switch (parser.Parse()) {
+ case -1:
+ wxLogMessage(wxT("Help was given, terminating."));
+ break;
+
+ case 0:
+ ShowCmdLine(parser);
+ break;
+
+ default:
+ wxLogMessage(wxT("Syntax error detected."));
+ break;
+ }
+
+#endif // wxUSE_CMDLINE_PARSER
+
+ //wxInitAllImageHandlers();
+#if wxUSE_LIBJPEG
+ wxImage::AddHandler( new wxJPEGHandler );
+#endif
+#if wxUSE_LIBOPENJPEG
+ wxImage::AddHandler( new wxJPEG2000Handler );
+#endif
+#if USE_MXF
+ wxImage::AddHandler( new wxMXFHandler );
+#endif // USE_MXF
+#if OPJ_MANYFORMATS
+ wxImage::AddHandler( new wxBMPHandler );
+ wxImage::AddHandler( new wxPNGHandler );
+ wxImage::AddHandler( new wxGIFHandler );
+ wxImage::AddHandler( new wxPNMHandler );
+ wxImage::AddHandler( new wxTIFFHandler );
+#endif
+ // we use a XPM image in our HTML page
+ wxImage::AddHandler(new wxXPMHandler);
+
+ // memory file system
+ wxFileSystem::AddHandler(new wxMemoryFSHandler);
+
+#ifdef OPJ_INICONFIG
+ //load decoding engine parameters
+ OPJconfig = new wxConfig(OPJ_APPLICATION, OPJ_APPLICATION_VENDOR);
+
+ OPJconfig->Read(wxT("decode/enabledeco"), &m_enabledeco, (bool) true);
+ OPJconfig->Read(wxT("decode/enableparse"), &m_enableparse, (bool) true);
+ OPJconfig->Read(wxT("decode/resizemethod"), &m_resizemethod, (long) 0);
+ OPJconfig->Read(wxT("decode/xxxreducefactor"), &m_reducefactor, (long) 0);
+ OPJconfig->Read(wxT("decode/xxxqualitylayers"), &m_qualitylayers, (long) 0);
+ OPJconfig->Read(wxT("decode/xxxcomponents"), &m_components, (long) 0);
+ OPJconfig->Read(wxT("decode/xxxframenum"), &m_framenum, (long) 0);
+#ifdef USE_JPWL
+ OPJconfig->Read(wxT("decode/enablejpwl"), &m_enablejpwl, (bool) true);
+ OPJconfig->Read(wxT("decode/expcomps"), &m_expcomps, (long) JPWL_EXPECTED_COMPONENTS);
+ OPJconfig->Read(wxT("decode/maxtiles"), &m_maxtiles, (long) JPWL_MAXIMUM_TILES);
+#endif // USE_JPWL
+
+ OPJconfig->Write(wxT("teststring"), wxT("This is a test value"));
+ OPJconfig->Write(wxT("testbool"), (bool) true);
+ OPJconfig->Write(wxT("testlong"), (long) 245);
+
+ OPJconfig->Read(wxT("showtoolbar"), &m_showtoolbar, (bool) true);
+ OPJconfig->Read(wxT("showbrowser"), &m_showbrowser, (bool) true);
+ OPJconfig->Read(wxT("showpeeker"), &m_showpeeker, (bool) true);
+ OPJconfig->Read(wxT("browserwidth"), &m_browserwidth, (long) OPJ_BROWSER_WIDTH);
+ OPJconfig->Read(wxT("peekerheight"), &m_peekerheight, (long) OPJ_PEEKER_HEIGHT);
+ OPJconfig->Read(wxT("framewidth"), &m_framewidth, (long) OPJ_FRAME_WIDTH);
+ OPJconfig->Read(wxT("frameheight"), &m_frameheight, (long) OPJ_FRAME_HEIGHT);
+
+ // load encoding engine parameters
+ OPJconfig->Read(wxT("encode/subsampling"), &m_subsampling, (wxString) wxT("1,1"));
+ OPJconfig->Read(wxT("encode/origin"), &m_origin, (wxString) wxT("0,0"));
+ OPJconfig->Read(wxT("encode/rates"), &m_rates, (wxString) wxT("20,10,5"));
+ OPJconfig->Read(wxT("encode/quality"), &m_quality, (wxString) wxT("30,35,40"));
+ OPJconfig->Read(wxT("encode/enablequality"), &m_enablequality, (bool) false);
+ OPJconfig->Read(wxT("encode/multicomp"), &m_multicomp, (bool) false);
+ OPJconfig->Read(wxT("encode/irreversible"), &m_irreversible, (bool) false);
+ OPJconfig->Read(wxT("encode/resolutions"), &m_resolutions, (int) 6);
+ OPJconfig->Read(wxT("encode/progression"), &m_progression, (int) 0);
+ OPJconfig->Read(wxT("encode/cbsize"), &m_cbsize, (wxString) wxT("32,32"));
+ OPJconfig->Read(wxT("encode/prsize"), &m_prsize, (wxString) wxT("[128,128],[128,128]"));
+ OPJconfig->Read(wxT("encode/tsize"), &m_tsize, (wxString) wxT(""));
+ OPJconfig->Read(wxT("encode/torigin"), &m_torigin, (wxString) wxT("0,0"));
+ OPJconfig->Read(wxT("encode/enablesop"), &m_enablesop, (bool) false);
+ OPJconfig->Read(wxT("encode/enableeph"), &m_enableeph, (bool) false);
+ OPJconfig->Read(wxT("encode/enablebypass"), &m_enablebypass, (bool) false);
+ OPJconfig->Read(wxT("encode/enablereset"), &m_enablereset, (bool) false);
+ OPJconfig->Read(wxT("encode/enablerestart"), &m_enablerestart, (bool) false);
+ OPJconfig->Read(wxT("encode/enablevsc"), &m_enablevsc, (bool) false);
+ OPJconfig->Read(wxT("encode/enableerterm"), &m_enableerterm, (bool) false);
+ OPJconfig->Read(wxT("encode/enablesegmark"), &m_enablesegmark, (bool) false);
+ OPJconfig->Read(wxT("encode/enablecomm"), &m_enablecomm, (bool) true);
+ OPJconfig->Read(wxT("encode/enablepoc"), &m_enablepoc, (bool) false);
+ OPJconfig->Read(wxT("encode/comment"), &m_comment, (wxString) wxT(""));
+ OPJconfig->Read(wxT("encode/poc"), &m_poc, (wxString) wxT("T1=0,0,1,5,3,CPRL/T1=5,0,1,6,3,CPRL"));
+ OPJconfig->Read(wxT("encode/enableidx"), &m_enableidx, (bool) false);
+ OPJconfig->Read(wxT("encode/index"), &m_index, (wxString) wxT("index.txt"));
+#ifdef USE_JPWL
+ OPJconfig->Read(wxT("encode/enablejpwl"), &m_enablejpwle, (bool) true);
+ for (n = 0; n < MYJPWL_MAX_NO_TILESPECS; n++) {
+ OPJconfig->Read(wxT("encode/jpwl/hprotsel") + wxString::Format(wxT("%02d"), n), &m_hprotsel[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/htileval") + wxString::Format(wxT("%02d"), n), &m_htileval[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/pprotsel") + wxString::Format(wxT("%02d"), n), &m_pprotsel[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/ptileval") + wxString::Format(wxT("%02d"), n), &m_ptileval[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/ppackval") + wxString::Format(wxT("%02d"), n), &m_ppackval[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/sensisel") + wxString::Format(wxT("%02d"), n), &m_sensisel[n], 0);
+ OPJconfig->Read(wxT("encode/jpwl/stileval") + wxString::Format(wxT("%02d"), n), &m_stileval[n], 0);
+ }
+#endif // USE_JPWL
+
+#else
+ // set decoding engine parameters
+ m_enabledeco = true;
+ m_enableparse = true;
+ m_resizemethod = 0;
+ m_reducefactor = 0;
+ m_qualitylayers = 0;
+ m_components = 0;
+ m_framenum = 0;
+#ifdef USE_JPWL
+ m_enablejpwl = true;
+ m_expcomps = JPWL_EXPECTED_COMPONENTS;
+ m_maxtiles = JPWL_MAXIMUM_TILES;
+#endif // USE_JPWL
+ m_showtoolbar = true;
+ m_showbrowser = true;
+ m_showpeeker = true;
+ m_browserwidth = OPJ_BROWSER_WIDTH;
+ m_peekerheight = OPJ_PEEKER_HEIGHT;
+ m_framewidth = OPJ_FRAME_WIDTH;
+ m_frameheight = OPJ_FRAME_HEIGHT;
+
+ // set encoding engine parameters
+ m_subsampling = wxT("1,1");
+ m_origin = wxT("0,0");
+ m_rates = wxT("20,10,5");
+ m_quality = wxT("30,35,40");
+ m_enablequality = false;
+ m_multicomp = false;
+ m_irreversible = false;
+ m_resolutions = 6;
+ m_progression = 0;
+ m_cbsize= wxT("32,32");
+ m_prsize= wxT("[128,128],[128,128]");
+ m_tsize = wxT("");
+ m_torigin = wxT("0,0");
+ m_enablesop = false;
+ m_enableeph = false;
+ m_enablebypass = false;
+ m_enablereset = false;
+ m_enablerestart = false;
+ m_enablevsc = false;
+ m_enableerterm = false;
+ m_enablesegmark = false;
+ m_enableidx = false;
+ m_index = wxT("index.txt");
+ m_enablecomm = true;
+ m_comment = wxT("");
+ m_enablepoc = false;
+ m_poc = wxT("T1=0,0,1,5,3,CPRL/T1=5,0,1,6,3,CPRL");
+#ifdef USE_JPWL
+ m_enablejpwle = true;
+ for (n = 0; n < MYJPWL_MAX_NO_TILESPECS; n++) {
+ m_hprotsel[n] = 0;
+ m_htileval[n] = 0;
+ m_pprotsel[n] = 0;
+ m_ptileval[n] = 0;
+ m_sensisel[n] = 0;
+ m_stileval[n] = 0;
+ }
+#endif // USE_JPWL
+
+#endif // OPJ_INICONFIG
+
+ if (m_comment == wxT("")) {
+#if defined __WXMSW__
+ m_comment = wxT("Created by OPJViewer Win32 - OpenJPEG version ");
+#elif defined __WXGTK__
+ m_comment = wxT("Created by OPJViewer Lin32 - OpenJPEG version ");
+#else
+ m_comment = wxT("Created by OPJViewer - OpenJPEG version ");
+#endif
+
+#ifdef USE_JPWL
+ m_comment += wxString::Format(wxT("%s with JPWL"), (char *) opj_version());
+#else
+ m_comment += wxString::Format(wxT("%s"), (char *) opj_version());
+#endif
+ }
+
+ // Create the main frame window
+ OPJFrame *frame = new OPJFrame(NULL, wxID_ANY, OPJ_APPLICATION_TITLEBAR,
+ wxDefaultPosition, wxSize(wxGetApp().m_framewidth, wxGetApp().m_frameheight),
+ wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE |
+ wxHSCROLL | wxVSCROLL);
+
+ // Give it an icon (this is ignored in MDI mode: uses resources)
+#ifdef __WXMSW__
+ frame->SetIcon(wxIcon(wxT("OPJViewer16")));
+#endif
+
+ frame->Show(true);
+
+ SetTopWindow(frame);
+
+ // if there are files on the command line, open them
+ if (!(m_filelist.IsEmpty())) {
+ //wxLogMessage(wxT("Habemus files!!!"));
+ wxArrayString paths, filenames;
+ for (unsigned int f = 0; f < wxGetApp().m_filelist.GetCount(); f++) {
+ paths.Add(wxFileName(wxGetApp().m_filelist[f]).GetFullPath());
+ filenames.Add(wxFileName(wxGetApp().m_filelist[f]).GetFullName());
+ }
+ //wxLogMessage(paths[0]);
+ frame->OpenFiles(paths, filenames);
+ }
+
+ return true;
+}
+
+int OPJViewerApp::OnExit()
+{
+ int n;
+
+#ifdef OPJ_INICONFIG
+ OPJconfig->Write(wxT("decode/enabledeco"), m_enabledeco);
+ OPJconfig->Write(wxT("decode/enableparse"), m_enableparse);
+ OPJconfig->Write(wxT("decode/resizemethod"), m_resizemethod);
+ OPJconfig->Write(wxT("decode/reducefactor"), m_reducefactor);
+ OPJconfig->Write(wxT("decode/qualitylayers"), m_qualitylayers);
+ OPJconfig->Write(wxT("decode/components"), m_components);
+ OPJconfig->Write(wxT("decode/framenum"), m_framenum);
+#ifdef USE_JPWL
+ OPJconfig->Write(wxT("decode/enablejpwl"), m_enablejpwl);
+ OPJconfig->Write(wxT("decode/expcomps"), m_expcomps);
+ OPJconfig->Write(wxT("decode/maxtiles"), m_maxtiles);
+#endif // USE_JPWL
+ OPJconfig->Write(wxT("showtoolbar"), m_showtoolbar);
+ OPJconfig->Write(wxT("showbrowser"), m_showbrowser);
+ OPJconfig->Write(wxT("showpeeker"), m_showpeeker);
+ OPJconfig->Write(wxT("browserwidth"), m_browserwidth);
+ OPJconfig->Write(wxT("peekerheight"), m_peekerheight);
+ OPJconfig->Write(wxT("framewidth"), m_framewidth);
+ OPJconfig->Write(wxT("frameheight"), m_frameheight);
+
+ OPJconfig->Write(wxT("encode/subsampling"), m_subsampling);
+ OPJconfig->Write(wxT("encode/origin"), m_origin);
+ OPJconfig->Write(wxT("encode/rates"), m_rates);
+ OPJconfig->Write(wxT("encode/quality"), m_quality);
+ OPJconfig->Write(wxT("encode/enablequality"), m_enablequality);
+ OPJconfig->Write(wxT("encode/multicomp"), m_multicomp);
+ OPJconfig->Write(wxT("encode/irreversible"), m_irreversible);
+ OPJconfig->Write(wxT("encode/resolutions"), m_resolutions);
+ OPJconfig->Write(wxT("encode/progression"), m_progression);
+ OPJconfig->Write(wxT("encode/cbsize"), m_cbsize);
+ OPJconfig->Write(wxT("encode/prsize"), m_prsize);
+ OPJconfig->Write(wxT("encode/tiles"), m_tsize);
+ OPJconfig->Write(wxT("encode/torigin"), m_torigin);
+ OPJconfig->Write(wxT("encode/enablesop"), m_enablesop);
+ OPJconfig->Write(wxT("encode/enableeph"), m_enableeph);
+ OPJconfig->Write(wxT("encode/enablebypass"), m_enablebypass);
+ OPJconfig->Write(wxT("encode/enablereset"), m_enablereset);
+ OPJconfig->Write(wxT("encode/enablerestart"), m_enablerestart);
+ OPJconfig->Write(wxT("encode/enablevsc"), m_enablevsc);
+ OPJconfig->Write(wxT("encode/enableerterm"), m_enableerterm);
+ OPJconfig->Write(wxT("encode/enablesegmark"), m_enablesegmark);
+ OPJconfig->Write(wxT("encode/enableidx"), m_enableidx);
+ OPJconfig->Write(wxT("encode/index"), m_index);
+ OPJconfig->Write(wxT("encode/enablecomm"), m_enablecomm);
+ OPJconfig->Write(wxT("encode/comment"), m_comment);
+ OPJconfig->Write(wxT("encode/enablepoc"), m_enablepoc);
+ OPJconfig->Write(wxT("encode/poc"), m_poc);
+#ifdef USE_JPWL
+ OPJconfig->Write(wxT("encode/enablejpwl"), m_enablejpwle);
+ for (n = 0; n < MYJPWL_MAX_NO_TILESPECS; n++) {
+ OPJconfig->Write(wxT("encode/jpwl/hprotsel") + wxString::Format(wxT("%02d"), n), m_hprotsel[n]);
+ OPJconfig->Write(wxT("encode/jpwl/htileval") + wxString::Format(wxT("%02d"), n), m_htileval[n]);
+ OPJconfig->Write(wxT("encode/jpwl/pprotsel") + wxString::Format(wxT("%02d"), n), m_pprotsel[n]);
+ OPJconfig->Write(wxT("encode/jpwl/ptileval") + wxString::Format(wxT("%02d"), n), m_ptileval[n]);
+ OPJconfig->Write(wxT("encode/jpwl/ppackval") + wxString::Format(wxT("%02d"), n), m_ppackval[n]);
+ OPJconfig->Write(wxT("encode/jpwl/sensisel") + wxString::Format(wxT("%02d"), n), m_sensisel[n]);
+ OPJconfig->Write(wxT("encode/jpwl/stileval") + wxString::Format(wxT("%02d"), n), m_stileval[n]);
+ }
+#endif // USE_JPWL
+
+#endif // OPJ_INICONFIG
+
+ return 1;
+}
+
+void OPJViewerApp::ShowCmdLine(const wxCmdLineParser& parser)
+{
+ wxString s = wxT("Command line parsed successfully:\nInput files: ");
+
+ size_t count = parser.GetParamCount();
+ for (size_t param = 0; param < count; param++) {
+ s << parser.GetParam(param) << ';';
+ m_filelist.Add(parser.GetParam(param));
+ }
+
+ //wxLogMessage(s);
+}
+
+// OPJFrame events
+
+// Event class for sending text messages between worker and GUI threads
+BEGIN_EVENT_TABLE(OPJFrame, wxMDIParentFrame)
+ EVT_MENU(OPJFRAME_HELPABOUT, OPJFrame::OnAbout)
+ EVT_MENU(OPJFRAME_FILEOPEN, OPJFrame::OnFileOpen)
+ EVT_MENU(OPJFRAME_FILESAVEAS, OPJFrame::OnFileSaveAs)
+ EVT_MENU(OPJFRAME_MEMORYOPEN, OPJFrame::OnMemoryOpen)
+ EVT_SIZE(OPJFrame::OnSize)
+ EVT_MENU(OPJFRAME_FILEEXIT, OPJFrame::OnQuit)
+ EVT_MENU(OPJFRAME_FILECLOSE, OPJFrame::OnClose)
+ EVT_MENU(OPJFRAME_VIEWZOOM, OPJFrame::OnZoom)
+ EVT_MENU(OPJFRAME_VIEWFIT, OPJFrame::OnFit)
+ EVT_MENU(OPJFRAME_VIEWRELOAD, OPJFrame::OnReload)
+ EVT_MENU(OPJFRAME_VIEWPREVFRAME, OPJFrame::OnPrevFrame)
+ EVT_MENU(OPJFRAME_VIEWHOMEFRAME, OPJFrame::OnHomeFrame)
+ EVT_MENU(OPJFRAME_VIEWNEXTFRAME, OPJFrame::OnNextFrame)
+ EVT_MENU(OPJFRAME_VIEWLESSLAYERS, OPJFrame::OnLessLayers)
+ EVT_MENU(OPJFRAME_VIEWALLLAYERS, OPJFrame::OnAllLayers)
+ EVT_MENU(OPJFRAME_VIEWMORELAYERS, OPJFrame::OnMoreLayers)
+ EVT_MENU(OPJFRAME_VIEWLESSRES, OPJFrame::OnLessRes)
+ EVT_MENU(OPJFRAME_VIEWFULLRES, OPJFrame::OnFullRes)
+ EVT_MENU(OPJFRAME_VIEWMORERES, OPJFrame::OnMoreRes)
+ EVT_MENU(OPJFRAME_VIEWPREVCOMP, OPJFrame::OnPrevComp)
+ EVT_MENU(OPJFRAME_VIEWALLCOMPS, OPJFrame::OnAllComps)
+ EVT_MENU(OPJFRAME_VIEWNEXTCOMP, OPJFrame::OnNextComp)
+ EVT_MENU(OPJFRAME_FILETOGGLEB, OPJFrame::OnToggleBrowser)
+ EVT_MENU(OPJFRAME_FILETOGGLEP, OPJFrame::OnTogglePeeker)
+ EVT_MENU(OPJFRAME_FILETOGGLET, OPJFrame::OnToggleToolbar)
+ EVT_MENU(OPJFRAME_SETSENCO, OPJFrame::OnSetsEnco)
+ EVT_MENU(OPJFRAME_SETSDECO, OPJFrame::OnSetsDeco)
+ EVT_SASH_DRAGGED_RANGE(OPJFRAME_BROWSEWIN, OPJFRAME_LOGWIN, OPJFrame::OnSashDrag)
+ EVT_NOTEBOOK_PAGE_CHANGED(LEFT_NOTEBOOK_ID, OPJFrame::OnNotebook)
+ EVT_MENU(OPJFRAME_THREADLOGMSG, OPJFrame::OnThreadLogmsg)
+END_EVENT_TABLE()
+
+// this is the frame constructor
+OPJFrame::OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
+ const wxPoint& pos, const wxSize& size, const long style)
+ : wxMDIParentFrame(parent, id, title, pos, size, style)
+{
+ // file menu and its items
+ wxMenu *file_menu = new wxMenu;
+
+ file_menu->Append(OPJFRAME_FILEOPEN, wxT("&Open\tCtrl+O"));
+ file_menu->SetHelpString(OPJFRAME_FILEOPEN, wxT("Open one or more files"));
+
+ file_menu->Append(OPJFRAME_MEMORYOPEN, wxT("&Memory\tCtrl+M"));
+ file_menu->SetHelpString(OPJFRAME_MEMORYOPEN, wxT("Open a memory buffer"));
+
+ file_menu->Append(OPJFRAME_FILECLOSE, wxT("&Close\tCtrl+C"));
+ file_menu->SetHelpString(OPJFRAME_FILECLOSE, wxT("Close current image"));
+
+ file_menu->AppendSeparator();
+
+ file_menu->Append(OPJFRAME_FILESAVEAS, wxT("&Save as\tCtrl+S"));
+ file_menu->SetHelpString(OPJFRAME_FILESAVEAS, wxT("Save the current image"));
+ //file_menu->Enable(OPJFRAME_FILESAVEAS, false);
+
+ file_menu->AppendSeparator();
+
+ file_menu->Append(OPJFRAME_FILETOGGLEB, wxT("Toggle &browser\tCtrl+B"));
+ file_menu->SetHelpString(OPJFRAME_FILETOGGLEB, wxT("Toggle the left browsing pane"));
+
+ file_menu->Append(OPJFRAME_FILETOGGLEP, wxT("Toggle &peeker\tCtrl+P"));
+ file_menu->SetHelpString(OPJFRAME_FILETOGGLEP, wxT("Toggle the bottom peeking pane"));
+
+ file_menu->Append(OPJFRAME_FILETOGGLET, wxT("Toggle &toolbar\tCtrl+T"));
+ file_menu->SetHelpString(OPJFRAME_FILETOGGLET, wxT("Toggle the toolbar"));
+
+ file_menu->AppendSeparator();
+
+ file_menu->Append(OPJFRAME_FILEEXIT, wxT("&Exit\tCtrl+Q"));
+ file_menu->SetHelpString(OPJFRAME_FILEEXIT, wxT("Quit this program"));
+
+ // view menu and its items
+ wxMenu *view_menu = new wxMenu;
+
+ view_menu->Append(OPJFRAME_VIEWZOOM, wxT("&Zoom\tCtrl+Z"));
+ view_menu->SetHelpString(OPJFRAME_VIEWZOOM, wxT("Rescale the image"));
+
+ view_menu->Append(OPJFRAME_VIEWFIT, wxT("Zoom to &fit\tCtrl+F"));
+ view_menu->SetHelpString(OPJFRAME_VIEWFIT, wxT("Fit the image in canvas"));
+
+ view_menu->Append(OPJFRAME_VIEWRELOAD, wxT("&Reload image\tCtrl+R"));
+ view_menu->SetHelpString(OPJFRAME_VIEWRELOAD, wxT("Reload the current image"));
+
+ view_menu->AppendSeparator();
+
+ view_menu->Append(OPJFRAME_VIEWPREVFRAME, wxT("&Prev frame\tLeft"));
+ view_menu->SetHelpString(OPJFRAME_VIEWPREVFRAME, wxT("View previous frame"));
+
+ view_menu->Append(OPJFRAME_VIEWHOMEFRAME, wxT("&Start frame\tHome"));
+ view_menu->SetHelpString(OPJFRAME_VIEWHOMEFRAME, wxT("View starting frame"));
+
+ view_menu->Append(OPJFRAME_VIEWNEXTFRAME, wxT("&Next frame\tRight"));
+ view_menu->SetHelpString(OPJFRAME_VIEWNEXTFRAME, wxT("View next frame"));
+
+ view_menu->AppendSeparator();
+
+ view_menu->Append(OPJFRAME_VIEWLESSLAYERS, wxT("&Less layers\t-"));
+ view_menu->SetHelpString(OPJFRAME_VIEWLESSLAYERS, wxT("Remove a layer"));
+
+ view_menu->Append(OPJFRAME_VIEWALLLAYERS, wxT("&All layers\t0"));
+ view_menu->SetHelpString(OPJFRAME_VIEWALLLAYERS, wxT("Show all layers"));
+
+ view_menu->Append(OPJFRAME_VIEWMORELAYERS, wxT("&More layers\t+"));
+ view_menu->SetHelpString(OPJFRAME_VIEWMORELAYERS, wxT("Add a layer"));
+
+ view_menu->AppendSeparator();
+
+ view_menu->Append(OPJFRAME_VIEWLESSRES, wxT("&Less resolution\t<"));
+ view_menu->SetHelpString(OPJFRAME_VIEWLESSRES, wxT("Reduce the resolution"));
+
+ view_menu->Append(OPJFRAME_VIEWFULLRES, wxT("&Full resolution\tf"));
+ view_menu->SetHelpString(OPJFRAME_VIEWFULLRES, wxT("Full resolution"));
+
+ view_menu->Append(OPJFRAME_VIEWMORERES, wxT("&More resolution\t>"));
+ view_menu->SetHelpString(OPJFRAME_VIEWMORERES, wxT("Increase the resolution"));
+
+ view_menu->AppendSeparator();
+
+ view_menu->Append(OPJFRAME_VIEWPREVCOMP, wxT("&Prev component\tDown"));
+ view_menu->SetHelpString(OPJFRAME_VIEWPREVCOMP, wxT("View previous component"));
+
+ view_menu->Append(OPJFRAME_VIEWALLCOMPS, wxT("&All components\ta"));
+ view_menu->SetHelpString(OPJFRAME_VIEWALLCOMPS, wxT("View all components"));
+
+ view_menu->Append(OPJFRAME_VIEWNEXTCOMP, wxT("&Next component\tUp"));
+ view_menu->SetHelpString(OPJFRAME_VIEWNEXTCOMP, wxT("View next component"));
+
+
+ // settings menu and its items
+ wxMenu *sets_menu = new wxMenu;
+
+ sets_menu->Append(OPJFRAME_SETSENCO, wxT("&Encoder\tCtrl+E"));
+ sets_menu->SetHelpString(OPJFRAME_SETSENCO, wxT("Encoder settings"));
+
+ sets_menu->Append(OPJFRAME_SETSDECO, wxT("&Decoder\tCtrl+D"));
+ sets_menu->SetHelpString(OPJFRAME_SETSDECO, wxT("Decoder settings"));
+
+ // help menu and its items
+ wxMenu *help_menu = new wxMenu;
+
+ help_menu->Append(OPJFRAME_HELPABOUT, wxT("&About\tF1"));
+ help_menu->SetHelpString(OPJFRAME_HELPABOUT, wxT("Basic info on the program"));
+
+ // the whole menubar
+ wxMenuBar *menu_bar = new wxMenuBar;
+ menu_bar->Append(file_menu, wxT("&File"));
+ menu_bar->Append(view_menu, wxT("&View"));
+ menu_bar->Append(sets_menu, wxT("&Settings"));
+ menu_bar->Append(help_menu, wxT("&Help"));
+
+ // Associate the menu bar with the frame
+ SetMenuBar(menu_bar);
+
+ // the status bar
+ CreateStatusBar();
+
+ // the toolbar
+ tool_bar = new wxToolBar(this, OPJFRAME_TOOLBAR,
+ wxDefaultPosition, wxDefaultSize,
+ wxTB_HORIZONTAL | wxNO_BORDER);
+ wxBitmap bmpOpen = wxArtProvider::GetBitmap(wxART_FILE_OPEN, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpSaveAs = wxArtProvider::GetBitmap(wxART_FILE_SAVE_AS, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpZoom = wxArtProvider::GetBitmap(wxART_FIND, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpFit = wxArtProvider::GetBitmap(wxART_FIND_AND_REPLACE, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpReload = wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpDecosettings = wxArtProvider::GetBitmap(wxART_REPORT_VIEW, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpEncosettings = wxArtProvider::GetBitmap(wxART_LIST_VIEW, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpPrevframe = wxArtProvider::GetBitmap(wxART_GO_BACK, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpHomeframe = wxArtProvider::GetBitmap(wxART_GO_HOME, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpNextframe = wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpLesslayers = bmpPrevframe;
+ wxBitmap bmpAlllayers = wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpMorelayers = bmpNextframe;
+ wxBitmap bmpLessres = bmpPrevframe;
+ wxBitmap bmpFullres = wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpMoreres = bmpNextframe;
+ wxBitmap bmpPrevcomp = bmpPrevframe;
+ wxBitmap bmpAllcomps = wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_TOOLBAR,
+ wxDefaultSize);
+ wxBitmap bmpNextcomp = bmpNextframe;
+
+ tool_bar->AddTool(OPJFRAME_FILEOPEN, bmpOpen, wxT("Open"));
+ tool_bar->AddTool(OPJFRAME_FILESAVEAS, bmpSaveAs, wxT("Save as "));
+ //tool_bar->EnableTool(OPJFRAME_FILESAVEAS, false);
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_VIEWZOOM, bmpZoom, wxT("Zoom"));
+ tool_bar->AddTool(OPJFRAME_VIEWFIT, bmpFit, wxT("Zoom to fit"));
+ tool_bar->AddTool(OPJFRAME_VIEWRELOAD, bmpReload, wxT("Reload"));
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_SETSDECO, bmpDecosettings, wxT("Decoder settings"));
+ tool_bar->AddTool(OPJFRAME_SETSENCO, bmpEncosettings, wxT("Encoder settings"));
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_VIEWPREVFRAME, bmpPrevframe, wxT("Previous frame"));
+ tool_bar->AddTool(OPJFRAME_VIEWHOMEFRAME, bmpHomeframe, wxT("Starting frame"));
+ tool_bar->AddTool(OPJFRAME_VIEWNEXTFRAME, bmpNextframe, wxT("Next frame"));
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_VIEWLESSLAYERS, bmpLesslayers, wxT("Remove a layer"));
+ tool_bar->AddTool(OPJFRAME_VIEWALLLAYERS, bmpAlllayers, wxT("Show all layers"));
+ tool_bar->AddTool(OPJFRAME_VIEWMORELAYERS, bmpMorelayers, wxT("Add a layer"));
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_VIEWLESSRES, bmpLessres, wxT("Reduce the resolution"));
+ tool_bar->AddTool(OPJFRAME_VIEWFULLRES, bmpFullres, wxT("Full resolution"));
+ tool_bar->AddTool(OPJFRAME_VIEWMORERES, bmpMoreres, wxT("Increase the resolution"));
+ tool_bar->AddSeparator();
+ tool_bar->AddTool(OPJFRAME_VIEWPREVCOMP, bmpPrevcomp, wxT("Previous component"));
+ tool_bar->AddTool(OPJFRAME_VIEWALLCOMPS, bmpAllcomps, wxT("All components"));
+ tool_bar->AddTool(OPJFRAME_VIEWNEXTCOMP, bmpNextcomp, wxT("Next component"));
+ tool_bar->Realize();
+
+ // associate the toolbar with the frame
+ SetToolBar(tool_bar);
+
+ // show the toolbar?
+ if (!wxGetApp().m_showtoolbar)
+ tool_bar->Show(false);
+ else
+ tool_bar->Show(true);
+
+ // the logging window
+ loggingWindow = new wxSashLayoutWindow(this, OPJFRAME_LOGWIN,
+ wxDefaultPosition, wxSize(400, wxGetApp().m_peekerheight),
+ wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN
+ );
+ loggingWindow->SetDefaultSize(wxSize(1000, wxGetApp().m_peekerheight));
+ loggingWindow->SetOrientation(wxLAYOUT_HORIZONTAL);
+ loggingWindow->SetAlignment(wxLAYOUT_BOTTOM);
+ //loggingWindow->SetBackgroundColour(wxColour(0, 0, 255));
+ loggingWindow->SetSashVisible(wxSASH_TOP, true);
+
+ // show the logging?
+ if (!wxGetApp().m_showpeeker)
+ loggingWindow->Show(false);
+ else
+ loggingWindow->Show(true);
+
+ // create the bottom notebook
+ m_bookCtrlbottom = new wxNotebook(loggingWindow, BOTTOM_NOTEBOOK_ID,
+ wxDefaultPosition, wxDefaultSize,
+ wxBK_LEFT);
+
+ // create the text control of the logger
+ m_textCtrl = new wxTextCtrl(m_bookCtrlbottom, wxID_ANY, wxT(""),
+ wxDefaultPosition, wxDefaultSize,
+ wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY
+ );
+ m_textCtrl->SetValue(_T("Logging window\n"));
+
+ // add it to the notebook
+ m_bookCtrlbottom->AddPage(m_textCtrl, wxT("Log"));
+
+ // create the text control of the browser
+ m_textCtrlbrowse = new wxTextCtrl(m_bookCtrlbottom, wxID_ANY, wxT(""),
+ wxDefaultPosition, wxDefaultSize,
+ wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY | wxTE_RICH
+ );
+ wxFont *browsefont = new wxFont(wxNORMAL_FONT->GetPointSize(),
+ wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
+ m_textCtrlbrowse->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, *browsefont));
+ m_textCtrlbrowse->AppendText(wxT("Browsing window\n"));
+
+ // add it the notebook
+ m_bookCtrlbottom->AddPage(m_textCtrlbrowse, wxT("Peek"), false);
+
+ // the browser window
+ markerTreeWindow = new wxSashLayoutWindow(this, OPJFRAME_BROWSEWIN,
+ wxDefaultPosition, wxSize(wxGetApp().m_browserwidth, 30),
+ wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN
+ );
+ markerTreeWindow->SetDefaultSize(wxSize(wxGetApp().m_browserwidth, 1000));
+ markerTreeWindow->SetOrientation(wxLAYOUT_VERTICAL);
+ markerTreeWindow->SetAlignment(wxLAYOUT_LEFT);
+ //markerTreeWindow->SetBackgroundColour(wxColour(0, 255, 0));
+ markerTreeWindow->SetSashVisible(wxSASH_RIGHT, true);
+ markerTreeWindow->SetExtraBorderSize(0);
+
+ // create the browser notebook
+ m_bookCtrl = new wxNotebook(markerTreeWindow, LEFT_NOTEBOOK_ID,
+ wxDefaultPosition, wxDefaultSize,
+ wxBK_TOP);
+
+ // show the browser?
+ if (!wxGetApp().m_showbrowser)
+ markerTreeWindow->Show(false);
+ else
+ markerTreeWindow->Show(true);
+
+#ifdef __WXMOTIF__
+ // For some reason, we get a memcpy crash in wxLogStream::DoLogStream
+ // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?
+ delete wxLog::SetActiveTarget(new wxLogStderr);
+#else
+ // set our text control as the log target
+ wxLogTextCtrl *logWindow = new wxLogTextCtrl(m_textCtrl);
+ delete wxLog::SetActiveTarget(logWindow);
+#endif
+
+ // associate drop targets with the controls
+ SetDropTarget(new OPJDnDFile(this));
+
+}
+
+// this is the frame destructor
+OPJFrame::~OPJFrame(void)
+{
+ // save size settings
+ GetSize(&(wxGetApp().m_framewidth), &(wxGetApp().m_frameheight));
+
+ // delete all possible things
+ delete m_bookCtrl;
+ m_bookCtrl = NULL;
+
+ delete markerTreeWindow;
+ markerTreeWindow = NULL;
+
+ delete m_textCtrl;
+ m_textCtrl = NULL;
+
+ delete m_bookCtrlbottom;
+ m_bookCtrlbottom = NULL;
+
+ delete loggingWindow;
+ loggingWindow = NULL;
+}
+
+void OPJFrame::OnNotebook(wxNotebookEvent& event)
+{
+ int sel = event.GetSelection();
+ long childnum;
+
+ m_bookCtrl->GetPageText(sel).ToLong(&childnum);
+
+ if (m_childhash[childnum])
+ m_childhash[childnum]->Activate();
+
+ //wxLogMessage(wxT("Selection changed (now %d --> %d)"), childnum, m_childhash[childnum]->m_winnumber);
+
+}
+
+
+void OPJFrame::Resize(int number)
+{
+ wxSize size = GetClientSize();
+}
+
+void OPJFrame::OnSetsEnco(wxCommandEvent& event)
+{
+ int n;
+
+ OPJEncoderDialog dialog(this, event.GetId());
+
+ if (dialog.ShowModal() == wxID_OK) {
+
+ // load settings
+ wxGetApp().m_subsampling = dialog.m_subsamplingCtrl->GetValue();
+ wxGetApp().m_origin = dialog.m_originCtrl->GetValue();
+ wxGetApp().m_rates = dialog.m_rateCtrl->GetValue();
+ wxGetApp().m_quality = dialog.m_qualityCtrl->GetValue();
+ wxGetApp().m_enablequality = dialog.m_qualityRadio->GetValue();
+ wxGetApp().m_multicomp = dialog.m_mctCheck->GetValue();
+ wxGetApp().m_irreversible = dialog.m_irrevCheck->GetValue();
+ wxGetApp().m_resolutions = dialog.m_resolutionsCtrl->GetValue();
+ wxGetApp().m_cbsize = dialog.m_cbsizeCtrl->GetValue();
+ wxGetApp().m_prsize = dialog.m_prsizeCtrl->GetValue();
+ wxGetApp().m_tsize = dialog.m_tsizeCtrl->GetValue();
+ wxGetApp().m_torigin = dialog.m_toriginCtrl->GetValue();
+ wxGetApp().m_progression = dialog.progressionBox->GetSelection();
+ wxGetApp().m_enablesop = dialog.m_sopCheck->GetValue();
+ wxGetApp().m_enableeph = dialog.m_ephCheck->GetValue();
+ wxGetApp().m_enablebypass = dialog.m_enablebypassCheck->GetValue();
+ wxGetApp().m_enablereset = dialog.m_enableresetCheck->GetValue();
+ wxGetApp().m_enablerestart = dialog.m_enablerestartCheck->GetValue();
+ wxGetApp().m_enablevsc = dialog.m_enablevscCheck->GetValue();
+ wxGetApp().m_enableerterm = dialog.m_enableertermCheck->GetValue();
+ wxGetApp().m_enablesegmark = dialog.m_enablesegmarkCheck->GetValue();
+ wxGetApp().m_enableidx = dialog.m_enableidxCheck->GetValue();
+ wxGetApp().m_index = dialog.m_indexCtrl->GetValue();
+ wxGetApp().m_enablecomm = dialog.m_enablecommCheck->GetValue();
+ wxGetApp().m_comment = dialog.m_commentCtrl->GetValue();
+ wxGetApp().m_enablepoc = dialog.m_enablepocCheck->GetValue();
+ wxGetApp().m_poc = dialog.m_pocCtrl->GetValue();
+#ifdef USE_JPWL
+ wxGetApp().m_enablejpwle = dialog.m_enablejpwlCheck->GetValue();
+ for (n = 0; n < MYJPWL_MAX_NO_TILESPECS; n++) {
+ wxGetApp().m_hprotsel[n] = dialog.m_hprotChoice[n]->GetSelection();
+ wxGetApp().m_htileval[n] = dialog.m_htileCtrl[n]->GetValue();
+ wxGetApp().m_pprotsel[n] = dialog.m_pprotChoice[n]->GetSelection();
+ wxGetApp().m_ptileval[n] = dialog.m_ptileCtrl[n]->GetValue();
+ wxGetApp().m_ppackval[n] = dialog.m_ppackCtrl[n]->GetValue();
+ wxGetApp().m_sensisel[n] = dialog.m_sensiChoice[n]->GetSelection();
+ wxGetApp().m_stileval[n] = dialog.m_stileCtrl[n]->GetValue();
+ }
+#endif // USE_JPWL
+ };
+}
+
+void OPJFrame::OnSetsDeco(wxCommandEvent& event)
+{
+ OPJDecoderDialog dialog(this, event.GetId());
+
+ if (dialog.ShowModal() == wxID_OK) {
+
+ // load settings
+ wxGetApp().m_enabledeco = dialog.m_enabledecoCheck->GetValue();
+ wxGetApp().m_enableparse = dialog.m_enableparseCheck->GetValue();
+ wxGetApp().m_resizemethod = dialog.m_resizeBox->GetSelection() - 1;
+ wxGetApp().m_reducefactor = dialog.m_reduceCtrl->GetValue();
+ wxGetApp().m_qualitylayers = dialog.m_layerCtrl->GetValue();
+ wxGetApp().m_components = dialog.m_numcompsCtrl->GetValue();
+ wxGetApp().m_framenum = dialog.m_framenumCtrl->GetValue();
+#ifdef USE_JPWL
+ wxGetApp().m_enablejpwl = dialog.m_enablejpwlCheck->GetValue();
+ wxGetApp().m_expcomps = dialog.m_expcompsCtrl->GetValue();
+ wxGetApp().m_maxtiles = dialog.m_maxtilesCtrl->GetValue();
+#endif // USE_JPWL
+
+ };
+}
+
+void OPJFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+ Close(true);
+}
+
+void OPJFrame::OnClose(wxCommandEvent& WXUNUSED(event))
+{
+ // current frame
+ OPJChildFrame *currframe = (OPJChildFrame *) GetActiveChild();
+
+ if (!currframe)
+ return;
+
+ wxCloseEvent e;
+ currframe->OnClose(e);
+}
+
+void OPJFrame::OnFit(wxCommandEvent& event)
+{
+ OPJChildFrame *currchild;
+ wxString eventstring = event.GetString();
+
+ //wxLogMessage(wxT("OnFit:%d:%s"), event.GetInt(), eventstring);
+
+ // current child
+ if (event.GetInt() >= 1) {
+ currchild = m_childhash[event.GetInt()];
+ } else {
+ currchild = (OPJChildFrame *) GetActiveChild();
+ }
+
+ // problems
+ if (!currchild)
+ return;
+
+ // current canvas
+ OPJCanvas *currcanvas = currchild->m_canvas;
+
+ // find a fit-to-width zoom
+ /*int zooml, wzooml, hzooml;
+ wxSize clientsize = currcanvas->GetClientSize();
+ wzooml = (int) ceil(100.0 * (double) (clientsize.GetWidth() - 2 * OPJ_CANVAS_BORDER) / (double) (currcanvas->m_image100.GetWidth()));
+ hzooml = (int) ceil(100.0 * (double) (clientsize.GetHeight() - 2 * OPJ_CANVAS_BORDER) / (double) (currcanvas->m_image100.GetHeight()));
+ zooml = wxMin(100, wxMin(wzooml, hzooml));*/
+
+ // fit to width
+ Rescale(-1, currchild);
+}
+
+void OPJFrame::OnZoom(wxCommandEvent& WXUNUSED(event))
+{
+ // current frame
+ OPJChildFrame *currframe = (OPJChildFrame *) GetActiveChild();
+
+ if (!currframe)
+ return;
+
+ // get the preferred zoom
+ long zooml = wxGetNumberFromUser(wxT("Choose a scale between 5% and 300%"),
+ wxT("Zoom (%)"),
+ wxT("Image scale"),
+ currframe->m_canvas->m_zooml, 5, 300, NULL, wxDefaultPosition);
+
+ // rescale current frame image if necessary
+ if (zooml >= 5) {
+ Rescale(zooml, currframe);
+ wxLogMessage(wxT("zoom to %d%%"), zooml);
+ }
+}
+
+void OPJFrame::Rescale(int zooml, OPJChildFrame *currframe)
+{
+ wxImage new_image = currframe->m_canvas->m_image100.ConvertToImage();
+
+ // resizing enabled?
+ if (wxGetApp().m_resizemethod == -1) {
+
+ zooml = 100;
+
+ } else {
+
+ if (zooml < 0) {
+ // find a fit-to-width zoom
+ int wzooml, hzooml;
+ //wxSize clientsize = currframe->m_canvas->GetClientSize();
+ wxSize clientsize = currframe->m_frame->GetActiveChild()->GetClientSize();
+ wzooml = (int) floor(100.0 * (double) clientsize.GetWidth() / (double) (2 * OPJ_CANVAS_BORDER + currframe->m_canvas->m_image100.GetWidth()));
+ hzooml = (int) floor(100.0 * (double) clientsize.GetHeight() / (double) (2 * OPJ_CANVAS_BORDER + currframe->m_canvas->m_image100.GetHeight()));
+ zooml = wxMin(100, wxMin(wzooml, hzooml));
+ }
+ }
+
+ if (zooml != 100)
+ new_image.Rescale((int) ((double) zooml * (double) new_image.GetWidth() / 100.0),
+ (int) ((double) zooml * (double) new_image.GetHeight() / 100.0),
+ wxGetApp().m_resizemethod ? wxIMAGE_QUALITY_HIGH : wxIMAGE_QUALITY_NORMAL);
+ currframe->m_canvas->m_image = wxBitmap(new_image);
+ currframe->m_canvas->SetScrollbars(20,
+ 20,
+ (int)(0.5 + (double) new_image.GetWidth() / 20.0),
+ (int)(0.5 + (double) new_image.GetHeight() / 20.0)
+ );
+
+ currframe->m_canvas->Refresh();
+
+ wxLogMessage(wxT("Rescale said %d%%"), zooml);
+
+ // update zoom
+ currframe->m_canvas->m_zooml = zooml;
+}
+
+
+void OPJFrame::OnReload(wxCommandEvent& event)
+{
+ OPJChildFrame *currframe = (OPJChildFrame *) GetActiveChild();
+
+ if (currframe) {
+ OPJDecoThread *dthread = currframe->m_canvas->CreateDecoThread();
+
+ if (dthread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start deco thread!"));
+ else
+ wxLogMessage(wxT("New deco thread started."));
+
+ currframe->m_canvas->Refresh();
+
+ // update zoom
+ //currframe->m_canvas->m_zooml = zooml;
+ }
+}
+
+void OPJFrame::OnPrevFrame(wxCommandEvent& event)
+{
+ if (--wxGetApp().m_framenum < 0)
+ wxGetApp().m_framenum = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnHomeFrame(wxCommandEvent& event)
+{
+ wxGetApp().m_framenum = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnNextFrame(wxCommandEvent& event)
+{
+ ++wxGetApp().m_framenum;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnLessLayers(wxCommandEvent& event)
+{
+ if (--wxGetApp().m_qualitylayers < 1)
+ wxGetApp().m_qualitylayers = 1;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnAllLayers(wxCommandEvent& event)
+{
+ wxGetApp().m_qualitylayers = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnMoreLayers(wxCommandEvent& event)
+{
+ ++wxGetApp().m_qualitylayers;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnLessRes(wxCommandEvent& event)
+{
+ ++wxGetApp().m_reducefactor;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnFullRes(wxCommandEvent& event)
+{
+ wxGetApp().m_reducefactor = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnMoreRes(wxCommandEvent& event)
+{
+ if (--wxGetApp().m_reducefactor < 0)
+ wxGetApp().m_reducefactor = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnPrevComp(wxCommandEvent& event)
+{
+ if (--wxGetApp().m_components < 1)
+ wxGetApp().m_components = 1;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnAllComps(wxCommandEvent& event)
+{
+ wxGetApp().m_components = 0;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnNextComp(wxCommandEvent& event)
+{
+ ++wxGetApp().m_components;
+
+ wxCommandEvent e;
+ OnReload(e);
+}
+
+void OPJFrame::OnToggleBrowser(wxCommandEvent& WXUNUSED(event))
+{
+ if (markerTreeWindow->IsShown())
+ markerTreeWindow->Show(false);
+ else
+ markerTreeWindow->Show(true);
+
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+
+ wxGetApp().m_showbrowser = markerTreeWindow->IsShown();
+
+ // Leaves bits of itself behind sometimes
+ GetClientWindow()->Refresh();
+}
+
+void OPJFrame::OnTogglePeeker(wxCommandEvent& WXUNUSED(event))
+{
+ if (loggingWindow->IsShown())
+ loggingWindow->Show(false);
+ else
+ loggingWindow->Show(true);
+
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+
+ wxGetApp().m_showpeeker = loggingWindow->IsShown();
+
+ // Leaves bits of itself behind sometimes
+ GetClientWindow()->Refresh();
+}
+
+void OPJFrame::OnToggleToolbar(wxCommandEvent& WXUNUSED(event))
+{
+ if (tool_bar->IsShown())
+ tool_bar->Show(false);
+ else
+ tool_bar->Show(true);
+
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+
+ wxGetApp().m_showtoolbar = tool_bar->IsShown();
+
+ // Leaves bits of itself behind sometimes
+ GetClientWindow()->Refresh();
+}
+
+void OPJFrame::OnSashDrag(wxSashEvent& event)
+{
+ int wid, hei;
+
+ if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)
+ return;
+
+ switch (event.GetId()) {
+ case OPJFRAME_BROWSEWIN:
+ {
+ markerTreeWindow->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));
+ break;
+ }
+ case OPJFRAME_LOGWIN:
+ {
+ loggingWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));
+ break;
+ }
+ }
+
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+
+ // Leaves bits of itself behind sometimes
+ GetClientWindow()->Refresh();
+
+ // update dimensions
+ markerTreeWindow->GetSize(&wid, &hei);
+ wxGetApp().m_browserwidth = wid;
+
+ loggingWindow->GetSize(&wid, &hei);
+ wxGetApp().m_peekerheight = hei;
+
+}
+
+void OPJFrame::OnThreadLogmsg(wxCommandEvent& event)
+{
+#if 1
+ wxLogMessage(wxT("Frame got message from worker thread: %d"), event.GetInt());
+ wxLogMessage(event.GetString());
+#else
+ int n = event.GetInt();
+ if ( n == -1 )
+ {
+ m_dlgProgress->Destroy();
+ m_dlgProgress = (wxProgressDialog *)NULL;
+
+ // the dialog is aborted because the event came from another thread, so
+ // we may need to wake up the main event loop for the dialog to be
+ // really closed
+ wxWakeUpIdle();
+ }
+ else
+ {
+ if ( !m_dlgProgress->Update(n) )
+ {
+ wxCriticalSectionLocker lock(m_critsectWork);
+
+ m_cancelled = true;
+ }
+ }
+#endif
+}
+
+
+// physically save the file
+void OPJFrame::SaveFile(wxArrayString paths, wxArrayString filenames)
+{
+ size_t count = paths.GetCount();
+ wxString msg, s;
+
+ if (wxFile::Exists(paths[0].c_str())) {
+
+ s.Printf(wxT("File %s already exists. Do you want to overwrite it?\n"), filenames[0].c_str());
+ wxMessageDialog dialog3(this, s, _T("File exists"), wxYES_NO);
+ if (dialog3.ShowModal() == wxID_NO)
+ return;
+ }
+
+ /*s.Printf(_T("File %d: %s (%s)\n"), (int)0, paths[0].c_str(), filenames[0].c_str());
+ msg += s;
+
+ wxMessageDialog dialog2(this, msg, _T("Selected files"));
+ dialog2.ShowModal();*/
+
+ if (!GetActiveChild())
+ return;
+
+ ((OPJChildFrame *) GetActiveChild())->m_canvas->m_savename = paths[0];
+
+ OPJEncoThread *ethread = ((OPJChildFrame *) GetActiveChild())->m_canvas->CreateEncoThread();
+
+ if (ethread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start enco thread!"));
+ else
+ wxLogMessage(wxT("New enco thread started."));
+
+
+}
+
+// physically open the files
+void OPJFrame::OpenFiles(wxArrayString paths, wxArrayString filenames)
+{
+
+ size_t count = paths.GetCount();
+ for (size_t n = 0; n < count; n++) {
+
+ wxString msg, s;
+ s.Printf(_T("File %d: %s (%s)\n"), (int)n, paths[n].c_str(), filenames[n].c_str());
+
+ msg += s;
+
+ /*wxMessageDialog dialog2(this, msg, _T("Selected files"));
+ dialog2.ShowModal();*/
+
+ // Make another frame, containing a canvas
+ OPJChildFrame *subframe = new OPJChildFrame(this,
+ paths[n],
+ winNumber,
+ wxT("Canvas Frame"),
+ wxDefaultPosition, wxSize(300, 300),
+ wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE
+ );
+ m_childhash[winNumber] = subframe;
+
+ // create own marker tree
+ m_treehash[winNumber] = new OPJMarkerTree(m_bookCtrl, subframe, paths[n], wxT("Parsing..."), TreeTest_Ctrl,
+ wxDefaultPosition, wxDefaultSize,
+ wxTR_DEFAULT_STYLE | wxSUNKEN_BORDER
+ );
+
+ m_bookCtrl->AddPage(m_treehash[winNumber], wxString::Format(wxT("%u"), winNumber), false);
+
+ for (unsigned int p = 0; p < m_bookCtrl->GetPageCount(); p++) {
+ if (m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), winNumber)) {
+ m_bookCtrl->ChangeSelection(p);
+ break;
+ }
+ }
+
+ winNumber++;
+ }
+}
+
+void OPJFrame::OnFileOpen(wxCommandEvent& WXUNUSED(event))
+{
+ wxString wildcards =
+#ifdef __WXMOTIF__
+ wxT("JPEG 2000 files (*.jp2,*.j2k,*.j2c,*.mj2)|*.*j*2*");
+#else
+#if wxUSE_LIBOPENJPEG
+ wxT("JPEG 2000 files (*.jp2,*.j2k,*.j2c,*.mj2)|*.jp2;*.j2k;*.j2c;*.mj2")
+#endif
+#if USE_MXF
+ wxT("|MXF JPEG 2000 video (*.mxf)|*.mxf")
+#endif // USE_MXF
+#if wxUSE_LIBJPEG
+ wxT("|JPEG files (*.jpg)|*.jpg")
+#endif
+#if OPJ_MANYFORMATS
+ wxT("|BMP files (*.bmp)|*.bmp")
+ wxT("|PNG files (*.png)|*.png")
+ wxT("|GIF files (*.gif)|*.gif")
+ wxT("|PNM files (*.pnm)|*.pnm")
+ wxT("|TIFF files (*.tif,*.tiff)|*.tif*")
+#endif
+ wxT("|All files|*");
+#endif
+ wxFileDialog dialog(this, _T("Open image file(s)"),
+ wxEmptyString, wxEmptyString, wildcards,
+ wxFD_OPEN|wxFD_MULTIPLE);
+
+ if (dialog.ShowModal() == wxID_OK) {
+ wxArrayString paths, filenames;
+
+ dialog.GetPaths(paths);
+ dialog.GetFilenames(filenames);
+
+ OpenFiles(paths, filenames);
+ }
+
+}
+
+void OPJFrame::OnFileSaveAs(wxCommandEvent& WXUNUSED(event))
+{
+ wxString wildcards =
+#ifdef wxUSE_LIBOPENJPEG
+#ifdef __WXMOTIF__
+ wxT("JPEG 2000 codestream (*.j2k)|*.*j*2*");
+#else
+ wxT("JPEG 2000 codestream (*.j2k)|*.j2k")
+ wxT("|JPEG 2000 file format (*.jp2)|*.jp2");
+#endif
+#else
+ wxT("Houston we have a problem");
+#endif
+
+ wxFileDialog dialog(this, _T("Save image file"),
+ wxEmptyString, wxEmptyString, wildcards,
+ wxFD_SAVE);
+
+ if (dialog.ShowModal() == wxID_OK) {
+ wxArrayString paths, filenames;
+
+ dialog.GetPaths(paths);
+ dialog.GetFilenames(filenames);
+
+ SaveFile(paths, filenames);
+ }
+
+
+}
+
+void OPJFrame::OnMemoryOpen(wxCommandEvent& WXUNUSED(event))
+{
+ // do nothing
+ return;
+
+ wxTextEntryDialog dialog(this, wxT("Memory HEX address range: start_address-stop_address"),
+ wxT("Decode a memory buffer"),
+ wxT("0x-0x"),
+ wxOK | wxCANCEL | wxCENTRE,
+ wxDefaultPosition);
+
+ if (dialog.ShowModal() == wxID_OK) {
+
+ }
+
+}
+
+BEGIN_EVENT_TABLE(OPJCanvas, wxScrolledWindow)
+ EVT_MOUSE_EVENTS(OPJCanvas::OnEvent)
+ EVT_MENU(OPJCANVAS_THREADSIGNAL, OPJCanvas::OnThreadSignal)
+END_EVENT_TABLE()
+
+// Define a constructor for my canvas
+OPJCanvas::OPJCanvas(wxFileName fname, wxWindow *parent, const wxPoint& pos, const wxSize& size)
+ : wxScrolledWindow(parent, wxID_ANY, pos, size,
+ wxSUNKEN_BORDER | wxNO_FULL_REPAINT_ON_RESIZE)
+{
+ SetBackgroundColour(OPJ_CANVAS_COLOUR);
+
+ m_fname = fname;
+ m_childframe = (OPJChildFrame *) parent;
+ // 100% zoom
+ m_zooml = 100;
+
+
+ OPJDecoThread *dthread = CreateDecoThread();
+
+ if (dthread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start deco thread!"));
+ else
+ wxLogMessage(wxT("New deco thread started."));
+
+ // 100% zoom
+ //m_zooml = 100;
+
+}
+
+OPJDecoThread *OPJCanvas::CreateDecoThread(void)
+{
+ OPJDecoThread *dthread = new OPJDecoThread(this);
+
+ if (dthread->Create() != wxTHREAD_NO_ERROR)
+ wxLogError(wxT("Can't create deco thread!"));
+
+ wxCriticalSectionLocker enter(wxGetApp().m_deco_critsect);
+ wxGetApp().m_deco_threads.Add(dthread);
+
+ return dthread;
+}
+
+OPJEncoThread *OPJCanvas::CreateEncoThread(void)
+{
+ OPJEncoThread *ethread = new OPJEncoThread(this);
+
+ if (ethread->Create() != wxTHREAD_NO_ERROR)
+ wxLogError(wxT("Can't create enco thread!"));
+
+ wxCriticalSectionLocker enter(wxGetApp().m_enco_critsect);
+ wxGetApp().m_enco_threads.Add(ethread);
+
+ return ethread;
+}
+
+#define activeoverlay 0
+// Define the repainting behaviour
+void OPJCanvas::OnDraw(wxDC& dc)
+{
+ if (m_image.Ok()) {
+ dc.DrawBitmap(m_image, OPJ_CANVAS_BORDER, OPJ_CANVAS_BORDER);
+
+ if (activeoverlay) {
+ dc.SetPen(*wxRED_PEN);
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ //int tw, th;
+ dc.DrawRectangle(OPJ_CANVAS_BORDER, OPJ_CANVAS_BORDER,
+ (unsigned long int) (0.5 + (double) m_zooml * (double) m_childframe->m_twidth / 100.0),
+ (unsigned long int) (0.5 + (double) m_zooml * (double) m_childframe->m_theight / 100.0));
+ }
+
+ } else {
+ dc.SetFont(*wxSWISS_FONT);
+ dc.SetPen(*wxBLACK_PEN);
+#ifdef __WXGTK__
+ dc.DrawText(_T("Decoding image, please wait... (press \"Zoom to Fit\" to show the image)"), 40, 50);
+#else
+ dc.DrawText(_T("Decoding image, please wait..."), 40, 50);
+#endif
+ }
+}
+
+// This implements a tiny doodling program! Drag the mouse using
+// the left button.
+void OPJCanvas::OnEvent(wxMouseEvent& event)
+{
+#if USE_PENCIL_ON_CANVAS
+ wxClientDC dc(this);
+ PrepareDC(dc);
+
+ wxPoint pt(event.GetLogicalPosition(dc));
+
+ if ((xpos > -1) && (ypos > -1) && event.Dragging()) {
+ dc.SetPen(*wxRED_PEN);
+ dc.DrawLine(xpos, ypos, pt.x, pt.y);
+ }
+ xpos = pt.x;
+ ypos = pt.y;
+#endif
+}
+
+void OPJFrame::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+ wxLayoutAlgorithm layout;
+ layout.LayoutMDIFrame(this);
+}
+
+void OPJCanvas::OnThreadSignal(wxCommandEvent& event)
+{
+#if 1
+ wxLogMessage(wxT("Canvas got signal from deco thread: %d"), event.GetInt());
+ wxLogMessage(event.GetString());
+#else
+ int n = event.GetInt();
+ if ( n == -1 )
+ {
+ m_dlgProgress->Destroy();
+ m_dlgProgress = (wxProgressDialog *)NULL;
+
+ // the dialog is aborted because the event came from another thread, so
+ // we may need to wake up the main event loop for the dialog to be
+ // really closed
+ wxWakeUpIdle();
+ }
+ else
+ {
+ if ( !m_dlgProgress->Update(n) )
+ {
+ wxCriticalSectionLocker lock(m_critsectWork);
+
+ m_cancelled = true;
+ }
+ }
+#endif
+}
+
+
+// Note that OPJFRAME_FILEOPEN and OPJFRAME_HELPABOUT commands get passed
+// to the parent window for processing, so no need to
+// duplicate event handlers here.
+
+BEGIN_EVENT_TABLE(OPJChildFrame, wxMDIChildFrame)
+ /*EVT_MENU(SASHTEST_CHILD_QUIT, OPJChildFrame::OnQuit)*/
+ EVT_CLOSE(OPJChildFrame::OnClose)
+ EVT_SET_FOCUS(OPJChildFrame::OnGotFocus)
+ EVT_KILL_FOCUS(OPJChildFrame::OnLostFocus)
+END_EVENT_TABLE()
+
+OPJChildFrame::OPJChildFrame(OPJFrame *parent, wxFileName fname, int winnumber, const wxString& title, const wxPoint& pos, const wxSize& size,
+const long style):
+ wxMDIChildFrame(parent, wxID_ANY, title, pos, size, style)
+{
+ m_frame = (OPJFrame *) parent;
+ m_canvas = NULL;
+ //my_children.Append(this);
+ m_fname = fname;
+ m_winnumber = winnumber;
+ SetTitle(wxString::Format(_T("%d: "), m_winnumber) + m_fname.GetFullName());
+
+ // Give it an icon (this is ignored in MDI mode: uses resources)
+#ifdef __WXMSW__
+ SetIcon(wxIcon(wxT("OPJChild16")));
+#endif
+
+ // Give it a status line
+ /*CreateStatusBar();*/
+
+ int width, height;
+ GetClientSize(&width, &height);
+
+ OPJCanvas *canvas = new OPJCanvas(fname, this, wxPoint(0, 0), wxSize(width, height));
+#if USE_PENCIL_ON_CANVAS
+ canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
+#endif
+ m_canvas = canvas;
+
+ // Give it scrollbars
+ canvas->SetScrollbars(20, 20, 5, 5);
+
+ Show(true);
+ Maximize(true);
+
+ /*wxLogError(wxString::Format(wxT("Created tree %d (0x%x)"), m_winnumber, m_frame->m_treehash[m_winnumber]));*/
+
+}
+
+OPJChildFrame::~OPJChildFrame(void)
+{
+ //my_children.DeleteObject(this);
+}
+
+
+void OPJChildFrame::OnClose(wxCloseEvent& event)
+{
+ for (unsigned int p = 0; p < m_frame->m_bookCtrl->GetPageCount(); p++) {
+ if (m_frame->m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), m_winnumber)) {
+ m_frame->m_bookCtrl->DeletePage(p);
+ break;
+ }
+ }
+ Destroy();
+
+ wxLogMessage(wxT("Closed: %d"), m_winnumber);
+}
+
+void OPJChildFrame::OnActivate(wxActivateEvent& event)
+{
+ /*if (event.GetActive() && m_canvas)
+ m_canvas->SetFocus();*/
+}
+
+void OPJChildFrame::OnGotFocus(wxFocusEvent& event)
+{
+ // we need to check if the notebook is being destroyed or not
+ if (!m_frame->m_bookCtrl)
+ return;
+
+ for (unsigned int p = 0; p < m_frame->m_bookCtrl->GetPageCount(); p++) {
+
+ if (m_frame->m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), m_winnumber)) {
+ m_frame->m_bookCtrl->ChangeSelection(p);
+ break;
+ }
+
+ }
+
+ //wxLogMessage(wxT("Got focus: %d (%x)"), m_winnumber, event.GetWindow());
+}
+
+void OPJChildFrame::OnLostFocus(wxFocusEvent& event)
+{
+ //wxLogMessage(wxT("Lost focus: %d (%x)"), m_winnumber, event.GetWindow());
+}
+
+
+////////////////////////////////
+// drag and drop
+////////////////////////////////
+
+bool OPJDnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
+{
+ /*size_t nFiles = filenames.GetCount();
+ wxString str;
+ str.Printf( _T("%d files dropped\n"), (int)nFiles);
+ for ( size_t n = 0; n < nFiles; n++ ) {
+ str << filenames[n] << wxT("\n");
+ }
+ wxLogMessage(str);*/
+ m_pOwner->OpenFiles(filenames, filenames);
+
+ return true;
+}
+
diff --git a/src/bin/wx/OPJViewer/source/OPJViewer.h b/src/bin/wx/OPJViewer/source/OPJViewer.h
new file mode 100644
index 00000000..ecc48b62
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJViewer.h
@@ -0,0 +1,812 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: sashtest.h
+// Purpose: Layout window/sash sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id: sashtest.h,v 1.5 2005/06/02 12:04:24 JS Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: treectrl.h
+// Purpose: wxTreeCtrl sample
+// Author: Julian Smart
+// Modified by:
+// Created: 04/01/98
+// RCS-ID: $Id: treetest.h,v 1.50 2006/11/04 11:26:51 VZ Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+// Name: dialogs.h
+// Purpose: Common dialogs demo
+// Author: Julian Smart
+// Modified by: ABX (2004) - adjustementd for conditional building
+// Created: 04/01/98
+// RCS-ID: $Id: dialogs.h,v 1.50 2006/10/08 14:12:59 VZ Exp $
+// Copyright: (c) Julian Smart
+// Licence: wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __OPJ_VIEWER_H__
+#define __OPJ_VIEWER_H__
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#include "wx/mdi.h"
+#endif
+
+#include "wx/toolbar.h"
+#include "wx/laywin.h"
+#include "wx/treectrl.h"
+
+#include "icon1.xpm"
+#include "icon2.xpm"
+#include "icon3.xpm"
+#include "icon4.xpm"
+#include "icon5.xpm"
+
+#include "wx/filedlg.h"
+#include "wx/toolbar.h"
+#include <wx/filename.h>
+#include <wx/busyinfo.h>
+#include <wx/cmdline.h>
+#include <wx/file.h>
+#include "wx/notebook.h"
+#include <wx/numdlg.h>
+
+#include "wx/propdlg.h"
+#include "wx/spinctrl.h"
+
+#include <wx/dnd.h>
+#include "wx/wxhtml.h"
+#include "wx/statline.h"
+#include <wx/fs_mem.h>
+
+#include <wx/imaglist.h>
+
+#include "wx/toolbar.h"
+#include "wx/artprov.h"
+
+#include "libopenjpeg/openjpeg.h"
+
+//#include "imagj2k.h"
+//#include "imagjp2.h"
+//#include "imagmj2.h"
+#include "imagjpeg2000.h"
+#ifdef USE_MXF
+#include "imagmxf.h"
+#endif // USE_MXF
+
+#ifdef __WXMSW__
+typedef unsigned __int64 int8byte;
+#endif // __WXMSW__
+
+#ifdef __WXGTK__
+typedef unsigned long long int8byte;
+#endif // __WXGTK__
+
+#define USE_GENERIC_TREECTRL 0
+#define USE_PENCIL_ON_CANVAS 0
+
+#if USE_GENERIC_TREECTRL
+#include "wx/generic/treectlg.h"
+#ifndef wxTreeCtrl
+#define wxTreeCtrl wxGenericTreeCtrl
+#define sm_classwxTreeCtrl sm_classwxGenericTreeCtrl
+#endif
+#endif
+
+#define OPJ_APPLICATION wxT("OPJViewer")
+#define OPJ_APPLICATION_NAME wxT("OpenJPEG Viewer")
+#define OPJ_APPLICATION_VERSION wxT("0.4 beta")
+#define OPJ_APPLICATION_TITLEBAR OPJ_APPLICATION_NAME wxT(" ") OPJ_APPLICATION_VERSION
+#define OPJ_APPLICATION_COPYRIGHT wxT("(C) 2007-2008, Giuseppe Baruffa")
+#define OPJ_APPLICATION_VENDOR wxT("OpenJPEG")
+
+#ifdef __WXMSW__
+#define OPJ_APPLICATION_PLATFORM wxT("Windows")
+#endif
+
+#ifdef __WXGTK__
+#define OPJ_APPLICATION_PLATFORM wxT("Linux")
+#endif
+
+#define OPJ_FRAME_WIDTH 800
+#define OPJ_FRAME_HEIGHT 600
+
+#define OPJ_BROWSER_WIDTH 300
+#define OPJ_PEEKER_HEIGHT 130
+
+#define OPJ_CANVAS_BORDER 10
+#define OPJ_CANVAS_COLOUR *wxWHITE
+
+
+
+#ifdef USE_JPWL
+
+//#define MYJPWL_MAX_NO_TILESPECS JPWL_MAX_NO_TILESPECS
+#define MYJPWL_MAX_NO_TILESPECS 4
+
+#endif // USE_JPWL
+
+
+class OPJDecoThread;
+class OPJEncoThread;
+class OPJParseThread;
+WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
+class OPJChildFrame;
+
+//////////////////////////////////
+// this is our main application //
+//////////////////////////////////
+class OPJViewerApp: public wxApp
+{
+ // public methods and variables
+ public:
+
+ // class constructor
+ OPJViewerApp() { m_showImages = true; m_showButtons = false; }
+
+ // other methods
+ bool OnInit(void);
+ int OnExit(void);
+ void SetShowImages(bool show) { m_showImages = show; }
+ bool ShowImages() const { return m_showImages; }
+ void ShowCmdLine(const wxCmdLineParser& parser);
+
+ // all the threads currently alive - as soon as the thread terminates, it's
+ // removed from the array
+ wxArrayThread m_deco_threads, m_parse_threads, m_enco_threads;
+
+ // crit section protects access to all of the arrays below
+ wxCriticalSection m_deco_critsect, m_parse_critsect, m_enco_critsect;
+
+ // semaphore used to wait for the threads to exit, see OPJFrame::OnQuit()
+ wxSemaphore m_deco_semAllDone, m_parse_semAllDone, m_enco_semAllDone;
+
+ // the last exiting thread should post to m_semAllDone if this is true
+ // (protected by the same m_critsect)
+ bool m_deco_waitingUntilAllDone, m_parse_waitingUntilAllDone, m_enco_waitingUntilAllDone;
+
+ // the list of all filenames written in the command line
+ wxArrayString m_filelist;
+
+ // displaying engine parameters
+ int m_resizemethod;
+
+ // decoding engine parameters
+ bool m_enabledeco, m_enableparse;
+ int m_reducefactor, m_qualitylayers, m_components, m_framenum;
+#ifdef USE_JPWL
+ bool m_enablejpwl, m_enablejpwle;
+ int m_expcomps, m_maxtiles;
+#endif // USE_JPWL
+ int m_framewidth, m_frameheight;
+
+ // encoding engine parameters
+ wxString m_subsampling, m_origin, m_rates, m_comment, m_index, m_quality;
+ wxString m_cbsize, m_prsize, m_tsize, m_torigin, m_poc;
+ bool m_enablecomm, m_enableidx, m_multicomp, m_irreversible, m_enablesop, m_enableeph;
+ bool m_enablebypass, m_enablereset, m_enablerestart, m_enablevsc, m_enableerterm;
+ bool m_enablesegmark, m_enablepoc;
+ bool m_enablequality;
+ int m_resolutions, m_progression;
+#ifdef USE_JPWL
+ int m_hprotsel[MYJPWL_MAX_NO_TILESPECS], m_pprotsel[MYJPWL_MAX_NO_TILESPECS];
+ int m_htileval[MYJPWL_MAX_NO_TILESPECS], m_ptileval[MYJPWL_MAX_NO_TILESPECS],
+ m_ppackval[MYJPWL_MAX_NO_TILESPECS];
+ int m_sensisel[MYJPWL_MAX_NO_TILESPECS], m_stileval[MYJPWL_MAX_NO_TILESPECS];
+#endif // USE_JPWL
+
+ // some layout settings
+ bool m_showtoolbar, m_showbrowser, m_showpeeker;
+ int m_browserwidth, m_peekerheight;
+
+ // application configuration
+ wxConfig *OPJconfig;
+
+ // private methods and variables
+ private:
+ bool m_showImages, m_showButtons;
+
+};
+
+DECLARE_APP(OPJViewerApp)
+
+///////////////////////////////////////////
+// this canvas is used to draw the image //
+///////////////////////////////////////////
+class OPJCanvas: public wxScrolledWindow
+{
+ // public methods and variables
+ public:
+
+ // class constructor
+ OPJCanvas(wxFileName fname, wxWindow *parent, const wxPoint& pos, const wxSize& size);
+
+ virtual void OnDraw(wxDC& dc);
+ void OnEvent(wxMouseEvent& event);
+ void WriteText(const wxString& text) {
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif //__WXGTK__
+ wxLogMessage(text);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif //__WXGTK__
+ }
+
+ void OnThreadSignal(wxCommandEvent& event);
+
+ OPJDecoThread *CreateDecoThread(void);
+ OPJEncoThread *CreateEncoThread(void);
+
+
+ OPJChildFrame *m_childframe;
+
+ wxBitmap m_image, m_image100;
+ wxFileName m_fname, m_savename;
+ long m_zooml;
+
+ DECLARE_EVENT_TABLE()
+};
+
+///////////////////////////////////////////////////
+// the data associated to each tree leaf or node //
+///////////////////////////////////////////////////
+class OPJMarkerData : public wxTreeItemData
+{
+ // public methods and variables
+ public:
+
+ // class constructor
+ OPJMarkerData(const wxString& desc, const wxString& fname = wxT(""), wxFileOffset start = 0, wxFileOffset length = 0) : m_desc(desc), m_filestring(fname) { m_start = start; m_length = length; }
+
+ void ShowInfo(wxTreeCtrl *tree);
+ const wxChar *GetDesc1() const { return m_desc.c_str(); }
+ const wxChar *GetDesc2() const { return m_filestring.c_str(); }
+ wxFileOffset m_start, m_length;
+ wxString m_desc;
+
+ // private methods and variables
+ private:
+ wxString m_filestring;
+};
+
+
+class OPJMarkerTree : public wxTreeCtrl
+{
+public:
+ enum
+ {
+ TreeCtrlIcon_File,
+ TreeCtrlIcon_FileSelected,
+ TreeCtrlIcon_Folder,
+ TreeCtrlIcon_FolderSelected,
+ TreeCtrlIcon_FolderOpened
+ };
+
+ OPJMarkerTree() { };
+ OPJMarkerTree(wxWindow *parent, OPJChildFrame *subframe, wxFileName fname, wxString name, const wxWindowID id,
+ const wxPoint& pos, const wxSize& size,
+ long style);
+ virtual ~OPJMarkerTree(){};
+ OPJParseThread *CreateParseThread(wxTreeItemId parentid = 0x00, OPJChildFrame *subframe = NULL);
+ void WriteText(const wxString& text) { wxMutexGuiEnter(); wxLogMessage(text); wxMutexGuiLeave(); }
+
+ wxFileName m_fname;
+ wxTextCtrl *m_peektextCtrl;
+ OPJChildFrame *m_childframe;
+
+ /*void OnBeginDrag(wxTreeEvent& event);
+ void OnBeginRDrag(wxTreeEvent& event);
+ void OnEndDrag(wxTreeEvent& event);*/
+ /*void OnBeginLabelEdit(wxTreeEvent& event);
+ void OnEndLabelEdit(wxTreeEvent& event);*/
+ /*void OnDeleteItem(wxTreeEvent& event);*/
+ /*void OnContextMenu(wxContextMenuEvent& event);*/
+ void OnItemMenu(wxTreeEvent& event);
+ /*void OnGetInfo(wxTreeEvent& event);
+ void OnSetInfo(wxTreeEvent& event);*/
+ /*void OnItemExpanded(wxTreeEvent& event);*/
+ void OnItemExpanding(wxTreeEvent& event);
+ /*void OnItemCollapsed(wxTreeEvent& event);
+ void OnItemCollapsing(wxTreeEvent& event);*/
+ void OnSelChanged(wxTreeEvent& event);
+ /*void OnSelChanging(wxTreeEvent& event);*/
+ /*void OnTreeKeyDown(wxTreeEvent& event);*/
+ /*void OnItemActivated(wxTreeEvent& event);*/
+ /*void OnItemRClick(wxTreeEvent& event);*/
+ /*void OnRMouseDown(wxMouseEvent& event);
+ void OnRMouseUp(wxMouseEvent& event);
+ void OnRMouseDClick(wxMouseEvent& event);*/
+ /*void GetItemsRecursively(const wxTreeItemId& idParent,
+ wxTreeItemIdValue cookie = 0);*/
+
+ void CreateImageList(int size = 16);
+ void CreateButtonsImageList(int size = 11);
+
+ /*void AddTestItemsToTree(size_t numChildren, size_t depth);*/
+ /*void DoSortChildren(const wxTreeItemId& item, bool reverse = false)
+ { m_reverseSort = reverse; wxTreeCtrl::SortChildren(item); }*/
+ /*void DoEnsureVisible() { if (m_lastItem.IsOk()) EnsureVisible(m_lastItem); }*/
+ /*void DoToggleIcon(const wxTreeItemId& item);*/
+ /*void ShowMenu(wxTreeItemId id, const wxPoint& pt);*/
+
+ int ImageSize(void) const { return m_imageSize; }
+
+ void SetLastItem(wxTreeItemId id) { m_lastItem = id; }
+
+protected:
+ /*virtual int OnCompareItems(const wxTreeItemId& i1, const wxTreeItemId& i2);*/
+
+ // is this the test item which we use in several event handlers?
+ /*bool IsTestItem(const wxTreeItemId& item)
+ {
+ // the test item is the first child folder
+ return GetItemParent(item) == GetRootItem() && !GetPrevSibling(item);
+ }*/
+
+private:
+ /*void AddItemsRecursively(const wxTreeItemId& idParent,
+ size_t nChildren,
+ size_t depth,
+ size_t folder);*/
+
+ void LogEvent(const wxChar *name, const wxTreeEvent& event);
+
+ int m_imageSize; // current size of images
+ bool m_reverseSort; // flag for OnCompareItems
+ wxTreeItemId m_lastItem, // for OnEnsureVisible()
+ m_draggedItem; // item being dragged right now
+
+ // NB: due to an ugly wxMSW hack you _must_ use DECLARE_DYNAMIC_CLASS()
+ // if you want your overloaded OnCompareItems() to be called.
+ // OTOH, if you don't want it you may omit the next line - this will
+ // make default (alphabetical) sorting much faster under wxMSW.
+ DECLARE_DYNAMIC_CLASS(OPJMarkerTree)
+ DECLARE_EVENT_TABLE()
+};
+
+// this hash map stores all the trees of currently opened images, with an integer key
+WX_DECLARE_HASH_MAP(int, OPJMarkerTree*, wxIntegerHash, wxIntegerEqual, OPJMarkerTreeHash);
+
+// this hash map stores all the children of currently opened images, with an integer key
+WX_DECLARE_HASH_MAP(int, OPJChildFrame*, wxIntegerHash, wxIntegerEqual, OPJChildFrameHash);
+
+// Define a new frame
+class OPJFrame: public wxMDIParentFrame
+{
+ public:
+
+ OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
+
+ ~OPJFrame(void);
+ void OnSize(wxSizeEvent& WXUNUSED(event));
+ void OnAbout(wxCommandEvent& WXUNUSED(event));
+ void OnFileOpen(wxCommandEvent& WXUNUSED(event));
+ void OnFileSaveAs(wxCommandEvent& WXUNUSED(event));
+ void OnMemoryOpen(wxCommandEvent& WXUNUSED(event));
+ void OnQuit(wxCommandEvent& WXUNUSED(event));
+ void OnClose(wxCommandEvent& WXUNUSED(event));
+ void OnZoom(wxCommandEvent& WXUNUSED(event));
+ void OnFit(wxCommandEvent& event);
+ void OnToggleBrowser(wxCommandEvent& WXUNUSED(event));
+ void OnTogglePeeker(wxCommandEvent& WXUNUSED(event));
+ void OnToggleToolbar(wxCommandEvent& WXUNUSED(event));
+ void OnReload(wxCommandEvent& event);
+ void OnPrevFrame(wxCommandEvent& event);
+ void OnHomeFrame(wxCommandEvent& event);
+ void OnNextFrame(wxCommandEvent& event);
+ void OnLessLayers(wxCommandEvent& event);
+ void OnAllLayers(wxCommandEvent& event);
+ void OnMoreLayers(wxCommandEvent& event);
+ void OnLessRes(wxCommandEvent& event);
+ void OnFullRes(wxCommandEvent& event);
+ void OnMoreRes(wxCommandEvent& event);
+ void OnPrevComp(wxCommandEvent& event);
+ void OnAllComps(wxCommandEvent& event);
+ void OnNextComp(wxCommandEvent& event);
+ void OnSetsEnco(wxCommandEvent& event);
+ void OnSetsDeco(wxCommandEvent& event);
+ void OnSashDrag(wxSashEvent& event);
+ void OpenFiles(wxArrayString paths, wxArrayString filenames);
+ void SaveFile(wxArrayString paths, wxArrayString filenames);
+ void OnNotebook(wxNotebookEvent& event);
+ void Rescale(int scale, OPJChildFrame *child);
+ void OnThreadLogmsg(wxCommandEvent& event);
+
+ OPJMarkerTreeHash m_treehash;
+ OPJChildFrameHash m_childhash;
+ wxSashLayoutWindow* markerTreeWindow;
+ wxSashLayoutWindow* loggingWindow;
+ wxToolBar* tool_bar;
+ void Resize(int number);
+ wxNotebook *m_bookCtrl;
+ wxNotebook *m_bookCtrlbottom;
+ wxTextCtrl *m_textCtrlbrowse;
+
+ private:
+ void TogStyle(int id, long flag);
+
+ void DoSort(bool reverse = false);
+
+ wxPanel *m_panel;
+ wxTextCtrl *m_textCtrl;
+
+ void DoSetBold(bool bold = true);
+
+protected:
+ wxSashLayoutWindow* m_topWindow;
+ wxSashLayoutWindow* m_leftWindow2;
+
+DECLARE_EVENT_TABLE()
+};
+
+class OPJChildFrame: public wxMDIChildFrame
+{
+ public:
+ OPJCanvas *m_canvas;
+ OPJChildFrame(OPJFrame *parent, wxFileName fname, int winnumber, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
+ ~OPJChildFrame(void);
+ void OnActivate(wxActivateEvent& event);
+ /*void OnQuit(wxCommandEvent& WXUNUSED(event));*/
+ void OnClose(wxCloseEvent& event);
+ void OnGotFocus(wxFocusEvent& event);
+ void OnLostFocus(wxFocusEvent& event);
+ OPJFrame *m_frame;
+ wxFileName m_fname;
+ int m_winnumber;
+
+ unsigned long m_twidth, m_theight, m_tx, m_ty;
+
+ DECLARE_EVENT_TABLE()
+};
+
+// frame and main menu ids
+enum {
+ OPJFRAME_FILEEXIT = wxID_EXIT,
+ OPJFRAME_HELPABOUT = wxID_ABOUT,
+ OPJFRAME_FILEOPEN,
+ OPJFRAME_MEMORYOPEN,
+ OPJFRAME_FILESAVEAS,
+ OPJFRAME_FILETOGGLEB,
+ OPJFRAME_FILETOGGLEP,
+ OPJFRAME_FILETOGGLET,
+ OPJFRAME_VIEWZOOM,
+ OPJFRAME_VIEWFIT,
+ OPJFRAME_VIEWRELOAD,
+ OPJFRAME_VIEWPREVFRAME,
+ OPJFRAME_VIEWHOMEFRAME,
+ OPJFRAME_VIEWNEXTFRAME,
+ OPJFRAME_VIEWLESSLAYERS,
+ OPJFRAME_VIEWALLLAYERS,
+ OPJFRAME_VIEWMORELAYERS,
+ OPJFRAME_VIEWLESSRES,
+ OPJFRAME_VIEWFULLRES,
+ OPJFRAME_VIEWMORERES,
+ OPJFRAME_VIEWPREVCOMP,
+ OPJFRAME_VIEWALLCOMPS,
+ OPJFRAME_VIEWNEXTCOMP,
+ OPJFRAME_FILECLOSE,
+ OPJFRAME_SETSENCO,
+ OPJFRAME_SETSDECO,
+
+ OPJFRAME_BROWSEWIN = 10000,
+ OPJFRAME_LOGWIN,
+ OPJFRAME_TOOLBAR,
+
+ OPJFRAME_THREADLOGMSG,
+ OPJCANVAS_THREADSIGNAL
+};
+
+
+// menu and control ids
+enum
+{
+ TreeTest_Quit = wxID_EXIT,
+ TreeTest_About = wxID_ABOUT,
+ TreeTest_TogButtons = wxID_HIGHEST,
+ TreeTest_TogTwist,
+ TreeTest_TogLines,
+ TreeTest_TogEdit,
+ TreeTest_TogHideRoot,
+ TreeTest_TogRootLines,
+ TreeTest_TogBorder,
+ TreeTest_TogFullHighlight,
+ TreeTest_SetFgColour,
+ TreeTest_SetBgColour,
+ TreeTest_ResetStyle,
+ TreeTest_Highlight,
+ TreeTest_Dump,
+ TreeTest_DumpSelected,
+ TreeTest_Count,
+ TreeTest_CountRec,
+ TreeTest_Sort,
+ TreeTest_SortRev,
+ TreeTest_SetBold,
+ TreeTest_ClearBold,
+ TreeTest_Rename,
+ TreeTest_Delete,
+ TreeTest_DeleteChildren,
+ TreeTest_DeleteAll,
+ TreeTest_Recreate,
+ TreeTest_ToggleImages,
+ TreeTest_ToggleButtons,
+ TreeTest_SetImageSize,
+ TreeTest_ToggleSel,
+ TreeTest_CollapseAndReset,
+ TreeTest_EnsureVisible,
+ TreeTest_AddItem,
+ TreeTest_InsertItem,
+ TreeTest_IncIndent,
+ TreeTest_DecIndent,
+ TreeTest_IncSpacing,
+ TreeTest_DecSpacing,
+ TreeTest_ToggleIcon,
+ TreeTest_Select,
+ TreeTest_Unselect,
+ TreeTest_SelectRoot,
+ TreeTest_Ctrl = 1000,
+ BOTTOM_NOTEBOOK_ID,
+ LEFT_NOTEBOOK_ID
+};
+
+class OPJEncoThread : public wxThread
+{
+public:
+ OPJEncoThread(OPJCanvas *canvas);
+
+ // thread execution starts here
+ virtual void *Entry();
+
+ // called when the thread exits - whether it terminates normally or is
+ // stopped with Delete() (but not when it is Kill()ed!)
+ virtual void OnExit();
+
+ // write something to the text control
+ void WriteText(const wxString& text);
+
+public:
+ unsigned m_count;
+ OPJCanvas *m_canvas;
+};
+
+class OPJDecoThread : public wxThread
+{
+public:
+ OPJDecoThread(OPJCanvas *canvas);
+
+ // thread execution starts here
+ virtual void *Entry();
+
+ // called when the thread exits - whether it terminates normally or is
+ // stopped with Delete() (but not when it is Kill()ed!)
+ virtual void OnExit();
+
+ // write something to the text control
+ void WriteText(const wxString& text);
+
+public:
+ unsigned m_count;
+ OPJCanvas *m_canvas;
+};
+
+class OPJParseThread : public wxThread
+{
+public:
+ OPJParseThread(OPJMarkerTree *tree, wxTreeItemId parentid = 0x00);
+
+ // thread execution starts here
+ virtual void *Entry();
+
+ // called when the thread exits - whether it terminates normally or is
+ // stopped with Delete() (but not when it is Kill()ed!)
+ virtual void OnExit();
+
+ // write something to the text control
+ void WriteText(const wxString& text);
+ void LoadFile(wxFileName fname);
+ void ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid);
+ void ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid);
+
+ unsigned m_count;
+ OPJMarkerTree *m_tree;
+ wxTreeItemId m_parentid;
+
+private:
+ int jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
+ wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint);
+ int box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
+ wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint);
+
+};
+
+
+// Drag and drop files target
+class OPJDnDFile: public wxFileDropTarget
+{
+public:
+ OPJDnDFile(OPJFrame *pOwner) { m_pOwner = pOwner; }
+ virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames);
+
+private:
+ OPJFrame *m_pOwner;
+};
+
+
+
+// Property sheet dialog: encoder
+class OPJEncoderDialog: public wxPropertySheetDialog
+{
+DECLARE_CLASS(OPJEncoderDialog)
+public:
+ OPJEncoderDialog(wxWindow* parent, int dialogType);
+ ~OPJEncoderDialog();
+
+ wxBookCtrlBase* m_settingsNotebook;
+
+ wxPanel* CreateMainSettingsPage(wxWindow* parent);
+ wxPanel* CreatePart1_1SettingsPage(wxWindow* parent);
+ wxPanel* CreatePart1_2SettingsPage(wxWindow* parent);
+/* wxPanel* CreatePart3SettingsPage(wxWindow* parent);*/
+ void OnEnableComm(wxCommandEvent& event);
+ void OnEnableIdx(wxCommandEvent& event);
+ void OnEnablePoc(wxCommandEvent& event);
+ void OnRadioQualityRate(wxCommandEvent& event);
+#ifdef USE_JPWL
+ void OnEnableJPWL(wxCommandEvent& event);
+ wxPanel* CreatePart11SettingsPage(wxWindow* parent);
+ /*wxCheckBox *m_enablejpwlCheck;*/
+ wxChoice *m_hprotChoice[MYJPWL_MAX_NO_TILESPECS];
+ wxSpinCtrl *m_htileCtrl[MYJPWL_MAX_NO_TILESPECS];
+ wxChoice *m_pprotChoice[MYJPWL_MAX_NO_TILESPECS];
+ wxSpinCtrl *m_ptileCtrl[MYJPWL_MAX_NO_TILESPECS];
+ wxSpinCtrl *m_ppackCtrl[MYJPWL_MAX_NO_TILESPECS];
+ wxChoice *m_sensiChoice[MYJPWL_MAX_NO_TILESPECS];
+ wxSpinCtrl *m_stileCtrl[MYJPWL_MAX_NO_TILESPECS];
+ void OnHprotSelect(wxCommandEvent& event);
+ void OnPprotSelect(wxCommandEvent& event);
+ void OnSensiSelect(wxCommandEvent& event);
+#endif // USE_JPWL
+
+ wxTextCtrl *m_subsamplingCtrl, *m_originCtrl, *m_rateCtrl, *m_commentCtrl;
+ wxRadioButton *m_rateRadio, *m_qualityRadio;
+ wxTextCtrl *m_indexCtrl, *m_qualityCtrl, *m_cbsizeCtrl, *m_prsizeCtrl, *m_pocCtrl;
+ wxTextCtrl *m_tsizeCtrl, *m_toriginCtrl;
+ wxRadioBox *progressionBox;
+ wxCheckBox *m_enablecommCheck, *m_enableidxCheck, *m_mctCheck, *m_irrevCheck;
+ wxCheckBox *m_sopCheck, *m_ephCheck, *m_enablebypassCheck, *m_enableresetCheck,
+ *m_enablerestartCheck, *m_enablevscCheck, *m_enableertermCheck, *m_enablesegmarkCheck;
+ wxCheckBox *m_enablepocCheck, *m_enablejpwlCheck;
+ wxSpinCtrl *m_resolutionsCtrl;
+
+protected:
+
+ enum {
+ OPJENCO_ENABLEJPWL = 100,
+ OPJENCO_RATEFACTOR,
+ OPJENCO_RATERADIO,
+ OPJENCO_QUALITYFACTOR,
+ OPJENCO_QUALITYRADIO,
+ OPJENCO_RESNUMBER,
+ OPJENCO_CODEBLOCKSIZE,
+ OPJENCO_PRECINCTSIZE,
+ OPJENCO_TILESIZE,
+ OPJENCO_PROGRESSION,
+ OPJENCO_SUBSAMPLING,
+ OPJENCO_ENABLESOP,
+ OPJENCO_ENABLEEPH,
+ OPJENCO_ENABLEBYPASS,
+ OPJENCO_ENABLERESET,
+ OPJENCO_ENABLERESTART,
+ OPJENCO_ENABLEVSC,
+ OPJENCO_ENABLEERTERM,
+ OPJENCO_ENABLESEGMARK,
+ OPJENCO_ENABLEPOC,
+ OPJENCO_ROICOMP,
+ OPJENCO_ROISHIFT,
+ OPJENCO_IMORIG,
+ OPJENCO_TILORIG,
+ OPJENCO_ENABLEMCT,
+ OPJENCO_ENABLEIRREV,
+ OPJENCO_ENABLEINDEX,
+ OPJENCO_INDEXNAME,
+ OPJENCO_POCSPEC,
+ OPJENCO_ENABLECOMM,
+ OPJENCO_COMMENTTEXT,
+ OPJENCO_HPROT,
+ OPJENCO_HTILE,
+ OPJENCO_PPROT,
+ OPJENCO_PTILE,
+ OPJENCO_PPACK,
+ OPJENCO_SENSI,
+ OPJENCO_STILE
+ };
+
+DECLARE_EVENT_TABLE()
+};
+
+// Property sheet dialog: decoder
+class OPJDecoderDialog: public wxPropertySheetDialog
+{
+DECLARE_CLASS(OPJDecoderDialog)
+public:
+ OPJDecoderDialog(wxWindow* parent, int dialogType);
+ ~OPJDecoderDialog();
+
+ wxBookCtrlBase* m_settingsNotebook;
+ wxCheckBox *m_enabledecoCheck, *m_enableparseCheck;
+ wxSpinCtrl *m_reduceCtrl, *m_layerCtrl, *m_numcompsCtrl;
+ wxRadioBox* m_resizeBox;
+
+ void OnEnableDeco(wxCommandEvent& event);
+
+ wxPanel* CreateMainSettingsPage(wxWindow* parent);
+ wxPanel* CreatePart1SettingsPage(wxWindow* parent);
+ wxPanel* CreatePart3SettingsPage(wxWindow* parent);
+#ifdef USE_JPWL
+ void OnEnableJPWL(wxCommandEvent& event);
+ wxPanel* CreatePart11SettingsPage(wxWindow* parent);
+ wxSpinCtrl *m_expcompsCtrl, *m_maxtilesCtrl;
+ wxCheckBox *m_enablejpwlCheck;
+#endif // USE_JPWL
+ wxSpinCtrl *m_framenumCtrl;
+
+
+protected:
+
+ enum {
+ OPJDECO_RESMETHOD = 100,
+ OPJDECO_REDUCEFACTOR,
+ OPJDECO_QUALITYLAYERS,
+ OPJDECO_NUMCOMPS,
+ OPJDECO_ENABLEDECO,
+ OPJDECO_ENABLEPARSE,
+ OPJDECO_ENABLEJPWL,
+ OPJDECO_EXPCOMPS,
+ OPJDECO_MAXTILES,
+ OPJDECO_FRAMENUM
+ };
+
+DECLARE_EVENT_TABLE()
+};
+
+#endif //__OPJ_VIEWER_H__
+
+
+
diff --git a/src/bin/wx/OPJViewer/source/OPJViewer.ico b/src/bin/wx/OPJViewer/source/OPJViewer.ico
new file mode 100644
index 00000000..931d5e02
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJViewer.ico
Binary files differ
diff --git a/src/bin/wx/OPJViewer/source/OPJViewer.rc b/src/bin/wx/OPJViewer/source/OPJViewer.rc
new file mode 100644
index 00000000..82af985b
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJViewer.rc
@@ -0,0 +1,3 @@
+OPJChild16 ICON OPJChild.ico
+OPJViewer16 ICON OPJViewer.ico
+#include "wx/msw/wx.rc" \ No newline at end of file
diff --git a/src/bin/wx/OPJViewer/source/OPJViewer16.xpm b/src/bin/wx/OPJViewer/source/OPJViewer16.xpm
new file mode 100644
index 00000000..7c65acb3
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/OPJViewer16.xpm
@@ -0,0 +1,26 @@
+/* XPM */
+static char *OPJViewer16[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 4 1",
+" c black",
+". c #800000",
+"X c red",
+"o c None",
+/* pixels */
+"oooooooooooooooo",
+"ooo.XXXXoooooooo",
+"ooXXoo .Xooooooo",
+"o..oooo .ooooooo",
+"oX.oooo ooooooo",
+"oX.oooo .ooooooo",
+"oXXoooo .ooooooo",
+"o.XXoo .oooooooo",
+"oo.XXXXooooooooo",
+"ooooooooo.Xo .oo",
+"ooooooooo X. ooo",
+"oooooooooo...ooo",
+"oooooooooo XXooo",
+"oooooooooo .Xooo",
+"oooooooooooooooo",
+"oooooooooooooooo"
+};
diff --git a/src/bin/wx/OPJViewer/source/about_htm.h b/src/bin/wx/OPJViewer/source/about_htm.h
new file mode 100644
index 00000000..79a859d8
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/about_htm.h
@@ -0,0 +1,54 @@
+wxString htmlaboutpage = wxT(
+"<html>"
+"<body bgcolor=#FFFFFF>"
+"<table cellspacing=7 cellpadding=1 border=0 width=100%>"
+"<tr>"
+"<td rowspan=3 valign=top align=center width=70>"
+"<img src=\"memory:opj_logo.xpm\"><br><br>"
+"</td>"
+"<td align=center>"
+"<font size=+0 color=#000000><b>"
+OPJ_APPLICATION " " OPJ_APPLICATION_VERSION
+"</b></font><br>"
+"<font size=-1 color=#000000><b>A JPEG 2000 image viewer</b></font><br>"
+"<font size=-2 color=#000000><b>" OPJ_APPLICATION_PLATFORM " version</b></font>"
+"</td>"
+"</tr>"
+"<tr height=3 valign=center>"
+"<td valign=center bgcolor=#cc3300></td>"
+"</tr>"
+"<tr>"
+"<td align=justify>"
+"<center><font size=+0 color=#000000><a href=\"http://www.openjpeg.org/\">OpenJPEG</a></font></center>"
+"<p><font size=-1 color=#000000>The OpenJPEG library is an open-source JPEG 2000 codec written in C language. "
+"In addition to the basic codec, various other features are under development.</font></p><br>"
+"<font size=-2 color=red>* Build: ")
+#include "build.h"
+wxT(", " __DATE__ ", " __TIME__ "</font><br>")
+wxT("<font size=-2 color=red>* " wxVERSION_STRING "</font><br>")
+wxT("<font size=-2 color=red>* OpenJPEG " OPENJPEG_VERSION " (")
+#ifdef USE_JPWL
+wxT("<font size=-2 color=green>JPWL</font> ")
+#endif // USE_JPWL
+#ifdef USE_JPSEC
+wxT("<font size=-2 color=green>JPSEC</font> ")
+#endif // USE_JPSEC
+wxT(")</font><br>")
+#ifdef USE_MXF
+wxT("<font size=-2 color=red>* MXFLib " MXFLIB_VERSION_MAJOR "." MXFLIB_VERSION_MINOR "." MXFLIB_VERSION_TWEAK " (" MXFLIB_VERSION_BUILD ")</font><br>")
+#endif // USE_MXF
+wxT("</td>"
+"</tr>"
+"<tr>"
+"<td colspan=2 bgcolor=#CC3300 height=3 valign=center></td>"
+"</tr>"
+"<tr>"
+"<td colspan=2>"
+"<font size=-2 color=#444444>OpenJPEG is &copy; 2002-2008 <a href=\"http://www.tele.ucl.ac.be/\">TELE</a> - <a href=\"http://www.uclouvain.be/\">Universite' Catholique de Louvain</a></font><br>"
+"<font size=-2 color=#444444>OPJViewer is &copy; 2007-2008 <a href=\"http://dsplab.diei.unipg.it/\">DSPLab</a> - <a href=\"http://www.unipg.it/\">Universita' degli studi di Perugia</a></font>"
+"</td>"
+"</tr>"
+"</table>"
+"</body>"
+"</html>"
+);
diff --git a/src/bin/wx/OPJViewer/source/build.h b/src/bin/wx/OPJViewer/source/build.h
new file mode 100644
index 00000000..f0f072c8
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/build.h
@@ -0,0 +1 @@
+wxT("491")
diff --git a/src/bin/wx/OPJViewer/source/icon1.xpm b/src/bin/wx/OPJViewer/source/icon1.xpm
new file mode 100644
index 00000000..69131fb5
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/icon1.xpm
@@ -0,0 +1,79 @@
+/* XPM */
+static const char *icon1_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"> c #97C4E7",
+"# c #4381AA",
+"d c #FFFFFF",
+"< c #71B2DE",
+"+ c #538BB1",
+"& c #D1E5F5",
+"q c #63B3DE",
+"6 c #F1F4F7",
+"* c #CAE1F3",
+"y c #7AC4E5",
+"= c #C3DDF1",
+"X c #74A1BD",
+"- c #BCD9EF",
+"5 c #619BC4",
+"3 c #E6EAF1",
+"2 c #4B8EBF",
+"o c #6B97B6",
+". c #4B82A8",
+" c None",
+"w c #54A6D8",
+"1 c #71A8D1",
+", c #85BBE2",
+"t c #EFF6FC",
+"7 c #DEEDF8",
+"@ c #4388B4",
+"a c #F7FBFD",
+"$ c #D7E0E9",
+"r c #FAFCFE",
+"4 c #DAEAF7",
+"e c #E9F3FA",
+"0 c #76BAE2",
+"% c #7FA6C0",
+"s c #FDFDFE",
+"O c #5896BE",
+"p c #B6D5EE",
+"8 c #87ABC3",
+": c #A5CCEA",
+"9 c #E5F0F9",
+"; c #AFD1EC",
+"i c #F4F9FD",
+"u c #8FB0C3",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" .XXXooOO++@#$ ",
+" %&*=-;:>>,<123 ",
+" %4&*=-;:>>,1>56 ",
+" %74&*=-;:>>1*>56 ",
+" 89700qqqqwq1e*>X ",
+" 8e974&*=-;:1re*>8 ",
+" 8te974&*=-;11111# ",
+" 8tty000qqqqqww>,+ ",
+" uitte974&*=-p:>>+ ",
+" uaitte974&*=-p:>O ",
+" uaayyyy000qqqqp:O ",
+" uraaitte974&*=-po ",
+" urraaitte974&*=-o ",
+" usryyyyyyy000q*=X ",
+" ussrraaitte974&*X ",
+" udssrraaitte974&X ",
+" uddyyyyyyyyyy074% ",
+" udddssrraaitte97% ",
+" uddddssrraaitte9% ",
+" udddddssrraaitte8 ",
+" uddddddssrraaitt8 ",
+" uuuuuuuuuuuuuu88u ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/src/bin/wx/OPJViewer/source/icon2.xpm b/src/bin/wx/OPJViewer/source/icon2.xpm
new file mode 100644
index 00000000..cb8f1032
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/icon2.xpm
@@ -0,0 +1,53 @@
+/* XPM */
+static const char *icon2_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 15 1",
+". c Black",
+"O c #97C4E7",
+"$ c #63B3DE",
+"@ c #CAE1F3",
+"; c #7AC4E5",
+"* c #74A1BD",
+"+ c #619BC4",
+"o c #4B8EBF",
+" c None",
+"% c #54A6D8",
+"= c #FAFCFE",
+"& c #E9F3FA",
+"# c #76BAE2",
+"X c #C00000",
+"- c #87ABC3",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ............. ",
+" .XXXXXXXXXX.o. ",
+" .XXXXXXXXXX.O+. ",
+" .XXXXXXXXXX.@O+. ",
+" .XX##$$$$%$.&@O* ",
+" .XXXXXXXXXX.=&@O- ",
+" .XXXXXXXXXX...... ",
+" .XX;###$$$$$%%XX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XX;;;;###$$$$XX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XX;;;;;;;###$XX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XX;;;;;;;;;;#XX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" .XXXXXXXXXXXXXXX. ",
+" ................. ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/src/bin/wx/OPJViewer/source/icon3.xpm b/src/bin/wx/OPJViewer/source/icon3.xpm
new file mode 100644
index 00000000..ddfa18b9
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/icon3.xpm
@@ -0,0 +1,79 @@
+/* XPM */
+static const char *icon3_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"6 c #EDF2FB",
+"- c #AAC1E8",
+": c #B9CDED",
+"X c #295193",
+", c #C6D6F0",
+"a c #4A7CCE",
+"u c #779DDB",
+"y c #7FA2DD",
+"$ c #3263B4",
+"5 c #EAF0FA",
+". c #2D59A3",
+"o c #6E96D8",
+"* c #356AC1",
+"r c #F7F9FD",
+"> c #BED0EE",
+"3 c #E1E9F7",
+"7 c #F0F5FC",
+"< c #CBD9F1",
+"2 c #DAE5F6",
+"# c #3161B1",
+" c None",
+"0 c #FDFEFF",
+"= c #9FB9E5",
+"e c #AEC5EA",
+"t c #89A9DF",
+"q c #98B5E4",
+"p c #5584D1",
+"d c #3A70CA",
+"@ c #305FAC",
+"i c #5D89D3",
+"1 c #D2DFF4",
+"% c #3366B9",
+"9 c #FAFCFE",
+"8 c #F5F8FD",
+"s c #4075CC",
+"O c #638ED5",
+"w c #90AFE2",
+"& c #3467BC",
+"+ c #2F5DA9",
+"; c #B3C8EB",
+"4 c #E5EDF9",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ......X ",
+" .oooooO+ ",
+" .ooooooo. ",
+" .+@@@##$%%&&&&&****. ",
+" .=-;:>,<12345678900. ",
+" .q=-;:>,<1234567890. ",
+" .wq=-e:>,<12345678r. ",
+" .twq=-e:>,<12345678. ",
+" .ytwq=-e:>,<1234567. ",
+" .uytwq=-e:>,<123456. ",
+" .ouytwq=-e:>,<12345. ",
+" .Oouytwq=-e;>,<1234. ",
+" .iOouytwq=-e;>,<123. ",
+" .piOouytwq=-e;>,<12. ",
+" .apiOouytwq=-e;>,<1. ",
+" .sapiOouytwq=-e;>,<. ",
+" .dsapiOouytwq=-e;>,. ",
+" ...................# ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/src/bin/wx/OPJViewer/source/icon4.xpm b/src/bin/wx/OPJViewer/source/icon4.xpm
new file mode 100644
index 00000000..37f95798
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/icon4.xpm
@@ -0,0 +1,43 @@
+/* XPM */
+static const char *icon4_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 5 1",
+". c Black",
+"o c #8399B4",
+"X c #8DA0B9",
+" c None",
+"O c #800000",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ....... ",
+" .XXXXXo. ",
+" .XXXXXXX. ",
+" .................... ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .OOOOOOOOOOOOOOOOOO. ",
+" .................... ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/src/bin/wx/OPJViewer/source/icon5.xpm b/src/bin/wx/OPJViewer/source/icon5.xpm
new file mode 100644
index 00000000..d4e8b118
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/icon5.xpm
@@ -0,0 +1,79 @@
+/* XPM */
+static const char *icon5_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"0 c #AAC1E8",
+"q c #B9CDED",
+"X c #295193",
+"e c #C6D6F0",
+"a c #4A7CCE",
+"& c #779DDB",
+"* c #7FA2DD",
+"2 c #EAF0FA",
+"@ c #2D59A3",
+"o c #6E96D8",
+"y c #356AC1",
+"d c #214279",
+"w c #BED0EE",
+"= c #85A7DF",
+"< c #E1E9F7",
+"3 c #F0F5FC",
+"s c #CBD9F1",
+", c #DAE5F6",
+"7 c #3161B1",
+" c None",
+". c #274D8B",
+"6 c #FDFEFF",
+"i c #E7EEF9",
+"9 c #9FB9E5",
+"- c #89A9DF",
+"8 c #98B5E4",
+"$ c #5584D1",
+"+ c #3569BF",
+"% c #305FAC",
+"O c #5D89D3",
+"> c #D2DFF4",
+"p c #3366B9",
+"5 c #FAFCFE",
+"4 c #F5F8FD",
+"t c #4075CC",
+"u c #638ED5",
+"r c #CEDCF2",
+"; c #90AFE2",
+"# c #2F5DA9",
+": c #B3C8EB",
+"1 c #E5EDF9",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ......X ",
+" XoooooO. ",
+" Xoooooo+. ",
+" Xooooooo@XXXXXXXXXX# ",
+" Xoooooooooooooooooo# ",
+" Xoooooooooooooooooo# ",
+" Xoo$################### ",
+" Xoo%O&*=-;:>,<123445667 ",
+" XooX890:qwer>,<123445q# ",
+" Xoty;890:qwer>,<12344# ",
+" Xo%u-;890:qwer>,<i234# ",
+" XoX&*-;890:qwer>,<i2r# ",
+" Xtpo&*-;890:qwer>,<i# ",
+" X%auo&*-;890:qwer>,<# ",
+" XX$Ouo&*-;890:qwer>s# ",
+" d%a$Ouo&*-;890:qwer# ",
+" d+ta$Ouo&*-;890:qwe# ",
+" d..................# ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/src/bin/wx/OPJViewer/source/imagjpeg2000.cpp b/src/bin/wx/OPJViewer/source/imagjpeg2000.cpp
new file mode 100644
index 00000000..ee2aa74d
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/imagjpeg2000.cpp
@@ -0,0 +1,1464 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: imagjpeg2000.cpp
+// Purpose: wxImage JPEG 2000 family file format handler
+// Author: Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik
+// RCS-ID: $Id: imagjpeg2000.cpp,v 0.00 2008/01/31 10:58:00 MW Exp $
+// Copyright: (c) Giuseppe Baruffa
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_IMAGE && wxUSE_LIBOPENJPEG
+
+#include "imagjpeg2000.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/intl.h"
+ #include "wx/bitmap.h"
+ #include "wx/module.h"
+#endif
+
+#include "libopenjpeg/openjpeg.h"
+
+#include "wx/filefn.h"
+#include "wx/wfstream.h"
+
+// ----------------------------------------------------------------------------
+// types
+// ----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// wxJPEG2000Handler
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxJPEG2000Handler,wxImageHandler)
+
+#if wxUSE_STREAMS
+
+//------------- JPEG 2000 Data Source Manager
+
+#define J2K_CFMT 0
+#define JP2_CFMT 1
+#define JPT_CFMT 2
+#define MJ2_CFMT 3
+#define PXM_DFMT 0
+#define PGX_DFMT 1
+#define BMP_DFMT 2
+#define YUV_DFMT 3
+
+#define MAX_MESSAGE_LEN 200
+
+/* check file type */
+int
+jpeg2000familytype(unsigned char *hdr, int hdr_len)
+{
+ // check length
+ if (hdr_len < 24)
+ return -1;
+
+ // check format
+ if (hdr[0] == 0x00 &&
+ hdr[1] == 0x00 &&
+ hdr[2] == 0x00 &&
+ hdr[3] == 0x0C &&
+ hdr[4] == 0x6A &&
+ hdr[5] == 0x50 &&
+ hdr[6] == 0x20 &&
+ hdr[7] == 0x20 &&
+ hdr[20] == 0x6A &&
+ hdr[21] == 0x70 &&
+ hdr[22] == 0x32)
+ // JP2 file format
+ return JP2_CFMT;
+ else if (hdr[0] == 0x00 &&
+ hdr[1] == 0x00 &&
+ hdr[2] == 0x00 &&
+ hdr[3] == 0x0C &&
+ hdr[4] == 0x6A &&
+ hdr[5] == 0x50 &&
+ hdr[6] == 0x20 &&
+ hdr[7] == 0x20 &&
+ hdr[20] == 0x6D &&
+ hdr[21] == 0x6A &&
+ hdr[22] == 0x70 &&
+ hdr[23] == 0x32)
+ // MJ2 file format
+ return MJ2_CFMT;
+ else if (hdr[0] == 0xFF &&
+ hdr[1] == 0x4F)
+ // J2K file format
+ return J2K_CFMT;
+ else
+ // unknown format
+ return -1;
+
+}
+
+/* we have to use this to avoid GUI-noGUI threads crashing */
+void printevent(const char *msg)
+{
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("%s"), msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+/* sample error callback expecting a FILE* client object */
+void jpeg2000_error_callback(const char *msg, void *client_data) {
+ char mess[MAX_MESSAGE_LEN + 20];
+ int message_len = strlen(msg);
+
+ if (message_len > MAX_MESSAGE_LEN)
+ message_len = MAX_MESSAGE_LEN;
+
+ if (msg[message_len - 1] == '\n')
+ message_len--;
+
+ sprintf(mess, "[ERROR] %.*s", message_len, msg);
+ printevent(mess);
+}
+
+/* sample warning callback expecting a FILE* client object */
+void jpeg2000_warning_callback(const char *msg, void *client_data) {
+ char mess[MAX_MESSAGE_LEN + 20];
+ int message_len = strlen(msg);
+
+ if (message_len > MAX_MESSAGE_LEN)
+ message_len = MAX_MESSAGE_LEN;
+
+ if (msg[message_len - 1] == '\n')
+ message_len--;
+
+ sprintf(mess, "[WARNING] %.*s", message_len, msg);
+ printevent(mess);
+}
+
+/* sample debug callback expecting no client object */
+void jpeg2000_info_callback(const char *msg, void *client_data) {
+ char mess[MAX_MESSAGE_LEN + 20];
+ int message_len = strlen(msg);
+
+ if (message_len > MAX_MESSAGE_LEN)
+ message_len = MAX_MESSAGE_LEN;
+
+ if (msg[message_len - 1] == '\n')
+ message_len--;
+
+ sprintf(mess, "[INFO] %.*s", message_len, msg);
+ printevent(mess);
+}
+
+/* macro functions */
+/* From little endian to big endian, 2 and 4 bytes */
+#define BYTE_SWAP2(X) ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
+#define BYTE_SWAP4(X) ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
+
+#ifdef __WXGTK__
+#define BYTE_SWAP8(X) ((X & 0x00000000000000FFULL) << 56) | ((X & 0x000000000000FF00ULL) << 40) | \
+ ((X & 0x0000000000FF0000ULL) << 24) | ((X & 0x00000000FF000000ULL) << 8) | \
+ ((X & 0x000000FF00000000ULL) >> 8) | ((X & 0x0000FF0000000000ULL) >> 24) | \
+ ((X & 0x00FF000000000000ULL) >> 40) | ((X & 0xFF00000000000000ULL) >> 56)
+#else
+#define BYTE_SWAP8(X) ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \
+ ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \
+ ((X & 0x000000FF00000000) >> 8) | ((X & 0x0000FF0000000000) >> 24) | \
+ ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56)
+#endif
+
+/* From codestream to int values */
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \
+ ((unsigned long int) (C)[(P) + 1] << 16) + \
+ ((unsigned long int) (C)[(P) + 2] << 8) + \
+ ((unsigned long int) (C)[(P) + 3] << 0))
+
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \
+ ((unsigned long int) (C)[(P) + 1] << 0))
+
+/* defines */
+#define SHORT_DESCR_LEN 32
+#define LONG_DESCR_LEN 256
+
+/* enumeration for file formats */
+#define JPEG2000FILENUM 4
+typedef enum {
+
+ JP2_FILE,
+ J2K_FILE,
+ MJ2_FILE,
+ UNK_FILE
+
+} jpeg2000filetype;
+
+/* enumeration for the box types */
+#define JPEG2000BOXNUM 23
+typedef enum {
+
+ FILE_BOX,
+ JP_BOX,
+ FTYP_BOX,
+ JP2H_BOX,
+ IHDR_BOX,
+ COLR_BOX,
+ JP2C_BOX,
+ JP2I_BOX,
+ XML_BOX,
+ UUID_BOX,
+ UINF_BOX,
+ MOOV_BOX,
+ MVHD_BOX,
+ TRAK_BOX,
+ TKHD_BOX,
+ MDIA_BOX,
+ MINF_BOX,
+ STBL_BOX,
+ STSD_BOX,
+ MJP2_BOX,
+ MDAT_BOX,
+ ANY_BOX,
+ UNK_BOX
+
+} jpeg2000boxtype;
+
+/* jpeg2000 family box signatures */
+#define FILE_SIGN ""
+#define JP_SIGN "jP\040\040"
+#define FTYP_SIGN "ftyp"
+#define JP2H_SIGN "jp2h"
+#define IHDR_SIGN "ihdr"
+#define COLR_SIGN "colr"
+#define JP2C_SIGN "jp2c"
+#define JP2I_SIGN "jp2i"
+#define XML_SIGN "xml\040"
+#define UUID_SIGN "uuid"
+#define UINF_SIGN "uinf"
+#define MOOV_SIGN "moov"
+#define MVHD_SIGN "mvhd"
+#define TRAK_SIGN "trak"
+#define TKHD_SIGN "tkhd"
+#define MDIA_SIGN "mdia"
+#define MINF_SIGN "minf"
+#define VMHD_SIGN "vmhd"
+#define STBL_SIGN "stbl"
+#define STSD_SIGN "stsd"
+#define MJP2_SIGN "mjp2"
+#define MDAT_SIGN "mdat"
+#define ANY_SIGN ""
+#define UNK_SIGN ""
+
+/* the box structure itself */
+struct jpeg2000boxdef {
+
+ char value[5]; /* hexadecimal value/string*/
+ char name[SHORT_DESCR_LEN]; /* short description */
+ char descr[LONG_DESCR_LEN]; /* long description */
+ int sbox; /* is it a superbox? */
+ int req[JPEG2000FILENUM]; /* mandatory box */
+ jpeg2000boxtype ins; /* contained in box... */
+
+};
+
+/* the possible boxes */
+struct jpeg2000boxdef jpeg2000box[] =
+{
+/* sign */ {FILE_SIGN,
+/* short */ "placeholder for nothing",
+/* long */ "Nothing to say",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP_SIGN,
+/* short */ "JPEG 2000 Signature box",
+/* long */ "This box uniquely identifies the file as being part of the JPEG 2000 family of files",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {FTYP_SIGN,
+/* short */ "File Type box",
+/* long */ "This box specifies file type, version and compatibility information, including specifying if this file "
+ "is a conforming JP2 file or if it can be read by a conforming JP2 reader",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP2H_SIGN,
+/* short */ "JP2 Header box",
+/* long */ "This box contains a series of boxes that contain header-type information about the file",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {IHDR_SIGN,
+/* short */ "Image Header box",
+/* long */ "This box specifies the size of the image and other related fields",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ JP2H_BOX},
+
+/* sign */ {COLR_SIGN,
+/* short */ "Colour Specification box",
+/* long */ "This box specifies the colourspace of the image",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ JP2H_BOX},
+
+/* sign */ {JP2C_SIGN,
+/* short */ "Contiguous Codestream box",
+/* long */ "This box contains the codestream as defined by Annex A",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP2I_SIGN,
+/* short */ "Intellectual Property box",
+/* long */ "This box contains intellectual property information about the image",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {XML_SIGN,
+/* short */ "XML box",
+/* long */ "This box provides a tool by which vendors can add XML formatted information to a JP2 file",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UUID_SIGN,
+/* short */ "UUID box",
+/* long */ "This box provides a tool by which vendors can add additional information to a file "
+ "without risking conflict with other vendors",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UINF_SIGN,
+/* short */ "UUID Info box",
+/* long */ "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {MOOV_SIGN,
+/* short */ "Movie box",
+/* long */ "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {MVHD_SIGN,
+/* short */ "Movie Header box",
+/* long */ "This box defines overall information which is media-independent, and relevant to the entire presentation "
+ "considered as a whole",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MOOV_BOX},
+
+/* sign */ {TRAK_SIGN,
+/* short */ "Track box",
+/* long */ "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MOOV_BOX},
+
+/* sign */ {TKHD_SIGN,
+/* short */ "Track Header box",
+/* long */ "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ TRAK_BOX},
+
+/* sign */ {MDIA_SIGN,
+/* short */ "Media box",
+/* long */ "The media declaration container contains all the objects which declare information about the media data "
+ "within a track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ TRAK_BOX},
+
+/* sign */ {MINF_SIGN,
+/* short */ "Media Information box",
+/* long */ "This box contains all the objects which declare characteristic information of the media in the track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
+/* sign */ {STBL_SIGN,
+/* short */ "Sample Table box",
+/* long */ "The sample table contains all the time and data indexing of the media samples in a track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {STSD_SIGN,
+/* short */ "Sample Description box",
+/* long */ "The sample description table gives detailed information about the coding type used, and any initialization "
+ "information needed for that coding",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {MJP2_SIGN,
+/* short */ "MJP2 Sample Description box",
+/* long */ "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "
+ "information needed for that coding",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {MDAT_SIGN,
+/* short */ "Media Data box",
+/* long */ "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {ANY_SIGN,
+/* short */ "Any box",
+/* long */ "All the existing boxes",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UNK_SIGN,
+/* short */ "Unknown Type box",
+/* long */ "The signature is not recognised to be that of an existing box",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ ANY_BOX}
+
+};
+
+/* declaration */
+int
+jpeg2000_box_handler_function(jpeg2000boxtype boxtype, wxInputStream& stream, unsigned long int filepoint,
+ unsigned long int filelimit, int level, char *scansign,
+ unsigned long int *scanpoint);
+
+#ifdef __WXMSW__
+typedef unsigned __int64 int8byte;
+#endif // __WXMSW__
+
+#ifdef __WXGTK__
+typedef unsigned long long int8byte;
+#endif // __WXGTK__
+
+/* internal mini-search for a box signature */
+int
+jpeg2000_file_parse(wxInputStream& stream, unsigned long int filepoint, unsigned long int filelimit, int level,
+ char *scansign, unsigned long int *scanpoint)
+{
+ unsigned long int LBox = 0x00000000;
+ char TBox[5] = "\0\0\0\0";
+ int8byte XLBox = 0x0000000000000000;
+ unsigned long int box_length = 0;
+ int last_box = 0, box_num = 0;
+ int box_type = ANY_BOX;
+ unsigned char fourbytes[4];
+ int box_number = 0;
+
+ /* cycle all over the file */
+ box_num = 0;
+ last_box = 0;
+ while (!last_box) {
+
+ /* do not exceed file limit */
+ if (filepoint >= filelimit)
+ return (0);
+
+ /* seek on file */
+ if (stream.SeekI(filepoint, wxFromStart) == wxInvalidOffset)
+ return (-1);
+
+ /* read the mandatory LBox, 4 bytes */
+ if (!stream.Read(fourbytes, 4)) {
+ wxLogError(wxT("Problem reading LBox from the file (file ended?)"));
+ return -1;
+ };
+ LBox = STREAM_TO_UINT32(fourbytes, 0);
+
+ /* read the mandatory TBox, 4 bytes */
+ if (!stream.Read(TBox, 4)) {
+ wxLogError(wxT("Problem reading TBox from the file (file ended?)"));
+ return -1;
+ };
+
+ /* look if scansign is got */
+ if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {
+ /* hack/exploit */
+ // stop as soon as you find the level-th codebox
+ if (box_number == level) {
+ memcpy(scansign, " ", 4);
+ *scanpoint = filepoint;
+ return (0);
+ } else
+ box_number++;
+
+ };
+
+ /* determine the box type */
+ for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)
+ if (memcmp(TBox, jpeg2000box[box_type].value, 4) == 0)
+ break;
+
+ /* read the optional XLBox, 8 bytes */
+ if (LBox == 1) {
+
+ if (!stream.Read(&XLBox, 8)) {
+ wxLogError(wxT("Problem reading XLBox from the file (file ended?)"));
+ return -1;
+ };
+ box_length = (unsigned long int) BYTE_SWAP8(XLBox);
+
+ } else if (LBox == 0x00000000) {
+
+ /* last box in file */
+ last_box = 1;
+ box_length = filelimit - filepoint;
+
+ } else
+
+ box_length = LBox;
+
+
+ /* go deep in the box */
+ jpeg2000_box_handler_function((jpeg2000boxtype) box_type,
+ stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8),
+ filepoint + box_length, level, scansign, scanpoint);
+
+ /* if it's a superbox go inside it */
+ if (jpeg2000box[box_type].sbox)
+ jpeg2000_file_parse(stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
+ level, scansign, scanpoint);
+
+ /* increment box number and filepoint*/
+ box_num++;
+ filepoint += box_length;
+
+ };
+
+ /* all good */
+ return (0);
+}
+
+// search first contiguos codestream box in an mj2 file
+unsigned long int
+searchjpeg2000c(wxInputStream& stream, unsigned long int fsize, int number)
+{
+ char scansign[] = "jp2c";
+ unsigned long int scanpoint = 0L;
+
+ wxLogMessage(wxT("Searching jp2c box... "));
+
+ /* do the parsing */
+ if (jpeg2000_file_parse(stream, 0, fsize, number, scansign, &scanpoint) < 0)
+ wxLogMessage(wxT("Unrecoverable error during JPEG 2000 box parsing: stopping"));
+
+ if (strcmp(scansign, " "))
+ wxLogMessage(wxT("Box not found"));
+ else {
+
+ wxLogMessage(wxString::Format(wxT("Box found at byte %d"), scanpoint));
+
+ };
+
+ return (scanpoint);
+}
+
+// search the jp2h box in the file
+unsigned long int
+searchjpeg2000headerbox(wxInputStream& stream, unsigned long int fsize)
+{
+ char scansign[] = "jp2h";
+ unsigned long int scanpoint = 0L;
+
+ wxLogMessage(wxT("Searching jp2h box... "));
+
+ /* do the parsing */
+ if (jpeg2000_file_parse(stream, 0, fsize, 0, scansign, &scanpoint) < 0)
+ wxLogMessage(wxT("Unrecoverable error during JPEG 2000 box parsing: stopping"));
+
+ if (strcmp(scansign, " "))
+ wxLogMessage(wxT("Box not found"));
+ else
+ wxLogMessage(wxString::Format(wxT("Box found at byte %d"), scanpoint));
+
+ return (scanpoint);
+}
+
+/* handling functions */
+#define ITEM_PER_ROW 10
+
+/* Box handler function */
+int
+jpeg2000_box_handler_function(jpeg2000boxtype boxtype, wxInputStream& stream, unsigned long int filepoint,
+ unsigned long int filelimit, int level,
+ char *scansign, unsigned long int *scanpoint)
+{
+ switch (boxtype) {
+
+ /* Sample Description box */
+ case (STSD_BOX):
+ jpeg2000_file_parse(stream, filepoint + 8, filelimit, level, scansign, scanpoint);
+ break;
+
+ /* MJP2 Sample Description box */
+ case (MJP2_BOX):
+ jpeg2000_file_parse(stream, filepoint + 78, filelimit, level, scansign, scanpoint);
+ break;
+
+ /* not yet implemented */
+ default:
+ break;
+
+ };
+
+ return (0);
+}
+
+// the jP and ftyp parts of the header
+#define jpeg2000headSIZE 32
+unsigned char jpeg2000head[jpeg2000headSIZE] = {
+ 0x00, 0x00, 0x00, 0x0C, 'j', 'P', ' ', ' ',
+ 0x0D, 0x0A, 0x87, 0x0A, 0x00, 0x00, 0x00, 0x14,
+ 'f', 't', 'y', 'p', 'j', 'p', '2', ' ',
+ 0x00, 0x00, 0x00, 0x00, 'j', 'p', '2', ' '
+};
+
+/////////////////////////////////////////////////
+/////////////////////////////////////////////////
+
+// load the jpeg2000 file format
+bool wxJPEG2000Handler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)
+{
+ opj_dparameters_t parameters; /* decompression parameters */
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_image_t *opjimage = NULL;
+ unsigned char *src = NULL;
+ unsigned char *ptr;
+ int file_length, jp2c_point, jp2h_point;
+ unsigned long int jp2hboxlen, jp2cboxlen;
+ opj_codestream_info_t cstr_info; /* Codestream information structure */
+ unsigned char hdr[24];
+ int jpfamform;
+
+ // destroy the image
+ image->Destroy();
+
+ /* read the beginning of the file to check the type */
+ if (!stream.Read(hdr, WXSIZEOF(hdr)))
+ return false;
+ if ((jpfamform = jpeg2000familytype(hdr, WXSIZEOF(hdr))) < 0)
+ return false;
+ stream.SeekI(0, wxFromStart);
+
+ /* handle to a decompressor */
+ opj_dinfo_t* dinfo = NULL;
+ opj_cio_t *cio = NULL;
+
+ /* configure the event callbacks */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = jpeg2000_error_callback;
+ event_mgr.warning_handler = jpeg2000_warning_callback;
+ event_mgr.info_handler = jpeg2000_info_callback;
+
+ /* set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* prepare parameters */
+ strncpy(parameters.infile, "", sizeof(parameters.infile) - 1);
+ strncpy(parameters.outfile, "", sizeof(parameters.outfile) - 1);
+ parameters.decod_format = jpfamform;
+ parameters.cod_format = BMP_DFMT;
+ if (m_reducefactor)
+ parameters.cp_reduce = m_reducefactor;
+ if (m_qualitylayers)
+ parameters.cp_layer = m_qualitylayers;
+ /*if (n_components)
+ parameters. = n_components;*/
+
+ /* JPWL only */
+#ifdef USE_JPWL
+ parameters.jpwl_exp_comps = m_expcomps;
+ parameters.jpwl_max_tiles = m_maxtiles;
+ parameters.jpwl_correct = m_enablejpwl;
+#endif /* USE_JPWL */
+
+ /* get a decoder handle */
+ if (jpfamform == JP2_CFMT || jpfamform == MJ2_CFMT)
+ dinfo = opj_create_decompress(CODEC_JP2);
+ else if (jpfamform == J2K_CFMT)
+ dinfo = opj_create_decompress(CODEC_J2K);
+ else
+ return false;
+
+ /* find length of the stream */
+ stream.SeekI(0, wxFromEnd);
+ file_length = (int) stream.TellI();
+
+ /* it's a movie */
+ if (jpfamform == MJ2_CFMT) {
+ /* search for the first codestream box and the movie header box */
+ jp2c_point = searchjpeg2000c(stream, file_length, m_framenum);
+ jp2h_point = searchjpeg2000headerbox(stream, file_length);
+
+ // read the jp2h box and store it
+ stream.SeekI(jp2h_point, wxFromStart);
+ stream.Read(&jp2hboxlen, sizeof(unsigned long int));
+ jp2hboxlen = BYTE_SWAP4(jp2hboxlen);
+
+ // read the jp2c box and store it
+ stream.SeekI(jp2c_point, wxFromStart);
+ stream.Read(&jp2cboxlen, sizeof(unsigned long int));
+ jp2cboxlen = BYTE_SWAP4(jp2cboxlen);
+
+ // malloc memory source
+ src = (unsigned char *) malloc(jpeg2000headSIZE + jp2hboxlen + jp2cboxlen);
+
+ // copy the jP and ftyp
+ memcpy(src, jpeg2000head, jpeg2000headSIZE);
+
+ // copy the jp2h
+ stream.SeekI(jp2h_point, wxFromStart);
+ stream.Read(&src[jpeg2000headSIZE], jp2hboxlen);
+
+ // copy the jp2c
+ stream.SeekI(jp2c_point, wxFromStart);
+ stream.Read(&src[jpeg2000headSIZE + jp2hboxlen], jp2cboxlen);
+ } else if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT) {
+ /* It's a plain image */
+ /* get data */
+ stream.SeekI(0, wxFromStart);
+ src = (unsigned char *) malloc(file_length);
+ stream.Read(src, file_length);
+ } else
+ return false;
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using user parameters */
+ opj_setup_decoder(dinfo, &parameters);
+
+ /* open a byte stream */
+ if (jpfamform == MJ2_CFMT)
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, jpeg2000headSIZE + jp2hboxlen + jp2cboxlen);
+ else if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT)
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+ else {
+ free(src);
+ return false;
+ }
+
+ /* decode the stream and fill the image structure */
+ opjimage = opj_decode_with_info(dinfo, cio, &cstr_info);
+ if (!opjimage) {
+ wxMutexGuiEnter();
+ wxLogError(wxT("JPEG 2000 failed to decode image!"));
+ wxMutexGuiLeave();
+ opj_destroy_decompress(dinfo);
+ opj_cio_close(cio);
+ free(src);
+ return false;
+ }
+
+ /* close the byte stream */
+ opj_cio_close(cio);
+
+ /*
+
+ - At this point, we have the structure "opjimage" that is filled with decompressed
+ data, as processed by the OpenJPEG decompression engine
+
+ - We need to fill the class "image" with the proper pixel sample values
+
+ */
+ {
+ int shiftbpp;
+ int c, tempcomps;
+
+ // check components number
+ if (m_components > opjimage->numcomps)
+ m_components = opjimage->numcomps;
+
+ // check image depth (only on the first one, for now)
+ if (m_components)
+ shiftbpp = opjimage->comps[m_components - 1].prec - 8;
+ else
+ shiftbpp = opjimage->comps[0].prec - 8;
+
+ // prepare image size
+ if (m_components)
+ image->Create(opjimage->comps[m_components - 1].w, opjimage->comps[m_components - 1].h, true);
+ else
+ image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true);
+
+ // access image raw data
+ image->SetMask(false);
+ ptr = image->GetData();
+
+ // workaround for components different from 1 or 3
+ if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("JPEG2000: weird number of components"));
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+ tempcomps = 1;
+ } else
+ tempcomps = opjimage->numcomps;
+
+ // workaround for subsampled components
+ for (c = 1; c < tempcomps; c++) {
+ if ((opjimage->comps[c].w != opjimage->comps[c - 1].w) || (opjimage->comps[c].h != opjimage->comps[c - 1].h)) {
+ tempcomps = 1;
+ break;
+ }
+ }
+
+ // workaround for different precision components
+ for (c = 1; c < tempcomps; c++) {
+ if (opjimage->comps[c].bpp != opjimage->comps[c - 1].bpp) {
+ tempcomps = 1;
+ break;
+ }
+ }
+
+ // only one component selected
+ if (m_components)
+ tempcomps = 1;
+
+ // RGB color picture
+ if (tempcomps == 3) {
+ int row, col;
+ int *r = opjimage->comps[0].data;
+ int *g = opjimage->comps[1].data;
+ int *b = opjimage->comps[2].data;
+ if (shiftbpp > 0) {
+ for (row = 0; row < opjimage->comps[0].h; row++) {
+ for (col = 0; col < opjimage->comps[0].w; col++) {
+
+ *(ptr++) = (*(r++)) >> shiftbpp;
+ *(ptr++) = (*(g++)) >> shiftbpp;
+ *(ptr++) = (*(b++)) >> shiftbpp;
+
+ }
+ }
+
+ } else if (shiftbpp < 0) {
+ for (row = 0; row < opjimage->comps[0].h; row++) {
+ for (col = 0; col < opjimage->comps[0].w; col++) {
+
+ *(ptr++) = (*(r++)) << -shiftbpp;
+ *(ptr++) = (*(g++)) << -shiftbpp;
+ *(ptr++) = (*(b++)) << -shiftbpp;
+
+ }
+ }
+
+ } else {
+ for (row = 0; row < opjimage->comps[0].h; row++) {
+ for (col = 0; col < opjimage->comps[0].w; col++) {
+
+ *(ptr++) = *(r++);
+ *(ptr++) = *(g++);
+ *(ptr++) = *(b++);
+
+ }
+ }
+ }
+ }
+
+ // B/W picture
+ if (tempcomps == 1) {
+ int row, col;
+ int selcomp;
+
+ if (m_components)
+ selcomp = m_components - 1;
+ else
+ selcomp = 0;
+
+ int *y = opjimage->comps[selcomp].data;
+ if (shiftbpp > 0) {
+ for (row = 0; row < opjimage->comps[selcomp].h; row++) {
+ for (col = 0; col < opjimage->comps[selcomp].w; col++) {
+
+ *(ptr++) = (*(y)) >> shiftbpp;
+ *(ptr++) = (*(y)) >> shiftbpp;
+ *(ptr++) = (*(y++)) >> shiftbpp;
+
+ }
+ }
+ } else if (shiftbpp < 0) {
+ for (row = 0; row < opjimage->comps[selcomp].h; row++) {
+ for (col = 0; col < opjimage->comps[selcomp].w; col++) {
+
+ *(ptr++) = (*(y)) << -shiftbpp;
+ *(ptr++) = (*(y)) << -shiftbpp;
+ *(ptr++) = (*(y++)) << -shiftbpp;
+
+ }
+ }
+ } else {
+ for (row = 0; row < opjimage->comps[selcomp].h; row++) {
+ for (col = 0; col < opjimage->comps[selcomp].w; col++) {
+
+ *(ptr++) = *(y);
+ *(ptr++) = *(y);
+ *(ptr++) = *(y++);
+
+ }
+ }
+ }
+ }
+
+
+ }
+
+ wxMutexGuiEnter();
+ wxLogMessage(wxT("JPEG 2000 image loaded."));
+ wxMutexGuiLeave();
+
+ /* close openjpeg structs */
+ opj_destroy_decompress(dinfo);
+ opj_image_destroy(opjimage);
+ free(src);
+
+ if (!image->Ok())
+ return false;
+ else
+ return true;
+
+}
+
+#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 */
+
+// save the j2k codestream
+bool wxJPEG2000Handler::SaveFile( wxImage *wimage, wxOutputStream& stream, bool verbose )
+{
+ opj_cparameters_t parameters; /* compression parameters */
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_image_t *oimage = NULL;
+ opj_image_cmptparm_t *cmptparm;
+ opj_cio_t *cio = NULL;
+ opj_codestream_info_t cstr_info;
+ int codestream_length;
+ bool bSuccess;
+ int i;
+ char indexfilename[OPJ_PATH_LEN] = ""; /* index file name */
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = jpeg2000_error_callback;
+ event_mgr.warning_handler = jpeg2000_warning_callback;
+ event_mgr.info_handler = jpeg2000_info_callback;
+
+ /* set encoding parameters to default values */
+ opj_set_default_encoder_parameters(&parameters);
+
+ /* load parameters */
+ parameters.cp_cinema = OFF;
+
+ /* subsampling */
+ if (sscanf(m_subsampling.ToAscii(), "%d,%d", &(parameters.subsampling_dx), &(parameters.subsampling_dy)) != 2) {
+ wxLogError(wxT("Wrong sub-sampling encoder setting: dx,dy"));
+ return false;
+ }
+
+ /* compression rates */
+ if ((m_rates != wxT("")) && (!m_enablequality)) {
+ const char *s1 = m_rates.ToAscii();
+ wxLogMessage(wxT("rates %s"), s1);
+ while (sscanf(s1, "%f", &(parameters.tcp_rates[parameters.tcp_numlayers])) == 1) {
+ parameters.tcp_numlayers++;
+ while (*s1 && *s1 != ',') {
+ s1++;
+ }
+ if (!*s1)
+ break;
+ s1++;
+ }
+ wxLogMessage(wxT("%d layers"), parameters.tcp_numlayers);
+ parameters.cp_disto_alloc = 1;
+ }
+
+ /* image quality, dB */
+ if ((m_quality != wxT("")) && (m_enablequality)) {
+ const char *s2 = m_quality.ToAscii();
+ wxLogMessage(wxT("qualities %s"), s2);
+ while (sscanf(s2, "%f", &parameters.tcp_distoratio[parameters.tcp_numlayers]) == 1) {
+ parameters.tcp_numlayers++;
+ while (*s2 && *s2 != ',') {
+ s2++;
+ }
+ if (!*s2)
+ break;
+ s2++;
+ }
+ wxLogMessage(wxT("%d layers"), parameters.tcp_numlayers);
+ parameters.cp_fixed_quality = 1;
+ }
+
+ /* image origin */
+ if (sscanf(m_origin.ToAscii(), "%d,%d", &parameters.image_offset_x0, &parameters.image_offset_y0) != 2) {
+ wxLogError(wxT("bad coordinate of the image origin: x0,y0"));
+ return false;
+ }
+
+ /* Create comment for codestream */
+ if(m_enablecomm) {
+ parameters.cp_comment = (char *) malloc(strlen(m_comment.ToAscii()) + 1);
+ if(parameters.cp_comment) {
+ strcpy(parameters.cp_comment, m_comment.ToAscii());
+ }
+ } else {
+ parameters.cp_comment = NULL;
+ }
+
+ /* indexing file */
+ if (m_enableidx) {
+ strncpy(indexfilename, m_index.ToAscii(), OPJ_PATH_LEN);
+ wxLogMessage(wxT("index file is %s"), indexfilename);
+ }
+
+ /* 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;
+ }
+
+ /* irreversible transform */
+ parameters.irreversible = (m_irreversible == true) ? 1 : 0;
+
+ /* resolutions */
+ parameters.numresolution = m_resolutions;
+
+ /* codeblocks size */
+ if (m_cbsize != wxT("")) {
+ int cblockw_init = 0, cblockh_init = 0;
+ sscanf(m_cbsize.ToAscii(), "%d,%d", &cblockw_init, &cblockh_init);
+ if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {
+ wxLogError(wxT("!! Size of code_block error !! Restrictions:\n width*height<=4096\n 4<=width,height<= 1024"));
+ return false;
+ }
+ parameters.cblockw_init = cblockw_init;
+ parameters.cblockh_init = cblockh_init;
+ }
+
+ /* precincts size */
+ if (m_prsize != wxT("")) {
+ char sep;
+ int res_spec = 0;
+ char *s = (char *) m_prsize.c_str();
+ do {
+ sep = 0;
+ sscanf(s, "[%d,%d]%c", &parameters.prcw_init[res_spec], &parameters.prch_init[res_spec], &sep);
+ parameters.csty |= 0x01;
+ res_spec++;
+ s = strpbrk(s, "]") + 2;
+ } while (sep == ',');
+ parameters.res_spec = res_spec;
+ }
+
+ /* tiles */
+ if (m_tsize != wxT("")) {
+ sscanf(m_tsize.ToAscii(), "%d,%d", &parameters.cp_tdx, &parameters.cp_tdy);
+ parameters.tile_size_on = true;
+ }
+
+ /* tile origin */
+ if (sscanf(m_torigin.ToAscii(), "%d,%d", &parameters.cp_tx0, &parameters.cp_ty0) != 2) {
+ wxLogError(wxT("tile offset setting error: X0,Y0"));
+ return false;
+ }
+
+ /* use SOP */
+ if (m_enablesop)
+ parameters.csty |= 0x02;
+
+ /* use EPH */
+ if (m_enableeph)
+ parameters.csty |= 0x04;
+
+ /* multiple component transform */
+ if (m_multicomp)
+ parameters.tcp_mct = 1;
+ else
+ parameters.tcp_mct = 0;
+
+ /* mode switch */
+ parameters.mode = (m_enablebypass ? 1 : 0) + (m_enablereset ? 2 : 0)
+ + (m_enablerestart ? 4 : 0) + (m_enablevsc ? 8 : 0)
+ + (m_enableerterm ? 16 : 0) + (m_enablesegmark ? 32 : 0);
+
+ /* progression order */
+ switch (m_progression) {
+
+ /* LRCP */
+ case 0:
+ parameters.prog_order = LRCP;
+ break;
+
+ /* RLCP */
+ case 1:
+ parameters.prog_order = RLCP;
+ break;
+
+ /* RPCL */
+ case 2:
+ parameters.prog_order = RPCL;
+ break;
+
+ /* PCRL */
+ case 3:
+ parameters.prog_order = PCRL;
+ break;
+
+ /* CPRL */
+ case 4:
+ parameters.prog_order = CPRL;
+ break;
+
+ /* DCI2K24 */
+ case 5:
+ parameters.cp_cinema = CINEMA2K_24;
+ parameters.cp_rsiz = CINEMA2K;
+ break;
+
+ /* DCI2K48 */
+ case 6:
+ parameters.cp_cinema = CINEMA2K_48;
+ parameters.cp_rsiz = CINEMA2K;
+ break;
+
+ /* DCI4K */
+ case 7:
+ parameters.cp_cinema = CINEMA4K_24;
+ parameters.cp_rsiz = CINEMA4K;
+ break;
+
+ default:
+ break;
+ }
+
+ /* check cinema */
+ if (parameters.cp_cinema) {
+
+ /* set up */
+ 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;
+
+ }
+
+ /* convert wx image into opj image */
+ cmptparm = (opj_image_cmptparm_t*) malloc(3 * sizeof(opj_image_cmptparm_t));
+
+ /* initialize opj image components */
+ memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
+ for(i = 0; i < 3; i++) {
+ cmptparm[i].prec = 8;
+ cmptparm[i].bpp = 8;
+ cmptparm[i].sgnd = false;
+ cmptparm[i].dx = parameters.subsampling_dx;
+ cmptparm[i].dy = parameters.subsampling_dy;
+ cmptparm[i].w = wimage->GetWidth();
+ cmptparm[i].h = wimage->GetHeight();
+ }
+
+ /* create the image */
+ oimage = opj_image_create(3, &cmptparm[0], CLRSPC_SRGB);
+ if(!oimage) {
+ if (cmptparm)
+ free(cmptparm);
+ return false;
+ }
+
+ /* set image offset and reference grid */
+ oimage->x0 = parameters.image_offset_x0;
+ oimage->y0 = parameters.image_offset_y0;
+ oimage->x1 = parameters.image_offset_x0 + (wimage->GetWidth() - 1) * 1 + 1;
+ oimage->y1 = parameters.image_offset_y0 + (wimage->GetHeight() - 1) * 1 + 1;
+
+ /* load image data */
+ unsigned char *value = wimage->GetData();
+ int area = wimage->GetWidth() * wimage->GetHeight();
+ for (i = 0; i < area; i++) {
+ oimage->comps[0].data[i] = *(value++);
+ oimage->comps[1].data[i] = *(value++);
+ oimage->comps[2].data[i] = *(value++);
+ }
+
+ /* check cinema again */
+ if (parameters.cp_cinema) {
+ 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 (!((oimage->comps[0].w == 2048) | (oimage->comps[0].h == 1080))) {
+ wxLogWarning(wxT("Image coordinates %d x %d is not 2K compliant. JPEG Digital Cinema Profile-3 "
+ "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080"),
+ oimage->comps[0].w, oimage->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 (!((oimage->comps[0].w == 4096) | (oimage->comps[0].h == 2160))) {
+ wxLogWarning(wxT("Image coordinates %d x %d is not 4K compliant. JPEG Digital Cinema Profile-4"
+ "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160"),
+ oimage->comps[0].w, oimage->comps[0].h);
+ parameters.cp_rsiz = STD_RSIZ;
+ }
+ parameters.POC[0].tile = 1;
+ parameters.POC[0].resno0 = 0;
+ parameters.POC[0].compno0 = 0;
+ parameters.POC[0].layno1 = 1;
+ parameters.POC[0].resno1 = parameters.numresolution - 1;
+ parameters.POC[0].compno1 = 3;
+ parameters.POC[0].prg1 = CPRL;
+ parameters.POC[1].tile = 1;
+ parameters.POC[1].resno0 = parameters.numresolution - 1;
+ parameters.POC[1].compno0 = 0;
+ parameters.POC[1].layno1 = 1;
+ parameters.POC[1].resno1 = parameters.numresolution;
+ parameters.POC[1].compno1 = 3;
+ parameters.POC[1].prg1 = CPRL;
+ parameters.numpocs = 2;
+ break;
+ }
+
+ switch (parameters.cp_cinema) {
+ case CINEMA2K_24:
+ case CINEMA4K_24:
+ for (i = 0 ; i < parameters.tcp_numlayers; i++) {
+ temp_rate = 0;
+ if (parameters.tcp_rates[i] == 0) {
+ parameters.tcp_rates[0] = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (CINEMA_24_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ }else{
+ temp_rate = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (parameters.tcp_rates[i] * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ if (temp_rate > CINEMA_24_CS ) {
+ parameters.tcp_rates[i]= ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (CINEMA_24_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ } else {
+ /* do nothing */
+ }
+ }
+ }
+ parameters.max_comp_size = COMP_24_CS;
+ break;
+
+ case CINEMA2K_48:
+ for (i = 0; i < parameters.tcp_numlayers; i++) {
+ temp_rate = 0 ;
+ if (parameters.tcp_rates[i] == 0) {
+ parameters.tcp_rates[0] = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (CINEMA_48_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ }else{
+ temp_rate =((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (parameters.tcp_rates[i] * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ if (temp_rate > CINEMA_48_CS ){
+ parameters.tcp_rates[0]= ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
+ (CINEMA_48_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
+ }else{
+ /* do nothing */
+ }
+ }
+ }
+ parameters.max_comp_size = COMP_48_CS;
+ break;
+ }
+
+ parameters.cp_disto_alloc = 1;
+ }
+
+ /* get a J2K compressor handle */
+ opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+
+ /* setup the encoder parameters using the current image and user parameters */
+ opj_setup_encoder(cinfo, &parameters, oimage);
+
+ /* open a byte stream for writing */
+ /* allocate memory for all tiles */
+ cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
+
+ /* encode the image */
+ bSuccess = opj_encode_with_info(cinfo, cio, oimage, &cstr_info);
+ if (!bSuccess) {
+
+ opj_cio_close(cio);
+ opj_destroy_compress(cinfo);
+ opj_image_destroy(oimage);
+ if (cmptparm)
+ free(cmptparm);
+ if(parameters.cp_comment)
+ free(parameters.cp_comment);
+ if(parameters.cp_matrice)
+ free(parameters.cp_matrice);
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+
+ wxLogError(wxT("failed to encode image"));
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+
+ return false;
+ }
+ codestream_length = cio_tell(cio);
+ wxLogMessage(wxT("Codestream: %d bytes"), codestream_length);
+
+ /* write the buffer to stream */
+ stream.Write(cio->buffer, codestream_length);
+
+ /* close and free the byte stream */
+ opj_cio_close(cio);
+
+ /* Write the index to disk */
+ if (*indexfilename) {
+ if (write_index_file(&cstr_info, indexfilename)) {
+ wxLogError(wxT("Failed to output index file"));
+ }
+ }
+
+ /* free remaining compression structures */
+ opj_destroy_compress(cinfo);
+
+ /* free image data */
+ opj_image_destroy(oimage);
+
+ if (cmptparm)
+ free(cmptparm);
+ if(parameters.cp_comment)
+ free(parameters.cp_comment);
+ if(parameters.cp_matrice)
+ free(parameters.cp_matrice);
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+
+ wxLogMessage(wxT("J2K: Image encoded!"));
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+
+ return true;
+}
+
+#ifdef __VISUALC__
+ #pragma warning(default:4611)
+#endif /* VC++ */
+
+// recognize the JPEG 2000 family starting box or the 0xFF4F JPEG 2000 SOC marker
+bool wxJPEG2000Handler::DoCanRead(wxInputStream& stream)
+{
+ unsigned char hdr[24];
+ int jpfamform;
+
+ if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+ return false;
+
+ jpfamform = jpeg2000familytype(hdr, WXSIZEOF(hdr));
+
+ return ((jpfamform == JP2_CFMT) || (jpfamform == MJ2_CFMT) || (jpfamform == J2K_CFMT));
+}
+
+#endif // wxUSE_STREAMS
+
+#endif // wxUSE_LIBOPENJPEG
diff --git a/src/bin/wx/OPJViewer/source/imagjpeg2000.h b/src/bin/wx/OPJViewer/source/imagjpeg2000.h
new file mode 100644
index 00000000..609a3063
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/imagjpeg2000.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: imagalljpeg2000.h
+// Purpose: wxImage JPEG 2000 family file format handler
+// Author: G. Baruffa - based on imagjpeg.h, Vaclav Slavik
+// RCS-ID: $Id: imagalljpeg2000.h,v 0.0 2008/01/31 11:22:00 VZ Exp $
+// Copyright: (c) Giuseppe Baruffa
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_IMAGJPEG2000_H_
+#define _WX_IMAGJPEG2000_H_
+
+#include "wx/defs.h"
+
+//-----------------------------------------------------------------------------
+// wxJPEG2000Handler
+//-----------------------------------------------------------------------------
+
+#if wxUSE_LIBOPENJPEG
+
+#include "wx/image.h"
+#include "libopenjpeg/openjpeg.h"
+#include "codec/index.h"
+
+#define wxBITMAP_TYPE_JPEG2000 50
+
+class WXDLLEXPORT wxJPEG2000Handler: public wxImageHandler
+{
+public:
+ inline wxJPEG2000Handler()
+ {
+ m_name = wxT("JPEG 2000 family file format");
+ m_extension = wxT("mj2");
+ m_type = wxBITMAP_TYPE_JPEG2000;
+ m_mime = wxT("image/mj2");
+
+ /* decoding */
+ m_reducefactor = 0;
+ m_qualitylayers = 0;
+ m_components = 0;
+#ifdef USE_JPWL
+ m_enablejpwl = true;
+ m_expcomps = JPWL_EXPECTED_COMPONENTS;
+ m_maxtiles = JPWL_MAXIMUM_TILES;
+#endif // USE_JPWL
+
+ /* encoding */
+ m_subsampling = wxT("1,1");
+ m_origin = wxT("0,0");
+ m_rates = wxT("20,10,5");
+ m_quality = wxT("30,35,40");
+ m_enablequality = false;
+ m_multicomp = false;
+ m_irreversible = false;
+ m_resolutions = 6;
+ m_progression = 0;
+ m_cbsize = wxT("32,32");
+ m_prsize = wxT("[128,128],[128,128]");
+ m_tsize = wxT("");
+ m_torigin = wxT("0,0");
+ /*m_progression
+ m_resilience*/
+ m_enablesop = false;
+ m_enableeph = false;
+ m_enablereset = false;
+ m_enablesegmark = false;
+ m_enablevsc = false;
+ m_enablerestart = false;
+ m_enableerterm = false;
+ m_enablebypass = false;
+ /*m_roicompo
+ m_roiup
+ m_indexfname*/
+ m_enableidx = false;
+ m_index = wxT("index.txt");
+ m_enablepoc = false;
+ m_poc = wxT("T1=0,0,1,5,3,CPRL/T1=5,0,1,6,3,CPRL");
+ m_enablecomm = true;
+
+#if defined __WXMSW__
+ m_comment = wxT("Created by OPJViewer Win32 - OpenJPEG version ");
+#elif defined __WXGTK__
+ m_comment = wxT("Created by OPJViewer Lin32 - OpenJPEG version ");
+#else
+ m_comment = wxT("Created by OPJViewer - OpenJPEG version ");
+#endif
+
+#ifdef USE_JPWL
+ m_comment += wxString::Format(wxT("%s with JPWL"), (char *) opj_version());
+#else
+ m_comment += wxString::Format(wxT("%s"), (char *) opj_version());
+#endif
+
+ }
+
+ // decoding engine parameters
+ int m_reducefactor, m_qualitylayers, m_components, m_framenum;
+#ifdef USE_JPWL
+ bool m_enablejpwl;
+ int m_expcomps, m_maxtiles;
+#endif // USE_JPWL
+
+ // encoding engine parameters
+ wxString m_subsampling;
+ wxString m_origin;
+ wxString m_rates;
+ wxString m_quality;
+ bool m_enablequality;
+ bool m_multicomp;
+ bool m_irreversible;
+ int m_resolutions;
+ int m_progression;
+ wxString m_cbsize;
+ wxString m_prsize;
+ wxString m_tsize;
+ wxString m_torigin;
+ /*m_progression
+ m_resilience*/
+ bool m_enablesop;
+ bool m_enableeph;
+ bool m_enablebypass;
+ bool m_enableerterm;
+ bool m_enablerestart;
+ bool m_enablereset;
+ bool m_enablesegmark;
+ bool m_enablevsc;
+ /*m_roicompo
+ m_roiup
+ m_indexfname*/
+ bool m_enableidx;
+ wxString m_index;
+ bool m_enablecomm;
+ wxString m_comment;
+ bool m_enablepoc;
+ wxString m_poc;
+
+#if wxUSE_STREAMS
+ virtual bool LoadFile(wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1);
+ virtual bool SaveFile(wxImage *image, wxOutputStream& stream, bool verbose=true);
+protected:
+ virtual bool DoCanRead(wxInputStream& stream);
+#endif
+
+private:
+ OPJ_PROG_ORDER give_progression(char progression[4]);
+ DECLARE_DYNAMIC_CLASS(wxJPEG2000Handler)
+};
+
+#endif // wxUSE_LIBOPENJPEG
+
+#endif // _WX_IMAGJPEG2000_H_
+
diff --git a/src/bin/wx/OPJViewer/source/imagmxf.cpp b/src/bin/wx/OPJViewer/source/imagmxf.cpp
new file mode 100644
index 00000000..ccfa9f9f
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/imagmxf.cpp
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: imagmxf.cpp
+// Purpose: wxImage MXF (Material eXchange Format) JPEG 2000 file format handler
+// Author: Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik
+// RCS-ID: $Id: imagmxf.cpp,v 0.00 2007/11/19 17:00:00 MW Exp $
+// Copyright: (c) Giuseppe Baruffa
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef USE_MXF
+
+#include "mxflib/mxflib.h"
+using namespace mxflib;
+
+namespace
+{
+ //! Structure holding information about the essence in each body stream
+ struct EssenceInfo
+ {
+ UMIDPtr PackageID;
+ PackagePtr Package;
+ MDObjectPtr Descriptor;
+ };
+ //! Map of EssenceInfo structures indexed by BodySID
+ typedef std::map<UInt32, EssenceInfo> EssenceInfoMap;
+
+ //! The map of essence info for this file
+ EssenceInfoMap EssenceLookup;
+};
+
+//! Build an EssenceInfoMap for the essence in a given file
+/*! \return True if al OK, else false
+ */
+bool BuildEssenceInfo(MXFFilePtr &File, EssenceInfoMap &EssenceLookup);
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#if wxUSE_IMAGE && wxUSE_LIBOPENJPEG
+
+#include "imagmxf.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/intl.h"
+ #include "wx/bitmap.h"
+ #include "wx/module.h"
+#endif
+
+
+#include "libopenjpeg/openjpeg.h"
+
+
+#include "wx/filefn.h"
+#include "wx/wfstream.h"
+
+// ----------------------------------------------------------------------------
+// types
+// ----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// wxMXFHandler
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxMXFHandler,wxImageHandler)
+
+#if wxUSE_STREAMS
+
+#include <stdarg.h>
+#define MAX_MESSAGE_LEN 200
+
+//------------- MXF Manager
+
+// Debug and error messages
+
+//! Display a warning message
+void mxflib::warning(const char *Fmt, ...)
+{
+ char msg[MAX_MESSAGE_LEN];
+ va_list args;
+
+ va_start(args, Fmt);
+ _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
+ va_end(args);
+
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[WARNING_MXF] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+//! Display an error message
+void mxflib::error(const char *Fmt, ...)
+{
+ char msg[MAX_MESSAGE_LEN];
+ va_list args;
+
+ va_start(args, Fmt);
+ _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
+ va_end(args);
+
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[ERROR_MXF] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+//! Display an error message
+void mxflib::debug(const char *Fmt, ...)
+{
+ char msg[MAX_MESSAGE_LEN];
+ va_list args;
+
+ va_start(args, Fmt);
+ _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
+ va_end(args);
+
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[DEBUG_MXF] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+
+
+//------------- JPEG 2000 Data Source Manager
+
+#define J2K_CFMT 0
+#define JP2_CFMT 1
+#define JPT_CFMT 2
+#define MJ2_CFMT 3
+#define PXM_DFMT 0
+#define PGX_DFMT 1
+#define BMP_DFMT 2
+#define YUV_DFMT 3
+
+/* sample error callback expecting a FILE* client object */
+void mxf_error_callback(const char *msg, void *client_data) {
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[ERROR] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+/* sample warning callback expecting a FILE* client object */
+void mxf_warning_callback(const char *msg, void *client_data) {
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[WARNING] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+/* sample debug callback expecting no client object */
+void mxf_info_callback(const char *msg, void *client_data) {
+ int message_len = strlen(msg) - 1;
+ if (msg[message_len] != '\n')
+ message_len = MAX_MESSAGE_LEN;
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+ wxLogMessage(wxT("[INFO] %.*s"), message_len, msg);
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+}
+
+
+/////////////////////////////////////////////////
+/////////////////////////////////////////////////
+
+// load the mxf file format
+bool wxMXFHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)
+{
+ opj_dparameters_t parameters; /* decompression parameters */
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_image_t *opjimage = NULL;
+ unsigned char *src = NULL;
+ unsigned char *ptr;
+ int file_length, j2k_point, j2k_len;
+ opj_codestream_info_t cstr_info; /* Codestream information structure */
+
+ // simply display the version of the library
+ wxLogMessage(wxT("Version of MXF: %s "), wxString::FromAscii(LibraryVersion().c_str()));
+ //wxLogMessage(wxT("MXF file name: %s"), m_filename.GetFullPath());
+
+ // open MXF file
+ MXFFilePtr TestFile = new MXFFile;
+ if (! TestFile->Open(m_filename.GetFullPath().c_str(), true))
+ {
+ wxLogError(wxT("Could not find %s"), m_filename.GetFullPath().c_str());
+ return false;
+ } else
+ wxLogMessage(wxT("Found %s"), m_filename.GetFullPath().c_str());
+
+ // Get the size
+ TestFile->SeekEnd();
+ wxLogMessage(wxT("Size is %d bytes"), TestFile->Tell());
+ TestFile->Seek(0);
+
+ // essence information
+ //BuildEssenceInfo(TestFile, EssenceLookup);
+
+ // close MXF file
+ TestFile->Close();
+
+ return false;
+
+ // destroy the image
+ image->Destroy();
+
+ /* handle to a decompressor */
+ opj_dinfo_t* dinfo = NULL;
+ opj_cio_t *cio = NULL;
+
+ /* configure the event callbacks (not required) */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = mxf_error_callback;
+ event_mgr.warning_handler = mxf_warning_callback;
+ event_mgr.info_handler = mxf_info_callback;
+
+ /* set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* prepare parameters */
+ strncpy(parameters.infile, "", sizeof(parameters.infile)-1);
+ strncpy(parameters.outfile, "", sizeof(parameters.outfile)-1);
+ parameters.decod_format = J2K_CFMT;
+ parameters.cod_format = BMP_DFMT;
+ if (m_reducefactor)
+ parameters.cp_reduce = m_reducefactor;
+ if (m_qualitylayers)
+ parameters.cp_layer = m_qualitylayers;
+ /*if (n_components)
+ parameters. = n_components;*/
+
+ /* JPWL only */
+#ifdef USE_JPWL
+ parameters.jpwl_exp_comps = m_expcomps;
+ parameters.jpwl_max_tiles = m_maxtiles;
+ parameters.jpwl_correct = m_enablejpwl;
+#endif /* USE_JPWL */
+
+ /* get a decoder handle */
+ dinfo = opj_create_decompress(CODEC_J2K);
+
+ /* find length of the stream */
+ stream.SeekI(0, wxFromEnd);
+ file_length = (int) stream.TellI();
+
+ /* search for the m_framenum codestream position and length */
+ //jp2c_point = searchjp2c(stream, file_length, m_framenum);
+ //jp2c_len = searchjp2c(stream, file_length, m_framenum);
+ j2k_point = 0;
+ j2k_len = 10;
+
+ // malloc memory source
+ src = (unsigned char *) malloc(j2k_len);
+
+ // copy the jp2c
+ stream.SeekI(j2k_point, wxFromStart);
+ stream.Read(src, j2k_len);
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using user parameters */
+ opj_setup_decoder(dinfo, &parameters);
+
+ /* open a byte stream */
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, j2k_len);
+
+ /* decode the stream and fill the image structure */
+ opjimage = opj_decode_with_info(dinfo, cio, &cstr_info);
+ if (!opjimage) {
+ wxMutexGuiEnter();
+ wxLogError(wxT("MXF: failed to decode image!"));
+ wxMutexGuiLeave();
+ opj_destroy_decompress(dinfo);
+ opj_cio_close(cio);
+ free(src);
+ return false;
+ }
+
+ /* close the byte stream */
+ opj_cio_close(cio);
+
+ /* common rendering method */
+#include "imagjpeg2000.cpp"
+
+ wxMutexGuiEnter();
+ wxLogMessage(wxT("MXF: image loaded."));
+ wxMutexGuiLeave();
+
+ /* close openjpeg structs */
+ opj_destroy_decompress(dinfo);
+ opj_image_destroy(opjimage);
+ free(src);
+
+ if (!image->Ok())
+ return false;
+ else
+ return true;
+
+}
+
+// save the mxf file format
+bool wxMXFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
+{
+ wxLogError(wxT("MXF: Couldn't save movie -> not implemented."));
+ return false;
+}
+
+#ifdef __VISUALC__
+ #pragma warning(default:4611)
+#endif /* VC++ */
+
+// recognize the MXF JPEG 2000 starting box
+bool wxMXFHandler::DoCanRead( wxInputStream& stream )
+{
+ unsigned char hdr[4];
+
+ if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+ return false;
+
+ return (hdr[0] == 0x06 &&
+ hdr[1] == 0x0E &&
+ hdr[2] == 0x2B &&
+ hdr[3] == 0x34);
+}
+
+//! Build an EssenceInfoMap for the essence in a given file
+/*! \return True if al OK, else false
+ */
+bool BuildEssenceInfo(MXFFilePtr &File, EssenceInfoMap &EssenceLookup)
+{
+ // Empty any old data
+ EssenceLookup.clear();
+
+ // Get the master metadata set (or the header if we must)
+ PartitionPtr MasterPartition = File->ReadMasterPartition();
+ if(!MasterPartition)
+ {
+ File->Seek(0);
+ MasterPartition = File->ReadPartition();
+ warning("File %s does not contain a cloased copy of header metadata - using the open copy in the file header\n", File->Name.c_str());
+ }
+
+ if(!MasterPartition)
+ {
+ error("Could not read header metadata from file %s\n", File->Name.c_str());
+ return false;
+ }
+
+ // Read and parse the metadata
+ MasterPartition->ReadMetadata();
+ MetadataPtr HMeta = MasterPartition->ParseMetadata();
+
+ if(!HMeta)
+ {
+ error("Could not read header metadata from file %s\n", File->Name.c_str());
+ return false;
+ }
+
+ /* Scan the Essence container data sets to get PackageID to BodySID mapping */
+ MDObjectPtr ECDSet = HMeta[ContentStorage_UL];
+ if(ECDSet) ECDSet = ECDSet->GetLink();
+ if(ECDSet) ECDSet = ECDSet[EssenceContainerDataBatch_UL];
+ if(!ECDSet)
+ {
+ error("Header metadata in file %s does not contain an EssenceContainerData set\n", File->Name.c_str());
+ return false;
+ }
+
+ MDObject::iterator it = ECDSet->begin();
+ while(it != ECDSet->end())
+ {
+ MDObjectPtr ThisECDSet = (*it).second->GetLink();
+ MDObjectPtr PackageID;
+ if(ThisECDSet) PackageID = ThisECDSet->Child(LinkedPackageUID_UL);
+ if(PackageID)
+ {
+ EssenceInfo NewEI;
+ NewEI.PackageID = new UMID(PackageID->PutData()->Data);
+
+ // Inset the basic essence info - but not if this is external essence (BodySID == 0)
+ UInt32 BodySID = ThisECDSet->GetUInt(BodySID_UL);
+ if(BodySID) EssenceLookup[BodySID] = NewEI;
+ }
+ it++;
+ }
+
+ /* Now find the other items for the essence lookup map */
+ if(EssenceLookup.size())
+ {
+ PackageList::iterator it = HMeta->Packages.begin();
+ while(it != HMeta->Packages.end())
+ {
+ // Only Source Packages are of interest
+ if((*it)->IsA(SourcePackage_UL))
+ {
+ MDObjectPtr Descriptor = (*it)->Child(Descriptor_UL);
+ if(Descriptor) Descriptor = Descriptor->GetLink();
+
+ if(Descriptor)
+ {
+ MDObjectPtr PackageID = (*it)->Child(PackageUID_UL);
+ if(PackageID)
+ {
+ UMIDPtr TheID = new UMID(PackageID->PutData()->Data);
+
+ /* Now do a lookup in the essence lookup map (it will need to be done the long way here */
+ EssenceInfoMap::iterator EL_it = EssenceLookup.begin();
+ while(EL_it != EssenceLookup.end())
+ {
+ if((*((*EL_it).second.PackageID)) == (*TheID))
+ {
+ // If found, set the missing items and stop searching
+ (*EL_it).second.Package = (*it);
+ (*EL_it).second.Descriptor = Descriptor;
+ break;
+ }
+ EL_it++;
+ }
+ }
+ }
+ }
+
+ it++;
+ }
+ }
+
+ return true;
+}
+
+
+#endif // wxUSE_STREAMS
+
+#endif // wxUSE_LIBOPENJPEG
+
+#endif // USE_MXF
+
diff --git a/src/bin/wx/OPJViewer/source/imagmxf.h b/src/bin/wx/OPJViewer/source/imagmxf.h
new file mode 100644
index 00000000..62158b4f
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/imagmxf.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Universita degli studi di Perugia (UPG), Italy
+ * 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.
+ */
+/////////////////////////////////////////////////////////////////////////////
+// Name: imagmxf.h
+// Purpose: wxImage MXF (Material eXchange Format) JPEG 2000 file format handler
+// Author: G. Baruffa - based on imagjpeg.h, Vaclav Slavik
+// RCS-ID: $Id: imagmj2.h,v 0.0 2007/11/19 17:00:00 VZ Exp $
+// Copyright: (c) Giuseppe Baruffa
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_IMAGMXF_H_
+#define _WX_IMAGMXF_H_
+
+#ifdef USE_MXF
+
+#include "wx/defs.h"
+#include "wx/filename.h"
+
+//-----------------------------------------------------------------------------
+// wxMXFHandler
+//-----------------------------------------------------------------------------
+
+#if wxUSE_LIBOPENJPEG
+
+#include "wx/image.h"
+#include "libopenjpeg/openjpeg.h"
+
+#define wxBITMAP_TYPE_MXF 51
+
+class WXDLLEXPORT wxMXFHandler: public wxImageHandler
+{
+public:
+ inline wxMXFHandler()
+ {
+ m_name = wxT("MXF JPEG 2000 file format");
+ m_extension = wxT("mxf");
+ m_type = wxBITMAP_TYPE_MXF;
+ m_mime = wxT("image/mxf");
+
+ m_reducefactor = 0;
+ m_qualitylayers = 0;
+ m_components = 0;
+ m_filename = wxT("");
+#ifdef USE_JPWL
+ m_enablejpwl = true;
+ m_expcomps = JPWL_EXPECTED_COMPONENTS;
+ m_maxtiles = JPWL_MAXIMUM_TILES;
+#endif // USE_JPWL
+ }
+
+ // decoding engine parameters
+ int m_reducefactor, m_qualitylayers, m_components, m_framenum;
+ wxFileName m_filename;
+#ifdef USE_JPWL
+ bool m_enablejpwl;
+ int m_expcomps, m_maxtiles;
+#endif // USE_JPWL
+
+#if wxUSE_STREAMS
+ virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
+ virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
+protected:
+ virtual bool DoCanRead( wxInputStream& stream );
+#endif
+
+private:
+ DECLARE_DYNAMIC_CLASS(wxMXFHandler)
+};
+
+#endif // wxUSE_LIBOPENJPEG
+
+#endif // USE_MXF
+
+#endif // _WX_IMAGMXF_H_
+
diff --git a/src/bin/wx/OPJViewer/source/license.txt b/src/bin/wx/OPJViewer/source/license.txt
new file mode 100644
index 00000000..6409db44
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/license.txt
@@ -0,0 +1,14 @@
+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, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditionsare 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. \ No newline at end of file
diff --git a/src/bin/wx/OPJViewer/source/opj_logo.xpm b/src/bin/wx/OPJViewer/source/opj_logo.xpm
new file mode 100644
index 00000000..c64d0a7b
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/opj_logo.xpm
@@ -0,0 +1,285 @@
+/* XPM */
+static char *opj_logo[] = {
+/* columns rows colors chars-per-pixel */
+"90 61 218 2",
+" c #BE3D12",
+". c #BF461D",
+"X c #AD5435",
+"o c #B64925",
+"O c #B54E2B",
+"+ c #BC4620",
+"@ c #BB4B25",
+"# c #BC4E29",
+"$ c #B5502F",
+"% c #BD512C",
+"& c #B45334",
+"* c #B35638",
+"= c #B45B3D",
+"- c #BB5533",
+"; c #BE5937",
+": c #BC5C3D",
+"> c #9C766A",
+", c #AD5D42",
+"< c #B55F41",
+"1 c #BA5E40",
+"2 c #A7634D",
+"3 c #A76C57",
+"4 c #AA6750",
+"5 c #AC6B56",
+"6 c #AA6E5A",
+"7 c #A4705E",
+"8 c #B46045",
+"9 c #B1644B",
+"0 c #BD6244",
+"q c #B96448",
+"w c #BC694D",
+"e c #B36B53",
+"r c #B26E58",
+"t c #BB6C52",
+"y c #B2725D",
+"u c #BD7056",
+"i c #BB745C",
+"p c #A67566",
+"a c #A57B6D",
+"s c #AE7562",
+"d c #AB7867",
+"f c #AA7C6C",
+"g c #A07E73",
+"h c #AA7F71",
+"j c #B37661",
+"k c #B47863",
+"l c #B27D6B",
+"z c #BB7863",
+"x c #BA7E69",
+"c c #C73605",
+"v c #C63A0B",
+"b c #CB3300",
+"n c #CA3807",
+"m c #C93A0A",
+"M c #C43E11",
+"N c #C93E10",
+"B c #C44115",
+"V c #C3441A",
+"C c #C4481E",
+"Z c #CA4113",
+"A c #C94519",
+"S c #CB481C",
+"D c #C24A23",
+"F c #C24F28",
+"G c #CD4D23",
+"H c #C4522D",
+"J c #CB532B",
+"K c #C25632",
+"L c #C35936",
+"P c #C25C3B",
+"I c #C85630",
+"U c #CB5933",
+"Y c #CB5E3A",
+"T c #D05026",
+"R c #CC613D",
+"E c #C26343",
+"W c #C46748",
+"Q c #C1694C",
+"! c #CD6744",
+"~ c #CA6C4D",
+"^ c #C37155",
+"/ c #C4755B",
+"( c #CB7356",
+") c #C8765B",
+"_ c #D06D4C",
+"` c #D07253",
+"' c #D47B5E",
+"] c #C37B63",
+"[ c #C27E68",
+"{ c #C97F68",
+"} c #A68175",
+"| c #A48479",
+" . c #AD8172",
+".. c #AD8578",
+"X. c #AB897D",
+"o. c #B1806F",
+"O. c #BA816F",
+"+. c #B38373",
+"@. c #B58778",
+"#. c #B3897B",
+"$. c #BA8472",
+"%. c #BB8C7C",
+"&. c #C2816B",
+"*. c #CD846C",
+"=. c #C38470",
+"-. c #C38976",
+";. c #C38D7B",
+":. c #CC8973",
+">. c #CF8F7A",
+",. c #CB907D",
+"<. c #D1937F",
+"1. c #948E8C",
+"2. c #9D8C86",
+"3. c #9D8F89",
+"4. c #96908E",
+"5. c #9C918D",
+"6. c #949392",
+"7. c #9B9492",
+"8. c #9D9997",
+"9. c #9D9C9C",
+"0. c #A38B83",
+"q. c #AA8D83",
+"w. c #A4918B",
+"e. c #AC9087",
+"r. c #AB938C",
+"t. c #A49590",
+"y. c #A29996",
+"u. c #A19D9C",
+"i. c #AA9790",
+"p. c #AC9994",
+"a. c #AC9E99",
+"s. c #B18D81",
+"d. c #B59084",
+"f. c #B49389",
+"g. c #BA9184",
+"h. c #B89589",
+"j. c #BA988D",
+"k. c #B29B93",
+"l. c #BC9C92",
+"z. c #ACA19D",
+"x. c #B1A19D",
+"c. c #BCA39B",
+"v. c #A3A3A3",
+"b. c #ABA5A3",
+"n. c #AEA9A7",
+"m. c #ABABAA",
+"M. c #B3A5A1",
+"N. c #B3A9A6",
+"B. c #B3ADAA",
+"V. c #B9A6A0",
+"C. c #B9AAA5",
+"Z. c #BAADA9",
+"A. c #B4B0AF",
+"S. c #BAB0AD",
+"D. c #B4B3B3",
+"F. c #BAB5B3",
+"G. c #BDB8B6",
+"H. c #BBBBBB",
+"J. c #C39384",
+"K. c #C0978A",
+"L. c #C2998B",
+"P. c #CA9483",
+"I. c #CD9A8A",
+"U. c #C19D92",
+"Y. c #D69B89",
+"T. c #DB9680",
+"R. c #C2A095",
+"E. c #C4A69C",
+"W. c #CCA193",
+"Q. c #C8A599",
+"!. c #CBA99D",
+"~. c #C6AEA6",
+"^. c #CCACA2",
+"/. c #CBB2AB",
+"(. c #C3B8B5",
+"). c #C2BDBC",
+"_. c #C9B9B3",
+"`. c #D3ADA0",
+"'. c #D3B4A9",
+"]. c #DCB2A4",
+"[. c #DEB6A8",
+"{. c #D1BFB9",
+"}. c #D9BEB5",
+"|. c #C5C0BE",
+" X c #CDC0BC",
+".X c #D2C1BB",
+"XX c #DDC3BB",
+"oX c #E0C5BC",
+"OX c #E0C8BF",
+"+X c #C2C2C2",
+"@X c #CBC4C2",
+"#X c #CDC8C6",
+"$X c #CCCBCB",
+"%X c #D2C6C2",
+"&X c #D1CECD",
+"*X c #DDC8C1",
+"=X c #DECFCA",
+"-X c #D9D1CE",
+";X c #D3D3D3",
+":X c #D9D5D4",
+">X c #DED9D7",
+",X c #DBDBDB",
+"<X c #E1CAC3",
+"1X c #E2CFC8",
+"2X c #E1D3CE",
+"3X c #E2D5D0",
+"4X c #E5D8D3",
+"5X c #E4DDDB",
+"6X c #E8DBD6",
+"7X c #EADEDA",
+"8X c #E6E0DE",
+"9X c #EBE0DC",
+"0X c #E4E4E4",
+"qX c #E8E2E0",
+"wX c #EBEBEB",
+"eX c #F0EAE8",
+"rX c #F3F3F3",
+"tX c #FEFEFE",
+/* pixels */
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXrXrXtXrXrXrXrXrXrXrXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXrXtXrXrXrXwXwXrXwXrXrXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXrXrXrXwXwX0X0XqX0X0X0X0XwXwXwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXrXtXrXwXwX2X[.[.].].].].].1XwXrXwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXrXrXrXwX0X0XL.J b b b b b b b J '.0X0XwXwXrXrXrXrXrXrXrXrXrXrXtXrXrXrXtXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXrXrXwX0XXXt m b m B V N b b v >.;X0XwXwXwXwXrXwXwXrXrXrXrXtXrXtXrXrXrXwXrXrXrXrXrXrXrXrXrXrXrXwXrXrXwXrXrXrXtXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXrXrXrX0X,X'.S b b P l.z.M.k.w n b b g.;X,X,X,X0X0X0X0X0XwXwXwXwXwXwXwXwXwX0X0X0XwX0X0XwXwXwXwX0X0X0X0X0X0XwXwXwXwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXrXrXwX0X:XT.m b A ] G.D.D.m.$.m b b $.$X&X.X}.XX>XOX}.oXXX<X0X0XwXwXwX0X2XXXoXXXoXOX5X0XwX0X1XoXXX5X*X}.}.oX<XqXrXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXrXwX0X,XL.b b D M.H.D.D.D.D.m.L b b W H.Z.# b Y / m b b b Z P.:X:X:X$X:.Z b b b b n :.;X;X;XR b A &.Z b b b b *.wXwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXrXwX0X:X$.b b E B.H.H.D.D.D.D.P b b E H.V.. b U L v v n b b ( #X;X$X~.Y b m N m b b ! {.&X#XI b C R v v n b b ! 0XwXrXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXwX0X:X!.A b Z F.H.H.H.H.H.D.m.L b b e b.+.b b V k i.r.t n b b s.H.x v b L q.b.p.D b b t F.$.n b M l a.M.y b b A :X0XwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXwX0X:XL.m b D H.).H.+XH.H.H.D.H b b 6 v.j b b - a.A.m.@.m b b h D.< b b w z.b.b.P b b q B.z b b @ B.D.m...v b G :X,XwXwXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwX0X,X&X/ b b , D.H.+X+X+X+XH.f.B b b 5.8.M b M w.v.v.v.r.D b b h l v b b M V v b b q u.X b n @.v.m.v.j b b Q &X,X0XwXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwX0X,X$X^ b b , H.H.+X+XH.H.H.s.N b n 7.7.v b B 8.v.v.v.w.M b b g r b b b n n n b b b b e y.O b n X.m.v.n.e b b u &X,X0XrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrX0X,X$X/ b b + F.H.H.H.+XH.d.b b M | 8.> c b @ 9.v.9.u., b b - 3.& b b 7 1.1.4.4.4.6.7.9.w.m b + t.v.m.p.D b b K.;X,X0XwXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwX0X,X$X-.b b b i D.H.G.H.J.N b b = 9.9.5 c b B 7.9.v.y.b b m f 4.O b b 3 6.6.6.g 9 4 h u.h b b - b.m.m.s.b b N ~.;X,X0XwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwX0X,X;XE.G b b I z ] ] ] W n b H l 9.8.9 b b m e 6 r e b b # 0.y.< b b O 6 p 6 < # ; q.v.t b b 0 n.A.A.+.b b H _.;X,XwXwXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwXwX,X;X#Xf.b b b b b b b b b - a.v.v.w.@ b b v b b b b b @ b.m.v.w.M b b b b b b v ..m.n.A b n g.H.H.H.4 b b [ &X,X0XwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXwXwX0X:X$XZ.Q H v n b m B H E x n.m.m.q.B b v < . v N + E z m.m.m.b.e - M m v M - t k.D.m.; # - V.H.+XH.s # # K.:X,X0XwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXwXwX,X,X$X+XG.Z.Z.B.C.S.F.H.H.H.D.D.j b b q v.b.a.n.B.H.H.+X+X+XH.H.D.Z.C.Z.Z.F.H.H.+X+XH.).H.$X&X&X;X$X#X#X:X,X0XwXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXrXwX0X,X;X#X+X+X+XH.H.+X+X+XH.H.H.D.e b n i n.m.D.H.H.+X#X$X$X+X+X+X+XH.H.H.H.+X+X+X$X&X&X&X$X;X;X;X:X;X:X,X,X0XwXwXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXrXrXwXwX,X,X;X;X$X$X$X;X;X&X;X$X#X+XF b v s.H.H.+X$X&X;X;X,X,X,X;X:X;X;X;X;X;X;X:X,X,X,X0X,X0X,X0X0X0X0X0X0X0XwXwXrXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXrXtXrXwXwX0X,X:X;X;X;X;X;X:X;X;X;X$X+XC b B k.+X+X$X$X;X,X,X0X0X0X0X0X;X,X,X,X,X,X,X,X,X0X0X0X0X0X0XwX0X0X0XwXwXrXrXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXrXrXrXrXwXwXwX0X0X0X0X0X0X0X,X,X:X^.^.!.$X$X;X,X,X0XwXwXwXwXwXwXwXwX0X0X0X0XwXwXwXwXwXwXrXrXwXrXrXrXrXrXrXrXrXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXrXrXrXrXwXwXwXwX0XwXwXwX0X0X,X:X;X$X&X&X;X,X,X0XwXwXwXrXrXrXrXrXwXwXwXwXwXwXwXrXrXrXwXrXrXrXrXrXrXrXrXrXrXtXrXtXtXrXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXrXrXrXrXrXrXrXrXrXwXwXwXwX0X,X0X0X0XwXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXwXrXrXrXrXrXtXrXrXrXtXrXrXrXrXrXrXrXrXrXtXtXtXrXrXtXtXtXtXrXrXtXrXrXtXrXtXrXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXrXtXtXrXtXrXrXrXrXrXrXwXwXwX0XwX0XwXwXwXrXrXrXtXtXrXrXrXrXrXrXrXrXwXrXwXrXwXwXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXrXtXrXrXtXtXrXrXrXrXrXrXrXrXrXrXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXwXrXrXrXrXrXrXtXrXtXrXrXrXrXrXwXwXwXwXwX0X0XwX0XwXwXwXwXwXwXwXrXwXwXwX0X0X0X0XwX0XwXwXrXrXrXwXrXwXwXwX0XwX0XwXwXwXrXrXrXrXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrXrXrXrXrXtXtXrXrXtXrXrXeX7X7X9XwXwXwX5X3X3X3X2X2X2X5X0XwXwXwXwXwX8X3X3X2X2X2X2X2X3X6X6X7XwXwXwXwXwXwX7X1XXXOXOX1X8XwXwXrXrXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXtXtXrXrXrXwXT.T T :.,X,X-X` G G G G G G U _ J.-X,X,X,X[ G G G G G G G G G G _ >XwX0X,X&XI.R N b b b m ! `.5XwXrXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXtXtXrXtXrXrXrXwX0X' b b ] >X,X%XJ b b b b b b b b Q {.:X;X:Xq b b b b b b b b b b Y >X0X,X-X'.^ n b b b b b m *.1XwXwXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrX0X0X%XL b b L.@X+X-.b b M L L L D b b b M V.+X(.N b b D H H H H H U U W.;X&X^.H b b n W -.-.W n b b J &XwXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXwXwX0X XF b b U.+X+X[ b b D z z j P v b b N U.H.S.m b m E Q t ^ ) / ) ) /.$X$X;.m b n A %.H.H.J.N b b N .XwXwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXwXwX,X:X!.m b L N.D.m.* b b y v.v.v.v.p.n b M f.m.w b b D u.v.m.m.D.G.H.H.+X).g.b b B j.F.D.D.D.D.l.; F I /.0XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXwX,X:XU.n b E B.A.n.$ b b s v.9.v.v.r.n n M r.b.1 b b D u.v.m.m.D.D.H.H.).H.k b b # M.G.D.D.D.D.Z.t w u _.0XwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXwXwX,X;X$XJ b m h b.v.i.m b M a 5.5.2.p M b c < 8.2.+ b b M o o o o # % j G.H.g.m b A M.D.D.D.B.M.M.M.M.Z.(.:X0XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrXrXwX,X,X&X(.n b M 0.v.v.s b b b b b n b b c b M u.v.g M b b b b b b b b b i G.D.0 b b 8 D.D.H.G.P n b b n b U :X,XwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrXwX0X,X;X$XV.n b M w.v.9.< b b b b b b b b c H r 9.v.a n b * < < w w Q Q g.D.B.: b b r D.D.D.m.C b b b b b ) ;X0XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrX6XP.=.K.;X#X+Xx n b D v.u.7.. b b M D . D & 2 q.b.b.v.v.< b b X 6.9.9.b.m.D.D.D.D.n.# b b f D.D.D.b.= 1 * N b n !.;X,XwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXrXrXwX<X~ P x $X+XH.z b b - v.v.3.M b b < r r r k 0.a.m.m.m.v.# b b , 6.9.v.m.D.D.D.H.D.z.O b b s D.D.D.N.f l 9 v b M ~.;X,XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXrXwX0XY.n b e H.H.V.F b b p b.v.h v b v v.m.A.D.H.+X+X+XH.D.p.b b m p 9.v.m.D.D.H.H.H.D.N.- b b - m.A.D.A.m.a.B b b - (.:X0XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXwXwX0XY.n b ; Z.C.$.A b v 0.m.m.l n b M m.D.D.H.+X#X+X+XH.H.r.b b m < d l l l $.;.J.V.H.B.w b b C @.s.a.k.#.j n b b : ).:X,XwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXwXwX0X'.N b b A B n b n z m.D.B.0 b b 9 H.H.+X$X;X:X;X$X$X+Xl b b b b b b b b b b b s.H.H.B.H b b b n Z Z b b V n b ] $X:X0XwXrXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXwX0X,X.XR b b b b b A P d.D.D.C.H b b j H.$X$X;X:X,X,X;X;X+X/ b b b b b b b b b b b a.H.H.D.u G b b b b b B H : v m ;.$X,XwXwXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXwXwX,X:X Xg.j 5 y s.C.H.H.+X+X|.E.Q.Q. X;X;X,X0XwXwX0X0X,X;X/.U.j.h.g.f.h.j.U.U.U.!.$X$X+X+XH.Z.g.y 4 6 l x.D.A.l.~.#X,X0XwXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXwX0X:X$XG.k.e.f.B.H.H.+X$X$X$X#X$X$X;X;X,X0XwXwXwXwX0X0X;X$X+XH.D.D.D.F.H.+X+X#X&X$X;X$X$X+X+XA.r.X.e.a.H.H.H.+X+X;X,X0XwXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXwX,X,X$X&X$X$X$X$X;X;X,X,X,X,X,X,X0XwXwXwXrXtXrXrXwXwX0X,X;X$X$X+X$X$X$X;X;X:X,X,X,X,X,X;X$X&X#X#X$X$X$X$X$X;X,X,X0XwXrXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXwXwX0X,X:X;X;X$X;X;X:X,X,X0X0X,X0X0X0XwXwXwXrXrXtXrXrXwXwX0X;X;X$X&X$X$X&X:X,X,X,X,X0X,X,X:X;X;X$X$X$X$X$X;X:X,X,X0XwXwXrXrXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXrXwXwXwX0X0X0X0X0X0XwXwXwXwXwXwXwXwXrXwXrXtXtXrXtXtXrXrXrXwX0X0X0X0X,X,X0X0X0X0XwXwXwXwXwXwX0X0X0X,X,X,X,X0X0XwXwXwXrXtXrXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrXwXwX0X0X0X0X0XwXwXwXrXwXrXrXrXrXrXtXrXtXtXtXtXrXrXrXwXwXwX0X0X0X0X0X0X0XwXwXwXwXwXwXwXwXwX0X0X0X0XwXwXwXwXwXrXrXrXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXrXrXrXrXrXrXrXrXrXrXtXtXrXtXtXrXtXtXtXtXtXtXtXrXtXrXtXrXrXrXrXwXwXrXrXrXrXrXrXrXtXrXrXrXrXrXrXrXwXrXrXrXrXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXrXtXrXrXrXrXrXrXtXtXrXtXrXtXrXrXtXtXtXtXtXtXtXtXtXtXtXrXrXrXrXrXrXrXrXrXrXrXtXtXrXtXrXrXtXrXrXrXrXrXrXrXrXtXrXrXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX",
+"tXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtXtX"
+};
diff --git a/src/bin/wx/OPJViewer/source/readmeafter.txt b/src/bin/wx/OPJViewer/source/readmeafter.txt
new file mode 100644
index 00000000..87c122be
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/readmeafter.txt
@@ -0,0 +1,34 @@
+This viewer is conceived to open and display information and image content of J2K, JP2,
+and MJ2 files.
+The viewer application interface is divided into three main panels:
+- a browsing pane;
+- a viewing pane;
+- a log/peek pane.
+
+The browsing pane will present the markers or boxes hierarchy, with position (byte number where marker/box starts and stops) and length information (i.e., inner length as signalled by marker/box and total length, with marker/box sign included), in the following form:
+
+filename
+|
+|_ #000: Marker/Box short name (Hex code)
+| |
+| |_ *** Marker/Box long name ***
+| |_ startbyte > stopbyte, inner_length + marker/box sign length (total length)
+| |_ Additional info, depending on the marker/box type
+| |_ ...
+|
+|_ #001: Marker/Box short name (Hex code)
+| |
+| |_ ...
+|
+...
+
+
+The viewing pane will display the decoded image contained in the JPEG 2000 file.
+It should display correctly images as large as 4000x2000, provided that a couple of GB of RAM are available. Nothing is known about the display of larger sizes: let us know if you manage to get it working.
+
+
+The log/peek pane is shared among two different subpanels:
+
+- the log panel will report a lot of debugging info coming out from the wx GUI as well as from the openjpeg library
+- the peek pane tries to give a peek on the codestream/file portion which is currently selected in the browsing pane. It shows both hex and ascii values corresponding to the marker/box section.
+
diff --git a/src/bin/wx/OPJViewer/source/readmebefore.txt b/src/bin/wx/OPJViewer/source/readmebefore.txt
new file mode 100644
index 00000000..a59b0e87
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/readmebefore.txt
@@ -0,0 +1,11 @@
+What is OpenJPEG ?
+==================
+The OpenJPEG library is an open-source JPEG 2000 codec written in C language. It has been developed in order to promote the use of JPEG 2000, the new still-image compression standard from the Joint Photographic Experts Group (JPEG). In addition to the basic codec, various other features are under development, among them the JP2 and MJ2 (Motion JPEG 2000) file formats, an indexing tool useful for the JPIP protocol, JPWL-tools for error-resilience, a Java-viewer for j2k-images, ...
+
+Who can use the library ?
+=========================
+Anybody. As the OpenJPEG library is released under the BSD license, anybody can use or modify the library, even for commercial applications. The only restriction is to retain the copyright in the sources or the binaries documentation.
+
+Who is developing the library ?
+===============================
+The library is developed by the Communications and Remote Sensing Lab (TELE), in the Université Catholique de Louvain (UCL). The JPWL module is developped and maintained by the Digital Signal Processing Lab (DSPLab) of the University of Perugia, Italy (UNIPG). As our purpose is to make OpenJPEG really useful for those interested in the image compression field, any feedback/advices are obviously welcome ! We will do our best to handle them quickly. \ No newline at end of file
diff --git a/src/bin/wx/OPJViewer/source/wxj2kparser.cpp b/src/bin/wx/OPJViewer/source/wxj2kparser.cpp
new file mode 100644
index 00000000..284c568a
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/wxj2kparser.cpp
@@ -0,0 +1,1465 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
+ * 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 "OPJViewer.h"
+
+/* From little endian to big endian, 2 bytes */
+#define BYTE_SWAP2(X) ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
+#define BYTE_SWAP4(X) ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
+
+/* From codestream to int values */
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \
+ ((unsigned long int) (C)[(P) + 1] << 16) + \
+ ((unsigned long int) (C)[(P) + 2] << 8) + \
+ ((unsigned long int) (C)[(P) + 3] << 0))
+
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \
+ ((unsigned long int) (C)[(P) + 1] << 0))
+
+
+/* Markers values */
+#define J2KMARK_NUM 24
+enum {
+ SOC_VAL = 0xFF4F,
+ SOT_VAL = 0xFF90,
+ SOD_VAL = 0xFF93,
+ EOC_VAL = 0xFFD9,
+ SIZ_VAL = 0xFF51,
+ COD_VAL = 0xFF52,
+ COC_VAL = 0xFF53,
+ RGN_VAL = 0xFF5E,
+ QCD_VAL = 0xFF5C,
+ QCC_VAL = 0xFF5D,
+ POD_VAL = 0xFF5F,
+ TLM_VAL = 0xFF55,
+ PLM_VAL = 0xFF57,
+ PLT_VAL = 0xFF58,
+ PPM_VAL = 0xFF60,
+ PPT_VAL = 0xFF61,
+ SOP_VAL = 0xFF91,
+ EPH_VAL = 0xFF92,
+ COM_VAL = 0xFF64
+#ifdef USE_JPWL
+ , EPB_VAL = 0xFF66,
+ ESD_VAL = 0xFF67,
+ EPC_VAL = 0xFF68,
+ RED_VAL = 0xFF69
+ /*, EPB_VAL = 0xFF96,
+ ESD_VAL = 0xFF98,
+ EPC_VAL = 0xFF97,
+ RED_VAL = 0xFF99*/
+#endif // USE_JPWL
+#ifdef USE_JPSEC
+ , SEC_VAL = 0xFF65
+#endif // USE_JPSEC
+};
+
+// All the markers in one vector
+unsigned short int marker_val[] = {
+ SOC_VAL, SOT_VAL, SOD_VAL, EOC_VAL,
+ SIZ_VAL,
+ COD_VAL, COC_VAL, RGN_VAL, QCD_VAL, QCC_VAL, POD_VAL,
+ TLM_VAL, PLM_VAL, PLT_VAL, PPM_VAL, PPT_VAL,
+ SOP_VAL, EPH_VAL,
+ COM_VAL
+#ifdef USE_JPWL
+ , EPB_VAL, ESD_VAL, EPC_VAL, RED_VAL
+#endif // USE_JPWL
+#ifdef USE_JPSEC
+ , SEC_VAL
+#endif // USE_JPSEC
+};
+
+// Marker names
+static const char *marker_name[] = {
+ "SOC", "SOT", "SOD", "EOC",
+ "SIZ",
+ "COD", "COC", "RGN", "QCD", "QCC", "POD",
+ "TLM", "PLM", "PLT", "PPM", "PPT",
+ "SOP", "EPH",
+ "COM"
+#ifdef USE_JPWL
+ , "EPB", "ESD", "EPC", "RED"
+#endif // USE_JPWL
+#ifdef USE_JPSEC
+ , "SEC"
+#endif // USE_JPSEC
+};
+
+// Marker descriptions
+static const char *marker_descr[] = {
+ "Start of codestream", "Start of tile-part", "Start of data", "End of codestream",
+ "Image and tile size",
+ "Coding style default", "Coding style component", "Region-of-interest", "Quantization default",
+ "Quantization component", "Progression order change, default",
+ "Tile-part lengths, main header", "Packet length, main header", "Packets length, tile-part header",
+ "Packed packet headers, main header", "Packed packet headers, tile-part header",
+ "Start of packet", "End of packet header",
+ "Comment and extension"
+#ifdef USE_JPWL
+ , "Error Protection Block", "Error Sensitivity Descriptor", "Error Protection Capability",
+ "Residual Errors Descriptor"
+#endif // USE_JPWL
+#ifdef USE_JPSEC
+ , "Main security marker"
+#endif // USE_JPSEC
+};
+
+void OPJParseThread::ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid)
+{
+ unsigned short int csiz = 0;
+
+ // check if the file is opened
+ if (m_file->IsOpened())
+ WriteText(wxT("File OK"));
+ else
+ return;
+
+ // position at the beginning
+ m_file->Seek(offset, wxFromStart);
+
+ // navigate the file
+ int m, inside_sod = 0, inside_sop = 0;
+ int nmarks = 0, maxmarks = 10000;
+ unsigned char onebyte[1];
+ unsigned char twobytes[2], firstbyte, secondbyte;
+ unsigned char fourbytes[4];
+ unsigned short int currmark;
+ unsigned short int currlen;
+ int lastPsot = 0, lastsotpos = 0;
+
+ WriteText(wxT("Start search..."));
+
+// advancing macro
+#define OPJ_ADVANCE(A) {offset += A; if (offset < length) m_file->Seek(offset, wxFromStart); else return;}
+
+ // begin search
+ while ((offset < length) && (!m_file->Eof())) {
+
+ // read one byte
+ if (m_file->Read(&firstbyte, 1) != 1)
+ break;
+
+ // look for 0xFF
+ if (firstbyte == 0xFF) {
+
+ // it is a possible marker
+ if (m_file->Read(&secondbyte, 1) != 1)
+ break;
+ else
+ currmark = (((unsigned short int) firstbyte) << 8) + (unsigned short int) secondbyte;
+
+ } else {
+
+ // nope, advance by one and search again
+ OPJ_ADVANCE(1);
+ continue;
+ }
+
+ // search the marker
+ for (m = 0; m < J2KMARK_NUM; m++) {
+ if (currmark == marker_val[m])
+ break;
+ }
+
+ // marker not found
+ if (m == J2KMARK_NUM) {
+ // nope, advance by one and search again
+ OPJ_ADVANCE(1);
+ continue;
+ }
+
+ // if we are inside SOD, only some markers are allowed
+ if (inside_sod) {
+
+ // we are inside SOP
+ if (inside_sop) {
+
+ }
+
+ // randomly marker coincident data
+ if ((currmark != SOT_VAL) &&
+ (currmark != EOC_VAL) &&
+ (currmark != SOP_VAL) &&
+ (currmark != EPH_VAL)) {
+ OPJ_ADVANCE(1);
+ continue;
+ }
+
+ // possible SOT?
+ if ((currmark == SOT_VAL)) {
+ // too early SOT
+ if (offset < (lastsotpos + lastPsot)) {
+ OPJ_ADVANCE(1);
+ continue;
+ }
+ // we were not in the last tile
+ /*if (lastPsot != 0) {
+ OPJ_ADVANCE(1);
+ break;
+ }*/
+ }
+ }
+
+ // beyond this point, the marker MUST BE real
+
+ // length of current marker segment
+ if ((currmark == SOD_VAL) ||
+ (currmark == SOC_VAL) ||
+ (currmark == EOC_VAL) ||
+ (currmark == EPH_VAL))
+
+ // zero length markers
+ currlen = 0;
+
+ else {
+
+ // read length field
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+
+ currlen = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];
+ }
+
+ // here we pass to AppendItem() normal and selected item images (we
+ // suppose that selected image follows the normal one in the enum)
+ int image, imageSel;
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ // append the marker
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("%03d: "), nmarks) +
+ wxString::FromAscii(marker_name[m]) +
+ wxString::Format(wxT(" (0x%04X)"), marker_val[m]),
+ image, imageSel,
+ new OPJMarkerData(wxT("MARK") + wxString::Format(wxT(" (%d)"), marker_val[m]),
+ m_tree->m_fname.GetFullPath(), offset, offset + currlen + 1)
+ );
+
+ // append some info
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ // marker name
+ wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,
+ wxT("*** ") + wxString::FromAscii(marker_descr[m]) + wxT(" ***"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);
+
+ // position and length
+ wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,
+ wxLongLong(offset).ToString() + wxT(" > ") + wxLongLong(offset + currlen + 1).ToString() +
+ wxT(", ") + wxString::Format(wxT("%d + 2 (%d)"), currlen, currlen + 2),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ // give additional info on markers
+ switch (currmark) {
+
+ /////////
+ // SOP //
+ /////////
+ case SOP_VAL:
+ {
+ // read packet number
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ int packnum = STREAM_TO_UINT16(twobytes, 0);
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Pack. no. %d"), packnum),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ inside_sop = 1;
+ };
+ break;
+
+#ifdef USE_JPWL
+ /////////
+ // RED //
+ /////////
+ case RED_VAL:
+ {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char pred = onebyte[0];
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxString address[] = {
+ wxT("Packet addressing"),
+ wxT("Byte-range addressing"),
+ wxT("Packet-range addressing"),
+ wxT("Reserved")
+ };
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ address[(pred & 0xC0) >> 6],
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d bytes range"), (((pred & 0x02) >> 1) + 1) * 2),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ pred & 0x01 ? wxT("Errors/erasures in codestream") : wxT("Error free codestream"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Residual corruption level: %d"), (pred & 0x38) >> 3),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /////////
+ // ESD //
+ /////////
+ case ESD_VAL:
+ {
+ unsigned short int cesd;
+ if (csiz < 257) {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ cesd = onebyte[0];
+ } else {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ cesd = STREAM_TO_UINT16(twobytes, 0);
+ }
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char pesd = onebyte[0];
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ pesd & 0x01 ? wxT("Comp. average") : wxString::Format(wxT("Comp. no. %d"), cesd),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ wxString meth[] = {
+ wxT("Relative error sensitivity"),
+ wxT("MSE"),
+ wxT("MSE reduction"),
+ wxT("PSNR"),
+ wxT("PSNR increase"),
+ wxT("MAXERR (absolute peak error)"),
+ wxT("TSE (total squared error)"),
+ wxT("Reserved")
+ };
+
+ subcurrid = m_tree->AppendItem(currid,
+ meth[(pesd & 0x38) >> 3],
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ wxString address[] = {
+ wxT("Packet addressing"),
+ wxT("Byte-range addressing"),
+ wxT("Packet-range addressing"),
+ wxT("Reserved")
+ };
+
+ subcurrid = m_tree->AppendItem(currid,
+ address[(pesd & 0xC0) >> 6],
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d bytes/value, %d bytes range"), ((pesd & 0x04) >> 2) + 1, (((pesd & 0x02) >> 1) + 1) * 2),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /////////
+ // EPC //
+ /////////
+ case EPC_VAL:
+ {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int pcrc = STREAM_TO_UINT16(twobytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int dl = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char pepc = onebyte[0];
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("CRC-16 = 0x%x"), pcrc),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Tot. length = %d"), dl),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%s%s%s%s"),
+ pepc & 0x10 ? wxT("ESD, ") : wxT(""),
+ pepc & 0x20 ? wxT("RED, ") : wxT(""),
+ pepc & 0x40 ? wxT("EPB, ") : wxT(""),
+ pepc & 0x80 ? wxT("Info") : wxT("")
+ ),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /////////
+ // EPB //
+ /////////
+ case EPB_VAL:
+ {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char depb = onebyte[0];
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int ldpepb = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int pepb = STREAM_TO_UINT32(fourbytes, 0);
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("No. %d, %slatest, %spacked"),
+ depb & 0x3F,
+ depb & 0x40 ? wxT("") : wxT("not "),
+ depb & 0x80 ? wxT("") : wxT("un")),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d bytes protected"), ldpepb),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (pepb == 0x00000000)
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxT("Predefined codes"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ else if ((pepb >= 0x10000000) && (pepb <= 0x1FFFFFFF)) {
+
+ wxString text = wxT("CRC code");
+ if (pepb == 0x10000000)
+ text << wxT(", CCITT (X25) 16 bits");
+ else if (pepb == 0x10000001)
+ text << wxT(", Ethernet 32 bits");
+ else
+ text << wxT(", JPWL RA");
+ subcurrid = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ } else if ((pepb >= 0x20000000) && (pepb <= 0x2FFFFFFF)) {
+
+ wxString text;
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("RS code, RS(%d, %d)"),
+ (pepb & 0x0000FF00) >> 8,
+ (pepb & 0x000000FF)),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ } else if ((pepb >= 0x30000000) && (pepb <= 0x3FFFFFFE))
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxT("JPWL RA"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ else if (pepb == 0xFFFFFFFF)
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxT("No method"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+#endif // USE_JPWL
+
+#ifdef USE_JPSEC
+ case SEC_VAL:
+ {
+
+ }
+ break;
+#endif // USE_JPSEC
+
+ /////////
+ // SIZ //
+ /////////
+ case SIZ_VAL:
+ {
+ int c;
+
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int rsiz = STREAM_TO_UINT16(twobytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int xsiz = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int ysiz = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int xosiz = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int yosiz = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int xtsiz = STREAM_TO_UINT32(fourbytes, 0);
+ this->m_tree->m_childframe->m_twidth = xtsiz;
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int ytsiz = STREAM_TO_UINT32(fourbytes, 0);
+ this->m_tree->m_childframe->m_theight = ytsiz;
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int xtosiz = STREAM_TO_UINT32(fourbytes, 0);
+ this->m_tree->m_childframe->m_tx = xtosiz;
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int ytosiz = STREAM_TO_UINT32(fourbytes, 0);
+ this->m_tree->m_childframe->m_ty = ytosiz;
+
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ csiz = STREAM_TO_UINT16(twobytes, 0);
+
+ bool equaldepth = true, equalsize = true;
+ unsigned char *ssiz = new unsigned char(csiz);
+ unsigned char *xrsiz = new unsigned char(csiz);
+ unsigned char *yrsiz = new unsigned char(csiz);
+
+ for (c = 0; c < csiz; c++) {
+
+ if (m_file->Read(&ssiz[c], 1) != 1)
+ break;
+
+ if (c > 0)
+ equaldepth = equaldepth && (ssiz[c] == ssiz[c - 1]);
+
+ if (m_file->Read(&xrsiz[c], 1) != 1)
+ break;
+
+ if (m_file->Read(&yrsiz[c], 1) != 1)
+ break;
+
+ if (c > 0)
+ equalsize = equalsize && (xrsiz[c] == xrsiz[c - 1]) && (yrsiz[c] == yrsiz[c - 1]) ;
+
+ }
+
+ if (equaldepth && equalsize)
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("I: %dx%d (%d, %d), %d c., %d%s bpp"),
+ xsiz, ysiz,
+ xosiz, yosiz,
+ csiz, ((ssiz[0] & 0x7F) + 1),
+ (ssiz[0] & 0x80) ? wxT("s") : wxT("u")),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ else
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("I: %dx%d (%d, %d), %d c."),
+ xsiz, ysiz,
+ xosiz, yosiz,
+ csiz),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("T: %dx%d (%d, %d)"),
+ xtsiz, ytsiz,
+ xtosiz, ytosiz),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid4 = m_tree->AppendItem(currid,
+ wxT("Components"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ for (c = 0; c < csiz; c++) {
+
+ wxTreeItemId subcurrid5 = m_tree->AppendItem(subcurrid4,
+ wxString::Format(wxT("#%d: %dx%d, %d%s bpp"),
+ c,
+ xsiz/xrsiz[c], ysiz/yrsiz[c],
+ ((ssiz[c] & 0x7F) + 1),
+ (ssiz[c] & 0x80) ? wxT("s") : wxT("u")),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+
+ };
+ break;
+
+ /////////
+ // SOT //
+ /////////
+ case SOT_VAL:
+ {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int isot = STREAM_TO_UINT16(twobytes, 0);
+
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ unsigned long int psot = STREAM_TO_UINT32(fourbytes, 0);
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char tpsot = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char tnsot = onebyte[0];
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("tile %d, psot = %d, part %d of %d"), isot, psot, tpsot, tnsot),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ lastPsot = psot;
+ lastsotpos = offset;
+ inside_sod = 0;
+ };
+ break;
+
+ /////////
+ // COC //
+ /////////
+ case COC_VAL:
+ {
+ unsigned short int ccoc;
+ if (csiz < 257) {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ ccoc = onebyte[0];
+ } else {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ ccoc = STREAM_TO_UINT16(twobytes, 0);
+ }
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char scoc = onebyte[0];
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Comp. no. %d"), ccoc),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ wxString text;
+ if (scoc & 0x01)
+ text << wxT("Partitioned entropy coder");
+ else
+ text << wxT("Unpartitioned entropy coder");
+
+ subcurrid = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char decomplevs = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbswidth = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbsheight = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbstyle = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char transform = onebyte[0];
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d levels (%d resolutions)"), decomplevs, decomplevs + 1),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (transform & 0x01)
+ text = wxT("5-3 reversible wavelet");
+ else
+ text = wxT("9-7 irreversible wavelet");
+ subcurrid = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Code-blocks: %dx%d"), 1 << ((cbswidth & 0x0F) + 2), 1 << ((cbsheight & 0x0F) + 2)),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxT("Coding styles"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ if (cbstyle & 0x01)
+ text = wxT("Selective arithmetic coding bypass");
+ else
+ text = wxT("No selective arithmetic coding bypass");
+ wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x02)
+ text = wxT("Reset context probabilities on coding pass boundaries");
+ else
+ text = wxT("No reset of context probabilities on coding pass boundaries");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x04)
+ text = wxT("Termination on each coding passs");
+ else
+ text = wxT("No termination on each coding pass");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x08)
+ text = wxT("Vertically stripe causal context");
+ else
+ text = wxT("No vertically stripe causal context");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x10)
+ text = wxT("Predictable termination");
+ else
+ text = wxT("No predictable termination");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x20)
+ text = wxT("Segmentation symbols are used");
+ else
+ text = wxT("No segmentation symbols are used");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /////////
+ // COD //
+ /////////
+ case COD_VAL:
+ {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char scod = onebyte[0];
+
+ wxString text;
+
+ if (scod & 0x01)
+ text << wxT("Partitioned entropy coder");
+ else
+ text << wxT("Unpartitioned entropy coder");
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ text = wxT("");
+ if (scod & 0x02)
+ text << wxT("Possible SOPs");
+ else
+ text << wxT("No SOPs");
+
+ if (scod & 0x04)
+ text << wxT(", possible EPHs");
+ else
+ text << wxT(", no EPHs");
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char progord = onebyte[0];
+
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int numlayers = STREAM_TO_UINT16(twobytes, 0);
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char mctransform = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char decomplevs = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbswidth = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbsheight = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char cbstyle = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char transform = onebyte[0];
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d levels (%d resolutions)"), decomplevs, decomplevs + 1),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ text = wxT("");
+ switch (progord) {
+ case (0):
+ text << wxT("LRCP");
+ break;
+ case (1):
+ text << wxT("RLCP");
+ break;
+ case (2):
+ text << wxT("LRCP");
+ break;
+ case (3):
+ text << wxT("RPCL");
+ break;
+ case (4):
+ text << wxT("CPRL");
+ break;
+ default:
+ text << wxT("unknown progression");
+ break;
+ }
+ text << wxString::Format(wxT(", %d layers"), numlayers);
+ if (transform & 0x01)
+ text << wxT(", 5-3 rev.");
+ else
+ text << wxT(", 9-7 irr.");
+ subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Code-blocks: %dx%d"), 1 << ((cbswidth & 0x0F) + 2), 1 << ((cbsheight & 0x0F) + 2)),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ switch (mctransform) {
+ case (0):
+ {
+ text = wxT("No MCT");
+ }
+ break;
+ case (1):
+ {
+ text = wxT("Reversible MCT on 0, 1, 2");
+ }
+ break;
+ case (2):
+ {
+ text = wxT("Irreversible MCT on 0, 1, 2");
+ }
+ break;
+ default:
+ {
+ text = wxT("Unknown");
+ }
+ break;
+ };
+ subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ wxT("Coding styles"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ if (cbstyle & 0x01)
+ text = wxT("Selective arithmetic coding bypass");
+ else
+ text = wxT("No selective arithmetic coding bypass");
+ wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x02)
+ text = wxT("Reset context probabilities on coding pass boundaries");
+ else
+ text = wxT("No reset of context probabilities on coding pass boundaries");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x04)
+ text = wxT("Termination on each coding passs");
+ else
+ text = wxT("No termination on each coding pass");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x08)
+ text = wxT("Vertically stripe causal context");
+ else
+ text = wxT("No vertically stripe causal context");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x10)
+ text = wxT("Predictable termination");
+ else
+ text = wxT("No predictable termination");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (cbstyle & 0x20)
+ text = wxT("Segmentation symbols are used");
+ else
+ text = wxT("No segmentation symbols are used");
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ };
+ break;
+
+ /////////
+ // QCC //
+ /////////
+ case QCC_VAL:
+ {
+ unsigned short int cqcc;
+ if (csiz < 257) {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ cqcc = onebyte[0];
+ } else {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ cqcc = STREAM_TO_UINT16(twobytes, 0);
+ }
+
+ wxTreeItemId subcurrid = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Comp. no. %d"), cqcc),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char sqcc = onebyte[0];
+
+ wxString text;
+ switch (sqcc & 0x1F) {
+ case (0):
+ text = wxT("No quantization");
+ break;
+ case (1):
+ text = wxT("Scalar implicit");
+ break;
+ case (2):
+ text = wxT("Scalar explicit");
+ break;
+ default:
+ text = wxT("Unknown");
+ break;
+ }
+ text << wxString::Format(wxT(", %d guard bits"), (sqcc & 0xE0) >> 5);
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /////////
+ // QCD //
+ /////////
+ case QCD_VAL:
+ {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char sqcd = onebyte[0];
+
+ wxString text;
+ switch (sqcd & 0x1F) {
+ case (0):
+ text = wxT("No quantization");
+ break;
+ case (1):
+ text = wxT("Scalar implicit");
+ break;
+ case (2):
+ text = wxT("Scalar explicit");
+ break;
+ default:
+ text = wxT("Unknown");
+ break;
+ }
+ text << wxString::Format(wxT(", %d guard bits"), (sqcd & 0xE0) >> 5);
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ };
+ break;
+
+ /////////
+ // COM //
+ /////////
+ case COM_VAL:
+ {
+ #define showlen 25
+ char comment[showlen];
+ wxString comments;
+
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int rcom = STREAM_TO_UINT16(twobytes, 0);
+
+ wxString text;
+ if (rcom == 0)
+ text = wxT("Binary values");
+ else if (rcom == 1)
+ text = wxT("ISO 8859-1 (latin-1) values");
+ else if (rcom < 65535)
+ text = wxT("Reserved for registration");
+ else
+ text = wxT("Reserved for extension");
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (m_file->Read(comment, showlen) != showlen)
+ break;
+ comments = wxString::FromAscii(comment).Truncate(wxMin(showlen, currlen - 4));
+ if ((currlen - 4) > showlen)
+ comments << wxT("...");
+ subcurrid3 = m_tree->AppendItem(currid,
+ comments,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+ break;
+
+ /////////
+ // TLM //
+ /////////
+ case TLM_VAL:
+ {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char ztlm = onebyte[0];
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char stlm = onebyte[0];
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("TLM #%d"), ztlm),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("%d bits/index, %d bits/length"),
+ 8 * ((stlm & 0x30) >> 4), 16 + 16 * ((stlm & 0x40) >> 6)),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ int n, numparts;
+
+ numparts = (currlen - 2) / ( ((stlm & 0x30) >> 4) + 2 + 2 * ((stlm & 0x40) >> 6));
+
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ subcurrid3 = m_tree->AppendItem(currid,
+ wxT("Tile parts"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ for (n = 0; n < numparts; n++) {
+
+ unsigned short int ttlm;
+ unsigned long int ptlm;
+
+ switch (((stlm & 0x30) >> 4)) {
+
+ case 0:
+ ttlm = 0;
+ break;
+
+ case 1:
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ ttlm = onebyte[0];
+ break;
+
+ case 2:
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ ttlm = STREAM_TO_UINT16(twobytes, 0);
+ break;
+
+ }
+
+ switch (((stlm & 0x40) >> 6)) {
+
+ case 0:
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ ptlm = STREAM_TO_UINT16(twobytes, 0);
+ break;
+
+ case 1:
+ if (m_file->Read(fourbytes, 4) != 4)
+ break;
+ ptlm = STREAM_TO_UINT32(fourbytes, 0);
+ break;
+
+ }
+
+ wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
+ wxString::Format(wxT("Tile %d: %d bytes"), ttlm, ptlm),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+
+ }
+ break;
+
+ /////////
+ // POD //
+ /////////
+ case POD_VAL:
+ {
+ int n, numchanges;
+
+ if (csiz < 257)
+ numchanges = (currlen - 2) / 7;
+ else
+ numchanges = (currlen - 2) / 9;
+
+ for (n = 0; n < numchanges; n++) {
+
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,
+ wxString::Format(wxT("Change #%d"), n),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char rspod = onebyte[0];
+
+ unsigned short int cspod;
+ if (csiz < 257) {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ cspod = onebyte[0];
+ } else {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ cspod = STREAM_TO_UINT16(twobytes, 0);
+ }
+
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ unsigned short int lyepod = STREAM_TO_UINT16(twobytes, 0);
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char repod = onebyte[0];
+
+ unsigned short int cepod;
+ if (csiz < 257) {
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ cepod = onebyte[0];
+ } else {
+ if (m_file->Read(twobytes, 2) != 2)
+ break;
+ cepod = STREAM_TO_UINT16(twobytes, 0);
+ }
+
+ if (m_file->Read(onebyte, 1) != 1)
+ break;
+ unsigned char ppod = onebyte[0];
+
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ wxTreeItemId subcurrid4 = m_tree->AppendItem(subcurrid3,
+ wxString::Format(wxT("%d <= Resolution < %d"), rspod, repod),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ wxString::Format(wxT("%d <= Component < %d"), cspod, cepod),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ wxString::Format(wxT("0 <= Layer < %d"), lyepod),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ wxString text = wxT("");
+ switch (ppod) {
+ case (0):
+ text << wxT("LRCP");
+ break;
+ case (1):
+ text << wxT("RLCP");
+ break;
+ case (2):
+ text << wxT("LRCP");
+ break;
+ case (3):
+ text << wxT("RPCL");
+ break;
+ case (4):
+ text << wxT("CPRL");
+ break;
+ default:
+ text << wxT("unknown progression");
+ break;
+ }
+ subcurrid4 = m_tree->AppendItem(subcurrid3,
+ text,
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ }
+
+ }
+ break;
+
+ /////////
+ // SOD //
+ /////////
+ case SOD_VAL:
+ {
+ inside_sod = 1;
+ };
+ break;
+
+ default:
+ break;
+
+ }
+
+ // increment number of markers
+ if (nmarks++ >= maxmarks) {
+ WriteText(wxT("Maximum amount of markers exceeded"));
+ break;
+ }
+
+ // advance position
+ OPJ_ADVANCE(currlen + 2);
+ }
+
+ WriteText(wxT("Search finished"));
+}
diff --git a/src/bin/wx/OPJViewer/source/wxjp2parser.cpp b/src/bin/wx/OPJViewer/source/wxjp2parser.cpp
new file mode 100644
index 00000000..182def8b
--- /dev/null
+++ b/src/bin/wx/OPJViewer/source/wxjp2parser.cpp
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
+ * 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 "OPJViewer.h"
+
+/* defines */
+#define SHORT_DESCR_LEN 32
+#define LONG_DESCR_LEN 256
+
+/* enumeration for file formats */
+#define J2FILENUM 4
+typedef enum {
+
+ JP2_FILE,
+ J2K_FILE,
+ MJ2_FILE,
+ UNK_FILE
+
+} j2filetype;
+
+/* enumeration for the box types */
+#define j22boxNUM 23
+typedef enum {
+
+ FILE_BOX,
+ JP_BOX,
+ FTYP_BOX,
+ JP2H_BOX,
+ IHDR_BOX,
+ COLR_BOX,
+ JP2C_BOX,
+ JP2I_BOX,
+ XML_BOX,
+ UUID_BOX,
+ UINF_BOX,
+ MOOV_BOX,
+ MVHD_BOX,
+ TRAK_BOX,
+ TKHD_BOX,
+ MDIA_BOX,
+ MDHD_BOX,
+ HDLR_BOX,
+ MINF_BOX,
+ VMHD_BOX,
+ STBL_BOX,
+ STSD_BOX,
+ STSZ_BOX,
+ MJP2_BOX,
+ MDAT_BOX,
+ ANY_BOX,
+ UNK_BOX
+
+} j22boxtype;
+
+/* the box structure itself */
+struct boxdef {
+
+ char value[5]; /* hexadecimal value/string*/
+ char name[SHORT_DESCR_LEN]; /* short description */
+ char descr[LONG_DESCR_LEN]; /* long description */
+ int sbox; /* is it a superbox? */
+ int req[J2FILENUM]; /* mandatory box */
+ j22boxtype ins; /* contained in box... */
+
+};
+
+
+/* jp2 family box signatures */
+#define FILE_SIGN ""
+#define JP_SIGN "jP\040\040"
+#define FTYP_SIGN "ftyp"
+#define JP2H_SIGN "jp2h"
+#define IHDR_SIGN "ihdr"
+#define COLR_SIGN "colr"
+#define JP2C_SIGN "jp2c"
+#define JP2I_SIGN "jp2i"
+#define XML_SIGN "xml\040"
+#define UUID_SIGN "uuid"
+#define UINF_SIGN "uinf"
+#define MOOV_SIGN "moov"
+#define MVHD_SIGN "mvhd"
+#define TRAK_SIGN "trak"
+#define TKHD_SIGN "tkhd"
+#define MDIA_SIGN "mdia"
+#define MDHD_SIGN "mdhd"
+#define HDLR_SIGN "hdlr"
+#define MINF_SIGN "minf"
+#define VMHD_SIGN "vmhd"
+#define STBL_SIGN "stbl"
+#define STSD_SIGN "stsd"
+#define STSZ_SIGN "stsz"
+#define MJP2_SIGN "mjp2"
+#define MDAT_SIGN "mdat"
+#define ANY_SIGN ""
+#define UNK_SIGN ""
+
+/* the possible boxes */
+struct boxdef j22box[] =
+{
+/* sign */ {FILE_SIGN,
+/* short */ "placeholder for nothing",
+/* long */ "Nothing to say",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP_SIGN,
+/* short */ "JPEG 2000 Signature box",
+/* long */ "This box uniquely identifies the file as being part of the JPEG 2000 family of files",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {FTYP_SIGN,
+/* short */ "File Type box",
+/* long */ "This box specifies file type, version and compatibility information, including specifying if this file "
+ "is a conforming JP2 file or if it can be read by a conforming JP2 reader",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP2H_SIGN,
+/* short */ "JP2 Header box",
+/* long */ "This box contains a series of boxes that contain header-type information about the file",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {IHDR_SIGN,
+/* short */ "Image Header box",
+/* long */ "This box specifies the size of the image and other related fields",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ JP2H_BOX},
+
+/* sign */ {COLR_SIGN,
+/* short */ "Colour Specification box",
+/* long */ "This box specifies the colourspace of the image",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ JP2H_BOX},
+
+/* sign */ {JP2C_SIGN,
+/* short */ "Contiguous Codestream box",
+/* long */ "This box contains the codestream as defined by Annex A",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {JP2I_SIGN,
+/* short */ "Intellectual Property box",
+/* long */ "This box contains intellectual property information about the image",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {XML_SIGN,
+/* short */ "XML box",
+/* long */ "This box provides a tool by which vendors can add XML formatted information to a JP2 file",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UUID_SIGN,
+/* short */ "UUID box",
+/* long */ "This box provides a tool by which vendors can add additional information to a file "
+ "without risking conflict with other vendors",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UINF_SIGN,
+/* short */ "UUID Info box",
+/* long */ "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {MOOV_SIGN,
+/* short */ "Movie box",
+/* long */ "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {MVHD_SIGN,
+/* short */ "Movie Header box",
+/* long */ "This box defines overall information which is media-independent, and relevant to the entire presentation "
+ "considered as a whole",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MOOV_BOX},
+
+/* sign */ {TRAK_SIGN,
+/* short */ "Track box",
+/* long */ "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MOOV_BOX},
+
+/* sign */ {TKHD_SIGN,
+/* short */ "Track Header box",
+/* long */ "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ TRAK_BOX},
+
+/* sign */ {MDIA_SIGN,
+/* short */ "Media box",
+/* long */ "The media declaration container contains all the objects which declare information about the media data "
+ "within a track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ TRAK_BOX},
+
+/* sign */ {MDHD_SIGN,
+/* short */ "Media Header box",
+/* long */ "The media header declares overall information which is media-independent, and relevant to characteristics "
+ "of the media in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
+/* sign */ {HDLR_SIGN,
+/* short */ "Handler Reference box",
+/* long */ "This box within a Media Box declares the process by which the media-data in the track may be presented, "
+ "and thus, the nature of the media in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
+/* sign */ {MINF_SIGN,
+/* short */ "Media Information box",
+/* long */ "This box contains all the objects which declare characteristic information of the media in the track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
+/* sign */ {VMHD_SIGN,
+/* short */ "Video Media Header box",
+/* long */ "The video media header contains general presentation information, independent of the coding, for video media",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {STBL_SIGN,
+/* short */ "Sample Table box",
+/* long */ "The sample table contains all the time and data indexing of the media samples in a track",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {STSD_SIGN,
+/* short */ "STSD Sample Description box",
+/* long */ "The sample description table gives detailed information about the coding type used, and any initialization "
+ "information needed for that coding",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {STSZ_SIGN,
+/* short */ "Sample Size box",
+/* long */ "This box contains the sample count and a table giving the size of each sample",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ STBL_BOX},
+
+/* sign */ {MJP2_SIGN,
+/* short */ "MJP2 Sample Description box",
+/* long */ "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "
+ "information needed for that coding",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MINF_BOX},
+
+/* sign */ {MDAT_SIGN,
+/* short */ "Media Data box",
+/* long */ "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",
+/* sbox */ 1,
+/* req */ {1, 1, 1},
+/* ins */ FILE_BOX},
+
+/* sign */ {ANY_SIGN,
+/* short */ "Any box",
+/* long */ "All the existing boxes",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ FILE_BOX},
+
+/* sign */ {UNK_SIGN,
+/* short */ "Unknown Type box",
+/* long */ "The signature is not recognised to be that of an existing box",
+/* sbox */ 0,
+/* req */ {0, 0, 0},
+/* ins */ ANY_BOX}
+
+};
+
+
+/* macro functions */
+/* From little endian to big endian, 2 and 4 bytes */
+#define BYTE_SWAP2(X) ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
+#define BYTE_SWAP4(X) ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
+
+#ifdef __WXGTK__
+#define BYTE_SWAP8(X) ((X & 0x00000000000000FFULL) << 56) | ((X & 0x000000000000FF00ULL) << 40) | \
+ ((X & 0x0000000000FF0000ULL) << 24) | ((X & 0x00000000FF000000ULL) << 8) | \
+ ((X & 0x000000FF00000000ULL) >> 8) | ((X & 0x0000FF0000000000ULL) >> 24) | \
+ ((X & 0x00FF000000000000ULL) >> 40) | ((X & 0xFF00000000000000ULL) >> 56)
+#else
+#define BYTE_SWAP8(X) ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \
+ ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \
+ ((X & 0x000000FF00000000) >> 8) | ((X & 0x0000FF0000000000) >> 24) | \
+ ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56)
+#endif
+
+/* From codestream to int values */
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \
+ ((unsigned long int) (C)[(P) + 1] << 16) + \
+ ((unsigned long int) (C)[(P) + 2] << 8) + \
+ ((unsigned long int) (C)[(P) + 3] << 0))
+
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \
+ ((unsigned long int) (C)[(P) + 1] << 0))
+
+#define OPJREAD_LONG(F,L,N) { \
+ if (F->Read(fourbytes, 4) < 4) { \
+ wxLogMessage(wxT("Problem reading " N " from the file (file ended?)")); \
+ return -1; \
+ }; \
+ L = STREAM_TO_UINT32(fourbytes, 0); \
+ }
+
+/* handling functions */
+#define ITEM_PER_ROW 10
+
+//#define indprint if (0) printf("%.*s", 2 * level + 9, indent), printf
+char indent[] = " "
+ " "
+ " "
+ " ";
+
+void indprint(wxString printout, int level)
+{
+ wxLogMessage(/*wxString::Format(wxT("%.*s"), 2 * level + 9, indent) + */printout);
+}
+
+/* Box handler function */
+int OPJParseThread::box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
+ wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)
+{
+ switch ((j22boxtype) boxtype) {
+
+
+ /* JPEG 2000 Signature box */
+ case (JP_BOX): {
+
+ unsigned long int checkdata = 0;
+ fileid->Read(&checkdata, sizeof(unsigned long int));
+ checkdata = BYTE_SWAP4(checkdata);
+
+ // add info
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Check data: %X -> %s"), checkdata, (checkdata == 0x0D0A870A) ? wxT("OK") : wxT("KO")),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ };
+ break;
+
+
+ /* JPEG 2000 codestream box */
+ case (JP2C_BOX): {
+
+ // add info
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString(wxT("Codestream")),
+ m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
+ new OPJMarkerData(wxT("INFO-CSTREAM"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+
+ m_tree->SetItemHasChildren(currid);
+
+ // parse the file
+ //ParseJ2KFile(fileid, filepoint, filelimit, currid);
+
+ };
+ break;
+
+
+
+
+
+ /* File Type box */
+ case (FTYP_BOX): {
+
+ char BR[4], CL[4];
+ unsigned long int MinV, numCL, i;
+ fileid->Read(BR, sizeof(char) * 4);
+ fileid->Read(&MinV, sizeof(unsigned long int));
+ MinV = BYTE_SWAP4(MinV);
+ numCL = (filelimit - fileid->Tell()) / 4;
+
+ // add info
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxT("Brand/Minor version: ") +
+ wxString::FromAscii(BR).Truncate(4) +
+ wxString::Format(wxT("/%d"), MinV),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Compatibility list")),
+ m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ for (i = 0; i < numCL; i++) {
+ fileid->Read(CL, sizeof(char) * 4);
+ m_tree->AppendItem(currid,
+ wxString::FromAscii(CL).Truncate(4),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+
+ };
+ break;
+
+
+
+ /* JP2 Header box */
+ case (IHDR_BOX): {
+
+ unsigned long int height, width;
+ unsigned short int nc;
+ unsigned char bpc, C, UnkC, IPR;
+ fileid->Read(&height, sizeof(unsigned long int));
+ height = BYTE_SWAP4(height);
+ fileid->Read(&width, sizeof(unsigned long int));
+ width = BYTE_SWAP4(width);
+ fileid->Read(&nc, sizeof(unsigned short int));
+ nc = BYTE_SWAP2(nc);
+ fileid->Read(&bpc, sizeof(unsigned char));
+ fileid->Read(&C, sizeof(unsigned char));
+ fileid->Read(&UnkC, sizeof(unsigned char));
+ fileid->Read(&IPR, sizeof(unsigned char));
+
+ // add info
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Dimensions: %d x %d x %d @ %d bpc"), width, height, nc, bpc + 1),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Compression type: %d"), C),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Colourspace unknown: %d"), UnkC),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Intellectual Property Rights: %d"), IPR),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ };
+ break;
+
+
+
+ /* Colour Specification box */
+ case (COLR_BOX): {
+
+ unsigned char METH, PREC, APPROX;
+ char methdescr[80], enumcsdescr[80];
+ unsigned long int EnumCS;
+ fileid->Read(&METH, sizeof(unsigned char));
+ switch (METH) {
+ case 1:
+ strcpy(methdescr, "Enumerated Colourspace");
+ break;
+ case 2:
+ strcpy(methdescr, "Restricted ICC profile");
+ break;
+ default:
+ strcpy(methdescr, "Unknown");
+ break;
+ };
+ fileid->Read(&PREC, sizeof(unsigned char));
+ fileid->Read(&APPROX, sizeof(unsigned char));
+ if (METH != 2) {
+ fileid->Read(&EnumCS, sizeof(unsigned long int));
+ EnumCS = BYTE_SWAP4(EnumCS);
+ switch (EnumCS) {
+ case 16:
+ strcpy(enumcsdescr, "sRGB");
+ break;
+ case 17:
+ strcpy(enumcsdescr, "greyscale");
+ break;
+ case 18:
+ strcpy(enumcsdescr, "sYCC");
+ break;
+ default:
+ strcpy(enumcsdescr, "Unknown");
+ break;
+ };
+ };
+
+ // add info
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Specification method: %d ("), METH) +
+ wxString::FromAscii(methdescr) +
+ wxT(")"),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Precedence: %d"), PREC),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Colourspace approximation: %d"), APPROX),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (METH != 2)
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Enumerated colourspace: %d ("), EnumCS) +
+ wxString::FromAscii(enumcsdescr) +
+ wxT(")"),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ if (METH != 1)
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("ICC profile: there is one")),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+
+ };
+ break;
+
+
+
+
+
+
+ /* Movie Header Box */
+ case (MVHD_BOX): {
+
+ unsigned long int version, rate, matrix[9], next_track_ID;
+ unsigned short int volume;
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ if (version == 0) {
+ unsigned long int creation_time, modification_time, timescale, duration;
+ fileid->Read(&creation_time, sizeof(unsigned long int));
+ creation_time = BYTE_SWAP4(creation_time);
+ fileid->Read(&modification_time, sizeof(unsigned long int));
+ modification_time = BYTE_SWAP4(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(unsigned long int));
+ duration = BYTE_SWAP4(duration);
+ const long unix_time = creation_time - 2082844800L;
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ const long unix_time1 = modification_time - 2082844800L;
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ } else {
+ int8byte creation_time, modification_time, duration;
+ unsigned long int timescale;
+ fileid->Read(&creation_time, sizeof(int8byte));
+ creation_time = BYTE_SWAP8(creation_time);
+ fileid->Read(&modification_time, sizeof(int8byte));
+ modification_time = BYTE_SWAP8(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(int8byte));
+ duration = BYTE_SWAP8(duration);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u"), creation_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u"), modification_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u"), timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u"), duration),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+ fileid->Read(&rate, sizeof(unsigned long int));
+ rate = BYTE_SWAP4(rate);
+ fileid->Read(&volume, sizeof(unsigned short int));
+ volume = BYTE_SWAP2(volume);
+ fileid->Seek(6, wxFromCurrent);
+ fileid->Read(&matrix, sizeof(unsigned char) * 9);
+ fileid->Seek(4, wxFromCurrent);
+ fileid->Read(&next_track_ID, sizeof(unsigned long int));
+ next_track_ID = BYTE_SWAP4(next_track_ID);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Rate: %d (%d.%d)"), rate, rate >> 16, rate & 0x0000FFFF),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Volume: %d (%d.%d)"), volume, volume >> 8, volume & 0x00FF),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Next track ID: %d"), next_track_ID),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+ break;
+
+
+ /* Sample Description box */
+ case (STSD_BOX): {
+
+ unsigned long int version, entry_count;
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ fileid->Read(&entry_count, sizeof(unsigned long int));
+ entry_count = BYTE_SWAP4(entry_count);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Entry count: %d"), entry_count),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+ jpeg2000parse(fileid, filepoint + 8, filelimit, parentid, level + 1, scansign, scanpoint);
+ };
+ break;
+
+
+ /* Sample Size box */
+ case (STSZ_BOX): {
+
+ unsigned long int version, sample_size, sample_count, entry_size;
+
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+
+ fileid->Read(&sample_size, sizeof(unsigned long int));
+ sample_size = BYTE_SWAP4(sample_size);
+
+ if (sample_size == 0) {
+ fileid->Read(&sample_count, sizeof(unsigned long int));
+ sample_count = BYTE_SWAP4(sample_count);
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Sample count: %d"), sample_count),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxT("Entries size (bytes)"),
+ m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+
+ wxString text;
+ for (unsigned int s = 0; s < sample_count; s++) {
+ fileid->Read(&entry_size, sizeof(unsigned long int));
+ entry_size = BYTE_SWAP4(entry_size);
+
+ text << wxString::Format(wxT("%d, "), entry_size);
+
+ if (((s % 10) == (ITEM_PER_ROW - 1)) || (s == (sample_count - 1))) {
+ m_tree->AppendItem(currid,
+ text,
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+ text = wxT("");
+ }
+
+ }
+
+ }
+
+ };
+ break;
+
+
+ /* Video Media Header box */
+ case (VMHD_BOX): {
+
+ unsigned long int version;
+ unsigned short int graphicsmode, opcolor[3];
+ char graphicsdescr[100];
+
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+
+ fileid->Read(&graphicsmode, sizeof(unsigned short int));
+ graphicsmode = BYTE_SWAP2(graphicsmode);
+ switch (graphicsmode) {
+ case (0x00):
+ strcpy(graphicsdescr, "copy");
+ break;
+ case (0x24):
+ strcpy(graphicsdescr, "transparent");
+ break;
+ case (0x0100):
+ strcpy(graphicsdescr, "alpha");
+ break;
+ case (0x0101):
+ strcpy(graphicsdescr, "whitealpha");
+ break;
+ case (0x0102):
+ strcpy(graphicsdescr, "blackalpha");
+ break;
+ default:
+ strcpy(graphicsdescr, "unknown");
+ break;
+ };
+
+ fileid->Read(opcolor, 3 * sizeof(unsigned short int));
+ opcolor[0] = BYTE_SWAP2(opcolor[0]);
+ opcolor[1] = BYTE_SWAP2(opcolor[1]);
+ opcolor[2] = BYTE_SWAP2(opcolor[2]);
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Composition mode: %d (")) +
+ wxString::FromAscii(graphicsdescr) +
+ wxT(")"),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("OP color: %d %d %d"), opcolor[0], opcolor[1], opcolor[2]),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+ };
+ break;
+
+
+
+ /* MJP2 Sample Description box */
+ case (MJP2_BOX): {
+
+ unsigned short int height, width, depth;
+ unsigned long int horizresolution, vertresolution;
+ char compressor_name[32];
+ fileid->Seek(24, wxFromCurrent);
+ fileid->Read(&width, sizeof(unsigned short int));
+ width = BYTE_SWAP2(width);
+ fileid->Read(&height, sizeof(unsigned short int));
+ height = BYTE_SWAP2(height);
+ fileid->Read(&horizresolution, sizeof(unsigned long int));
+ horizresolution = BYTE_SWAP4(horizresolution);
+ fileid->Read(&vertresolution, sizeof(unsigned long int));
+ vertresolution = BYTE_SWAP4(vertresolution);
+ fileid->Seek(6, wxFromCurrent);
+ fileid->Read(compressor_name, sizeof(char) * 32);
+ fileid->Read(&depth, sizeof(unsigned short int));
+ depth = BYTE_SWAP2(depth);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Dimensions: %d x %d @ %d bpp"), width, height, depth),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Resolution: %d.%d x %d.%d"), horizresolution >> 16, horizresolution & 0x0000FFFF,
+ vertresolution >> 16, vertresolution & 0x0000FFFF),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Compressor: %.32s"), compressor_name),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ jpeg2000parse(fileid, filepoint + 78, filelimit, parentid, level + 1, scansign, scanpoint);
+
+ };
+ break;
+
+ /* Media Header box */
+ case (MDHD_BOX): {
+ unsigned long int version;
+ unsigned short int language;
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ if (version == 0) {
+ unsigned long int creation_time, modification_time, timescale, duration;
+ fileid->Read(&creation_time, sizeof(unsigned long int));
+ creation_time = BYTE_SWAP4(creation_time);
+ fileid->Read(&modification_time, sizeof(unsigned long int));
+ modification_time = BYTE_SWAP4(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(unsigned long int));
+ duration = BYTE_SWAP4(duration);
+ const long unix_time = creation_time - 2082844800L;
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ const long unix_time1 = modification_time - 2082844800L;
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ } else {
+ int8byte creation_time, modification_time, duration;
+ unsigned long int timescale;
+ fileid->Read(&creation_time, sizeof(int8byte));
+ creation_time = BYTE_SWAP8(creation_time);
+ fileid->Read(&modification_time, sizeof(int8byte));
+ modification_time = BYTE_SWAP8(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(int8byte));
+ duration = BYTE_SWAP8(duration);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u"), creation_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u"), modification_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u"), timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u"), duration),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ }
+ fileid->Read(&language, sizeof(unsigned short int));
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Language: %d (%c%c%c)"), language & 0xEFFF,
+ 0x60 + (char) ((language >> 10) & 0x001F), 0x60 + (char) ((language >> 5) & 0x001F), 0x60 + (char) ((language >> 0) & 0x001F)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+ break;
+
+ /* Media Handler box */
+ case (HDLR_BOX): {
+ unsigned long int version, predefined, temp[3];
+ char handler[4], name[256];
+ int namelen = wxMin(256, (filelimit - filepoint - 24));
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ fileid->Read(&predefined, sizeof(unsigned long int));
+ fileid->Read(handler, 4 * sizeof(char));
+ fileid->Read(&temp, 3 * sizeof(unsigned long int));
+ fileid->Read(name, namelen * sizeof(char));
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Handler: %.4s"), handler),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Name: %.255s"), name),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
+ /* not yet implemented */
+ default:
+ break;
+
+ };
+
+ return (0);
+}
+
+
+void OPJParseThread::ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid)
+{
+ unsigned long int scanpoint;
+
+ jpeg2000parse(fileid, filepoint, filelimit, parentid, 0, NULL, &scanpoint);
+}
+
+/* the parsing function itself */
+/*
+ fileid = fid of the file to scan (you should open it by yourself)
+ filepoint = first byte where to start to scan from (usually 0)
+ filelimit = first byte where to stop to scan from (usually the file size)
+ level = set this to 0
+ scansign = signature to scan for (NULL avoids search, returns " " if successful)
+ scanpoint = point where the scan signature lies
+*/
+int OPJParseThread::jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,
+ wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)
+{
+ unsigned long int LBox = 0x00000000;
+ //int LBox_read;
+ char TBox[5] = "\0\0\0\0";
+ //int TBox_read;
+ int8byte XLBox = 0x0000000000000000;
+ //int XLBox_read;
+ unsigned long int box_length = 0;
+ int last_box = 0, box_num = 0;
+ int box_type = ANY_BOX;
+ unsigned char /*onebyte[1], twobytes[2],*/ fourbytes[4];
+
+ /* cycle all over the file */
+ box_num = 0;
+ last_box = 0;
+ while (!last_box) {
+
+ /* do not exceed file limit */
+ if (filepoint >= filelimit)
+ return (0);
+
+ /* seek on file */
+ if (fileid->Seek(filepoint, wxFromStart) == wxInvalidOffset)
+ return (-1);
+
+ /* read the mandatory LBox, 4 bytes */
+ if (fileid->Read(fourbytes, 4) < 4) {
+ WriteText(wxT("Problem reading LBox from the file (file ended?)"));
+ return -1;
+ };
+ LBox = STREAM_TO_UINT32(fourbytes, 0);
+
+ /* read the mandatory TBox, 4 bytes */
+ if (fileid->Read(TBox, 4) < 4) {
+ WriteText(wxT("Problem reading TBox from the file (file ended?)"));
+ return -1;
+ };
+
+ /* look if scansign is got */
+ if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {
+ memcpy(scansign, " ", 4);
+ *scanpoint = filepoint;
+
+ /* hack/exploit */
+ // stop as soon as you find the codebox
+ return (0);
+
+ };
+
+ /* determine the box type */
+ for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)
+ if (memcmp(TBox, j22box[box_type].value, 4) == 0)
+ break;
+
+ /* read the optional XLBox, 8 bytes */
+ if (LBox == 1) {
+
+ if (fileid->Read(&XLBox, 8) < 8) {
+ WriteText(wxT("Problem reading XLBox from the file (file ended?)"));
+ return -1;
+ };
+ box_length = (unsigned long int) BYTE_SWAP8(XLBox);
+
+ } else if (LBox == 0x00000000) {
+
+ /* last box in file */
+ last_box = 1;
+ box_length = filelimit - filepoint;
+
+ } else
+
+ box_length = LBox;
+
+ /* show box info */
+
+ // append the marker
+ int image, imageSel;
+ image = m_tree->TreeCtrlIcon_Folder;
+ imageSel = image + 1;
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("%03d: "), box_num) +
+ wxString::FromAscii(TBox) +
+ wxString::Format(wxT(" (0x%04X)"),
+ ((unsigned long int) TBox[3]) + ((unsigned long int) TBox[2] << 8) +
+ ((unsigned long int) TBox[1] << 16) + ((unsigned long int) TBox[0] << 24)
+ ),
+ image, imageSel,
+ new OPJMarkerData(wxT("BOX"), m_tree->m_fname.GetFullPath(), filepoint, filepoint + box_length)
+ );
+
+ // append some info
+ image = m_tree->TreeCtrlIcon_File;
+ imageSel = image + 1;
+
+ // box name
+ wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,
+ wxT("*** ") + wxString::FromAscii(j22box[box_type].name) + wxT(" ***"),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);
+
+ // position and length
+ wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,
+ wxLongLong(filepoint).ToString() + wxT(" > ") + wxLongLong(filepoint + box_length - 1).ToString() +
+ wxT(", ") + wxString::Format(wxT("%d + 8 (%d)"), box_length, box_length + 8),
+ image, imageSel,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ /* go deep in the box */
+ box_handler_function((int) box_type, fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
+ currid, level, scansign, scanpoint);
+
+ /* if it's a superbox go inside it */
+ if (j22box[box_type].sbox)
+ jpeg2000parse(fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
+ currid, level + 1, scansign, scanpoint);
+
+ /* increment box number and filepoint*/
+ box_num++;
+ filepoint += box_length;
+
+ };
+
+ /* all good */
+ return (0);
+}
+
diff --git a/src/lib/openjp2/CMakeLists.txt b/src/lib/openjp2/CMakeLists.txt
new file mode 100644
index 00000000..f58fe59d
--- /dev/null
+++ b/src/lib/openjp2/CMakeLists.txt
@@ -0,0 +1,77 @@
+include_regular_expression("^.*$")
+# Defines the source code for the library
+set(OPENJPEG_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/bio.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cio.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dwt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/event.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/image.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/j2k.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/j2k_lib.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/jp2.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/jpt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mct.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mqc.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/pi.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/raw.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/t1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/t2.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tcd.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tgt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cidx_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/phix_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/ppix_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/thix_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/tpix_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/function_list.c
+)
+
+# Build the library
+if(WIN32)
+ if(BUILD_SHARED_LIBS)
+ add_definitions(-DOPJ_EXPORTS)
+ else()
+ add_definitions(-DOPJ_STATIC)
+ endif()
+endif()
+add_library(${OPENJPEG_LIBRARY_NAME} ${OPENJPEG_SRCS})
+if(UNIX)
+ target_link_libraries(${OPENJPEG_LIBRARY_NAME} m)
+endif()
+set_target_properties(${OPENJPEG_LIBRARY_NAME} PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES})
+
+# Install library
+install(TARGETS ${OPENJPEG_LIBRARY_NAME}
+ EXPORT OpenJPEGTargets
+ RUNTIME DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ LIBRARY DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+ ARCHIVE DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+)
+
+# Install includes files
+install(FILES openjpeg.h opj_stdint.h
+ DESTINATION ${OPENJPEG_INSTALL_INCLUDE_DIR} COMPONENT Headers
+)
+
+# install man page of the library
+install(
+ FILES ${OPENJPEG_SOURCE_DIR}/doc/man/man3/libopenjpeg.3
+ DESTINATION ${OPENJPEG_INSTALL_MAN_DIR}/man3)
+
+# Experimental option; let's how cppcheck performs
+# Implementation details:
+# I could not figure out how to easily upload a file to CDash. Instead simply
+# pretend cppcheck is part of the Build step. Technically cppcheck can even
+# output gcc formatted error/warning report
+# Another implementation detail: I could not redirect error to the error
+# catching mechanism something is busted in cmake 2.8.5, I had to use the
+# warning regex to catch them.
+if(OPENJPEG_CPPCHECK)
+ find_package(CPPCHECK REQUIRED)
+ foreach(f ${OPENJPEG_SRCS})
+ # cppcheck complains about too many configuration, pretend to be WIN32:
+ add_custom_command(TARGET ${OPENJPEG_LIBRARY_NAME}
+ COMMAND ${CPPCHECK_EXECUTABLE} -DWIN32 ${f})
+ endforeach()
+endif()
diff --git a/src/lib/openjp2/Makefile.am b/src/lib/openjp2/Makefile.am
new file mode 100644
index 00000000..2fb79f9f
--- /dev/null
+++ b/src/lib/openjp2/Makefile.am
@@ -0,0 +1,109 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+SUBDIRS = .
+
+if WANT_JPWL
+SUBDIRS += jpwl
+endif
+
+includesdir = $(includedir)/openjpeg-$(MAJOR_NR).$(MINOR_NR)
+includes_HEADERS = openjpeg.h opj_stdint.h $(top_builddir)/opj_config.h
+
+lib_LTLIBRARIES = libopenjpeg.la
+
+libopenjpeg_la_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg
+libopenjpeg_la_CFLAGS =
+libopenjpeg_la_LIBADD = -lm
+libopenjpeg_la_LDFLAGS = -no-undefined -version-info @lt_version@
+
+libopenjpeg_la_SOURCES = \
+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 \
+t1_generate_luts.c \
+t2.c \
+tcd.c \
+tgt.c \
+cidx_manager.c \
+phix_manager.c \
+ppix_manager.c \
+thix_manager.c \
+tpix_manager.c \
+function_list.c \
+bio.h \
+cio.h \
+dwt.h \
+event.h \
+fix.h \
+image.h \
+indexbox_manager.h \
+int.h \
+j2k.h \
+j2k_lib.h \
+jp2.h \
+jpt.h \
+mct.h \
+mqc.h \
+opj_includes.h \
+opj_malloc.h \
+pi.h \
+raw.h \
+t1.h \
+t1_luts.h \
+t2.h \
+tcd.h \
+tgt.h \
+cidx_manager.h \
+function_list.h
+
+EXTRA_DIST = \
+CMakeLists.txt
+
+install-data-hook:
+ cd $(DESTDIR)$(includedir) && rm -f openjpeg.h
+ @rm -rf $(top_builddir)/report.txt
+ @echo -e " (LA)\t$(libdir)/libopenjpeg.la" >> $(top_builddir)/report.txt
+if BUILD_SHARED
+ @( $(call solist) ) >> $(top_builddir)/report.txt
+endif
+if BUILD_STATIC
+ @echo -e " (A)\t$(base)/$(a)" >> $(top_builddir)/report.txt
+endif
+ @echo -e " (H)\t$(includedir)/openjpeg-$(MAJOR_NR).$(MINOR_NR)/openjpeg.h" >> $(top_builddir)/report.txt
+
+uninstall-hook:
+ rm -f $(DESTDIR)$(includedir)/openjpeg.h
+
+solist = $(foreach f, $(dll) $(so), echo -e ' $(SO_PREFIX)\t$(base)/$(f)' ;)
+get_tok = $(shell grep -E "^$(1)=" $(lib_LTLIBRARIES) | cut -d "'" -f 2)
+base = $(call get_tok,libdir)
+so = $(call get_tok,library_names)
+a = $(call get_tok,old_library)
+
+if HAVE_WIN32
+SO_PREFIX = (DLL)
+dll = $(call get_tok,dlname)
+else
+if HAVE_DARWIN
+SO_PREFIX = (DY)
+dll =
+else
+SO_PREFIX = (SO)
+dll =
+endif
+endif
diff --git a/src/lib/openjp2/bio.c b/src/lib/openjp2/bio.c
new file mode 100644
index 00000000..0bf601bb
--- /dev/null
+++ b/src/lib/openjp2/bio.c
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.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 opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b);
+/**
+Read a bit
+@param bio BIO handle
+@return Returns the read bit
+*/
+static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio);
+/**
+Write a byte
+@param bio BIO handle
+@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise
+*/
+static opj_bool opj_bio_byteout(opj_bio_t *bio);
+/**
+Read a byte
+@param bio BIO handle
+@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise
+*/
+static opj_bool opj_bio_bytein(opj_bio_t *bio);
+
+/*@}*/
+
+/*@}*/
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+opj_bool opj_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 OPJ_FALSE;
+ }
+ *bio->bp++ = (unsigned char)(bio->buf >> 8); /* TODO MSD: check this conversion */
+ return OPJ_TRUE;
+}
+
+opj_bool opj_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 OPJ_FALSE;
+ }
+ bio->buf |= *bio->bp++;
+ return OPJ_TRUE;
+}
+
+void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) {
+ if (bio->ct == 0) {
+ opj_bio_byteout(bio); // TODO_MSD: check this line
+ }
+ bio->ct--;
+ bio->buf |= b << bio->ct;
+}
+
+OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) {
+ if (bio->ct == 0) {
+ opj_bio_bytein(bio); // TODO_MSD: check this line
+ }
+ bio->ct--;
+ return (bio->buf >> bio->ct) & 1;
+}
+
+/*
+==========================================================
+ Bit Input/Output interface
+==========================================================
+*/
+
+opj_bio_t* opj_bio_create(void) {
+ opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t));
+ return bio;
+}
+
+void opj_bio_destroy(opj_bio_t *bio) {
+ if(bio) {
+ opj_free(bio);
+ }
+}
+
+ptrdiff_t bio_numbytes(opj_bio_t *bio) {
+ return (bio->bp - bio->start);
+}
+
+void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int 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, unsigned char *bp, int len) {
+ bio->start = bp;
+ bio->end = bp + len;
+ bio->bp = bp;
+ bio->buf = 0;
+ bio->ct = 0;
+}
+
+void bio_write(opj_bio_t *bio, int v, int n) {
+ int i;
+ for (i = n - 1; i >= 0; i--) {
+ opj_bio_putbit(bio, (v >> i) & 1);
+ }
+}
+
+int bio_read(opj_bio_t *bio, int n) {
+ int i, v;
+ v = 0;
+ for (i = n - 1; i >= 0; i--) {
+ v += opj_bio_getbit(bio) << i;
+ }
+ return v;
+}
+
+int bio_flush(opj_bio_t *bio) {
+ bio->ct = 0;
+ if (! opj_bio_byteout(bio)) {
+ return 1;
+ }
+ if (bio->ct == 7) {
+ bio->ct = 0;
+ if (! opj_bio_byteout(bio)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int bio_inalign(opj_bio_t *bio) {
+ bio->ct = 0;
+ if ((bio->buf & 0xff) == 0xff) {
+ if (! opj_bio_bytein(bio)) {
+ return 1;
+ }
+ bio->ct = 0;
+ }
+ return 0;
+}
diff --git a/src/lib/openjp2/bio.h b/src/lib/openjp2/bio.h
new file mode 100644
index 00000000..61191f7d
--- /dev/null
+++ b/src/lib/openjp2/bio.h
@@ -0,0 +1,128 @@
+/*
+ * 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 __BIO_H
+#define __BIO_H
+
+#include <stddef.h> /* ptrdiff_t */
+
+/**
+@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.
+*/
+
+/** @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 */
+ int 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* opj_bio_create(void);
+/**
+Destroy a previously created BIO handle
+@param bio BIO handle to destroy
+*/
+void opj_bio_destroy(opj_bio_t *bio);
+/**
+Number of bytes written.
+@param bio BIO handle
+@return Returns the number of bytes written
+*/
+ptrdiff_t 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, unsigned char *bp, int len);
+/**
+Init decoder
+@param bio BIO handle
+@param bp Input buffer
+@param len Input buffer length
+*/
+void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int 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, int v, int n);
+/**
+Read bits
+@param bio BIO handle
+@param n Number of bits to read
+@return Returns the corresponding read number
+*/
+int bio_read(opj_bio_t *bio, int n);
+/**
+Flush bits
+@param bio BIO handle
+@return Returns 1 if successful, returns 0 otherwise
+*/
+int 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
+*/
+int bio_inalign(opj_bio_t *bio);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __BIO_H */
+
diff --git a/src/lib/openjp2/cidx_manager.c b/src/lib/openjp2/cidx_manager.c
new file mode 100644
index 00000000..f3b251ff
--- /dev/null
+++ b/src/lib/openjp2/cidx_manager.c
@@ -0,0 +1,211 @@
+/*
+ * $Id: cidx_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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"
+
+
+/*
+ * Write CPTR Codestream finder box
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] clen length of j2k codestream
+ * @param[in] cio file output handle
+ */
+void write_cptr(int coff, int clen, opj_cio_t *cio);
+
+
+/*
+ * Write main header index table (box)
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information
+ * @param[in] cio file output handle
+ * @return length of mainmhix box
+ */
+int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio);
+
+
+/*
+ * Check if EPH option is used
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] markers marker information
+ * @param[in] marknum number of markers
+ * @param[in] cio file output handle
+ * @return true if EPH is used
+ */
+opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio);
+
+
+int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen)
+{
+ int len, i, lenp;
+ opj_jp2_box_t *box;
+ int num_box = 0;
+ opj_bool EPHused;
+ (void)image; /* unused ? */
+
+ lenp = -1;
+ box = (opj_jp2_box_t *)opj_calloc( 32, sizeof(opj_jp2_box_t));
+
+ for (i=0;i<2;i++){
+
+ if(i)
+ cio_seek( cio, lenp);
+
+ lenp = cio_tell( cio);
+
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_CIDX, 4); /* CIDX */
+ write_cptr( offset, cstr_info.codestream_size, cio);
+
+ write_manf( i, num_box, box, cio);
+
+ num_box = 0;
+ box[num_box].length = write_mainmhix( offset, cstr_info, cio);
+ box[num_box].type = JPIP_MHIX;
+ num_box++;
+
+ box[num_box].length = write_tpix( offset, cstr_info, j2klen, cio);
+ box[num_box].type = JPIP_TPIX;
+ num_box++;
+
+ box[num_box].length = write_thix( offset, cstr_info, cio);
+ box[num_box].type = JPIP_THIX;
+ num_box++;
+
+ EPHused = check_EPHuse( offset, cstr_info.marker, cstr_info.marknum, cio);
+
+ box[num_box].length = write_ppix( offset, cstr_info, EPHused, j2klen, cio);
+ box[num_box].type = JPIP_PPIX;
+ num_box++;
+
+ box[num_box].length = write_phix( offset, cstr_info, EPHused, j2klen, cio);
+ box[num_box].type = JPIP_PHIX;
+ num_box++;
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+ }
+
+ opj_free( box);
+
+ return len;
+}
+
+void write_cptr(int coff, int clen, opj_cio_t *cio)
+{
+ int len, lenp;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_CPTR, 4); /* T */
+ cio_write( cio, 0, 2); /* DR A PRECISER !! */
+ cio_write( cio, 0, 2); /* CONT */
+ cio_write( cio, coff, 8); /* COFF A PRECISER !! */
+ cio_write( cio, clen, 8); /* CLEN */
+ len = cio_tell( cio) - lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+}
+
+void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio)
+{
+ int len, lenp, i;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_MANF,4); /* T */
+
+ if (second){ /* Write only during the second pass */
+ for( i=0; i<v; i++){
+ cio_write( cio, box[i].length, 4); /* Box length */
+ cio_write( cio, box[i].type, 4); /* Box type */
+ }
+ }
+
+ len = cio_tell( cio) - lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+}
+
+int write_mainmhix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio)
+{
+ int i;
+ int len, lenp;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_MHIX, 4); /* MHIX */
+
+ cio_write( cio, cstr_info.main_head_end-cstr_info.main_head_start+1, 8); /* TLEN */
+
+ for(i = 1; i < cstr_info.marknum; i++){ /* Marker restricted to 1 apparition, skip SOC marker */
+ cio_write( cio, cstr_info.marker[i].type, 2);
+ cio_write( cio, 0, 2);
+ cio_write( cio, cstr_info.marker[i].pos-coff, 8);
+ cio_write( cio, cstr_info.marker[i].len, 2);
+ }
+
+ len = cio_tell( cio) - lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
+
+opj_bool check_EPHuse( int coff, opj_marker_info_t *markers, int marknum, opj_cio_t *cio)
+{
+ opj_bool EPHused = OPJ_FALSE;
+ int i=0;
+ int org_pos;
+ unsigned int Scod;
+
+ for(i = 0; i < marknum; i++){
+ if( markers[i].type == J2K_MS_COD){
+ org_pos = cio_tell( cio);
+ cio_seek( cio, coff+markers[i].pos+2);
+
+ Scod = cio_read( cio, 1);
+ if( ((Scod >> 2) & 1))
+ EPHused = OPJ_TRUE;
+ cio_seek( cio, org_pos);
+
+ break;
+ }
+ }
+ return EPHused;
+}
diff --git a/src/lib/openjp2/cidx_manager.h b/src/lib/openjp2/cidx_manager.h
new file mode 100644
index 00000000..23eebd52
--- /dev/null
+++ b/src/lib/openjp2/cidx_manager.h
@@ -0,0 +1,56 @@
+/*
+ * $Id: cidx_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.h from 2KAN indexer
+ */
+
+
+#ifndef CIDX_MANAGER_H_
+# define CIDX_MANAGER_H_
+
+#include "openjpeg.h"
+
+
+/*
+ * Write Codestream index box (superbox)
+ *
+ * @param[in] offset offset of j2k codestream
+ * @param[in] cio file output handle
+ * @param[in] image image data
+ * @param[in] cstr_info codestream information
+ * @param[in] j2klen length of j2k codestream
+ * @return length of cidx box
+ */
+int write_cidx( int offset, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t cstr_info, int j2klen);
+
+
+#endif /* !CIDX_MANAGER_H_ */
diff --git a/src/lib/openjp2/cio.c b/src/lib/openjp2/cio.c
new file mode 100644
index 00000000..bd0ab15c
--- /dev/null
+++ b/src/lib/openjp2/cio.c
@@ -0,0 +1,786 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.h"
+
+/* ----------------------------------------------------------------------- */
+
+opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) {
+ opj_cp_t *cp = NULL;
+ opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t));
+ if(!cio) return NULL;
+ cio->cinfo = cinfo;
+ if(buffer && length) {
+ /* wrap a user buffer containing the encoded image */
+ cio->openmode = OPJ_STREAM_READ;
+ cio->buffer = buffer;
+ cio->length = length;
+ }
+ else if(!buffer && !length && cinfo) {
+ /* allocate a buffer for the encoded image */
+ cio->openmode = OPJ_STREAM_WRITE;
+ switch(cinfo->codec_format) {
+ case CODEC_J2K:
+ cp = ((opj_j2k_t*)cinfo->j2k_handle)->cp;
+ break;
+ case CODEC_JP2:
+ cp = ((opj_jp2_t*)cinfo->jp2_handle)->j2k->cp;
+ break;
+ default:
+ opj_free(cio);
+ return NULL;
+ }
+ cio->length = (int) (0.1625 * cp->img_size + 2000); /* 0.1625 = 1.3/8 and 2000 bytes as a minimum for headers */
+ assert(cio->length >= 0);
+ cio->buffer = (unsigned char *)opj_malloc((OPJ_SIZE_T)cio->length);
+ if(!cio->buffer) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error allocating memory for compressed bitstream\n");
+ opj_free(cio);
+ return NULL;
+ }
+ }
+ else {
+ opj_free(cio);
+ return NULL;
+ }
+
+ /* Initialize byte IO */
+ cio->start = cio->buffer;
+ cio->end = cio->buffer + cio->length;
+ cio->bp = cio->buffer;
+
+ return cio;
+}
+
+void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) {
+ if(cio) {
+ if(cio->openmode == OPJ_STREAM_WRITE) {
+ /* destroy the allocated buffer */
+ opj_free(cio->buffer);
+ }
+ /* destroy the cio */
+ opj_free(cio);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Get position in byte stream.
+ */
+OPJ_OFF_T OPJ_CALLCONV cio_tell(opj_cio_t *cio) {
+ return cio->bp - cio->start;
+}
+
+/*
+ * Set position in byte stream.
+ *
+ * pos : position, in number of bytes, from the beginning of the stream
+ */
+void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
+ cio->bp = cio->start + pos;
+}
+
+/*
+ * Number of bytes left before the end of the stream.
+ */
+OPJ_SIZE_T cio_numbytesleft(opj_cio_t *cio) {
+ const ptrdiff_t diff = cio->end - cio->bp;
+ assert( diff >= 0 );
+ return (OPJ_SIZE_T)diff;
+}
+
+/*
+ * Get pointer to the current position in the stream.
+ */
+unsigned char *cio_getbp(opj_cio_t *cio) {
+ return cio->bp;
+}
+
+/*
+ * Write a byte.
+ */
+opj_bool cio_byteout(opj_cio_t *cio, unsigned char v) {
+ if (cio->bp >= cio->end) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n");
+ return OPJ_FALSE;
+ }
+ *cio->bp++ = v;
+ return OPJ_TRUE;
+}
+
+/*
+ * Read a byte.
+ */
+unsigned char cio_bytein(opj_cio_t *cio) {
+ if (cio->bp >= cio->end) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "read error: passed the end of the codestream (start = %d, current = %d, end = %d\n", cio->start, cio->bp, cio->end);
+ return 0;
+ }
+ return *cio->bp++;
+}
+
+/*
+ * Write some bytes.
+ *
+ * v : value to write
+ * n : number of bytes to write
+ */
+unsigned int cio_write(opj_cio_t *cio, unsigned long long int v, int n) {
+ int i;
+ for (i = n - 1; i >= 0; i--) {
+ if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )
+ return 0;
+ }
+ assert( n >= 0 );
+ return (unsigned int)n;
+}
+
+/*
+ * Read some bytes.
+ *
+ * n : number of bytes to read
+ *
+ * return : value of the n bytes read
+ */
+unsigned int cio_read(opj_cio_t *cio, int n) {
+ int i;
+ unsigned int v = 0;
+ for (i = n - 1; i >= 0; i--) {
+ const unsigned int c = cio_bytein(cio);
+ v += c << (i << 3);
+ }
+ return v;
+}
+
+/*
+ * Skip some bytes.
+ *
+ * n : number of bytes to skip
+ */
+void cio_skip(opj_cio_t *cio, int n) {
+ cio->bp += n;
+}
+
+/* ----------------------------------------------------------------------- */
+
+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);
+}
+
+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<p_nb_bytes;++i) {
+ *(p_buffer++) = *(l_data_ptr--);
+ }
+}
+
+void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, OPJ_UINT32 p_nb_bytes)
+{
+ OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
+
+ assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32));
+
+ *p_value = 0;
+ memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,p_nb_bytes);
+}
+
+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;i<p_nb_bytes;++i) {
+ *(l_data_ptr--) = *(p_buffer++);
+ }
+}
+
+void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
+{
+ const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
+ memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT64));
+}
+
+void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value)
+{
+ const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT64) - 1;
+ OPJ_UINT32 i;
+ for (i=0;i<sizeof(OPJ_FLOAT64);++i) {
+ *(p_buffer++) = *(l_data_ptr--);
+ }
+}
+
+void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
+{
+ OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
+ memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT64));
+}
+
+void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value)
+{
+ OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64)-1;
+ OPJ_UINT32 i;
+ for (i=0;i<sizeof(OPJ_FLOAT64);++i) {
+ *(l_data_ptr--) = *(p_buffer++);
+ }
+}
+
+void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
+{
+ const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value);
+ memcpy(p_buffer,l_data_ptr,sizeof(OPJ_FLOAT32));
+}
+
+void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value)
+{
+ const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof(OPJ_FLOAT32) - 1;
+ OPJ_UINT32 i;
+ for (i=0;i<sizeof(OPJ_FLOAT32);++i) {
+ *(p_buffer++) = *(l_data_ptr--);
+ }
+}
+
+void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
+{
+ OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value);
+ memcpy(l_data_ptr,p_buffer,sizeof(OPJ_FLOAT32));
+}
+
+void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value)
+{
+ OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32)-1;
+ OPJ_UINT32 i;
+ for (i=0;i<sizeof(OPJ_FLOAT32);++i) {
+ *(l_data_ptr--) = *(p_buffer++);
+ }
+}
+
+opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,opj_bool l_is_input)
+{
+ opj_stream_private_t * l_stream = 00;
+ l_stream = (opj_stream_private_t*) opj_malloc(sizeof(opj_stream_private_t));
+ if (! l_stream) {
+ return 00;
+ }
+
+ memset(l_stream,0,sizeof(opj_stream_private_t));
+ l_stream->m_buffer_size = p_buffer_size;
+ l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_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;
+}
+
+opj_stream_t* OPJ_CALLCONV opj_stream_default_create(opj_bool l_is_input)
+{
+ return opj_stream_create(J2K_STREAM_CHUNK_SIZE,l_is_input);
+}
+
+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);
+ }
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length)
+{
+ opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
+ l_stream->m_user_data_length = data_length;
+}
+
+OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
+{
+ OPJ_SIZE_T 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 += (OPJ_OFF_T)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 += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
+ p_stream->m_bytes_in_buffer = 0;
+ return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T)-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 += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
+ p_stream->m_bytes_in_buffer = 0;
+ }
+ else {
+ /* case where we are already at the end of the buffer
+ so reset the m_current_data to point to the start of the
+ stored buffer to get ready to read from disk*/
+ p_stream->m_current_data = p_stream->m_stored_data;
+ }
+
+ while(1){
+ /* 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 == (OPJ_SIZE_T)-1) {
+ /* end of stream */
+ opj_event_msg_v2(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 : (OPJ_SIZE_T)-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 += (OPJ_OFF_T)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 += (OPJ_OFF_T)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 == (OPJ_SIZE_T)-1) {
+ /* end of stream */
+ opj_event_msg_v2(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 : (OPJ_SIZE_T)-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 += (OPJ_OFF_T)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 += (OPJ_OFF_T)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;
+ }
+ }
+ }
+}
+
+OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,
+ const OPJ_BYTE * p_buffer,
+ OPJ_SIZE_T p_size,
+ opj_event_mgr_t * p_event_mgr)
+{
+ OPJ_SIZE_T l_remaining_bytes = 0;
+ OPJ_SIZE_T l_write_nb_bytes = 0;
+
+ if (p_stream->m_status & opj_stream_e_error) {
+ return (OPJ_SIZE_T)-1;
+ }
+
+ while(1) {
+ 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 += (OPJ_OFF_T)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 += (OPJ_OFF_T)l_remaining_bytes;
+ }
+
+ if (! opj_stream_flush(p_stream, p_event_mgr)) {
+ return (OPJ_SIZE_T)-1;
+ }
+ }
+
+}
+
+opj_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_SIZE_T 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 == (OPJ_SIZE_T)-1) {
+ p_stream->m_status |= opj_stream_e_error;
+ opj_event_msg_v2(p_event_mgr, EVT_INFO, "Error on writting stream!\n");
+
+ return OPJ_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 OPJ_TRUE;
+}
+
+OPJ_OFF_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
+{
+ OPJ_OFF_T l_skip_nb_bytes = 0;
+ OPJ_OFF_T l_current_skip_nb_bytes = 0;
+
+ assert( p_size >= 0 );
+
+ if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) {
+ p_stream->m_current_data += p_size;
+ /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer
+ which is of type OPJ_SIZE_T */
+ p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)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 += (OPJ_OFF_T)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_OFF_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 += (OPJ_OFF_T)p_stream->m_bytes_in_buffer;
+ p_stream->m_current_data = p_stream->m_stored_data;
+ p_size -= (OPJ_OFF_T)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_OFF_T) -1) {
+ opj_event_msg_v2(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_OFF_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;
+}
+
+OPJ_OFF_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
+{
+ opj_bool l_is_written = 0;
+ OPJ_OFF_T l_current_skip_nb_bytes = 0;
+ OPJ_OFF_T l_skip_nb_bytes = 0;
+
+ if (p_stream->m_status & opj_stream_e_error) {
+ return (OPJ_OFF_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_OFF_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_OFF_T)-1) {
+ opj_event_msg_v2(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_OFF_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;
+}
+
+OPJ_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream)
+{
+ return p_stream->m_byte_offset;
+}
+
+OPJ_OFF_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream)
+{
+ assert( p_stream->m_byte_offset >= 0 );
+ assert( p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset);
+ return p_stream->m_user_data_length ?
+ (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset :
+ 0;
+}
+
+OPJ_OFF_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
+{
+ assert(p_size >= 0);
+ return p_stream->m_opj_skip(p_stream,p_size,p_event_mgr);
+}
+
+opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr)
+{
+ OPJ_ARG_NOT_USED(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 OPJ_FALSE;
+ }
+ else {
+ /* reset stream status */
+ p_stream->m_status &= (~opj_stream_e_end);
+ p_stream->m_byte_offset = p_size;
+
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_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 OPJ_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 OPJ_FALSE;
+ }
+ else {
+ p_stream->m_byte_offset = p_size;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr)
+{
+ assert(p_size >= 0);
+ return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr);
+}
+
+opj_bool opj_stream_has_seek (const opj_stream_private_t * p_stream)
+{
+ return p_stream->m_seek_fn != opj_stream_default_seek;
+}
+
+OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
+{
+ OPJ_ARG_NOT_USED(p_buffer);
+ OPJ_ARG_NOT_USED(p_nb_bytes);
+ OPJ_ARG_NOT_USED(p_user_data);
+ return (OPJ_SIZE_T) -1;
+}
+
+OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
+{
+ OPJ_ARG_NOT_USED(p_buffer);
+ OPJ_ARG_NOT_USED(p_nb_bytes);
+ OPJ_ARG_NOT_USED(p_user_data);
+ return (OPJ_SIZE_T) -1;
+}
+
+OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+ OPJ_ARG_NOT_USED(p_nb_bytes);
+ OPJ_ARG_NOT_USED(p_user_data);
+ return (OPJ_OFF_T) -1;
+}
+
+opj_bool opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data)
+{
+ OPJ_ARG_NOT_USED(p_nb_bytes);
+ OPJ_ARG_NOT_USED(p_user_data);
+ return OPJ_FALSE;
+}
diff --git a/src/lib/openjp2/cio.h b/src/lib/openjp2/cio.h
new file mode 100644
index 00000000..f5c4a862
--- /dev/null
+++ b/src/lib/openjp2/cio.h
@@ -0,0 +1,409 @@
+/*
+ * 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 __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 "opj_config.h"
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Number of bytes left before the end of the stream
+@param cio CIO handle
+@return Returns the number of bytes before the end of the stream
+*/
+OPJ_SIZE_T cio_numbytesleft(opj_cio_t *cio);
+/**
+Get pointer to the current position in the stream
+@param cio CIO handle
+@return Returns a pointer to the current position
+*/
+unsigned char *cio_getbp(opj_cio_t *cio);
+/**
+*/
+opj_bool cio_byteout(opj_cio_t *cio, unsigned char v);
+/**
+*/
+unsigned char cio_bytein(opj_cio_t *cio);
+/**
+Write some bytes
+@param cio CIO handle
+@param v Value to write
+@param n Number of bytes to write
+@return Returns the number of bytes written or 0 if an error occured
+*/
+unsigned int cio_write(opj_cio_t *cio, unsigned long long int v, int n);
+/**
+Read some bytes
+@param cio CIO handle
+@param n Number of bytes to read
+@return Returns the value of the n bytes read
+*/
+unsigned int cio_read(opj_cio_t *cio, int n);
+/**
+Skip some bytes
+@param cio CIO handle
+@param n Number of bytes to skip
+*/
+void cio_skip(opj_cio_t *cio, int n);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+
+
+/* ----------------------------------------------------------------------- */
+
+#if defined(OPJ_BIG_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
+ #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
+#endif
+
+
+
+typedef enum
+{
+ opj_signed_sentinel = -1, /* do not use in code */
+ 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;
+
+ /**
+ * User data length
+ */
+ OPJ_UINT64 m_user_data_length;
+
+ /**
+ * 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_OFF_T (* m_opj_skip)(struct opj_stream_private * ,OPJ_OFF_T , struct opj_event_mgr *);
+
+ opj_bool (* m_opj_seek) (struct opj_stream_private * , OPJ_OFF_T , struct opj_event_mgr *);
+
+ /**
+ * number of bytes containing in the buffer.
+ */
+ OPJ_SIZE_T m_bytes_in_buffer;
+
+ /**
+ * The number of bytes read/written from the beginning of the stream
+ */
+ OPJ_OFF_T m_byte_offset;
+
+ /**
+ * The size of the buffer.
+ */
+ OPJ_SIZE_T m_buffer_size;
+
+ /**
+ * Flags to tell the status of the stream.
+ */
+ opj_stream_flag 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_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T 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_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_SIZE_T 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.
+ */
+opj_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_OFF_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_OFF_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_OFF_T opj_stream_tell (const opj_stream_private_t * p_stream);
+
+
+/**
+ * Get the number of bytes left before the end of the stream (similar to cio_numbytesleft).
+ *
+ * @param p_stream the stream to get the information from.
+ *
+ * @return Number of bytes left before the end of the stream.
+ */
+OPJ_OFF_T opj_stream_get_number_byte_left (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_OFF_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_OFF_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_OFF_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_OFF_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 OPJ_TRUE if success, or OPJ_FALSE if an error occured.
+ */
+opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_OFF_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_bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_OFF_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.
+ */
+opj_bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr);
+
+/**
+ * Tells if the given stream is seekable.
+ */
+opj_bool opj_stream_has_seek (const opj_stream_private_t * p_stream);
+
+OPJ_SIZE_T opj_stream_default_read (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data);
+OPJ_SIZE_T opj_stream_default_write (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data);
+OPJ_OFF_T opj_stream_default_skip (OPJ_OFF_T p_nb_bytes, void * p_user_data);
+opj_bool opj_stream_default_seek (OPJ_OFF_T p_nb_bytes, void * p_user_data);
+
+
+
+#endif /* __CIO_H */
+
diff --git a/src/lib/openjp2/dwt.c b/src/lib/openjp2/dwt.c
new file mode 100644
index 00000000..94586eb5
--- /dev/null
+++ b/src/lib/openjp2/dwt.c
@@ -0,0 +1,1061 @@
+/*
+ * 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 <dzonatas@dzonux.net>
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * 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 <xmmintrin.h>
+#endif
+
+#include "opj_includes.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 opj_dwt_alpha = 1.586134342f; /* 12994 */
+static const OPJ_FLOAT32 opj_dwt_beta = 0.052980118f; /* 434 */
+static const OPJ_FLOAT32 opj_dwt_gamma = -0.882911075f; /* -7233 */
+static const OPJ_FLOAT32 opj_dwt_delta = -0.443506852f; /* -3633 */
+
+static const OPJ_FLOAT32 opj_K = 1.230174105f; /* 10078 */
+static const OPJ_FLOAT32 opj_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 opj_dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+/**
+Forward lazy transform (vertical)
+*/
+static void opj_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 opj_dwt_interleave_h(dwt_t* h, OPJ_INT32 *a);
+/**
+Inverse lazy transform (vertical)
+*/
+static void opj_dwt_interleave_v(dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x);
+/**
+Forward 5-3 wavelet transform in 1-D
+*/
+static void opj_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 opj_dwt_decode_1(dwt_t *v);
+static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+/**
+Forward 9-7 wavelet transform in 1-D
+*/
+static void opj_dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas);
+/**
+Explicit calculation of the Quantization Stepsizes
+*/
+static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize);
+/**
+Inverse wavelet transform in 2-D.
+*/
+static opj_bool opj_dwt_decode_tile(opj_tcd_tilecomp_v2_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
+
+static opj_bool opj_dwt_encode_procedure( opj_tcd_tilecomp_v2_t * tilec,
+ void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) );
+
+static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_v2_t* restrict r, OPJ_UINT32 i);
+
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 1-D. */
+/* </summary> */
+static void opj_v4dwt_decode(v4dwt_t* restrict dwt);
+
+static void opj_v4dwt_interleave_h(v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size);
+
+static void opj_v4dwt_interleave_v(v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read);
+
+#ifdef __SSE__
+static void opj_v4dwt_decode_step1_sse(v4* w, OPJ_INT32 count, const __m128 c);
+
+static void opj_v4dwt_decode_step2_sse(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, __m128 c);
+#endif
+
+static void opj_v4dwt_decode_step1(v4* w, OPJ_INT32 count, const OPJ_FLOAT32 c);
+static void opj_v4dwt_decode_step2(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c);
+
+
+/*@}*/
+
+/*@}*/
+
+#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)))
+
+/* <summary> */
+/* This table contains the norms of the 5-3 wavelets for different bands. */
+/* </summary> */
+static const OPJ_FLOAT64 opj_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}
+};
+
+/* <summary> */
+/* This table contains the norms of the 9-7 wavelets for different bands. */
+/* </summary> */
+static const OPJ_FLOAT64 opj_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
+==========================================================
+*/
+
+/* <summary> */
+/* Forward lazy transform (horizontal). */
+/* </summary> */
+void opj_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<sn; ++i) {
+ *l_dest++ = *l_src;
+ l_src += 2;
+ }
+
+ l_dest = b + sn;
+ l_src = a + 1 - cas;
+
+ for (i=0; i<dn; ++i) {
+ *l_dest++=*l_src;
+ l_src += 2;
+ }
+}
+
+/* <summary> */
+/* Forward lazy transform (vertical). */
+/* </summary> */
+void opj_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)];*/
+}
+
+/* <summary> */
+/* Inverse lazy transform (horizontal). */
+/* </summary> */
+void opj_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;
+ }
+}
+
+/* <summary> */
+/* Inverse lazy transform (vertical). */
+/* </summary> */
+void opj_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;
+ }
+}
+
+
+/* <summary> */
+/* Forward 5-3 wavelet transform in 1-D. */
+/* </summary> */
+void opj_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;
+ }
+ }
+}
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 1-D. */
+/* </summary> */
+void opj_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;
+ }
+ }
+}
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 1-D. */
+/* </summary> */
+void opj_dwt_decode_1(dwt_t *v) {
+ opj_dwt_decode_1_(v->mem, v->dn, v->sn, v->cas);
+}
+
+/* <summary> */
+/* Forward 9-7 wavelet transform in 1-D. */
+/* </summary> */
+void opj_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 */
+ }
+ }
+}
+
+void opj_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
+==========================================================
+*/
+
+
+/* <summary> */
+/* Forward 5-3 wavelet transform in 2-D. */
+/* </summary> */
+INLINE opj_bool opj_dwt_encode_procedure(opj_tcd_tilecomp_v2_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_v2_t * l_cur_res = 0;
+ opj_tcd_resolution_v2_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 = opj_dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * sizeof(OPJ_INT32);
+ bj = (OPJ_INT32*)opj_malloc(l_data_size);
+ if (! bj) {
+ return OPJ_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);
+
+ opj_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);
+ opj_dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+ }
+
+ l_cur_res = l_last_res;
+
+ --l_last_res;
+ }
+
+ opj_free(bj);
+ return OPJ_TRUE;
+}
+
+/* Forward 5-3 wavelet transform in 2-D. */
+/* </summary> */
+opj_bool opj_dwt_encode(opj_tcd_tilecomp_v2_t * tilec)
+{
+ return opj_dwt_encode_procedure(tilec,opj_dwt_encode_1);
+}
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 2-D. */
+/* </summary> */
+opj_bool opj_dwt_decode(opj_tcd_tilecomp_v2_t* tilec, OPJ_UINT32 numres) {
+ return opj_dwt_decode_tile(tilec, numres, &opj_dwt_decode_1);
+}
+
+
+/* <summary> */
+/* Get gain of 5-3 wavelet transform. */
+/* </summary> */
+OPJ_UINT32 opj_dwt_getgain(OPJ_UINT32 orient) {
+ if (orient == 0)
+ return 0;
+ if (orient == 1 || orient == 2)
+ return 1;
+ return 2;
+}
+
+/* <summary> */
+/* Get norm of 5-3 wavelet. */
+/* </summary> */
+double dwt_getnorm(int level, int orient) {
+ return opj_dwt_norms[orient][level];
+}
+
+/* <summary> */
+/* Get norm of 5-3 wavelet. */
+/* </summary> */
+OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) {
+ return opj_dwt_norms[orient][level];
+}
+
+/* <summary> */
+/* Forward 9-7 wavelet transform in 2-D. */
+/* </summary> */
+opj_bool opj_dwt_encode_real(opj_tcd_tilecomp_v2_t * tilec)
+{
+ return opj_dwt_encode_procedure(tilec,opj_dwt_encode_1_real);
+}
+
+/* <summary> */
+/* Get gain of 9-7 wavelet transform. */
+/* </summary> */
+OPJ_UINT32 opj_dwt_getgain_real(OPJ_UINT32 orient) {
+ (void)orient;
+ return 0;
+}
+
+/* <summary> */
+/* Get norm of 9-7 wavelet. */
+/* </summary> */
+double dwt_getnorm_real(int level, int orient) {
+ return opj_dwt_norms_real[orient][level];
+}
+
+/* <summary> */
+/* Get norm of 9-7 wavelet. */
+/* </summary> */
+OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) {
+ return opj_dwt_norms_real[orient][level];
+}
+
+void opj_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 = opj_dwt_norms_real[orient][level];
+ stepsize = (1 << (gain)) / norm;
+ }
+ opj_dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]);
+ }
+}
+
+#ifdef OPJ_V1
+/* <summary> */
+/* Determine maximum computed resolution level for inverse wavelet transform */
+/* </summary> */
+static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) {
+ int mr = 1;
+ int w;
+ while( --i ) {
+ r++;
+ if( mr < ( w = r->x1 - r->x0 ) )
+ mr = w ;
+ if( mr < ( w = r->y1 - r->y0 ) )
+ mr = w ;
+ }
+ return mr ;
+}
+#endif
+/* <summary> */
+/* Determine maximum computed resolution level for inverse wavelet transform */
+/* </summary> */
+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 ;
+}
+
+/* <summary> */
+/* Determine maximum computed resolution level for inverse wavelet transform */
+/* </summary> */
+OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_v2_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 ;
+}
+
+/* <summary> */
+/* Inverse wavelet transform in 2-D. */
+/* </summary> */
+opj_bool opj_dwt_decode_tile(opj_tcd_tilecomp_v2_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) {
+ dwt_t h;
+ dwt_t v;
+
+ opj_tcd_resolution_v2_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_INT32*)
+ opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
+ if
+ (! h.mem)
+ {
+ return OPJ_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) {
+ opj_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;
+ opj_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 OPJ_TRUE;
+}
+
+void opj_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){
+ if ( count + 3 * x < size && ((size_t) a & 0x0f) == 0 && ((size_t) bi & 0x0f) == 0 && (x & 0x0f) == 0 ) {
+ /* Fast code path */
+ for(i = 0; i < count; ++i){
+ OPJ_INT32 j = i;
+ bi[i*8 ] = a[j];
+ j += x;
+ bi[i*8 + 1] = a[j];
+ j += x;
+ bi[i*8 + 2] = a[j];
+ j += x;
+ bi[i*8 + 3] = a[j];
+ }
+ }
+ else {
+ /* Slow code path */
+ 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]; /* This one*/
+ }
+ }
+
+ bi = (float*) (w->wavelet + 1 - w->cas);
+ a += w->sn;
+ size -= w->sn;
+ count = w->dn;
+ }
+}
+
+void opj_v4dwt_interleave_v(v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x, OPJ_INT32 nb_elts_read){
+ v4* restrict bi = v->wavelet + v->cas;
+ OPJ_INT32 i;
+
+ for(i = 0; i < v->sn; ++i){
+ memcpy(&bi[i*2], &a[i*x], nb_elts_read * 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], nb_elts_read * sizeof(OPJ_FLOAT32));
+ }
+}
+
+#ifdef __SSE__
+
+void opj_v4dwt_decode_step1_sse(v4* w, int count, const __m128 c){
+ __m128* restrict vw = (__m128*) w;
+ OPJ_INT32 i;
+ /* 4x unrolled loop */
+ for(i = 0; i < count >> 2; ++i){
+ *vw = _mm_mul_ps(*vw, c);
+ vw += 2;
+ *vw = _mm_mul_ps(*vw, c);
+ vw += 2;
+ *vw = _mm_mul_ps(*vw, c);
+ vw += 2;
+ *vw = _mm_mul_ps(*vw, c);
+ vw += 2;
+ }
+ count &= 3;
+ for(i = 0; i < count; ++i){
+ *vw = _mm_mul_ps(*vw, c);
+ vw += 2;
+ }
+}
+
+void opj_v4dwt_decode_step2_sse(v4* l, v4* w, int k, int m, __m128 c){
+ __m128* restrict vl = (__m128*) l;
+ __m128* restrict vw = (__m128*) w;
+ int i;
+ __m128 tmp1, tmp2, tmp3;
+ tmp1 = vl[0];
+ for(i = 0; i < m; ++i){
+ tmp2 = vw[-1];
+ tmp3 = vw[ 0];
+ vw[-1] = _mm_add_ps(tmp2, _mm_mul_ps(_mm_add_ps(tmp1, tmp3), c));
+ tmp1 = tmp3;
+ vw += 2;
+ }
+ vl = vw - 2;
+ if(m >= k){
+ return;
+ }
+ c = _mm_add_ps(c, c);
+ c = _mm_mul_ps(c, vl[0]);
+ for(; m < k; ++m){
+ __m128 tmp = vw[-1];
+ vw[-1] = _mm_add_ps(tmp, c);
+ vw += 2;
+ }
+}
+
+#else
+
+void opj_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;
+ }
+}
+
+void opj_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;
+ int 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
+
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 1-D. */
+/* </summary> */
+void opj_v4dwt_decode(v4dwt_t* restrict dwt)
+{
+ int 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__
+ opj_v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(opj_K));
+ opj_v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(opj_c13318));
+ opj_v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(opj_dwt_delta));
+ opj_v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(opj_dwt_gamma));
+ opj_v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(opj_dwt_beta));
+ opj_v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(opj_dwt_alpha));
+#else
+ opj_v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, opj_K);
+ opj_v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, opj_c13318);
+ opj_v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), opj_dwt_delta);
+ opj_v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), opj_dwt_gamma);
+ opj_v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), opj_dwt_beta);
+ opj_v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), opj_dwt_alpha);
+#endif
+}
+
+
+/* KEEP TRUNK VERSION + return type of v2 because rev557 */
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 2-D. */
+/* </summary> */
+/* V1 void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){ */
+opj_bool dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres)
+{
+ v4dwt_t h;
+ v4dwt_t v;
+
+ opj_tcd_resolution_t* res = tilec->resolutions;
+
+ int rw = res->x1 - res->x0; /* width of the resolution level computed */
+ int rh = res->y1 - res->y0; /* height of the resolution level computed */
+
+ int 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) {
+ float * restrict aj = (float*) tilec->data;
+ int bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0);
+ int 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 % 2;
+
+ for(j = rh; j > 3; j -= 4){
+ int k;
+ opj_v4dwt_interleave_h(&h, aj, w, bufsize);
+ opj_v4dwt_decode(&h);
+ for(k = rw; --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];
+ }
+ aj += w*4;
+ bufsize -= w*4;
+ }
+ if (rh & 0x03) {
+ int k;
+ j = rh & 0x03;
+ opj_v4dwt_interleave_h(&h, aj, w, bufsize);
+ opj_v4dwt_decode(&h);
+ for(k = rw; --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];
+ }
+ }
+ }
+
+ v.dn = rh - v.sn;
+ v.cas = res->y0 % 2;
+
+ aj = (float*) tilec->data;
+ for(j = rw; j > 3; j -= 4){
+ int k;
+ opj_v4dwt_interleave_v(&v, aj, w, 4);
+ opj_v4dwt_decode(&v);
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(float));
+ }
+ aj += 4;
+ }
+ if (rw & 0x03){
+ int k;
+ j = rw & 0x03;
+ opj_v4dwt_interleave_v(&v, aj, w, j);
+ opj_v4dwt_decode(&v);
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(float));
+ }
+ }
+ }
+
+ opj_aligned_free(h.wavelet);
+ return OPJ_TRUE;
+}
+
+
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 2-D. */
+/* </summary> */
+opj_bool dwt_decode_real_v2(opj_tcd_tilecomp_v2_t* restrict tilec, OPJ_UINT32 numres)
+{
+ v4dwt_t h;
+ v4dwt_t v;
+
+ opj_tcd_resolution_v2_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((opj_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 % 2;
+
+ for(j = rh; j > 3; j -= 4) {
+ OPJ_INT32 k;
+ opj_v4dwt_interleave_h(&h, aj, w, bufsize);
+ opj_v4dwt_decode(&h);
+
+ for(k = rw; --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];
+ }
+
+ aj += w*4;
+ bufsize -= w*4;
+ }
+
+ if (rh & 0x03) {
+ OPJ_INT32 k;
+ j = rh & 0x03;
+ opj_v4dwt_interleave_h(&h, aj, w, bufsize);
+ opj_v4dwt_decode(&h);
+ for(k = rw; --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];
+ }
+ }
+ }
+
+ v.dn = rh - v.sn;
+ v.cas = res->y0 % 2;
+
+ aj = (OPJ_FLOAT32*) tilec->data;
+ for(j = rw; j > 3; j -= 4){
+ OPJ_UINT32 k;
+
+ opj_v4dwt_interleave_v(&v, aj, w, 4);
+ opj_v4dwt_decode(&v);
+
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32));
+ }
+ aj += 4;
+ }
+
+ if (rw & 0x03){
+ OPJ_UINT32 k;
+
+ j = rw & 0x03;
+
+ opj_v4dwt_interleave_v(&v, aj, w, j);
+ opj_v4dwt_decode(&v);
+
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(OPJ_FLOAT32));
+ }
+ }
+ }
+
+ opj_aligned_free(h.wavelet);
+ return OPJ_TRUE;
+}
diff --git a/src/lib/openjp2/dwt.h b/src/lib/openjp2/dwt.h
new file mode 100644
index 00000000..88308164
--- /dev/null
+++ b/src/lib/openjp2/dwt.h
@@ -0,0 +1,122 @@
+/*
+ * 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 __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.
+*/
+
+/** @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)
+*/
+opj_bool opj_dwt_encode(opj_tcd_tilecomp_v2_t * 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
+*/
+opj_bool opj_dwt_decode(opj_tcd_tilecomp_v2_t* 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 opj_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
+*/
+double dwt_getnorm(int level, int orient); /* TODO REMOVE IT*/
+OPJ_FLOAT64 opj_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)
+*/
+opj_bool opj_dwt_encode_real(opj_tcd_tilecomp_v2_t * tilec);
+/**
+KEEP TRUNK VERSION + return type of v2 because rev557
+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
+*/
+/* V1 void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres); */
+opj_bool dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres);
+
+opj_bool dwt_decode_real_v2(opj_tcd_tilecomp_v2_t* restrict 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 opj_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
+*/
+double dwt_getnorm_real(int level, int orient);
+OPJ_FLOAT64 opj_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 opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __DWT_H */
diff --git a/src/lib/openjp2/event.c b/src/lib/openjp2/event.c
new file mode 100644
index 00000000..23978b5b
--- /dev/null
+++ b/src/lib/openjp2/event.c
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.h"
+
+/* ==========================================================
+ Utility functions
+ ==========================================================*/
+
+#ifdef OPJ_CODE_NOT_USED
+#ifndef _WIN32
+static char*
+i2a(unsigned i, char *a, unsigned r) {
+ if (i/r > 0) a = i2a(i/r,a,r);
+ *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
+ return a+1;
+}
+
+/**
+ Transforms integer i into an ascii string and stores the result in a;
+ string is encoded in the base indicated by r.
+ @param i Number to be converted
+ @param a String result
+ @param r Base of value; must be in the range 2 - 36
+ @return Returns a
+*/
+static char *
+_itoa(int i, char *a, int r) {
+ r = ((r < 2) || (r > 36)) ? 10 : r;
+ if(i < 0) {
+ *a = '-';
+ *i2a(-i, a+1, r) = 0;
+ }
+ else *i2a(i, a, r) = 0;
+ return a;
+}
+
+#endif /* !_WIN32 */
+#endif
+
+/* ----------------------------------------------------------------------- */
+/**
+ * Default callback function.
+ * Do nothing.
+ */
+static void opj_default_callback (const char *msg, void *client_data){}
+
+/* ----------------------------------------------------------------------- */
+opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
+#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */
+ opj_msg_callback msg_handler = NULL;
+
+ opj_event_mgr_t *event_mgr = cinfo->event_mgr;
+ if(event_mgr != NULL) {
+ switch(event_type) {
+ case EVT_ERROR:
+ msg_handler = event_mgr->error_handler;
+ break;
+ case EVT_WARNING:
+ msg_handler = event_mgr->warning_handler;
+ break;
+ case EVT_INFO:
+ msg_handler = event_mgr->info_handler;
+ break;
+ default:
+ break;
+ }
+ if(msg_handler == NULL) {
+ return OPJ_FALSE;
+ }
+ } else {
+ return OPJ_FALSE;
+ }
+
+ if ((fmt != NULL) && (event_mgr != NULL)) {
+ va_list arg;
+ int str_length/*, i, j*/; /* UniPG */
+ 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, cinfo->client_data);
+ }
+
+ return OPJ_TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+opj_bool opj_event_msg_v2(opj_event_mgr_t* p_event_mgr, int event_type, const 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 OPJ_FALSE;
+ }
+ } else {
+ return OPJ_FALSE;
+ }
+
+ if ((fmt != 00) && (p_event_mgr != 00)) {
+ va_list arg;
+ int str_length/*, i, j*/; /* UniPG */
+ 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 OPJ_TRUE;
+}
+
+void opj_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;
+}
+
diff --git a/src/lib/openjp2/event.h b/src/lib/openjp2/event.h
new file mode 100644
index 00000000..111cea9f
--- /dev/null
+++ b/src/lib/openjp2/event.h
@@ -0,0 +1,104 @@
+/*
+ * 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 __EVENT_H
+#define __EVENT_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
+<ul>
+<li>Error messages
+<li>Warning messages
+<li>Debugging messages
+</ul>
+*/
+#if 0
+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;
+#endif
+
+#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) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Write formatted data to a string and send the string to a user callback.
+@param cinfo Codec context info
+@param event_type Event type or callback to use to send the message
+@param fmt Format-control string (plus optional arguments)
+@return Returns true if successful, returns false otherwise
+* FIXME Change by its v2 version this function after ended the merge
+*/
+opj_bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
+
+/* ----------------------------------------------------------------------- */
+
+/**
+ * Write formatted data to a string and send the string to a user callback.
+ *
+ * @param event_mgr Event handler
+ * @param event_type Event type or callback to use to send the message
+ * @param fmt Format-control string (plus optional arguments)
+ *
+ * @return Returns true if successful, returns false otherwise
+ */
+opj_bool opj_event_msg_v2(opj_event_mgr_t* event_mgr, int event_type, const char *fmt, ...);
+/* ----------------------------------------------------------------------- */
+
+/**
+ * Set the event manager with the default callback function for the 3 levels.
+ */
+void opj_set_default_event_handler(opj_event_mgr_t * p_manager);
+
+/*@}*/
+
+/*@}*/
+
+#endif /* __EVENT_H */
diff --git a/src/lib/openjp2/fix.h b/src/lib/openjp2/fix.h
new file mode 100644
index 00000000..bcb2acb5
--- /dev/null
+++ b/src/lib/openjp2/fix.h
@@ -0,0 +1,64 @@
+/*
+ * 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
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define int64 __int64
+#else
+#define int64 long long
+#endif
+
+/**
+@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) {
+ int64 temp = (int64) a * (int64) b ;
+ temp += temp & 4096;
+ return (int) (temp >> 13) ;
+}
+
+/*@}*/
+
+#endif /* __FIX_H */
diff --git a/src/lib/openjp2/function_list.c b/src/lib/openjp2/function_list.c
new file mode 100644
index 00000000..1f84a429
--- /dev/null
+++ b/src/lib/openjp2/function_list.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
+ * 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"
+
+/**
+ * Default size of the validation list, if not sufficient, data will be reallocated with a double size.
+ */
+#define OPJ_VALIDATION_SIZE 10
+
+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_procedure*)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;
+}
+
+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);
+}
+
+opj_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)
+ {
+ opj_procedure * new_procedures;
+
+ p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE;
+ new_procedures = (opj_procedure*)opj_realloc(
+ p_validation_list->m_procedures,
+ p_validation_list->m_nb_max_procedures * sizeof(opj_procedure));
+ if (! new_procedures)
+ {
+ opj_free(p_validation_list->m_procedures);
+ p_validation_list->m_nb_max_procedures = 0;
+ p_validation_list->m_nb_procedures = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add a new validation procedure\n"); */
+ fprintf(stderr, "Not enough memory to add a new validation procedure\n");
+
+ return OPJ_FALSE;
+ }
+ else
+ {
+ p_validation_list->m_procedures = new_procedures;
+ }
+ }
+ p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = p_procedure;
+ ++p_validation_list->m_nb_procedures;
+
+ return OPJ_TRUE;
+}
+
+OPJ_UINT32 opj_procedure_list_get_nb_procedures (opj_procedure_list_t * p_validation_list)
+{
+ return p_validation_list->m_nb_procedures;
+}
+
+opj_procedure* opj_procedure_list_get_first_procedure (opj_procedure_list_t * p_validation_list)
+{
+ return p_validation_list->m_procedures;
+}
+
+void opj_procedure_list_clear (opj_procedure_list_t * p_validation_list)
+{
+ p_validation_list->m_nb_procedures = 0;
+}
diff --git a/src/lib/openjp2/function_list.h b/src/lib/openjp2/function_list.h
new file mode 100644
index 00000000..3707eec5
--- /dev/null
+++ b/src/lib/openjp2/function_list.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
+ * 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*/
+/*@{*/
+
+/**************************************************************************************************
+ ***************************************** FORWARD DECLARATION ************************************
+ **************************************************************************************************/
+
+/**
+ * declare a function pointer
+ */
+typedef void (*opj_procedure)(void);
+
+/**
+ * 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 OPJ_FALSE if the procedure could ne added.
+ */
+opj_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/src/lib/openjp2/image.c b/src/lib/openjp2/image.c
new file mode 100644
index 00000000..c9ae8216
--- /dev/null
+++ b/src/lib/openjp2/image.c
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.h"
+
+opj_image_t* opj_image_create0(void) {
+ opj_image_t *image = (opj_image_t*)opj_calloc(1, 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 = NULL;
+
+ image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t));
+ if(image) {
+ 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) {
+ fprintf(stderr,"Unable to allocate memory for image.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ /* 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->bpp = cmptparms[compno].bpp;
+ comp->sgnd = cmptparms[compno].sgnd;
+ comp->data = (int*) opj_calloc(comp->w * comp->h, sizeof(int));
+ if(!comp->data) {
+ fprintf(stderr,"Unable to allocate memory for image.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ }
+ }
+
+ return image;
+}
+
+void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) {
+ if(image) {
+ if(image->comps) {
+ OPJ_UINT32 compno;
+
+ /* image components */
+ for(compno = 0; compno < image->numcomps; compno++) {
+ opj_image_comp_t *image_comp = &(image->comps[compno]);
+ if(image_comp->data) {
+ opj_free(image_comp->data);
+ }
+ }
+ opj_free(image->comps);
+ }
+
+ if(image->icc_profile_buf) {
+ opj_free(image->icc_profile_buf);
+ }
+
+ opj_free(image);
+ }
+}
+
+/**
+ * Updates the components characteristics of the image from the coding parameters.
+ *
+ * @param p_image_header the image header to update.
+ * @param p_cp the coding parameters from which to update the image.
+ */
+void opj_image_comp_header_update(opj_image_t * p_image_header, const struct opj_cp_v2 * 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 = NULL;
+
+ l_x0 = int_max(p_cp->tx0 , p_image_header->x0);
+ l_y0 = int_max(p_cp->ty0 , p_image_header->y0);
+ l_x1 = int_min(p_cp->tx0 + p_cp->tw * p_cp->tdx, p_image_header->x1);
+ l_y1 = int_min(p_cp->ty0 + p_cp->th * p_cp->tdy, p_image_header->y1);
+
+ l_img_comp = p_image_header->comps;
+ for (i = 0; i < p_image_header->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_comp_x0/*l_x0*/;
+ l_img_comp->y0 = l_comp_y0/*l_y0*/;
+ ++l_img_comp;
+ }
+}
+
+
+/**
+ * Copy only header of image and its component header (no data are copied)
+ * if dest image have data, they will be freed
+ *
+ * @param p_image_src the src image
+ * @param p_image_dest the dest image
+ *
+ */
+void opj_copy_image_header(const opj_image_t* p_image_src, opj_image_t* p_image_dest)
+{
+ OPJ_UINT32 compno;
+
+ /* preconditions */
+ assert(p_image_src != 00);
+ assert(p_image_dest != 00);
+
+ p_image_dest->x0 = p_image_src->x0;
+ p_image_dest->y0 = p_image_src->y0;
+ p_image_dest->x1 = p_image_src->x1;
+ p_image_dest->y1 = p_image_src->y1;
+
+ if (p_image_dest->comps){
+ for(compno = 0; compno < p_image_dest->numcomps; compno++) {
+ opj_image_comp_t *image_comp = &(p_image_dest->comps[compno]);
+ if(image_comp->data) {
+ opj_free(image_comp->data);
+ }
+ }
+ opj_free(p_image_dest->comps);
+ p_image_dest->comps = NULL;
+ }
+
+ p_image_dest->numcomps = p_image_src->numcomps;
+
+ p_image_dest->comps = (opj_image_comp_t*) opj_malloc(p_image_dest->numcomps * sizeof(opj_image_comp_t));
+ if (!p_image_dest->comps){
+ p_image_dest->comps = NULL;
+ p_image_dest->numcomps = 0;
+ return;
+ }
+
+ for (compno=0; compno < p_image_dest->numcomps; compno++){
+ memcpy( &(p_image_dest->comps[compno]),
+ &(p_image_src->comps[compno]),
+ sizeof(opj_image_comp_t));
+ p_image_dest->comps[compno].data = NULL;
+ }
+
+ p_image_dest->color_space = p_image_src->color_space;
+ p_image_dest->icc_profile_len = p_image_src->icc_profile_len;
+
+ if (p_image_dest->icc_profile_len) {
+ p_image_dest->icc_profile_buf = (OPJ_BYTE*)opj_malloc(p_image_dest->icc_profile_len);
+ if (!p_image_dest->icc_profile_buf){
+ p_image_dest->icc_profile_buf = NULL;
+ p_image_dest->icc_profile_len = 0;
+ return;
+ }
+ memcpy( p_image_dest->icc_profile_buf,
+ p_image_src->icc_profile_buf,
+ p_image_src->icc_profile_len);
+ }
+ else
+ p_image_dest->icc_profile_buf = NULL;
+
+ return;
+}
+
+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;
+}
diff --git a/src/lib/openjp2/image.h b/src/lib/openjp2/image.h
new file mode 100644
index 00000000..a6cd9f58
--- /dev/null
+++ b/src/lib/openjp2/image.h
@@ -0,0 +1,63 @@
+/*
+ * 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 __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_v2;
+
+/** @defgroup IMAGE IMAGE - Implementation of operations on images */
+/*@{*/
+
+/**
+ * Create an empty image
+ *
+ * @return returns an empty image if successful, returns NULL otherwise
+ */
+opj_image_t* opj_image_create0(void);
+
+
+
+/**
+ * Updates the components characteristics of the image from the coding parameters.
+ *
+ * @param p_image_header the image header to update.
+ * @param p_cp the coding parameters from which to update the image.
+ */
+void opj_image_comp_header_update(opj_image_t * p_image, const struct opj_cp_v2* p_cp);
+
+void opj_copy_image_header(const opj_image_t* p_image_src, opj_image_t* p_image_dest);
+
+/*@}*/
+
+#endif /* __IMAGE_H */
+
diff --git a/src/lib/openjp2/indexbox_manager.h b/src/lib/openjp2/indexbox_manager.h
new file mode 100644
index 00000000..7364df62
--- /dev/null
+++ b/src/lib/openjp2/indexbox_manager.h
@@ -0,0 +1,118 @@
+/*
+ * $Id: indexbox_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.c from 2KAN indexer
+ */
+
+#ifndef INDEXBOX_MANAGER_H_
+# define INDEXBOX_MANAGER_H_
+
+#include "openjpeg.h"
+#include "j2k.h" /* needed to use jp2.h */
+#include "jp2.h"
+
+#define JPIP_CIDX 0x63696478 /* Codestream index */
+#define JPIP_CPTR 0x63707472 /* Codestream Finder Box */
+#define JPIP_MANF 0x6d616e66 /* Manifest Box */
+#define JPIP_FAIX 0x66616978 /* Fragment array Index box */
+#define JPIP_MHIX 0x6d686978 /* Main Header Index Table */
+#define JPIP_TPIX 0x74706978 /* Tile-part Index Table box */
+#define JPIP_THIX 0x74686978 /* Tile header Index Table box */
+#define JPIP_PPIX 0x70706978 /* Precinct Packet Index Table box */
+#define JPIP_PHIX 0x70686978 /* Packet Header index Table */
+#define JPIP_FIDX 0x66696478 /* File Index */
+#define JPIP_FPTR 0x66707472 /* File Finder */
+#define JPIP_PRXY 0x70727879 /* Proxy boxes */
+#define JPIP_IPTR 0x69707472 /* Index finder box */
+#define JPIP_PHLD 0x70686c64 /* Place holder */
+
+
+/*
+ * Write tile-part Index table box (superbox)
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of tpix box
+ */
+int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio);
+
+
+/*
+ * Write tile header index table box (superbox)
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information pointer
+ * @param[in] cio file output handle
+ * @return length of thix box
+ */
+int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio);
+
+
+/*
+ * Write precinct packet index table box (superbox)
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information
+ * @param[in] EPHused true if EPH option used
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of ppix box
+ */
+int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
+
+
+/*
+ * Write packet header index table box (superbox)
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information
+ * @param[in] EPHused true if EPH option used
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of ppix box
+ */
+int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
+
+/*
+ * Wriet manifest box (box)
+ *
+ * @param[in] second number to be visited
+ * @param[in] v number of boxes
+ * @param[in] box box to be manifested
+ * @param[in] cio file output handle
+ */
+void write_manf(int second, int v, opj_jp2_box_t *box, opj_cio_t *cio);
+
+
+#endif /* !INDEXBOX_MANAGER_H_ */
diff --git a/src/lib/openjp2/int.h b/src/lib/openjp2/int.h
new file mode 100644
index 00000000..57fec99d
--- /dev/null
+++ b/src/lib/openjp2/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
+ * 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.
+*/
+
+/** @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 int int_min(int a, int 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 int int_max(int a, int 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
+<ul>
+<li>Returns a if (min < a < max)
+<li>Returns max if (a > max)
+<li>Returns min if (a < min)
+</ul>
+*/
+static INLINE int int_clamp(int a, int min, int max) {
+ if (a < min)
+ return min;
+ if (a > max)
+ return max;
+ return a;
+}
+/**
+@return Get absolute value of integer
+*/
+static INLINE int int_abs(int a) {
+ return a < 0 ? -a : a;
+}
+/**
+Divide an integer and round upwards
+@return Returns a divided by b
+*/
+static INLINE int int_ceildiv(int a, int 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 int int_ceildivpow2(int a, int 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 int int_floordivpow2(int a, int b) {
+ return a >> b;
+}
+/**
+Get logarithm of an integer and round downwards
+@return Returns log2(a)
+*/
+static INLINE int int_floorlog2(int a) {
+ int 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/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
new file mode 100644
index 00000000..c76bcba5
--- /dev/null
+++ b/src/lib/openjp2/j2k.c
@@ -0,0 +1,9754 @@
+/*
+ * 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 <jerome.fimes@c-s.fr>
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011-2012, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
+ * 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"
+
+/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+ * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures.
+ */
+static void opj_j2k_setup_header_reading (opj_j2k_v2_t *p_j2k);
+
+/**
+ * The read header procedure.
+ */
+static opj_bool opj_j2k_read_header_procedure( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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.
+ */
+static opj_bool opj_j2k_encoding_validation ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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.
+ */
+static opj_bool opj_j2k_decoding_validation ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * 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 opj_j2k_setup_encoding_validation (opj_j2k_v2_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 opj_j2k_setup_decoding_validation (opj_j2k_v2_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 opj_j2k_setup_end_compress (opj_j2k_v2_t *p_j2k);
+
+/**
+ * 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.
+ */
+static opj_bool opj_j2k_mct_validation (opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Builds the tcd decoder to use to decode tile.
+ */
+static opj_bool opj_j2k_build_decoder ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+/**
+ * Builds the tcd encoder to use to encode tile.
+ */
+static opj_bool opj_j2k_build_encoder ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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.
+*/
+static opj_bool opj_j2k_create_tcd( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_exec ( opj_j2k_v2_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 opj_bool opj_j2k_update_rates( opj_j2k_v2_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.
+ */
+static opj_bool opj_j2k_copy_default_tcp_and_create_tcd ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Destroys the memory associated with the decoding of headers.
+ */
+static opj_bool opj_j2k_destroy_header_memory ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 * opj_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 opj_j2k_tcp_destroy (opj_tcp_v2_t *p_tcp);
+
+/**
+ * Destroys the data inside a tile coding parameter structure.
+ *
+ * @param p_tcp the tile coding parameter which contain data to destroy.
+ */
+static void opj_j2k_tcp_data_destroy (opj_tcp_v2_t *p_tcp);
+
+/**
+ * Destroys a coding parameter structure.
+ *
+ * @param p_cp the coding parameter to destroy.
+ */
+static void opj_j2k_cp_destroy (opj_cp_v2_t *p_cp);
+
+/**
+ * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
+ *
+ * @param p_j2k J2K codec.
+ * @param p_tile_no FIXME DOC
+ * @param p_comp_no the component number to output.
+ * @param p_data FIXME DOC
+ * @param p_header_size FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return FIXME DOC
+*/
+static opj_bool opj_j2k_write_SPCod_SPCoc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Gets the size taken by writing a SPCod or SPCoc for the given tile and component.
+ *
+ * @param p_j2k the J2K codec.
+ * @param p_tile_no the tile index.
+ * @param p_comp_no the component being outputted.
+ *
+ * @return the number of bytes taken by the SPCod element.
+ */
+static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size (opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no );
+
+/**
+ * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
+ * @param p_j2k the jpeg2000 codec.
+ * @param compno FIXME DOC
+ * @param p_header_data the data contained in the COM box.
+ * @param p_header_size the size of the data contained in the COM marker.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_SPCod_SPCoc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 compno,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param p_tile_no the tile index.
+ * @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 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_v2_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 opj_bool opj_j2k_write_SQcd_SQcc(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager);
+
+/**
+ * Updates the Tile Length Marker.
+ */
+static void opj_j2k_update_tlm ( opj_j2k_v2_t * p_j2k, OPJ_UINT32 p_tile_part_size);
+
+/**
+ * Reads a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param p_j2k J2K codec.
+ * @param compno the component number to output.
+ * @param p_header_data the data buffer.
+ * @param p_header_size pointer to the size of the data buffer, it is changed by the function.
+ * @param p_manager the user event manager.
+ *
+*/
+static opj_bool opj_j2k_read_SQcd_SQcc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 compno,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Copies the tile component parameters of all the component from the first tile component.
+ *
+ * @param p_j2k the J2k codec.
+ */
+static void opj_j2k_copy_tile_component_parameters( opj_j2k_v2_t *p_j2k );
+
+/**
+ * Copies the tile quantization parameters of all the component from the first tile component.
+ *
+ * @param p_j2k the J2k codec.
+ */
+static void opj_j2k_copy_tile_quantization_parameters( opj_j2k_v2_t *p_j2k );
+
+/**
+ * Reads the tiles.
+ */
+static opj_bool opj_j2k_decode_tiles ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager);
+
+static opj_bool opj_j2k_pre_write_tile ( opj_j2k_v2_t * p_j2k,
+ OPJ_UINT32 p_tile_index,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+static opj_bool opj_j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image);
+
+static void opj_j2k_get_tile_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data);
+
+static opj_bool opj_j2k_post_write_tile (opj_j2k_v2_t * p_j2k,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 p_data_size,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Sets up the procedures to do on writing header.
+ * Developers wanting to extend the library can add their own writing procedures.
+ */
+static void opj_j2k_setup_header_writting (opj_j2k_v2_t *p_j2k);
+
+static opj_bool opj_j2k_write_first_tile_part( opj_j2k_v2_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 opj_bool opj_j2k_write_all_tile_parts( opj_j2k_v2_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 );
+
+/**
+ * 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 opj_bool opj_j2k_get_end_header( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+static opj_bool opj_j2k_allocate_tile_element_cstr_index(opj_j2k_v2_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 opj_bool opj_j2k_write_soc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a SOC marker (Start of Codestream)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_stream XXX needs data
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_soc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the SIZ marker (image and tile size)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_siz( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a SIZ marker (image and tile size)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_header_data the data contained in the SIZ box.
+ * @param p_header_size the size of the data contained in the SIZ marker.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_siz(opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_com( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a COM marker (comments)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_header_data the data contained in the COM box.
+ * @param p_header_size the size of the data contained in the COM marker.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_com ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_cod( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_cod ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager);
+
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_comp_no the index of the component to output.
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_coc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_comp_no the index of the component to output.
+ * @param p_data FIXME DOC
+ * @param p_data_written FIXME DOC
+ * @param p_manager the user event manager.
+*/
+static void opj_j2k_write_coc_in_memory(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Gets the maximum size taken by a coc.
+ *
+ * @param p_j2k the jpeg2000 codec to use.
+ */
+static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_v2_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 opj_bool opj_j2k_read_coc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the QCD marker (quantization default)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_qcd( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_qcd ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_qcc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the QCC marker (quantization component)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_comp_no the index of the component to output.
+ * @param p_data FIXME DOC
+ * @param p_data_written the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static void opj_j2k_write_qcc_in_memory(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Gets the maximum size taken by a qcc.
+ */
+static OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_v2_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 opj_bool opj_j2k_read_qcc( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_poc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+/**
+ * Writes the POC marker (Progression Order Change)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_data FIXME DOC
+ * @param p_data_written the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+static void opj_j2k_write_poc_in_memory(opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * p_manager );
+/**
+ * Gets the maximum size taken by the writting of a POC.
+ */
+static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_v2_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 opj_bool opj_j2k_read_poc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Gets the maximum size taken by the toc headers of all the tile parts of any given tile.
+ */
+static OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_v2_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 opj_j2k_get_specific_header_sizes(opj_j2k_v2_t *p_j2k);
+
+/**
+ * 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 opj_bool opj_j2k_read_crg ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_tlm ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_updated_tlm( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_plm ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_plt ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+#if 0
+/**
+ * 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 opj_bool j2k_read_ppm_v2 (
+ opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ struct opj_event_mgr * p_manager
+ );
+#endif
+
+static opj_bool j2k_read_ppm_v3 (
+ opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_ppt ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_tlm( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the SOT marker (Start of tile-part)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_data FIXME DOC
+ * @param p_data_written FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_sot( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ const opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_sot ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+/**
+ * Writes the SOD marker (Start of data)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_tile_coder FIXME DOC
+ * @param p_data FIXME DOC
+ * @param p_data_written FIXME DOC
+ * @param p_total_data_size FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_sod( opj_j2k_v2_t *p_j2k,
+ opj_tcd_v2_t * p_tile_coder,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ OPJ_UINT32 p_total_data_size,
+ const opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a SOD marker (Start Of Data)
+ *
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_stream FIXME DOC
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_sod( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+void opj_j2k_update_tlm (opj_j2k_v2_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;
+}
+
+/**
+ * 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 opj_bool opj_j2k_write_rgn( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_rgn (opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_eoc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a EOC marker (End Of Codestream)
+ *
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_stream FIXME DOC
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_eoc ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_mct_data_group( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_init_info( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+Add main header marker information
+@param cstr_index Codestream information structure
+@param type marker type
+@param pos byte offset of marker segment
+@param len length of marker segment
+ */
+static opj_bool opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) ;
+/**
+Add tile header marker information
+@param tileno tile index number
+@param cstr_index Codestream information structure
+@param type marker type
+@param pos byte offset of marker segment
+@param len length of marker segment
+ */
+static opj_bool opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len);
+
+/**
+ * Reads an unknown marker
+ *
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_stream the stream object to read from.
+ * @param output_marker FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the marker could be deduced.
+*/
+static opj_bool opj_j2k_read_unk( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ OPJ_UINT32 *output_marker,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the MCT marker (Multiple Component Transform)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_mct_record FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_mct_record( opj_j2k_v2_t *p_j2k,
+ opj_mct_data_t * p_mct_record,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_mct ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes the MCC marker (Multiple Component Collection)
+ *
+ * @param p_j2k J2K codec.
+ * @param p_mcc_record FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_write_mcc_record( opj_j2k_v2_t *p_j2k,
+ opj_simple_mcc_decorrelation_data_t * p_mcc_record,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_mcc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_mco( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_mco ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+static opj_bool opj_j2k_add_mct(opj_tcp_v2_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index);
+
+static void opj_j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+
+static void opj_j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+
+static void opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+static void opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+
+/**
+ * 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 opj_bool opj_j2k_end_encoding( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_cbd( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_read_cbd ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_image_components( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_regions( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 opj_bool opj_j2k_write_epc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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.
+ * @param p_manager the user event manager.
+ *
+ * @return true if the pocs are valid.
+ */
+static opj_bool opj_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 opj_j2k_get_num_tp( opj_cp_v2_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 opj_bool opj_j2k_calculate_tp( opj_j2k_v2_t *p_j2k,
+ opj_cp_v2_t *cp,
+ OPJ_UINT32 * p_nb_tiles,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager);
+
+static void opj_j2k_dump_MH_info(opj_j2k_v2_t* p_j2k, FILE* out_stream);
+
+static void opj_j2k_dump_MH_index(opj_j2k_v2_t* p_j2k, FILE* out_stream);
+
+static opj_codestream_index_t* opj_j2k_create_cstr_index(void);
+
+static OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_v2_t * p_tcp);
+
+static OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_v2_t * p_tcp);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+typedef struct j2k_prog_order{
+ OPJ_PROG_ORDER enum_prog;
+ char str_prog[5];
+}j2k_prog_order_t;
+
+j2k_prog_order_t j2k_prog_order_list[] = {
+ {CPRL, "CPRL"},
+ {LRCP, "LRCP"},
+ {PCRL, "PCRL"},
+ {RLCP, "RLCP"},
+ {RPCL, "RPCL"},
+ {(OPJ_PROG_ORDER)-1, ""}
+};
+
+/**
+ * FIXME DOC
+ */
+static const OPJ_UINT32 MCT_ELEMENT_SIZE [] =
+{
+ 2,
+ 4,
+ 4,
+ 8
+};
+
+typedef void (* opj_j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
+
+const opj_j2k_mct_function j2k_mct_read_functions_to_float [] =
+{
+ opj_j2k_read_int16_to_float,
+ opj_j2k_read_int32_to_float,
+ opj_j2k_read_float32_to_float,
+ opj_j2k_read_float64_to_float
+};
+
+const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] =
+{
+ opj_j2k_read_int16_to_int32,
+ opj_j2k_read_int32_to_int32,
+ opj_j2k_read_float32_to_int32,
+ opj_j2k_read_float64_to_int32
+};
+
+const opj_j2k_mct_function j2k_mct_write_functions_from_float [] =
+{
+ opj_j2k_write_float_to_int16,
+ opj_j2k_write_float_to_int32,
+ opj_j2k_write_float_to_float,
+ opj_j2k_write_float_to_float64
+};
+
+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 */
+ opj_bool (*handler) ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+}
+opj_dec_memory_marker_handler_t;
+
+const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] =
+{
+ {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, opj_j2k_read_sot},
+ {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_cod},
+ {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_coc},
+ {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_rgn},
+ {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcd},
+ {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcc},
+ {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_poc},
+ {J2K_MS_SIZ, J2K_STATE_MHSIZ, opj_j2k_read_siz},
+ {J2K_MS_TLM, J2K_STATE_MH, opj_j2k_read_tlm},
+ {J2K_MS_PLM, J2K_STATE_MH, opj_j2k_read_plm},
+ {J2K_MS_PLT, J2K_STATE_TPH, opj_j2k_read_plt},
+ {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm_v3},
+ {J2K_MS_PPT, J2K_STATE_TPH, opj_j2k_read_ppt},
+ {J2K_MS_SOP, 0, 0},
+ {J2K_MS_CRG, J2K_STATE_MH, opj_j2k_read_crg},
+ {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_com},
+ {J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mct},
+ {J2K_MS_CBD, J2K_STATE_MH , opj_j2k_read_cbd},
+ {J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mcc},
+ {J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mco},
+#ifdef USE_JPWL
+#ifdef TODO_MS /* remove these functions which are not commpatible with the v2 API */
+ {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc},
+ {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb},
+ {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd},
+ {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red},
+#endif
+#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 */
+ {J2K_MS_UNK, J2K_STATE_MH | J2K_STATE_TPH, 0}/*opj_j2k_read_unk is directly used*/
+};
+
+void opj_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;i<p_nb_elem;++i) {
+ opj_read_bytes(l_src_data,&l_temp,2);
+
+ l_src_data+=sizeof(OPJ_INT16);
+
+ *(l_dest_data++) = (OPJ_FLOAT32) l_temp;
+ }
+}
+
+void opj_j2k_read_int32_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;i<p_nb_elem;++i) {
+ opj_read_bytes(l_src_data,&l_temp,4);
+
+ l_src_data+=sizeof(OPJ_INT32);
+
+ *(l_dest_data++) = (OPJ_FLOAT32) l_temp;
+ }
+}
+
+void opj_j2k_read_float32_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_FLOAT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_float(l_src_data,&l_temp);
+
+ l_src_data+=sizeof(OPJ_FLOAT32);
+
+ *(l_dest_data++) = l_temp;
+ }
+}
+
+void opj_j2k_read_float64_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_FLOAT64 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_double(l_src_data,&l_temp);
+
+ l_src_data+=sizeof(OPJ_FLOAT64);
+
+ *(l_dest_data++) = (OPJ_FLOAT32) l_temp;
+ }
+}
+
+void opj_j2k_read_int16_to_int32 (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_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_bytes(l_src_data,&l_temp,2);
+
+ l_src_data+=sizeof(OPJ_INT16);
+
+ *(l_dest_data++) = (OPJ_INT32) l_temp;
+ }
+}
+
+void opj_j2k_read_int32_to_int32 (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_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_bytes(l_src_data,&l_temp,4);
+
+ l_src_data+=sizeof(OPJ_INT32);
+
+ *(l_dest_data++) = (OPJ_INT32) l_temp;
+ }
+}
+
+void opj_j2k_read_float32_to_int32 (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_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
+ OPJ_UINT32 i;
+ OPJ_FLOAT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_float(l_src_data,&l_temp);
+
+ l_src_data+=sizeof(OPJ_FLOAT32);
+
+ *(l_dest_data++) = (OPJ_INT32) l_temp;
+ }
+}
+
+void opj_j2k_read_float64_to_int32 (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_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
+ OPJ_UINT32 i;
+ OPJ_FLOAT64 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ opj_read_double(l_src_data,&l_temp);
+
+ l_src_data+=sizeof(OPJ_FLOAT64);
+
+ *(l_dest_data++) = (OPJ_INT32) l_temp;
+ }
+}
+
+void opj_j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+{
+ OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
+ OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ l_temp = (OPJ_UINT32) *(l_src_data++);
+
+ opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT16));
+
+ l_dest_data+=sizeof(OPJ_INT16);
+ }
+}
+
+void opj_j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+{
+ OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
+ OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ l_temp = (OPJ_UINT32) *(l_src_data++);
+
+ opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT32));
+
+ l_dest_data+=sizeof(OPJ_INT32);
+ }
+}
+
+void opj_j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+{
+ OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
+ OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
+ OPJ_UINT32 i;
+ OPJ_FLOAT32 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ l_temp = (OPJ_FLOAT32) *(l_src_data++);
+
+ opj_write_float(l_dest_data,l_temp);
+
+ l_dest_data+=sizeof(OPJ_FLOAT32);
+ }
+}
+
+void opj_j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
+{
+ OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
+ OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
+ OPJ_UINT32 i;
+ OPJ_FLOAT64 l_temp;
+
+ for (i=0;i<p_nb_elem;++i) {
+ l_temp = (OPJ_FLOAT64) *(l_src_data++);
+
+ opj_write_double(l_dest_data,l_temp);
+
+ l_dest_data+=sizeof(OPJ_FLOAT64);
+ }
+}
+
+char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){
+ j2k_prog_order_t *po;
+ for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){
+ if(po->enum_prog == prg_order){
+ return po->str_prog;
+ }
+ }
+ return po->str_prog;
+}
+
+opj_bool opj_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;
+ opj_bool loss = OPJ_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_v2(p_manager , EVT_ERROR, "Not enough memory for checking the poc values.\n");
+ return OPJ_FALSE;
+ }
+ memset(packet_array,0,step_l * p_num_layers* sizeof(OPJ_UINT32));
+
+ if (p_nb_pocs == 0) {
+ return OPJ_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_v2(p_manager , EVT_ERROR, "Missing packets possible loss of data\n");
+ }
+
+ opj_free(packet_array);
+
+ return !loss;
+}
+
+/* ----------------------------------------------------------------------- */
+
+OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_v2_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno)
+{
+ const OPJ_CHAR *prog = 00;
+ OPJ_UINT32 i;
+ OPJ_UINT32 tpnum = 1;
+ opj_tcp_v2_t *tcp = 00;
+ opj_poc_t * l_current_poc = 00;
+
+ /* preconditions */
+ 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 = opj_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;
+}
+
+opj_bool opj_j2k_calculate_tp( opj_j2k_v2_t *p_j2k,
+ opj_cp_v2_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_v2_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 >> */
+ /* TODO mergeV2: check this part which use cstr_info */
+ /*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 = opj_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 OPJ_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 = opj_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_soc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 OPJ_FALSE;
+ }
+
+/* UniPG>> */
+#ifdef USE_JPWL
+ /* update markers struct */
+/*
+ opj_bool res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2);
+*/
+ assert( 0 && "TODO" );
+#endif /* USE_JPWL */
+/* <<UniPG */
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Reads a SOC marker (Start of Codestream)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_stream FIXME DOC
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_soc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_BYTE l_data [2];
+ OPJ_UINT32 l_marker;
+
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_stream != 00);
+
+ if (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) {
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(l_data,&l_marker,2);
+ if (l_marker != J2K_MS_SOC) {
+ return OPJ_FALSE;
+ }
+
+ /* Next marker should be a SIZ marker in the main header */
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSIZ;
+
+ /* FIXME move it in a index structure included in p_j2k*/
+ p_j2k->cstr_index->main_head_start = opj_stream_tell(p_stream) - 2;
+
+ opj_event_msg_v2(p_manager, EVT_INFO, "Start to read j2k main header (%d).\n", p_j2k->cstr_index->main_head_start);
+
+ /* Add the marker to the codestream index*/
+ if (OPJ_FALSE == opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_SOC, p_j2k->cstr_index->main_head_start, 2)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n");
+ return OPJ_FALSE;
+ }
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_siz( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_size_len;
+ OPJ_BYTE * l_current_ptr;
+ opj_image_t * l_image = 00;
+ opj_cp_v2_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_private_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) {
+
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory for the SIZ marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Reads a SIZ marker (image and tile size)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_header_data the data contained in the SIZ box.
+ * @param p_header_size the size of the data contained in the SIZ marker.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_siz(opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_v2_t *l_cp = 00;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcp_v2_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_private_image;
+ l_cp = &(p_j2k->m_cp);
+
+ /* minimum size == 39 - 3 (= minimum component parameter) */
+ if (p_header_size < 36) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with SIZ marker size\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error with SIZ marker size\n");
+ return OPJ_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, (OPJ_UINT32*) &l_cp->tdx, 4); /* XTsiz */
+ p_header_data+=4;
+ opj_read_bytes(p_header_data, (OPJ_UINT32*) &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, (OPJ_UINT32*) &l_tmp, 2); /* Csiz */
+ p_header_data+=2;
+ if (l_tmp < 16385)
+ l_image->numcomps = (OPJ_UINT16) l_tmp;
+ else {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with SIZ marker: number of component is illegal -> %d\n", l_tmp);
+ return OPJ_FALSE;
+ }
+
+ if (l_image->numcomps != l_nb_comp) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with SIZ marker: number of component is not compatible with the remaining number of parameters ( %d vs %d)\n", l_image->numcomps, l_nb_comp);
+ return OPJ_FALSE;
+ }
+
+#ifdef USE_JPWL
+ if (l_cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters */
+ if (!(l_image->x1 * l_image->y1)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "JPWL: bad image size (%d x %d)\n",
+ l_image->x1, l_image->y1);
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ }
+
+ /* FIXME check previously in the function so why keep this piece of code ? Need by the norm ?
+ if (l_image->numcomps != ((len - 38) / 3)) {
+ opj_event_msg_v2(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n",
+ l_image->numcomps, ((len - 38) / 3));
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ */ /* we try to correct */
+ /* opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust this\n");
+ if (l_image->numcomps < ((len - 38) / 3)) {
+ len = 38 + 3 * l_image->numcomps;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n",
+ len);
+ } else {
+ l_image->numcomps = ((len - 38) / 3);
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n",
+ l_image->numcomps);
+ }
+ }
+ */
+
+ /* update components number in the jpwl_exp_comps filed */
+ l_cp->exp_comps = l_image->numcomps;
+ }
+#endif /* USE_JPWL */
+
+ /* Allocate the resulting image components */
+ 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_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_FALSE;
+ }
+
+ memset(l_image->comps,0,l_image->numcomps * sizeof(opj_image_comp_t));
+ l_img_comp = l_image->comps;
+
+ /* Read the component information */
+ 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,&tmp,1); /* XRsiz_i */
+ ++p_header_data;
+ l_img_comp->dx = (OPJ_INT32)tmp; /* should be between 1 and 255 */
+ opj_read_bytes(p_header_data,&tmp,1); /* YRsiz_i */
+ ++p_header_data;
+ l_img_comp->dy = (OPJ_INT32)tmp; /* should be between 1 and 255 */
+
+#ifdef USE_JPWL
+ if (l_cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters, again */
+ if (!(l_image->comps[i].dx * l_image->comps[i].dy)) {
+ opj_event_msg_v2(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n",
+ i, i, l_image->comps[i].dx, l_image->comps[i].dy);
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust them\n");
+ if (!l_image->comps[i].dx) {
+ l_image->comps[i].dx = 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n",
+ i, l_image->comps[i].dx);
+ }
+ if (!l_image->comps[i].dy) {
+ l_image->comps[i].dy = 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n",
+ i, l_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;
+ }
+
+ /* Compute the number of tiles */
+ 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;
+
+ /* Define the tiles which will be decoded */
+ 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 (l_cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters */
+ if ((l_cp->tw < 1) || (l_cp->th < 1) || (l_cp->tw > l_cp->max_tiles) || (l_cp->th > l_cp->max_tiles)) {
+ opj_event_msg_v2(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad number of tiles (%d x %d)\n",
+ l_cp->tw, l_cp->th);
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust them\n");
+ if (l_cp->tw < 1) {
+ l_cp->tw= 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n",
+ l_cp->tw);
+ }
+ if (l_cp->tw > l_cp->max_tiles) {
+ l_cp->tw= 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- too large x, increase expectance of %d\n"
+ "- setting %d tiles in x => HYPOTHESIS!!!\n",
+ l_cp->max_tiles, l_cp->tw);
+ }
+ if (l_cp->th < 1) {
+ l_cp->th= 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n",
+ l_cp->th);
+ }
+ if (l_cp->th > l_cp->max_tiles) {
+ l_cp->th= 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- too large y, increase expectance of %d to continue\n",
+ "- setting %d tiles in y => HYPOTHESIS!!!\n",
+ l_cp->max_tiles, l_cp->th);
+ }
+ }
+ }
+#endif /* USE_JPWL */
+
+ /* memory allocations */
+ l_cp->tcps = (opj_tcp_v2_t*) opj_calloc(l_nb_tiles, sizeof(opj_tcp_v2_t));
+ if (l_cp->tcps == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_FALSE;
+ }
+ memset(l_cp->tcps,0,l_nb_tiles*sizeof(opj_tcp_t));
+
+#ifdef USE_JPWL
+ if (l_cp->correct) {
+ if (!l_cp->tcps) {
+ opj_event_msg_v2(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: could not alloc tcps field of cp\n");
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ }
+ }
+#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_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_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_mct_data_t*)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_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_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_simple_mcc_decorrelation_data_t*)
+ 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_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_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;i<l_image->numcomps;++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_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n");
+ return OPJ_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_STATE_MH; /* FIXME J2K_DEC_STATE_MH; */
+ opj_image_comp_header_update(l_image,l_cp);
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_com( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write the COM marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Reads a COM marker (comments)
+ * @param p_j2k the jpeg2000 file codec.
+ * @param p_header_data the data contained in the COM box.
+ * @param p_header_size the size of the data contained in the COM marker.
+ * @param p_manager the user event manager.
+*/
+static opj_bool opj_j2k_read_com ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_header_data != 00);
+ (void)p_header_size;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_cod( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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 + opj_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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write COD marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 (! opj_j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting COD marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (l_remaining_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting COD marker\n");
+ return OPJ_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 OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_cod ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* loop */
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_tmp;
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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_image = p_j2k->m_private_image;
+ l_cp = &(p_j2k->m_cp);
+
+ /* If we are in the first tile-part header of the current tile */
+ l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ?
+ &l_cp->tcps[p_j2k->m_current_tile_number] :
+ p_j2k->m_specific_param.m_decoder.m_default_tcp;
+
+ /* Make sure room is sufficient */
+ if (p_header_size < 5) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COD marker\n");
+ return OPJ_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 user didn't set a number layer to decode take the max specify in the codestream. */
+ 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 (! opj_j2k_read_SPCod_SPCoc(p_j2k,0,p_header_data,&p_header_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COD marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_header_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COD marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* Apply the coding style to other components of the current tile or the m_default_tcp*/
+ opj_j2k_copy_tile_component_parameters(p_j2k);
+
+ /* Index */
+#ifdef WIP_REMOVE_MSD
+ if (p_j2k->cstr_info) {
+ /*opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info;*/
+ p_j2k->cstr_info->prog = l_tcp->prg;
+ p_j2k->cstr_info->numlayers = l_tcp->numlayers;
+ p_j2k->cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(l_image->numcomps * sizeof(OPJ_UINT32));
+ for (i = 0; i < l_image->numcomps; ++i) {
+ p_j2k->cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1;
+ }
+ }
+#endif
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_coc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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_private_image->numcomps <= 256) ? 1 : 2;
+
+ l_coc_size = 5 + l_comp_room + opj_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) {
+ OPJ_BYTE *new_header_tile_data;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data
+ = (OPJ_BYTE*)opj_realloc(
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+ l_coc_size);
+
+ new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write COC marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size;
+ }
+
+ opj_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_write_coc_in_memory( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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_private_image;
+ l_comp_room = (l_image->numcomps <= 256) ? 1 : 2;
+
+ l_coc_size = 5 + l_comp_room + opj_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);
+ opj_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;
+}
+
+OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_v2_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_private_image->numcomps;
+
+ for (i=0;i<l_nb_tiles;++i) {
+ for (j=0;j<l_nb_comp;++j) {
+ l_max = uint_max(l_max,opj_j2k_get_SPCod_SPCoc_size(p_j2k,i,j));
+ }
+ }
+
+ return 6 + l_max;
+}
+
+/**
+ * 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 opj_bool opj_j2k_read_coc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_cp_v2_t *l_cp = NULL;
+ opj_tcp_v2_t *l_tcp = NULL;
+ opj_image_t *l_image = NULL;
+ 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_STATE_TPH ) ? /*FIXME 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_private_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_v2(p_manager, EVT_ERROR, "Error reading COC marker\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading COC marker (bad number of components)\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_header_data,&l_tcp->tccps[l_comp_no].csty,1); /* Scoc */
+ ++p_header_data ;
+
+ if (! opj_j2k_read_SPCod_SPCoc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COC marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_header_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COC marker\n");
+ return OPJ_FALSE;
+ }
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_qcd( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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 + opj_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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write QCD marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 (! opj_j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting QCD marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (l_remaining_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting QCD marker\n");
+ return OPJ_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 OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_qcd ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(p_header_data != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ if (! opj_j2k_read_SQcd_SQcc(p_j2k,0,p_header_data,&p_header_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading QCD marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_header_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading QCD marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* Apply the quantization parameters to other components of the current tile or the m_default_tcp */
+ opj_j2k_copy_tile_quantization_parameters(p_j2k);
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_qcc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 + opj_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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write QCC marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size;
+ }
+
+ opj_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_write_qcc_in_memory( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * 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 + opj_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_private_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;
+ }
+
+ opj_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;
+}
+
+OPJ_UINT32 opj_j2k_get_max_qcc_size (opj_j2k_v2_t *p_j2k)
+{
+ return opj_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.
+*/
+static opj_bool opj_j2k_read_qcc( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_private_image->numcomps;
+
+ if (l_num_comp <= 256) {
+ if (p_header_size < 1) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading QCC marker\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading QCC marker\n");
+ return OPJ_FALSE;
+ }
+ opj_read_bytes(p_header_data,&l_comp_no,2);
+ p_header_data+=2;
+ p_header_size-=2;
+ }
+
+#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 (/*(l_comp_no < 0) ||*/ (l_comp_no >= l_num_comp)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "JPWL: bad component number in QCC (%d out of a maximum of %d)\n",
+ l_comp_no, l_num_comp);
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ l_comp_no = backup_compno % l_num_comp;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust this\n"
+ "- setting component number to %d\n",
+ l_comp_no);
+ }
+
+ /* keep your private count of tiles */
+ backup_compno++;
+ };
+#endif /* USE_JPWL */
+
+ if (! opj_j2k_read_SQcd_SQcc(p_j2k,l_comp_no,p_header_data,&p_header_size,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading QCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_header_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading QCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_poc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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_v2_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_private_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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write POC marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size;
+ }
+
+ opj_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_write_poc_in_memory( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ opj_event_mgr_t * 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_v2_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_private_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;
+}
+
+OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_v2_t *p_j2k)
+{
+ opj_tcp_v2_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;i<l_nb_tiles;++i) {
+ l_max_poc = uint_max(l_max_poc,l_tcp->numpocs);
+ ++l_tcp;
+ }
+
+ ++l_max_poc;
+
+ return 4 + 9 * l_max_poc;
+}
+
+OPJ_UINT32 opj_j2k_get_max_toc_size (opj_j2k_v2_t *p_j2k)
+{
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_nb_tiles;
+ OPJ_UINT32 l_max = 0;
+ opj_tcp_v2_t * l_tcp = 00;
+
+ l_tcp = p_j2k->m_cp.tcps;
+ l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ;
+
+ for (i=0;i<l_nb_tiles;++i) {
+ l_max = uint_max(l_max,l_tcp->m_nb_tile_parts);
+
+ ++l_tcp;
+ }
+
+ return 12 * l_max;
+}
+
+OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_v2_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_private_image->numcomps - 1;
+ l_nb_bytes += opj_j2k_get_max_toc_size(p_j2k);
+
+ if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == 0) {
+ l_coc_bytes = opj_j2k_get_max_coc_size(p_j2k);
+ l_nb_bytes += l_nb_comps * l_coc_bytes;
+
+ l_qcc_bytes = opj_j2k_get_max_qcc_size(p_j2k);
+ l_nb_bytes += l_nb_comps * l_qcc_bytes;
+ }
+
+ l_nb_bytes += opj_j2k_get_max_poc_size(p_j2k);
+
+ /*** DEVELOPER CORNER, Add room for your headers ***/
+
+ return l_nb_bytes;
+}
+
+/**
+ * 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 opj_bool opj_j2k_read_poc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 i, l_nb_comp, l_tmp;
+ 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, l_comp_room;
+
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_t *l_tcp = 00;
+ opj_poc_t *l_current_poc = 00;
+
+ /* preconditions */
+ assert(p_header_data != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ l_image = p_j2k->m_private_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_v2(p_manager, EVT_ERROR, "Error reading POC marker\n");
+ return OPJ_FALSE;
+ }
+
+ l_cp = &(p_j2k->m_cp);
+ l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_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 OPJ_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.
+*/
+static opj_bool opj_j2k_read_crg ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_private_image->numcomps;
+
+ if (p_header_size != l_nb_comp *4) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading CRG marker\n");
+ return OPJ_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 OPJ_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.
+*/
+static opj_bool opj_j2k_read_tlm ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_v2(p_manager, EVT_ERROR, "Error reading TLM marker\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading TLM marker\n");
+ return OPJ_FALSE;
+ }
+ /* FIXME 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 OPJ_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.
+*/
+static opj_bool opj_j2k_read_plm ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(p_header_data != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ if (p_header_size < 1) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PLM marker\n");
+ return OPJ_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 OPJ_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.
+*/
+static opj_bool opj_j2k_read_plt ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_v2(p_manager, EVT_ERROR, "Error reading PLT marker\n");
+ return OPJ_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); /* Iplt_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_v2(p_manager, EVT_ERROR, "Error reading PLT marker\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+#if 0
+opj_bool j2k_read_ppm_v2 (
+ opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ struct opj_event_mgr * p_manager
+ )
+{
+
+ opj_cp_v2_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_v2(p_manager, EVT_ERROR, "Error reading PPM marker\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading PPM marker\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm */
+ p_header_data+=4;
+ p_header_size-=4;
+
+ /* First PPM marker: Initialization */
+ 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);
+ if (l_cp->ppm_buffer == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n");
+ return OPJ_FALSE;
+ }
+ memset(l_cp->ppm_buffer,0,l_cp->ppm_len);
+
+ l_cp->ppm_data = l_cp->ppm_buffer;
+ }
+
+ while (1) {
+ 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 ;
+
+ OPJ_BYTE *new_ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len);
+ if (! new_ppm_buffer) {
+ opj_free(l_cp->ppm_buffer);
+ l_cp->ppm_buffer = NULL;
+ l_cp->ppm_len = 0;
+ l_cp->ppm_data = NULL;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n");
+ return OPJ_FALSE;
+ }
+ l_cp->ppm_buffer = new_ppm_buffer;
+ memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm);
+ l_cp->ppm_data = l_cp->ppm_buffer;
+ }
+ else {
+ return OPJ_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 OPJ_TRUE;
+}
+#endif
+
+opj_bool j2k_read_ppm_v3 (
+ opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ struct opj_event_mgr * p_manager
+ )
+{
+ opj_cp_v2_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);
+
+ /* Minimum size of PPM marker is equal to the size of Zppm element */
+ if (p_header_size < 1) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PPM marker\n");
+ return OPJ_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) {
+ /* We need now at least the Nppm^0 element */
+ if (p_header_size < 4) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PPM marker\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_header_data,&l_N_ppm,4); /* First N_ppm */
+ p_header_data+=4;
+ p_header_size-=4;
+
+ /* First PPM marker: Initialization */
+ l_cp->ppm_len = l_N_ppm;
+ l_cp->ppm_data_read = 0;
+
+ l_cp->ppm_data = (OPJ_BYTE *) opj_malloc(l_cp->ppm_len);
+ l_cp->ppm_buffer = l_cp->ppm_data;
+ if (l_cp->ppm_data == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read ppm marker\n");
+ return OPJ_FALSE;
+ }
+ memset(l_cp->ppm_data,0,l_cp->ppm_len);
+
+ l_cp->ppm_data_current = l_cp->ppm_data;
+
+ /*l_cp->ppm_data = l_cp->ppm_buffer;*/
+ }
+ else {
+ if (p_header_size < 4) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Empty PPM marker\n");
+ return OPJ_TRUE;
+ }
+ else {
+ /* Uncompleted Ippm series in the previous PPM marker?*/
+ if (l_cp->ppm_data_read < l_cp->ppm_len) {
+ /* Get the place where add the remaining Ippm series*/
+ l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_data_read]);
+ l_N_ppm = l_cp->ppm_len - l_cp->ppm_data_read;
+ }
+ else {
+ OPJ_BYTE *new_ppm_data;
+ opj_read_bytes(p_header_data,&l_N_ppm,4); /* First N_ppm */
+ p_header_data+=4;
+ p_header_size-=4;
+
+ /* Increase the size of ppm_data to add the new Ippm series*/
+ assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
+ new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
+ if (! new_ppm_data) {
+ opj_free(l_cp->ppm_data);
+ l_cp->ppm_data = NULL;
+ l_cp->ppm_buffer = NULL; /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
+ l_cp->ppm_len = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new Ippm series\n");
+ return OPJ_FALSE;
+ }
+ l_cp->ppm_data = new_ppm_data;
+ l_cp->ppm_buffer = l_cp->ppm_data;
+
+ /* Keep the position of the place where concatenate the new series*/
+ l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
+ l_cp->ppm_len += l_N_ppm;
+ }
+ }
+ }
+
+ l_remaining_data = p_header_size;
+
+ while (l_remaining_data >= l_N_ppm) {
+ /* read a complete Ippm series*/
+ memcpy(l_cp->ppm_data_current, p_header_data, l_N_ppm);
+ p_header_size -= l_N_ppm;
+ p_header_data += l_N_ppm;
+
+ l_cp->ppm_data_read += l_N_ppm; /* Increase the number of data read*/
+
+ if (p_header_size)
+ {
+ opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm^i */
+ p_header_data+=4;
+ p_header_size-=4;
+ }
+ else {
+ l_remaining_data = p_header_size;
+ break;
+ }
+
+ l_remaining_data = p_header_size;
+
+ /* Next Ippm series is a complete series ?*/
+ if (l_remaining_data > l_N_ppm) {
+ OPJ_BYTE *new_ppm_data;
+ /* Increase the size of ppm_data to add the new Ippm series*/
+ assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
+ new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
+ if (! new_ppm_data) {
+ opj_free(l_cp->ppm_data);
+ l_cp->ppm_data = NULL;
+ l_cp->ppm_buffer = NULL; /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
+ l_cp->ppm_len = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (complete) Ippm series\n");
+ return OPJ_FALSE;
+ }
+ l_cp->ppm_data = new_ppm_data;
+ l_cp->ppm_buffer = l_cp->ppm_data;
+
+ /* Keep the position of the place where concatenate the new series */
+ l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
+ l_cp->ppm_len += l_N_ppm;
+ }
+
+ }
+
+ /* Need to read an incomplete Ippm series*/
+ if (l_remaining_data) {
+ OPJ_BYTE *new_ppm_data;
+ assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
+ new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
+ if (! new_ppm_data) {
+ opj_free(l_cp->ppm_data);
+ l_cp->ppm_data = NULL;
+ l_cp->ppm_buffer = NULL; /* TODO: no need for a new local variable: ppm_buffer and ppm_data are enough */
+ l_cp->ppm_len = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to increase the size of ppm_data to add the new (incomplete) Ippm series\n");
+ return OPJ_FALSE;
+ }
+ l_cp->ppm_data = new_ppm_data;
+ l_cp->ppm_buffer = l_cp->ppm_data;
+
+ /* Keep the position of the place where concatenate the new series*/
+ l_cp->ppm_data_current = &(l_cp->ppm_data[l_cp->ppm_len]);
+ l_cp->ppm_len += l_N_ppm;
+
+ /* Read incomplete Ippm series*/
+ memcpy(l_cp->ppm_data_current, p_header_data, l_remaining_data);
+ p_header_size -= l_remaining_data;
+ p_header_data += l_remaining_data;
+
+ l_cp->ppm_data_read += l_remaining_data; /* Increase the number of data read*/
+ }
+
+#ifdef CLEAN_MSD
+
+ 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 ;
+
+ OPJ_BYTE *new_ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len);
+ if (! new_ppm_buffer) {
+ opj_free(l_cp->ppm_buffer);
+ l_cp->ppm_buffer = NULL;
+ l_cp->ppm_len = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read ppm marker\n");
+ return OPJ_FALSE;
+ }
+ l_cp->ppm_buffer = new_ppm_buffer;
+ memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm);
+
+ l_cp->ppm_data = l_cp->ppm_buffer;
+ }
+ else {
+ return OPJ_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;
+ }
+ }
+#endif
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_ppt ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_t *l_tcp = 00;
+ OPJ_UINT32 l_Z_ppt;
+
+ /* preconditions */
+ assert(p_header_data != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ /* We need to have the Z_ppt element at minimum */
+ if (p_header_size < 1) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PPT marker\n");
+ return OPJ_FALSE;
+ }
+
+ l_cp = &(p_j2k->m_cp);
+ if (l_cp->ppm){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n");
+ return OPJ_FALSE;
+ }
+
+ 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;
+
+ /* Allocate buffer to read the packet header */
+ if (l_Z_ppt == 0) {
+ /* First PPT marker */
+ l_tcp->ppt_data_size = 0;
+ l_tcp->ppt_len = p_header_size;
+
+ l_tcp->ppt_buffer = (OPJ_BYTE *) opj_calloc(l_tcp->ppt_len, sizeof(OPJ_BYTE) );
+ if (l_tcp->ppt_buffer == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+ return OPJ_FALSE;
+ }
+ l_tcp->ppt_data = l_tcp->ppt_buffer;
+
+ /* memset(l_tcp->ppt_buffer,0,l_tcp->ppt_len); */
+ }
+ else {
+ OPJ_BYTE *new_ppt_buffer;
+ l_tcp->ppt_len += p_header_size;
+
+ new_ppt_buffer = (OPJ_BYTE *) opj_realloc(l_tcp->ppt_buffer, l_tcp->ppt_len);
+ if (! new_ppt_buffer) {
+ opj_free(l_tcp->ppt_buffer);
+ l_tcp->ppt_buffer = NULL;
+ l_tcp->ppt_len = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+ return OPJ_FALSE;
+ }
+ l_tcp->ppt_buffer = new_ppt_buffer;
+ l_tcp->ppt_data = l_tcp->ppt_buffer;
+
+ memset(l_tcp->ppt_buffer+l_tcp->ppt_data_size,0,p_header_size);
+ }
+
+ /* Read packet header from buffer */
+ 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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_tlm( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write TLM marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_sot( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ const opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 */
+/*
+ opj_bool res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2);
+*/
+ assert( 0 && "TODO" );
+#endif /* USE_JPWL */
+
+ * p_data_written = 12;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_sot ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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);
+
+ /* Size of this marker is fixed = 12 (we have already read marker and its size)*/
+ if (p_header_size != 8) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading SOT marker\n");
+ return OPJ_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 (l_cp->correct) {
+
+ OPJ_UINT32 tileno = p_j2k->m_current_tile_number;
+ static OPJ_UINT32 backup_tileno = 0;
+
+ /* tileno is negative or larger than the number of tiles!!! */
+ if (tileno > (l_cp->tw * l_cp->th)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "JPWL: bad tile number (%d out of a maximum of %d)\n",
+ tileno, (l_cp->tw * l_cp->th));
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ tileno = backup_tileno;
+ opj_event_msg_v2(p_manager, 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;
+
+ /* PSot should be equal to zero or >=14 or <= 2^32-1 */
+ if ((l_tot_len !=0 ) && (l_tot_len < 14) )
+ {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Psot value (%d) is not correct regards to the JPEG2000 norm!\n", l_tot_len);
+ return OPJ_FALSE;
+ }
+
+#ifdef USE_JPWL
+ if (l_cp->correct) {
+
+ /* totlen is negative or larger than the bytes left!!! */
+ if (/*(l_tot_len < 0) ||*/ (l_tot_len > p_header_size ) ) { /* FIXME it seems correct; for info in V1 -> (p_stream_numbytesleft(p_stream) + 8))) { */
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "JPWL: bad tile byte size (%d bytes against %d bytes left)\n",
+ l_tot_len, p_header_size ); /* FIXME it seems correct; for info in V1 -> p_stream_numbytesleft(p_stream) + 8); */
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ l_tot_len = 0;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust this\n"
+ "- setting Psot to %d => assuming it is the last tile\n",
+ l_tot_len);
+ }
+ };
+#endif /* USE_JPWL */
+
+ /* Ref A.4.2: Psot could be equal zero if it is the last tile-part of the codestream.*/
+ if (!l_tot_len) {
+ opj_event_msg_v2(p_manager, EVT_INFO, "Psot value of the current tile-part is equal to zero, "
+ "we assuming it is the last tile-part of the codestream.\n");
+ p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
+ }
+
+ opj_read_bytes(p_header_data,&l_current_part ,1); /* TPsot */
+ ++p_header_data;
+
+ opj_read_bytes(p_header_data,&l_num_parts ,1); /* TNsot */
+ ++p_header_data;
+
+ if (l_num_parts != 0) { /* Number of tile-part header is provided by this tile-part header */
+ /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of
+ * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */
+ if (l_tcp->m_nb_tile_parts) {
+ if (l_current_part >= l_tcp->m_nb_tile_parts){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "In SOT marker, TPSot (%d) is not valid regards to the current "
+ "number of tile-part (%d), giving up\n", l_current_part, l_tcp->m_nb_tile_parts );
+ p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
+ return OPJ_FALSE;
+ }
+ }
+ l_tcp->m_nb_tile_parts = l_num_parts;
+ }
+
+ /* If know the number of tile part header we will check if we didn't read the last*/
+ 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; /* Process the last tile-part header*/
+ }
+ }
+
+ if (!p_j2k->m_specific_param.m_decoder.m_last_tile_part){
+ /* Keep the size of data to skip after this marker */
+ p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - 12; /* SOT_marker_size = 12 */
+ }
+ else {
+ /* FIXME: need to be computed from the number of bytes remaining in the codestream */
+ p_j2k->m_specific_param.m_decoder.m_sot_length = 0;
+ }
+
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH;
+
+ /* Check if the current tile is outside the area we want decode or not corresponding to the tile index*/
+ if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec == -1) {
+ 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);
+ }
+ else {
+ assert( p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0 );
+ p_j2k->m_specific_param.m_decoder.m_skip_data =
+ (p_j2k->m_current_tile_number != (OPJ_UINT32)p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec);
+ }
+
+ /* Index */
+ if (p_j2k->cstr_index)
+ {
+ assert(p_j2k->cstr_index->tile_index != 00);
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number;
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = l_current_part;
+
+ if (l_num_parts != 0){
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = l_num_parts;
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = l_num_parts;
+
+ if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) {
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index =
+ (opj_tp_index_t*)opj_calloc(l_num_parts, sizeof(opj_tp_index_t));
+ }
+ else {
+ opj_tp_index_t *new_tp_index = (opj_tp_index_t *) opj_realloc(
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, l_num_parts* sizeof(opj_tp_index_t));
+ if (! new_tp_index) {
+ opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index);
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = new_tp_index;
+ }
+ }
+ else{
+ /*if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index)*/ {
+
+ if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) {
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 10;
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index =
+ (opj_tp_index_t*)opj_calloc( p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps,
+ sizeof(opj_tp_index_t));
+ }
+
+ if ( l_current_part >= p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps ){
+ opj_tp_index_t *new_tp_index;
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps += 10;
+ new_tp_index = (opj_tp_index_t *) opj_realloc(
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index,
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps * sizeof(opj_tp_index_t));
+ if (! new_tp_index) {
+ opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index);
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL;
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = new_tp_index;
+ }
+ }
+
+ }
+
+ }
+
+ /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */
+ /* if (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 OPJ_TRUE;
+ }
+
+opj_bool opj_j2k_write_sod( opj_j2k_v2_t *p_j2k,
+ opj_tcd_v2_t * p_tile_coder,
+ OPJ_BYTE * p_data,
+ OPJ_UINT32 * p_data_written,
+ OPJ_UINT32 p_total_data_size,
+ const opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_tcp_v2_t *l_tcp = 00;
+ opj_codestream_info_t *l_cstr_info = 00;
+ opj_cp_v2_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];
+
+ /* 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 >> */
+ /* TODO mergeV2: check this part which use cstr_info */
+ /*l_cstr_info = p_j2k->cstr_info;
+ 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 */
+ /*opj_bool res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2);
+*/
+ assert( 0 && "TODO" );
+#endif /* USE_JPWL */
+ /* <<UniPG */
+ /*}*/
+ /* << INDEX */
+
+ if (p_j2k->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 (! opj_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_v2(p_manager, EVT_ERROR, "Cannot encode tile\n");
+ return OPJ_FALSE;
+ }
+
+ *p_data_written += 2;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_sod (opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 l_current_read_size;
+ opj_codestream_index_t * l_cstr_index = 00;
+ OPJ_BYTE ** l_current_data = 00;
+ opj_tcp_v2_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]);
+
+ if (p_j2k->m_specific_param.m_decoder.m_last_tile_part) {
+ /* opj_stream_get_number_byte_left returns OPJ_OFF_T
+ // but we are in the last tile part,
+ // so its result will fit on OPJ_UINT32 unless we find
+ // a file with a single tile part of more than 4 GB...*/
+ p_j2k->m_specific_param.m_decoder.m_sot_length = (OPJ_UINT32)(opj_stream_get_number_byte_left(p_stream) - 2);
+ }
+ else
+ p_j2k->m_specific_param.m_decoder.m_sot_length -= 2;
+
+ l_current_data = &(l_tcp->m_data);
+ l_tile_len = &l_tcp->m_data_size;
+
+ if (! *l_current_data) {
+ /* LH: oddly enough, in this path, l_tile_len!=0.
+ * TODO: If this was consistant, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
+ */
+ *l_current_data = (OPJ_BYTE*) opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length);
+ }
+ else {
+ OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data, *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length);
+ if (! l_new_current_data) {
+ opj_free(*l_current_data);
+ /*nothing more is done as l_current_data will be set to null, and just
+ afterward we enter in the error path
+ and the actual tile_len is updated (committed) at the end of the
+ function. */
+ }
+ *l_current_data = l_new_current_data;
+ }
+
+ if (*l_current_data == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to decode tile\n");
+ return OPJ_FALSE;
+ }
+
+ /* Index */
+ l_cstr_index = p_j2k->cstr_index;
+ if (l_cstr_index) {
+ OPJ_OFF_T l_current_pos = opj_stream_tell(p_stream) - 2;
+
+ OPJ_UINT32 l_current_tile_part = l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno;
+ l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header =
+ l_current_pos;
+ l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos =
+ l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2;
+
+ if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number,
+ l_cstr_index,
+ J2K_MS_SOD,
+ l_current_pos,
+ p_j2k->m_specific_param.m_decoder.m_sot_length + 2)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n");
+ return OPJ_FALSE;
+ }
+
+ /*l_cstr_index->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_STATE_NEOC;
+ }
+ else {
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
+ }
+
+ *l_tile_len += l_current_read_size;
+
+ return OPJ_TRUE;
+}
+
+ opj_bool opj_j2k_write_rgn(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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_v2_t *l_cp = 00;
+ opj_tcp_v2_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_eoc( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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 */
+ /*
+ opj_bool res = 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 OPJ_FALSE;
+ }
+
+ if ( ! opj_stream_flush(p_stream,p_manager) ) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_rgn (opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 l_nb_comp;
+ opj_image_t * l_image = 00;
+
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_t *l_tcp = 00;
+ OPJ_UINT32 l_comp_room, l_comp_no, l_roi_sty;
+
+ /* preconditions*/
+ assert(p_header_data != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ l_image = p_j2k->m_private_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_v2(p_manager, EVT_ERROR, "Error reading RGN marker\n");
+ return OPJ_FALSE;
+ }
+
+ l_cp = &(p_j2k->m_cp);
+ l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_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 (l_cp->correct) {
+ /* totlen is negative or larger than the bytes left!!! */
+ if (l_comp_room >= l_nb_comp) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "JPWL: bad component number in RGN (%d when there are only %d)\n",
+ l_comp_room, l_nb_comp);
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ }
+ };
+#endif /* USE_JPWL */
+
+ opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&(l_tcp->tccps[l_comp_no].roishift)),1); /* SPrgn */
+ ++p_header_data;
+
+ return OPJ_TRUE;
+
+}
+
+OPJ_FLOAT32 opj_j2k_get_tp_stride (opj_tcp_v2_t * p_tcp)
+{
+ return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14);
+}
+
+OPJ_FLOAT32 opj_j2k_get_default_stride (opj_tcp_v2_t * p_tcp)
+{
+ (void)p_tcp;
+ return 0;
+}
+
+opj_bool opj_j2k_update_rates( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ opj_cp_v2_t * l_cp = 00;
+ opj_image_t * l_image = 00;
+ opj_tcp_v2_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_v2_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_private_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 = opj_j2k_get_tp_stride;
+ }
+ else {
+ l_tp_stride_func = opj_j2k_get_default_stride;
+ }
+
+ for (i=0;i<l_cp->th;++i) {
+ for (j=0;j<l_cp->tw;++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;i<l_cp->th;++i) {
+ for (j=0;j<l_cp->tw;++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;i<l_image->numcomps;++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 += opj_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 *) 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 OPJ_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 OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_eoc ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ OPJ_UINT32 i;
+ opj_tcd_v2_t * l_tcd = 00;
+ OPJ_UINT32 l_nb_tiles;
+ opj_tcp_v2_t * l_tcp = 00;
+ opj_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 = opj_tcd_create(OPJ_TRUE);
+ if (l_tcd == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
+ return OPJ_FALSE;
+ }
+
+ for (i = 0; i < l_nb_tiles; ++i) {
+ if (l_tcp->m_data) {
+ if (! opj_tcd_init_decode_tile(l_tcd, i)) {
+ opj_tcd_destroy(l_tcd);
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
+ return OPJ_FALSE;
+ }
+
+ l_success = opj_tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, p_j2k->cstr_index);
+ /* cleanup */
+
+ if (! l_success) {
+ p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR;
+ break;
+ }
+ }
+
+ opj_j2k_tcp_destroy(l_tcp);
+ ++l_tcp;
+ }
+
+ opj_tcd_destroy(l_tcd);
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_get_end_header(opj_j2k_v2_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_index->main_head_end = opj_stream_tell(p_stream);
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_mct_data_group( opj_j2k_v2_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_v2_t * l_tcp;
+
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ if (! opj_j2k_write_cbd(p_j2k,p_stream,p_manager)) {
+ return OPJ_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;i<l_tcp->m_nb_mct_records;++i) {
+
+ if (! opj_j2k_write_mct_record(p_j2k,l_mct_record,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ ++l_mct_record;
+ }
+
+ l_mcc_record = l_tcp->m_mcc_records;
+
+ for (i=0;i<l_tcp->m_nb_mcc_records;++i) {
+
+ if (! opj_j2k_write_mcc_record(p_j2k,l_mcc_record,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ ++l_mcc_record;
+ }
+
+ if (! opj_j2k_write_mco(p_j2k,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_image_components(opj_j2k_v2_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_private_image->numcomps; ++compno)
+ {
+ if (! opj_j2k_write_coc(p_j2k,compno,p_stream, p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ if (! opj_j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_regions( opj_j2k_v2_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_private_image->numcomps; ++compno) {
+ if (l_tccp->roishift) {
+
+ if (! opj_j2k_write_rgn(p_j2k,0,compno,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ ++l_tccp;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_epc( opj_j2k_v2_t *p_j2k,
+ struct opj_stream_private *p_stream,
+ struct opj_event_mgr * p_manager )
+{
+ opj_codestream_index_t * l_cstr_index = 00;
+
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_stream != 00);
+
+ l_cstr_index = p_j2k->cstr_index;
+ if (l_cstr_index) {
+ l_cstr_index->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_cstr_index->codestream_size -= l_cstr_index->main_head_start;
+ /* <<UniPG */
+ }
+
+#ifdef USE_JPWL
+ /* preparation of JPWL marker segments */
+#if 0
+ if(cp->epc_on) {
+
+ /* encode according to JPWL */
+ jpwl_encode(p_j2k, p_stream, image);
+
+ }
+#endif
+ assert( 0 && "TODO" );
+#endif /* USE_JPWL */
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_unk ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ OPJ_UINT32 *output_marker,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 l_unknown_marker;
+ const opj_dec_memory_marker_handler_t * l_marker_handler;
+ OPJ_UINT32 l_size_unk = 2;
+
+ /* preconditions*/
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_stream != 00);
+
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Unknown marker\n");
+
+ while(1) {
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* read 2 bytes as the new marker ID*/
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_unknown_marker,2);
+
+ if (!(l_unknown_marker < 0xff00)) {
+
+ /* Get the marker handler from the marker ID*/
+ l_marker_handler = opj_j2k_get_marker_handler(l_unknown_marker);
+
+ if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Marker is not compliant with its position\n");
+ return OPJ_FALSE;
+ }
+ else {
+ if (l_marker_handler->id != J2K_MS_UNK) {
+ /* Add the marker to the codestream index*/
+ if (l_marker_handler->id != J2K_MS_SOT)
+ {
+ opj_bool res = opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_UNK,
+ (OPJ_UINT32) opj_stream_tell(p_stream) - l_size_unk,
+ l_size_unk);
+ if (res == OPJ_FALSE) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n");
+ return OPJ_FALSE;
+ }
+ }
+ break; /* next marker is known and well located */
+ }
+ else
+ l_size_unk += 2;
+ }
+ }
+ }
+
+ *output_marker = l_marker_handler->id ;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_mct_record( opj_j2k_v2_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) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write MCT marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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 OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_mct ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 i;
+ opj_tcp_v2_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_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_v2(p_manager, EVT_ERROR, "Error reading MCT marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* first marker */
+ opj_read_bytes(p_header_data,&l_tmp,2); /* Zmct */
+ p_header_data += 2;
+ if (l_tmp != 0) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Cannot take in charge mct data within multiple MCT records\n");
+ return OPJ_TRUE;
+ }
+
+ if(p_header_size <= 6) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCT marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/
+ opj_read_bytes(p_header_data,&l_tmp,2); /* Imct */
+ p_header_data += 2;
+
+ l_indix = l_tmp & 0xff;
+ l_mct_data = l_tcp->m_mct_records;
+
+ for (i=0;i<l_tcp->m_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) {
+ opj_mct_data_t *new_mct_records;
+ l_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS;
+
+ new_mct_records = (opj_mct_data_t *) opj_realloc(l_tcp->m_mct_records, l_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t));
+ if (! new_mct_records) {
+ opj_free(l_tcp->m_mct_records);
+ l_tcp->m_mct_records = NULL;
+ l_tcp->m_nb_max_mct_records = 0;
+ l_tcp->m_nb_mct_records = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n");
+ return OPJ_FALSE;
+ }
+ l_tcp->m_mct_records = new_mct_records;
+ 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 = (J2K_MCT_ARRAY_TYPE)((l_tmp >> 8) & 3);
+ l_mct_data->m_element_type = (J2K_MCT_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_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple MCT markers\n");
+ return OPJ_TRUE;
+ }
+
+ p_header_size -= 6;
+
+ l_mct_data->m_data = (OPJ_BYTE*)opj_malloc(p_header_size);
+ if (! l_mct_data->m_data) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCT marker\n");
+ return OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_mcc_record( opj_j2k_v2_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)
+ {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write MCC marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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;i<p_mcc_record->m_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;i<p_mcc_record->m_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_mcc ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager )
+{
+ OPJ_UINT32 i,j;
+ OPJ_UINT32 l_tmp;
+ OPJ_UINT32 l_indix;
+ opj_tcp_v2_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_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_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* first marker */
+ opj_read_bytes(p_header_data,&l_tmp,2); /* Zmcc */
+ p_header_data += 2;
+ if (l_tmp != 0) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n");
+ return OPJ_TRUE;
+ }
+
+ if (p_header_size < 7) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_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;i<l_tcp->m_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) {
+ opj_simple_mcc_decorrelation_data_t *new_mcc_records;
+ l_tcp->m_nb_max_mcc_records += J2K_MCC_DEFAULT_NB_RECORDS;
+
+ new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc(
+ l_tcp->m_mcc_records, l_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t));
+ if (! new_mcc_records) {
+ opj_free(l_tcp->m_mcc_records);
+ l_tcp->m_mcc_records = NULL;
+ l_tcp->m_nb_max_mcc_records = 0;
+ l_tcp->m_nb_mcc_records = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read MCC marker\n");
+ return OPJ_FALSE;
+ }
+ l_tcp->m_mcc_records = new_mcc_records;
+ 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_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple data spanning\n");
+ return OPJ_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_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple collections\n");
+ return OPJ_TRUE;
+ }
+
+ p_header_size -= 7;
+
+ for (i=0;i<l_nb_collections;++i) {
+ if (p_header_size < 3) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_header_data,&l_tmp,1); /* Xmcci type of component transformation -> array based decorrelation */
+ ++p_header_data;
+
+ if (l_tmp != 1) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Cannot take in charge collections other than array decorrelation\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2);
+
+ for (j=0;j<l_mcc_record->m_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_v2(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n");
+ return OPJ_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_v2(p_manager, EVT_WARNING, "Cannot take in charge collections without same number of indixes\n");
+ return OPJ_TRUE;
+ }
+
+ if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3);
+
+ for (j=0;j<l_mcc_record->m_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_v2(p_manager, EVT_WARNING, "Cannot take in charge collections with indix shuffle\n");
+ return OPJ_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;j<l_tcp->m_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_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+ }
+
+ l_indix = (l_tmp >> 8) & 0xff;
+ if (l_indix != 0) {
+ l_mct_data = l_tcp->m_mct_records;
+ for (j=0;j<l_tcp->m_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_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+ }
+ }
+
+ if (p_header_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCC marker\n");
+ return OPJ_FALSE;
+ }
+
+ ++l_tcp->m_nb_mcc_records;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_mco( opj_j2k_v2_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_v2_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) {
+
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write MCO marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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;i<l_tcp->m_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 OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_mco ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 l_tmp, i;
+ OPJ_UINT32 l_nb_stages;
+ opj_tcp_v2_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_private_image;
+ l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_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_v2(p_manager, EVT_ERROR, "Error reading MCO marker\n");
+ return OPJ_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_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple transformation stages.\n");
+ return OPJ_TRUE;
+ }
+
+ if (p_header_size != l_nb_stages + 1) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Error reading MCO marker\n");
+ return OPJ_FALSE;
+ }
+
+ l_tccp = l_tcp->tccps;
+ l_img_comp = l_image->comps;
+
+ for (i=0;i<l_image->numcomps;++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;i<l_nb_stages;++i) {
+ opj_read_bytes(p_header_data,&l_tmp,1);
+ ++p_header_data;
+
+ if (! opj_j2k_add_mct(l_tcp,p_j2k->m_private_image,l_tmp)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_add_mct(opj_tcp_v2_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;i<p_tcp->m_nb_mcc_records;++i) {
+ if (l_mcc_record->m_index == p_index) {
+ break;
+ }
+ }
+
+ if (i==p_tcp->m_nb_mcc_records) {
+ /** element discarded **/
+ return OPJ_TRUE;
+ }
+
+ if (l_mcc_record->m_nb_comps != p_image->numcomps) {
+ /** do not support number of comps != image */
+ return OPJ_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 OPJ_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_FLOAT32*)opj_malloc(l_mct_size);
+
+ if (! p_tcp->m_mct_decoding_matrix ) {
+ return OPJ_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 OPJ_FALSE;
+ }
+
+ l_nb_elem = p_image->numcomps;
+ l_offset_size = l_nb_elem * sizeof(OPJ_UINT32);
+ l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size);
+
+ if (! l_offset_data ) {
+ return OPJ_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;i<p_image->numcomps;++i) {
+ l_tccp->m_dc_level_shift = *(l_current_offset_data++);
+ ++l_tccp;
+ }
+
+ opj_free(l_offset_data);
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_cbd( opj_j2k_v2_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_private_image;
+ l_cbd_size = 6 + p_j2k->m_private_image->numcomps;
+
+ if (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+ OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size);
+ if (! new_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 = NULL;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to write CBD marker\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
+ 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;i<l_image->numcomps;++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 OPJ_FALSE;
+ }
+
+ return OPJ_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.
+*/
+static opj_bool opj_j2k_read_cbd ( opj_j2k_v2_t *p_j2k,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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_private_image->numcomps;
+
+ if (p_header_size != (p_j2k->m_private_image->numcomps + 2)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Crror reading CBD marker\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Crror reading CBD marker\n");
+ return OPJ_FALSE;
+ }
+
+ l_comp = p_j2k->m_private_image->comps;
+ for (i=0;i<l_num_comp;++i) {
+ opj_read_bytes(p_header_data,&l_comp_def,1); /* Component bit depth */
+ ++p_header_data;
+ l_comp->sgnd = (l_comp_def>>7) & 1;
+ l_comp->prec = (l_comp_def&0x7f) + 1;
+ ++l_comp;
+ }
+
+ return OPJ_TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K / JPT decoder interface */
+/* ----------------------------------------------------------------------- */
+
+void opj_j2k_setup_decoder(opj_j2k_v2_t *j2k, opj_dparameters_t *parameters)
+{
+ if(j2k && parameters) {
+ j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer;
+ j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce;
+
+#ifdef USE_JPWL
+ j2k->m_cp.correct = parameters->jpwl_correct;
+ j2k->m_cp.exp_comps = parameters->jpwl_exp_comps;
+ j2k->m_cp.max_tiles = parameters->jpwl_max_tiles;
+#endif /* USE_JPWL */
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K encoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_j2k_v2_t* opj_j2k_create_compress(void)
+{
+ opj_j2k_v2_t *l_j2k = (opj_j2k_v2_t*) opj_malloc(sizeof(opj_j2k_v2_t));
+ if (!l_j2k) {
+ return NULL;
+ }
+
+ memset(l_j2k,0,sizeof(opj_j2k_v2_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) {
+ opj_j2k_destroy(l_j2k);
+ return NULL;
+ }
+
+ 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) {
+ opj_j2k_destroy(l_j2k);
+ return NULL;
+ }
+
+ /* execution list creation*/
+ l_j2k->m_procedure_list = opj_procedure_list_create();
+ if (! l_j2k->m_procedure_list) {
+ opj_j2k_destroy(l_j2k);
+ return NULL;
+ }
+
+ return l_j2k;
+}
+
+void opj_j2k_setup_encoder( opj_j2k_v2_t *p_j2k,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 i, j, tileno, numpocs_tile;
+ opj_cp_v2_t *cp = 00;
+ opj_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 = OPJ_TRUE;
+ cp->info_on = OPJ_FALSE; /* no informative technique */
+
+ /* set EPB on */
+ if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) {
+ cp->epb_on = OPJ_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 = OPJ_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 = OPJ_FALSE;
+
+ } else {
+ cp->epc_on = OPJ_FALSE;
+ }
+#endif /* USE_JPWL */
+
+ /* initialize the mutiple tiles */
+ /* ---------------------------- */
+ cp->tcps = (opj_tcp_v2_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_v2_t));
+ if (parameters->numpocs) {
+ /* initialisation of POC */
+ l_res = opj_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_v2_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_event_msg_v2(p_manager, EVT_ERROR, "MCT not supported for now\n");
+ return;
+
+ /* TODO MSD : merge v2 add invert.c or used a external lib ?
+ OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * sizeof(OPJ_FLOAT32);
+ OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)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_FLOAT32*)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_FLOAT32*)opj_malloc(lMctSize);
+ assert(opj_matrix_inversion_f(lTmpBuf,(tcp->m_mct_decoding_matrix),image->numcomps));
+
+ tcp->mct_norms = (OPJ_FLOAT64*)
+ 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];
+ }
+
+ opj_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) {
+ OPJ_INT32 p = 0, it_res;
+ for (it_res = tccp->numresolutions - 1; it_res >= 0; it_res--) {
+ if (p < parameters->res_spec) {
+
+ if (parameters->prcw_init[p] < 1) {
+ tccp->prcw[it_res] = 1;
+ } else {
+ tccp->prcw[it_res] = int_floorlog2(parameters->prcw_init[p]);
+ }
+
+ if (parameters->prch_init[p] < 1) {
+ tccp->prch[it_res] = 1;
+ }else {
+ tccp->prch[it_res] = 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[it_res] = 1;
+ } else {
+ tccp->prcw[it_res] = int_floorlog2(size_prcw);
+ }
+
+ if (size_prch < 1) {
+ tccp->prch[it_res] = 1;
+ } else {
+ tccp->prch[it_res] = int_floorlog2(size_prch);
+ }
+ }
+ p++;
+ /*printf("\nsize precinct for level %d : %d,%d\n", it_res,tccp->prcw[it_res], tccp->prch[it_res]); */
+ } /*end for*/
+ } else {
+ for (j = 0; j < tccp->numresolutions; j++) {
+ tccp->prcw[j] = 15;
+ tccp->prch[j] = 15;
+ }
+ }
+ }
+
+ opj_dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec);
+ }
+ }
+
+ if (parameters->mct_data) {
+ opj_free(parameters->mct_data);
+ parameters->mct_data = 00;
+ }
+}
+
+static opj_bool opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len)
+{
+ assert(cstr_index != 00);
+
+ /* expand the list? */
+ if ((cstr_index->marknum + 1) > cstr_index->maxmarknum) {
+ opj_marker_info_t *new_marker;
+ cstr_index->maxmarknum = 100 + (int) ((float) cstr_index->maxmarknum * 1.0F);
+ new_marker = (opj_marker_info_t *) opj_realloc(cstr_index->marker, cstr_index->maxmarknum *sizeof(opj_marker_info_t));
+ if (! new_marker) {
+ opj_free(cstr_index->marker);
+ cstr_index->marker = NULL;
+ cstr_index->maxmarknum = 0;
+ cstr_index->marknum = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); */
+ return OPJ_FALSE;
+ }
+ cstr_index->marker = new_marker;
+ }
+
+ /* add the marker */
+ cstr_index->marker[cstr_index->marknum].type = (OPJ_UINT16)type;
+ cstr_index->marker[cstr_index->marknum].pos = (OPJ_INT32)pos;
+ cstr_index->marker[cstr_index->marknum].len = (OPJ_INT32)len;
+ cstr_index->marknum++;
+ return OPJ_TRUE;
+}
+
+static opj_bool opj_j2k_add_tlmarker(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len)
+{
+ assert(cstr_index != 00);
+ assert(cstr_index->tile_index != 00);
+
+ /* expand the list? */
+ if ((cstr_index->tile_index[tileno].marknum + 1) > cstr_index->tile_index[tileno].maxmarknum) {
+ opj_marker_info_t *new_marker;
+ cstr_index->tile_index[tileno].maxmarknum = 100 + (int) ((float) cstr_index->tile_index[tileno].maxmarknum * 1.0F);
+ new_marker = (opj_marker_info_t *) opj_realloc(
+ cstr_index->tile_index[tileno].marker,
+ cstr_index->tile_index[tileno].maxmarknum *sizeof(opj_marker_info_t));
+ if (! new_marker) {
+ opj_free(cstr_index->tile_index[tileno].marker);
+ cstr_index->tile_index[tileno].marker = NULL;
+ cstr_index->tile_index[tileno].maxmarknum = 0;
+ cstr_index->tile_index[tileno].marknum = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); */
+ return OPJ_FALSE;
+ }
+ cstr_index->tile_index[tileno].marker = new_marker;
+ }
+
+ /* add the marker */
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type = (OPJ_UINT16)type;
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos = (OPJ_INT32)pos;
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len = (OPJ_INT32)len;
+ cstr_index->tile_index[tileno].marknum++;
+
+ if (type == J2K_MS_SOT) {
+ OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno;
+
+ if (cstr_index->tile_index[tileno].tp_index)
+ cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos;
+
+ }
+ return OPJ_TRUE;
+}
+
+/*
+ * -----------------------------------------------------------------------
+ * -----------------------------------------------------------------------
+ * -----------------------------------------------------------------------
+ */
+
+opj_bool opj_j2k_end_decompress(opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ (void)p_j2k;
+ (void)p_stream;
+ (void)p_manager;
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_header( opj_stream_private_t *p_stream,
+ opj_j2k_v2_t* p_j2k,
+ opj_image_t** p_image,
+ opj_event_mgr_t* p_manager )
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ /* create an empty image header */
+ p_j2k->m_private_image = opj_image_create0();
+ if (! p_j2k->m_private_image) {
+ return OPJ_FALSE;
+ }
+
+ /* customization of the validation */
+ opj_j2k_setup_decoding_validation(p_j2k);
+
+ /* validation of the parameters codec */
+ if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ /* customization of the encoding */
+ opj_j2k_setup_header_reading(p_j2k);
+
+ /* read header */
+ if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ *p_image = opj_image_create0();
+ if (! (*p_image)) {
+ return OPJ_FALSE;
+ }
+
+ /* Copy codestream image information to the output image */
+ opj_copy_image_header(p_j2k->m_private_image, *p_image);
+
+ /*Allocate and initialize some elements of codestrem index*/
+ if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)){
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_setup_header_reading (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions*/
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_read_header_procedure);
+
+ /* DEVELOPER CORNER, add your custom procedures */
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd);
+
+}
+
+void opj_j2k_setup_decoding_validation (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions*/
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_decoder);
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_decoding_validation);
+ /* DEVELOPER CORNER, add your custom validation procedure */
+
+}
+
+opj_bool opj_j2k_mct_validation ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ opj_bool l_is_valid = OPJ_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_v2_t * l_tcp = p_j2k->m_cp.tcps;
+
+ for (i=0;i<l_nb_tiles;++i) {
+ if (l_tcp->mct == 2) {
+ opj_tccp_t * l_tccp = l_tcp->tccps;
+ l_is_valid &= (l_tcp->m_mct_coding_matrix != 00);
+
+ for (j=0;j<p_j2k->m_private_image->numcomps;++j) {
+ l_is_valid &= ! (l_tccp->qmfbid & 1);
+ ++l_tccp;
+ }
+ }
+ ++l_tcp;
+ }
+ }
+
+ return l_is_valid;
+}
+
+opj_bool opj_j2k_setup_mct_encoding(opj_tcp_v2_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 OPJ_TRUE;
+ }
+
+ if (p_tcp->m_mct_decoding_matrix) {
+ if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) {
+ opj_mct_data_t *new_mct_records;
+ p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS;
+
+ new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t));
+ if (! new_mct_records) {
+ opj_free(p_tcp->m_mct_records);
+ p_tcp->m_mct_records = NULL;
+ p_tcp->m_nb_max_mct_records = 0;
+ p_tcp->m_nb_mct_records = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */
+ return OPJ_FALSE;
+ }
+ p_tcp->m_mct_records = new_mct_records;
+ 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_BYTE*)opj_malloc(l_mct_size );
+
+ if (! l_mct_deco_data->m_data) {
+ return OPJ_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) {
+ opj_mct_data_t *new_mct_records;
+ p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS;
+ new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t));
+ if (! new_mct_records) {
+ opj_free(p_tcp->m_mct_records);
+ p_tcp->m_mct_records = NULL;
+ p_tcp->m_nb_max_mct_records = 0;
+ p_tcp->m_nb_mct_records = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */
+ return OPJ_FALSE;
+ }
+ p_tcp->m_mct_records = new_mct_records;
+ 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_BYTE*)opj_malloc(l_mct_size );
+
+ if (! l_mct_offset_data->m_data) {
+ return OPJ_FALSE;
+ }
+
+ l_data = (OPJ_FLOAT32*)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 OPJ_FALSE;
+ }
+
+ l_tccp = p_tcp->tccps;
+ l_current_data = l_data;
+
+ for (i=0;i<l_nb_elem;++i) {
+ *(l_current_data++) = (OPJ_FLOAT32) (l_tccp->m_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) {
+ opj_simple_mcc_decorrelation_data_t *new_mcc_records;
+ p_tcp->m_nb_max_mcc_records += J2K_MCT_DEFAULT_NB_RECORDS;
+ new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc(
+ p_tcp->m_mcc_records, p_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t));
+ if (! new_mcc_records) {
+ opj_free(p_tcp->m_mcc_records);
+ p_tcp->m_mcc_records = NULL;
+ p_tcp->m_nb_max_mcc_records = 0;
+ p_tcp->m_nb_mcc_records = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */
+ return OPJ_FALSE;
+ }
+ p_tcp->m_mcc_records = new_mcc_records;
+ 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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_build_decoder (opj_j2k_v2_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 */
+ (void)p_j2k;
+ (void)p_stream;
+ (void)p_manager;
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_build_encoder (opj_j2k_v2_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 */
+ (void)p_j2k;
+ (void)p_stream;
+ (void)p_manager;
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_encoding_validation ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ opj_bool l_is_valid = OPJ_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_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_v2(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
+ return OPJ_FALSE;
+ }
+
+ if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
+ return OPJ_FALSE;
+ }
+
+ /* PARAMETER VALIDATION */
+ return l_is_valid;
+}
+
+opj_bool opj_j2k_decoding_validation ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_bool l_is_valid = OPJ_TRUE;
+
+ /* preconditions*/
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ /* STATE checking */
+ /* make sure the state is at 0 */
+#ifdef TODO_MSD
+ l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE);
+#endif
+ l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == 0x0000);
+
+ /* 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;
+}
+
+opj_bool opj_j2k_read_header_procedure( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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);
+
+ /* We enter in the main header */
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSOC;
+
+ /* Try to read the SOC marker, the codestream must begin with SOC marker */
+ if (! opj_j2k_read_soc(p_j2k,p_stream,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Expected a SOC marker \n");
+ return OPJ_FALSE;
+ }
+
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* Read 2 bytes as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+
+ /* Try to read until the SOT is detected */
+ while (l_current_marker != J2K_MS_SOT) {
+
+ /* Check if the current marker ID is valid */
+ if (l_current_marker < 0xff00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "We expected read a marker ID (0xff--) instead of %.8x\n", l_current_marker);
+ return OPJ_FALSE;
+ }
+
+ /* Get the marker handler from the marker ID */
+ l_marker_handler = opj_j2k_get_marker_handler(l_current_marker);
+
+ /* Manage case where marker is unknown */
+ if (l_marker_handler->id == J2K_MS_UNK) {
+ if (! opj_j2k_read_unk(p_j2k, p_stream, &l_current_marker, p_manager)){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Unknow marker have been detected and generated error.\n");
+ return OPJ_FALSE;
+ }
+
+ if (l_current_marker == J2K_MS_SOT)
+ break; /* SOT marker is detected main header is completely read */
+ else /* Get the marker handler from the marker ID */
+ l_marker_handler = opj_j2k_get_marker_handler(l_current_marker);
+ }
+
+ /* Check if the marker is known and if it is the right place to find it */
+ if (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Marker is not compliant with its position\n");
+ return OPJ_FALSE;
+ }
+
+ /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* read 2 bytes as the marker size */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2);
+ l_marker_size -= 2; /* Subtract the size of the marker ID already read */
+
+ /* Check if the marker size is compatible with the header data size */
+ if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) {
+ OPJ_BYTE *new_header_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size);
+ if (! new_header_data) {
+ opj_free(p_j2k->m_specific_param.m_decoder.m_header_data);
+ p_j2k->m_specific_param.m_decoder.m_header_data = NULL;
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read header\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data;
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size;
+ }
+
+ /* Try to read the rest of the marker segment from stream and copy them into the buffer */
+ 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_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* Read the marker segment with the correct marker handler */
+ 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_v2(p_manager, EVT_ERROR, "Marker handler function failed to read the marker segment\n");
+ return OPJ_FALSE;
+ }
+
+ /* Add the marker to the codestream index*/
+ if (OPJ_FALSE == opj_j2k_add_mhmarker(
+ p_j2k->cstr_index,
+ l_marker_handler->id,
+ (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4,
+ l_marker_size + 4 )) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* read 2 bytes as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+ }
+
+ opj_event_msg_v2(p_manager, EVT_INFO, "Main header has been correctly decoded.\n");
+
+ /* Position of the last element if the main header */
+ p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2;
+
+ /* Next step: read a tile-part header */
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_exec ( opj_j2k_v2_t * p_j2k,
+ opj_procedure_list_t * p_procedure_list,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ opj_bool (** l_procedure) (opj_j2k_v2_t * ,opj_stream_private_t *,opj_event_mgr_t *) = 00;
+ opj_bool l_result = OPJ_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 = (opj_bool (**) (opj_j2k_v2_t * ,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list);
+
+ for (i=0;i<l_nb_proc;++i) {
+ l_result = l_result && ((*l_procedure) (p_j2k,p_stream,p_manager));
+ ++l_procedure;
+ }
+
+ /* and clear the procedure list at the end.*/
+ opj_procedure_list_clear(p_procedure_list);
+ return l_result;
+}
+
+/* FIXME DOC*/
+static opj_bool opj_j2k_copy_default_tcp_and_create_tcd ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_tcp_v2_t * l_tcp = 00;
+ opj_tcp_v2_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 */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ l_image = p_j2k->m_private_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 each tile */
+ for (i=0; i<l_nb_tiles; ++i) {
+ /* keep the tile-compo coding parameters pointer of the current tile coding parameters*/
+ l_current_tccp = l_tcp->tccps;
+ /*Copy default coding parameters into the current tile coding parameters*/
+ memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_v2_t));
+ /* Initialize some values of the current tile coding parameters*/
+ l_tcp->ppt = 0;
+ l_tcp->ppt_data = 00;
+ /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/
+ l_tcp->tccps = l_current_tccp;
+
+ /* Get the mct_decoding_matrix of the dflt_tile_cp and copy them into the current tile cp*/
+ if (l_default_tcp->m_mct_decoding_matrix) {
+ l_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size);
+ if (! l_tcp->m_mct_decoding_matrix ) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mct_decoding_matrix,l_default_tcp->m_mct_decoding_matrix,l_mct_size);
+ }
+
+ /* Get the mct_record of the dflt_tile_cp and copy them into the current tile cp*/
+ l_mct_records_size = l_default_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t);
+ l_tcp->m_mct_records = (opj_mct_data_t*)opj_malloc(l_mct_records_size);
+ if (! l_tcp->m_mct_records) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records,l_mct_records_size);
+
+ /* Copy the mct record data from dflt_tile_cp to the current tile*/
+ l_src_mct_rec = l_default_tcp->m_mct_records;
+ l_dest_mct_rec = l_tcp->m_mct_records;
+
+ for (j=0;j<l_default_tcp->m_nb_mct_records;++j) {
+
+ if (l_src_mct_rec->m_data) {
+
+ l_dest_mct_rec->m_data = (OPJ_BYTE*) opj_malloc(l_src_mct_rec->m_data_size);
+ if(! l_dest_mct_rec->m_data) {
+ return OPJ_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;
+ }
+
+ /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/
+ 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_simple_mcc_decorrelation_data_t*) opj_malloc(l_mcc_records_size);
+ if (! l_tcp->m_mcc_records) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size);
+
+ /* Copy the mcc record data from dflt_tile_cp to the current tile*/
+ l_src_mcc_rec = l_default_tcp->m_mcc_records;
+ l_dest_mcc_rec = l_tcp->m_mcc_records;
+
+ for (j=0;j<l_default_tcp->m_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;
+ }
+
+ /* Copy all the dflt_tile_compo_cp to the current tile cp */
+ memcpy(l_current_tccp,l_default_tcp->tccps,l_tccp_size);
+
+ /* Move to next tile cp*/
+ ++l_tcp;
+ }
+
+ /* Create the current tile decoder*/
+ p_j2k->m_tcd = (opj_tcd_v2_t*)opj_tcd_create(OPJ_TRUE); /* FIXME why a cast ? */
+ if (! p_j2k->m_tcd ) {
+ return OPJ_FALSE;
+ }
+
+ if ( !opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp)) ) {
+ opj_tcd_destroy(p_j2k->m_tcd);
+ p_j2k->m_tcd = 00;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+const opj_dec_memory_marker_handler_t * opj_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; /* we find a handler corresponding to the marker ID*/
+ }
+ }
+ return e;
+}
+
+void opj_j2k_destroy (opj_j2k_v2_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) {
+ opj_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;
+ }
+ }
+
+ opj_tcd_destroy(p_j2k->m_tcd);
+
+ opj_j2k_cp_destroy(&(p_j2k->m_cp));
+ memset(&(p_j2k->m_cp),0,sizeof(opj_cp_v2_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;
+
+ j2k_destroy_cstr_index(p_j2k->cstr_index);
+ p_j2k->cstr_index = NULL;
+
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+
+ opj_image_destroy(p_j2k->m_output_image);
+ p_j2k->m_output_image = NULL;
+
+ opj_free(p_j2k);
+}
+
+void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind)
+{
+ if (p_cstr_ind) {
+
+ if (p_cstr_ind->marker) {
+ opj_free(p_cstr_ind->marker);
+ p_cstr_ind->marker = NULL;
+ }
+
+ if (p_cstr_ind->tile_index) {
+ OPJ_UINT32 it_tile = 0;
+
+ for (it_tile=0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) {
+
+ if(p_cstr_ind->tile_index[it_tile].packet_index) {
+ opj_free(p_cstr_ind->tile_index[it_tile].packet_index);
+ p_cstr_ind->tile_index[it_tile].packet_index = NULL;
+ }
+
+ if(p_cstr_ind->tile_index[it_tile].tp_index){
+ opj_free(p_cstr_ind->tile_index[it_tile].tp_index);
+ p_cstr_ind->tile_index[it_tile].tp_index = NULL;
+ }
+
+ if(p_cstr_ind->tile_index[it_tile].marker){
+ opj_free(p_cstr_ind->tile_index[it_tile].marker);
+ p_cstr_ind->tile_index[it_tile].marker = NULL;
+
+ }
+ }
+
+ opj_free( p_cstr_ind->tile_index);
+ p_cstr_ind->tile_index = NULL;
+ }
+
+ opj_free(p_cstr_ind);
+ }
+}
+
+void opj_j2k_tcp_destroy (opj_tcp_v2_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;i<p_tcp->m_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;
+ }
+
+ opj_j2k_tcp_data_destroy(p_tcp);
+
+}
+
+void opj_j2k_tcp_data_destroy (opj_tcp_v2_t *p_tcp)
+{
+ if (p_tcp->m_data) {
+ opj_free(p_tcp->m_data);
+ p_tcp->m_data = NULL;
+ p_tcp->m_data_size = 0;
+ }
+}
+
+void opj_j2k_cp_destroy (opj_cp_v2_t *p_cp)
+{
+ OPJ_UINT32 l_nb_tiles;
+ opj_tcp_v2_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)
+ {
+ opj_j2k_tcp_destroy(l_current_tile);
+ ++l_current_tile;
+ }
+ opj_free(p_cp->tcps);
+ p_cp->tcps = 00;
+ }
+ opj_free(p_cp->ppm_buffer);
+ p_cp->ppm_buffer = 00;
+ p_cp->ppm_data = NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */
+ opj_free(p_cp->comment);
+ p_cp->comment = 00;
+ if (! p_cp->m_is_decoder)
+ {
+ opj_free(p_cp->m_specific_param.m_enc.m_matrice);
+ p_cp->m_specific_param.m_enc.m_matrice = 00;
+ }
+}
+
+opj_bool opj_j2k_read_tile_header( opj_j2k_v2_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,
+ opj_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_v2_t * l_tcp = NULL;
+ OPJ_UINT32 l_nb_tiles;
+
+ /* preconditions */
+ assert(p_stream != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ /* Reach the End Of Codestream ?*/
+ if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC){
+ l_current_marker = J2K_MS_EOC;
+ }
+ /* We need to encounter a SOT marker (a new tile-part header) */
+ else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT){
+ return OPJ_FALSE;
+ }
+
+ /* Read into the codestream until reach the EOC or ! can_decode ??? FIXME */
+ while ( (!p_j2k->m_specific_param.m_decoder.m_can_decode) && (l_current_marker != J2K_MS_EOC) ) {
+
+ /* Try to read until the Start Of Data is detected */
+ while (l_current_marker != J2K_MS_SOD) {
+
+ /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* Read 2 bytes from the buffer as the marker size */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2);
+
+ /* Why this condition? FIXME */
+ if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH){
+ p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2);
+ }
+ l_marker_size -= 2; /* Subtract the size of the marker ID already read */
+
+ /* Get the marker handler from the marker ID */
+ l_marker_handler = opj_j2k_get_marker_handler(l_current_marker);
+
+ /* Check if the marker is known and if it is the right place to find it */
+ if (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Marker is not compliant with its position\n");
+ return OPJ_FALSE;
+ }
+/* FIXME manage case of unknown marker as in the main header ? */
+
+ /* Check if the marker size is compatible with the header data size */
+ if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) {
+ OPJ_BYTE *new_header_data = (OPJ_BYTE *) opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size);
+ if (! new_header_data) {
+ opj_free(p_j2k->m_specific_param.m_decoder.m_header_data);
+ p_j2k->m_specific_param.m_decoder.m_header_data = NULL;
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = 0;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to read header\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data;
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size;
+ }
+
+ /* Try to read the rest of the marker segment from stream and copy them into the buffer */
+ 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_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ if (!l_marker_handler->handler) {
+ /* See issue #175 */
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not sure how that happened.\n");
+ return OPJ_FALSE;
+ }
+ /* Read the marker segment with the correct marker handler */
+ 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_v2(p_manager, EVT_ERROR, "Fail to read the current marker segment (%#x)\n", l_current_marker);
+ return OPJ_FALSE;
+ }
+
+ /* Add the marker to the codestream index*/
+ if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number,
+ p_j2k->cstr_index,
+ l_marker_handler->id,
+ (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4,
+ l_marker_size + 4 )) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n");
+ return OPJ_FALSE;
+ }
+
+ /* Keep the position of the last SOT marker read */
+ if ( l_marker_handler->id == J2K_MS_SOT ) {
+ OPJ_UINT32 sot_pos = (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4 ;
+ if (sot_pos > p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos)
+ {
+ p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = sot_pos;
+ }
+ }
+
+ if (p_j2k->m_specific_param.m_decoder.m_skip_data) {
+ /* Skip the rest of the tile part header*/
+ 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_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+ l_current_marker = J2K_MS_SOD; /* Normally we reached a SOD */
+ }
+ else {
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+ /* Read 2 bytes from the buffer as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+ }
+ }
+
+ /* If we didn't skip data before, we need to read the SOD marker*/
+ if (! p_j2k->m_specific_param.m_decoder.m_skip_data) {
+ /* Try to read the SOD marker and skip data ? FIXME */
+ if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ if (! p_j2k->m_specific_param.m_decoder.m_can_decode){
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* Read 2 bytes from buffer as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+ }
+ }
+ else {
+ /* Indicate we will try to read a new tile-part header*/
+ 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_STATE_TPHSOT;
+
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_FALSE;
+ }
+
+ /* Read 2 bytes from buffer as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+ }
+ }
+
+ /* Current marker is the EOC marker ?*/
+ if (l_current_marker == J2K_MS_EOC) {
+ if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC ){
+ p_j2k->m_current_tile_number = 0;
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
+ }
+ }
+
+ /* FIXME DOC ???*/
+ 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 = OPJ_FALSE;
+ return OPJ_TRUE;
+ }
+ }
+
+ /*FIXME ???*/
+ if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
+ return OPJ_FALSE;
+ }
+
+ opj_event_msg_v2(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n",
+ p_j2k->m_current_tile_number, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
+
+ *p_tile_index = p_j2k->m_current_tile_number;
+ *p_go_on = OPJ_TRUE;
+ *p_data_size = opj_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 |= 0x0080;/* FIXME J2K_DEC_STATE_DATA;*/
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_decode_tile ( opj_j2k_v2_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_v2_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 & 0x0080/*FIXME J2K_DEC_STATE_DATA*/)
+ || (p_tile_index != p_j2k->m_current_tile_number) ) {
+ return OPJ_FALSE;
+ }
+
+ l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]);
+ if (! l_tcp->m_data) {
+ opj_j2k_tcp_destroy(l_tcp);
+ return OPJ_FALSE;
+ }
+
+ if (! opj_tcd_decode_tile( p_j2k->m_tcd,
+ l_tcp->m_data,
+ l_tcp->m_data_size,
+ p_tile_index,
+ p_j2k->cstr_index) ) {
+ opj_j2k_tcp_destroy(l_tcp);
+ p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
+ return OPJ_FALSE;
+ }
+
+ if (! opj_tcd_update_tile_data(p_j2k->m_tcd,p_data,p_data_size)) {
+ return OPJ_FALSE;
+ }
+
+ /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access)
+ * we destroy just the data which will be re-read in read_tile_header*/
+ /*opj_j2k_tcp_destroy(l_tcp);
+ p_j2k->m_tcd->tcp = 0;*/
+ opj_j2k_tcp_data_destroy(l_tcp);
+
+ p_j2k->m_specific_param.m_decoder.m_can_decode = 0;
+ p_j2k->m_specific_param.m_decoder.m_state &= (~ (0x0080));/* FIXME J2K_DEC_STATE_DATA);*/
+
+ if (p_j2k->m_specific_param.m_decoder.m_state != 0x0100){ /*FIXME J2K_DEC_STATE_EOC)*/
+ if (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n");
+ return OPJ_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 = 0x0100;/*FIXME J2K_DEC_STATE_EOC;*/
+ }
+ else if (l_current_marker != J2K_MS_SOT)
+ {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short, expected SOT\n");
+ return OPJ_FALSE;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image)
+{
+ OPJ_UINT32 i,j,k = 0;
+ OPJ_UINT32 l_width_src,l_height_src;
+ OPJ_UINT32 l_width_dest,l_height_dest;
+ OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src;
+ OPJ_INT32 l_start_offset_src, l_line_offset_src, l_end_offset_src ;
+ OPJ_UINT32 l_start_x_dest , l_start_y_dest;
+ OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest;
+ OPJ_INT32 l_start_offset_dest, l_line_offset_dest;
+
+ opj_image_comp_t * l_img_comp_src = 00;
+ opj_image_comp_t * l_img_comp_dest = 00;
+
+ opj_tcd_tilecomp_v2_t * l_tilec = 00;
+ opj_image_t * l_image_src = 00;
+ OPJ_UINT32 l_size_comp, l_remaining;
+ OPJ_INT32 * l_dest_ptr;
+ opj_tcd_resolution_v2_t* l_res= 00;
+
+ l_tilec = p_tcd->tcd_image->tiles->comps;
+ l_image_src = p_tcd->image;
+ l_img_comp_src = l_image_src->comps;
+
+ l_img_comp_dest = p_output_image->comps;
+
+ for (i=0; i<l_image_src->numcomps; i++) {
+
+ /* Allocate output component buffer if necessary */
+ if (!l_img_comp_dest->data) {
+
+ l_img_comp_dest->data = (OPJ_INT32*) opj_calloc(l_img_comp_dest->w * l_img_comp_dest->h, sizeof(OPJ_INT32));
+ if (! l_img_comp_dest->data) {
+ return OPJ_FALSE;
+ }
+ }
+
+ /* Copy info from decoded comp image to output image */
+ l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded;
+
+ /*-----*/
+ /* Compute the precision of the output buffer */
+ l_size_comp = l_img_comp_src->prec >> 3; /*(/ 8)*/
+ l_remaining = l_img_comp_src->prec & 7; /* (%8) */
+ l_res = l_tilec->resolutions + l_img_comp_src->resno_decoded;
+
+ if (l_remaining) {
+ ++l_size_comp;
+ }
+
+ if (l_size_comp == 3) {
+ l_size_comp = 4;
+ }
+ /*-----*/
+
+ /* Current tile component size*/
+ /*if (i == 0) {
+ fprintf(stdout, "SRC: l_res_x0=%d, l_res_x1=%d, l_res_y0=%d, l_res_y1=%d\n",
+ l_res->x0, l_res->x1, l_res->y0, l_res->y1);
+ }*/
+
+ l_width_src = (l_res->x1 - l_res->x0);
+ l_height_src = (l_res->y1 - l_res->y0);
+
+ /* Border of the current output component*/
+ l_x0_dest = int_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor);
+ l_y0_dest = int_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor);
+ l_x1_dest = l_x0_dest + l_img_comp_dest->w;
+ l_y1_dest = l_y0_dest + l_img_comp_dest->h;
+
+ /*if (i == 0) {
+ fprintf(stdout, "DEST: l_x0_dest=%d, l_x1_dest=%d, l_y0_dest=%d, l_y1_dest=%d (%d)\n",
+ l_x0_dest, l_x1_dest, l_y0_dest, l_y1_dest, l_img_comp_dest->factor );
+ }*/
+
+ /*-----*/
+ /* Compute the area (l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src)
+ * of the input buffer (decoded tile component) which will be move
+ * in the output buffer. Compute the area of the output buffer (l_start_x_dest,
+ * l_start_y_dest, l_width_dest, l_height_dest) which will be modified
+ * by this input area.
+ * */
+ assert( l_res->x0 >= 0);
+ assert( l_res->x1 >= 0);
+ if ( l_x0_dest < (OPJ_UINT32)l_res->x0 ) {
+ l_start_x_dest = l_res->x0 - l_x0_dest;
+ l_offset_x0_src = 0;
+
+ if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) {
+ l_width_dest = l_width_src;
+ l_offset_x1_src = 0;
+ }
+ else {
+ l_width_dest = l_x1_dest - l_res->x0 ;
+ l_offset_x1_src = l_width_src - l_width_dest;
+ }
+ }
+ else {
+ l_start_x_dest = 0 ;
+ l_offset_x0_src = l_x0_dest - l_res->x0;
+
+ if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) {
+ l_width_dest = l_width_src - l_offset_x0_src;
+ l_offset_x1_src = 0;
+ }
+ else {
+ l_width_dest = l_img_comp_dest->w ;
+ l_offset_x1_src = l_res->x1 - l_x1_dest;
+ }
+ }
+
+ if ( l_y0_dest < (OPJ_UINT32)l_res->y0 ) {
+ l_start_y_dest = l_res->y0 - l_y0_dest;
+ l_offset_y0_src = 0;
+
+ if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) {
+ l_height_dest = l_height_src;
+ l_offset_y1_src = 0;
+ }
+ else {
+ l_height_dest = l_y1_dest - l_res->y0 ;
+ l_offset_y1_src = l_height_src - l_height_dest;
+ }
+ }
+ else {
+ l_start_y_dest = 0 ;
+ l_offset_y0_src = l_y0_dest - l_res->y0;
+
+ if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) {
+ l_height_dest = l_height_src - l_offset_y0_src;
+ l_offset_y1_src = 0;
+ }
+ else {
+ l_height_dest = l_img_comp_dest->h ;
+ l_offset_y1_src = l_res->y1 - l_y1_dest;
+ }
+ }
+
+ if( (l_offset_x0_src < 0 ) || (l_offset_y0_src < 0 ) || (l_offset_x1_src < 0 ) || (l_offset_y1_src < 0 ) ){
+ return OPJ_FALSE;
+ }
+ /*-----*/
+
+ /* Compute the input buffer offset */
+ l_start_offset_src = l_offset_x0_src + l_offset_y0_src * l_width_src;
+ l_line_offset_src = l_offset_x1_src + l_offset_x0_src;
+ l_end_offset_src = l_offset_y1_src * l_width_src - l_offset_x0_src;
+
+ /* Compute the output buffer offset */
+ l_start_offset_dest = l_start_x_dest + l_start_y_dest * l_img_comp_dest->w;
+ l_line_offset_dest = l_img_comp_dest->w - l_width_dest;
+
+ /* Move the output buffer to the first place where we will write*/
+ l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
+
+ /*if (i == 0) {
+ fprintf(stdout, "COMPO[%d]:\n",i);
+ fprintf(stdout, "SRC: l_start_x_src=%d, l_start_y_src=%d, l_width_src=%d, l_height_src=%d\n"
+ "\t tile offset:%d, %d, %d, %d\n"
+ "\t buffer offset: %d; %d, %d\n",
+ l_res->x0, l_res->y0, l_width_src, l_height_src,
+ l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src,
+ l_start_offset_src, l_line_offset_src, l_end_offset_src);
+
+ fprintf(stdout, "DEST: l_start_x_dest=%d, l_start_y_dest=%d, l_width_dest=%d, l_height_dest=%d\n"
+ "\t start offset: %d, line offset= %d\n",
+ l_start_x_dest, l_start_y_dest, l_width_dest, l_height_dest, l_start_offset_dest, l_line_offset_dest);
+ }*/
+
+ switch (l_size_comp) {
+ case 1:
+ {
+ OPJ_CHAR * l_src_ptr = (OPJ_CHAR*) p_data;
+ l_src_ptr += l_start_offset_src; /* Move to the first place where we will read*/
+
+ if (l_img_comp_src->sgnd) {
+ for (j = 0 ; j < l_height_dest ; ++j) {
+ for ( k = 0 ; k < l_width_dest ; ++k) {
+ *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++)); /* Copy only the data needed for the output image */
+ }
+
+ l_dest_ptr+= l_line_offset_dest; /* Move to the next place where we will write */
+ l_src_ptr += l_line_offset_src ; /* Move to the next place where we will read */
+ }
+ }
+ else {
+ for ( j = 0 ; j < l_height_dest ; ++j ) {
+ for ( k = 0 ; k < l_width_dest ; ++k) {
+ *(l_dest_ptr++) = (OPJ_INT32) ((*(l_src_ptr++))&0xff);
+ }
+
+ l_dest_ptr+= l_line_offset_dest;
+ l_src_ptr += l_line_offset_src;
+ }
+ }
+
+ l_src_ptr += l_end_offset_src; /* Move to the end of this component-part of the input buffer */
+ p_data = (OPJ_BYTE*) l_src_ptr; /* Keep the current position for the next component-part */
+ }
+ break;
+ case 2:
+ {
+ OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_data;
+ l_src_ptr += l_start_offset_src;
+
+ if (l_img_comp_src->sgnd) {
+ for (j=0;j<l_height_dest;++j) {
+ for (k=0;k<l_width_dest;++k) {
+ *(l_dest_ptr++) = *(l_src_ptr++);
+ }
+
+ l_dest_ptr+= l_line_offset_dest;
+ l_src_ptr += l_line_offset_src ;
+ }
+ }
+ else {
+ for (j=0;j<l_height_dest;++j) {
+ for (k=0;k<l_width_dest;++k) {
+ *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff;
+ }
+
+ l_dest_ptr+= l_line_offset_dest;
+ l_src_ptr += l_line_offset_src ;
+ }
+ }
+
+ l_src_ptr += l_end_offset_src;
+ p_data = (OPJ_BYTE*) l_src_ptr;
+ }
+ break;
+ case 4:
+ {
+ OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_data;
+ l_src_ptr += l_start_offset_src;
+
+ for (j=0;j<l_height_dest;++j) {
+ for (k=0;k<l_width_dest;++k) {
+ *(l_dest_ptr++) = (*(l_src_ptr++));
+ }
+
+ l_dest_ptr+= l_line_offset_dest;
+ l_src_ptr += l_line_offset_src ;
+ }
+
+ l_src_ptr += l_end_offset_src;
+ p_data = (OPJ_BYTE*) l_src_ptr;
+ }
+ break;
+ }
+
+ ++l_img_comp_dest;
+ ++l_img_comp_src;
+ ++l_tilec;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_set_decode_area( opj_j2k_v2_t *p_j2k,
+ opj_image_t* p_image,
+ OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
+ OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
+ opj_event_mgr_t * p_manager )
+{
+ opj_cp_v2_t * l_cp = &(p_j2k->m_cp);
+ opj_image_t * l_image = p_j2k->m_private_image;
+
+ OPJ_UINT32 it_comp;
+ OPJ_INT32 l_comp_x1, l_comp_y1;
+ opj_image_comp_t* l_img_comp = NULL;
+
+ /* Check if we are read the main header */
+ if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { /* FIXME J2K_DEC_STATE_TPHSOT)*/
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Need to decode the main header before begin to decode the remaining codestream");
+ return OPJ_FALSE;
+ }
+
+ if ( !p_start_x && !p_start_y && !p_end_x && !p_end_y){
+ opj_event_msg_v2(p_manager, EVT_INFO, "No decoded area parameters, set the decoded area to the whole image\n");
+
+ 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;
+
+ return OPJ_TRUE;
+ }
+
+ /* ----- */
+ /* Check if the positions provided by the user are correct */
+
+ /* Left */
+ assert(p_start_x >= 0 );
+ assert(p_start_y >= 0 );
+
+ if ((OPJ_UINT32)p_start_x > l_image->x1 ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n",
+ p_start_x, l_image->x1);
+ return OPJ_FALSE;
+ }
+ else if ((OPJ_UINT32)p_start_x < l_image->x0){
+ opj_event_msg_v2(p_manager, EVT_WARNING,
+ "Left position of the decoded area (region_x0=%d) is outside the image area (XOsiz=%d).\n",
+ p_start_x, l_image->x0);
+ p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0;
+ p_image->x0 = l_image->x0;
+ }
+ else {
+ p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_start_x - l_cp->tx0) / l_cp->tdx;
+ p_image->x0 = p_start_x;
+ }
+
+ /* Up */
+ if ((OPJ_UINT32)p_start_y > l_image->y1){
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n",
+ p_start_y, l_image->y1);
+ return OPJ_FALSE;
+ }
+ else if ((OPJ_UINT32)p_start_y < l_image->y0){
+ opj_event_msg_v2(p_manager, EVT_WARNING,
+ "Up position of the decoded area (region_y0=%d) is outside the image area (YOsiz=%d).\n",
+ p_start_y, l_image->y0);
+ p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0;
+ p_image->y0 = l_image->y0;
+ }
+ else {
+ p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_start_y - l_cp->ty0) / l_cp->tdy;
+ p_image->y0 = p_start_y;
+ }
+
+ /* Right */
+ assert((OPJ_UINT32)p_end_x > 0);
+ assert((OPJ_UINT32)p_end_y > 0);
+ if ((OPJ_UINT32)p_end_x < l_image->x0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n",
+ p_end_x, l_image->x0);
+ return OPJ_FALSE;
+ }
+ else if ((OPJ_UINT32)p_end_x > l_image->x1) {
+ opj_event_msg_v2(p_manager, EVT_WARNING,
+ "Right position of the decoded area (region_x1=%d) is outside the image area (Xsiz=%d).\n",
+ p_end_x, l_image->x1);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw;
+ p_image->x1 = l_image->x1;
+ }
+ else {
+ p_j2k->m_specific_param.m_decoder.m_end_tile_x = int_ceildiv((p_end_x - l_cp->tx0), l_cp->tdx);
+ p_image->x1 = p_end_x;
+ }
+
+ /* Bottom */
+ if ((OPJ_UINT32)p_end_y < l_image->y0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n",
+ p_end_y, l_image->y0);
+ return OPJ_FALSE;
+ }
+ if ((OPJ_UINT32)p_end_y > l_image->y1){
+ opj_event_msg_v2(p_manager, EVT_WARNING,
+ "Bottom position of the decoded area (region_y1=%d) is outside the image area (Ysiz=%d).\n",
+ p_end_y, l_image->y1);
+ p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th;
+ p_image->y1 = l_image->y1;
+ }
+ else{
+ p_j2k->m_specific_param.m_decoder.m_end_tile_y = int_ceildiv((p_end_y - l_cp->ty0), l_cp->tdy);
+ p_image->y1 = p_end_y;
+ }
+ /* ----- */
+
+ p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1;
+
+ l_img_comp = p_image->comps;
+ for (it_comp=0; it_comp < p_image->numcomps; ++it_comp)
+ {
+ OPJ_INT32 l_h,l_w;
+
+ l_img_comp->x0 = int_ceildiv(p_image->x0, l_img_comp->dx);
+ l_img_comp->y0 = int_ceildiv(p_image->y0, l_img_comp->dy);
+ l_comp_x1 = int_ceildiv(p_image->x1, l_img_comp->dx);
+ l_comp_y1 = int_ceildiv(p_image->y1, l_img_comp->dy);
+
+ l_w = int_ceildivpow2(l_comp_x1, l_img_comp->factor)
+ - int_ceildivpow2(l_img_comp->x0, l_img_comp->factor);
+ if (l_w < 0){
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Size x of the decoded component image is incorrect (comp[%d].w=%d).\n",
+ it_comp, l_w);
+ return OPJ_FALSE;
+ }
+ l_img_comp->w = l_w;
+
+ l_h = int_ceildivpow2(l_comp_y1, l_img_comp->factor)
+ - int_ceildivpow2(l_img_comp->y0, l_img_comp->factor);
+ if (l_h < 0){
+ opj_event_msg_v2(p_manager, EVT_ERROR,
+ "Size y of the decoded component image is incorrect (comp[%d].h=%d).\n",
+ it_comp, l_h);
+ return OPJ_FALSE;
+ }
+ l_img_comp->h = l_h;
+
+ l_img_comp++;
+ }
+
+ opj_event_msg_v2( p_manager, EVT_INFO,"Setting decoding area to %d,%d,%d,%d\n",
+ p_image->x0, p_image->y0, p_image->x1, p_image->y1);
+
+ return OPJ_TRUE;
+}
+
+opj_j2k_v2_t* opj_j2k_create_decompress(void)
+{
+ opj_j2k_v2_t *l_j2k = (opj_j2k_v2_t*) opj_malloc(sizeof(opj_j2k_v2_t));
+ if (!l_j2k) {
+ return 00;
+ }
+ memset(l_j2k,0,sizeof(opj_j2k_v2_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_v2_t*) opj_malloc(sizeof(opj_tcp_v2_t));
+ if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) {
+ opj_j2k_destroy(l_j2k);
+ return 00;
+ }
+ memset(l_j2k->m_specific_param.m_decoder.m_default_tcp,0,sizeof(opj_tcp_v2_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) {
+ opj_j2k_destroy(l_j2k);
+ return 00;
+ }
+
+ l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE;
+
+ l_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = -1 ;
+
+ l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ;
+
+ /* codestream index creation */
+ l_j2k->cstr_index = opj_j2k_create_cstr_index();
+
+ /*(opj_codestream_index_t*) opj_malloc(sizeof(opj_codestream_index_t));
+ if (!l_j2k->cstr_index){
+ opj_j2k_destroy(l_j2k);
+ return NULL;
+ }
+
+ l_j2k->cstr_index->marker = (opj_marker_info_t*) opj_malloc(100 * sizeof(opj_marker_info_t));
+*/
+
+ /* validation list creation */
+ l_j2k->m_validation_list = opj_procedure_list_create();
+ if (! l_j2k->m_validation_list) {
+ opj_j2k_destroy(l_j2k);
+ return 00;
+ }
+
+ /* execution list creation */
+ l_j2k->m_procedure_list = opj_procedure_list_create();
+ if (! l_j2k->m_procedure_list) {
+ opj_j2k_destroy(l_j2k);
+ return 00;
+ }
+
+ return l_j2k;
+}
+
+opj_codestream_index_t* opj_j2k_create_cstr_index(void)
+{
+ opj_codestream_index_t* cstr_index = (opj_codestream_index_t*)
+ opj_calloc(1,sizeof(opj_codestream_index_t));
+ if (!cstr_index)
+ return NULL;
+
+ cstr_index->maxmarknum = 100;
+ cstr_index->marknum = 0;
+ cstr_index->marker = (opj_marker_info_t*)
+ opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t));
+ if (!cstr_index-> marker)
+ return NULL;
+
+ cstr_index->tile_index = NULL;
+
+ return cstr_index;
+}
+
+OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size ( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no )
+{
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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_private_image->numcomps);
+
+ if (l_tccp->csty & J2K_CCP_CSTY_PRT) {
+ return 5 + l_tccp->numresolutions;
+ }
+ else {
+ return 5;
+ }
+}
+
+opj_bool opj_j2k_write_SPCod_SPCoc( opj_j2k_v2_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_v2_t *l_cp = 00;
+ opj_tcp_v2_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_private_image->numcomps));
+
+ if (*p_header_size < 5) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error writting SPCod SPCoc element\n");
+ return OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_SPCod_SPCoc( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 compno,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 i, l_tmp;
+ opj_cp_v2_t *l_cp = NULL;
+ opj_tcp_v2_t *l_tcp = NULL;
+ opj_tccp_t *l_tccp = NULL;
+ OPJ_BYTE * l_current_ptr = NULL;
+
+ /* 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_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_private_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_v2(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n");
+ return OPJ_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_v2(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 |= 0x8000;/* FIXME J2K_DEC_STATE_ERR;*/
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n");
+ return OPJ_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;
+ }
+ }
+
+#ifdef WIP_REMOVE_MSD
+ /* INDEX >> */
+ if (p_j2k->cstr_info && compno == 0) {
+ OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32);
+
+ p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkh = l_tccp->cblkh;
+ p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkw = l_tccp->cblkw;
+ p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].numresolutions = l_tccp->numresolutions;
+ p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblksty = l_tccp->cblksty;
+ p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].qmfbid = l_tccp->qmfbid;
+
+ 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 */
+#endif
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_copy_tile_component_parameters( opj_j2k_v2_t *p_j2k )
+{
+ /* loop */
+ OPJ_UINT32 i;
+ opj_cp_v2_t *l_cp = NULL;
+ opj_tcp_v2_t *l_tcp = NULL;
+ opj_tccp_t *l_ref_tccp = NULL, *l_copied_tccp = NULL;
+ 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_STATE_TPH) ? /* FIXME 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; i<p_j2k->m_private_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;
+ }
+}
+
+OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size ( opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_tile_no,
+ OPJ_UINT32 p_comp_no )
+{
+ OPJ_UINT32 l_num_bands;
+
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_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_private_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;
+ }
+}
+
+opj_bool opj_j2k_write_SQcd_SQcc( opj_j2k_v2_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_v2_t *l_cp = 00;
+ opj_tcp_v2_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_private_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_v2(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n");
+ return OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_read_SQcd_SQcc(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 p_comp_no,
+ OPJ_BYTE* p_header_data,
+ OPJ_UINT32 * p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* loop*/
+ OPJ_UINT32 l_band_no;
+ opj_cp_v2_t *l_cp = 00;
+ opj_tcp_v2_t *l_tcp = 00;
+ opj_tccp_t *l_tccp = 00;
+ OPJ_BYTE * l_current_ptr = 00;
+ OPJ_UINT32 l_tmp, l_num_band;
+
+ /* preconditions*/
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_header_data != 00);
+
+ l_cp = &(p_j2k->m_cp);
+ /* come from tile part header or main header ?*/
+ l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? /*FIXME 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_private_image->numcomps);
+
+ l_tccp = &l_tcp->tccps[p_comp_no];
+ l_current_ptr = p_header_data;
+
+ if (*p_header_size < 1) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading SQcd or SQcc element\n");
+ return OPJ_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;
+
+ if( l_num_band > J2K_MAXBANDS ) {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "While reading CCP_QNTSTY element inside QCD or QCC marker segment, "
+ "number of subbands (%d) is greater to J2K_MAXBANDS (%d). So we limit the number of elements stored to "
+ "J2K_MAXBANDS (%d) and skip the rest. \n", l_num_band, J2K_MAXBANDS, J2K_MAXBANDS);
+ /*return OPJ_FALSE;*/
+ }
+ }
+
+#ifdef USE_JPWL
+ if (l_cp->correct) {
+
+ /* if JPWL is on, we check whether there are too many subbands */
+ if (/*(l_num_band < 0) ||*/ (l_num_band >= J2K_MAXBANDS)) {
+ opj_event_msg_v2(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad number of subbands in Sqcx (%d)\n",
+ l_num_band);
+ if (!JPWL_ASSUME) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ /* we try to correct */
+ l_num_band = 1;
+ opj_event_msg_v2(p_manager, EVT_WARNING, "- trying to adjust them\n"
+ "- setting number of bands to %d => HYPOTHESIS!!!\n",
+ l_num_band);
+ };
+
+ };
+#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;
+ if (l_band_no < J2K_MAXBANDS){
+ 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;
+ if (l_band_no < J2K_MAXBANDS){
+ 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 OPJ_TRUE;
+}
+
+void opj_j2k_copy_tile_quantization_parameters( opj_j2k_v2_t *p_j2k )
+{
+ OPJ_UINT32 i;
+ opj_cp_v2_t *l_cp = NULL;
+ opj_tcp_v2_t *l_tcp = NULL;
+ opj_tccp_t *l_ref_tccp = NULL;
+ opj_tccp_t *l_copied_tccp = NULL;
+ 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_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_size = J2K_MAXBANDS * sizeof(opj_stepsize_t);
+
+ for (i=1;i<p_j2k->m_private_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;
+ }
+}
+
+void j2k_dump (opj_j2k_v2_t* p_j2k, OPJ_INT32 flag, FILE* out_stream)
+{
+ /* Check if the flag is compatible with j2k file*/
+ if ( (flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)){
+ fprintf(out_stream, "Wrong flag\n");
+ return;
+ }
+
+ /* Dump the image_header */
+ if (flag & OPJ_IMG_INFO){
+ if (p_j2k->m_private_image)
+ j2k_dump_image_header(p_j2k->m_private_image, 0, out_stream);
+ }
+
+ /* Dump the codestream info from main header */
+ if (flag & OPJ_J2K_MH_INFO){
+ opj_j2k_dump_MH_info(p_j2k, out_stream);
+ }
+
+ /* Dump the codestream info of the current tile */
+ if (flag & OPJ_J2K_TH_INFO){
+
+ }
+
+ /* Dump the codestream index from main header */
+ if (flag & OPJ_J2K_MH_IND){
+ opj_j2k_dump_MH_index(p_j2k, out_stream);
+ }
+
+ /* Dump the codestream index of the current tile */
+ if (flag & OPJ_J2K_TH_IND){
+
+ }
+
+}
+
+void opj_j2k_dump_MH_index(opj_j2k_v2_t* p_j2k, FILE* out_stream)
+{
+ opj_codestream_index_t* cstr_index = p_j2k->cstr_index;
+ OPJ_UINT32 it_marker, it_tile, it_tile_part;
+
+ fprintf(out_stream, "Codestream index from main header: {\n");
+
+ fprintf(out_stream, "\t Main header start position=%" PRIi64 "\n"
+ "\t Main header end position=%" PRIi64 "\n",
+ cstr_index->main_head_start, cstr_index->main_head_end);
+
+ fprintf(out_stream, "\t Marker list: {\n");
+
+ if (cstr_index->marker){
+ for (it_marker=0; it_marker < cstr_index->marknum ; it_marker++){
+ fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n",
+ cstr_index->marker[it_marker].type,
+ cstr_index->marker[it_marker].pos,
+ cstr_index->marker[it_marker].len );
+ }
+ }
+
+ fprintf(out_stream, "\t }\n");
+
+ if (cstr_index->tile_index){
+
+ /* Simple test to avoid to write empty information*/
+ OPJ_UINT32 l_acc_nb_of_tile_part = 0;
+ for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){
+ l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps;
+ }
+
+ if (l_acc_nb_of_tile_part)
+ {
+ fprintf(out_stream, "\t Tile index: {\n");
+
+ for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){
+ OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps;
+
+ fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, nb_of_tile_part);
+
+ if (cstr_index->tile_index[it_tile].tp_index){
+ for (it_tile_part =0; it_tile_part < nb_of_tile_part; it_tile_part++){
+ fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" PRIi64 ", end_pos=%" PRIi64 ".\n",
+ it_tile_part,
+ cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos,
+ cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header,
+ cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos);
+ }
+ }
+
+ if (cstr_index->tile_index[it_tile].marker){
+ for (it_marker=0; it_marker < cstr_index->tile_index[it_tile].marknum ; it_marker++){
+ fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n",
+ cstr_index->tile_index[it_tile].marker[it_marker].type,
+ cstr_index->tile_index[it_tile].marker[it_marker].pos,
+ cstr_index->tile_index[it_tile].marker[it_marker].len );
+ }
+ }
+ }
+ fprintf(out_stream,"\t }\n");
+ }
+ }
+
+ fprintf(out_stream,"}\n");
+
+}
+
+void opj_j2k_dump_MH_info(opj_j2k_v2_t* p_j2k, FILE* out_stream)
+{
+ opj_tcp_v2_t * l_default_tile=NULL;
+
+ fprintf(out_stream, "Codestream info from main header: {\n");
+
+ fprintf(out_stream, "\t tx0=%d, ty0=%d\n", p_j2k->m_cp.tx0, p_j2k->m_cp.ty0);
+ fprintf(out_stream, "\t tdx=%d, tdy=%d\n", p_j2k->m_cp.tdx, p_j2k->m_cp.tdy);
+ fprintf(out_stream, "\t tw=%d, th=%d\n", p_j2k->m_cp.tw, p_j2k->m_cp.th);
+
+ l_default_tile = p_j2k->m_specific_param.m_decoder.m_default_tcp;
+ if (l_default_tile)
+ {
+ OPJ_INT32 compno;
+ OPJ_INT32 numcomps = p_j2k->m_private_image->numcomps;
+
+ fprintf(out_stream, "\t default tile {\n");
+ fprintf(out_stream, "\t\t csty=%#x\n", l_default_tile->csty);
+ fprintf(out_stream, "\t\t prg=%#x\n", l_default_tile->prg);
+ fprintf(out_stream, "\t\t numlayers=%d\n", l_default_tile->numlayers);
+ fprintf(out_stream, "\t\t mct=%x\n", l_default_tile->mct);
+
+ for (compno = 0; compno < numcomps; compno++) {
+ opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]);
+ OPJ_UINT32 resno;
+ OPJ_INT32 bandno, numbands;
+
+ /* coding style*/
+ fprintf(out_stream, "\t\t comp %d {\n", compno);
+ fprintf(out_stream, "\t\t\t csty=%#x\n", l_tccp->csty);
+ fprintf(out_stream, "\t\t\t numresolutions=%d\n", l_tccp->numresolutions);
+ fprintf(out_stream, "\t\t\t cblkw=2^%d\n", l_tccp->cblkw);
+ fprintf(out_stream, "\t\t\t cblkh=2^%d\n", l_tccp->cblkh);
+ fprintf(out_stream, "\t\t\t cblksty=%#x\n", l_tccp->cblksty);
+ fprintf(out_stream, "\t\t\t qmfbid=%d\n", l_tccp->qmfbid);
+
+ fprintf(out_stream, "\t\t\t preccintsize (w,h)=");
+ for (resno = 0; resno < l_tccp->numresolutions; resno++) {
+ fprintf(out_stream, "(%d,%d) ", l_tccp->prcw[resno], l_tccp->prch[resno]);
+ }
+ fprintf(out_stream, "\n");
+
+ /* quantization style*/
+ fprintf(out_stream, "\t\t\t qntsty=%d\n", l_tccp->qntsty);
+ fprintf(out_stream, "\t\t\t numgbits=%d\n", l_tccp->numgbits);
+ fprintf(out_stream, "\t\t\t stepsizes (m,e)=");
+ numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : l_tccp->numresolutions * 3 - 2;
+ for (bandno = 0; bandno < numbands; bandno++) {
+ fprintf(out_stream, "(%d,%d) ", l_tccp->stepsizes[bandno].mant,
+ l_tccp->stepsizes[bandno].expn);
+ }
+ fprintf(out_stream, "\n");
+
+ /* RGN value*/
+ fprintf(out_stream, "\t\t\t roishift=%d\n", l_tccp->roishift);
+
+ fprintf(out_stream, "\t\t }\n");
+ } /*end of component of default tile*/
+ fprintf(out_stream, "\t }\n"); /*end of default tile*/
+
+ }
+
+ fprintf(out_stream, "}\n");
+
+}
+
+void j2k_dump_image_header(opj_image_t* img_header, opj_bool dev_dump_flag, FILE* out_stream)
+{
+ char tab[2];
+
+ if (dev_dump_flag){
+ fprintf(stdout, "[DEV] Dump an image_header struct {\n");
+ tab[0] = '\0';
+ }
+ else {
+ fprintf(out_stream, "Image info {\n");
+ tab[0] = '\t';tab[1] = '\0';
+ }
+
+ fprintf(out_stream, "%s x0=%d, y0=%d\n", tab, img_header->x0, img_header->y0);
+ fprintf(out_stream, "%s x1=%d, y1=%d\n", tab, img_header->x1, img_header->y1);
+ fprintf(out_stream, "%s numcomps=%d\n", tab, img_header->numcomps);
+
+ if (img_header->comps){
+ OPJ_UINT32 compno;
+ for (compno = 0; compno < img_header->numcomps; compno++) {
+ fprintf(out_stream, "%s\t component %d {\n", tab, compno);
+ j2k_dump_image_comp_header(&(img_header->comps[compno]), dev_dump_flag, out_stream);
+ fprintf(out_stream,"%s}\n",tab);
+ }
+ }
+
+ fprintf(out_stream, "}\n");
+}
+
+void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, opj_bool dev_dump_flag, FILE* out_stream)
+{
+ char tab[3];
+
+ if (dev_dump_flag){
+ fprintf(stdout, "[DEV] Dump an image_comp_header struct {\n");
+ tab[0] = '\0';
+ } else {
+ tab[0] = '\t';tab[1] = '\t';tab[2] = '\0';
+ }
+
+ fprintf(out_stream, "%s dx=%d, dy=%d\n", tab, comp_header->dx, comp_header->dy);
+ fprintf(out_stream, "%s prec=%d\n", tab, comp_header->prec);
+ fprintf(out_stream, "%s sgnd=%d\n", tab, comp_header->sgnd);
+
+ if (dev_dump_flag)
+ fprintf(out_stream, "}\n");
+}
+
+opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_v2_t* p_j2k)
+{
+ OPJ_UINT16 compno;
+ OPJ_UINT16 numcomps = p_j2k->m_private_image->numcomps;
+ opj_tcp_v2_t *l_default_tile;
+ opj_codestream_info_v2_t* cstr_info = (opj_codestream_info_v2_t*) opj_calloc(1,sizeof(opj_codestream_info_v2_t));
+
+ cstr_info->nbcomps = p_j2k->m_private_image->numcomps;
+
+ cstr_info->tx0 = p_j2k->m_cp.tx0;
+ cstr_info->ty0 = p_j2k->m_cp.ty0;
+ cstr_info->tdx = p_j2k->m_cp.tdx;
+ cstr_info->tdy = p_j2k->m_cp.tdy;
+ cstr_info->tw = p_j2k->m_cp.tw;
+ cstr_info->th = p_j2k->m_cp.th;
+
+ cstr_info->tile_info = NULL; /* Not fill from the main header*/
+
+ l_default_tile = p_j2k->m_specific_param.m_decoder.m_default_tcp;
+
+ cstr_info->m_default_tile_info.csty = l_default_tile->csty;
+ cstr_info->m_default_tile_info.prg = l_default_tile->prg;
+ cstr_info->m_default_tile_info.numlayers = l_default_tile->numlayers;
+ cstr_info->m_default_tile_info.mct = l_default_tile->mct;
+
+ cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc(cstr_info->nbcomps, sizeof(opj_tccp_info_t));
+
+ for (compno = 0; compno < numcomps; compno++) {
+ opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]);
+ opj_tccp_info_t *l_tccp_info = &(cstr_info->m_default_tile_info.tccp_info[compno]);
+ OPJ_INT32 bandno, numbands;
+
+ /* coding style*/
+ l_tccp_info->csty = l_tccp->csty;
+ l_tccp_info->numresolutions = l_tccp->numresolutions;
+ l_tccp_info->cblkw = l_tccp->cblkw;
+ l_tccp_info->cblkh = l_tccp->cblkh;
+ l_tccp_info->cblksty = l_tccp->cblksty;
+ l_tccp_info->qmfbid = l_tccp->qmfbid;
+ if (l_tccp->numresolutions < J2K_MAXRLVLS)
+ {
+ memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions);
+ memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions);
+ }
+
+ /* quantization style*/
+ l_tccp_info->qntsty = l_tccp->qntsty;
+ l_tccp_info->numgbits = l_tccp->numgbits;
+
+ numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : l_tccp->numresolutions * 3 - 2;
+ if (numbands < J2K_MAXBANDS) {
+ for (bandno = 0; bandno < numbands; bandno++) {
+ l_tccp_info->stepsizes_mant[bandno] = l_tccp->stepsizes[bandno].mant;
+ l_tccp_info->stepsizes_expn[bandno] = l_tccp->stepsizes[bandno].expn;
+ }
+ }
+
+ /* RGN value*/
+ l_tccp_info->roishift = l_tccp->roishift;
+ }
+
+ return cstr_info;
+}
+
+opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_v2_t* p_j2k)
+{
+ opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*)
+ opj_calloc(1,sizeof(opj_codestream_index_t));
+ if (!l_cstr_index)
+ return NULL;
+
+ l_cstr_index->main_head_start = p_j2k->cstr_index->main_head_start;
+ l_cstr_index->main_head_end = p_j2k->cstr_index->main_head_end;
+ l_cstr_index->codestream_size = p_j2k->cstr_index->codestream_size;
+
+ l_cstr_index->marknum = p_j2k->cstr_index->marknum;
+ l_cstr_index->marker = (opj_marker_info_t*)opj_malloc(l_cstr_index->marknum*sizeof(opj_marker_info_t));
+ if (!l_cstr_index->marker){
+ opj_free( l_cstr_index);
+ return NULL;
+ }
+
+ if (p_j2k->cstr_index->marker)
+ memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, l_cstr_index->marknum * sizeof(opj_marker_info_t) );
+ else{
+ opj_free(l_cstr_index->marker);
+ l_cstr_index->marker = NULL;
+ }
+
+ l_cstr_index->nb_of_tiles = p_j2k->cstr_index->nb_of_tiles;
+ l_cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(l_cstr_index->nb_of_tiles, sizeof(opj_tile_index_t) );
+ if (!l_cstr_index->tile_index){
+ opj_free( l_cstr_index->marker);
+ opj_free( l_cstr_index);
+ return NULL;
+ }
+
+ if (!p_j2k->cstr_index->tile_index){
+ opj_free(l_cstr_index->tile_index);
+ l_cstr_index->tile_index = NULL;
+ }
+ else {
+ OPJ_UINT32 it_tile = 0;
+ for (it_tile = 0; it_tile < l_cstr_index->nb_of_tiles; it_tile++ ){
+
+ /* Tile Marker*/
+ l_cstr_index->tile_index[it_tile].marknum = p_j2k->cstr_index->tile_index[it_tile].marknum;
+
+ l_cstr_index->tile_index[it_tile].marker =
+ (opj_marker_info_t*)opj_malloc(l_cstr_index->tile_index[it_tile].marknum*sizeof(opj_marker_info_t));
+
+ if (!l_cstr_index->tile_index[it_tile].marker) {
+ OPJ_UINT32 it_tile_free;
+
+ for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){
+ opj_free(l_cstr_index->tile_index[it_tile_free].marker);
+ }
+
+ opj_free( l_cstr_index->tile_index);
+ opj_free( l_cstr_index->marker);
+ opj_free( l_cstr_index);
+ return NULL;
+ }
+
+ if (p_j2k->cstr_index->tile_index[it_tile].marker)
+ memcpy( l_cstr_index->tile_index[it_tile].marker,
+ p_j2k->cstr_index->tile_index[it_tile].marker,
+ l_cstr_index->tile_index[it_tile].marknum * sizeof(opj_marker_info_t) );
+ else{
+ opj_free(l_cstr_index->tile_index[it_tile].marker);
+ l_cstr_index->tile_index[it_tile].marker = NULL;
+ }
+
+ /* Tile part index*/
+ l_cstr_index->tile_index[it_tile].nb_tps = p_j2k->cstr_index->tile_index[it_tile].nb_tps;
+
+ l_cstr_index->tile_index[it_tile].tp_index =
+ (opj_tp_index_t*)opj_malloc(l_cstr_index->tile_index[it_tile].nb_tps*sizeof(opj_tp_index_t));
+
+ if(!l_cstr_index->tile_index[it_tile].tp_index){
+ OPJ_UINT32 it_tile_free;
+
+ for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){
+ opj_free(l_cstr_index->tile_index[it_tile_free].marker);
+ opj_free(l_cstr_index->tile_index[it_tile_free].tp_index);
+ }
+
+ opj_free( l_cstr_index->tile_index);
+ opj_free( l_cstr_index->marker);
+ opj_free( l_cstr_index);
+ return NULL;
+ }
+
+ if (p_j2k->cstr_index->tile_index[it_tile].tp_index){
+ memcpy( l_cstr_index->tile_index[it_tile].tp_index,
+ p_j2k->cstr_index->tile_index[it_tile].tp_index,
+ l_cstr_index->tile_index[it_tile].nb_tps * sizeof(opj_tp_index_t) );
+ }
+ else{
+ opj_free(l_cstr_index->tile_index[it_tile].tp_index);
+ l_cstr_index->tile_index[it_tile].tp_index = NULL;
+ }
+
+ /* Packet index (NOT USED)*/
+ l_cstr_index->tile_index[it_tile].nb_packet = 0;
+ l_cstr_index->tile_index[it_tile].packet_index = NULL;
+
+ }
+ }
+
+ return l_cstr_index;
+}
+
+opj_bool opj_j2k_allocate_tile_element_cstr_index(opj_j2k_v2_t *p_j2k)
+{
+ OPJ_UINT32 it_tile=0;
+
+ p_j2k->cstr_index->nb_of_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th;
+ p_j2k->cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(p_j2k->cstr_index->nb_of_tiles, sizeof(opj_tile_index_t));
+ if (!p_j2k->cstr_index->tile_index)
+ return OPJ_FALSE;
+
+ for (it_tile=0; it_tile < p_j2k->cstr_index->nb_of_tiles; it_tile++){
+ p_j2k->cstr_index->tile_index[it_tile].maxmarknum = 100;
+ p_j2k->cstr_index->tile_index[it_tile].marknum = 0;
+ p_j2k->cstr_index->tile_index[it_tile].marker = (opj_marker_info_t*)
+ opj_calloc(p_j2k->cstr_index->tile_index[it_tile].maxmarknum, sizeof(opj_marker_info_t));
+ if (!p_j2k->cstr_index->tile_index[it_tile].marker)
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_decode_tiles ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+{
+ opj_bool l_go_on = OPJ_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_BYTE*)opj_malloc(1000);
+ if (! l_current_data) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to decode tiles\n");
+ return OPJ_FALSE;
+ }
+ l_max_data_size = 1000;
+
+ while (OPJ_TRUE) {
+ if (! opj_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)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+
+ if (! l_go_on) {
+ break;
+ }
+
+ if (l_data_size > l_max_data_size) {
+ OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_data_size);
+ if (! l_new_current_data) {
+ opj_free(l_current_data);
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
+ return OPJ_FALSE;
+ }
+ l_current_data = l_new_current_data;
+ l_max_data_size = l_data_size;
+ }
+
+ if (! opj_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 OPJ_FALSE;
+ }
+ opj_event_msg_v2(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
+
+ if (! opj_j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ opj_event_msg_v2(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1);
+
+ }
+
+ opj_free(l_current_data);
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Sets up the procedures to do on decoding data. Developpers wanting to extend the library can add their own reading procedures.
+ */
+static void opj_j2k_setup_decoding (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions*/
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_tiles);
+ /* DEVELOPER CORNER, add your custom procedures */
+
+}
+
+/*
+ * Read and decode one tile.
+ */
+static opj_bool opj_j2k_decode_one_tile ( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+{
+ opj_bool l_go_on = OPJ_TRUE;
+ OPJ_UINT32 l_current_tile_no;
+ OPJ_UINT32 l_tile_no_to_dec;
+ 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_BYTE*)opj_malloc(1000);
+ if (! l_current_data) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to decode one tile\n");
+ return OPJ_FALSE;
+ }
+ l_max_data_size = 1000;
+
+ /*Allocate and initialize some elements of codestrem index if not already done*/
+ if( !p_j2k->cstr_index->tile_index)
+ {
+ if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)){
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ }
+ /* Move into the codestream to the first SOT used to decode the desired tile */
+ l_tile_no_to_dec = p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec;
+ if (p_j2k->cstr_index->tile_index)
+ if(p_j2k->cstr_index->tile_index->tp_index)
+ {
+ if ( ! p_j2k->cstr_index->tile_index[l_tile_no_to_dec].nb_tps) {
+ /* the index for this tile has not been built,
+ * so move to the last SOT read */
+ if ( !(opj_stream_read_seek(p_stream, p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos+2, p_manager)) ){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
+ return OPJ_FALSE;
+ }
+ }
+ else{
+ if ( !(opj_stream_read_seek(p_stream, p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos+2, p_manager)) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
+ return OPJ_FALSE;
+ }
+ }
+ /* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */
+ if(p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC)
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
+ }
+
+ while (OPJ_TRUE) {
+ if (! opj_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)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+
+ if (! l_go_on) {
+ break;
+ }
+
+ if (l_data_size > l_max_data_size) {
+ OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_data_size);
+ if (! l_new_current_data) {
+ opj_free(l_current_data);
+ l_current_data = NULL;
+ /* TODO: LH: why tile numbering policy used in messages differs from
+ the one used in opj_j2k_decode_tiles() ? */
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to decode tile %d/%d\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
+ return OPJ_FALSE;
+ }
+ l_current_data = l_new_current_data;
+ l_max_data_size = l_data_size;
+ }
+
+ if (! opj_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 OPJ_FALSE;
+ }
+ opj_event_msg_v2(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
+
+ if (! opj_j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ opj_event_msg_v2(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no);
+
+ if(l_current_tile_no == l_tile_no_to_dec)
+ {
+ /* move into the codestream to the the first SOT (FIXME or not move?)*/
+ if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
+ return OPJ_FALSE;
+ }
+ break;
+ }
+ else {
+ opj_event_msg_v2(p_manager, EVT_WARNING, "Tile read, decode and updated is not the desired (%d vs %d).\n", l_current_tile_no, l_tile_no_to_dec);
+ }
+
+ }
+
+ opj_free(l_current_data);
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Sets up the procedures to do on decoding one tile. Developpers wanting to extend the library can add their own reading procedures.
+ */
+static void opj_j2k_setup_decoding_tile (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions*/
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_decode_one_tile);
+ /* DEVELOPER CORNER, add your custom procedures */
+
+}
+
+opj_bool opj_j2k_decode(opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t * p_stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 compno;
+
+ if (!p_image)
+ return OPJ_FALSE;
+
+ p_j2k->m_output_image = opj_image_create0();
+ if (! (p_j2k->m_output_image)) {
+ return OPJ_FALSE;
+ }
+ opj_copy_image_header(p_image, p_j2k->m_output_image);
+
+ /* customization of the decoding */
+ opj_j2k_setup_decoding(p_j2k);
+
+ /* Decode the codestream */
+ if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ /* Move data and copy one information from codec to output image*/
+ for (compno = 0; compno < p_image->numcomps; compno++) {
+ p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded;
+ p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
+ p_j2k->m_output_image->comps[compno].data = NULL;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_get_tile( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index )
+{
+ OPJ_UINT32 compno;
+ OPJ_UINT32 l_tile_x, l_tile_y;
+ opj_image_comp_t* l_img_comp;
+
+ if (!p_image) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "We need an image previously created.\n");
+ return OPJ_FALSE;
+ }
+
+ if ( /*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) ){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1);
+ return OPJ_FALSE;
+ }
+
+ /* Compute the dimension of the desired tile*/
+ l_tile_x = tile_index % p_j2k->m_cp.tw;
+ l_tile_y = tile_index / p_j2k->m_cp.tw;
+
+ p_image->x0 = l_tile_x * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0;
+ if (p_image->x0 < p_j2k->m_private_image->x0)
+ p_image->x0 = p_j2k->m_private_image->x0;
+ p_image->x1 = (l_tile_x + 1) * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0;
+ if (p_image->x1 > p_j2k->m_private_image->x1)
+ p_image->x1 = p_j2k->m_private_image->x1;
+
+ p_image->y0 = l_tile_y * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0;
+ if (p_image->y0 < p_j2k->m_private_image->y0)
+ p_image->y0 = p_j2k->m_private_image->y0;
+ p_image->y1 = (l_tile_y + 1) * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0;
+ if (p_image->y1 > p_j2k->m_private_image->y1)
+ p_image->y1 = p_j2k->m_private_image->y1;
+
+ l_img_comp = p_image->comps;
+ for (compno=0; compno < p_image->numcomps; ++compno)
+ {
+ OPJ_INT32 l_comp_x1, l_comp_y1;
+
+ l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor;
+
+ l_img_comp->x0 = int_ceildiv(p_image->x0, l_img_comp->dx);
+ l_img_comp->y0 = int_ceildiv(p_image->y0, l_img_comp->dy);
+ l_comp_x1 = int_ceildiv(p_image->x1, l_img_comp->dx);
+ l_comp_y1 = int_ceildiv(p_image->y1, l_img_comp->dy);
+
+ l_img_comp->w = int_ceildivpow2(l_comp_x1, l_img_comp->factor) - int_ceildivpow2(l_img_comp->x0, l_img_comp->factor);
+ l_img_comp->h = int_ceildivpow2(l_comp_y1, l_img_comp->factor) - int_ceildivpow2(l_img_comp->y0, l_img_comp->factor);
+
+ l_img_comp++;
+ }
+
+ /* Destroy the previous output image*/
+ if (p_j2k->m_output_image)
+ opj_image_destroy(p_j2k->m_output_image);
+
+ /* Create the ouput image from the information previously computed*/
+ p_j2k->m_output_image = opj_image_create0();
+ if (! (p_j2k->m_output_image)) {
+ return OPJ_FALSE;
+ }
+ opj_copy_image_header(p_image, p_j2k->m_output_image);
+
+ p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = tile_index;
+
+ /* customization of the decoding */
+ opj_j2k_setup_decoding_tile(p_j2k);
+
+ /* Decode the codestream */
+ if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ /* Move data and copy one information from codec to output image*/
+ for (compno = 0; compno < p_image->numcomps; compno++) {
+ p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded;
+
+ if (p_image->comps[compno].data)
+ opj_free(p_image->comps[compno].data);
+
+ p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
+
+ p_j2k->m_output_image->comps[compno].data = NULL;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_set_decoded_resolution_factor(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 it_comp;
+
+ p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor;
+
+ if (p_j2k->m_private_image) {
+ if (p_j2k->m_private_image->comps) {
+ if (p_j2k->m_specific_param.m_decoder.m_default_tcp) {
+ if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps) {
+ for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) {
+ OPJ_UINT32 max_res = p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[it_comp].numresolutions;
+ if ( res_factor >= max_res){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Resolution factor is greater than the maximum resolution in the component.\n");
+ return OPJ_FALSE;
+ }
+ p_j2k->m_private_image->comps[it_comp].factor = res_factor;
+ }
+ return OPJ_TRUE;
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool opj_j2k_encode_v2( opj_j2k_v2_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_BYTE*)opj_malloc(1000);
+ if (! l_current_data) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to encode all tiles\n");
+ return OPJ_FALSE;
+ }
+ l_max_tile_size = 1000;
+
+ l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+ for (i=0;i<l_nb_tiles;++i) {
+ if (! opj_j2k_pre_write_tile(p_j2k,i,p_stream,p_manager)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+
+ l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd);
+ if (l_current_tile_size > l_max_tile_size) {
+ OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, l_current_tile_size);
+ if (! l_new_current_data) {
+ opj_free(l_current_data);
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to encode all tiles\n");
+ return OPJ_FALSE;
+ }
+ l_current_data = l_new_current_data;
+ l_max_tile_size = l_current_tile_size;
+ }
+
+ opj_j2k_get_tile_data(p_j2k->m_tcd,l_current_data);
+
+ if (! opj_j2k_post_write_tile (p_j2k,l_current_data,l_current_tile_size,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ opj_free(l_current_data);
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_end_compress( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+{
+ /* customization of the encoding */
+ opj_j2k_setup_end_compress(p_j2k);
+
+ if (! opj_j2k_exec (p_j2k, p_j2k->m_procedure_list, p_stream, p_manager))
+ {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_start_compress(opj_j2k_v2_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_private_image = opj_image_create0();
+ opj_copy_image_header(p_image, p_j2k->m_private_image);
+
+ /* TODO_MSD: Find a better way */
+ if (p_image->comps) {
+ OPJ_UINT32 it_comp;
+ for (it_comp = 0 ; it_comp < p_image->numcomps; it_comp++) {
+ if (p_image->comps[it_comp].data) {
+ p_j2k->m_private_image->comps[it_comp].data =p_image->comps[it_comp].data;
+ p_image->comps[it_comp].data = NULL;
+
+ }
+ }
+ }
+
+ /* customization of the validation */
+ opj_j2k_setup_encoding_validation (p_j2k);
+
+ /* validation of the parameters codec */
+ if (! opj_j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ /* customization of the encoding */
+ opj_j2k_setup_header_writting(p_j2k);
+
+ /* write header */
+ if (! opj_j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_pre_write_tile ( opj_j2k_v2_t * p_j2k,
+ OPJ_UINT32 p_tile_index,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager )
+{
+ (void)p_stream;
+ if (p_tile_index != p_j2k->m_current_tile_number) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "The given tile index does not match." );
+ return OPJ_FALSE;
+ }
+
+ opj_event_msg_v2(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 (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_get_tile_data (opj_tcd_v2_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_v2_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;i<p_tcd->image->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;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr) = (OPJ_CHAR) (*l_src_ptr);
+ ++l_dest_ptr;
+ ++l_src_ptr;
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+ else {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr) = (*l_src_ptr)&0xff;
+ ++l_dest_ptr;
+ ++l_src_ptr;
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+
+ p_data = (OPJ_BYTE*) l_dest_ptr;
+ }
+ break;
+ case 2:
+ {
+ OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_data;
+ if (l_img_comp->sgnd) {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (OPJ_INT16) (*(l_src_ptr++));
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+ else {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff;
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+
+ p_data = (OPJ_BYTE*) l_dest_ptr;
+ }
+ break;
+ case 4:
+ {
+ OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_data;
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = *(l_src_ptr++);
+ }
+ l_src_ptr += l_stride;
+ }
+
+ p_data = (OPJ_BYTE*) l_dest_ptr;
+ }
+ break;
+ }
+
+ ++l_img_comp;
+ ++l_tilec;
+ }
+}
+
+opj_bool opj_j2k_post_write_tile ( opj_j2k_v2_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_v2_t * l_tcd = 00;
+ opj_cp_v2_t * l_cp = 00;
+ opj_tcp_v2_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;
+
+ /* preconditions */
+ 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 (! opj_tcd_copy_tile_data(l_tcd,p_data,p_data_size)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." );
+ return OPJ_FALSE;
+ }
+
+ l_nb_bytes_written = 0;
+ if (! opj_j2k_write_first_tile_part(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+ l_current_data += l_nb_bytes_written;
+ l_available_data -= l_nb_bytes_written;
+
+ l_nb_bytes_written = 0;
+ if (! opj_j2k_write_all_tile_parts(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) {
+ return OPJ_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 OPJ_FALSE;
+ }
+
+ ++p_j2k->m_current_tile_number;
+
+ return OPJ_TRUE;
+}
+
+void opj_j2k_setup_end_compress (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+
+ /* DEVELOPER CORNER, insert your custom procedures */
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_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,(opj_procedure)opj_j2k_write_updated_tlm);
+ }
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_epc );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_end_encoding );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_destroy_header_memory);
+}
+
+void opj_j2k_setup_encoding_validation (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_build_encoder);
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_encoding_validation);
+
+ /* DEVELOPER CORNER, add your custom validation procedure */
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (opj_procedure)opj_j2k_mct_validation);
+}
+
+void opj_j2k_setup_header_writting (opj_j2k_v2_t *p_j2k)
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_init_info );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_soc );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_siz );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_cod );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_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,(opj_procedure)opj_j2k_write_image_components );
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_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,(opj_procedure)opj_j2k_write_poc );
+ }
+ }
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_write_regions);
+
+ if (p_j2k->m_cp.comment != 00) {
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_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,(opj_procedure)opj_j2k_write_mct_data_group );
+ }
+ /* End of Developer Corner */
+
+ if (p_j2k->cstr_index) {
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_get_end_header );
+ }
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_create_tcd);
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)opj_j2k_update_rates);
+}
+
+opj_bool opj_j2k_write_first_tile_part (opj_j2k_v2_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_v2_t *l_tcp = 00;
+ opj_tcd_v2_t * l_tcd = 00;
+ opj_cp_v2_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 (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager))
+ {
+ return OPJ_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_private_image->numcomps; compno++) {
+ l_current_nb_bytes_written = 0;
+ opj_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;
+ opj_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;
+ opj_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 (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+ return OPJ_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){
+ opj_j2k_update_tlm(p_j2k,l_nb_bytes_written);
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_all_tile_parts( opj_j2k_v2_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_v2_t *l_tcp = 00;
+ opj_tcd_v2_t * l_tcd = 00;
+ opj_cp_v2_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 = opj_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 (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) {
+ return OPJ_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 (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+ return OPJ_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) {
+ opj_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 = opj_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 (! opj_j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) {
+ return OPJ_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 (! opj_j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+ return OPJ_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) {
+ opj_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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_updated_tlm( opj_j2k_v2_t *p_j2k,
+ struct opj_stream_private *p_stream,
+ struct opj_event_mgr * p_manager )
+{
+ OPJ_UINT32 l_tlm_size;
+ OPJ_OFF_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 OPJ_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 OPJ_FALSE;
+ }
+
+ if (! opj_stream_seek(p_stream,l_current_position,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_end_encoding( opj_j2k_v2_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_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 OPJ_TRUE;
+}
+
+/**
+ * Destroys the memory associated with the decoding of headers.
+ */
+static opj_bool opj_j2k_destroy_header_memory ( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ 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 OPJ_TRUE;
+}
+
+opj_bool opj_j2k_init_info( opj_j2k_v2_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);
+ (void)l_cstr_info;
+
+ /* TODO mergeV2: check this part which use cstr_info */
+ /*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 opj_j2k_calculate_tp(p_j2k,&(p_j2k->m_cp),&p_j2k->m_specific_param.m_encoder.m_total_tile_parts,p_j2k->m_private_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.
+*/
+static opj_bool opj_j2k_create_tcd( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+ assert(p_stream != 00);
+
+ p_j2k->m_tcd = opj_tcd_create(OPJ_FALSE);
+
+ if (! p_j2k->m_tcd) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n");
+ return OPJ_FALSE;
+ }
+
+ if (!opj_tcd_init(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp)) {
+ opj_tcd_destroy(p_j2k->m_tcd);
+ p_j2k->m_tcd = 00;
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_j2k_write_tile (opj_j2k_v2_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 (! opj_j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error while opj_j2k_pre_write_tile with tile index = %d\n", p_tile_index);
+ return OPJ_FALSE;
+ }
+ else {
+ if (! opj_j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error while opj_j2k_post_write_tile with tile index = %d\n", p_tile_index);
+ return OPJ_FALSE;
+ }
+ }
+
+ return OPJ_TRUE;
+}
diff --git a/src/lib/openjp2/j2k.h b/src/lib/openjp2/j2k.h
new file mode 100644
index 00000000..2782a096
--- /dev/null
+++ b/src/lib/openjp2/j2k.h
@@ -0,0 +1,1043 @@
+/*
+ * 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 <jerome.fimes@c-s.fr>
+ * Copyright (c) 2011, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
+ *
+ * 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.
+*/
+
+/** @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 /**< Selective arithmetic coding bypass */
+#define J2K_CCP_CBLKSTY_RESET 0x02 /**< Reset context probabilities on coding pass boundaries */
+#define J2K_CCP_CBLKSTY_TERMALL 0x04 /**< Termination on each coding pass */
+#define J2K_CCP_CBLKSTY_VSC 0x08 /**< Vertically stripe causal context */
+#define J2K_CCP_CBLKSTY_PTERM 0x10 /**< Predictable termination */
+#define J2K_CCP_CBLKSTY_SEGSYM 0x20 /**< Segmentation symbols are used */
+#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 */
+
+#define J2K_MS_UNK 0 /**< UNKNOWN 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 */
+/* <<UniPG */
+
+/* ----------------------------------------------------------------------- */
+
+/**
+ * Values that specify the status of the decoding process when decoding the main header.
+ * These values may be combined with a | operator.
+ * */
+typedef enum J2K_STATUS {
+ J2K_STATE_NONE = 0x0000, /**< a SOC marker is expected */
+ J2K_STATE_MHSOC = 0x0001, /**< a SOC marker is expected */
+ J2K_STATE_MHSIZ = 0x0002, /**< a SIZ marker is expected */
+ J2K_STATE_MH = 0x0004, /**< the decoding process is in the main header */
+ J2K_STATE_TPHSOT = 0x0008, /**< the decoding process is in a tile part header and expects a SOT marker */
+ J2K_STATE_TPH = 0x0010, /**< the decoding process is in a tile part header */
+ J2K_STATE_MT = 0x0020, /**< the EOC marker has just been read */
+ J2K_STATE_NEOC = 0x0040, /**< the decoding process must not expect a EOC marker because the codestream is truncated */
+
+ J2K_STATE_EOC = 0x0100, /**< the decoding process has encountered the EOC marker */
+ J2K_STATE_ERR = 0x8000 /**< the decoding process has encountered an error (FIXME warning V1 = 0x0080)*/
+} J2K_STATUS;
+
+/**
+ * Type of elements storing in the MCT data
+ */
+typedef enum MCT_ELEMENT_TYPE
+{
+ MCT_TYPE_INT16 = 0, /** MCT data is stored as signed shorts*/
+ MCT_TYPE_INT32 = 1, /** MCT data is stored as signed integers*/
+ MCT_TYPE_FLOAT = 2, /** MCT data is stored as floats*/
+ MCT_TYPE_DOUBLE = 3 /** MCT data is stored as doubles*/
+} J2K_MCT_ELEMENT_TYPE;
+
+/**
+ * Type of MCT array
+ */
+typedef enum MCT_ARRAY_TYPE
+{
+ MCT_TYPE_DEPENDENCY = 0,
+ MCT_TYPE_DECORRELATION = 1,
+ MCT_TYPE_OFFSET = 2
+} J2K_MCT_ARRAY_TYPE;
+
+/* ----------------------------------------------------------------------- */
+
+/**
+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;
+
+/**
+ * Quantization stepsize
+ */
+typedef struct opj_stepsize {
+ /** exponent */
+ int expn;
+ /** mantissa */
+ int mant;
+} opj_stepsize_t;
+
+/**
+Tile-component coding parameters
+*/
+typedef struct opj_tccp
+{
+ /** coding style */
+ OPJ_UINT32 csty;
+ /** number of resolutions */
+ OPJ_UINT32 numresolutions;
+ /** code-blocks width */
+ OPJ_UINT32 cblkw;
+ /** code-blocks height */
+ OPJ_UINT32 cblkh;
+ /** code-block coding style */
+ OPJ_UINT32 cblksty;
+ /** discrete wavelet transform identifier */
+ OPJ_UINT32 qmfbid;
+ /** quantisation style */
+ OPJ_UINT32 qntsty;
+ /** stepsizes used for quantization */
+ opj_stepsize_t stepsizes[J2K_MAXBANDS];
+ /** number of guard bits */
+ OPJ_UINT32 numgbits;
+ /** Region Of Interest shift */
+ OPJ_INT32 roishift;
+ /** precinct width */
+ OPJ_UINT32 prcw[J2K_MAXRLVLS];
+ /** precinct height */
+ OPJ_UINT32 prch[J2K_MAXRLVLS];
+ /** the dc_level_shift **/
+ OPJ_INT32 m_dc_level_shift;
+}
+opj_tccp_t;
+
+
+/** V1 STYLE
+Tile coding parameters :
+this structure is used to store coding/decoding parameters common to all
+tiles (information like COD, COC in main header)
+*/
+typedef struct opj_tcp {
+ /** 1 : first part-tile of a tile */
+ int first;
+ /** coding style */
+ int csty;
+ /** progression order */
+ OPJ_PROG_ORDER prg;
+ /** number of layers */
+ int numlayers;
+ /** multi-component transform identifier */
+ int mct;
+ /** rates of layers */
+ float rates[100];
+ /** number of progression order changes */
+ int numpocs;
+ /** indicates if a POC marker has been used O:NO, 1:YES */
+ int POC;
+ /** progression order changes */
+ opj_poc_t pocs[32];
+ /** packet header store there for futur use in t2_decode_packet */
+ unsigned char *ppt_data;
+ /** pointer remaining on the first byte of the first header if ppt is used */
+ unsigned char *ppt_data_first;
+ /** If ppt == 1 --> there was a PPT marker for the present tile */
+ int ppt;
+ /** used in case of multiple marker PPT (number of info already stored) */
+ int ppt_store;
+ /** ppmbug1 */
+ int ppt_len;
+ /** add fixed_quality */
+ float distoratio[100];
+ /** tile-component coding parameters */
+ opj_tccp_t *tccps;
+} opj_tcp_t;
+
+/**
+ * FIXME DOC
+ */
+typedef struct opj_mct_data
+{
+ J2K_MCT_ELEMENT_TYPE m_element_type;
+ J2K_MCT_ARRAY_TYPE m_array_type;
+ OPJ_UINT32 m_index;
+ OPJ_BYTE * m_data;
+ OPJ_UINT32 m_data_size;
+}
+opj_mct_data_t;
+
+/**
+ * FIXME DOC
+ */
+typedef struct opj_simple_mcc_decorrelation_data
+{
+ OPJ_UINT32 m_index;
+ OPJ_UINT32 m_nb_comps;
+ opj_mct_data_t * m_decorrelation_array;
+ opj_mct_data_t * m_offset_array;
+ OPJ_UINT32 m_is_irreversible : 1;
+}
+opj_simple_mcc_decorrelation_data_t;
+
+/**
+Tile coding parameters :
+this structure is used to store coding/decoding parameters common to all
+tiles (information like COD, COC in main header)
+*/
+typedef struct opj_tcp_v2
+{
+ /** coding style */
+ OPJ_UINT32 csty;
+ /** progression order */
+ OPJ_PROG_ORDER prg;
+ /** number of layers */
+ OPJ_UINT32 numlayers;
+ OPJ_UINT32 num_layers_to_decode;
+ /** multi-component transform identifier */
+ OPJ_UINT32 mct;
+ /** rates of layers */
+ OPJ_FLOAT32 rates[100];
+ /** number of progression order changes */
+ OPJ_UINT32 numpocs;
+ /** progression order changes */
+ opj_poc_t pocs[32];
+ /** packet header store there for futur use in t2_decode_packet */
+ OPJ_BYTE *ppt_data;
+ /** used to keep a track of the allocated memory */
+ OPJ_BYTE *ppt_buffer;
+ /** Number of bytes stored inside ppt_data*/
+ OPJ_UINT32 ppt_data_size;
+ /** size of ppt_data*/
+ OPJ_UINT32 ppt_len;
+ /** add fixed_quality */
+ OPJ_FLOAT32 distoratio[100];
+ /** tile-component coding parameters */
+ opj_tccp_t *tccps;
+ /** number of tile parts for the tile. */
+ OPJ_UINT32 m_nb_tile_parts;
+ /** data for the tile */
+ OPJ_BYTE * m_data;
+ /** size of data */
+ OPJ_UINT32 m_data_size;
+ /** encoding norms */
+ OPJ_FLOAT64 * mct_norms;
+ /** the mct decoding matrix */
+ OPJ_FLOAT32 * m_mct_decoding_matrix;
+ /** the mct coding matrix */
+ OPJ_FLOAT32 * m_mct_coding_matrix;
+ /** mct records */
+ opj_mct_data_t * m_mct_records;
+ /** the number of mct records. */
+ OPJ_UINT32 m_nb_mct_records;
+ /** the max number of mct records. */
+ OPJ_UINT32 m_nb_max_mct_records;
+ /** mcc records */
+ opj_simple_mcc_decorrelation_data_t * m_mcc_records;
+ /** the number of mct records. */
+ OPJ_UINT32 m_nb_mcc_records;
+ /** the max number of mct records. */
+ OPJ_UINT32 m_nb_max_mcc_records;
+
+
+ /***** FLAGS *******/
+ /** If ppt == 1 --> 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_v2_t;
+
+
+
+
+
+/** V1 STYLE
+Coding parameters
+*/
+typedef struct opj_cp {
+ /** Digital cinema profile*/
+ OPJ_CINEMA_MODE cinema;
+ /** Maximum rate for each component. If == 0, component size limitation is not considered */
+ int max_comp_size;
+ /** Size of the image in bits*/
+ int img_size;
+ /** Rsiz*/
+ OPJ_RSIZ_CAPABILITIES rsiz;
+ /** Enabling Tile part generation*/
+ char tp_on;
+ /** Flag determining tile part generation*/
+ char tp_flag;
+ /** Position of tile part flag in progression order*/
+ int tp_pos;
+ /** allocation by rate/distortion */
+ int disto_alloc;
+ /** allocation by fixed layer */
+ int fixed_alloc;
+ /** add fixed_quality */
+ int fixed_quality;
+ /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */
+ int reduce;
+ /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */
+ int layer;
+ /** if == NO_LIMITATION, decode entire codestream; if == LIMIT_TO_MAIN_HEADER then only decode the main header */
+ OPJ_LIMIT_DECODING limit_decoding;
+ /** XTOsiz */
+ int tx0;
+ /** YTOsiz */
+ int ty0;
+ /** XTsiz */
+ int tdx;
+ /** YTsiz */
+ int tdy;
+ /** comment for coding */
+ char *comment;
+ /** number of tiles in width */
+ int tw;
+ /** number of tiles in heigth */
+ int th;
+ /** ID number of the tiles present in the codestream */
+ int *tileno;
+ /** size of the vector tileno */
+ int tileno_size;
+ /** packet header store there for futur use in t2_decode_packet */
+ unsigned char *ppm_data;
+ /** pointer remaining on the first byte of the first header if ppm is used */
+ unsigned char *ppm_data_first;
+ /** if ppm == 1 --> there was a PPM marker for the present tile */
+ int ppm;
+ /** use in case of multiple marker PPM (number of info already store) */
+ int ppm_store;
+ /** use in case of multiple marker PPM (case on non-finished previous info) */
+ int ppm_previous;
+ /** ppmbug1 */
+ int ppm_len;
+ /** tile coding parameters */
+ opj_tcp_t *tcps;
+ /** fixed layer */
+ int *matrice;
+/* UniPG>> */
+#ifdef USE_JPWL
+ /** enables writing of EPC in MH, thus activating JPWL */
+ opj_bool epc_on;
+ /** enables writing of EPB, in case of activated JPWL */
+ opj_bool epb_on;
+ /** enables writing of ESD, in case of activated JPWL */
+ opj_bool esd_on;
+ /** enables writing of informative techniques of ESD, in case of activated JPWL */
+ opj_bool info_on;
+ /** enables writing of RED, in case of activated JPWL */
+ opj_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 */
+ opj_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 */
+/* <<UniPG */
+} opj_cp_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_v2
+{
+ /** Size of the image in bits*/
+ /*int img_size;*/
+ /** Rsiz*/
+ OPJ_RSIZ_CAPABILITIES rsiz;
+ /** XTOsiz */
+ OPJ_UINT32 tx0; /* MSD see norm */
+ /** YTOsiz */
+ OPJ_UINT32 ty0; /* MSD see norm */
+ /** 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 store there for futur use in t2_decode_packet */
+ OPJ_BYTE *ppm_data;
+ /** size of the ppm_data*/
+ OPJ_UINT32 ppm_len;
+ /** size of the ppm_data*/
+ OPJ_UINT32 ppm_data_read;
+
+ OPJ_BYTE *ppm_data_current;
+
+ /** packet header storage original buffer */
+ OPJ_BYTE *ppm_buffer;
+ /** pointer remaining on the first byte of the first header if ppm is used */
+ OPJ_BYTE *ppm_data_first;
+ /** Number of bytes actually stored inside the ppm_data */
+ OPJ_UINT32 ppm_data_size;
+ /** use in case of multiple marker PPM (number of info already store) */
+ OPJ_INT32 ppm_store;
+ /** use in case of multiple marker PPM (case on non-finished previous info) */
+ OPJ_INT32 ppm_previous;
+
+ /** tile coding parameters */
+ opj_tcp_v2_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 */
+ opj_bool epc_on;
+ /** enables writing of EPB, in case of activated JPWL */
+ opj_bool epb_on;
+ /** enables writing of ESD, in case of activated JPWL */
+ opj_bool esd_on;
+ /** enables writing of informative techniques of ESD, in case of activated JPWL */
+ opj_bool info_on;
+ /** enables writing of RED, in case of activated JPWL */
+ opj_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 */
+ opj_bool correct;
+ /** expected number of components at the decoder */
+ int exp_comps;
+ /** maximum number of tiles at the decoder */
+ OPJ_UINT32 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;
+/* <<UniPG */
+} opj_cp_v2_t;
+
+
+typedef struct opj_j2k_dec
+{
+ /** locate in which part of the codestream the decoder is (main header, tile header, end) */
+ OPJ_UINT32 m_state;
+ /**
+ * store decoding parameters common to all tiles (information like COD, COC in main header)
+ */
+ opj_tcp_v2_t *m_default_tcp;
+ OPJ_BYTE *m_header_data;
+ OPJ_UINT32 m_header_data_size;
+ /** to tell the tile part length */
+ OPJ_UINT32 m_sot_length;
+ /** Only tiles index in the correct range will be decoded.*/
+ OPJ_UINT32 m_start_tile_x;
+ OPJ_UINT32 m_start_tile_y;
+ OPJ_UINT32 m_end_tile_x;
+ OPJ_UINT32 m_end_tile_y;
+ /**
+ * Decoded area set by the user
+ */
+ OPJ_UINT32 m_DA_x0;
+ OPJ_UINT32 m_DA_y0;
+ OPJ_UINT32 m_DA_x1;
+ OPJ_UINT32 m_DA_y1;
+
+ /** Index of the tile to decode (used in get_tile) */
+ OPJ_INT32 m_tile_ind_to_dec;
+ /** Position of the last SOT marker read */
+ OPJ_OFF_T m_last_sot_read_pos;
+
+ /**
+ * Indicate that the current tile-part is assume as the last tile part of the codestream.
+ * It is useful in the case of PSot is equal to zero. The sot length will be compute in the
+ * SOD reader function. FIXME NOT USED for the moment
+ */
+ opj_bool m_last_tile_part;
+ /** to tell that a tile can be decoded. */
+ OPJ_UINT32 m_can_decode : 1;
+ OPJ_UINT32 m_discard_tiles : 1;
+ OPJ_UINT32 m_skip_data : 1;
+
+} opj_j2k_dec_t;
+
+typedef struct opj_j2k_enc
+{
+ /** Tile part number, regardless of poc, for each new poc, tp is reset to 1*/
+ OPJ_UINT32 m_current_poc_tile_part_number; /* tp_num */
+
+ /** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/
+ OPJ_UINT32 m_current_tile_part_number; /*cur_tp_num */
+
+ /**
+ locate the start position of the TLM marker
+ after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
+ */
+ OPJ_OFF_T m_tlm_start;
+ /**
+ * Stores the sizes of the tlm.
+ */
+ OPJ_BYTE * m_tlm_sot_offsets_buffer;
+ /**
+ * The current offset of the tlm buffer.
+ */
+ OPJ_BYTE * m_tlm_sot_offsets_current;
+
+ /** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/
+ /** used in TLMmarker*/
+ OPJ_UINT32 m_total_tile_parts; /* totnum_tp */
+
+ /* encoded data for a tile */
+ OPJ_BYTE * m_encoded_tile_data;
+
+ /* size of the encoded_data */
+ OPJ_UINT32 m_encoded_tile_size;
+
+ /* encoded data for a tile */
+ OPJ_BYTE * m_header_tile_data;
+
+ /* size of the encoded_data */
+ OPJ_UINT32 m_header_tile_data_size;
+
+
+} opj_j2k_enc_t;
+
+/**
+JPEG-2000 codestream reader/writer
+*/
+typedef struct opj_j2k {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** locate in which part of the codestream the decoder is (main header, tile header, end) */
+ int state;
+ /** number of the tile curently concern by coding/decoding */
+ int curtileno;
+ /** Tile part number*/
+ int tp_num;
+ /** Tilepart number currently coding*/
+ int cur_tp_num;
+ /** Total number of tileparts of the current tile*/
+ int *cur_totnum_tp;
+ /**
+ locate the start position of the TLM marker
+ after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
+ */
+ int tlm_start;
+ /** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/
+ /** used in TLMmarker*/
+ int totnum_tp;
+ /**
+ locate the position of the end of the tile in the codestream,
+ used to detect a truncated codestream (in j2k_read_sod)
+ */
+ unsigned char *eot;
+ /**
+ locate the start position of the SOT marker of the current coded tile:
+ after encoding the tile, a jump (in j2k_write_sod) is done to the SOT marker to store the value of its length.
+ */
+ int sot_start;
+ int sod_start;
+ /**
+ as the J2K-file is written in several parts during encoding,
+ it enables to make the right correction in position return by cio_tell
+ */
+ int pos_correction;
+ /** array used to store the data of each tile */
+ unsigned char **tile_data;
+ /** array used to store the length of each tile */
+ int *tile_len;
+ /**
+ decompression only :
+ store decoding parameters common to all tiles (information like COD, COC in main header)
+ */
+ opj_tcp_t *default_tcp;
+ /** pointer to the encoded / decoded image */
+ opj_image_t *image;
+ /** pointer to the coding parameters */
+ opj_cp_t *cp;
+ /** helper used to write the index file */
+ opj_codestream_info_t *cstr_info;
+ /** pointer to the byte i/o stream */
+ opj_cio_t *cio;
+} opj_j2k_t;
+
+struct opj_tcd_v2;
+/**
+JPEG-2000 codestream reader/writer
+*/
+typedef struct opj_j2k_v2
+{
+ /* J2K codestream is decoded*/
+ opj_bool m_is_decoder;
+
+ /* FIXME DOC*/
+ union
+ {
+ opj_j2k_dec_t m_decoder;
+ opj_j2k_enc_t m_encoder;
+ }
+ m_specific_param;
+
+ /** pointer to the internal/private encoded / decoded image */
+ opj_image_t* m_private_image;
+
+ /* pointer to the output image (decoded)*/
+ opj_image_t* m_output_image;
+
+ /** Coding parameters */
+ opj_cp_v2_t m_cp;
+
+ /** the list of procedures to exec **/
+ struct opj_procedure_list * m_procedure_list;
+
+ /** the list of validation procedures to follow to make sure the code is valid **/
+ struct opj_procedure_list * m_validation_list;
+
+ /** helper used to write the index file */
+ opj_codestream_index_t *cstr_index;
+
+ /** number of the tile curently concern by coding/decoding */
+ OPJ_UINT32 m_current_tile_number;
+
+ /** the current tile coder/decoder **/
+ struct opj_tcd_v2 * m_tcd;
+
+}
+opj_j2k_v2_t;
+
+
+
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in j2k->cp.
+@param j2k J2K decompressor handle
+@param parameters decompression parameters
+*/
+void opj_j2k_setup_decoder(opj_j2k_v2_t *j2k, opj_dparameters_t *parameters);
+
+/**
+ * Creates a J2K compression structure
+ *
+ * @return Returns a handle to a J2K compressor if successful, returns NULL otherwise
+*/
+opj_j2k_v2_t* opj_j2k_create_compress(void);
+
+
+void opj_j2k_setup_encoder( opj_j2k_v2_t *p_j2k,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager);
+
+/**
+Converts an enum type progression order to string type
+*/
+char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+/**
+ * Ends the decompression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool opj_j2k_end_decompress(opj_j2k_v2_t *j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager);
+
+/**
+ * Reads a jpeg2000 codestream header structure.
+ *
+ * @param p_stream the stream to read data from.
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_image FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+opj_bool opj_j2k_read_header( opj_stream_private_t *p_stream,
+ opj_j2k_v2_t* p_j2k,
+ opj_image_t** p_image,
+ opj_event_mgr_t* p_manager );
+
+
+/**
+ * Destroys a jpeg2000 codec.
+ *
+ * @param p_j2k the jpeg20000 structure to destroy.
+ */
+void opj_j2k_destroy (opj_j2k_v2_t *p_j2k);
+
+/**
+ * Destroys a codestream index structure.
+ *
+ * @param p_cstr_ind the codestream index parameter to destroy.
+ */
+void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind);
+
+/**
+ * Decode tile data.
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_tile_index
+ * @param p_data FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+opj_bool opj_j2k_decode_tile ( opj_j2k_v2_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 );
+
+/**
+ * Reads a tile header.
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_tile_x0 FIXME DOC
+ * @param p_tile_y0 FIXME DOC
+ * @param p_tile_x1 FIXME DOC
+ * @param p_tile_y1 FIXME DOC
+ * @param p_nb_comps FIXME DOC
+ * @param p_go_on FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+opj_bool opj_j2k_read_tile_header ( opj_j2k_v2_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,
+ opj_bool * p_go_on,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * 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_image FIXME DOC
+ * @param p_start_x the left 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_x the right 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.
+ */
+opj_bool opj_j2k_set_decode_area( opj_j2k_v2_t *p_j2k,
+ opj_image_t* p_image,
+ OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
+ OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Creates a J2K decompression structure.
+ *
+ * @return a handle to a J2K decompressor if successful, NULL otherwise.
+ */
+opj_j2k_v2_t* opj_j2k_create_decompress(void);
+
+
+/**
+ * Dump some elements from the J2K decompression structure .
+ *
+ *@param p_j2k the jpeg2000 codec.
+ *@param flag flag to describe what elments are dump.
+ *@param out_stream output stream where dump the elements.
+ *
+*/
+void j2k_dump (opj_j2k_v2_t* p_j2k, OPJ_INT32 flag, FILE* out_stream);
+
+
+
+/**
+ * Dump an image header structure.
+ *
+ *@param image the image header to dump.
+ *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function
+ *@param out_stream output stream where dump the elements.
+ */
+void j2k_dump_image_header(opj_image_t* image, opj_bool dev_dump_flag, FILE* out_stream);
+
+/**
+ * Dump a component image header structure.
+ *
+ *@param comp the component image header to dump.
+ *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function
+ *@param out_stream output stream where dump the elements.
+ */
+void j2k_dump_image_comp_header(opj_image_comp_t* comp, opj_bool dev_dump_flag, FILE* out_stream);
+
+/**
+ * Get the codestream info from a JPEG2000 codec.
+ *
+ *@param p_j2k the component image header to dump.
+ *
+ *@return the codestream information extract from the jpg2000 codec
+ */
+opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_v2_t* p_j2k);
+
+/**
+ * Get the codestream index from a JPEG2000 codec.
+ *
+ *@param p_j2k the component image header to dump.
+ *
+ *@return the codestream index extract from the jpg2000 codec
+ */
+opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_v2_t* p_j2k);
+
+/**
+ * Decode an image from a JPEG-2000 codestream
+ * @param j2k J2K decompressor handle
+ * @param p_stream FIXME DOC
+ * @param p_image FIXME DOC
+ * @param p_manager FIXME DOC
+ * @return FIXME DOC
+*/
+opj_bool opj_j2k_decode(opj_j2k_v2_t *j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t *p_image,
+ opj_event_mgr_t *p_manager);
+
+
+opj_bool opj_j2k_get_tile( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index );
+
+opj_bool opj_j2k_set_decoded_resolution_factor(opj_j2k_v2_t *p_j2k,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager);
+
+
+/**
+ * Writes a tile.
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+opj_bool opj_j2k_write_tile ( opj_j2k_v2_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 );
+
+/**
+ * Encodes an image into a JPEG-2000 codestream
+ */
+opj_bool opj_j2k_encode_v2( opj_j2k_v2_t * p_j2k,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * 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_image FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool opj_j2k_start_compress(opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager);
+
+/**
+ * Ends the compression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool opj_j2k_end_compress( opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+opj_bool opj_j2k_setup_mct_encoding (opj_tcp_v2_t * p_tcp, opj_image_t * p_image);
+
+
+#endif /* __J2K_H */
diff --git a/src/lib/openjp2/j2k_lib.c b/src/lib/openjp2/j2k_lib.c
new file mode 100644
index 00000000..a96df221
--- /dev/null
+++ b/src/lib/openjp2/j2k_lib.c
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/times.h>
+#endif /* _WIN32 */
+#include "opj_includes.h"
+
+OPJ_FLOAT64 opj_clock(void) {
+#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
+}
+
diff --git a/src/lib/openjp2/j2k_lib.h b/src/lib/openjp2/j2k_lib.h
new file mode 100644
index 00000000..73a14c7d
--- /dev/null
+++ b/src/lib/openjp2/j2k_lib.h
@@ -0,0 +1,54 @@
+/*
+ * 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_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.
+*/
+
+/** @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/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c
new file mode 100644
index 00000000..95e6a751
--- /dev/null
+++ b/src/lib/openjp2/jp2.c
@@ -0,0 +1,2324 @@
+/*
+ * 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) 2010-2011, Kaori Hagihara
+ * 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"
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+#define BOX_SIZE 1024
+
+/** @name Local static functions */
+/*@{*/
+
+/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/
+
+/**
+ * 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, false else.
+ */
+static opj_bool opj_jp2_read_ihdr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE *p_image_header_data,
+ OPJ_UINT32 p_image_header_size,
+ opj_event_mgr_t * 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 OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * p_nb_bytes_written );
+
+/**
+ * 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 OPJ_BYTE * opj_jp2_write_bpcc( opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * 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 opj_bool opj_jp2_read_bpcc( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_bpc_header_data,
+ OPJ_UINT32 p_bpc_header_size,
+ opj_event_mgr_t * p_manager );
+
+static opj_bool opj_jp2_read_cdef( opj_jp2_v2_t * jp2,
+ OPJ_BYTE * p_cdef_header_data,
+ OPJ_UINT32 p_cdef_header_size,
+ opj_event_mgr_t * p_manager );
+
+static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color);
+
+/**
+ * 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 OPJ_BYTE * opj_jp2_write_colr( opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * p_nb_bytes_written );
+
+/**
+ * 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 opj_bool opj_jp2_write_ftyp( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * 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 opj_bool opj_jp2_read_ftyp( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager );
+
+opj_bool opj_jp2_skip_jp2c( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * 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.
+*/
+static opj_bool opj_jp2_read_jp2h( opj_jp2_v2_t *jp2,
+ OPJ_BYTE *p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_jp2_write_jp2c( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * 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 opj_bool opj_jp2_read_jp(opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * 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 opj_bool opj_jp2_write_jp( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager );
+
+/**
+Apply collected palette data
+@param color Collector for profile, cdef and pclr data
+@param image
+*/
+static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color);
+
+static void opj_jp2_free_pclr(opj_jp2_color_t *color);
+
+/**
+ * Collect palette data
+ *
+ * @param jp2 JP2 handle
+ * @param p_pclr_header_data FIXME DOC
+ * @param p_pclr_header_size FIXME DOC
+ * @param p_manager
+ *
+ * @return Returns true if successful, returns false otherwise
+*/
+static opj_bool opj_jp2_read_pclr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_pclr_header_data,
+ OPJ_UINT32 p_pclr_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Collect component mapping data
+ *
+ * @param jp2 JP2 handle
+ * @param p_cmap_header_data FIXME DOC
+ * @param p_cmap_header_size FIXME DOC
+ * @param p_manager FIXME DOC
+ *
+ * @return Returns true if successful, returns false otherwise
+*/
+
+static opj_bool opj_jp2_read_cmap( opj_jp2_v2_t * jp2,
+ OPJ_BYTE * p_cmap_header_data,
+ OPJ_UINT32 p_cmap_header_size,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads the Color 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 opj_bool opj_jp2_read_colr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_colr_header_data,
+ OPJ_UINT32 p_colr_header_size,
+ opj_event_mgr_t * 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.
+ */
+static void opj_jp2_setup_end_header_writting (opj_jp2_v2_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 opj_jp2_setup_end_header_reading (opj_jp2_v2_t *jp2);
+
+/**
+ * Reads a jpeg2000 file header structure.
+ *
+ * @param jp2 the jpeg2000 file header structure.
+ * @param stream the stream to read data from.
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+static opj_bool opj_jp2_read_header_procedure( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * 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 stream the stream to execute the procedures on.
+ * @param p_manager the user manager.
+ *
+ * @return true if all the procedures were successfully executed.
+ */
+static opj_bool opj_jp2_exec ( opj_jp2_v2_t * jp2,
+ opj_procedure_list_t * p_procedure_list,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * 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 opj_bool opj_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);
+
+/**
+ * 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 opj_jp2_setup_encoding_validation (opj_jp2_v2_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 opj_jp2_setup_header_writting (opj_jp2_v2_t *jp2);
+
+opj_bool opj_jp2_default_validation ( opj_jp2_v2_t * jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * 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 * opj_jp2_img_find_handler (OPJ_UINT32 p_id);
+
+/**
+ * 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 * opj_jp2_find_handler (OPJ_UINT32 p_id );
+
+const opj_jp2_header_handler_t jp2_header [] =
+{
+ {JP2_JP,opj_jp2_read_jp},
+ {JP2_FTYP,opj_jp2_read_ftyp},
+ {JP2_JP2H,opj_jp2_read_jp2h}
+};
+
+const opj_jp2_header_handler_t jp2_img_header [] =
+{
+ {JP2_IHDR,opj_jp2_read_ihdr},
+ {JP2_COLR,opj_jp2_read_colr},
+ {JP2_BPCC,opj_jp2_read_bpcc},
+ {JP2_PCLR,opj_jp2_read_pclr},
+ {JP2_CMAP,opj_jp2_read_cmap},
+ {JP2_CDEF,opj_jp2_read_cdef}
+
+};
+
+/**
+ * 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 box the box structure to fill.
+ * @param p_data the character string to read data from.
+ * @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.
+ * @param p_manager FIXME DOC
+ *
+ * @return true if the box is reconized, false otherwise
+*/
+static opj_bool opj_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 );
+
+/**
+ * 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 opj_jp2_setup_decoding_validation (opj_jp2_v2_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 opj_jp2_setup_header_reading (opj_jp2_v2_t *jp2);
+
+/* ----------------------------------------------------------------------- */
+
+ opj_bool opj_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 OPJ_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 OPJ_FALSE;
+ }
+
+ opj_read_bytes(l_data_header,&l_xl_part_size, 4);
+ if (l_xl_part_size != 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n");
+ return OPJ_FALSE;
+ }
+ opj_read_bytes(l_data_header,&(box->length), 4);
+ }
+ return OPJ_TRUE;
+}
+
+#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
+
+opj_bool opj_jp2_read_ihdr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE *p_image_header_data,
+ OPJ_UINT32 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_v2(p_manager, EVT_ERROR, "Bad image header box (bad size)\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Not enough memory to handle image header (ihdr)\n");
+ return OPJ_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;
+
+ /* if equal to 0 then need a BPC box (cf. chapter about image header box of the norm) */
+ /*if (jp2->bpc == 0){
+ indicate with a flag that we will wait a BPC box
+ }*/
+
+ opj_read_bytes(p_image_header_data,&(jp2->C),1); /* C */
+ ++ p_image_header_data;
+
+ /* Should be equal to 7 cf. chapter about image header box of the norm */
+ if (jp2->C != 7){
+ opj_event_msg_v2(p_manager, EVT_INFO, "JP2 IHDR box: compression type indicate that the file is not a conforming JP2 file (%d) \n", jp2->C);
+ }
+
+ 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 OPJ_TRUE;
+}
+
+OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * 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;
+}
+
+OPJ_BYTE * opj_jp2_write_bpcc( opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * 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;
+}
+
+opj_bool opj_jp2_read_bpcc( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_bpc_header_data,
+ OPJ_UINT32 p_bpc_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 i;
+
+ /* preconditions */
+ assert(p_bpc_header_data != 00);
+ assert(jp2 != 00);
+ assert(p_manager != 00);
+
+ /* TODO MSD */
+ /*if (jp2->bpc != 0 ){
+ opj_event_msg_v2(p_manager, EVT_WARNING, "A BPCC header box is available although BPC is different to zero (%d)\n",jp2->bpc);
+ }*/
+
+ /* and length is relevant */
+ if (p_bpc_header_size != jp2->numcomps) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n");
+ return OPJ_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 OPJ_TRUE;
+}
+
+OPJ_BYTE * opj_jp2_write_colr( opj_jp2_v2_t *jp2,
+ OPJ_UINT32 * 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;
+}
+
+void opj_jp2_free_pclr(opj_jp2_color_t *color)
+{
+ opj_free(color->jp2_pclr->channel_sign);
+ opj_free(color->jp2_pclr->channel_size);
+ opj_free(color->jp2_pclr->entries);
+
+ if(color->jp2_pclr->cmap) opj_free(color->jp2_pclr->cmap);
+
+ opj_free(color->jp2_pclr); color->jp2_pclr = NULL;
+}
+
+void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
+{
+ opj_image_comp_t *old_comps, *new_comps;
+ OPJ_BYTE *channel_size, *channel_sign;
+ OPJ_UINT32 *entries;
+ opj_jp2_cmap_comp_t *cmap;
+ OPJ_INT32 *src, *dst;
+ OPJ_UINT32 j, max;
+ OPJ_UINT16 i, nr_channels, cmp, pcol;
+ OPJ_INT32 k, top_k;
+
+ channel_size = color->jp2_pclr->channel_size;
+ channel_sign = color->jp2_pclr->channel_sign;
+ entries = color->jp2_pclr->entries;
+ cmap = color->jp2_pclr->cmap;
+ nr_channels = color->jp2_pclr->nr_channels;
+
+ old_comps = image->comps;
+ new_comps = (opj_image_comp_t*)
+ opj_malloc(nr_channels * sizeof(opj_image_comp_t));
+
+ for(i = 0; i < nr_channels; ++i) {
+ pcol = cmap[i].pcol; cmp = cmap[i].cmp;
+
+ new_comps[pcol] = old_comps[cmp];
+
+ /* Direct use */
+ if(cmap[i].mtyp == 0){
+ old_comps[cmp].data = NULL; continue;
+ }
+
+ /* Palette mapping: */
+ new_comps[pcol].data = (int*)
+ opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int));
+ new_comps[pcol].prec = channel_size[i];
+ new_comps[pcol].sgnd = channel_sign[i];
+ }
+
+ top_k = color->jp2_pclr->nr_entries - 1;
+
+ for(i = 0; i < nr_channels; ++i) {
+ /* Direct use: */
+ if(cmap[i].mtyp == 0) continue;
+
+ /* Palette mapping: */
+ cmp = cmap[i].cmp; pcol = cmap[i].pcol;
+ src = old_comps[cmp].data;
+ dst = new_comps[pcol].data;
+ max = new_comps[pcol].w * new_comps[pcol].h;
+
+ for(j = 0; j < max; ++j)
+ {
+ /* The index */
+ if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k;
+
+ /* The colour */
+ dst[j] = entries[k * nr_channels + pcol];
+ }
+ }
+
+ max = image->numcomps;
+ for(i = 0; i < max; ++i) {
+ if(old_comps[i].data) opj_free(old_comps[i].data);
+ }
+
+ opj_free(old_comps);
+ image->comps = new_comps;
+ image->numcomps = nr_channels;
+
+ opj_jp2_free_pclr(color);
+
+}/* apply_pclr() */
+
+opj_bool opj_jp2_read_pclr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_pclr_header_data,
+ OPJ_UINT32 p_pclr_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_jp2_pclr_t *jp2_pclr;
+ OPJ_BYTE *channel_size, *channel_sign;
+ OPJ_UINT32 *entries;
+ OPJ_UINT16 nr_entries,nr_channels;
+ OPJ_UINT16 i, j;
+ OPJ_UINT32 l_value;
+
+ /* preconditions */
+ assert(p_pclr_header_data != 00);
+ assert(jp2 != 00);
+ assert(p_manager != 00);
+ (void)p_pclr_header_size;
+
+ if(jp2->color.jp2_pclr)
+ return OPJ_FALSE;
+
+ opj_read_bytes(p_pclr_header_data, &l_value , 2); /* NE */
+ p_pclr_header_data += 2;
+ nr_entries = (OPJ_UINT16) l_value;
+
+ opj_read_bytes(p_pclr_header_data, &l_value , 1); /* NPC */
+ ++p_pclr_header_data;
+ nr_channels = (OPJ_UINT16) l_value;
+
+ entries = (OPJ_UINT32*) opj_malloc(nr_channels * nr_entries * sizeof(OPJ_UINT32));
+ channel_size = (OPJ_BYTE*) opj_malloc(nr_channels);
+ channel_sign = (OPJ_BYTE*) opj_malloc(nr_channels);
+
+ jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t));
+ jp2_pclr->channel_sign = channel_sign;
+ jp2_pclr->channel_size = channel_size;
+ jp2_pclr->entries = entries;
+ jp2_pclr->nr_entries = nr_entries;
+ jp2_pclr->nr_channels = (OPJ_BYTE) l_value;
+ jp2_pclr->cmap = NULL;
+
+ jp2->color.jp2_pclr = jp2_pclr;
+
+ for(i = 0; i < nr_channels; ++i) {
+ opj_read_bytes(p_pclr_header_data, &l_value , 1); /* Bi */
+ ++p_pclr_header_data;
+
+ channel_size[i] = (l_value & 0x7f) + 1;
+ channel_sign[i] = (l_value & 0x80)? 1 : 0;
+ }
+
+ for(j = 0; j < nr_entries; ++j) {
+ for(i = 0; i < nr_channels; ++i) {
+ int bytes_to_read = (channel_size[i]+7)>>3;
+
+ opj_read_bytes(p_pclr_header_data, &l_value , bytes_to_read); /* Cji */
+ p_pclr_header_data += bytes_to_read;
+ *entries = (OPJ_UINT32) l_value;
+ entries++;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_read_cmap( opj_jp2_v2_t * jp2,
+ OPJ_BYTE * p_cmap_header_data,
+ OPJ_UINT32 p_cmap_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_jp2_cmap_comp_t *cmap;
+ OPJ_BYTE i, nr_channels;
+ OPJ_UINT32 l_value;
+
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_cmap_header_data != 00);
+ assert(p_manager != 00);
+ (void)p_cmap_header_size;
+
+ /* Need nr_channels: */
+ if(jp2->color.jp2_pclr == NULL) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Need to read a PCLR box before the CMAP box.\n");
+ return OPJ_FALSE;
+ }
+
+ /* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box
+ * inside a JP2 Header box' :
+ */
+ if(jp2->color.jp2_pclr->cmap) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Only one CMAP box is allowed.\n");
+ return OPJ_FALSE;
+ }
+
+ nr_channels = jp2->color.jp2_pclr->nr_channels;
+ cmap = (opj_jp2_cmap_comp_t*) opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t));
+
+ for(i = 0; i < nr_channels; ++i) {
+ opj_read_bytes(p_cmap_header_data, &l_value, 2); /* CMP^i */
+ p_cmap_header_data +=2;
+ cmap[i].cmp = (OPJ_UINT16) l_value;
+
+ opj_read_bytes(p_cmap_header_data, &l_value, 1); /* MTYP^i */
+ ++p_cmap_header_data;
+ cmap[i].mtyp = (OPJ_BYTE) l_value;
+
+ opj_read_bytes(p_cmap_header_data, &l_value, 1); /* PCOL^i */
+ ++p_cmap_header_data;
+ cmap[i].pcol = (OPJ_BYTE) l_value;
+ }
+
+ jp2->color.jp2_pclr->cmap = cmap;
+
+ return OPJ_TRUE;
+}
+
+void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
+{
+ opj_jp2_cdef_info_t *info;
+ OPJ_INT32 color_space;
+ OPJ_UINT16 i, n, cn, typ, asoc, acn;
+
+ color_space = image->color_space;
+ info = color->jp2_cdef->info;
+ n = color->jp2_cdef->n;
+
+ for(i = 0; i < n; ++i)
+ {
+ /* WATCH: acn = asoc - 1 ! */
+ if((asoc = info[i].asoc) == 0) continue;
+
+ cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
+
+ if(cn != acn)
+ {
+ opj_image_comp_t saved;
+
+ memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
+ memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
+ memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
+
+ info[i].asoc = cn + 1;
+ info[acn].asoc = info[acn].cn + 1;
+ }
+ }
+
+ if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
+
+ opj_free(color->jp2_cdef); color->jp2_cdef = NULL;
+
+}/* jp2_apply_cdef() */
+
+opj_bool opj_jp2_read_cdef( opj_jp2_v2_t * jp2,
+ OPJ_BYTE * p_cdef_header_data,
+ OPJ_UINT32 p_cdef_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_jp2_cdef_info_t *cdef_info;
+ unsigned short i;
+ OPJ_UINT32 l_value;
+
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_cdef_header_data != 00);
+ assert(p_manager != 00);
+ (void)p_cdef_header_size;
+
+ /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box
+ * inside a JP2 Header box.'*/
+ if(jp2->color.jp2_cdef) return OPJ_FALSE;
+
+ opj_read_bytes(p_cdef_header_data,&l_value ,2); /* N */
+ p_cdef_header_data+= 2;
+
+ if ( (OPJ_UINT16)l_value == 0){ /* szukw000: FIXME */
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Number of channel description is equal to zero in CDEF box.\n");
+ return OPJ_FALSE;
+ }
+
+ cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof(opj_jp2_cdef_info_t));
+
+ jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t));
+ jp2->color.jp2_cdef->info = cdef_info;
+ jp2->color.jp2_cdef->n = (OPJ_UINT16) l_value;
+
+ for(i = 0; i < jp2->color.jp2_cdef->n; ++i) {
+ opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Cn^i */
+ p_cdef_header_data +=2;
+ cdef_info[i].cn = (OPJ_UINT16) l_value;
+
+ opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Typ^i */
+ p_cdef_header_data +=2;
+ cdef_info[i].typ = (OPJ_UINT16) l_value;
+
+ opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Asoc^i */
+ p_cdef_header_data +=2;
+ cdef_info[i].asoc = (OPJ_UINT16) l_value;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_read_colr( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_colr_header_data,
+ OPJ_UINT32 p_colr_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 l_value;
+
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_colr_header_data != 00);
+ assert(p_manager != 00);
+
+ if (p_colr_header_size < 3) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Bad COLR header box (bad size)\n");
+ return OPJ_FALSE;
+ }
+
+ /* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour
+ * Specification boxes after the first.'
+ */
+ if(jp2->color.jp2_has_colr) {
+ opj_event_msg_v2(p_manager, EVT_INFO, "A conforming JP2 reader shall ignore all Colour Specification boxes after the first, so we ignore this one.\n");
+ p_colr_header_data += p_colr_header_size;
+ return OPJ_TRUE;
+ }
+
+ 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_v2(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4); /* EnumCS */
+ }
+ else if (jp2->meth == 2) {
+ /* ICC profile */
+ int it_icc_value = 0;
+ int icc_len = p_colr_header_size - 3;
+
+ jp2->color.icc_profile_len = icc_len;
+ jp2->color.icc_profile_buf = (unsigned char*) opj_malloc(icc_len);
+
+ memset(jp2->color.icc_profile_buf, 0, icc_len * sizeof(unsigned char));
+
+ for (it_icc_value = 0; it_icc_value < icc_len; ++it_icc_value)
+ {
+ opj_read_bytes(p_colr_header_data,&l_value,1); /* icc values */
+ ++p_colr_header_data;
+ jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value;
+ }
+
+ }
+ else /* TODO MSD */
+ opj_event_msg_v2(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), so we will skip the fields following the approx field.\n", jp2->meth);
+
+ jp2->color.jp2_has_colr = 1;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_decode(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
+{
+ if (!p_image)
+ return OPJ_FALSE;
+
+ /* J2K decoding */
+ if( ! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ if (!jp2->ignore_pclr_cmap_cdef){
+
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16)
+ p_image->color_space = CLRSPC_SRGB;
+ else if (jp2->enumcs == 17)
+ p_image->color_space = CLRSPC_GRAY;
+ else if (jp2->enumcs == 18)
+ p_image->color_space = CLRSPC_SYCC;
+ else
+ p_image->color_space = CLRSPC_UNKNOWN;
+
+ /* Apply the color space if needed */
+ if(jp2->color.jp2_cdef) {
+ opj_jp2_apply_cdef(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.jp2_pclr) {
+ /* Part 1, I.5.3.4: Either both or none : */
+ if( !jp2->color.jp2_pclr->cmap)
+ opj_jp2_free_pclr(&(jp2->color));
+ else
+ opj_jp2_apply_pclr(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.icc_profile_buf) {
+ p_image->icc_profile_buf = jp2->color.icc_profile_buf;
+ p_image->icc_profile_len = jp2->color.icc_profile_len;
+ jp2->color.icc_profile_buf = NULL;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_write_jp2h(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ 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;
+ opj_bool l_result = OPJ_TRUE;
+
+ /* to store the data of the super box */
+ unsigned char l_jp2h_data [8];
+
+ /* preconditions */
+ assert(stream != 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 = opj_jp2_write_ihdr;
+ l_writers[1].handler = opj_jp2_write_bpcc;
+ l_writers[2].handler = opj_jp2_write_colr;
+ }
+ else {
+ l_nb_pass = 2;
+ l_writers[0].handler = opj_jp2_write_ihdr;
+ l_writers[1].handler = opj_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;i<l_nb_pass;++i) {
+ l_current_writer->m_data = l_current_writer->handler(jp2,&(l_current_writer->m_size));
+ if (l_current_writer->m_data == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to hold JP2 Header data\n");
+ l_result = OPJ_FALSE;
+ break;
+ }
+
+ l_jp2h_size += l_current_writer->m_size;
+ ++l_current_writer;
+ }
+
+ if (! l_result) {
+ l_current_writer = l_writers;
+ for (i=0;i<l_nb_pass;++i) {
+ if (l_current_writer->m_data != 00) {
+ opj_free(l_current_writer->m_data );
+ }
+ ++l_current_writer;
+ }
+
+ return OPJ_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(stream,l_jp2h_data,8,p_manager) != 8) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while writing JP2 Header box\n");
+ l_result = OPJ_FALSE;
+ }
+
+ if (l_result) {
+ l_current_writer = l_writers;
+ for (i=0;i<l_nb_pass;++i) {
+ if (opj_stream_write_data(stream,l_current_writer->m_data,l_current_writer->m_size,p_manager) != l_current_writer->m_size) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n");
+ l_result = OPJ_FALSE;
+ break;
+ }
+ ++l_current_writer;
+ }
+ }
+
+ l_current_writer = l_writers;
+
+ /* cleanup */
+ for (i=0;i<l_nb_pass;++i) {
+ if (l_current_writer->m_data != 00) {
+ opj_free(l_current_writer->m_data );
+ }
+ ++l_current_writer;
+ }
+
+ return l_result;
+}
+
+opj_bool opj_jp2_write_ftyp(opj_jp2_v2_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;
+ opj_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_v2(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error while writting ftyp data to stream\n");
+ }
+
+ opj_free(l_ftyp_data);
+
+ return l_result;
+}
+
+opj_bool opj_jp2_write_jp2c(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager )
+{
+ OPJ_OFF_T j2k_codestream_exit;
+ OPJ_BYTE 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,
+ (OPJ_UINT32) (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_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+ return OPJ_FALSE;
+ }
+
+ if (opj_stream_write_data(cio,l_data_header,8,p_manager) != 8) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+ return OPJ_FALSE;
+ }
+
+ if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_write_jp( opj_jp2_v2_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 OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 decoder interface */
+/* ----------------------------------------------------------------------- */
+
+void opj_jp2_setup_decoder(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters)
+{
+ /* setup the J2K codec */
+ opj_j2k_setup_decoder(jp2->j2k, parameters);
+
+ /* further JP2 initializations go here */
+ jp2->color.jp2_has_colr = 0;
+ jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 encoder interface */
+/* ----------------------------------------------------------------------- */
+
+void opj_jp2_setup_encoder( opj_jp2_v2_t *jp2,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager)
+{
+ OPJ_UINT32 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_v2(p_manager, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n");
+ return;
+ }
+
+ opj_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 */
+
+ /* jp2->jpip_on = parameters->jpip_on; */
+}
+
+opj_bool opj_jp2_encode(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager)
+{
+ return opj_j2k_encode_v2(jp2->j2k, stream, p_manager);
+}
+
+opj_bool opj_jp2_end_decompress(opj_jp2_v2_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 */
+ opj_jp2_setup_end_header_reading(jp2);
+
+ /* write header */
+ if (! opj_jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return opj_j2k_end_decompress(jp2->j2k, cio, p_manager);
+}
+
+opj_bool opj_jp2_end_compress( opj_jp2_v2_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 */
+ opj_jp2_setup_end_header_writting(jp2);
+
+ if (! opj_j2k_end_compress(jp2->j2k,cio,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ /* write header */
+ return opj_jp2_exec(jp2,jp2->m_procedure_list,cio,p_manager);
+}
+
+void opj_jp2_setup_end_header_writting (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2c );
+ /* DEVELOPER CORNER, add your custom procedures */
+}
+
+void opj_jp2_setup_end_header_reading (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure );
+ /* DEVELOPER CORNER, add your custom procedures */
+}
+
+opj_bool opj_jp2_default_validation ( opj_jp2_v2_t * jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_bool l_is_valid = OPJ_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;
+}
+
+opj_bool opj_jp2_read_header_procedure( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_jp2_box_t box;
+ OPJ_UINT32 l_nb_bytes_read;
+ const opj_jp2_header_handler_t * l_current_handler;
+ OPJ_UINT32 l_last_data_size = BOX_SIZE;
+ OPJ_UINT32 l_current_data_size;
+ unsigned char * l_current_data = 00;
+
+ /* preconditions */
+ assert(stream != 00);
+ assert(jp2 != 00);
+ assert(p_manager != 00);
+
+ l_current_data = (unsigned char*)opj_malloc(l_last_data_size);
+
+ if (l_current_data == 00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to handle jpeg2000 file header\n");
+ return OPJ_FALSE;
+ }
+ memset(l_current_data, 0 , l_last_data_size);
+
+ while (opj_jp2_read_boxhdr(&box,&l_nb_bytes_read,stream,p_manager)) {
+ /* is it the codestream box ? */
+ if (box.type == JP2_JP2C) {
+ if (jp2->jp2_state & JP2_STATE_HEADER) {
+ jp2->jp2_state |= JP2_STATE_CODESTREAM;
+ opj_free(l_current_data);
+ return OPJ_TRUE;
+ }
+ else {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "bad placed jpeg codestream\n");
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ }
+ else if (box.length == 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n");
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+
+ l_current_handler = opj_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) {
+ unsigned char* new_current_data = (unsigned char*)opj_realloc(l_current_data,l_current_data_size);
+ if (!l_current_data){
+ opj_free(l_current_data);
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to handle jpeg2000 box\n");
+ return OPJ_FALSE;
+ }
+ l_current_data = new_current_data;
+ l_last_data_size = l_current_data_size;
+ }
+
+ l_nb_bytes_read = opj_stream_read_data(stream,l_current_data,l_current_data_size,p_manager);
+ if (l_nb_bytes_read != l_current_data_size) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with reading JPEG2000 box, stream error\n");
+ /* TODO: LH: why nothing is freed here (as
+ all other returns imply a free, even
+ in the nominal case)? */
+ return OPJ_FALSE;
+ }
+
+ if (! l_current_handler->handler(jp2,l_current_data,l_current_data_size,p_manager)) {
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ }
+ else {
+ jp2->jp2_state |= JP2_STATE_UNKNOWN;
+ if (opj_stream_skip(stream,l_current_data_size,p_manager) != l_current_data_size) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with skipping JPEG2000 box, stream error\n");
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
+ }
+ }
+
+ opj_free(l_current_data);
+
+ return OPJ_TRUE;
+}
+
+/**
+ * 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 stream the stream to execute the procedures on.
+ * @param p_manager the user manager.
+ *
+ * @return true if all the procedures were successfully executed.
+ */
+static opj_bool opj_jp2_exec ( opj_jp2_v2_t * jp2,
+ opj_procedure_list_t * p_procedure_list,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager
+ )
+
+{
+ opj_bool (** l_procedure) (opj_jp2_v2_t * jp2, opj_stream_private_t *, opj_event_mgr_t *) = 00;
+ opj_bool l_result = OPJ_TRUE;
+ OPJ_UINT32 l_nb_proc, i;
+
+ /* preconditions */
+ assert(p_procedure_list != 00);
+ assert(jp2 != 00);
+ assert(stream != 00);
+ assert(p_manager != 00);
+
+ l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list);
+ l_procedure = (opj_bool (**) (opj_jp2_v2_t * jp2, opj_stream_private_t *, opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list);
+
+ for (i=0;i<l_nb_proc;++i) {
+ l_result = l_result && (*l_procedure) (jp2,stream,p_manager);
+ ++l_procedure;
+ }
+
+ /* and clear the procedure list at the end. */
+ opj_procedure_list_clear(p_procedure_list);
+ return l_result;
+}
+
+opj_bool opj_jp2_start_compress(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(stream != 00);
+ assert(p_manager != 00);
+
+ /* customization of the validation */
+ opj_jp2_setup_encoding_validation (jp2);
+
+ /* validation of the parameters codec */
+ if (! opj_jp2_exec(jp2,jp2->m_validation_list,stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ /* customization of the encoding */
+ opj_jp2_setup_header_writting(jp2);
+
+ /* write header */
+ if (! opj_jp2_exec (jp2,jp2->m_procedure_list,stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return opj_j2k_start_compress(jp2->j2k,stream,p_image,p_manager);
+}
+
+const opj_jp2_header_handler_t * opj_jp2_find_handler (OPJ_UINT32 p_id)
+{
+ OPJ_UINT32 i, l_handler_size = sizeof(jp2_header) / sizeof(opj_jp2_header_handler_t);
+
+ for (i=0;i<l_handler_size;++i) {
+ if (jp2_header[i].id == p_id) {
+ return &jp2_header[i];
+ }
+ }
+ return NULL;
+}
+
+/**
+ * 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 00 if it could not be found.
+ */
+static const opj_jp2_header_handler_t * opj_jp2_img_find_handler (OPJ_UINT32 p_id)
+{
+ OPJ_UINT32 i, l_handler_size = sizeof(jp2_img_header) / sizeof(opj_jp2_header_handler_t);
+ for (i=0;i<l_handler_size;++i)
+ {
+ if (jp2_img_header[i].id == p_id) {
+ return &jp2_img_header[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * 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 opj_bool opj_jp2_read_jp(opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 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_v2(p_manager, EVT_ERROR, "The signature box must be the first box in the file.\n");
+ return OPJ_FALSE;
+ }
+
+ /* assure length of data is correct (4 -> magic number) */
+ if (p_header_size != 4) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with JP signature Box size\n");
+ return OPJ_FALSE;
+ }
+
+ /* rearrange data */
+ opj_read_bytes(p_header_data,&l_magic_number,4);
+ if (l_magic_number != 0x0d0a870a ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with JP Signature : bad magic number\n");
+ return OPJ_FALSE;
+ }
+
+ jp2->jp2_state |= JP2_STATE_SIGNATURE;
+
+ return OPJ_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.
+ */
+static opj_bool opj_jp2_read_ftyp( opj_jp2_v2_t *jp2,
+ OPJ_BYTE * p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 i, 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_v2(p_manager, EVT_ERROR, "The ftyp box must be the second box in the file.\n");
+ return OPJ_FALSE;
+ }
+
+ /* assure length of data is correct */
+ if (p_header_size < 8) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n");
+ return OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_jp2_skip_jp2c( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager )
+{
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(stream != 00);
+ assert(p_manager != 00);
+
+ jp2->j2k_codestream_offset = opj_stream_tell(stream);
+
+ if (opj_stream_skip(stream,8,p_manager) != 8) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/**
+ * 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.
+*/
+static opj_bool opj_jp2_read_jp2h( opj_jp2_v2_t *jp2,
+ OPJ_BYTE *p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager
+ )
+{
+ OPJ_UINT32 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_v2(p_manager, EVT_ERROR, "The box must be the first box in the file.\n");
+ return OPJ_FALSE;
+ }
+
+ jp2->jp2_img_state = JP2_IMG_STATE_NONE;
+
+ /* iterate while remaining data */
+ while (p_header_size > 0) {
+
+ if (! opj_jp2_read_boxhdr_char(&box,p_header_data,&l_box_size,p_header_size, p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n");
+ return OPJ_FALSE;
+ }
+
+ if (box.length > p_header_size) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box: box length is inconsistent.\n");
+ return OPJ_FALSE;
+ }
+
+ l_current_handler = opj_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 OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_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
+ )
+{
+ OPJ_UINT32 l_value;
+
+ /* 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_v2(p_manager, EVT_ERROR, "Cannot handle box of less than 8 bytes\n");
+ return OPJ_FALSE;
+ }
+
+ /* process read data */
+ opj_read_bytes(p_data, &l_value, 4);
+ p_data += 4;
+ box->length = (OPJ_INT32)(l_value);
+
+ opj_read_bytes(p_data, &l_value, 4);
+ p_data += 4;
+ box->type = (OPJ_INT32)(l_value);
+
+ *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_v2(p_manager, EVT_ERROR, "Cannot handle XL box of less than 16 bytes\n");
+ return OPJ_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_v2(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n");
+ return OPJ_FALSE;
+ }
+
+ opj_read_bytes(p_data, &l_value, 4);
+ *p_number_bytes_read += 4;
+ box->length = (OPJ_INT32)(l_value);
+
+ if (box->length == 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n");
+ return OPJ_FALSE;
+ }
+ }
+ else if (box->length == 0) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_jp2_read_header( opj_stream_private_t *p_stream,
+ opj_jp2_v2_t *jp2,
+ opj_image_t ** p_image,
+ opj_event_mgr_t * p_manager
+ )
+{
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ /* customization of the validation */
+ opj_jp2_setup_decoding_validation (jp2);
+
+ /* customization of the encoding */
+ opj_jp2_setup_header_reading(jp2);
+
+ /* validation of the parameters codec */
+ if (! opj_jp2_exec(jp2,jp2->m_validation_list,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ /* read header */
+ if (! opj_jp2_exec (jp2,jp2->m_procedure_list,p_stream,p_manager)) {
+ return OPJ_FALSE;
+ }
+
+ return opj_j2k_read_header( p_stream,
+ jp2->j2k,
+ p_image,
+ p_manager);
+}
+
+void opj_jp2_setup_encoding_validation (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+
+ opj_procedure_list_add_procedure(jp2->m_validation_list, (opj_procedure)opj_jp2_default_validation);
+ /* DEVELOPER CORNER, add your custom validation procedure */
+}
+
+void opj_jp2_setup_decoding_validation (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+ /* DEVELOPER CORNER, add your custom validation procedure */
+}
+
+void opj_jp2_setup_header_writting (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp );
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_ftyp );
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_write_jp2h );
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_skip_jp2c );
+
+ /* DEVELOPER CORNER, insert your custom procedures */
+
+}
+
+void opj_jp2_setup_header_reading (opj_jp2_v2_t *jp2)
+{
+ /* preconditions */
+ assert(jp2 != 00);
+
+ opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)opj_jp2_read_header_procedure );
+ /* DEVELOPER CORNER, add your custom procedures */
+}
+
+opj_bool opj_jp2_read_tile_header ( opj_jp2_v2_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,
+ opj_bool * p_go_on,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ return opj_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);
+}
+
+opj_bool opj_jp2_write_tile ( opj_jp2_v2_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 opj_j2k_write_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager);
+}
+
+opj_bool opj_jp2_decode_tile ( opj_jp2_v2_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 opj_j2k_decode_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager);
+}
+
+void opj_jp2_destroy(opj_jp2_v2_t *jp2)
+{
+ if (jp2) {
+ /* destroy the J2K codec */
+ opj_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->color.icc_profile_buf) {
+ opj_free(jp2->color.icc_profile_buf);
+ jp2->color.icc_profile_buf = 00;
+ }
+
+ if (jp2->color.jp2_cdef) {
+ if (jp2->color.jp2_cdef->info) {
+ opj_free(jp2->color.jp2_cdef->info);
+ jp2->color.jp2_cdef->info = NULL;
+ }
+
+ opj_free(jp2->color.jp2_cdef);
+ jp2->color.jp2_cdef = 00;
+ }
+
+ if (jp2->color.jp2_pclr) {
+ if (jp2->color.jp2_pclr->cmap) {
+ opj_free(jp2->color.jp2_pclr->cmap);
+ jp2->color.jp2_pclr->cmap = NULL;
+ }
+ if (jp2->color.jp2_pclr->channel_sign) {
+ opj_free(jp2->color.jp2_pclr->channel_sign);
+ jp2->color.jp2_pclr->channel_sign = NULL;
+ }
+ if (jp2->color.jp2_pclr->channel_size) {
+ opj_free(jp2->color.jp2_pclr->channel_size);
+ jp2->color.jp2_pclr->channel_size = NULL;
+ }
+ if (jp2->color.jp2_pclr->entries) {
+ opj_free(jp2->color.jp2_pclr->entries);
+ jp2->color.jp2_pclr->entries = NULL;
+ }
+
+ opj_free(jp2->color.jp2_pclr);
+ jp2->color.jp2_pclr = 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);
+ }
+}
+
+opj_bool opj_jp2_set_decode_area( opj_jp2_v2_t *p_jp2,
+ opj_image_t* p_image,
+ OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
+ OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
+ opj_event_mgr_t * p_manager
+ )
+{
+ return opj_j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, p_end_x, p_end_y, p_manager);
+}
+
+opj_bool opj_jp2_get_tile( opj_jp2_v2_t *p_jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index
+ )
+{
+ if (!p_image)
+ return OPJ_FALSE;
+
+ opj_event_msg_v2(p_manager, EVT_WARNING, "JP2 box which are after the codestream will not be read by this function.\n");
+
+ if (! opj_j2k_get_tile(p_jp2->j2k, p_stream, p_image, p_manager, tile_index) ){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ /* Set Image Color Space */
+ if (p_jp2->enumcs == 16)
+ p_image->color_space = CLRSPC_SRGB;
+ else if (p_jp2->enumcs == 17)
+ p_image->color_space = CLRSPC_GRAY;
+ else if (p_jp2->enumcs == 18)
+ p_image->color_space = CLRSPC_SYCC;
+ else
+ p_image->color_space = CLRSPC_UNKNOWN;
+
+ /* Apply the color space if needed */
+ if(p_jp2->color.jp2_cdef) {
+ opj_jp2_apply_cdef(p_image, &(p_jp2->color));
+ }
+
+ if(p_jp2->color.jp2_pclr) {
+ /* Part 1, I.5.3.4: Either both or none : */
+ if( !p_jp2->color.jp2_pclr->cmap)
+ opj_jp2_free_pclr(&(p_jp2->color));
+ else
+ opj_jp2_apply_pclr(p_image, &(p_jp2->color));
+ }
+
+ if(p_jp2->color.icc_profile_buf) {
+ p_image->icc_profile_buf = p_jp2->color.icc_profile_buf;
+ p_image->icc_profile_len = p_jp2->color.icc_profile_len;
+ p_jp2->color.icc_profile_buf = NULL;
+ }
+
+ return OPJ_TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 encoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_jp2_v2_t* opj_jp2_create(opj_bool p_is_decoder)
+{
+ opj_jp2_v2_t *jp2 = (opj_jp2_v2_t*)opj_malloc(sizeof(opj_jp2_v2_t));
+ if (jp2) {
+ memset(jp2,0,sizeof(opj_jp2_v2_t));
+
+ /* create the J2K codec */
+ if (! p_is_decoder) {
+ jp2->j2k = opj_j2k_create_compress();
+ }
+ else {
+ jp2->j2k = opj_j2k_create_decompress();
+ }
+
+ if (jp2->j2k == 00) {
+ opj_jp2_destroy(jp2);
+ return 00;
+ }
+
+ /* Color structure */
+ jp2->color.icc_profile_buf = NULL;
+ jp2->color.icc_profile_len = 0;
+ jp2->color.jp2_cdef = NULL;
+ jp2->color.jp2_pclr = NULL;
+ jp2->color.jp2_has_colr = 0;
+
+ /* validation list creation */
+ jp2->m_validation_list = opj_procedure_list_create();
+ if (! jp2->m_validation_list) {
+ opj_jp2_destroy(jp2);
+ return 00;
+ }
+
+ /* execution list creation */
+ jp2->m_procedure_list = opj_procedure_list_create();
+ if (! jp2->m_procedure_list) {
+ opj_jp2_destroy(jp2);
+ return 00;
+ }
+ }
+
+ return jp2;
+}
+
+void jp2_dump(opj_jp2_v2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream)
+{
+ /* preconditions */
+ assert(p_jp2 != 00);
+
+ j2k_dump(p_jp2->j2k,
+ flag,
+ out_stream);
+}
+
+opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_v2_t* p_jp2)
+{
+ return j2k_get_cstr_index(p_jp2->j2k);
+}
+
+opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_v2_t* p_jp2)
+{
+ return j2k_get_cstr_info(p_jp2->j2k);
+}
+
+opj_bool opj_jp2_set_decoded_resolution_factor(opj_jp2_v2_t *p_jp2,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager)
+{
+ return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager);
+}
+
diff --git a/src/lib/openjp2/jp2.h b/src/lib/openjp2/jp2.h
new file mode 100644
index 00000000..f2f3c757
--- /dev/null
+++ b/src/lib/openjp2/jp2.h
@@ -0,0 +1,511 @@
+/*
+ * 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
+ * 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)
+
+*/
+
+/** @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 (super-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 /**< Data entry URL box */
+#define JP2_PCLR 0x70636c72 /**< Palette box */
+#define JP2_CMAP 0x636d6170 /**< Component Mapping box */
+#define JP2_CDEF 0x63646566 /**< Channel Definition box */
+#define JP2_DTBL 0x6474626c /**< Data Reference box */
+#define JP2_BPCC 0x62706363 /**< Bits per component box */
+#define JP2_JP2 0x6a703220 /**< File type fields */
+
+/* For the future */
+/* #define JP2_RES 0x72657320 */ /**< Resolution box (super-box) */
+/* #define JP2_JP2I 0x6a703269 */ /**< Intellectual property box */
+/* #define JP2_XML 0x786d6c20 */ /**< XML box */
+/* #define JP2_UUID 0x75756994 */ /**< UUID box */
+/* #define JP2_UINF 0x75696e66 */ /**< UUID info box (super-box) */
+/* #define JP2_ULST 0x756c7374 */ /**< UUID list box */
+
+/* ----------------------------------------------------------------------- */
+
+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 = 0x7fffffff /* ISO C restricts enumerator values to range of 'int' */
+}
+JP2_STATE;
+
+typedef enum
+{
+ JP2_IMG_STATE_NONE = 0x0,
+ JP2_IMG_STATE_UNKNOWN = 0x7fffffff
+}
+JP2_IMG_STATE;
+
+/**
+Channel description: channel index, type, assocation
+*/
+typedef struct opj_jp2_cdef_info
+{
+ OPJ_UINT16 cn, typ, asoc;
+} opj_jp2_cdef_info_t;
+
+/**
+Channel descriptions and number of descriptions
+*/
+typedef struct opj_jp2_cdef
+{
+ opj_jp2_cdef_info_t *info;
+ OPJ_UINT16 n;
+} opj_jp2_cdef_t;
+
+/**
+Component mappings: channel index, mapping type, palette index
+*/
+typedef struct opj_jp2_cmap_comp
+{
+ OPJ_UINT16 cmp;
+ OPJ_BYTE mtyp, pcol;
+} opj_jp2_cmap_comp_t;
+
+/**
+Palette data: table entries, palette columns
+*/
+typedef struct opj_jp2_pclr
+{
+ OPJ_UINT32 *entries;
+ OPJ_BYTE *channel_sign;
+ OPJ_BYTE *channel_size;
+ opj_jp2_cmap_comp_t *cmap;
+ OPJ_UINT16 nr_entries;
+ OPJ_BYTE nr_channels;
+} opj_jp2_pclr_t;
+
+/**
+Collector for ICC profile, palette, component mapping, channel description
+*/
+typedef struct opj_jp2_color
+{
+ OPJ_BYTE *icc_profile_buf;
+ OPJ_UINT32 icc_profile_len;
+
+ opj_jp2_cdef_t *jp2_cdef;
+ opj_jp2_pclr_t *jp2_pclr;
+ OPJ_BYTE jp2_has_colr;
+} opj_jp2_color_t;
+
+/**
+JP2 component
+*/
+typedef struct opj_jp2_comps {
+ int depth;
+ int sgnd;
+ OPJ_UINT32 bpcc;
+} opj_jp2_comps_t;
+
+/**
+JPEG-2000 file format reader/writer
+*/
+typedef struct opj_jp2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+ /** handle to the J2K codec */
+ opj_j2k_t *j2k;
+ unsigned int w;
+ unsigned int h;
+ 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 j2k_codestream_length;
+ opj_bool jpip_on;
+ opj_bool ignore_pclr_cmap_cdef;
+} opj_jp2_t;
+
+/**
+JPEG-2000 file format reader/writer
+*/
+typedef struct opj_jp2_v2
+{
+ /** handle to the J2K codec */
+ struct opj_j2k_v2 *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 */
+ OPJ_UINT32 w;
+ /* height of image */
+ OPJ_UINT32 h;
+ /* number of components in the image */
+ OPJ_UINT32 numcomps;
+ OPJ_UINT32 bpc;
+ OPJ_UINT32 C;
+ OPJ_UINT32 UnkC;
+ OPJ_UINT32 IPR;
+ OPJ_UINT32 meth;
+ OPJ_UINT32 approx;
+ OPJ_UINT32 enumcs;
+ OPJ_UINT32 precedence;
+ OPJ_UINT32 brand;
+ OPJ_UINT32 minversion;
+ OPJ_UINT32 numcl;
+ OPJ_UINT32 *cl;
+ opj_jp2_comps_t *comps;
+ OPJ_OFF_T j2k_codestream_offset;
+ OPJ_UINT32 jp2_state;
+ OPJ_UINT32 jp2_img_state;
+
+ opj_jp2_color_t color;
+
+ opj_bool ignore_pclr_cmap_cdef;
+}
+opj_jp2_v2_t;
+
+/**
+JP2 Box
+*/
+typedef struct opj_jp2_box {
+ OPJ_UINT32 length;
+ OPJ_UINT32 type;
+ OPJ_INT32 init_pos;
+} opj_jp2_box_t;
+
+typedef struct opj_jp2_header_handler
+{
+ /* marker value */
+ OPJ_UINT32 id;
+ /* action linked to the marker */
+ opj_bool (*handler) ( opj_jp2_v2_t *jp2,
+ OPJ_BYTE *p_header_data,
+ OPJ_UINT32 p_header_size,
+ opj_event_mgr_t * p_manager);
+}
+opj_jp2_header_handler_t;
+
+
+typedef struct opj_jp2_img_header_writer_handler
+{
+ /* action to perform */
+ OPJ_BYTE* (*handler) (opj_jp2_v2_t *jp2, OPJ_UINT32 * p_data_size);
+ /* result of the action : data */
+ OPJ_BYTE* m_data;
+ /* size of data */
+ OPJ_UINT32 m_size;
+}
+opj_jp2_img_header_writer_handler_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+ * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box).
+ *
+ * @param jp2 the jpeg2000 file codec.
+ * @param stream the stream to write data to.
+ * @param p_manager user event manager.
+ *
+ * @return true if writting was successful.
+*/
+opj_bool opj_jp2_write_jp2h(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+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 opj_jp2_setup_decoder(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters);
+
+/**
+ * Decode an image from a JPEG-2000 file stream
+ * @param jp2 JP2 decompressor handle
+ * @param p_stream FIXME DOC
+ * @param p_image FIXME DOC
+ * @param p_manager FIXME DOC
+ *
+ * @return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_bool opj_jp2_decode(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * 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
+ * @param p_manager FIXME DOC
+*/
+void opj_jp2_setup_encoder( opj_jp2_v2_t *jp2,
+ opj_cparameters_t *parameters,
+ opj_image_t *image,
+ opj_event_mgr_t * p_manager);
+
+/**
+Encode an image into a JPEG-2000 file stream
+@param jp2 JP2 compressor handle
+@param stream Output buffer stream
+@param p_manager event manager
+@return Returns true if successful, returns false otherwise
+*/
+opj_bool opj_jp2_encode( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_event_mgr_t * p_manager);
+
+
+/**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+ * @param jp2 the jpeg2000 file codec.
+ * @param stream the stream object.
+ * @param p_image FIXME DOC
+ * @param p_manager FIXME DOC
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool opj_jp2_start_compress(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *stream,
+ opj_image_t * p_image,
+ opj_event_mgr_t * p_manager);
+
+
+/**
+ * Ends the compression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool opj_jp2_end_compress( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+/* ----------------------------------------------------------------------- */
+
+/**
+ * Ends the decompression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool opj_jp2_end_decompress(opj_jp2_v2_t *jp2,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager);
+
+/**
+ * Reads a jpeg2000 file header structure.
+ *
+ * @param p_stream the stream to read data from.
+ * @param jp2 the jpeg2000 file header structure.
+ * @param p_image FIXME DOC
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+opj_bool opj_jp2_read_header( opj_stream_private_t *p_stream,
+ opj_jp2_v2_t *jp2,
+ opj_image_t ** p_image,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Reads a tile header.
+ * @param p_jp2 the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_tile_x0 FIXME DOC
+ * @param p_tile_y0 FIXME DOC
+ * @param p_tile_x1 FIXME DOC
+ * @param p_tile_y1 FIXME DOC
+ * @param p_nb_comps FIXME DOC
+ * @param p_go_on FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+opj_bool opj_jp2_read_tile_header ( opj_jp2_v2_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,
+ opj_bool * p_go_on,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager );
+
+/**
+ * Writes a tile.
+ *
+ * @param p_jp2 the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ */
+opj_bool opj_jp2_write_tile ( opj_jp2_v2_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 );
+
+/**
+ * Decode tile data.
+ * @param p_jp2 the jpeg2000 codec.
+ * @param p_tile_index FIXME DOC
+ * @param p_data FIXME DOC
+ * @param p_data_size FIXME DOC
+ * @param p_stream the stream to write data to.
+ * @param p_manager the user event manager.
+ *
+ * @return FIXME DOC
+ */
+opj_bool opj_jp2_decode_tile ( opj_jp2_v2_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 );
+
+/**
+ * Creates a jpeg2000 file decompressor.
+ *
+ * @return an empty jpeg2000 file codec.
+ */
+opj_jp2_v2_t* opj_jp2_create (opj_bool p_is_decoder);
+
+/**
+Destroy a JP2 decompressor handle
+@param jp2 JP2 decompressor handle to destroy
+*/
+void opj_jp2_destroy(opj_jp2_v2_t *jp2);
+
+
+/**
+ * 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_image FIXME DOC
+ * @param p_start_x the left 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_x the right 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.
+ */
+opj_bool opj_jp2_set_decode_area( opj_jp2_v2_t *p_jp2,
+ opj_image_t* p_image,
+ OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
+ OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
+ opj_event_mgr_t * p_manager );
+
+ /**
+ *
+ */
+opj_bool opj_jp2_get_tile( opj_jp2_v2_t *p_jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager,
+ OPJ_UINT32 tile_index );
+
+
+/**
+ *
+ */
+opj_bool opj_jp2_set_decoded_resolution_factor(opj_jp2_v2_t *p_jp2,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager);
+
+
+/* TODO MSD: clean these 3 functions */
+/**
+ * Dump some elements from the JP2 decompression structure .
+ *
+ *@param p_jp2 the jp2 codec.
+ *@param flag flag to describe what elments are dump.
+ *@param out_stream output stream where dump the elements.
+ *
+*/
+void jp2_dump (opj_jp2_v2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream);
+
+/**
+ * Get the codestream info from a JPEG2000 codec.
+ *
+ *@param p_jp2 jp2 codec.
+ *
+ *@return the codestream information extract from the jpg2000 codec
+ */
+opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_v2_t* p_jp2);
+
+/**
+ * Get the codestream index from a JPEG2000 codec.
+ *
+ *@param p_jp2 jp2 codec.
+ *
+ *@return the codestream index extract from the jpg2000 codec
+ */
+opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_v2_t* p_jp2);
+
+
+/*@}*/
+
+/*@}*/
+
+#endif /* __JP2_H */
+
diff --git a/src/lib/openjp2/jpt.c b/src/lib/openjp2/jpt.c
new file mode 100644
index 00000000..a2566ea8
--- /dev/null
+++ b/src/lib/openjp2/jpt.c
@@ -0,0 +1,155 @@
+/*
+ * 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
+ * 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"
+
+/*
+ * Read the information contains in VBAS [JPP/JPT stream message header]
+ * Store information (7 bits) in value
+ *
+ */
+unsigned int jpt_read_VBAS_info(opj_cio_t *cio, unsigned int value) {
+ unsigned char elmt;
+
+ elmt = cio_read(cio, 1);
+ while ((elmt >> 7) == 1) {
+ value = (value << 7);
+ value |= (elmt & 0x7f);
+ elmt = cio_read(cio, 1);
+ }
+ value = (value << 7);
+ value |= (elmt & 0x7f);
+
+ return value;
+}
+
+/*
+ * 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
+ *
+ */
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header) {
+ unsigned char elmt, Class = 0, CSn = 0;
+ jpt_reinit_msg_header(header);
+
+ /* ------------- */
+ /* VBAS : Bin-ID */
+ /* ------------- */
+ elmt = cio_read(cio, 1);
+
+ /* See for Class and CSn */
+ switch ((elmt >> 5) & 0x03) {
+ case 0:
+ opj_event_msg(cinfo, EVT_ERROR, "Forbidden value encounter in message header !!\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)
+ header->Id = jpt_read_VBAS_info(cio, header->Id);
+
+ /* ------------ */
+ /* VBAS : Class */
+ /* ------------ */
+ if (Class == 1) {
+ header->Class_Id = 0;
+ header->Class_Id = jpt_read_VBAS_info(cio, header->Class_Id);
+ }
+
+ /* ---------- */
+ /* VBAS : CSn */
+ /* ---------- */
+ if (CSn == 1) {
+ header->CSn_Id = 0;
+ header->CSn_Id = jpt_read_VBAS_info(cio, header->CSn_Id);
+ }
+
+ /* ----------------- */
+ /* VBAS : Msg_offset */
+ /* ----------------- */
+ header->Msg_offset = jpt_read_VBAS_info(cio, header->Msg_offset);
+
+ /* ----------------- */
+ /* VBAS : Msg_length */
+ /* ----------------- */
+ header->Msg_length = jpt_read_VBAS_info(cio, header->Msg_length);
+
+ /* ---------- */
+ /* VBAS : Aux */
+ /* ---------- */
+ if ((header->Class_Id & 0x01) == 1) {
+ header->Layer_nb = 0;
+ header->Layer_nb = jpt_read_VBAS_info(cio, header->Layer_nb);
+ }
+}
diff --git a/src/lib/openjp2/jpt.h b/src/lib/openjp2/jpt.h
new file mode 100644
index 00000000..eb01f98e
--- /dev/null
+++ b/src/lib/openjp2/jpt.h
@@ -0,0 +1,75 @@
+/*
+ * 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
+ * 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.
+*/
+
+/**
+Message Header JPT stream structure
+*/
+typedef struct opj_jpt_msg_header {
+ /** In-class Identifier */
+ unsigned int Id;
+ /** Last byte information */
+ unsigned int last_byte;
+ /** Class Identifier */
+ unsigned int Class_Id;
+ /** CSn : index identifier */
+ unsigned int CSn_Id;
+ /** Message offset */
+ unsigned int Msg_offset;
+ /** Message length */
+ unsigned int Msg_length;
+ /** Auxiliary for JPP case */
+ unsigned int 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 cinfo Codec context info
+@param cio CIO handle
+@param header Message header structure
+*/
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header);
+
+#endif
diff --git a/src/lib/openjp2/mct.c b/src/lib/openjp2/mct.c
new file mode 100644
index 00000000..fcc105e6
--- /dev/null
+++ b/src/lib/openjp2/mct.c
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#include "opj_includes.h"
+
+/* <summary> */
+/* This table contains the norms of the basis function of the reversible MCT. */
+/* </summary> */
+static const double mct_norms[3] = { 1.732, .8292, .8292 };
+
+/* <summary> */
+/* This table contains the norms of the basis function of the irreversible MCT. */
+/* </summary> */
+static const double 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;
+}
+
+/* <summary> */
+/* Foward reversible MCT. */
+/* </summary> */
+void mct_encode(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for(i = 0; i < n; ++i) {
+ int r = c0[i];
+ int g = c1[i];
+ int b = c2[i];
+ int y = (r + (g * 2) + b) >> 2;
+ int u = b - g;
+ int v = r - g;
+ c0[i] = y;
+ c1[i] = u;
+ c2[i] = v;
+ }
+}
+
+/* <summary> */
+/* Inverse reversible MCT. */
+/* </summary> */
+void mct_decode(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for (i = 0; i < n; ++i) {
+ int y = c0[i];
+ int u = c1[i];
+ int v = c2[i];
+ int g = y - ((u + v) >> 2);
+ int r = v + g;
+ int b = u + g;
+ c0[i] = r;
+ c1[i] = g;
+ c2[i] = b;
+ }
+}
+
+/* <summary> */
+/* Get norm of basis function of reversible MCT. */
+/* </summary> */
+double mct_getnorm(int compno) {
+ return mct_norms[compno];
+}
+
+/* <summary> */
+/* Foward irreversible MCT. */
+/* </summary> */
+void mct_encode_real(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for(i = 0; i < n; ++i) {
+ int r = c0[i];
+ int g = c1[i];
+ int b = c2[i];
+ int y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934);
+ int u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096);
+ int v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666);
+ c0[i] = y;
+ c1[i] = u;
+ c2[i] = v;
+ }
+}
+
+/* <summary> */
+/* Inverse irreversible MCT. */
+/* </summary> */
+void mct_decode_real(
+ float* restrict c0,
+ float* restrict c1,
+ float* restrict c2,
+ int n)
+{
+ int i;
+#ifdef __SSE__
+ __m128 vrv, vgu, vgv, vbu;
+ vrv = _mm_set1_ps(1.402f);
+ vgu = _mm_set1_ps(0.34413f);
+ vgv = _mm_set1_ps(0.71414f);
+ vbu = _mm_set1_ps(1.772f);
+ for (i = 0; i < (n >> 3); ++i) {
+ __m128 vy, vu, vv;
+ __m128 vr, vg, vb;
+
+ vy = _mm_load_ps(c0);
+ vu = _mm_load_ps(c1);
+ vv = _mm_load_ps(c2);
+ vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv));
+ vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv));
+ vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu));
+ _mm_store_ps(c0, vr);
+ _mm_store_ps(c1, vg);
+ _mm_store_ps(c2, vb);
+ c0 += 4;
+ c1 += 4;
+ c2 += 4;
+
+ vy = _mm_load_ps(c0);
+ vu = _mm_load_ps(c1);
+ vv = _mm_load_ps(c2);
+ vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv));
+ vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv));
+ vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu));
+ _mm_store_ps(c0, vr);
+ _mm_store_ps(c1, vg);
+ _mm_store_ps(c2, vb);
+ c0 += 4;
+ c1 += 4;
+ c2 += 4;
+ }
+ n &= 7;
+#endif
+ for(i = 0; i < n; ++i) {
+ float y = c0[i];
+ float u = c1[i];
+ float v = c2[i];
+ float r = y + (v * 1.402f);
+ float g = y - (u * 0.34413f) - (v * (0.71414f));
+ float b = y + (u * 1.772f);
+ c0[i] = r;
+ c1[i] = g;
+ c2[i] = b;
+ }
+}
+
+/* <summary> */
+/* Get norm of basis function of irreversible MCT. */
+/* </summary> */
+double mct_getnorm_real(int compno) {
+ return mct_norms_real[compno];
+}
+
+
+opj_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 OPJ_FALSE;
+ }
+
+ lCurrentMatrix = lCurrentData + pNbComp;
+
+ for (i =0;i<lNbMatCoeff;++i) {
+ lCurrentMatrix[i] = (OPJ_INT32) (*(lMct++) * lMultiplicator);
+ }
+
+ for (i = 0; i < n; ++i) {
+ lMctPtr = lCurrentMatrix;
+ for (j=0;j<pNbComp;++j) {
+ lCurrentData[j] = (*(lData[j]));
+ }
+
+ for (j=0;j<pNbComp;++j) {
+ *(lData[j]) = 0;
+ for (k=0;k<pNbComp;++k) {
+ *(lData[j]) += fix_mul(*lMctPtr, lCurrentData[k]);
+ ++lMctPtr;
+ }
+
+ ++lData[j];
+ }
+ }
+
+ opj_free(lCurrentData);
+
+ return OPJ_TRUE;
+}
+
+opj_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)
+{
+ OPJ_FLOAT32 * lMct;
+ OPJ_UINT32 i;
+ OPJ_UINT32 j;
+ OPJ_UINT32 k;
+
+ OPJ_FLOAT32 * lCurrentData = 00;
+ OPJ_FLOAT32 * lCurrentResult = 00;
+ OPJ_FLOAT32 ** lData = (OPJ_FLOAT32 **) pData;
+
+ lCurrentData = (OPJ_FLOAT32 *) opj_malloc (2 * pNbComp * sizeof(OPJ_FLOAT32));
+ if
+ (! lCurrentData)
+ {
+ return OPJ_FALSE;
+ }
+ lCurrentResult = lCurrentData + pNbComp;
+
+ for
+ (i = 0; i < n; ++i)
+ {
+ lMct = (OPJ_FLOAT32 *) pDecodingData;
+ for
+ (j=0;j<pNbComp;++j)
+ {
+ lCurrentData[j] = (OPJ_FLOAT32) (*(lData[j]));
+ }
+ for
+ (j=0;j<pNbComp;++j)
+ {
+ lCurrentResult[j] = 0;
+ for
+ (k=0;k<pNbComp;++k)
+ {
+ lCurrentResult[j] += *(lMct++) * lCurrentData[k];
+ }
+ *(lData[j]++) = (OPJ_FLOAT32) (lCurrentResult[j]);
+ }
+ }
+ opj_free(lCurrentData);
+ return OPJ_TRUE;
+}
+
+void opj_calculate_norms( OPJ_FLOAT64 * pNorms,
+ OPJ_UINT32 pNbComps,
+ OPJ_FLOAT32 * pMatrix)
+{
+ OPJ_UINT32 i,j,lIndex;
+ OPJ_FLOAT32 lCurrentValue;
+ OPJ_FLOAT64 * lNorms = (OPJ_FLOAT64 *) pNorms;
+ OPJ_FLOAT32 * lMatrix = (OPJ_FLOAT32 *) pMatrix;
+
+ for (i=0;i<pNbComps;++i) {
+ lNorms[i] = 0;
+ lIndex = i;
+
+ for (j=0;j<pNbComps;++j) {
+ lCurrentValue = lMatrix[lIndex];
+ lIndex += pNbComps;
+ lNorms[i] += lCurrentValue * lCurrentValue;
+ }
+ lNorms[i] = sqrt(lNorms[i]);
+ }
+}
diff --git a/src/lib/openjp2/mct.h b/src/lib/openjp2/mct.h
new file mode 100644
index 00000000..68107136
--- /dev/null
+++ b/src/lib/openjp2/mct.h
@@ -0,0 +1,128 @@
+/*
+ * 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 __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.
+*/
+
+/** @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(int *c0, int *c1, int *c2, int 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(int *c0, int *c1, int *c2, int 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
+*/
+double mct_getnorm(int 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(int *c0, int *c1, int *c2, int 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(float* c0, float* c1, float* c2, int 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
+*/
+double mct_getnorm_real(int compno);
+
+
+opj_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);
+
+opj_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/src/lib/openjp2/mqc.c b/src/lib/openjp2/mqc.c
new file mode 100644
index 00000000..8aeba10d
--- /dev/null
+++ b/src/lib/openjp2/mqc.c
@@ -0,0 +1,599 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.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 INLINE int mqc_mpsexchange(opj_mqc_t *const mqc);
+/**
+FIXME: documentation ???
+@param mqc MQC handle
+@return
+*/
+static INLINE int mqc_lpsexchange(opj_mqc_t *const mqc);
+/**
+Input a byte
+@param mqc MQC handle
+*/
+static INLINE void mqc_bytein(opj_mqc_t *const mqc);
+/**
+Renormalize mqc->a and mqc->c while decoding
+@param mqc MQC handle
+*/
+static INLINE void mqc_renormd(opj_mqc_t *const mqc);
+/*@}*/
+
+/*@}*/
+
+/* <summary> */
+/* This array defines all the possible states for a context. */
+/* </summary> */
+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) {
+ unsigned int tempc = mqc->c + mqc->a;
+ mqc->c |= 0xffff;
+ if (mqc->c >= tempc) {
+ mqc->c -= 0x8000;
+ }
+}
+
+static INLINE int mqc_mpsexchange(opj_mqc_t *const mqc) {
+ int 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 INLINE int mqc_lpsexchange(opj_mqc_t *const mqc) {
+ int 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;
+}
+
+#ifdef MQC_PERF_OPT
+static INLINE void mqc_bytein(opj_mqc_t *const mqc) {
+ unsigned int i = *((unsigned int *) mqc->bp);
+ mqc->c += i & 0xffff00;
+ mqc->ct = i & 0x0f;
+ mqc->bp += (i >> 2) & 0x04;
+}
+#else
+static void mqc_bytein(opj_mqc_t *const mqc) {
+ if (mqc->bp != mqc->end) {
+ unsigned int 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;
+ }
+}
+#endif
+
+static INLINE void mqc_renormd(opj_mqc_t *const 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));
+#ifdef MQC_PERF_OPT
+ mqc->buffer = NULL;
+#endif
+ return mqc;
+}
+
+void mqc_destroy(opj_mqc_t *mqc) {
+ if(mqc) {
+#ifdef MQC_PERF_OPT
+ if (mqc->buffer) { /* TODO: LH: this test is pointless as free() is a no-op on 0 */
+ opj_free(mqc->buffer);
+ }
+#endif
+ opj_free(mqc);
+ }
+}
+
+int mqc_numbytes(opj_mqc_t *mqc) {
+ return mqc->bp - mqc->start;
+}
+
+void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp) {
+ mqc_setcurctx(mqc, 0);
+ mqc->a = 0x8000;
+ mqc->c = 0;
+ mqc->bp = bp - 1;
+ mqc->ct = 12;
+ if (*mqc->bp == 0xff) {
+ mqc->ct = 13;
+ }
+ mqc->start = bp;
+}
+
+void mqc_encode(opj_mqc_t *mqc, int 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, int 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;
+ }
+}
+
+int mqc_bypass_flush_enc(opj_mqc_t *mqc) {
+ unsigned char 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);
+}
+
+int mqc_restart_enc(opj_mqc_t *mqc) {
+ int correction = 1;
+
+ /* <flush part> */
+ int 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) {
+ /* <Re-init part> */
+ 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) {
+ int 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) {
+ int i;
+ mqc_setcurctx(mqc, 18);
+
+ for (i = 1; i < 5; i++) {
+ mqc_encode(mqc, i % 2);
+ }
+}
+
+opj_bool mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int 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;
+
+#ifdef MQC_PERF_OPT
+ {
+ unsigned int c;
+ unsigned int *ip;
+ unsigned char *end = mqc->end - 1;
+ void* new_buffer = opj_realloc(mqc->buffer, (len + 1) * sizeof(unsigned int));
+ if (! new_buffer) {
+ opj_free(mqc->buffer);
+ mqc->buffer = NULL;
+ return OPJ_FALSE;
+ }
+ mqc->buffer = new_buffer;
+ ip = (unsigned int *) mqc->buffer;
+
+ while (bp < end) {
+ c = *(bp + 1);
+ if (*bp == 0xff) {
+ if (c > 0x8f) {
+ break;
+ } else {
+ *ip = 0x00000017 | (c << 9);
+ }
+ } else {
+ *ip = 0x00000018 | (c << 8);
+ }
+ bp++;
+ ip++;
+ }
+
+ /* Handle last byte of data */
+ c = 0xff;
+ if (*bp == 0xff) {
+ *ip = 0x0000ff18;
+ } else {
+ bp++;
+ *ip = 0x00000018 | (c << 8);
+ }
+ ip++;
+
+ *ip = 0x0000ff08;
+ mqc->bp = mqc->buffer;
+ }
+#endif
+ mqc_bytein(mqc);
+ mqc->c <<= 7;
+ mqc->ct -= 7;
+ mqc->a = 0x8000;
+ return OPJ_TRUE;
+}
+
+int mqc_decode(opj_mqc_t *const mqc) {
+ int 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 d;
+}
+
+void mqc_resetstates(opj_mqc_t *mqc) {
+ int i;
+ for (i = 0; i < MQC_NUMCTXS; i++) {
+ mqc->ctxs[i] = mqc_states;
+ }
+}
+
+void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob) {
+ mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)];
+}
+
+
diff --git a/src/lib/openjp2/mqc.h b/src/lib/openjp2/mqc.h
new file mode 100644
index 00000000..7984aaf8
--- /dev/null
+++ b/src/lib/openjp2/mqc.h
@@ -0,0 +1,200 @@
+/*
+ * 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 __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.
+*/
+
+/** @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) */
+ unsigned int qeval;
+ /** the Most Probable Symbol (0 or 1) */
+ int 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 19
+
+/**
+MQ coder
+*/
+typedef struct opj_mqc {
+ unsigned int c;
+ unsigned int a;
+ unsigned int ct;
+ unsigned char *bp;
+ unsigned char *start;
+ unsigned char *end;
+ opj_mqc_state_t *ctxs[MQC_NUMCTXS];
+ opj_mqc_state_t **curctx;
+#ifdef MQC_PERF_OPT
+ unsigned char *buffer;
+#endif
+} 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
+*/
+int 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, int ctxno, int msb, int 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, unsigned char *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[(int)(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, int 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.
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+*/
+void mqc_bypass_init_enc(opj_mqc_t *mqc);
+/**
+BYPASS mode switch, coding operation.
+JPEG 2000 p 505.
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+void mqc_bypass_enc(opj_mqc_t *mqc, int d);
+/**
+BYPASS mode switch, flush operation
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@return Returns 1 (always)
+*/
+int 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)
+*/
+int 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
+*/
+opj_bool mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len);
+/**
+Decode a symbol
+@param mqc MQC handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int mqc_decode(opj_mqc_t *const mqc);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MQC_H */
diff --git a/src/lib/openjp2/openjpeg.c b/src/lib/openjp2/openjpeg.c
new file mode 100644
index 00000000..8d879f21
--- /dev/null
+++ b/src/lib/openjp2/openjpeg.c
@@ -0,0 +1,1062 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#endif /* _WIN32 */
+
+#include "opj_config.h"
+#include "opj_includes.h"
+
+/**
+ * Decompression handler.
+ */
+typedef struct opj_decompression
+{
+ /** Main header reading function handler*/
+ opj_bool (*opj_read_header) ( struct opj_stream_private * cio,
+ void * p_codec,
+ opj_image_t **p_image,
+ struct opj_event_mgr * p_manager);
+ /** Decoding function */
+ opj_bool (*opj_decode) ( void * p_codec,
+ struct opj_stream_private *p_cio,
+ opj_image_t *p_image,
+ struct opj_event_mgr * p_manager);
+ /** FIXME DOC */
+ opj_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,
+ opj_bool * p_should_go_on,
+ struct opj_stream_private *p_cio,
+ struct opj_event_mgr * p_manager);
+ /** FIXME DOC */
+ opj_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);
+ /** Reading function used after codestream if necessary */
+ opj_bool (* opj_end_decompress) ( void *p_codec,
+ struct opj_stream_private *cio,
+ struct opj_event_mgr * p_manager);
+ /** Codec destroy function handler*/
+ void (*opj_destroy) (void * p_codec);
+ /** Setup decoder function handler */
+ void (*opj_setup_decoder) (void * p_codec, opj_dparameters_t * p_param);
+ /** Set decode area function handler */
+ opj_bool (*opj_set_decode_area) ( void * p_codec,
+ opj_image_t* p_image,
+ 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);
+
+ /** Get tile function */
+ opj_bool (*opj_get_decoded_tile) ( void *p_codec,
+ opj_stream_private_t *p_cio,
+ opj_image_t *p_image,
+ struct opj_event_mgr * p_manager,
+ OPJ_UINT32 tile_index);
+
+ /** Set the decoded resolution factor */
+ opj_bool (*opj_set_decoded_resolution_factor) ( void * p_codec,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager);
+
+}opj_decompression_t;
+
+/**
+ * Compression handler. FIXME DOC
+ */
+typedef struct opj_compression
+{
+ opj_bool (* opj_start_compress) ( void *p_codec,
+ struct opj_stream_private *cio,
+ struct opj_image * p_image,
+ struct opj_event_mgr * p_manager);
+
+ opj_bool (* opj_encode) ( void * p_codec,
+ struct opj_stream_private *p_cio,
+ struct opj_event_mgr * p_manager);
+
+ opj_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);
+
+ opj_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;
+
+/**
+ * Main codec handler used for compression or decompression.
+ */
+typedef struct opj_codec_private
+{
+ /** FIXME DOC */
+ union
+ {
+ opj_decompression_t m_decompression;
+ opj_compression_t m_compression;
+ } m_codec_data;
+ /** FIXME DOC*/
+ void * m_codec;
+ /** Event handler */
+ opj_event_mgr_t m_event_mgr;
+ /** Flag to indicate if the codec is used to decode or encode*/
+ opj_bool is_decompressor;
+ void (*opj_dump_codec) (void * p_codec, OPJ_INT32 info_flag, FILE* output_stream);
+ opj_codestream_info_v2_t* (*opj_get_codec_info)(void* p_codec);
+ opj_codestream_index_t* (*opj_get_codec_index)(void* p_codec);
+}
+opj_codec_private_t;
+
+/* ---------------------------------------------------------------------- */
+/* Functions to set info_handler */
+
+opj_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 OPJ_FALSE;
+ }
+
+ l_codec->m_event_mgr.info_handler = p_callback;
+ l_codec->m_event_mgr.m_info_data = p_user_data;
+
+ return OPJ_TRUE;
+}
+
+opj_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 OPJ_FALSE;
+ }
+
+ l_codec->m_event_mgr.warning_handler = p_callback;
+ l_codec->m_event_mgr.m_warning_data = p_user_data;
+
+ return OPJ_TRUE;
+}
+
+opj_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 OPJ_FALSE;
+ }
+
+ l_codec->m_event_mgr.error_handler = p_callback;
+ l_codec->m_event_mgr.m_error_data = p_user_data;
+
+ return OPJ_TRUE;
+}
+
+/* ---------------------------------------------------------------------- */
+
+OPJ_SIZE_T opj_read_from_file (void * p_buffer, OPJ_SIZE_T p_nb_bytes, FILE * p_file)
+{
+ OPJ_SIZE_T l_nb_read = fread(p_buffer,1,p_nb_bytes,p_file);
+ return l_nb_read ? l_nb_read : -1;
+}
+
+OPJ_UINT64 opj_get_data_length_from_file (FILE * p_file)
+{
+ OPJ_OFF_T file_length = 0;
+
+ OPJ_FSEEK(p_file, 0, SEEK_END);
+ file_length = (OPJ_UINT64)OPJ_FTELL(p_file);
+ OPJ_FSEEK(p_file, 0, SEEK_SET);
+
+ return file_length;
+}
+
+OPJ_SIZE_T opj_write_from_file (void * p_buffer, OPJ_SIZE_T p_nb_bytes, FILE * p_file)
+{
+ return fwrite(p_buffer,1,p_nb_bytes,p_file);
+}
+
+OPJ_OFF_T opj_skip_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data)
+{
+ if (OPJ_FSEEK(p_user_data,p_nb_bytes,SEEK_CUR)) {
+ return -1;
+ }
+
+ return p_nb_bytes;
+}
+
+opj_bool opj_seek_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data)
+{
+ if (OPJ_FSEEK(p_user_data,p_nb_bytes,SEEK_SET)) {
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/* ---------------------------------------------------------------------- */
+#ifdef _WIN32
+#ifndef OPJ_STATIC
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+
+ OPJ_ARG_NOT_USED(lpReserved);
+ OPJ_ARG_NOT_USED(hModule);
+
+ 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 PACKAGE_VERSION;
+}
+
+/* ---------------------------------------------------------------------- */
+/* DECOMPRESSION FUNCTIONS*/
+
+opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format)
+{
+ opj_codec_private_t *l_codec = 00;
+
+ l_codec = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t));
+ if (!l_codec){
+ return 00;
+ }
+ memset(l_codec, 0, sizeof(opj_codec_private_t));
+
+ l_codec->is_decompressor = 1;
+
+ switch (p_format) {
+ case CODEC_J2K:
+ l_codec->opj_dump_codec = (void (*) (void*, OPJ_INT32, FILE*)) j2k_dump;
+
+ l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*) (void*) ) j2k_get_cstr_info;
+
+ l_codec->opj_get_codec_index = (opj_codestream_index_t* (*) (void*) ) j2k_get_cstr_index;
+
+ l_codec->m_codec_data.m_decompression.opj_decode =
+ (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ opj_image_t*, struct opj_event_mgr * )) opj_j2k_decode;
+
+ l_codec->m_codec_data.m_decompression.opj_end_decompress =
+ (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_j2k_end_decompress;
+
+ l_codec->m_codec_data.m_decompression.opj_read_header =
+ (opj_bool (*) ( struct opj_stream_private *,
+ void *,
+ opj_image_t **,
+ struct opj_event_mgr * )) opj_j2k_read_header;
+
+ l_codec->m_codec_data.m_decompression.opj_destroy =
+ (void (*) (void *))opj_j2k_destroy;
+
+ l_codec->m_codec_data.m_decompression.opj_setup_decoder =
+ (void (*) (void * , opj_dparameters_t * )) opj_j2k_setup_decoder;
+
+ l_codec->m_codec_data.m_decompression.opj_read_tile_header =
+ (opj_bool (*) ( void *,
+ OPJ_UINT32*,
+ OPJ_UINT32*,
+ OPJ_INT32*, OPJ_INT32*,
+ OPJ_INT32*, OPJ_INT32*,
+ OPJ_UINT32*,
+ opj_bool*,
+ struct opj_stream_private *,
+ struct opj_event_mgr * )) opj_j2k_read_tile_header;
+
+ l_codec->m_codec_data.m_decompression.opj_decode_tile_data =
+ (opj_bool (*) ( void *,
+ OPJ_UINT32,
+ OPJ_BYTE*,
+ OPJ_UINT32,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_j2k_decode_tile;
+
+ l_codec->m_codec_data.m_decompression.opj_set_decode_area =
+ (opj_bool (*) ( void *,
+ opj_image_t*,
+ OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32,
+ struct opj_event_mgr *)) opj_j2k_set_decode_area;
+
+ l_codec->m_codec_data.m_decompression.opj_get_decoded_tile =
+ (opj_bool (*) ( void *p_codec,
+ opj_stream_private_t *p_cio,
+ opj_image_t *p_image,
+ struct opj_event_mgr * p_manager,
+ OPJ_UINT32 tile_index)) opj_j2k_get_tile;
+
+ l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor =
+ (opj_bool (*) ( void * p_codec,
+ OPJ_UINT32 res_factor,
+ struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_resolution_factor;
+
+ l_codec->m_codec = opj_j2k_create_decompress();
+
+ if (! l_codec->m_codec) {
+ opj_free(l_codec);
+ return NULL;
+ }
+
+ break;
+
+ case CODEC_JP2:
+ /* get a JP2 decoder handle */
+ l_codec->opj_dump_codec = (void (*) (void*, OPJ_INT32, FILE*)) jp2_dump;
+
+ l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*) (void*) ) jp2_get_cstr_info;
+
+ l_codec->opj_get_codec_index = (opj_codestream_index_t* (*) (void*) ) jp2_get_cstr_index;
+
+ l_codec->m_codec_data.m_decompression.opj_decode =
+ (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ opj_image_t*,
+ struct opj_event_mgr * )) opj_jp2_decode;
+
+ l_codec->m_codec_data.m_decompression.opj_end_decompress =
+ (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_jp2_end_decompress;
+
+ l_codec->m_codec_data.m_decompression.opj_read_header =
+ (opj_bool (*) ( struct opj_stream_private *,
+ void *,
+ opj_image_t **,
+ struct opj_event_mgr * )) opj_jp2_read_header;
+
+ l_codec->m_codec_data.m_decompression.opj_read_tile_header =
+ (opj_bool (*) ( void *,
+ OPJ_UINT32*,
+ OPJ_UINT32*,
+ OPJ_INT32*,
+ OPJ_INT32*,
+ OPJ_INT32 * ,
+ OPJ_INT32 * ,
+ OPJ_UINT32 * ,
+ opj_bool *,
+ struct opj_stream_private *,
+ struct opj_event_mgr * )) opj_jp2_read_tile_header;
+
+ l_codec->m_codec_data.m_decompression.opj_decode_tile_data =
+ (opj_bool (*) ( void *,
+ OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,
+ struct opj_stream_private *,
+ struct opj_event_mgr * )) opj_jp2_decode_tile;
+
+ l_codec->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))opj_jp2_destroy;
+
+ l_codec->m_codec_data.m_decompression.opj_setup_decoder =
+ (void (*) (void * ,opj_dparameters_t * )) opj_jp2_setup_decoder;
+
+ l_codec->m_codec_data.m_decompression.opj_set_decode_area =
+ (opj_bool (*) ( void *,
+ opj_image_t*,
+ OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32,
+ struct opj_event_mgr * )) opj_jp2_set_decode_area;
+
+ l_codec->m_codec_data.m_decompression.opj_get_decoded_tile =
+ (opj_bool (*) ( void *p_codec,
+ opj_stream_private_t *p_cio,
+ opj_image_t *p_image,
+ struct opj_event_mgr * p_manager,
+ OPJ_UINT32 tile_index)) opj_jp2_get_tile;
+
+ l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor =
+ (opj_bool (*) ( void * p_codec,
+ OPJ_UINT32 res_factor,
+ opj_event_mgr_t * p_manager)) opj_jp2_set_decoded_resolution_factor;
+
+ l_codec->m_codec = opj_jp2_create(OPJ_TRUE);
+
+ if (! l_codec->m_codec) {
+ opj_free(l_codec);
+ return 00;
+ }
+
+ break;
+ case CODEC_UNKNOWN:
+ case CODEC_JPT:
+ default:
+ opj_free(l_codec);
+ return 00;
+ }
+
+ opj_set_default_event_handler(&(l_codec->m_event_mgr));
+ return (opj_codec_t*) l_codec;
+}
+
+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->cp_limit_decoding = NO_LIMITATION;
+
+ parameters->decod_format = -1;
+ parameters->cod_format = -1;
+ parameters->flags = 0;
+/* UniPG>> */
+#ifdef USE_JPWL
+ parameters->jpwl_correct = OPJ_FALSE;
+ parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS;
+ parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES;
+#endif /* USE_JPWL */
+/* <<UniPG */
+ }
+}
+
+opj_bool OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
+ opj_dparameters_t *parameters
+ )
+{
+ if (p_codec && parameters) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+
+ if (! l_codec->is_decompressor) {
+ opj_event_msg_v2(&(l_codec->m_event_mgr), EVT_ERROR,
+ "Codec provided to the opj_setup_decoder function is not a decompressor handler.\n");
+ return OPJ_FALSE;
+ }
+
+ l_codec->m_codec_data.m_decompression.opj_setup_decoder(l_codec->m_codec,
+ parameters);
+ return OPJ_TRUE;
+ }
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_read_header ( opj_stream_t *p_stream,
+ opj_codec_t *p_codec,
+ opj_image_t **p_image )
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec;
+ opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
+
+ if(! l_codec->is_decompressor) {
+ opj_event_msg_v2(&(l_codec->m_event_mgr), EVT_ERROR,
+ "Codec provided to the opj_read_header function is not a decompressor handler.\n");
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_read_header( l_stream,
+ l_codec->m_codec,
+ p_image,
+ &(l_codec->m_event_mgr) );
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_decode( opj_codec_t *p_codec,
+ opj_stream_t *p_stream,
+ opj_image_t* p_image)
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_decode(l_codec->m_codec,
+ l_stream,
+ p_image,
+ &(l_codec->m_event_mgr) );
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec,
+ opj_image_t* p_image,
+ 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_codec = (opj_codec_private_t *) p_codec;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_set_decode_area( l_codec->m_codec,
+ p_image,
+ p_start_x, p_start_y,
+ p_end_x, p_end_y,
+ &(l_codec->m_event_mgr) );
+ }
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_read_tile_header( opj_codec_t *p_codec,
+ opj_stream_t * p_stream,
+ 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,
+ opj_bool * p_should_go_on)
+{
+ if (p_codec && p_stream && p_data_size && p_tile_index) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_read_tile_header( l_codec->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_stream,
+ &(l_codec->m_event_mgr));
+ }
+ return OPJ_FALSE;
+}
+
+opj_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
+ )
+{
+ if (p_codec && p_data && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_decode_tile_data( l_codec->m_codec,
+ p_tile_index,
+ p_data,
+ p_data_size,
+ l_stream,
+ &(l_codec->m_event_mgr) );
+ }
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec,
+ opj_stream_t *p_stream,
+ opj_image_t *p_image,
+ OPJ_UINT32 tile_index)
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_get_decoded_tile( l_codec->m_codec,
+ l_stream,
+ p_image,
+ &(l_codec->m_event_mgr),
+ tile_index);
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec,
+ OPJ_UINT32 res_factor )
+{
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+
+ if ( !l_codec ){
+ fprintf(stderr, "[ERROR] Input parameters of the setup_decoder function are incorrect.\n");
+ return OPJ_FALSE;
+ }
+
+ l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor(l_codec->m_codec,
+ res_factor,
+ &(l_codec->m_event_mgr) );
+ return OPJ_TRUE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* COMPRESSION FUNCTIONS*/
+
+opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format)
+{
+ opj_codec_private_t *l_codec = 00;
+
+ l_codec = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t));
+ if (!l_codec) {
+ return 00;
+ }
+ memset(l_codec, 0, sizeof(opj_codec_private_t));
+
+ l_codec->is_decompressor = 0;
+
+ switch(p_format) {
+ case CODEC_J2K:
+ l_codec->m_codec_data.m_compression.opj_encode = (opj_bool (*) (void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr * )) opj_j2k_encode_v2;
+
+ l_codec->m_codec_data.m_compression.opj_end_compress = (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_j2k_end_compress;
+
+ l_codec->m_codec_data.m_compression.opj_start_compress = (opj_bool (*) (void *,
+ struct opj_stream_private *,
+ struct opj_image * ,
+ struct opj_event_mgr *)) opj_j2k_start_compress;
+
+ l_codec->m_codec_data.m_compression.opj_write_tile = (opj_bool (*) (void *,
+ OPJ_UINT32,
+ OPJ_BYTE*,
+ OPJ_UINT32,
+ struct opj_stream_private *,
+ struct opj_event_mgr *) ) opj_j2k_write_tile;
+
+ l_codec->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) opj_j2k_destroy;
+
+ l_codec->m_codec_data.m_compression.opj_setup_encoder = (void (*) ( void *,
+ opj_cparameters_t *,
+ struct opj_image *,
+ struct opj_event_mgr * )) opj_j2k_setup_encoder;
+
+ l_codec->m_codec = opj_j2k_create_compress();
+ if (! l_codec->m_codec) {
+ opj_free(l_codec);
+ return 00;
+ }
+
+ break;
+
+ case CODEC_JP2:
+ /* get a JP2 decoder handle */
+ l_codec->m_codec_data.m_compression.opj_encode = (opj_bool (*) (void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr * )) opj_jp2_encode;
+
+ l_codec->m_codec_data.m_compression.opj_end_compress = (opj_bool (*) ( void *,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_jp2_end_compress;
+
+ l_codec->m_codec_data.m_compression.opj_start_compress = (opj_bool (*) (void *,
+ struct opj_stream_private *,
+ struct opj_image * ,
+ struct opj_event_mgr *)) opj_jp2_start_compress;
+
+ l_codec->m_codec_data.m_compression.opj_write_tile = (opj_bool (*) (void *,
+ OPJ_UINT32,
+ OPJ_BYTE*,
+ OPJ_UINT32,
+ struct opj_stream_private *,
+ struct opj_event_mgr *)) opj_jp2_write_tile;
+
+ l_codec->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) opj_jp2_destroy;
+
+ l_codec->m_codec_data.m_compression.opj_setup_encoder = (void (*) ( void *,
+ opj_cparameters_t *,
+ struct opj_image *,
+ struct opj_event_mgr * )) opj_jp2_setup_encoder;
+
+ l_codec->m_codec = opj_jp2_create(OPJ_FALSE);
+ if (! l_codec->m_codec) {
+ opj_free(l_codec);
+ return 00;
+ }
+
+ break;
+
+ case CODEC_UNKNOWN:
+ case CODEC_JPT:
+ default:
+ opj_free(l_codec);
+ return 00;
+ }
+
+ opj_set_default_event_handler(&(l_codec->m_event_mgr));
+ return (opj_codec_t*) l_codec;
+}
+
+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;
+ parameters->tcp_rates[0] = 0;
+ parameters->tcp_numlayers = 0;
+ parameters->cp_disto_alloc = 0;
+ parameters->cp_fixed_alloc = 0;
+ parameters->cp_fixed_quality = 0;
+ parameters->jpip_on = OPJ_FALSE;
+/* UniPG>> */
+#ifdef USE_JPWL
+ parameters->jpwl_epc_on = OPJ_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 */
+/* <<UniPG */
+ }
+}
+
+opj_bool OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
+ opj_cparameters_t *parameters,
+ opj_image_t *p_image)
+{
+ if (p_codec && parameters && p_image) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+
+ if (! l_codec->is_decompressor) {
+ l_codec->m_codec_data.m_compression.opj_setup_encoder( l_codec->m_codec,
+ parameters,
+ p_image,
+ &(l_codec->m_event_mgr) );
+ return OPJ_TRUE;
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_start_compress ( opj_codec_t *p_codec,
+ opj_image_t * p_image,
+ opj_stream_t *p_stream)
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return l_codec->m_codec_data.m_compression.opj_start_compress( l_codec->m_codec,
+ l_stream,
+ p_image,
+ &(l_codec->m_event_mgr));
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_encode(opj_codec_t *p_info, opj_stream_t *p_stream)
+{
+ if (p_info && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ l_codec->m_codec_data.m_compression.opj_encode( l_codec->m_codec,
+ l_stream,
+ &(l_codec->m_event_mgr));
+ return OPJ_TRUE;
+ }
+ }
+
+ return OPJ_FALSE;
+
+}
+
+opj_bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,
+ opj_stream_t *p_stream)
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec,
+ l_stream,
+ &(l_codec->m_event_mgr));
+ }
+ }
+ return OPJ_FALSE;
+
+}
+
+opj_bool OPJ_CALLCONV opj_end_decompress ( opj_codec_t *p_codec,
+ opj_stream_t *p_stream)
+{
+ if (p_codec && p_stream) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (! l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_decompression.opj_end_decompress(l_codec->m_codec,
+ l_stream,
+ &(l_codec->m_event_mgr) );
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV 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 */
+ int rsiz = (int)parameters->cp_rsiz | (int)MCT;
+ parameters->cp_rsiz = (OPJ_RSIZ_CAPABILITIES)rsiz;
+ 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 OPJ_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 OPJ_TRUE;
+}
+
+opj_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 )
+{
+ if (p_codec && p_stream && p_data) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+ opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream;
+
+ if (l_codec->is_decompressor) {
+ return OPJ_FALSE;
+ }
+
+ return l_codec->m_codec_data.m_compression.opj_write_tile( l_codec->m_codec,
+ p_tile_index,
+ p_data,
+ p_data_size,
+ l_stream,
+ &(l_codec->m_event_mgr) );
+ }
+
+ return OPJ_FALSE;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_codec)
+{
+ if (p_codec) {
+ opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+
+ if (l_codec->is_decompressor) {
+ l_codec->m_codec_data.m_decompression.opj_destroy(l_codec->m_codec);
+ }
+ else {
+ l_codec->m_codec_data.m_compression.opj_destroy(l_codec->m_codec);
+ }
+
+ l_codec->m_codec = 00;
+ opj_free(l_codec);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+void OPJ_CALLCONV opj_dump_codec( opj_codec_t *p_codec,
+ OPJ_INT32 info_flag,
+ FILE* output_stream)
+{
+ if (p_codec) {
+ opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec;
+
+ l_codec->opj_dump_codec(l_codec->m_codec, info_flag, output_stream);
+ return;
+ }
+
+ fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n");
+ return;
+}
+
+opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info(opj_codec_t *p_codec)
+{
+ if (p_codec) {
+ opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec;
+
+ return l_codec->opj_get_codec_info(l_codec->m_codec);
+ }
+
+ return NULL;
+}
+
+void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t **cstr_info) {
+ if (cstr_info) {
+
+ if ((*cstr_info)->m_default_tile_info.tccp_info){
+ opj_free((*cstr_info)->m_default_tile_info.tccp_info);
+ }
+
+ if ((*cstr_info)->tile_info){
+ /* FIXME not used for the moment*/
+ }
+
+ opj_free((*cstr_info));
+ (*cstr_info) = NULL;
+ }
+}
+
+opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index(opj_codec_t *p_codec)
+{
+ if (p_codec) {
+ opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec;
+
+ return l_codec->opj_get_codec_index(l_codec->m_codec);
+ }
+
+ return NULL;
+}
+
+void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index)
+{
+ if (*p_cstr_index){
+ j2k_destroy_cstr_index(*p_cstr_index);
+ (*p_cstr_index) = NULL;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (FILE * p_file, opj_bool p_is_read_stream)
+{
+ return opj_stream_create_file_stream(p_file,J2K_STREAM_CHUNK_SIZE,p_is_read_stream);
+}
+
+opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream ( FILE * p_file,
+ OPJ_SIZE_T p_size,
+ opj_bool p_is_read_stream)
+{
+ opj_stream_t* l_stream = 00;
+
+ if (! p_file) {
+ return NULL;
+ }
+
+ l_stream = opj_stream_create(p_size,p_is_read_stream);
+ if (! l_stream) {
+ return NULL;
+ }
+
+ opj_stream_set_user_data(l_stream, p_file);
+ opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file));
+ opj_stream_set_read_function(l_stream, (opj_stream_read_fn) opj_read_from_file);
+ opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_file);
+ opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_file);
+ opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_file);
+
+ return l_stream;
+}
diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h
new file mode 100644
index 00000000..de1576ff
--- /dev/null
+++ b/src/lib/openjp2/openjpeg.h
@@ -0,0 +1,1546 @@
+ /*
+ * 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 <jerome.fimes@c-s.fr>
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Mickael Savinaud, Communications & Systemes <mickael.savinaud@c-s.fr>
+ * 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
+
+
+/*
+==========================================================
+ Compiler directives
+==========================================================
+*/
+
+/* deprecated attribute */
+#ifdef __GNUC__
+ #define DEPRECATED(func) func __attribute__ ((deprecated))
+#elif defined(_MSC_VER)
+ #define DEPRECATED(func) __declspec(deprecated) func
+#else
+ #pragma message("WARNING: You need to implement DEPRECATED for this compiler")
+ #define DEPRECATED(func) func
+#endif
+
+#if defined(OPJ_STATIC) || !defined(_WIN32)
+/* http://gcc.gnu.org/wiki/Visibility */
+#if __GNUC__ >= 4
+#define OPJ_API __attribute__ ((visibility ("default")))
+#define OPJ_LOCAL __attribute__ ((visibility ("hidden")))
+#else
+#define OPJ_API
+#define OPJ_LOCAL
+#endif
+#define OPJ_CALLCONV
+#else
+#define OPJ_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 OPJ_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
+OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
+defined with this macro as being exported.
+*/
+#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT)
+#define OPJ_API __declspec(dllexport)
+#else
+#define OPJ_API __declspec(dllimport)
+#endif /* OPJ_EXPORTS */
+#endif /* !OPJ_STATIC || !_WIN32 */
+
+typedef int opj_bool; /*FIXME it should be to follow the name of others OPJ_TYPE -> OPJ_BOOL*/
+#define OPJ_TRUE 1
+#define OPJ_FALSE 0
+
+typedef char OPJ_CHAR;
+typedef float OPJ_FLOAT32;
+typedef double OPJ_FLOAT64;
+typedef unsigned char OPJ_BYTE;
+
+#include "opj_stdint.h"
+
+typedef int8_t OPJ_INT8;
+typedef uint8_t OPJ_UINT8;
+typedef int16_t OPJ_INT16;
+typedef uint16_t OPJ_UINT16;
+typedef int32_t OPJ_INT32;
+typedef uint32_t OPJ_UINT32;
+typedef int64_t OPJ_INT64;
+typedef uint64_t OPJ_UINT64;
+
+/* Avoid compile-time warning because parameter is not used */
+#define OPJ_ARG_NOT_USED(x) (void)(x)
+
+/*
+==========================================================
+ 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 */
+/* <<UniPG */
+
+/**
+ * FIXME EXPERIMENTAL FOR THE MOMENT
+ * Supported options about file information
+*/
+#define OPJ_IMG_INFO 1 /**< Basic image information provided to the user */
+#define OPJ_J2K_MH_INFO 2 /**< Codestream information based only on the main header */
+#define OPJ_J2K_TH_INFO 4 /**< Tile information based on the current tile header */
+/*FIXME #define OPJ_J2K_CSTR_INFO 6*/ /**< */
+#define OPJ_J2K_MH_IND 16 /**< Codestream index based only on the main header */
+#define OPJ_J2K_TH_IND 32 /**< Tile index based on the current tile */
+/*FIXME #define OPJ_J2K_CSTR_IND 48*/ /**< */
+#define OPJ_JP2_INFO 128 /**< JP2 file information */
+#define OPJ_JP2_IND 256 /**< JP2 file index */
+
+
+/*
+==========================================================
+ enum definitions
+==========================================================
+*/
+/**
+ * Rsiz Capabilities
+ * */
+typedef enum RSIZ_CAPABILITIES {
+ STD_RSIZ = 0, /** Standard JPEG2000 profile*/
+ CINEMA2K = 3, /** Profile name for a 2K image*/
+ CINEMA4K = 4, /** Profile name for a 4K image*/
+ MCT = 0x8100
+} OPJ_RSIZ_CAPABILITIES;
+
+/**
+ * Digital cinema operation mode
+ * */
+typedef enum CINEMA_MODE {
+ OFF = 0, /** Not Digital Cinema*/
+ CINEMA2K_24 = 1, /** 2K Digital Cinema at 24 fps*/
+ CINEMA2K_48 = 2, /** 2K Digital Cinema at 48 fps*/
+ CINEMA4K_24 = 3 /** 4K Digital Cinema at 24 fps*/
+}OPJ_CINEMA_MODE;
+
+/**
+ * Progression order
+ * */
+typedef enum PROG_ORDER {
+ PROG_UNKNOWN = -1, /**< place-holder */
+ LRCP = 0, /**< layer-resolution-component-precinct order */
+ RLCP = 1, /**< resolution-layer-component-precinct order */
+ RPCL = 2, /**< resolution-precinct-component-layer order */
+ PCRL = 3, /**< precinct-component-resolution-layer order */
+ CPRL = 4 /**< component-precinct-resolution-layer order */
+} OPJ_PROG_ORDER;
+
+/**
+ * Supported image color spaces
+*/
+typedef enum COLOR_SPACE {
+ CLRSPC_UNKNOWN = -1, /**< not supported by the library */
+ CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */
+ CLRSPC_SRGB = 1, /**< sRGB */
+ CLRSPC_GRAY = 2, /**< grayscale */
+ CLRSPC_SYCC = 3 /**< YUV */
+} OPJ_COLOR_SPACE;
+
+/**
+ * Supported codec
+*/
+typedef enum CODEC_FORMAT {
+ CODEC_UNKNOWN = -1, /**< place-holder */
+ CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */
+ CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */
+ CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */
+} OPJ_CODEC_FORMAT;
+
+/**
+ * Limit decoding to certain portions of the codestream.
+*/
+typedef enum LIMIT_DECODING {
+ NO_LIMITATION = 0, /**< No limitation for the decoding. The entire codestream will de decoded */
+ LIMIT_TO_MAIN_HEADER = 1, /**< The decoding is limited to the Main Header */
+ DECODE_ALL_BUT_PACKETS = 2 /**< Decode everything except the JPEG 2000 packets */
+} OPJ_LIMIT_DECODING;
+
+
+/*
+==========================================================
+ event manager typedef definitions
+==========================================================
+*/
+
+/**
+ * Callback function prototype for events
+ * @param msg Event message
+ * @param client_data
+ * */
+typedef void (*opj_msg_callback) (const char *msg, void *client_data);
+
+
+
+/** SHOULD BE MOVE IN EVET.H when we remove old functions TODO MSD
+Message handler object
+used for
+<ul>
+<li>Error messages
+<li>Warning messages
+<li>Debugging messages
+</ul>
+*/
+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;
+
+/*
+==========================================================
+ codec typedef definitions
+==========================================================
+*/
+
+/**
+ * Progression order changes
+ *
+ */
+typedef struct opj_poc {
+ /** Resolution num start, Component num start, given by POC */
+ OPJ_UINT32 resno0, compno0;
+ /** Layer num end,Resolution num end, Component num end, given by POC */
+ OPJ_UINT32 layno1, resno1, compno1;
+ /** Layer num start,Precinct num start, Precinct num end */
+ int layno0, precno0, precno1;
+ /** Progression order enum*/
+ OPJ_PROG_ORDER prg1,prg;
+ /** Progression order string*/
+ char progorder[5];
+ /** Tile number */
+ int tile;
+ /** Start and end values for Tile width and height*/
+ int tx0,tx1,ty0,ty1;
+ /** Start value, initialised in pi_initialise_encode*/
+ int layS, resS, compS, prcS;
+ /** End value, initialised in pi_initialise_encode */
+ int layE, resE, compE, prcE;
+ /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/
+ int txS,txE,tyS,tyE,dx,dy;
+ /** Temporary values for Tile parts, initialised in pi_create_encode */
+ int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t;
+} opj_poc_t;
+
+/**
+ * Compression parameters
+ * */
+typedef struct opj_cparameters {
+ /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */
+ opj_bool tile_size_on;
+ /** XTOsiz */
+ int cp_tx0;
+ /** YTOsiz */
+ int cp_ty0;
+ /** XTsiz */
+ int cp_tdx;
+ /** YTsiz */
+ int cp_tdy;
+ /** allocation by rate/distortion */
+ int cp_disto_alloc;
+ /** allocation by fixed layer */
+ int cp_fixed_alloc;
+ /** add fixed_quality */
+ int cp_fixed_quality;
+ /** fixed layer */
+ int *cp_matrice;
+ /** comment for coding */
+ char *cp_comment;
+ /** csty : coding style */
+ int csty;
+ /** progression order (default LRCP) */
+ OPJ_PROG_ORDER prog_order;
+ /** progression order changes */
+ opj_poc_t POC[32];
+ /** number of progression order changes (POC), default to 0 */
+ int numpocs;
+ /** number of layers */
+ int tcp_numlayers;
+ /** rates of layers */
+ float tcp_rates[100];
+ /** different psnr for successive layers */
+ float tcp_distoratio[100];
+ /** number of resolutions */
+ int numresolution;
+ /** initial code block width, default to 64 */
+ int cblockw_init;
+ /** initial code block height, default to 64 */
+ int cblockh_init;
+ /** mode switch (cblk_style) */
+ int mode;
+ /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */
+ int irreversible;
+ /** region of interest: affected component in [0..3], -1 means no ROI */
+ int roi_compno;
+ /** region of interest: upshift value */
+ int roi_shift;
+ /* number of precinct size specifications */
+ int res_spec;
+ /** initial precinct width */
+ int prcw_init[J2K_MAXRLVLS];
+ /** initial precinct height */
+ int prch_init[J2K_MAXRLVLS];
+
+ /**@name command line encoder parameters (not used inside the library) */
+ /*@{*/
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */
+ int index_on;
+ /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */
+ char index[OPJ_PATH_LEN];
+ /** subimage encoding: origin image offset in x direction */
+ int image_offset_x0;
+ /** subimage encoding: origin image offset in y direction */
+ int image_offset_y0;
+ /** subsampling value for dx */
+ int subsampling_dx;
+ /** subsampling value for dy */
+ int subsampling_dy;
+ /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/
+ int decod_format;
+ /** output file format 0: J2K, 1: JP2, 2: JPT */
+ int cod_format;
+ /*@}*/
+
+/* UniPG>> */
+ /**@name JPWL encoding parameters */
+ /*@{*/
+ /** enables writing of EPC in MH, thus activating JPWL */
+ opj_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];
+ /*@}*/
+/* <<UniPG */
+
+ /** Digital Cinema compliance 0-not compliant, 1-compliant*/
+ OPJ_CINEMA_MODE cp_cinema;
+ /** Maximum rate for each component. If == 0, component size limitation is not considered */
+ int max_comp_size;
+ /** Profile name*/
+ OPJ_RSIZ_CAPABILITIES cp_rsiz;
+ /** Tile part generation*/
+ char tp_on;
+ /** Flag for Tile part generation*/
+ char tp_flag;
+ /** MCT (multiple component transform) */
+ char tcp_mct;
+ /** Enable JPIP indexing*/
+ opj_bool jpip_on;
+ /** Naive implementation of MCT restricted to a single reversible array based encoding without offset concerning all the components. */
+ void * mct_data;
+
+} opj_cparameters_t;
+
+#define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG 0x0001
+
+/**
+ * Decompression parameters
+ * */
+typedef struct opj_dparameters {
+ /**
+ Set the number of highest resolution levels to be discarded.
+ The image resolution is effectively divided by 2 to the power of the number of discarded levels.
+ The reduce factor is limited by the smallest total number of decomposition levels among tiles.
+ if != 0, then original dimension divided by 2^(reduce);
+ if == 0 or not used, image is decoded to the full resolution
+ */
+ int cp_reduce;
+ /**
+ Set the maximum number of quality layers to decode.
+ If there are less quality layers than the specified number, all the quality layers are decoded.
+ if != 0, then only the first "layer" layers are decoded;
+ if == 0 or not used, all the quality layers are decoded
+ */
+ int cp_layer;
+
+ /**@name command line decoder parameters (not used inside the library) */
+ /*@{*/
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** input file format 0: J2K, 1: JP2, 2: JPT */
+ int decod_format;
+ /** output file format 0: PGX, 1: PxM, 2: BMP */
+ int cod_format;
+
+ /** Decoding area left boundary */
+ OPJ_UINT32 DA_x0;
+ /** Decoding area right boundary */
+ OPJ_UINT32 DA_x1;
+ /** Decoding area up boundary */
+ OPJ_UINT32 DA_y0;
+ /** Decoding area bottom boundary */
+ OPJ_UINT32 DA_y1;
+ /** Verbose mode */
+ opj_bool m_verbose;
+
+ /** tile number ot the decoded tile*/
+ OPJ_UINT32 tile_index;
+ /** Nb of tile to decode */
+ OPJ_UINT32 nb_tile_to_decode;
+
+ /*@}*/
+
+/* UniPG>> */
+ /**@name JPWL decoding parameters */
+ /*@{*/
+ /** activates the JPWL correction capabilities */
+ opj_bool jpwl_correct;
+ /** expected number of components */
+ int jpwl_exp_comps;
+ /** maximum number of tiles */
+ int jpwl_max_tiles;
+ /*@}*/
+/* <<UniPG */
+
+ /**
+ Specify whether the decoding should be done on the entire codestream, or be limited to the main header
+ Limiting the decoding to the main header makes it possible to extract the characteristics of the codestream
+ if == NO_LIMITATION, the entire codestream is decoded;
+ if == LIMIT_TO_MAIN_HEADER, only the main header is decoded;
+ */
+ OPJ_LIMIT_DECODING cp_limit_decoding;
+
+ unsigned int flags;
+} opj_dparameters_t;
+
+
+/* ---> FIXME V1 style */
+/** Common fields between JPEG-2000 compression and decompression master structs. */
+
+#define opj_common_fields \
+ opj_event_mgr_t *event_mgr; /**< pointer to the event manager */\
+ void * client_data; /**< Available for use by application */\
+ opj_bool is_decompressor; /**< So common code can tell which is which */\
+ OPJ_CODEC_FORMAT codec_format; /**< selected codec */\
+ void *j2k_handle; /**< pointer to the J2K codec */\
+ void *jp2_handle; /**< pointer to the JP2 codec */\
+ void *mj2_handle /**< pointer to the MJ2 codec */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure. There are no actual instances of
+ * opj_common_struct_t, only of opj_cinfo_t and opj_dinfo_t.
+ */
+typedef struct opj_common_struct {
+ opj_common_fields; /* Fields common to both master struct types */
+ /* Additional fields follow in an actual opj_cinfo_t or
+ * opj_dinfo_t. All three structs must agree on these
+ * initial fields! (This would be a lot cleaner in C++.)
+ */
+} opj_common_struct_t;
+
+typedef opj_common_struct_t * opj_common_ptr;
+
+/**
+ * Compression context info
+ * */
+typedef struct opj_cinfo {
+ /** Fields shared with opj_dinfo_t */
+ opj_common_fields;
+ /* other specific fields go here */
+} opj_cinfo_t;
+
+/**
+ * Decompression context info
+ * */
+typedef struct opj_dinfo {
+ /** Fields shared with opj_cinfo_t */
+ opj_common_fields;
+ /* other specific fields go here */
+} opj_dinfo_t;
+
+/* <--- V1 style */
+
+/**
+ * JPEG2000 codec V2.
+ * */
+typedef void * opj_codec_t;
+
+/*
+==========================================================
+ I/O stream typedef definitions
+==========================================================
+*/
+
+/*
+ * Stream open flags.
+ */
+/** The stream was opened for reading. */
+#define OPJ_STREAM_READ 0x0001
+/** The stream was opened for writing. */
+#define OPJ_STREAM_WRITE 0x0002
+
+/**
+Byte input-output stream (CIO)
+DEPRECATED
+*/
+typedef struct opj_cio {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** open mode (read/write) either OPJ_STREAM_READ or OPJ_STREAM_WRITE */
+ int openmode;
+ /** pointer to the start of the buffer */
+ unsigned char *buffer;
+ /** buffer size in bytes */
+ /* FIXME: MM length is 'int' ?? */
+ int length;
+
+ /** pointer to the start of the stream */
+ unsigned char *start;
+ /** pointer to the end of the stream */
+ unsigned char *end;
+ /** pointer to the current position */
+ unsigned char *bp;
+} opj_cio_t;
+
+
+/*
+ * FIXME DOC
+ */
+typedef OPJ_SIZE_T (* opj_stream_read_fn) (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) ;
+typedef OPJ_SIZE_T (* opj_stream_write_fn) (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) ;
+typedef OPJ_OFF_T (* opj_stream_skip_fn) (OPJ_OFF_T p_nb_bytes, void * p_user_data) ;
+typedef opj_bool (* opj_stream_seek_fn) (OPJ_OFF_T p_nb_bytes, void * p_user_data) ;
+
+/*
+ * JPEG2000 Stream.
+ */
+typedef void * opj_stream_t;
+
+/*
+==========================================================
+ image typedef definitions
+==========================================================
+*/
+
+/**
+ * Defines a single image component
+ * */
+typedef struct opj_image_comp {
+ /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+ OPJ_UINT32 dx;
+ /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+ OPJ_UINT32 dy;
+ /** data width */
+ OPJ_UINT32 w;
+ /** data height */
+ OPJ_UINT32 h;
+ /** x component offset compared to the whole image */
+ OPJ_UINT32 x0;
+ /** y component offset compared to the whole image */
+ OPJ_UINT32 y0;
+ /** precision */
+ OPJ_UINT32 prec;
+ /** image depth in bits */
+ OPJ_UINT32 bpp;
+ /** signed (1) / unsigned (0) */
+ OPJ_UINT32 sgnd;
+ /** number of decoded resolution */
+ OPJ_UINT32 resno_decoded;
+ /** number of division by 2 of the out image compared to the original size of image */
+ OPJ_UINT32 factor;
+ /** image component data */
+ OPJ_INT32 *data;
+} opj_image_comp_t;
+
+/**
+ * Defines image data and characteristics
+ * */
+typedef struct opj_image {
+ /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */
+ OPJ_UINT32 x0;
+ /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */
+ OPJ_UINT32 y0;
+ /** Xsiz: width of the reference grid */
+ OPJ_UINT32 x1;
+ /** Ysiz: height of the reference grid */
+ OPJ_UINT32 y1;
+ /** number of components in the image */
+ OPJ_UINT32 numcomps;
+ /** color space: sRGB, Greyscale or YUV */
+ OPJ_COLOR_SPACE color_space;
+ /** image components */
+ opj_image_comp_t *comps;
+ /** 'restricted' ICC profile */
+ OPJ_BYTE *icc_profile_buf;
+ /** size of ICC profile */
+ OPJ_UINT32 icc_profile_len;
+} opj_image_t;
+
+
+/**
+ * Component parameters structure used by the opj_image_create function
+ * */
+typedef struct opj_image_comptparm {
+ /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+ OPJ_UINT32 dx;
+ /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+ OPJ_UINT32 dy;
+ /** data width */
+ OPJ_UINT32 w;
+ /** data height */
+ OPJ_UINT32 h;
+ /** x component offset compared to the whole image */
+ OPJ_UINT32 x0;
+ /** y component offset compared to the whole image */
+ OPJ_UINT32 y0;
+ /** precision */
+ OPJ_UINT32 prec;
+ /** image depth in bits */
+ OPJ_UINT32 bpp;
+ /** signed (1) / unsigned (0) */
+ OPJ_UINT32 sgnd;
+} opj_image_cmptparm_t;
+
+
+/*
+==========================================================
+ Information on the JPEG 2000 codestream
+==========================================================
+*/
+
+/**
+ * Index structure : Information concerning a packet inside tile
+ * */
+typedef struct opj_packet_info {
+ /** packet start position (including SOP marker if it exists) */
+ OPJ_OFF_T start_pos;
+ /** end of packet header position (including EPH marker if it exists)*/
+ OPJ_OFF_T end_ph_pos;
+ /** packet end position */
+ OPJ_OFF_T end_pos;
+ /** packet distorsion */
+ double disto;
+} opj_packet_info_t;
+
+
+/* UniPG>> */
+/**
+ * Marker structure
+ * */
+typedef struct opj_marker_info_t {
+ /** marker type */
+ unsigned short int type;
+ /** position in codestream */
+ OPJ_OFF_T pos;
+ /** length, marker val included */
+ int len;
+} opj_marker_info_t;
+/* <<UniPG */
+
+/**
+ * Index structure : Information concerning tile-parts
+*/
+typedef struct opj_tp_info {
+ /** start position of tile part */
+ int tp_start_pos;
+ /** end position of tile part header */
+ int tp_end_header;
+ /** end position of tile part */
+ int tp_end_pos;
+ /** start packet of tile part */
+ int tp_start_pack;
+ /** number of packets of tile part */
+ int tp_numpacks;
+} opj_tp_info_t;
+
+/**
+ * Index structure : information regarding tiles
+*/
+typedef struct opj_tile_info {
+ /** value of thresh for each layer by tile cfr. Marcela */
+ double *thresh;
+ /** number of tile */
+ int tileno;
+ /** start position */
+ int start_pos;
+ /** end position of the header */
+ int end_header;
+ /** end position */
+ int end_pos;
+ /** precinct number for each resolution level (width) */
+ int pw[33];
+ /** precinct number for each resolution level (height) */
+ int ph[33];
+ /** precinct size (in power of 2), in X for each resolution level */
+ int pdx[33];
+ /** precinct size (in power of 2), in Y for each resolution level */
+ int pdy[33];
+ /** information concerning packets inside tile */
+ opj_packet_info_t *packet;
+ /** add fixed_quality */
+ int numpix;
+ /** add fixed_quality */
+ double distotile;
+ /** number of markers */
+ int marknum;
+ /** list of markers */
+ opj_marker_info_t *marker;
+ /** actual size of markers array */
+ int maxmarknum;
+ /** number of tile parts */
+ int num_tps;
+ /** information concerning tile parts */
+ opj_tp_info_t *tp;
+} opj_tile_info_t;
+
+/**
+ * Index structure of the codestream
+*/
+typedef struct opj_codestream_info {
+ /** maximum distortion reduction on the whole image (add for Marcela) */
+ double D_max;
+ /** packet number */
+ int packno;
+ /** writing the packet in the index with t2_encode_packets */
+ int index_write;
+ /** image width */
+ int image_w;
+ /** image height */
+ int image_h;
+ /** progression order */
+ OPJ_PROG_ORDER prog;
+ /** tile size in x */
+ int tile_x;
+ /** tile size in y */
+ int tile_y;
+ /** */
+ int tile_Ox;
+ /** */
+ int tile_Oy;
+ /** number of tiles in X */
+ int tw;
+ /** number of tiles in Y */
+ int th;
+ /** component numbers */
+ int numcomps;
+ /** number of layer */
+ int numlayers;
+ /** number of decomposition for each component */
+ int *numdecompos;
+/* UniPG>> */
+ /** number of markers */
+ int marknum;
+ /** list of markers */
+ opj_marker_info_t *marker;
+ /** actual size of markers array */
+ int maxmarknum;
+/* <<UniPG */
+ /** main header position */
+ int main_head_start;
+ /** main header position */
+ int main_head_end;
+ /** codestream's size */
+ int codestream_size;
+ /** information regarding tiles inside image */
+ opj_tile_info_t *tile;
+} opj_codestream_info_t;
+
+/* <----------------------------------------------------------- */
+/* new output managment of the codestream information and index */
+
+/**
+ * Tile-component coding parameters information
+ */
+typedef struct opj_tccp_info
+{
+ /** component index */
+ OPJ_UINT32 compno;
+ /** coding style */
+ OPJ_UINT32 csty;
+ /** number of resolutions */
+ OPJ_UINT32 numresolutions;
+ /** code-blocks width */
+ OPJ_UINT32 cblkw;
+ /** code-blocks height */
+ OPJ_UINT32 cblkh;
+ /** code-block coding style */
+ OPJ_UINT32 cblksty;
+ /** discrete wavelet transform identifier */
+ OPJ_UINT32 qmfbid;
+ /** quantisation style */
+ OPJ_UINT32 qntsty;
+ /** stepsizes used for quantization */
+ OPJ_UINT32 stepsizes_mant[J2K_MAXBANDS];
+ /** stepsizes used for quantization */
+ OPJ_UINT32 stepsizes_expn[J2K_MAXBANDS];
+ /** number of guard bits */
+ OPJ_UINT32 numgbits;
+ /** Region Of Interest shift */
+ OPJ_INT32 roishift;
+ /** precinct width */
+ OPJ_UINT32 prcw[J2K_MAXRLVLS];
+ /** precinct height */
+ OPJ_UINT32 prch[J2K_MAXRLVLS];
+}
+opj_tccp_info_t;
+
+/**
+ * Tile coding parameters information
+ */
+typedef struct opj_tile_v2_info {
+
+ /** number (index) of tile */
+ int tileno;
+ /** coding style */
+ OPJ_UINT32 csty;
+ /** progression order */
+ OPJ_PROG_ORDER prg;
+ /** number of layers */
+ OPJ_UINT32 numlayers;
+ /** multi-component transform identifier */
+ OPJ_UINT32 mct;
+
+ /** information concerning tile component parameters*/
+ opj_tccp_info_t *tccp_info;
+
+} opj_tile_info_v2_t;
+
+/**
+ * Information structure about the codestream (FIXME should be expand and enhance)
+ */
+typedef struct opj_codestream_info_v2 {
+ /* Tile info */
+ /** tile origin in x = XTOsiz */
+ OPJ_UINT32 tx0;
+ /** tile origin in y = YTOsiz */
+ OPJ_UINT32 ty0;
+ /** tile size in x = XTsiz */
+ OPJ_UINT32 tdx;
+ /** tile size in y = YTsiz */
+ OPJ_UINT32 tdy;
+ /** number of tiles in X */
+ OPJ_UINT32 tw;
+ /** number of tiles in Y */
+ OPJ_UINT32 th;
+
+ /** number of components*/
+ OPJ_UINT32 nbcomps;
+
+ /** Default information regarding tiles inside image */
+ opj_tile_info_v2_t m_default_tile_info;
+
+ /** information regarding tiles inside image */
+ opj_tile_info_v2_t *tile_info; /* FIXME not used for the moment */
+
+} opj_codestream_info_v2_t;
+
+
+/**
+ * Index structure about a tile part
+ */
+typedef struct opj_tp_index {
+ /** start position */
+ OPJ_OFF_T start_pos;
+ /** end position of the header */
+ OPJ_OFF_T end_header;
+ /** end position */
+ OPJ_OFF_T end_pos;
+
+} opj_tp_index_t;
+
+/**
+ * Index structure about a tile
+ */
+typedef struct opj_tile_index {
+ /** tile index */
+ OPJ_UINT32 tileno;
+
+ /** number of tile parts */
+ OPJ_UINT32 nb_tps;
+ /** current nb of tile part (allocated)*/
+ OPJ_UINT32 current_nb_tps;
+ /** current tile-part index */
+ OPJ_UINT32 current_tpsno;
+ /** information concerning tile parts */
+ opj_tp_index_t *tp_index;
+
+ /* UniPG>> */
+ /** number of markers */
+ OPJ_UINT32 marknum;
+ /** list of markers */
+ opj_marker_info_t *marker;
+ /** actual size of markers array */
+ OPJ_UINT32 maxmarknum;
+ /* <<UniPG */
+
+ /** packet number */
+ OPJ_UINT32 nb_packet;
+ /** information concerning packets inside tile */
+ opj_packet_info_t *packet_index;
+
+} opj_tile_index_t;
+
+/**
+ * Index structure of the codestream (FIXME should be expand and enhance)
+ */
+typedef struct opj_codestream_index {
+ /** main header start position (SOC position) */
+ OPJ_OFF_T main_head_start;
+ /** main header end position (first SOT position) */
+ OPJ_OFF_T main_head_end;
+
+ /** codestream's size */
+ OPJ_UINT64 codestream_size;
+
+/* UniPG>> */
+ /** number of markers */
+ OPJ_UINT32 marknum;
+ /** list of markers */
+ opj_marker_info_t *marker;
+ /** actual size of markers array */
+ OPJ_UINT32 maxmarknum;
+/* <<UniPG */
+
+ /** */
+ OPJ_UINT32 nb_of_tiles;
+ /** */
+ opj_tile_index_t *tile_index; /* FIXME not used for the moment */
+
+}opj_codestream_index_t;
+/* -----------------------------------------------------------> */
+
+/*
+==========================================================
+ Metadata from the JP2file
+==========================================================
+*/
+
+/**
+ * Info structure of the JP2 file
+ * FIXME
+ */
+typedef struct opj_jp2_metadata {
+ /** */
+ OPJ_INT32 not_used;
+
+} opj_jp2_metadata_t;
+
+/**
+ * Index structure of the JP2 file
+ * FIXME
+ */
+typedef struct opj_jp2_index {
+ /** */
+ OPJ_INT32 not_used;
+
+} opj_jp2_index_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+==========================================================
+ openjpeg version
+==========================================================
+*/
+
+OPJ_API const char * OPJ_CALLCONV opj_version(void);
+
+/*
+==========================================================
+ image functions definitions
+==========================================================
+*/
+
+/**
+ * Create an image
+ * @param numcmpts number of components
+ * @param cmptparms components parameters
+ * @param clrspc image color space
+ * @return returns a new image structure if successful, returns NULL otherwise
+ * */
+OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc);
+
+/**
+ * Deallocate any resources associated with an image
+ * @param image image to be destroyed
+ */
+OPJ_API void OPJ_CALLCONV opj_image_destroy(opj_image_t *image);
+
+
+/**
+ * Creates an image without allocating memory for the image (used in the new version of the library).
+ *
+ * @param numcmpts the number of components
+ * @param cmptparms the components parameters
+ * @param clrspc the image color space
+ *
+ * @return a new image structure if successful, NULL otherwise.
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc);
+
+
+/*
+==========================================================
+ stream functions definitions
+==========================================================
+*/
+/* CIO functions are DEPRECATED see following stream functions */
+/**
+Open and allocate a memory stream for read / write.
+On reading, the user must provide a buffer containing encoded data. The buffer will be
+wrapped by the returned CIO handle.
+On writing, buffer parameters must be set to 0: a buffer will be allocated by the library
+to contain encoded data.
+@param cinfo Codec context info
+@param buffer Reading: buffer address. Writing: NULL
+@param length Reading: buffer length. Writing: 0
+@return Returns a CIO handle if successful, returns NULL otherwise
+*/
+OPJ_API opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length);
+
+/**
+Close and free a CIO handle
+@param cio CIO handle to free
+*/
+OPJ_API void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio);
+
+/**
+Get position in byte stream
+@param cio CIO handle
+@return Returns the position in bytes
+*/
+OPJ_API OPJ_OFF_T OPJ_CALLCONV cio_tell(opj_cio_t *cio);
+/**
+Set position in byte stream
+@param cio CIO handle
+@param pos Position, in number of bytes, from the beginning of the stream
+*/
+OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos);
+
+/* <----------- */
+/* V2 framework */
+
+/**
+ * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream.
+ *
+ * @param p_is_input if set to true then the stream will be an input stream, an output stream else.
+ *
+ * @return a stream object.
+*/
+OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create(opj_bool p_is_input);
+
+/**
+ * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream.
+ *
+ * @param p_buffer_size FIXME DOC
+ * @param p_is_input if set to true then the stream will be an input stream, an output stream else.
+ *
+ * @return a stream object.
+*/
+OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, opj_bool p_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.
+ *
+ * @param p_stream the stream to destroy.
+ */
+OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_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);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * Sets the given function to be used as a seek function, the stream is then seekable.
+ * @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_seek_function(opj_stream_t* p_stream, opj_stream_seek_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);
+
+/**
+ * Sets the length of the user data for the stream.
+ *
+ * @param p_stream the stream to modify
+ * @param data_length length of the user_data.
+*/
+OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT64 data_length);
+
+/**
+ * Helper function.
+ * Sets the stream to be a file stream. The FILE must have been open previously.
+ * @param p_file the file stream to operate on
+ * @param p_is_read_stream whether the stream is a read stream (true) or not (false)
+*/
+OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (FILE * p_file, opj_bool p_is_read_stream);
+
+/**
+ * FIXME DOC
+ * @param p_file the file stream to operate on
+ * @param p_buffer_size FIXME DOC
+ * @param p_is_read_stream FIXME DOC
+*/
+OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (FILE * p_file, OPJ_SIZE_T p_buffer_size, opj_bool p_is_read_stream);
+
+/* -----------> */
+
+/*
+==========================================================
+ event manager functions definitions
+==========================================================
+*/
+OPJ_API opj_bool OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data);
+OPJ_API opj_bool OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data);
+OPJ_API opj_bool OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, opj_msg_callback p_callback,void * p_user_data);
+
+/*
+==========================================================
+ codec functions definitions
+==========================================================
+*/
+
+/**
+ * Creates a J2K/JP2 decompression structure
+ * @param format Decoder to select
+ *
+ * @return Returns a handle to a decompressor if successful, returns NULL otherwise
+ * */
+OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format);
+
+/**
+ * Destroy a decompressor handle
+ *
+ * @param p_codec decompressor handle to destroy
+ */
+OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec);
+
+/**
+ * Read after the codestream if necessary
+ * @param p_codec the JPEG2000 codec to read.
+ * @param p_stream the JPEG2000 stream.
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_end_decompress ( opj_codec_t *p_codec,
+ opj_stream_t *p_stream);
+
+
+/**
+ * Set decoding parameters to default values
+ * @param parameters Decompression parameters
+ */
+OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters);
+
+/**
+ * Setup the decoder with decompression parameters provided by the user and with the message handler
+ * provided by the user.
+ *
+ * @param p_codec decompressor handler
+ * @param parameters decompression parameters
+ *
+ * @return true if the decoder is correctly set
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
+ opj_dparameters_t *parameters );
+
+/**
+ * Decodes an image header.
+ *
+ * @param p_stream the jpeg2000 stream.
+ * @param p_codec the jpeg2000 codec to read.
+ * @param p_image the image structure initialized with the characteristics of encoded image.
+ *
+ * @return true if the main header of the codestream and the JP2 header is correctly read.
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_read_header ( opj_stream_t *p_stream,
+ opj_codec_t *p_codec,
+ opj_image_t **p_image);
+
+/**
+ * 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_image FIXME DOC
+ * @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 opj_bool OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec,
+ opj_image_t* p_image,
+ 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
+ * @param p_decompressor decompressor handle
+ * @param p_stream Input buffer stream
+ * @param p_image the decoded image
+ * @return true if success, otherwise false
+ * */
+OPJ_API opj_bool OPJ_CALLCONV opj_decode( opj_codec_t *p_decompressor,
+ opj_stream_t *p_stream,
+ opj_image_t *p_image);
+
+/**
+ * Get the decoded tile from the codec
+ * @param p_codec the jpeg2000 codec.
+ * @param p_stream input streamm
+ * @param p_image output image
+ * @param tile_index index of the tile which will be decode
+ *
+ * @return true if success, otherwise false
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec,
+ opj_stream_t *p_stream,
+ opj_image_t *p_image,
+ OPJ_UINT32 tile_index);
+
+/**
+ * Set the resolution factor of the decoded image
+ * @param p_codec the jpeg2000 codec.
+ * @param res_factor resolution factor to set
+ *
+ * @return true if success, otherwise false
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, OPJ_UINT32 res_factor);
+
+/**
+ * Writes a tile with the given data.
+ *
+ * @param p_codec 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 opj_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 opj_bool OPJ_CALLCONV opj_read_tile_header( opj_codec_t *p_codec,
+ opj_stream_t * p_stream,
+ 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,
+ opj_bool * p_should_go_on );
+
+/**
+ * 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 opj_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 );
+
+/* COMPRESSION FUNCTIONS*/
+
+/**
+ * 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);
+
+/**
+Set encoding parameters to default values, that means :
+<ul>
+<li>Lossless
+<li>1 tile
+<li>Size of precinct : 2^15 x 2^15 (means 1 precinct)
+<li>Size of code-block : 64 x 64
+<li>Number of resolutions: 6
+<li>No SOP marker in the codestream
+<li>No EPH marker in the codestream
+<li>No sub-sampling in x or y direction
+<li>No mode switch activated
+<li>Progression order: LRCP
+<li>No index file
+<li>No ROI upshifted
+<li>No offset of the origin of the image
+<li>No offset of the origin of the tiles
+<li>Reversible DWT 5-3
+</ul>
+@param parameters Compression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters);
+
+/**
+ * Setup the encoder parameters using the current image and using user parameters.
+ * @param p_codec Compressor handle
+ * @param parameters Compression parameters
+ * @param image Input filled image
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
+ opj_cparameters_t *parameters,
+ opj_image_t *image);
+
+/**
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_start_compress ( opj_codec_t *p_codec,
+ opj_image_t * p_image,
+ opj_stream_t *p_cio);
+
+/**
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,
+ opj_stream_t *p_stream);
+
+/**
+ * Encode an image into a JPEG-2000 codestream
+ * @param p_codec compressor handle
+ * @param p_stream Output buffer stream
+ *
+ * @return Returns true if successful, returns false otherwise
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_encode(opj_codec_t *p_codec,
+ opj_stream_t *p_stream);
+
+
+/**
+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_v2_t **cstr_info);
+
+
+
+/*
+==========================================================
+ codec output functions definitions
+==========================================================
+*/
+
+/**
+ * Dump the codec information into the output stream
+ *
+ * @param p_codec the jpeg2000 codec.
+ * @param info_flag type of information dump.
+ * @param output_stream output stream where dump the informations get from the codec.
+ *
+ */
+OPJ_API void OPJ_CALLCONV opj_dump_codec( opj_codec_t *p_codec,
+ OPJ_INT32 info_flag,
+ FILE* output_stream);
+
+/**
+ * Get the codestream information from the codec
+ *
+ * @param p_codec the jpeg2000 codec.
+ *
+ * @return a pointer to a codestream information structure.
+ *
+ */
+OPJ_API opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info(opj_codec_t *p_codec);
+
+/**
+ * Get the codestream index from the codec
+ *
+ * @param p_codec the jpeg2000 codec.
+ *
+ * @return a pointer to a codestream index structure.
+ *
+ */
+OPJ_API opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index(opj_codec_t *p_codec);
+
+OPJ_API void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index);
+
+
+/**
+ * Get the JP2 file information from the codec FIXME
+ *
+ * @param p_codec the jpeg2000 codec.
+ *
+ * @return a pointer to a JP2 metadata structure.
+ *
+ */
+OPJ_API opj_jp2_metadata_t* OPJ_CALLCONV opj_get_jp2_metadata(opj_codec_t *p_codec);
+
+/**
+ * Get the JP2 file index from the codec FIXME
+ *
+ * @param p_codec the jpeg2000 codec.
+ *
+ * @return a pointer to a JP2 index structure.
+ *
+ */
+OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec);
+
+
+/*
+==========================================================
+ new functions
+==========================================================
+*/
+
+/**
+ * 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 opj_bool OPJ_CALLCONV opj_set_MCT( opj_cparameters_t *parameters,
+ OPJ_FLOAT32 * pEncodingMatrix,
+ OPJ_INT32 * p_dc_shift,
+ OPJ_UINT32 pNbComp);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENJPEG_H */
diff --git a/src/lib/openjp2/opj_includes.h b/src/lib/openjp2/opj_includes.h
new file mode 100644
index 00000000..98a5b86b
--- /dev/null
+++ b/src/lib/openjp2/opj_includes.h
@@ -0,0 +1,185 @@
+/*
+ * 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 OPJ_INCLUDES_H
+#define OPJ_INCLUDES_H
+
+/*
+ * This must be included before any system headers,
+ * since they can react to macro defined there
+ */
+#include "opj_config.h"
+
+/*
+ ==========================================================
+ Standard includes used by the library
+ ==========================================================
+*/
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <assert.h>
+
+/*
+ Use fseeko() and ftello() if they are available since they use
+ 'off_t' rather than 'long'. It is wrong to use fseeko() and
+ ftello() only on systems with special LFS support since some systems
+ (e.g. FreeBSD) support a 64-bit off_t by default.
+*/
+#if defined(HAVE_FSEEKO)
+# define fseek fseeko
+# define ftell ftello
+#endif
+
+
+#if defined(WIN32) && !defined(Windows95) && !defined(__BORLANDC__) && \
+ !(defined(_MSC_VER) && _MSC_VER < 1400) && \
+ !(defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x800)
+ /*
+ Windows '95 and Borland C do not support _lseeki64
+ Visual Studio does not support _fseeki64 and _ftelli64 until the 2005 release.
+ Without these interfaces, files over 2GB in size are not supported for Windows.
+ */
+# define OPJ_FSEEK(stream,offset,whence) _fseeki64(stream,/* __int64 */ offset,whence)
+# define OPJ_FSTAT(fildes,stat_buff) _fstati64(fildes,/* struct _stati64 */ stat_buff)
+# define OPJ_FTELL(stream) /* __int64 */ _ftelli64(stream)
+# define OPJ_STAT_STRUCT_T struct _stati64
+# define OPJ_STAT(path,stat_buff) _stati64(path,/* struct _stati64 */ stat_buff)
+#else
+# define OPJ_FSEEK(stream,offset,whence) fseek(stream,offset,whence)
+# define OPJ_FSTAT(fildes,stat_buff) fstat(fildes,stat_buff)
+# define OPJ_FTELL(stream) ftell(stream)
+# define OPJ_STAT_STRUCT_T struct stat
+# define OPJ_STAT(path,stat_buff) stat(path,stat_buff)
+#endif
+
+
+/*
+ ==========================================================
+ OpenJPEG interface
+ ==========================================================
+ */
+#include "openjpeg.h"
+
+/*
+ ==========================================================
+ 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 __forceinline
+ #elif defined(__GNUC__)
+ #define INLINE __inline__
+ #elif defined(__MWERKS__)
+ #define INLINE inline
+ #else
+ /* add other compilers here ... */
+ #define INLINE
+ #endif /* defined(<Compiler>) */
+#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 and Borland C do not have lrintf */
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+static INLINE long lrintf(float f){
+#ifdef _M_X64
+ return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f));
+#else
+ int i;
+
+ _asm{
+ fld f
+ fistp i
+ };
+
+ return i;
+#endif
+}
+#endif
+
+#include "opj_inttypes.h"
+#include "j2k_lib.h"
+#include "opj_malloc.h"
+#include "event.h"
+#include "bio.h"
+#include "cio.h"
+
+#include "image.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "jpt.h"
+
+#include "mqc.h"
+#include "raw.h"
+#include "bio.h"
+#include "tgt.h"
+#include "pi.h"
+#include "tcd.h"
+#include "t1.h"
+#include "dwt.h"
+#include "t2.h"
+#include "mct.h"
+#include "int.h"
+#include "fix.h"
+
+#include "cidx_manager.h"
+#include "indexbox_manager.h"
+
+/* JPWL>> */
+#ifdef USE_JPWL
+#include "openjpwl/jpwl.h"
+#endif /* USE_JPWL */
+/* <<JPWL */
+
+/* V2 */
+#include "function_list.h"
+
+#endif /* OPJ_INCLUDES_H */
diff --git a/src/lib/openjp2/opj_inttypes.h b/src/lib/openjp2/opj_inttypes.h
new file mode 100644
index 00000000..d6a29263
--- /dev/null
+++ b/src/lib/openjp2/opj_inttypes.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012, Mathieu Malaterre <mathieu.malaterre@gmail.com>
+ * 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_INTTYPES_H
+#define OPJ_INTTYPES_H
+
+#include "opj_config.h"
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#if defined(_WIN32)
+#define PRId64 "I64d"
+#define PRIi64 "I64i"
+#define PRIu64 "I64u"
+#define PRIx64 "I64x"
+#else
+#error unsupported platform
+#endif
+#endif
+
+#endif /* OPJ_INTTYPES_H */
diff --git a/src/lib/openjp2/opj_malloc.h b/src/lib/openjp2/opj_malloc.h
new file mode 100644
index 00000000..0b1d4fc1
--- /dev/null
+++ b/src/lib/openjp2/opj_malloc.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * 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.
+*/
+
+/** @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
+*/
+#ifdef ALLOC_PERF_OPT
+void * OPJ_CALLCONV opj_malloc(size_t size);
+#else
+#define opj_malloc(size) malloc(size)
+#endif
+
+/**
+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
+*/
+#ifdef ALLOC_PERF_OPT
+void * OPJ_CALLCONV opj_calloc(size_t _NumOfElements, size_t _SizeOfElements);
+#else
+#define opj_calloc(num, size) calloc(num, size)
+#endif
+
+/**
+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 <mm_malloc.h>
+ #define HAVE_MM_MALLOC
+ #else /* MSVC, Intel C++ */
+ #include <malloc.h>
+ #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__)
+ #define HAVE_MEMALIGN
+ #include <malloc.h>
+ #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
+
+#ifdef ALLOC_PERF_OPT
+ #undef opj_aligned_malloc
+ #define opj_aligned_malloc(size) opj_malloc(size)
+ #undef opj_aligned_free
+ #define opj_aligned_free(m) opj_free(m)
+#endif
+
+/**
+Reallocate memory blocks.
+@param m Pointer to previously allocated memory block
+@param s New size in bytes
+@return Returns a void pointer to the reallocated (and possibly moved) memory block
+*/
+#ifdef ALLOC_PERF_OPT
+void * OPJ_CALLCONV opj_realloc(void * m, size_t s);
+#else
+#define opj_realloc(m, s) realloc(m, s)
+#endif
+
+/**
+Deallocates or frees a memory block.
+@param m Previously allocated memory block to be freed
+*/
+#ifdef ALLOC_PERF_OPT
+void OPJ_CALLCONV opj_free(void * m);
+#else
+#define opj_free(m) free(m)
+#endif
+
+#ifdef __GNUC__
+#pragma GCC poison malloc calloc realloc free
+#endif
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __OPJ_MALLOC_H */
+
diff --git a/src/lib/openjp2/opj_stdint.h b/src/lib/openjp2/opj_stdint.h
new file mode 100644
index 00000000..3dd2ec2b
--- /dev/null
+++ b/src/lib/openjp2/opj_stdint.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Mathieu Malaterre <mathieu.malaterre@gmail.com>
+ * 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_STDINT_H
+#define OPJ_STDINT_H
+
+#include "opj_config.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#else
+#if defined(_WIN32)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#error unsupported platform
+#endif
+#endif
+typedef size_t OPJ_SIZE_T;
+
+/* 64-bit file offset type */
+typedef int64_t OPJ_OFF_T;
+
+#ifndef HAVE_SSIZE_T
+#if defined(_WIN32)
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#else
+#error SSIZE_T is undefined
+#endif /* _WIN32 */
+#endif
+
+#endif /* OPJ_STDINT_H */
diff --git a/src/lib/openjp2/phix_manager.c b/src/lib/openjp2/phix_manager.c
new file mode 100644
index 00000000..0e2e5704
--- /dev/null
+++ b/src/lib/openjp2/phix_manager.c
@@ -0,0 +1,169 @@
+/*
+ * $Id: phix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.c from 2KAN indexer
+ */
+
+#include "opj_includes.h"
+
+
+/*
+ * Write faix box of phix
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] compno component number
+ * @param[in] cstr_info codestream information
+ * @param[in] EPHused true if if EPH option used
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of faix box
+ */
+int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
+
+int write_phix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp=0, compno, i;
+ opj_jp2_box_t *box;
+
+ box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t));
+
+ for( i=0;i<2;i++){
+ if (i) cio_seek( cio, lenp);
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_PHIX, 4); /* PHIX */
+
+ write_manf( i, cstr_info.numcomps, box, cio);
+
+ for( compno=0; compno<cstr_info.numcomps; compno++){
+ box[compno].length = write_phixfaix( coff, compno, cstr_info, EPHused, j2klen, cio);
+ box[compno].type = JPIP_FAIX;
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+ }
+
+ opj_free(box);
+
+ return len;
+}
+
+int write_phixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp, tileno, version, i, nmax, size_of_coding; /* 4 or 8 */
+ opj_tile_info_t *tile_Idx;
+ opj_packet_info_t packet;
+ int resno, precno, layno, num_packet;
+ int numOfres, numOfprec, numOflayers;
+ packet.end_ph_pos = packet.start_pos = -1;
+ (void)EPHused; /* unused ? */
+
+ if( j2klen > pow( 2, 32)){
+ size_of_coding = 8;
+ version = 1;
+ }
+ else{
+ size_of_coding = 4;
+ version = 0;
+ }
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_FAIX, 4); /* FAIX */
+ cio_write( cio, version,1); /* Version 0 = 4 bytes */
+
+ nmax = 0;
+ for( i=0; i<=cstr_info.numdecompos[compno]; i++)
+ nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers;
+
+ cio_write( cio, nmax, size_of_coding); /* NMAX */
+ cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
+
+ for( tileno=0; tileno<cstr_info.tw*cstr_info.th; tileno++){
+ tile_Idx = &cstr_info.tile[ tileno];
+
+ num_packet = 0;
+ numOfres = cstr_info.numdecompos[compno] + 1;
+
+ for( resno=0; resno<numOfres ; resno++){
+ numOfprec = tile_Idx->pw[resno]*tile_Idx->ph[resno];
+ for( precno=0; precno<numOfprec; precno++){
+ numOflayers = cstr_info.numlayers;
+ for( layno=0; layno<numOflayers; layno++){
+
+ switch ( cstr_info.prog){
+ case LRCP:
+ packet = tile_Idx->packet[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno];
+ break;
+ case RLCP:
+ packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno];
+ break;
+ case RPCL:
+ packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno];
+ break;
+ case PCRL:
+ packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno];
+ break;
+ case CPRL:
+ packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno];
+ break;
+ default:
+ fprintf( stderr, "failed to ppix indexing\n");
+ }
+
+ cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */
+ cio_write( cio, packet.end_ph_pos-packet.start_pos+1, size_of_coding); /* length */
+
+ num_packet++;
+ }
+ }
+ }
+
+ /* PADDING */
+ while( num_packet < nmax){
+ cio_write( cio, 0, size_of_coding); /* start position */
+ cio_write( cio, 0, size_of_coding); /* length */
+ num_packet++;
+ }
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
diff --git a/src/lib/openjp2/pi.c b/src/lib/openjp2/pi.c
new file mode 100644
index 00000000..8ebc510c
--- /dev/null
+++ b/src/lib/openjp2/pi.c
@@ -0,0 +1,2376 @@
+/*
+ * 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 "opj_includes.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 opj_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 opj_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 opj_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 opj_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 opj_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 p_dx_min the minimum dx of all the components of all the resolutions for the tile.
+ * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile.
+ */
+static void pi_update_encode_poc_and_final (opj_cp_v2_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);
+
+void pi_update_encode_not_poc ( opj_cp_v2_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);
+
+void get_encoding_parameters( const opj_image_t *p_image,
+ const opj_cp_v2_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 );
+
+void get_all_encoding_parameters(
+ const opj_image_t *p_image,
+ const opj_cp_v2_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
+ );
+
+opj_pi_iterator_t * pi_create( const opj_image_t *image,
+ const opj_cp_v2_t *cp,
+ OPJ_UINT32 tileno );
+
+void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_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_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res);
+
+OPJ_INT32 pi_check_next_level( OPJ_INT32 pos,
+ opj_cp_v2_t *cp,
+ OPJ_UINT32 tileno,
+ OPJ_UINT32 pino,
+ const OPJ_CHAR *prog);
+
+/*@}*/
+
+/*@}*/
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+static opj_bool pi_next_lrcp(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long 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 OPJ_TRUE;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+static opj_bool pi_next_rlcp(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long 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 OPJ_TRUE;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+static opj_bool pi_next_rpcl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ goto LABEL_SKIP;
+ } else {
+ int 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++) {
+ int 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++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int 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 << rpy))))){
+ 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 OPJ_TRUE;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+static opj_bool pi_next_pcrl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ comp = &pi->comps[pi->compno];
+ goto LABEL_SKIP;
+ } else {
+ int 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++) {
+ int 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];
+ for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int 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 << rpy))))){
+ 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 OPJ_TRUE;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+static opj_bool pi_next_cprl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long 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++) {
+ int resno;
+ comp = &pi->comps[pi->compno];
+ pi->dx = 0;
+ pi->dy = 0;
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int 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->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int 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 << rpy))))){
+ 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 OPJ_TRUE;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return OPJ_FALSE;
+}
+
+/*
+==========================================================
+ Packet iterator interface
+==========================================================
+*/
+
+opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, int tileno) {
+ int p, q;
+ int compno, resno, pino;
+ opj_pi_iterator_t *pi = NULL;
+ opj_tcp_t *tcp = NULL;
+ opj_tccp_t *tccp = NULL;
+
+ tcp = &cp->tcps[tileno];
+
+ pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t));
+ if(!pi) {
+ /* TODO: throw an error */
+ return NULL;
+ }
+
+ for (pino = 0; pino < tcp->numpocs + 1; pino++) { /* change */
+ int maxres = 0;
+ int maxprec = 0;
+ p = tileno % cp->tw;
+ q = tileno / cp->tw;
+
+ pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+ pi[pino].numcomps = image->numcomps;
+
+ pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t));
+ if(!pi[pino].comps) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ int tcx0, tcy0, tcx1, tcy1;
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ tccp = &tcp->tccps[compno];
+ comp->dx = image->comps[compno].dx;
+ comp->dy = image->comps[compno].dy;
+ comp->numresolutions = tccp->numresolutions;
+
+ comp->resolutions = (opj_pi_resolution_t*) opj_calloc(comp->numresolutions, sizeof(opj_pi_resolution_t));
+ if(!comp->resolutions) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ tcx0 = int_ceildiv(pi->tx0, comp->dx);
+ tcy0 = int_ceildiv(pi->ty0, comp->dy);
+ tcx1 = int_ceildiv(pi->tx1, comp->dx);
+ tcy1 = int_ceildiv(pi->ty1, comp->dy);
+ if (comp->numresolutions > maxres) {
+ maxres = comp->numresolutions;
+ }
+
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int levelno;
+ int rx0, ry0, rx1, ry1;
+ int px0, py0, px1, py1;
+ opj_pi_resolution_t *res = &comp->resolutions[resno];
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ res->pdx = tccp->prcw[resno];
+ res->pdy = tccp->prch[resno];
+ } else {
+ res->pdx = 15;
+ res->pdy = 15;
+ }
+ levelno = comp->numresolutions - 1 - resno;
+ rx0 = int_ceildivpow2(tcx0, levelno);
+ ry0 = int_ceildivpow2(tcy0, levelno);
+ rx1 = int_ceildivpow2(tcx1, levelno);
+ ry1 = int_ceildivpow2(tcy1, levelno);
+ px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
+ py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
+ px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
+ py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
+ res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
+ res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
+
+ if (res->pw*res->ph > maxprec) {
+ maxprec = res->pw*res->ph;
+ }
+
+ }
+ }
+
+ tccp = &tcp->tccps[0];
+ pi[pino].step_p = 1;
+ pi[pino].step_c = maxprec * pi[pino].step_p;
+ pi[pino].step_r = image->numcomps * pi[pino].step_c;
+ pi[pino].step_l = maxres * pi[pino].step_r;
+
+ if (pino == 0) {
+ pi[pino].include = (short int*) opj_calloc(image->numcomps * maxres * tcp->numlayers * maxprec, sizeof(short int));
+ if(!pi[pino].include) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+ }
+ else {
+ pi[pino].include = pi[pino - 1].include;
+ }
+
+ if (tcp->POC == 0) {
+ pi[pino].first = 1;
+ pi[pino].poc.resno0 = 0;
+ pi[pino].poc.compno0 = 0;
+ pi[pino].poc.layno1 = tcp->numlayers;
+ pi[pino].poc.resno1 = maxres;
+ pi[pino].poc.compno1 = image->numcomps;
+ pi[pino].poc.prg = tcp->prg;
+ } else {
+ pi[pino].first = 1;
+ pi[pino].poc.resno0 = tcp->pocs[pino].resno0;
+ pi[pino].poc.compno0 = tcp->pocs[pino].compno0;
+ pi[pino].poc.layno1 = tcp->pocs[pino].layno1;
+ pi[pino].poc.resno1 = tcp->pocs[pino].resno1;
+ pi[pino].poc.compno1 = tcp->pocs[pino].compno1;
+ pi[pino].poc.prg = tcp->pocs[pino].prg;
+ }
+ pi[pino].poc.layno0 = 0;
+ pi[pino].poc.precno0 = 0;
+ pi[pino].poc.precno1 = maxprec;
+
+ }
+
+ return pi;
+}
+
+opj_pi_iterator_t *pi_create_decode_v2( opj_image_t *p_image,
+ opj_cp_v2_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_v2_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_UINT32*)opj_malloc(
+ l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
+ if
+ (! l_tmp_data)
+ {
+ return 00;
+ }
+ l_tmp_ptr = (OPJ_UINT32**)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 +1) * l_step_l, sizeof(OPJ_INT16));
+ if
+ (!l_current_pi->include)
+ {
+ opj_free(l_tmp_data);
+ opj_free(l_tmp_ptr);
+ pi_destroy_v2(l_pi, l_bound);
+ return 00;
+ }
+ memset(l_current_pi->include,0, (l_tcp->numlayers + 1) * 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 ; pino<l_bound ; ++pino )
+ {
+ opj_pi_comp_t *l_current_comp = l_current_pi->comps;
+ 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;
+}
+
+opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno, J2K_T2_MODE t2_mode){
+ int p, q, pino;
+ int compno, resno;
+ int maxres = 0;
+ int maxprec = 0;
+ opj_pi_iterator_t *pi = NULL;
+ opj_tcp_t *tcp = NULL;
+ opj_tccp_t *tccp = NULL;
+
+ tcp = &cp->tcps[tileno];
+
+ pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t));
+ if(!pi) { return NULL;}
+ pi->tp_on = cp->tp_on;
+
+ for(pino = 0;pino < tcp->numpocs+1 ; pino ++){
+ p = tileno % cp->tw;
+ q = tileno / cp->tw;
+
+ pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+ pi[pino].numcomps = image->numcomps;
+
+ pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t));
+ if(!pi[pino].comps) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ for (compno = 0; compno < pi[pino].numcomps; compno++) {
+ int tcx0, tcy0, tcx1, tcy1;
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ tccp = &tcp->tccps[compno];
+ comp->dx = image->comps[compno].dx;
+ comp->dy = image->comps[compno].dy;
+ comp->numresolutions = tccp->numresolutions;
+
+ comp->resolutions = (opj_pi_resolution_t*) opj_malloc(comp->numresolutions * sizeof(opj_pi_resolution_t));
+ if(!comp->resolutions) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ tcx0 = int_ceildiv(pi[pino].tx0, comp->dx);
+ tcy0 = int_ceildiv(pi[pino].ty0, comp->dy);
+ tcx1 = int_ceildiv(pi[pino].tx1, comp->dx);
+ tcy1 = int_ceildiv(pi[pino].ty1, comp->dy);
+ if (comp->numresolutions > maxres) {
+ maxres = comp->numresolutions;
+ }
+
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int levelno;
+ int rx0, ry0, rx1, ry1;
+ int px0, py0, px1, py1;
+ opj_pi_resolution_t *res = &comp->resolutions[resno];
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ res->pdx = tccp->prcw[resno];
+ res->pdy = tccp->prch[resno];
+ } else {
+ res->pdx = 15;
+ res->pdy = 15;
+ }
+ levelno = comp->numresolutions - 1 - resno;
+ rx0 = int_ceildivpow2(tcx0, levelno);
+ ry0 = int_ceildivpow2(tcy0, levelno);
+ rx1 = int_ceildivpow2(tcx1, levelno);
+ ry1 = int_ceildivpow2(tcy1, levelno);
+ px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
+ py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
+ px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
+ py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
+ res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
+ res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
+
+ if (res->pw*res->ph > maxprec) {
+ maxprec = res->pw * res->ph;
+ }
+ }
+ }
+
+ tccp = &tcp->tccps[0];
+ pi[pino].step_p = 1;
+ pi[pino].step_c = maxprec * pi[pino].step_p;
+ pi[pino].step_r = image->numcomps * pi[pino].step_c;
+ pi[pino].step_l = maxres * pi[pino].step_r;
+
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ opj_pi_comp_t *comp = &pi->comps[compno];
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int dx, dy;
+ opj_pi_resolution_t *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[pino].dx = !pi->dx ? dx : int_min(pi->dx, dx);
+ pi[pino].dy = !pi->dy ? dy : int_min(pi->dy, dy);
+ }
+ }
+
+ if (pino == 0) {
+ pi[pino].include = (short int*) opj_calloc(tcp->numlayers * pi[pino].step_l, sizeof(short int));
+ if(!pi[pino].include) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+ }
+ else {
+ pi[pino].include = pi[pino - 1].include;
+ }
+
+ /* Generation of boundaries for each prog flag*/
+ if(tcp->POC && ( cp->cinema || ((!cp->cinema) && (t2_mode == FINAL_PASS)))){
+ tcp->pocs[pino].compS= tcp->pocs[pino].compno0;
+ tcp->pocs[pino].compE= tcp->pocs[pino].compno1;
+ tcp->pocs[pino].resS = tcp->pocs[pino].resno0;
+ tcp->pocs[pino].resE = tcp->pocs[pino].resno1;
+ tcp->pocs[pino].layE = tcp->pocs[pino].layno1;
+ tcp->pocs[pino].prg = tcp->pocs[pino].prg1;
+ if (pino > 0)
+ tcp->pocs[pino].layS = (tcp->pocs[pino].layE > tcp->pocs[pino - 1].layE) ? tcp->pocs[pino - 1].layE : 0;
+ }else {
+ tcp->pocs[pino].compS= 0;
+ tcp->pocs[pino].compE= image->numcomps;
+ tcp->pocs[pino].resS = 0;
+ tcp->pocs[pino].resE = maxres;
+ tcp->pocs[pino].layS = 0;
+ tcp->pocs[pino].layE = tcp->numlayers;
+ tcp->pocs[pino].prg = tcp->prg;
+ }
+ tcp->pocs[pino].prcS = 0;
+ tcp->pocs[pino].prcE = maxprec;;
+ tcp->pocs[pino].txS = pi[pino].tx0;
+ tcp->pocs[pino].txE = pi[pino].tx1;
+ tcp->pocs[pino].tyS = pi[pino].ty0;
+ tcp->pocs[pino].tyE = pi[pino].ty1;
+ tcp->pocs[pino].dx = pi[pino].dx;
+ tcp->pocs[pino].dy = pi[pino].dy;
+ }
+ return pi;
+ }
+
+opj_pi_iterator_t *pi_initialise_encode_v2(
+ const opj_image_t *p_image,
+ opj_cp_v2_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_v2_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_UINT32*)opj_malloc(
+ l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
+ if (! l_tmp_data) {
+ return 00;
+ }
+
+ l_tmp_ptr = (OPJ_UINT32**)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_v2(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 ; pino<l_bound ; ++pino ) {
+ opj_pi_comp_t *l_current_comp = l_current_pi->comps;
+ 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;
+}
+
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
+ int compno, pino;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ if(pi) {
+ for (pino = 0; pino < tcp->numpocs + 1; pino++) {
+ if(pi[pino].comps) {
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ if(comp->resolutions) {
+ opj_free(comp->resolutions);
+ }
+ }
+ opj_free(pi[pino].comps);
+ }
+ }
+ if(pi->include) {
+ opj_free(pi->include);
+ }
+ opj_free(pi);
+ }
+}
+
+opj_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 OPJ_FALSE;
+ }
+
+ return OPJ_FALSE;
+}
+
+opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){
+ char prog[4];
+ int i;
+ int incr_top=1,resetX=0;
+ opj_tcp_t *tcps =&cp->tcps[tileno];
+ opj_poc_t *tcp= &tcps->pocs[pino];
+
+ pi[pino].first = 1;
+ pi[pino].poc.prg = tcp->prg;
+
+ switch(tcp->prg){
+ case CPRL: strncpy(prog, "CPRL",4);
+ break;
+ case LRCP: strncpy(prog, "LRCP",4);
+ break;
+ case PCRL: strncpy(prog, "PCRL",4);
+ break;
+ case RLCP: strncpy(prog, "RLCP",4);
+ break;
+ case RPCL: strncpy(prog, "RPCL",4);
+ break;
+ case PROG_UNKNOWN:
+ return OPJ_TRUE;
+ }
+
+ if(!(cp->tp_on && ((!cp->cinema && (t2_mode == FINAL_PASS)) || cp->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 {
+ if( tpnum < cur_totnum_tp){
+ for(i=3;i>=0;i--){
+ switch(prog[i]){
+ case 'C':
+ if (i > tppos){
+ pi[pino].poc.compno0 = tcp->compS;
+ pi[pino].poc.compno1 = tcp->compE;
+ }else{
+ if (tpnum == 0){
+ tcp->comp_t = tcp->compS;
+ pi[pino].poc.compno0 = tcp->comp_t;
+ pi[pino].poc.compno1 = tcp->comp_t+1;
+ tcp->comp_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->comp_t ==tcp->compE){
+ 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{
+ pi[pino].poc.compno0 = tcp->comp_t;
+ pi[pino].poc.compno1 = tcp->comp_t+1;
+ tcp->comp_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.compno0 = tcp->comp_t-1;
+ pi[pino].poc.compno1 = tcp->comp_t;
+ }
+ }
+ }
+ break;
+
+ case 'R':
+ if (i > tppos){
+ pi[pino].poc.resno0 = tcp->resS;
+ pi[pino].poc.resno1 = tcp->resE;
+ }else{
+ if (tpnum == 0){
+ tcp->res_t = tcp->resS;
+ pi[pino].poc.resno0 = tcp->res_t;
+ pi[pino].poc.resno1 = tcp->res_t+1;
+ tcp->res_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->res_t==tcp->resE){
+ 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{
+ pi[pino].poc.resno0 = tcp->res_t;
+ pi[pino].poc.resno1 = tcp->res_t+1;
+ tcp->res_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.resno0 = tcp->res_t - 1;
+ pi[pino].poc.resno1 = tcp->res_t;
+ }
+ }
+ }
+ break;
+
+ case 'L':
+ if (i > tppos){
+ pi[pino].poc.layno0 = tcp->layS;
+ pi[pino].poc.layno1 = tcp->layE;
+ }else{
+ if (tpnum == 0){
+ tcp->lay_t = tcp->layS;
+ pi[pino].poc.layno0 = tcp->lay_t;
+ pi[pino].poc.layno1 = tcp->lay_t+1;
+ tcp->lay_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->lay_t == tcp->layE){
+ 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{
+ pi[pino].poc.layno0 = tcp->lay_t;
+ pi[pino].poc.layno1 = tcp->lay_t+1;
+ tcp->lay_t+=1;
+ incr_top=0;
+ }
+ }else{
+ 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:
+ if (i > tppos){
+ pi[pino].poc.precno0 = tcp->prcS;
+ pi[pino].poc.precno1 = tcp->prcE;
+ }else{
+ if (tpnum == 0){
+ tcp->prc_t = tcp->prcS;
+ pi[pino].poc.precno0 = tcp->prc_t;
+ pi[pino].poc.precno1 = tcp->prc_t+1;
+ tcp->prc_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->prc_t == tcp->prcE){
+ 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{
+ pi[pino].poc.precno0 = tcp->prc_t;
+ pi[pino].poc.precno1 = tcp->prc_t+1;
+ tcp->prc_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.precno0 = tcp->prc_t - 1;
+ pi[pino].poc.precno1 = tcp->prc_t;
+ }
+ }
+ }
+ break;
+ default:
+ if (i > tppos){
+ 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{
+ if (tpnum == 0){
+ 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;
+ }else{
+ if (incr_top == 1){
+ if(tcp->tx0_t >= tcp->txE){
+ if(tcp->ty0_t >= tcp->tyE){
+ 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{
+ 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;
+ pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy);
+ pi[pino].poc.ty1 = tcp->ty0_t ;
+ incr_top=0;
+ }
+ }else{
+ 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;
+ }
+ }
+ }
+ }
+ return OPJ_FALSE;
+}
+
+void pi_update_encoding_parameters( const opj_image_t *p_image,
+ opj_cp_v2_t *p_cp,
+ OPJ_UINT32 p_tile_no )
+{
+ /* encoding parameters 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_v2_t *l_tcp = 00;
+
+ /* preconditions */
+ 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);
+ }
+
+}
+
+void get_encoding_parameters( const opj_image_t *p_image,
+ const opj_cp_v2_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_v2_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 */
+ 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) {
+ /* arithmetic 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 p_dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile.
+ * @param p_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_v2_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_v2_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;
+ }
+}
+
+opj_pi_iterator_t * pi_create( const opj_image_t *image,
+ const opj_cp_v2_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_v2_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 NULL;
+ }
+ 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_v2(l_pi, l_poc_bound);
+ return NULL;
+ }
+
+ 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_v2(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;
+}
+
+void pi_update_encode_poc_and_final (opj_cp_v2_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_v2_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;
+ }
+}
+
+void pi_update_encode_not_poc ( opj_cp_v2_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_v2_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;
+ }
+}
+
+void pi_destroy_v2(
+ 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);
+ }
+}
+
+void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_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;pino<l_bound;++pino)
+ {
+ l_current_pi->poc.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_v2_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;pino<l_bound;++pino)
+ {
+ l_current_pi->poc.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;
+ }
+}
+
+void pi_create_encode_v2( opj_pi_iterator_t *pi,
+ opj_cp_v2_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_v2_t *tcps =&cp->tcps[tileno];
+ opj_poc_t *tcp= &tcps->pocs[pino];
+
+ prog = opj_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;
+ }
+ }
+ }
+ }
+ }
+}
+
+OPJ_INT32 pi_check_next_level( OPJ_INT32 pos,
+ opj_cp_v2_t *cp,
+ OPJ_UINT32 tileno,
+ OPJ_UINT32 pino,
+ const OPJ_CHAR *prog)
+{
+ OPJ_INT32 i,l;
+ opj_tcp_v2_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;
+}
diff --git a/src/lib/openjp2/pi.h b/src/lib/openjp2/pi.h
new file mode 100644
index 00000000..4d61e4b3
--- /dev/null
+++ b/src/lib/openjp2/pi.h
@@ -0,0 +1,216 @@
+/*
+ * 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 __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.
+*/
+
+/** @defgroup PI PI - Implementation of a packet iterator */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_resolution {
+ int pdx, pdy;
+ int pw, ph;
+} opj_pi_resolution_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_comp {
+ int dx, dy;
+ /** number of resolution levels */
+ int numresolutions;
+ opj_pi_resolution_t *resolutions;
+} opj_pi_comp_t;
+
+/**
+Packet iterator
+*/
+typedef struct opj_pi_iterator {
+ /** Enabling Tile part generation*/
+ char tp_on;
+ /** precise if the packet has been already used (usefull for progression order change) */
+ short int *include;
+ /** layer step used to localize the packet in the include vector */
+ int step_l;
+ /** resolution step used to localize the packet in the include vector */
+ int step_r;
+ /** component step used to localize the packet in the include vector */
+ int step_c;
+ /** precinct step used to localize the packet in the include vector */
+ int step_p;
+ /** component that identify the packet */
+ int compno;
+ /** resolution that identify the packet */
+ int resno;
+ /** precinct that identify the packet */
+ int precno;
+ /** layer that identify the packet */
+ int layno;
+ /** 0 if the first packet */
+ int first;
+ /** progression order change information */
+ opj_poc_t poc;
+ /** number of components in the image */
+ int numcomps;
+ /** Components*/
+ opj_pi_comp_t *comps;
+ int tx0, ty0, tx1, ty1;
+ int x, y, dx, dy;
+} opj_pi_iterator_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a packet iterator for Encoder
+@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
+@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
+@return Returns a packet iterator that points to the first packet of the tile
+@see pi_destroy
+*/
+opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno,J2K_T2_MODE t2_mode);
+
+/**
+ * Creates a packet iterator for encoding.
+ *
+ * @param image the image being encoded.
+ * @param cp the coding parameters.
+ * @param tileno index of the tile being encoded.
+ * @param 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_v2( const struct opj_image *image,
+ struct opj_cp_v2 *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_v2 *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 pino Iterator index for pi
+@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
+@param cur_totnum_tp The total number of tile parts in the current tile
+@return Returns true if an error is detected
+*/
+opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp);
+
+/**
+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 pino FIXME DOC
+@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 FIXME DOC
+*/
+void pi_create_encode_v2( opj_pi_iterator_t *pi, struct opj_cp_v2 *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(opj_image_t * image, opj_cp_t * cp, int tileno);
+
+/**
+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_v2(struct opj_image * image, struct opj_cp_v2 * cp, OPJ_UINT32 tileno);
+
+/**
+Destroy a packet iterator
+@param pi Previously created packet iterator
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which the packets were listed
+@see pi_create
+*/
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int 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_v2(
+ 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
+*/
+opj_bool pi_next(opj_pi_iterator_t * pi);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __PI_H */
diff --git a/src/lib/openjp2/ppix_manager.c b/src/lib/openjp2/ppix_manager.c
new file mode 100644
index 00000000..5afbbfd7
--- /dev/null
+++ b/src/lib/openjp2/ppix_manager.c
@@ -0,0 +1,170 @@
+/*
+ * $Id: ppix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.c from 2KAN indexer
+ */
+
+#include "opj_includes.h"
+
+/*
+ * Write faix box of ppix
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] compno component number
+ * @param[in] cstr_info codestream information
+ * @param[in] EPHused true if if EPH option used
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of faix box
+ */
+int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio);
+
+int write_ppix( int coff, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp, compno, i;
+ opj_jp2_box_t *box;
+
+ /* printf("cstr_info.packno %d\n", cstr_info.packno); //NMAX? */
+
+ lenp = -1;
+ box = (opj_jp2_box_t *)opj_calloc( cstr_info.numcomps, sizeof(opj_jp2_box_t));
+
+ for (i=0;i<2;i++){
+ if (i) cio_seek( cio, lenp);
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_PPIX, 4); /* PPIX */
+
+ write_manf( i, cstr_info.numcomps, box, cio);
+
+ for (compno=0; compno<cstr_info.numcomps; compno++){
+ box[compno].length = write_ppixfaix( coff, compno, cstr_info, EPHused, j2klen, cio);
+ box[compno].type = JPIP_FAIX;
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+ }
+
+ opj_free(box);
+
+ return len;
+}
+
+int write_ppixfaix( int coff, int compno, opj_codestream_info_t cstr_info, opj_bool EPHused, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp, tileno, version, i, nmax, size_of_coding; /* 4 or 8*/
+ opj_tile_info_t *tile_Idx;
+ opj_packet_info_t packet;
+ int resno, precno, layno, num_packet;
+ int numOfres, numOfprec, numOflayers;
+ packet.end_pos = packet.end_ph_pos = packet.start_pos = -1;
+ (void)EPHused; /* unused ? */
+
+ if( j2klen > pow( 2, 32)){
+ size_of_coding = 8;
+ version = 1;
+ }
+ else{
+ size_of_coding = 4;
+ version = 0;
+ }
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_FAIX, 4); /* FAIX */
+ cio_write( cio, version, 1); /* Version 0 = 4 bytes */
+
+ nmax = 0;
+ for( i=0; i<=cstr_info.numdecompos[compno]; i++)
+ nmax += cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * cstr_info.numlayers;
+
+ cio_write( cio, nmax, size_of_coding); /* NMAX */
+ cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
+
+ for( tileno=0; tileno<cstr_info.tw*cstr_info.th; tileno++){
+ tile_Idx = &cstr_info.tile[ tileno];
+
+ num_packet=0;
+ numOfres = cstr_info.numdecompos[compno] + 1;
+
+ for( resno=0; resno<numOfres ; resno++){
+ numOfprec = tile_Idx->pw[resno]*tile_Idx->ph[resno];
+ for( precno=0; precno<numOfprec; precno++){
+ numOflayers = cstr_info.numlayers;
+ for( layno=0; layno<numOflayers; layno++){
+
+ switch ( cstr_info.prog){
+ case LRCP:
+ packet = tile_Idx->packet[ ((layno*numOfres+resno)*cstr_info.numcomps+compno)*numOfprec+precno];
+ break;
+ case RLCP:
+ packet = tile_Idx->packet[ ((resno*numOflayers+layno)*cstr_info.numcomps+compno)*numOfprec+precno];
+ break;
+ case RPCL:
+ packet = tile_Idx->packet[ ((resno*numOfprec+precno)*cstr_info.numcomps+compno)*numOflayers+layno];
+ break;
+ case PCRL:
+ packet = tile_Idx->packet[ ((precno*cstr_info.numcomps+compno)*numOfres+resno)*numOflayers + layno];
+ break;
+ case CPRL:
+ packet = tile_Idx->packet[ ((compno*numOfprec+precno)*numOfres+resno)*numOflayers + layno];
+ break;
+ default:
+ fprintf( stderr, "failed to ppix indexing\n");
+ }
+
+ cio_write( cio, packet.start_pos-coff, size_of_coding); /* start position */
+ cio_write( cio, packet.end_pos-packet.start_pos+1, size_of_coding); /* length */
+
+ num_packet++;
+ }
+ }
+ }
+
+ while( num_packet < nmax){ /* PADDING */
+ cio_write( cio, 0, size_of_coding); /* start position */
+ cio_write( cio, 0, size_of_coding); /* length */
+ num_packet++;
+ }
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
diff --git a/src/lib/openjp2/raw.c b/src/lib/openjp2/raw.c
new file mode 100644
index 00000000..3d231bfd
--- /dev/null
+++ b/src/lib/openjp2/raw.c
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * 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"
+
+/*
+==========================================================
+ 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);
+ }
+}
+
+int raw_numbytes(opj_raw_t *raw) {
+ return raw->bp - raw->start;
+}
+
+void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len) {
+ raw->start = bp;
+ raw->lenmax = len;
+ raw->len = 0;
+ raw->c = 0;
+ raw->ct = 0;
+}
+
+int raw_decode(opj_raw_t *raw) {
+ int 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/src/lib/openjp2/raw.h b/src/lib/openjp2/raw.h
new file mode 100644
index 00000000..3c4b372f
--- /dev/null
+++ b/src/lib/openjp2/raw.h
@@ -0,0 +1,100 @@
+/*
+ * 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
+ * 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.
+*/
+
+/** @defgroup RAW RAW - Implementation of operations for raw encoding */
+/*@{*/
+
+/**
+RAW encoding operations
+*/
+typedef struct opj_raw {
+ /** temporary buffer where bits are coded or decoded */
+ unsigned char c;
+ /** number of bits already read or free to write */
+ unsigned int ct;
+ /** maximum length to decode */
+ unsigned int lenmax;
+ /** length decoded */
+ unsigned int len;
+ /** pointer to the current position in the buffer */
+ unsigned char *bp;
+ /** pointer to the start of the buffer */
+ unsigned char *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
+*/
+int 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, unsigned char *bp, int len);
+/**
+Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN
+@param raw RAW handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int raw_decode(opj_raw_t *raw);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __RAW_H */
diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c
new file mode 100644
index 00000000..2418e586
--- /dev/null
+++ b/src/lib/openjp2/t1.c
@@ -0,0 +1,1410 @@
+/*
+ * 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 <seg@haxxed.com>
+ * 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 "t1_luts.h"
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static INLINE OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient);
+static OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f);
+static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f);
+static OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f);
+static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos);
+static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos);
+static void opj_t1_updateflags(flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride);
+/**
+Encode significant pass
+*/
+static void opj_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 opj_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 opj_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 opj_t1_dec_sigpass( opj_t1_t *t1,
+ OPJ_INT32 bpno,
+ OPJ_UINT32 orient,
+ OPJ_BYTE type,
+ OPJ_UINT32 cblksty);
+
+
+/**
+Encode refinement pass
+*/
+static void opj_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);
+
+
+/**
+Encode refinement pass
+*/
+static void opj_t1_enc_refpass( opj_t1_t *t1,
+ OPJ_INT32 bpno,
+ OPJ_INT32 *nmsedec,
+ OPJ_BYTE type,
+ OPJ_UINT32 cblksty);
+
+/**
+Decode refinement pass
+*/
+static void opj_t1_dec_refpass( opj_t1_t *t1,
+ OPJ_INT32 bpno,
+ OPJ_BYTE type,
+ OPJ_UINT32 cblksty);
+
+/**
+Decode refinement pass
+*/
+static void opj_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 clean-up pass
+*/
+static void opj_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_partial(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf);
+static void t1_dec_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf);
+static void t1_dec_clnpass_step_vsc(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ int partial,
+ int vsc);
+/**
+Encode clean-up pass
+*/
+static void opj_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,
+ int bpno,
+ int orient,
+ int cblksty);
+static double t1_getwmsedec(
+ int nmsedec,
+ int compno,
+ int level,
+ int orient,
+ int bpno,
+ int qmfbid,
+ double stepsize,
+ int numcomps,
+ int mct);
+
+static OPJ_FLOAT64 t1_getwmsedec_v2(
+ 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);
+
+static void opj_t1_encode_cblk( opj_t1_t *t1,
+ opj_tcd_cblk_enc_v2_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_v2_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 opj_bool opj_t1_decode_cblk( opj_t1_t *t1,
+ opj_tcd_cblk_dec_v2_t* cblk,
+ OPJ_UINT32 orient,
+ OPJ_UINT32 roishift,
+ OPJ_UINT32 cblksty);
+
+opj_bool opj_t1_allocate_buffers( opj_t1_t *t1,
+ OPJ_UINT32 w,
+ OPJ_UINT32 h);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+OPJ_BYTE opj_t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) {
+ return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)];
+}
+
+OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 f) {
+ return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+OPJ_UINT32 opj_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);
+}
+
+OPJ_BYTE opj_t1_getspb(OPJ_UINT32 f) {
+ return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+OPJ_INT16 opj_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)];
+}
+
+OPJ_INT16 opj_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)];
+}
+
+void opj_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;
+}
+
+void opj_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, opj_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 += opj_t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag)); /* ESSAI */
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
+ mqc_bypass_enc(mqc, v);
+ } else {
+ mqc_encode(mqc, v ^ opj_t1_getspb(flag));
+ }
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ *flagsp |= T1_VISIT;
+ }
+}
+void opj_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;
+ opj_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);
+ }
+ }
+ }
+}
+
+
+void opj_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 += opj_t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ v = int_abs(*datap) & one ? 1 : 0;
+ mqc_setcurctx(mqc, opj_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;
+ }
+}
+
+
+void opj_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;
+ opj_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);
+ }
+ }
+ }
+}
+
+
+void opj_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, opj_t1_getctxno_zc(flag, orient));
+ v = int_abs(*datap) & one ? 1 : 0;
+ mqc_encode(mqc, v);
+ if (v) {
+LABEL_PARTIAL:
+ *nmsedec += opj_t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
+ v = *datap < 0 ? 1 : 0;
+ mqc_encode(mqc, v ^ opj_t1_getspb(flag));
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp &= ~T1_VISIT;
+}
+
+static void t1_dec_clnpass_step_partial(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf)
+{
+ int v, flag;
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ OPJ_ARG_NOT_USED(orient);
+
+ flag = *flagsp;
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ opj_t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ *flagsp &= ~T1_VISIT;
+} /* VSC and BYPASS by Antonin */
+
+static void t1_dec_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf)
+{
+ int v, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = *flagsp;
+ if (!(flag & (T1_SIG | T1_VISIT))) {
+ mqc_setcurctx(mqc, opj_t1_getctxno_zc(flag, orient));
+ if (mqc_decode(mqc)) {
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ opj_t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp &= ~T1_VISIT;
+} /* VSC and BYPASS by Antonin */
+
+static void t1_dec_clnpass_step_vsc(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ int partial,
+ int vsc)
+{
+ int v, 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, opj_t1_getctxno_zc(flag, orient));
+ if (mqc_decode(mqc)) {
+LABEL_PARTIAL:
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ opj_t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp &= ~T1_VISIT;
+}
+
+void opj_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;
+ opj_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,
+ int bpno,
+ int orient,
+ int cblksty)
+{
+ int i, j, k, one, half, oneplushalf, agg, runlen, vsc;
+ int segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ one = 1 << bpno;
+ half = one >> 1;
+ oneplushalf = one | half;
+ if (cblksty & J2K_CCP_CBLKSTY_VSC) {
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ if (k + 3 < t1->h) {
+ 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 = 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 = (j == k + 3 || j == t1->h - 1) ? 1 : 0;
+ t1_dec_clnpass_step_vsc(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ orient,
+ oneplushalf,
+ agg && (j == k + runlen),
+ vsc);
+ }
+ }
+ }
+ } else {
+ int *data1 = t1->data;
+ flag_t *flags1 = &t1->flags[1];
+ for (k = 0; k < (t1->h & ~3); k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ int *data2 = data1 + i;
+ flag_t *flags2 = flags1 + i;
+ 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));
+ 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);
+ flags2 += runlen * t1->flags_stride;
+ data2 += runlen * t1->w;
+ for (j = k + runlen; j < k + 4 && j < t1->h; ++j) {
+ flags2 += t1->flags_stride;
+ if (agg && (j == k + runlen)) {
+ t1_dec_clnpass_step_partial(t1, flags2, data2, orient, oneplushalf);
+ } else {
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ }
+ data2 += t1->w;
+ }
+ } else {
+ flags2 += t1->flags_stride;
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ data2 += t1->w;
+ flags2 += t1->flags_stride;
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ data2 += t1->w;
+ flags2 += t1->flags_stride;
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ data2 += t1->w;
+ flags2 += t1->flags_stride;
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ data2 += t1->w;
+ }
+ }
+ data1 += t1->w << 2;
+ flags1 += t1->flags_stride << 2;
+ }
+ for (i = 0; i < t1->w; ++i) {
+ int *data2 = data1 + i;
+ flag_t *flags2 = flags1 + i;
+ for (j = k; j < t1->h; ++j) {
+ flags2 += t1->flags_stride;
+ t1_dec_clnpass_step(t1, flags2, data2, orient, oneplushalf);
+ data2 += t1->w;
+ }
+ }
+ }
+
+ if (segsym) {
+ int 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 double t1_getwmsedec(
+ int nmsedec,
+ int compno,
+ int level,
+ int orient,
+ int bpno,
+ int qmfbid,
+ double stepsize,
+ int numcomps,
+ int mct)
+{
+ double w1, w2, wmsedec;
+ if (qmfbid == 1) {
+ w1 = (mct && numcomps==3) ? mct_getnorm(compno) : 1.0;
+ w2 = dwt_getnorm(level, orient);
+ } else { /* if (qmfbid == 0) */
+ w1 = (mct && numcomps==3) ? mct_getnorm_real(compno) : 1.0;
+ w2 = dwt_getnorm_real(level, orient);
+ }
+ wmsedec = w1 * w2 * stepsize * (1 << bpno);
+ wmsedec *= wmsedec * nmsedec / 8192.0;
+
+ return wmsedec;
+}
+
+/** mod fixed_quality */
+static OPJ_FLOAT64 t1_getwmsedec_v2(
+ 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 = opj_dwt_getnorm(level, orient);
+ } else { /* if (qmfbid == 0) */
+ w2 = opj_dwt_getnorm_real(level, orient);
+ }
+
+ wmsedec = w1 * w2 * stepsize * (1 << bpno);
+ wmsedec *= wmsedec * nmsedec / 8192.0;
+
+ return wmsedec;
+}
+
+opj_bool opj_t1_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 OPJ_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 OPJ_FALSE;
+ }
+ t1->flagssize=flagssize;
+ }
+ memset(t1->flags,0,flagssize * sizeof(flag_t));
+
+ t1->w=w;
+ t1->h=h;
+
+ return OPJ_TRUE;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+/**
+ * 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* opj_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) {
+ opj_t1_destroy(l_t1);
+ return 00;
+ }
+
+ l_t1->raw = raw_create();
+ if (! l_t1->raw) {
+ opj_t1_destroy(l_t1);
+ return 00;
+ }
+
+ return l_t1;
+}
+
+
+/**
+ * Destroys a previously created T1 handle
+ *
+ * @param p_t1 Tier 1 handle to destroy
+*/
+void opj_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);
+}
+
+opj_bool opj_t1_decode_cblks( opj_t1_t* t1,
+ opj_tcd_tilecomp_v2_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_v2_t* res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_v2_t* restrict band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; ++precno) {
+ opj_tcd_precinct_v2_t* precinct = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
+ opj_tcd_cblk_dec_v2_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;
+
+ if (OPJ_FALSE == opj_t1_decode_cblk(
+ t1,
+ cblk,
+ band->bandno,
+ tccp->roishift,
+ tccp->cblksty)) {
+ return OPJ_FALSE;
+ }
+
+ x = cblk->x0 - band->x0;
+ y = cblk->y0 - band->y0;
+ if (band->bandno & 1) {
+ opj_tcd_resolution_v2_t* pres = &tilec->resolutions[resno - 1];
+ x += pres->x1 - pres->x0;
+ }
+ if (band->bandno & 2) {
+ opj_tcd_resolution_v2_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 / 2;
+ }
+ }
+ } 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 */
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_t1_decode_cblk(opj_t1_t *t1,
+ opj_tcd_cblk_dec_v2_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(!opj_t1_allocate_buffers(
+ t1,
+ cblk->x1 - cblk->x0,
+ cblk->y1 - cblk->y0))
+ {
+ return OPJ_FALSE;
+ }
+
+ 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 {
+ if (OPJ_FALSE == mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ for (passno = 0; passno < seg->real_num_passes; ++passno) {
+ switch (passtype) {
+ case 0:
+ opj_t1_dec_sigpass(t1, bpno+1, orient, type, cblksty);
+ break;
+ case 1:
+ opj_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--;
+ }
+ }
+ }
+ return OPJ_TRUE;
+}
+
+opj_bool opj_t1_encode_cblks( opj_t1_t *t1,
+ opj_tcd_tile_v2_t *tile,
+ opj_tcp_v2_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_v2_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_v2_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_v2_t* restrict band = &res->bands[bandno];
+ OPJ_INT32 bandconst = 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192));
+
+ for (precno = 0; precno < res->pw * res->ph; ++precno) {
+ opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) {
+ opj_tcd_cblk_enc_v2_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_v2_t *pres = &tilec->resolutions[resno - 1];
+ x += pres->x1 - pres->x0;
+ }
+ if (band->bandno & 2) {
+ opj_tcd_resolution_v2_t *pres = &tilec->resolutions[resno - 1];
+ y += pres->y1 - pres->y0;
+ }
+
+ if(!opj_t1_allocate_buffers(
+ t1,
+ cblk->x1 - cblk->x0,
+ cblk->y1 - cblk->y0))
+ {
+ return OPJ_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,
+ bandconst) >> (11 - T1_NMSEDEC_FRACBITS);
+ }
+ }
+ }
+
+ opj_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 OPJ_TRUE;
+}
+
+/** mod fixed_quality */
+void opj_t1_encode_cblk(opj_t1_t *t1,
+ opj_tcd_cblk_enc_v2_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_v2_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_v2_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:
+ opj_t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty);
+ break;
+ case 1:
+ opj_t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty);
+ break;
+ case 2:
+ opj_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_v2(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; passno<cblk->totalpasses; passno++) {
+ opj_tcd_pass_v2_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);
+ }
+}
+
+void opj_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;
+ opj_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 */
+
+
+void opj_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, opj_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 */
+
+void opj_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;
+ opj_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 */
+
+void opj_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;
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ } else {
+ mqc_setcurctx(mqc, opj_t1_getctxno_zc(flag, orient));
+ if (mqc_decode(mqc)) {
+ mqc_setcurctx(mqc, opj_t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ opj_t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ opj_t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp |= T1_VISIT;
+ }
+} /* VSC and BYPASS by Antonin */
+
diff --git a/src/lib/openjp2/t1.h b/src/lib/openjp2/t1.h
new file mode 100644
index 00000000..ab6c626d
--- /dev/null
+++ b/src/lib/openjp2/t1.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
+ * 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.
+*/
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/* ----------------------------------------------------------------------- */
+#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)*/
+
+/* ----------------------------------------------------------------------- */
+
+typedef OPJ_INT16 flag_t;
+
+/**
+Tier-1 coding (coding of code-block coefficients)
+*/
+typedef struct opj_t1 {
+ /** codec context */
+ opj_common_ptr cinfo; /* TODO MSD : TO BE REMOVED */
+
+ /** MQC component */
+ opj_mqc_t *mqc;
+ /** RAW component */
+ opj_raw_t *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 */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Encode the code-blocks of a tile
+@param t1 T1 handle
+@param tile The tile to encode
+@param tcp Tile coding parameters
+@param mct_norms FIXME DOC
+*/
+opj_bool opj_t1_encode_cblks( opj_t1_t *t1,
+ opj_tcd_tile_v2_t *tile,
+ opj_tcp_v2_t *tcp,
+ const OPJ_FLOAT64 * mct_norms);
+
+/**
+Decode the code-blocks of a tile
+@param t1 T1 handle
+@param tilec The tile to decode
+@param tccp Tile coding parameters
+*/
+opj_bool opj_t1_decode_cblks( opj_t1_t* t1,
+ opj_tcd_tilecomp_v2_t* tilec,
+ opj_tccp_t* tccp);
+
+
+
+/**
+ * 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* opj_t1_create();
+
+/**
+ * Destroys a previously created T1 handle
+ *
+ * @param p_t1 Tier 1 handle to destroy
+*/
+void opj_t1_destroy(opj_t1_t *p_t1);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T1_H */
diff --git a/src/lib/openjp2/t1_generate_luts.c b/src/lib/openjp2/t1_generate_luts.c
new file mode 100644
index 00000000..ffeff03e
--- /dev/null
+++ b/src/lib/openjp2/t1_generate_luts.c
@@ -0,0 +1,274 @@
+/*
+ * 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 <seg@haxxed.com>
+ * 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"
+
+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/src/lib/openjp2/t1_luts.h b/src/lib/openjp2/t1_luts.h
new file mode 100644
index 00000000..1523b33a
--- /dev/null
+++ b/src/lib/openjp2/t1_luts.h
@@ -0,0 +1,143 @@
+/* This file was automatically generated by t1_generate_luts.c */
+
+static OPJ_BYTE 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 OPJ_BYTE 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 OPJ_BYTE 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 OPJ_INT16 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 OPJ_INT16 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 OPJ_INT16 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 OPJ_INT16 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/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c
new file mode 100644
index 00000000..372b10ea
--- /dev/null
+++ b/src/lib/openjp2/t2.c
@@ -0,0 +1,1271 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static void t2_putcommacode(opj_bio_t *bio, int n);
+
+static OPJ_UINT32 opj_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 opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n);
+static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio);
+
+/**
+Encode a packet of a tile to a destination buffer
+@param tileno Number of the tile encoded
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@param dest Destination buffer
+@param p_data_written FIXME DOC
+@param len Length of the destination buffer
+@param cstr_info Codestream information structure
+@return
+*/
+static opj_bool opj_t2_encode_packet( OPJ_UINT32 tileno,
+ opj_tcd_tile_v2_t *tile,
+ opj_tcp_v2_t *tcp,
+ opj_pi_iterator_t *pi,
+ OPJ_BYTE *dest,
+ OPJ_UINT32 * p_data_written,
+ OPJ_UINT32 len,
+ opj_codestream_info_t *cstr_info);
+
+/**
+Decode a packet of a tile from a source buffer
+@param t2 T2 handle
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@param src Source buffer
+@param data_read FIXME DOC
+@param max_length FIXME DOC
+@param pack_info Packet information
+
+@return FIXME DOC
+*/
+static opj_bool opj_t2_decode_packet( opj_t2_v2_t* t2,
+ opj_tcd_tile_v2_t *tile,
+ opj_tcp_v2_t *tcp,
+ opj_pi_iterator_t *pi,
+ OPJ_BYTE *src,
+ OPJ_UINT32 * data_read,
+ OPJ_UINT32 max_length,
+ opj_packet_info_t *pack_info);
+
+static opj_bool opj_t2_skip_packet( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_t *p_tile,
+ opj_tcp_v2_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);
+
+static opj_bool opj_t2_read_packet_header( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_t *p_tile,
+ opj_tcp_v2_t *p_tcp,
+ opj_pi_iterator_t *p_pi,
+ opj_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);
+
+static opj_bool opj_t2_read_packet_data(opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_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);
+
+static opj_bool opj_t2_skip_packet_data(opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_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);
+
+/**
+@param cblk
+@param index
+@param cblksty
+@param first
+*/
+static opj_bool opj_t2_init_seg( opj_tcd_cblk_dec_v2_t* cblk,
+ OPJ_UINT32 index,
+ OPJ_UINT32 cblksty,
+ OPJ_UINT32 first);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+/* #define RESTART 0x04 */
+// TODO MSD->LHE
+static void t2_putcommacode(opj_bio_t *bio, int n) {
+ while (--n >= 0) {
+ bio_write(bio, 1, 1);
+ }
+ bio_write(bio, 0, 1);
+}
+
+OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio)
+{
+ OPJ_UINT32 n = 0;
+ while (bio_read(bio, 1)) {
+ ++n;
+ }
+ return n;
+}
+
+void opj_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);
+ }
+}
+
+OPJ_UINT32 opj_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));
+}
+
+/* ----------------------------------------------------------------------- */
+
+opj_bool opj_t2_encode_packets( opj_t2_v2_t* p_t2,
+ OPJ_UINT32 p_tile_no,
+ opj_tcd_tile_v2_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_v2_t *l_cp = p_t2->cp;
+ opj_tcp_v2_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_v2(l_image, l_cp, p_tile_no, p_t2_mode);
+ if (!l_pi) {
+ return OPJ_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;
+
+ // TODO MSD : check why this function cannot fail (cf. v1)
+ pi_create_encode_v2(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 (! opj_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_v2(l_pi, l_nb_pocs);
+ return OPJ_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_v2(l_pi, l_nb_pocs);
+ return OPJ_FALSE;
+ }
+ }
+
+ ++l_current_pi;
+ }
+ }
+ }
+ else { /* t2_mode == FINAL_PASS */
+ pi_create_encode_v2(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 (! opj_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_v2(l_pi, l_nb_pocs);
+ return OPJ_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_v2(l_pi, l_nb_pocs);
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_t2_decode_packets( opj_t2_v2_t *p_t2,
+ OPJ_UINT32 p_tile_no,
+ opj_tcd_tile_v2_t *p_tile,
+ OPJ_BYTE *p_src,
+ OPJ_UINT32 * p_data_read,
+ OPJ_UINT32 p_max_len,
+ opj_codestream_index_t *p_cstr_index)
+{
+ 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_v2_t *l_cp = p_t2->cp;
+ opj_cp_v2_t *cp = p_t2->cp;
+ opj_tcp_v2_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;
+
+#ifdef TODO_MSD
+ if (p_cstr_index) {
+ l_pack_info = p_cstr_index->tile_index[p_tile_no].packet;
+ }
+#endif
+
+ /* create a packet iterator */
+ l_pi = pi_create_decode_v2(l_image, l_cp, p_tile_no);
+ if (!l_pi) {
+ return OPJ_FALSE;
+ }
+
+ tp_start_packno = 0;
+ l_current_pi = l_pi;
+
+ for (pino = 0; pino <= l_tcp->numpocs; ++pino) {
+
+ /* if the resolution needed is to low, one dim of the tilec could be equal to zero
+ * and no packets are used to encode this resolution and
+ * l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions
+ * and no l_img_comp->resno_decoded are computed
+ */
+ opj_bool* first_pass_failed = (opj_bool*)opj_malloc(l_image->numcomps * sizeof(opj_bool));
+ memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(opj_bool));
+
+ 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;
+
+ first_pass_failed[l_current_pi->compno] = OPJ_FALSE;
+
+ if (! opj_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_v2(l_pi,l_nb_pocs);
+ return OPJ_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 (! opj_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_v2(l_pi,l_nb_pocs);
+ return OPJ_FALSE;
+ }
+ }
+
+ if (first_pass_failed[l_current_pi->compno]) {
+ l_img_comp = &(l_image->comps[l_current_pi->compno]);
+ if (l_img_comp->resno_decoded == 0)
+ l_img_comp->resno_decoded = p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1;
+ }
+
+ l_current_data += l_nb_bytes_read;
+ p_max_len -= l_nb_bytes_read;
+
+ /* INDEX >> */
+#ifdef TODO_MSD
+ if(p_cstr_info) {
+ opj_tile_info_v2_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;
+ }
+#endif
+ /* << INDEX */
+ }
+ ++l_current_pi;
+
+ opj_free(first_pass_failed);
+ }
+ /* INDEX >> */
+#ifdef TODO_MSD
+ 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 */
+ }
+#endif
+ /* << INDEX */
+
+ /* don't forget to release pi */
+ pi_destroy_v2(l_pi,l_nb_pocs);
+ *p_data_read = l_current_data - p_src;
+ return OPJ_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_v2_t* opj_t2_create(opj_image_t *p_image, opj_cp_v2_t *p_cp)
+{
+ /* create the t2 structure */
+ opj_t2_v2_t *l_t2 = (opj_t2_v2_t*)opj_malloc(sizeof(opj_t2_v2_t));
+ if (!l_t2) {
+ return NULL;
+ }
+ memset(l_t2,0,sizeof(opj_t2_v2_t));
+
+ l_t2->image = p_image;
+ l_t2->cp = p_cp;
+
+ return l_t2;
+}
+
+void opj_t2_destroy(opj_t2_v2_t *t2) {
+ if(t2) {
+ opj_free(t2);
+ }
+}
+
+opj_bool opj_t2_decode_packet( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_t *p_tile,
+ opj_tcp_v2_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)
+{
+ opj_bool l_read_data;
+ OPJ_UINT32 l_nb_bytes_read = 0;
+ OPJ_UINT32 l_nb_total_bytes_read = 0;
+
+ *p_data_read = 0;
+
+ if (! opj_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 OPJ_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 (! opj_t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+ return OPJ_FALSE;
+ }
+
+ l_nb_total_bytes_read += l_nb_bytes_read;
+ }
+
+ *p_data_read = l_nb_total_bytes_read;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_t2_encode_packet( OPJ_UINT32 tileno,
+ opj_tcd_tile_v2_t * tile,
+ opj_tcp_v2_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_v2_t *band = 00;
+ opj_tcd_cblk_enc_v2_t* cblk = 00;
+ opj_tcd_pass_v2_t *pass = 00;
+
+ opj_tcd_tilecomp_v2_t *tilec = &tile->comps[compno];
+ opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+ opj_bio_t *bio = 00; /* BIO component */
+
+ /* <SOP 0xff91> */
+ 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;
+ }
+ /* </SOP> */
+
+ if (!layno) {
+ band = res->bands;
+
+ for(bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_precinct_v2_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_v2_t* cblk = &prc->cblks.enc[cblkno];
+
+ cblk->numpasses = 0;
+ tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps);
+ }
+ ++band;
+ }
+ }
+
+ bio = opj_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_v2_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 */
+ opj_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)) {
+ opj_bio_destroy(bio);
+ return OPJ_FALSE; /* modified to eliminate longjmp !! */
+ }
+
+ l_nb_bytes = bio_numbytes(bio);
+ c += l_nb_bytes;
+ length -= l_nb_bytes;
+
+ opj_bio_destroy(bio);
+
+ /* <EPH 0xff92> */
+ if (tcp->csty & J2K_CP_CSTY_EPH) {
+ c[0] = 255;
+ c[1] = 146;
+ c += 2;
+ length -= 2;
+ }
+ /* </EPH> */
+
+ /* << 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_v2_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 OPJ_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 OPJ_TRUE;
+}
+
+static opj_bool opj_t2_skip_packet( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_t *p_tile,
+ opj_tcp_v2_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)
+{
+ opj_bool l_read_data;
+ OPJ_UINT32 l_nb_bytes_read = 0;
+ OPJ_UINT32 l_nb_total_bytes_read = 0;
+
+ *p_data_read = 0;
+
+ if (! opj_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 OPJ_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 (! opj_t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info)) {
+ return OPJ_FALSE;
+ }
+
+ l_nb_total_bytes_read += l_nb_bytes_read;
+ }
+ *p_data_read = l_nb_total_bytes_read;
+
+ return OPJ_TRUE;
+}
+
+
+
+opj_bool opj_t2_read_packet_header( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_t *p_tile,
+ opj_tcp_v2_t *p_tcp,
+ opj_pi_iterator_t *p_pi,
+ opj_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_v2_t *l_cp = p_t2->cp;
+ opj_bio_t *l_bio = 00; /* BIO component */
+ opj_tcd_band_v2_t *l_band = 00;
+ opj_tcd_cblk_dec_v2_t* l_cblk = 00;
+ opj_tcd_resolution_v2_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_v2_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 = opj_bio_create();
+ if (! l_bio) {
+ return OPJ_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);
+ opj_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 = OPJ_FALSE;
+ *p_data_read = l_current_data - p_src_data;
+ return OPJ_TRUE;
+ }
+
+ l_band = l_res->bands;
+ for (bandno = 0; bandno < l_res->numbands; ++bandno) {
+ opj_tcd_precinct_v2_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 = opj_t2_getnumpasses(l_bio);
+ l_increment = opj_t2_getcommacode(l_bio);
+
+ /* length indicator increment */
+ l_cblk->numlenbits += l_increment;
+ l_segno = 0;
+
+ if (!l_cblk->numsegs) {
+ if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) {
+ opj_bio_destroy(l_bio);
+ return OPJ_FALSE;
+ }
+ }
+ else {
+ l_segno = l_cblk->numsegs - 1;
+ if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) {
+ ++l_segno;
+ if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
+ opj_bio_destroy(l_bio);
+ return OPJ_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 (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
+ opj_bio_destroy(l_bio);
+ return OPJ_FALSE;
+ }
+ }
+ } while (n > 0);
+
+ ++l_cblk;
+ }
+
+ ++l_band;
+ }
+
+ if (bio_inalign(l_bio)) {
+ opj_bio_destroy(l_bio);
+ return OPJ_FALSE;
+ }
+
+ l_header_data += bio_numbytes(l_bio);
+ opj_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 = OPJ_TRUE;
+ *p_data_read = l_current_data - p_src_data;
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_t2_read_packet_data( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_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_v2_t *l_band = 00;
+ opj_tcd_cblk_dec_v2_t* l_cblk = 00;
+ opj_tcd_resolution_v2_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_v2_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 OPJ_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 ((l_cblk->len + l_seg->newlen) > 8192) {
+ opj_event_msg(p_t2->cinfo, EVT_WARNING,
+ "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+ l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(p_t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return OPJ_FALSE;
+ }
+ l_seg->newlen = 8192 - l_cblk->len;
+ opj_event_msg(p_t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", l_seg->newlen);
+ break;
+ };
+
+#endif /* USE_JPWL */
+
+ if ((l_cblk->len + l_seg->newlen) > 8192) {
+ return OPJ_FALSE;
+ }
+
+ 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 OPJ_TRUE;
+}
+
+opj_bool opj_t2_skip_packet_data( opj_t2_v2_t* p_t2,
+ opj_tcd_tile_v2_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_v2_t *l_band = 00;
+ opj_tcd_cblk_dec_v2_t* l_cblk = 00;
+ opj_tcd_resolution_v2_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_v2_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 OPJ_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 ((l_cblk->len + l_seg->newlen) > 8192) {
+ opj_event_msg(p_t2->cinfo, EVT_WARNING,
+ "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+ l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(p_t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return -999;
+ }
+ l_seg->newlen = 8192 - l_cblk->len;
+ opj_event_msg(p_t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", l_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;
+ }
+
+ ++l_band;
+ }
+
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_t2_init_seg( opj_tcd_cblk_dec_v2_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) {
+ opj_tcd_seg_t* new_segs;
+ cblk->m_current_max_segs += J2K_DEFAULT_NB_SEGS;
+
+ new_segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, cblk->m_current_max_segs * sizeof(opj_tcd_seg_t));
+ if(! new_segs) {
+ opj_free(cblk->segs);
+ cblk->segs = NULL;
+ cblk->m_current_max_segs = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to initialize segment %d\n", l_nb_segs); */
+ return OPJ_FALSE;
+ }
+ cblk->segs = new_segs;
+ }
+
+ 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 OPJ_TRUE;
+}
diff --git a/src/lib/openjp2/t2.h b/src/lib/openjp2/t2.h
new file mode 100644
index 00000000..2cefac9b
--- /dev/null
+++ b/src/lib/openjp2/t2.h
@@ -0,0 +1,140 @@
+/*
+ * 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 __T2_H
+#define __T2_H
+/**
+@file t2.h
+@brief Implementation of a tier-2 coding (packetization of code-block data) (T2)
+
+*/
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/**
+Tier-2 coding
+*/
+typedef struct opj_t2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */
+ opj_image_t *image;
+ /** pointer to the image coding parameters */
+ opj_cp_t *cp;
+} opj_t2_t;
+
+/**
+Tier-2 coding
+*/
+typedef struct opj_t2_v2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */
+ opj_image_t *image;
+ /** pointer to the image coding parameters */
+ opj_cp_v2_t *cp;
+} opj_t2_v2_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 p_data_written FIXME DOC
+@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 pino FIXME DOC
+@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
+*/
+opj_bool opj_t2_encode_packets( opj_t2_v2_t* t2,
+ OPJ_UINT32 tileno,
+ opj_tcd_tile_v2_t *tile,
+ OPJ_UINT32 maxlayers,
+ OPJ_BYTE *dest,
+ OPJ_UINT32 * p_data_written,
+ OPJ_UINT32 len,
+ opj_codestream_info_t *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 tileno number that identifies the tile for which to decode the packets
+@param tile tile for which to decode the packets
+@param src FIXME DOC
+@param p_data_read the source buffer
+@param len length of the source buffer
+@param cstr_info FIXME DOC
+
+@return FIXME DOC
+ */
+opj_bool opj_t2_decode_packets( opj_t2_v2_t *t2,
+ OPJ_UINT32 tileno,
+ opj_tcd_tile_v2_t *tile,
+ OPJ_BYTE *src,
+ OPJ_UINT32 * p_data_read,
+ OPJ_UINT32 len,
+ opj_codestream_index_t *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_v2_t* opj_t2_create(opj_image_t *p_image, opj_cp_v2_t *p_cp);
+
+/**
+Destroy a T2 handle
+@param t2 T2 handle to destroy
+*/
+void opj_t2_destroy(opj_t2_v2_t *t2);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T2_H */
diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c
new file mode 100644
index 00000000..d7725141
--- /dev/null
+++ b/src/lib/openjp2/tcd.c
@@ -0,0 +1,2109 @@
+/*
+ * 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 "opj_includes.h"
+
+/* ----------------------------------------------------------------------- */
+
+
+void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
+ int tileno, compno, resno, bandno, precno;/*, cblkno;*/
+
+ fprintf(fd, "image {\n");
+ fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n",
+ img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, tcd->image->y1);
+
+ for (tileno = 0; tileno < img->th * img->tw; tileno++) {
+ opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno];
+ fprintf(fd, " tile {\n");
+ fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n",
+ tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps);
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ fprintf(fd, " tilec {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n",
+ tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions);
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+ fprintf(fd, "\n res {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n",
+ res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands);
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ fprintf(fd, " band {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n",
+ band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps);
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prec = &band->precincts[precno];
+ fprintf(fd, " prec {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n",
+ prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch);
+ /*
+ for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) {
+ opj_tcd_cblk_t *cblk = &prec->cblks[cblkno];
+ fprintf(fd, " cblk {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d\n",
+ cblk->x0, cblk->y0, cblk->x1, cblk->y1);
+ fprintf(fd, " }\n");
+ }
+ */
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, "}\n");
+}
+/**
+* Allocates memory for a decoding code block.
+*/
+static opj_bool opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_v2_t * p_code_block);
+
+/**
+ * Deallocates the decoding data of the given precinct.
+ */
+static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_v2_t * p_precinct);
+
+/**
+ * Allocates memory for an encoding code block.
+ */
+static opj_bool opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_v2_t * p_code_block);
+
+/**
+ * Deallocates the encoding data of the given precinct.
+ */
+static void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_v2_t * p_precinct);
+
+
+/**
+Free the memory allocated for encoding
+@param tcd TCD handle
+*/
+static void opj_tcd_free_tile(opj_tcd_v2_t *tcd);
+
+
+static opj_bool opj_tcd_t2_decode ( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_src_data,
+ OPJ_UINT32 * p_data_read,
+ OPJ_UINT32 p_max_src_size,
+ opj_codestream_index_t *p_cstr_index );
+
+static opj_bool opj_tcd_t1_decode (opj_tcd_v2_t *p_tcd);
+
+static opj_bool opj_tcd_dwt_decode (opj_tcd_v2_t *p_tcd);
+
+static opj_bool opj_tcd_mct_decode (opj_tcd_v2_t *p_tcd);
+
+static opj_bool opj_tcd_dc_level_shift_decode (opj_tcd_v2_t *p_tcd);
+
+
+static opj_bool opj_tcd_dc_level_shift_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool opj_tcd_mct_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool opj_tcd_dwt_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool opj_tcd_t1_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool opj_tcd_t2_encode ( opj_tcd_v2_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 );
+
+static opj_bool opj_tcd_rate_allocate_encode( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_dest_data,
+ OPJ_UINT32 p_max_dest_size,
+ opj_codestream_info_t *p_cstr_info );
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Create a new TCD handle
+*/
+opj_tcd_v2_t* opj_tcd_create(opj_bool p_is_decoder)
+{
+ opj_tcd_v2_t *l_tcd = 00;
+
+ /* create the tcd structure */
+ l_tcd = (opj_tcd_v2_t*) opj_malloc(sizeof(opj_tcd_v2_t));
+ if (!l_tcd) {
+ return 00;
+ }
+ memset(l_tcd,0,sizeof(opj_tcd_v2_t));
+
+ l_tcd->m_is_decoder = p_is_decoder ? 1 : 0;
+
+ l_tcd->tcd_image = (opj_tcd_image_v2_t*)opj_malloc(sizeof(opj_tcd_image_v2_t));
+ if (!l_tcd->tcd_image) {
+ opj_free(l_tcd);
+ return 00;
+ }
+ memset(l_tcd->tcd_image,0,sizeof(opj_tcd_image_v2_t));
+
+ return l_tcd;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+void opj_tcd_rateallocate_fixed(opj_tcd_v2_t *tcd) {
+ OPJ_UINT32 layno;
+
+ for (layno = 0; layno < tcd->tcp->numlayers; layno++) {
+ opj_tcd_makelayer_fixed(tcd, layno, 1);
+ }
+}
+
+
+void opj_tcd_makelayer( opj_tcd_v2_t *tcd,
+ OPJ_UINT32 layno,
+ OPJ_FLOAT64 thresh,
+ OPJ_UINT32 final)
+{
+ OPJ_UINT32 compno, resno, bandno, precno, cblkno;
+ OPJ_UINT32 passno;
+
+ opj_tcd_tile_v2_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_v2_t *tilec = &tcd_tile->comps[compno];
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_v2_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_v2_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;
+ }
+ }
+ }
+ }
+ }
+}
+
+void opj_tcd_makelayer_fixed(opj_tcd_v2_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_v2_t *cp = tcd->cp;
+ opj_tcd_tile_v2_t *tcd_tile = tcd->tcd_image->tiles;
+ opj_tcp_v2_t *tcd_tcp = tcd->tcp;
+
+ for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+ opj_tcd_tilecomp_v2_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_v2_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_v2_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;
+ }
+ }
+ }
+ }
+ }
+}
+
+opj_bool opj_tcd_rateallocate( opj_tcd_v2_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_v2_t *cp = tcd->cp;
+ opj_tcd_tile_v2_t *tcd_tile = tcd->tcd_image->tiles;
+ opj_tcp_v2_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_v2_t *tilec = &tcd_tile->comps[compno];
+ tilec->numpix = 0;
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_v2_t *cblk = &prc->cblks.enc[cblkno];
+
+ for (passno = 0; passno < cblk->totalpasses; passno++) {
+ opj_tcd_pass_v2_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;
+ opj_bool success = OPJ_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_v2_t*t2 = opj_t2_create(tcd->image, cp);
+ OPJ_FLOAT64 thresh = 0;
+
+ if (t2 == 00) {
+ return OPJ_FALSE;
+ }
+
+ for (i = 0; i < 128; ++i) {
+ OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */
+
+ thresh = (lo + hi) / 2;
+
+ opj_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 (! opj_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 (! opj_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 = OPJ_TRUE;
+ goodthresh = stable_thresh == 0? thresh : stable_thresh;
+
+ opj_t2_destroy(t2);
+ } else {
+ success = OPJ_TRUE;
+ goodthresh = min;
+ }
+
+ if (!success) {
+ return OPJ_FALSE;
+ }
+
+ if(cstr_info) { /* Threshold for Marcela Index */
+ cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh;
+ }
+
+ opj_tcd_makelayer(tcd, layno, goodthresh, 1);
+
+ /* fixed_quality */
+ cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_init( opj_tcd_v2_t *p_tcd,
+ opj_image_t * p_image,
+ opj_cp_v2_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_v2_t *) opj_malloc(sizeof(opj_tcd_tile_v2_t));
+ if (! p_tcd->tcd_image->tiles) {
+ return OPJ_FALSE;
+ }
+ memset(p_tcd->tcd_image->tiles,0, sizeof(opj_tcd_tile_v2_t));
+
+ l_tile_comp_size = p_image->numcomps * sizeof(opj_tcd_tilecomp_v2_t);
+ p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_v2_t *) opj_malloc(l_tile_comp_size);
+ if (! p_tcd->tcd_image->tiles->comps ) {
+ return OPJ_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 OPJ_TRUE;
+}
+
+/**
+Destroy a previously created TCD handle
+*/
+void opj_tcd_destroy(opj_tcd_v2_t *tcd) {
+ if (tcd) {
+ opj_tcd_free_tile(tcd);
+
+ if (tcd->tcd_image) {
+ opj_free(tcd->tcd_image);
+ tcd->tcd_image = 00;
+ }
+ opj_free(tcd);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+#define MACRO_TCD_ALLOCATE(FUNCTION,TYPE,FRACTION,ELEMENT,FUNCTION_ELEMENT) \
+opj_bool FUNCTION ( opj_tcd_v2_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_v2_t * l_tcp = 00; \
+ opj_cp_v2_t * l_cp = 00; \
+ opj_tcd_tile_v2_t * l_tile = 00; \
+ opj_tccp_t *l_tccp = 00; \
+ opj_tcd_tilecomp_v2_t *l_tilec = 00; \
+ opj_image_comp_t * l_image_comp = 00; \
+ opj_tcd_resolution_v2_t *l_res = 00; \
+ opj_tcd_band_v2_t *l_band = 00; \
+ opj_stepsize_t * l_step_size = 00; \
+ opj_tcd_precinct_v2_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; \
+ /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/ \
+ \
+ /* 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); \
+ /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/ \
+ \
+ /*tile->numcomps = image->numcomps; */ \
+ for(compno = 0; compno < l_tile->numcomps; ++compno) { \
+ /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/ \
+ \
+ /* 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); \
+ /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ \
+ \
+ 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_malloc(l_data_size); \
+ if (! l_tilec->data ) { \
+ return OPJ_FALSE; \
+ } \
+ /*fprintf(stderr, "\tAllocate data of tilec (int): %d x OPJ_UINT32\n",l_data_size);*/ \
+ \
+ l_tilec->data_size = l_data_size; \
+ } \
+ else if (l_data_size > l_tilec->data_size) { \
+ OPJ_INT32 * new_data = (OPJ_INT32 *) opj_realloc(l_tilec->data, l_data_size); \
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to handle tile data\n"); */ \
+ fprintf(stderr, "Not enough memory to handle tile data\n"); \
+ if (! new_data) { \
+ opj_free(l_tilec->data); \
+ l_tilec->data = NULL; \
+ l_tilec->data_size = 0; \
+ return OPJ_FALSE; \
+ } \
+ l_tilec->data = new_data; \
+ /*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->data_size, l_data_size);*/ \
+ l_tilec->data_size = l_data_size; \
+ } \
+ \
+ l_data_size = l_tilec->numresolutions * sizeof(opj_tcd_resolution_v2_t); \
+ \
+ if (l_tilec->resolutions == 00) { \
+ l_tilec->resolutions = (opj_tcd_resolution_v2_t *) opj_malloc(l_data_size); \
+ if (! l_tilec->resolutions ) { \
+ return OPJ_FALSE; \
+ } \
+ /*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_v2_t): %d\n",l_data_size);*/ \
+ l_tilec->resolutions_size = l_data_size; \
+ memset(l_tilec->resolutions,0,l_data_size); \
+ } \
+ else if (l_data_size > l_tilec->resolutions_size) { \
+ opj_tcd_resolution_v2_t* new_resolutions = (opj_tcd_resolution_v2_t *) opj_realloc(l_tilec->resolutions, l_data_size); \
+ if (! new_resolutions) { \
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to tile resolutions\n"); */ \
+ fprintf(stderr, "Not enough memory to tile resolutions\n"); \
+ opj_free(l_tilec->resolutions); \
+ l_tilec->resolutions = NULL; \
+ l_tilec->resolutions_size = 0; \
+ return OPJ_FALSE; \
+ } \
+ l_tilec->resolutions = new_resolutions; \
+ /*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/ \
+ 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 = &opj_dwt_getgain_real; \
+ } \
+ else { \
+ l_gain_ptr = &opj_dwt_getgain; \
+ } \
+ /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ \
+ \
+ for(resno = 0; resno < l_tilec->numresolutions; ++resno) { \
+ /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/ \
+ 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); \
+ /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/ \
+ /* 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]; \
+ /*fprintf(stderr, "\t\t\tpdx=%d, pdy=%d\n", l_pdx, l_pdy);*/ \
+ /* 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; \
+ /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ \
+ \
+ 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); \
+ /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ \
+ \
+ l_nb_precincts = l_res->pw * l_res->ph; \
+ l_nb_precinct_size = l_nb_precincts * sizeof(opj_tcd_precinct_v2_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; \
+ /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ \
+ \
+ 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_v2_t *) opj_malloc( /*3 * */ l_nb_precinct_size); \
+ if (! l_band->precincts) { \
+ return OPJ_FALSE; \
+ } \
+ /*fprintf(stderr, "\t\t\t\tAllocate precincts of a band (opj_tcd_precinct_v2_t): %d\n",l_nb_precinct_size); */ \
+ 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) { \
+ \
+ opj_tcd_precinct_v2_t * new_precincts = (opj_tcd_precinct_v2_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size); \
+ if (! new_precincts) { \
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to handle band precints\n"); */ \
+ fprintf(stderr, "Not enough memory to handle band precints\n"); \
+ opj_free(l_band->precincts); \
+ l_band->precincts = NULL; \
+ l_band->precincts_data_size = 0; \
+ return OPJ_FALSE; \
+ } \
+ l_band->precincts = new_precincts; \
+ /*fprintf(stderr, "\t\t\t\tReallocate precincts of a band (opj_tcd_precinct_v2_t): from %d to %d\n",l_band->precincts_data_size, l_nb_precinct_size);*/ \
+ 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); \
+ /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/ \
+ /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/ \
+ \
+ /* precinct size (global) */ \
+ /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/ \
+ \
+ 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); \
+ /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/ \
+ \
+ tlcblkxstart = int_floordivpow2(l_current_precinct->x0, cblkwidthexpn) << cblkwidthexpn; \
+ /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/ \
+ tlcblkystart = int_floordivpow2(l_current_precinct->y0, cblkheightexpn) << cblkheightexpn; \
+ /*fprintf(stderr, "\t tlcblkystart =%d\n",tlcblkystart );*/ \
+ brcblkxend = int_ceildivpow2(l_current_precinct->x1, cblkwidthexpn) << cblkwidthexpn; \
+ /*fprintf(stderr, "\t brcblkxend =%d\n",brcblkxend );*/ \
+ brcblkyend = int_ceildivpow2(l_current_precinct->y1, cblkheightexpn) << cblkheightexpn; \
+ /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/ \
+ 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; \
+ /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",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 OPJ_FALSE; \
+ } \
+ /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_v2_t): %d\n",l_nb_code_blocks_size);*/ \
+ \
+ 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) { \
+ TYPE *new_ELEMENT = (TYPE*) opj_realloc(l_current_precinct->cblks.ELEMENT, l_nb_code_blocks_size); \
+ if (! new_ELEMENT) { \
+ opj_free(l_current_precinct->cblks.ELEMENT); \
+ l_current_precinct->cblks.ELEMENT = NULL; \
+ l_current_precinct->block_size = 0; \
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory for current precinct codeblock element\n"); */ \
+ fprintf(stderr, "Not enough memory for current precinct codeblock element\n"); \
+ return OPJ_FALSE; \
+ } \
+ l_current_precinct->cblks.ELEMENT = new_ELEMENT; \
+ /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_v2_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size); */\
+ \
+ 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_v2(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) { \
+ fprintf(stderr, "WARNING: No incltree created.\n"); \
+ /*return OPJ_FALSE;*/ \
+ } \
+ \
+ if (! l_current_precinct->imsbtree) { \
+ l_current_precinct->imsbtree = tgt_create_v2( \
+ 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) { \
+ fprintf(stderr, "WARNING: No imsbtree created.\n"); \
+ /*return OPJ_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 OPJ_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 OPJ_TRUE; \
+} \
+
+
+MACRO_TCD_ALLOCATE(opj_tcd_init_encode_tile, opj_tcd_cblk_enc_v2_t, 1.f, enc, opj_tcd_code_block_enc_allocate)
+MACRO_TCD_ALLOCATE(opj_tcd_init_decode_tile, opj_tcd_cblk_dec_v2_t, 0.5f, dec, opj_tcd_code_block_dec_allocate)
+
+#undef MACRO_TCD_ALLOCATE
+
+/**
+ * Allocates memory for an encoding code block.
+ */
+opj_bool opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_v2_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 OPJ_FALSE;
+ }
+
+ p_code_block->data[0] = 0;
+ 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 OPJ_FALSE;
+ }
+
+ p_code_block->passes = (opj_tcd_pass_v2_t*) opj_malloc(100 * sizeof(opj_tcd_pass_v2_t));
+ if (! p_code_block->passes) {
+ return OPJ_FALSE;
+ }
+ }
+
+ memset(p_code_block->layers,0,100 * sizeof(opj_tcd_layer_t));
+ memset(p_code_block->passes,0,100 * sizeof(opj_tcd_pass_v2_t));
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Allocates memory for a decoding code block.
+ */
+opj_bool opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_v2_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 OPJ_FALSE;
+ }
+ /*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/
+
+ 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 OPJ_FALSE;
+ }
+ memset(p_code_block->segs,0,l_seg_size);
+ /*fprintf(stderr, "Allocate %d elements of code_block->data\n", J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/
+
+ p_code_block->m_current_max_segs = J2K_DEFAULT_NB_SEGS;
+ /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/
+ }
+ /* TODO */
+ /*p_code_block->numsegs = 0; */
+
+ return OPJ_TRUE;
+}
+
+OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 i;
+ OPJ_UINT32 l_data_size = 0;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
+ opj_tcd_resolution_v2_t * l_res = 00;
+ OPJ_UINT32 l_size_comp, l_remaining;
+
+ l_tile_comp = p_tcd->tcd_image->tiles->comps;
+ l_img_comp = p_tcd->image->comps;
+
+ for (i=0;i<p_tcd->image->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;
+}
+
+opj_bool opj_tcd_encode_tile( opj_tcd_v2_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_v2_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_v2_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 */
+
+ /* FIXME _ProfStart(PGROUP_DC_SHIFT); */
+ /*---------------TILE-------------------*/
+ if (! opj_tcd_dc_level_shift_encode(p_tcd)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_DC_SHIFT); */
+
+ /* FIXME _ProfStart(PGROUP_MCT); */
+ if (! opj_tcd_mct_encode(p_tcd)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_MCT); */
+
+ /* FIXME _ProfStart(PGROUP_DWT); */
+ if (! opj_tcd_dwt_encode(p_tcd)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_DWT); */
+
+ /* FIXME _ProfStart(PGROUP_T1); */
+ if (! opj_tcd_t1_encode(p_tcd)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_T1); */
+
+ /* FIXME _ProfStart(PGROUP_RATE); */
+ if (! opj_tcd_rate_allocate_encode(p_tcd,p_dest,p_max_length,p_cstr_info)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_RATE); */
+
+ }
+ /*--------------TIER2------------------*/
+
+ /* INDEX */
+ if (p_cstr_info) {
+ p_cstr_info->index_write = 1;
+ }
+ /* FIXME _ProfStart(PGROUP_T2); */
+
+ if (! opj_tcd_t2_encode(p_tcd,p_dest,p_data_written,p_max_length,p_cstr_info)) {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_T2); */
+
+ /*---------------CLEAN-------------------*/
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_decode_tile( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE *p_src,
+ OPJ_UINT32 p_max_length,
+ OPJ_UINT32 p_tile_no,
+ opj_codestream_index_t *p_cstr_index
+ )
+{
+ OPJ_UINT32 l_data_read;
+ p_tcd->tcd_tileno = p_tile_no;
+ p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]);
+
+#ifdef TODO_MSD /* FIXME */
+ /* INDEX >> */
+ if(p_cstr_info) {
+ OPJ_UINT32 resno, compno, numprec = 0;
+ for (compno = 0; compno < (OPJ_UINT32) p_cstr_info->numcomps; compno++) {
+ opj_tcp_v2_t *tcp = &p_tcd->cp->tcps[0];
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_tcd_tilecomp_v2_t *tilec_idx = &p_tcd->tcd_image->tiles->comps[compno];
+ for (resno = 0; resno < tilec_idx->numresolutions; resno++) {
+ opj_tcd_resolution_v2_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 */
+#endif
+
+ /*--------------TIER2------------------*/
+ /* FIXME _ProfStart(PGROUP_T2); */
+ l_data_read = 0;
+ if
+ (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index))
+ {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_T2); */
+
+ /*------------------TIER1-----------------*/
+
+ /* FIXME _ProfStart(PGROUP_T1); */
+ if
+ (! opj_tcd_t1_decode(p_tcd))
+ {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_T1); */
+
+ /*----------------DWT---------------------*/
+
+ /* FIXME _ProfStart(PGROUP_DWT); */
+ if
+ (! opj_tcd_dwt_decode(p_tcd))
+ {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_DWT); */
+
+ /*----------------MCT-------------------*/
+ /* FIXME _ProfStart(PGROUP_MCT); */
+ if
+ (! opj_tcd_mct_decode(p_tcd))
+ {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_MCT); */
+
+ /* FIXME _ProfStart(PGROUP_DC_SHIFT); */
+ if
+ (! opj_tcd_dc_level_shift_decode(p_tcd))
+ {
+ return OPJ_FALSE;
+ }
+ /* FIXME _ProfStop(PGROUP_DC_SHIFT); */
+
+
+ /*---------------TILE-------------------*/
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_update_tile_data ( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_dest,
+ OPJ_UINT32 p_dest_length
+ )
+{
+ OPJ_UINT32 i,j,k,l_data_size = 0;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcd_tilecomp_v2_t * l_tilec = 00;
+ opj_tcd_resolution_v2_t * l_res;
+ OPJ_UINT32 l_size_comp, l_remaining;
+ OPJ_UINT32 l_stride, l_width,l_height;
+
+ l_data_size = opj_tcd_get_decoded_tile_size(p_tcd);
+ if (l_data_size > p_dest_length) {
+ return OPJ_FALSE;
+ }
+
+ l_tilec = p_tcd->tcd_image->tiles->comps;
+ l_img_comp = p_tcd->image->comps;
+
+ for (i=0;i<p_tcd->image->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;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (OPJ_CHAR) (*(l_src_ptr++));
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+ else {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (OPJ_BYTE) ((*(l_src_ptr++))&0xff);
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+
+ p_dest = (OPJ_BYTE *)l_dest_ptr;
+ }
+ break;
+ case 2:
+ {
+ const OPJ_INT32 * l_src_ptr = l_tilec->data;
+ OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest;
+
+ if (l_img_comp->sgnd) {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (OPJ_INT16) (*(l_src_ptr++));
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+ else {
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (OPJ_UINT16) ((*(l_src_ptr++))&0xffff);
+ }
+ l_src_ptr += l_stride;
+ }
+ }
+
+ p_dest = (OPJ_BYTE*) l_dest_ptr;
+ }
+ break;
+ case 4:
+ {
+ OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest;
+ OPJ_INT32 * l_src_ptr = l_tilec->data;
+
+ for (j=0;j<l_height;++j) {
+ for (k=0;k<l_width;++k) {
+ *(l_dest_ptr++) = (*(l_src_ptr++));
+ }
+ l_src_ptr += l_stride;
+ }
+
+ p_dest = (OPJ_BYTE*) l_dest_ptr;
+ }
+ break;
+ }
+
+ ++l_img_comp;
+ ++l_tilec;
+ }
+
+ return OPJ_TRUE;
+}
+
+
+
+
+void opj_tcd_free_tile(opj_tcd_v2_t *p_tcd)
+{
+ OPJ_UINT32 compno, resno, bandno, precno;
+ opj_tcd_tile_v2_t *l_tile = 00;
+ opj_tcd_tilecomp_v2_t *l_tile_comp = 00;
+ opj_tcd_resolution_v2_t *l_res = 00;
+ opj_tcd_band_v2_t *l_band = 00;
+ opj_tcd_precinct_v2_t *l_precinct = 00;
+ OPJ_UINT32 l_nb_resolutions, l_nb_precincts;
+ void (* l_tcd_code_block_deallocate) (opj_tcd_precinct_v2_t *) = 00;
+
+ if (! p_tcd) {
+ return;
+ }
+
+ if (! p_tcd->tcd_image) {
+ return;
+ }
+
+ if (p_tcd->m_is_decoder) {
+ l_tcd_code_block_deallocate = opj_tcd_code_block_dec_deallocate;
+ }
+ else {
+ l_tcd_code_block_deallocate = opj_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_v2_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_v2_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_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;
+}
+
+
+opj_bool opj_tcd_t2_decode (opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_src_data,
+ OPJ_UINT32 * p_data_read,
+ OPJ_UINT32 p_max_src_size,
+ opj_codestream_index_t *p_cstr_index
+ )
+{
+ opj_t2_v2_t * l_t2;
+
+ l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp);
+ if (l_t2 == 00) {
+ return OPJ_FALSE;
+ }
+
+ if (! opj_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_index)) {
+ opj_t2_destroy(l_t2);
+ return OPJ_FALSE;
+ }
+
+ opj_t2_destroy(l_t2);
+
+ /*---------------CLEAN-------------------*/
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_t1_decode ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 compno;
+ opj_t1_t * l_t1;
+ opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+ opj_tcd_tilecomp_v2_t* l_tile_comp = l_tile->comps;
+ opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
+
+
+ l_t1 = opj_t1_create();
+ if (l_t1 == 00) {
+ return OPJ_FALSE;
+ }
+
+ for (compno = 0; compno < l_tile->numcomps; ++compno) {
+ /* The +3 is headroom required by the vectorized DWT */
+ if (OPJ_FALSE == opj_t1_decode_cblks(l_t1, l_tile_comp, l_tccp)) {
+ opj_t1_destroy(l_t1);
+ return OPJ_FALSE;
+ }
+ ++l_tile_comp;
+ ++l_tccp;
+ }
+
+ opj_t1_destroy(l_t1);
+
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_tcd_dwt_decode ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 compno;
+ opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+ opj_tcd_tilecomp_v2_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 (! opj_dwt_decode(l_tile_comp, l_img_comp->resno_decoded+1)) {
+ return OPJ_FALSE;
+ }
+ }
+ else {
+ if (! dwt_decode_real_v2(l_tile_comp, l_img_comp->resno_decoded+1)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ ++l_tile_comp;
+ ++l_img_comp;
+ ++l_tccp;
+ }
+
+ return OPJ_TRUE;
+}
+opj_bool opj_tcd_mct_decode ( opj_tcd_v2_t *p_tcd )
+{
+ opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+ opj_tcp_v2_t * l_tcp = p_tcd->tcp;
+ opj_tcd_tilecomp_v2_t * l_tile_comp = l_tile->comps;
+ OPJ_UINT32 l_samples,i;
+
+ if (! l_tcp->mct) {
+ return OPJ_TRUE;
+ }
+
+ l_samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0);
+
+ if (l_tile->numcomps >= 3 ){
+ if (l_tcp->mct == 2) {
+ OPJ_BYTE ** l_data;
+
+ if (! l_tcp->m_mct_decoding_matrix) {
+ return OPJ_TRUE;
+ }
+
+ l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*));
+ if (! l_data) {
+ return OPJ_FALSE;
+ }
+
+ for (i=0;i<l_tile->numcomps;++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 OPJ_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);
+ }
+ }
+ }
+ else {
+ /* FIXME need to use opj_event_msg_v2 function */
+ fprintf(stderr,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",l_tile->numcomps);
+ }
+
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_tcd_dc_level_shift_decode ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 compno;
+ opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
+ opj_tccp_t * l_tccp = 00;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcd_resolution_v2_t* l_res = 00;
+ opj_tcp_v2_t * l_tcp = 00;
+ opj_tcd_tile_v2_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;j<l_height;++j) {
+ for (i = 0; i < l_width; ++i) {
+ *l_current_ptr = int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min, l_max);
+ ++l_current_ptr;
+ }
+ l_current_ptr += l_stride;
+ }
+ }
+ else {
+ for (j=0;j<l_height;++j) {
+ for (i = 0; i < l_width; ++i) {
+ OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr);
+ *l_current_ptr = int_clamp(lrintf(l_value) + l_tccp->m_dc_level_shift, l_min, l_max); ;
+ ++l_current_ptr;
+ }
+ l_current_ptr += l_stride;
+ }
+ }
+
+ ++l_img_comp;
+ ++l_tccp;
+ ++l_tile_comp;
+ }
+
+ return OPJ_TRUE;
+}
+
+
+
+/**
+ * Deallocates the encoding data of the given precinct.
+ */
+void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_v2_t * p_precinct)
+{
+ OPJ_UINT32 cblkno , l_nb_code_blocks;
+
+ opj_tcd_cblk_dec_v2_t * l_code_block = p_precinct->cblks.dec;
+ if (l_code_block) {
+ /*fprintf(stderr,"deallocate codeblock:{\n");*/
+ /*fprintf(stderr,"\t x0=%d, y0=%d, x1=%d, y1=%d\n",l_code_block->x0, l_code_block->y0, l_code_block->x1, l_code_block->y1);*/
+ /*fprintf(stderr,"\t numbps=%d, numlenbits=%d, len=%d, numnewpasses=%d, real_num_segs=%d, m_current_max_segs=%d\n ",
+ l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/
+
+
+ l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_v2_t);
+ /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/
+
+ 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;
+ }
+}
+
+/**
+ * Deallocates the encoding data of the given precinct.
+ */
+void opj_tcd_code_block_enc_deallocate (opj_tcd_precinct_v2_t * p_precinct)
+{
+ OPJ_UINT32 cblkno , l_nb_code_blocks;
+
+ opj_tcd_cblk_enc_v2_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;
+ }
+}
+
+OPJ_UINT32 opj_tcd_get_encoded_tile_size ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 i,l_data_size = 0;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcd_tilecomp_v2_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;i<p_tcd->image->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;
+}
+
+opj_bool opj_tcd_dc_level_shift_encode ( opj_tcd_v2_t *p_tcd )
+{
+ OPJ_UINT32 compno;
+ opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
+ opj_tccp_t * l_tccp = 00;
+ opj_image_comp_t * l_img_comp = 00;
+ opj_tcp_v2_t * l_tcp = 00;
+ opj_tcd_tile_v2_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 OPJ_TRUE;
+}
+
+opj_bool opj_tcd_mct_encode ( opj_tcd_v2_t *p_tcd )
+{
+ opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+ opj_tcd_tilecomp_v2_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_v2_t * l_tcp = p_tcd->tcp;
+
+ if(!p_tcd->tcp->mct) {
+ return OPJ_TRUE;
+ }
+
+ if (p_tcd->tcp->mct == 2) {
+ if (! p_tcd->tcp->m_mct_coding_matrix) {
+ return OPJ_TRUE;
+ }
+
+ l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*));
+ if (! l_data) {
+ return OPJ_FALSE;
+ }
+
+ for (i=0;i<l_tile->numcomps;++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 OPJ_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 OPJ_TRUE;
+}
+
+opj_bool opj_tcd_dwt_encode ( opj_tcd_v2_t *p_tcd )
+{
+ opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+ opj_tcd_tilecomp_v2_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 (! opj_dwt_encode(l_tile_comp)) {
+ return OPJ_FALSE;
+ }
+ }
+ else if (l_tccp->qmfbid == 0) {
+ if (! opj_dwt_encode_real(l_tile_comp)) {
+ return OPJ_FALSE;
+ }
+ }
+
+ ++l_tile_comp;
+ ++l_tccp;
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_t1_encode ( opj_tcd_v2_t *p_tcd )
+{
+ opj_t1_t * l_t1;
+ const OPJ_FLOAT64 * l_mct_norms;
+ opj_tcp_v2_t * l_tcp = p_tcd->tcp;
+
+ l_t1 = opj_t1_create();
+ if (l_t1 == 00) {
+ return OPJ_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 (! opj_t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) {
+ opj_t1_destroy(l_t1);
+ return OPJ_FALSE;
+ }
+
+ opj_t1_destroy(l_t1);
+
+ return OPJ_TRUE;
+}
+
+opj_bool opj_tcd_t2_encode (opj_tcd_v2_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_v2_t * l_t2;
+
+ l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp);
+ if (l_t2 == 00) {
+ return OPJ_FALSE;
+ }
+
+ if (! opj_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))
+ {
+ opj_t2_destroy(l_t2);
+ return OPJ_FALSE;
+ }
+
+ opj_t2_destroy(l_t2);
+
+ /*---------------CLEAN-------------------*/
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_tcd_rate_allocate_encode( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_dest_data,
+ OPJ_UINT32 p_max_dest_size,
+ opj_codestream_info_t *p_cstr_info )
+{
+ opj_cp_v2_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 (! opj_tcd_rateallocate(p_tcd, p_dest_data,&l_nb_written, p_max_dest_size, p_cstr_info)) {
+ return OPJ_FALSE;
+ }
+ }
+ else {
+ /* Fixed layer allocation */
+ opj_tcd_rateallocate_fixed(p_tcd);
+ }
+
+ return OPJ_TRUE;
+}
+
+
+opj_bool opj_tcd_copy_tile_data ( opj_tcd_v2_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_v2_t * l_tilec = 00;
+ OPJ_UINT32 l_size_comp, l_remaining;
+ OPJ_UINT32 l_nb_elem;
+
+ l_data_size = opj_tcd_get_encoded_tile_size(p_tcd);
+ if (l_data_size != p_src_length) {
+ return OPJ_FALSE;
+ }
+
+ l_tilec = p_tcd->tcd_image->tiles->comps;
+ l_img_comp = p_tcd->image->comps;
+ for (i=0;i<p_tcd->image->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;j<l_nb_elem;++j) {
+ *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+ }
+ }
+ else {
+ for (j=0;j<l_nb_elem;++j) {
+ *(l_dest_ptr++) = (*(l_src_ptr++))&0xff;
+ }
+ }
+
+ p_src = (OPJ_BYTE*) l_src_ptr;
+ }
+ break;
+ case 2:
+ {
+ OPJ_INT32 * l_dest_ptr = l_tilec->data;
+ OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src;
+
+ if (l_img_comp->sgnd) {
+ for (j=0;j<l_nb_elem;++j) {
+ *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+ }
+ }
+ else {
+ for (j=0;j<l_nb_elem;++j) {
+ *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff;
+ }
+ }
+
+ p_src = (OPJ_BYTE*) l_src_ptr;
+ }
+ break;
+ case 4:
+ {
+ OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_src;
+ OPJ_INT32 * l_dest_ptr = l_tilec->data;
+
+ for (j=0;j<l_nb_elem;++j) {
+ *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+ }
+
+ p_src = (OPJ_BYTE*) l_src_ptr;
+ }
+ break;
+ }
+
+ ++l_img_comp;
+ ++l_tilec;
+ }
+
+ return OPJ_TRUE;
+}
diff --git a/src/lib/openjp2/tcd.h b/src/lib/openjp2/tcd.h
new file mode 100644
index 00000000..b43d2850
--- /dev/null
+++ b/src/lib/openjp2/tcd.h
@@ -0,0 +1,475 @@
+/*
+ * 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 __TCD_H
+#define __TCD_H
+/**
+@file tcd.h
+@brief Implementation of a tile coder/decoder (TCD)
+
+The functions in TCD.C encode or decode each tile independently from
+each other. The functions in TCD.C are used by other functions in J2K.C.
+*/
+
+/** @defgroup TCD TCD - Implementation of a tile coder/decoder */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+/*typedef struct opj_tcd_seg { */
+/* unsigned char** data; */
+/* int dataindex; */
+/* int numpasses; */
+/* int len; */
+/* int maxpasses; */
+/* int numnewpasses; */
+/* int newlen; */
+/*} opj_tcd_seg_t; */
+
+/**
+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 {
+ int rate;
+ double distortiondec;
+ int term, len;
+} opj_tcd_pass_t;
+
+typedef struct opj_tcd_pass_v2 {
+ OPJ_UINT32 rate;
+ OPJ_FLOAT64 distortiondec;
+ OPJ_UINT32 len;
+ OPJ_UINT32 term : 1;
+} opj_tcd_pass_v2_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 {
+ unsigned char* data; /* Data */
+ opj_tcd_layer_t* layers; /* layer information */
+ opj_tcd_pass_t* passes; /* information about the passes */
+ int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numbps;
+ int numlenbits;
+ int numpasses; /* number of pass already done for the code-blocks */
+ int numpassesinlayers; /* number of passes in the layer */
+ int totalpasses; /* total number of passes */
+} opj_tcd_cblk_enc_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_cblk_enc_v2 {
+ OPJ_BYTE* data; /* Data */
+ opj_tcd_layer_t* layers; /* layer information */
+ opj_tcd_pass_v2_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_v2_t;
+
+typedef struct opj_tcd_cblk_dec {
+ unsigned char* data; /* Data */
+ opj_tcd_seg_t* segs; /* segments information */
+ int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numbps;
+ int numlenbits;
+ int len; /* length */
+ int numnewpasses; /* number of pass added to the code-blocks */
+ int numsegs; /* number of segments */
+} opj_tcd_cblk_dec_t;
+
+
+typedef struct opj_tcd_cblk_dec_v2 {
+ OPJ_BYTE * data; /* Data */
+ opj_tcd_seg_t* segs; /* segments information */
+ 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_v2_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_precinct {
+ int x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */
+ int cw, ch; /* number of precinct in width and height */
+ union{ /* code-blocks information */
+ opj_tcd_cblk_enc_t* enc;
+ opj_tcd_cblk_dec_t* dec;
+ } cblks;
+ opj_tgt_tree_t *incltree; /* inclusion tree */
+ opj_tgt_tree_t *imsbtree; /* IMSB tree */
+} opj_tcd_precinct_t;
+
+
+typedef struct opj_tcd_precinct_v2 {
+ 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 height */
+ union{ /* code-blocks information */
+ opj_tcd_cblk_enc_v2_t* enc;
+ opj_tcd_cblk_dec_v2_t* dec;
+ } cblks;
+ OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */
+ opj_tgt_tree_t *incltree; /* inclusion tree */
+ opj_tgt_tree_t *imsbtree; /* IMSB tree */
+} opj_tcd_precinct_v2_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_band {
+ int x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */
+ int bandno;
+ opj_tcd_precinct_t *precincts; /* precinct information */
+ int numbps;
+ float stepsize;
+} opj_tcd_band_t;
+
+typedef struct opj_tcd_band_v2 {
+ 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_v2_t *precincts; /* precinct information */
+ OPJ_UINT32 precincts_data_size; /* size of data taken by precincts */
+ OPJ_INT32 numbps;
+ OPJ_FLOAT32 stepsize;
+} opj_tcd_band_v2_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_resolution {
+ int x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */
+ int pw, ph;
+ int numbands; /* number sub-band for the resolution level */
+ opj_tcd_band_t bands[3]; /* subband information */
+} opj_tcd_resolution_t;
+
+typedef struct opj_tcd_resolution_v2 {
+ 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_v2_t bands[3]; /* subband information */
+} opj_tcd_resolution_v2_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tilecomp {
+ int x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numresolutions; /* number of resolutions level */
+ opj_tcd_resolution_t *resolutions; /* resolutions information */
+ int *data; /* data of the component */
+ int numpix; /* add fixed_quality */
+} opj_tcd_tilecomp_t;
+
+typedef struct opj_tcd_tilecomp_v2
+{
+ 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_v2_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_v2_t;
+
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tile {
+ int x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numcomps; /* number of components in tile */
+ opj_tcd_tilecomp_t *comps; /* Components information */
+ int numpix; /* add fixed_quality */
+ double distotile; /* add fixed_quality */
+ double distolayer[100]; /* add fixed_quality */
+ /** packet number */
+ int packno;
+} opj_tcd_tile_t;
+
+typedef struct opj_tcd_tile_v2 {
+ 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_v2_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_v2_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_image {
+ int tw, th; /* number of tiles in width and height */
+ opj_tcd_tile_t *tiles; /* Tiles information */
+} opj_tcd_image_t;
+
+typedef struct opj_tcd_image_v2
+{
+ opj_tcd_tile_v2_t *tiles; /* Tiles information */
+}
+opj_tcd_image_v2_t;
+
+/**
+Tile coder/decoder
+*/
+typedef struct opj_tcd {
+ /** Position of the tilepart flag in Progression order*/
+ int tp_pos;
+ /** Tile part number*/
+ int tp_num;
+ /** Current tile part number*/
+ int cur_tp_num;
+ /** Total number of tileparts of the current tile*/
+ int cur_totnum_tp;
+ /** Current Packet iterator number */
+ int cur_pino;
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** info on each image tile */
+ opj_tcd_image_t *tcd_image;
+ /** image */
+ opj_image_t *image;
+ /** coding parameters */
+ opj_cp_t *cp;
+ /** pointer to the current encoded/decoded tile */
+ opj_tcd_tile_t *tcd_tile;
+ /** coding/decoding parameters common to all tiles */
+ opj_tcp_t *tcp;
+ /** current encoded/decoded tile */
+ int tcd_tileno;
+ /** Time taken to encode a tile*/
+ double encoding_time;
+} opj_tcd_t;
+
+
+/**
+Tile coder/decoder
+*/
+typedef struct opj_tcd_v2
+{
+ /** 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 */
+ opj_tcd_image_v2_t *tcd_image;
+ /** image header */
+ opj_image_t *image;
+ /** coding parameters */
+ opj_cp_v2_t *cp;
+ /** coding/decoding parameters common to all tiles */
+ opj_tcp_v2_t *tcp;
+ /** current encoded/decoded tile */
+ OPJ_UINT32 tcd_tileno;
+ /** tell if the tcd is a decoder. */
+ OPJ_UINT32 m_is_decoder : 1;
+} opj_tcd_v2_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 p_is_decoder FIXME DOC
+@return Returns a new TCD handle if successful returns NULL otherwise
+*/
+opj_tcd_v2_t* opj_tcd_create(opj_bool p_is_decoder);
+
+/**
+Destroy a previously created TCD handle
+@param tcd TCD handle to destroy
+*/
+void opj_tcd_destroy(opj_tcd_v2_t *tcd);
+
+/**
+ * Initialize the tile coder and may reuse some memory.
+ * @param p_tcd TCD handle.
+ * @param p_image raw image.
+ * @param p_cp coding parameters.
+ *
+ * @return true if the encoding values could be set (false otherwise).
+*/
+opj_bool opj_tcd_init( opj_tcd_v2_t *p_tcd,
+ opj_image_t * p_image,
+ opj_cp_v2_t * p_cp );
+
+/**
+ * Allocates memory for decoding a specific tile.
+ *
+ * @param p_tcd the tile decoder.
+ * @param p_tile_no the index of the tile received in sequence. This not necessarily lead to the
+ * tile at index p_tile_no.
+ *
+ * @return true if the remaining data is sufficient.
+ */
+opj_bool opj_tcd_init_decode_tile(opj_tcd_v2_t *p_tcd, OPJ_UINT32 p_tile_no);
+
+void opj_tcd_makelayer_fixed(opj_tcd_v2_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final);
+
+void opj_tcd_rateallocate_fixed(opj_tcd_v2_t *tcd);
+
+void opj_tcd_makelayer( opj_tcd_v2_t *tcd,
+ OPJ_UINT32 layno,
+ OPJ_FLOAT64 thresh,
+ OPJ_UINT32 final);
+
+opj_bool opj_tcd_rateallocate( opj_tcd_v2_t *tcd,
+ OPJ_BYTE *dest,
+ OPJ_UINT32 * p_data_written,
+ OPJ_UINT32 len,
+ opj_codestream_info_t *cstr_info);
+
+/**
+ * Gets the maximum tile size that will be taken by the tile once decoded.
+ */
+OPJ_UINT32 opj_tcd_get_decoded_tile_size (opj_tcd_v2_t *p_tcd );
+
+/**
+ * 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.
+*/
+opj_bool opj_tcd_encode_tile( opj_tcd_v2_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
+@param cstr_info FIXME DOC
+*/
+opj_bool opj_tcd_decode_tile( opj_tcd_v2_t *tcd,
+ OPJ_BYTE *src,
+ OPJ_UINT32 len,
+ OPJ_UINT32 tileno,
+ opj_codestream_index_t *cstr_info);
+
+
+/**
+ * Copies tile data from the system onto the given memory block.
+ */
+opj_bool opj_tcd_update_tile_data ( opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_dest,
+ OPJ_UINT32 p_dest_length );
+
+/**
+ *
+ */
+OPJ_UINT32 opj_tcd_get_encoded_tile_size ( opj_tcd_v2_t *p_tcd );
+
+/**
+ * Initialize the tile coder and may reuse some meory.
+ *
+ * @param p_tcd TCD handle.
+ * @param p_tile_no current tile index to encode.
+ *
+ * @return true if the encoding values could be set (false otherwise).
+*/
+opj_bool opj_tcd_init_encode_tile ( opj_tcd_v2_t *p_tcd,
+ OPJ_UINT32 p_tile_no );
+
+/**
+ * Copies tile data from the given memory block onto the system.
+ */
+opj_bool opj_tcd_copy_tile_data (opj_tcd_v2_t *p_tcd,
+ OPJ_BYTE * p_src,
+ OPJ_UINT32 p_src_length );
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TCD_H */
diff --git a/src/lib/openjp2/tgt.c b/src/lib/openjp2/tgt.c
new file mode 100644
index 00000000..54bf536b
--- /dev/null
+++ b/src/lib/openjp2/tgt.c
@@ -0,0 +1,433 @@
+/*
+ * 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.
+ */
+
+#include "opj_includes.h"
+
+/*
+==========================================================
+ Tag-tree coder interface
+==========================================================
+*/
+
+opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv) {
+ int nplh[32];
+ int nplv[32];
+ opj_tgt_node_t *node = NULL;
+ opj_tgt_node_t *parentnode = NULL;
+ opj_tgt_node_t *parentnode0 = NULL;
+ opj_tgt_tree_t *tree = NULL;
+ int i, j, k;
+ int numlvls;
+ int n;
+
+ tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t));
+ if(!tree) return NULL;
+ 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 NULL;
+ }
+
+ tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t));
+ if(!tree->nodes) {
+ opj_free(tree);
+ return NULL;
+ }
+
+ node = tree->nodes;
+ parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv];
+ parentnode0 = parentnode;
+
+ for (i = 0; i < numlvls - 1; ++i) {
+ for (j = 0; j < nplv[i]; ++j) {
+ k = nplh[i];
+ while (--k >= 0) {
+ node->parent = parentnode;
+ ++node;
+ if (--k >= 0) {
+ node->parent = parentnode;
+ ++node;
+ }
+ ++parentnode;
+ }
+ if ((j & 1) || j == nplv[i] - 1) {
+ parentnode0 = parentnode;
+ } else {
+ parentnode = parentnode0;
+ parentnode0 += nplh[i];
+ }
+ }
+ }
+ node->parent = 0;
+
+ tgt_reset(tree);
+
+ return tree;
+}
+
+opj_tgt_tree_t *tgt_create_v2(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) {
+ fprintf(stderr, "ERROR in tgt_create_v2 while allocating tree\n");
+ 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);
+ fprintf(stderr, "WARNING in tgt_create_v2 tree->numnodes == 0, no tree created.\n");
+ return 00;
+ }
+
+ tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t));
+ if(!tree->nodes) {
+ fprintf(stderr, "ERROR in tgt_create_v2 while allocating node of the tree\n");
+ 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. (V2 framevork)
+ *
+ * @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)
+ {
+ opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size);
+ if
+ (! p_tree->nodes)
+ {
+ fprintf(stderr, "Not enough memory to reinitialize the tag tree\n");
+ tgt_destroy(p_tree);
+ return 00;
+ }
+ p_tree->nodes = new_nodes;
+ 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 *tree) {
+ opj_free(tree->nodes);
+ opj_free(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 *tree) {
+ int i;
+
+ if (NULL == tree)
+ return;
+
+ for (i = 0; i < tree->numnodes; i++) {
+ tree->nodes[i].value = 999;
+ tree->nodes[i].low = 0;
+ tree->nodes[i].known = 0;
+ }
+}*/
+
+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/src/lib/openjp2/tgt.h b/src/lib/openjp2/tgt.h
new file mode 100644
index 00000000..d3880f13
--- /dev/null
+++ b/src/lib/openjp2/tgt.h
@@ -0,0 +1,131 @@
+/*
+ * 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 <jerome.fimes@c-s.fr>
+ * 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.
+*/
+
+/** @defgroup TGT TGT - Implementation of a tag-tree coder */
+/*@{*/
+
+/**
+Tag node
+*/
+typedef struct opj_tgt_node {
+ struct opj_tgt_node *parent;
+ OPJ_INT32 value;
+ OPJ_INT32 low;
+ OPJ_UINT32 known;
+} 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(int numleafsh, int numleafsv);
+opj_tgt_tree_t *tgt_create_v2(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(opj_bio_t *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(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TGT_H */
diff --git a/src/lib/openjp2/thix_manager.c b/src/lib/openjp2/thix_manager.c
new file mode 100644
index 00000000..38054886
--- /dev/null
+++ b/src/lib/openjp2/thix_manager.c
@@ -0,0 +1,118 @@
+/*
+ * $Id: thix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.c from 2KAN indexer
+ */
+
+#include "opj_includes.h"
+
+/*
+ * Write tile-part headers mhix box
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] cstr_info codestream information
+ * @param[in] tileno tile number
+ * @param[in] cio file output handle
+ * @return length of mhix box
+ */
+int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio);
+
+int write_thix( int coff, opj_codestream_info_t cstr_info, opj_cio_t *cio)
+{
+ int len, lenp, i;
+ int tileno;
+ opj_jp2_box_t *box;
+
+ lenp = 0;
+ box = (opj_jp2_box_t *)opj_calloc( cstr_info.tw*cstr_info.th, sizeof(opj_jp2_box_t));
+
+ for ( i = 0; i < 2 ; i++ ){
+ if (i)
+ cio_seek( cio, lenp);
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_THIX, 4); /* THIX */
+ write_manf( i, cstr_info.tw*cstr_info.th, box, cio);
+
+ for (tileno = 0; tileno < cstr_info.tw*cstr_info.th; tileno++){
+ box[tileno].length = write_tilemhix( coff, cstr_info, tileno, cio);
+ box[tileno].type = JPIP_MHIX;
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+ }
+
+ opj_free(box);
+
+ return len;
+}
+
+int write_tilemhix( int coff, opj_codestream_info_t cstr_info, int tileno, opj_cio_t *cio)
+{
+ int i;
+ opj_tile_info_t tile;
+ opj_tp_info_t tp;
+ int marknum;
+ int len, lenp;
+ opj_marker_info_t *marker;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_MHIX, 4); /* MHIX */
+
+ tile = cstr_info.tile[tileno];
+ tp = tile.tp[0];
+
+ cio_write( cio, tp.tp_end_header-tp.tp_start_pos+1, 8); /* TLEN */
+
+ marker = cstr_info.tile[tileno].marker;
+
+ for( i=0; i<cstr_info.tile[tileno].marknum; i++){ /* Marker restricted to 1 apparition */
+ cio_write( cio, marker[i].type, 2);
+ cio_write( cio, 0, 2);
+ cio_write( cio, marker[i].pos-coff, 8);
+ cio_write( cio, marker[i].len, 2);
+ }
+
+ /* free( marker);*/
+
+ len = cio_tell( cio) - lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
diff --git a/src/lib/openjp2/tpix_manager.c b/src/lib/openjp2/tpix_manager.c
new file mode 100644
index 00000000..6cc49c73
--- /dev/null
+++ b/src/lib/openjp2/tpix_manager.c
@@ -0,0 +1,152 @@
+/*
+ * $Id: tpix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2003-2004, Yannick Verschueren
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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.
+ */
+
+/*! \file
+ * \brief Modification of jpip.c from 2KAN indexer
+ */
+
+#include "opj_includes.h"
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+
+/*
+ * Write faix box of tpix
+ *
+ * @param[in] coff offset of j2k codestream
+ * @param[in] compno component number
+ * @param[in] cstr_info codestream information
+ * @param[in] j2klen length of j2k codestream
+ * @param[in] cio file output handle
+ * @return length of faix box
+ */
+int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio);
+
+
+int write_tpix( int coff, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp;
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_TPIX, 4); /* TPIX */
+
+ write_tpixfaix( coff, 0, cstr_info, j2klen, cio);
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
+
+
+/*
+ * Get number of maximum tile parts per tile
+ *
+ * @param[in] cstr_info codestream information
+ * @return number of maximum tile parts per tile
+ */
+int get_num_max_tile_parts( opj_codestream_info_t cstr_info);
+
+int write_tpixfaix( int coff, int compno, opj_codestream_info_t cstr_info, int j2klen, opj_cio_t *cio)
+{
+ int len, lenp;
+ int i, j;
+ int Aux;
+ int num_max_tile_parts;
+ int size_of_coding; /* 4 or 8 */
+ opj_tp_info_t tp;
+ int version;
+
+ num_max_tile_parts = get_num_max_tile_parts( cstr_info);
+
+ if( j2klen > pow( 2, 32)){
+ size_of_coding = 8;
+ version = num_max_tile_parts == 1 ? 1:3;
+ }
+ else{
+ size_of_coding = 4;
+ version = num_max_tile_parts == 1 ? 0:2;
+ }
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_FAIX, 4); /* FAIX */
+ cio_write( cio, version, 1); /* Version 0 = 4 bytes */
+
+ cio_write( cio, num_max_tile_parts, size_of_coding); /* NMAX */
+ cio_write( cio, cstr_info.tw*cstr_info.th, size_of_coding); /* M */
+ for (i = 0; i < cstr_info.tw*cstr_info.th; i++){
+ for (j = 0; j < cstr_info.tile[i].num_tps; j++){
+ tp = cstr_info.tile[i].tp[j];
+ cio_write( cio, tp.tp_start_pos-coff, size_of_coding); /* start position */
+ cio_write( cio, tp.tp_end_pos-tp.tp_start_pos+1, size_of_coding); /* length */
+ if (version & 0x02){
+ if( cstr_info.tile[i].num_tps == 1 && cstr_info.numdecompos[compno] > 1)
+ Aux = cstr_info.numdecompos[compno] + 1;
+ else
+ Aux = j + 1;
+
+ cio_write( cio, Aux,4);
+ /*cio_write(img.tile[i].tile_parts[j].num_reso_AUX,4);*/ /* Aux_i,j : Auxiliary value */
+ /* fprintf(stderr,"AUX value %d\n",Aux);*/
+ }
+ /*cio_write(0,4);*/
+ }
+ /* PADDING */
+ while (j < num_max_tile_parts){
+ cio_write( cio, 0, size_of_coding); /* start position */
+ cio_write( cio, 0, size_of_coding); /* length */
+ if (version & 0x02)
+ cio_write( cio, 0,4); /* Aux_i,j : Auxiliary value */
+ j++;
+ }
+ }
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+
+}
+
+int get_num_max_tile_parts( opj_codestream_info_t cstr_info)
+{
+ int num_max_tp = 0, i;
+
+ for( i=0; i<cstr_info.tw*cstr_info.th; i++)
+ num_max_tp = MAX( cstr_info.tile[i].num_tps, num_max_tp);
+
+ return num_max_tp;
+}
diff --git a/src/lib/openjpip/CMakeLists.txt b/src/lib/openjpip/CMakeLists.txt
new file mode 100644
index 00000000..e42e95fc
--- /dev/null
+++ b/src/lib/openjpip/CMakeLists.txt
@@ -0,0 +1,72 @@
+include_regular_expression("^.*$")
+
+include_directories(
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2
+ ${FCGI_INCLUDE_DIRS}
+ ${CURL_INCLUDE_DIRS}
+)
+
+# Defines the source code for the library
+set(OPENJPIP_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/boxheader_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/codestream_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/imgreg_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/marker_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/msgqueue_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/box_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/faixbox_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/index_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/metadata_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/placeholder_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/byte_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/ihdrbox_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/manfbox_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/mhixbox_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/target_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cachemodel_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/j2kheader_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/jp2k_encoder.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/openjpip.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/query_parser.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/channel_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/session_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/jpip_parser.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/sock_manager.c
+ )
+
+set(SERVER_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/auxtrans_manager.c
+ )
+
+set(LOCAL_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/jp2k_decoder.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/imgsock_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/jpipstream_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cache_manager.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dec_clientmsg_handler.c
+ )
+
+# Build the library
+add_library(openjpip_local STATIC ${OPENJPIP_SRCS} ${LOCAL_SRCS})
+target_link_libraries(openjpip_local ${OPENJPEG_LIBRARY_NAME})
+if(WIN32)
+ # add Winsock on windows+mingw
+ target_link_libraries(openjpip_local ws2_32)
+endif()
+
+# Install library
+install(TARGETS openjpip_local
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+ )
+
+if(BUILD_JPIP_SERVER)
+ add_library(openjpip_server STATIC ${OPENJPIP_SRCS} ${SERVER_SRCS})
+ target_link_libraries(openjpip_server ${FCGI_LIBRARIES} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ set_target_properties(openjpip_server
+ PROPERTIES COMPILE_FLAGS "-DSERVER")
+ install(TARGETS openjpip_server
+ EXPORT OpenJPEGTargets
+ DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+ )
+endif()
diff --git a/src/lib/openjpip/Makefile.am b/src/lib/openjpip/Makefile.am
new file mode 100644
index 00000000..6def5d6f
--- /dev/null
+++ b/src/lib/openjpip/Makefile.am
@@ -0,0 +1,153 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+includesdir = $(includedir)/openjpeg-$(MAJOR_NR).$(MINOR_NR)
+includes_HEADERS =
+
+lib_LTLIBRARIES =
+
+if WANT_JPIP
+lib_LTLIBRARIES += libopenjpip_local.la
+endif
+
+if WANT_JPIP_SERVER
+lib_LTLIBRARIES += libopenjpip_server.la
+endif
+
+JPIP_SRC = \
+openjpip.c \
+query_parser.c \
+channel_manager.c \
+session_manager.c \
+jpip_parser.c \
+boxheader_manager.c \
+codestream_manager.c \
+imgreg_manager.c \
+marker_manager.c \
+msgqueue_manager.c \
+box_manager.c \
+faixbox_manager.c \
+index_manager.c \
+metadata_manager.c \
+placeholder_manager.c \
+byte_manager.c \
+ihdrbox_manager.c \
+manfbox_manager.c \
+mhixbox_manager.c \
+target_manager.c \
+cachemodel_manager.c \
+j2kheader_manager.c \
+jp2k_encoder.c \
+sock_manager.c \
+openjpip.h \
+bool.h \
+boxheader_manager.h \
+box_manager.h \
+byte_manager.h \
+codestream_manager.h \
+faixbox_manager.h \
+ihdrbox_manager.h \
+imgreg_manager.h \
+index_manager.h \
+manfbox_manager.h \
+marker_manager.h \
+metadata_manager.h \
+mhixbox_manager.h \
+msgqueue_manager.h \
+placeholder_manager.h \
+target_manager.h \
+cachemodel_manager.h \
+j2kheader_manager.h \
+jp2k_encoder.h \
+query_parser.h \
+channel_manager.h \
+session_manager.h \
+jpip_parser.h \
+jp2k_decoder.h \
+sock_manager.h
+
+SERVER_SRC = auxtrans_manager.c \
+auxtrans_manager.h
+
+LOCAL_SRC = jp2k_decoder.c \
+imgsock_manager.c \
+jpipstream_manager.c \
+cache_manager.c \
+dec_clientmsg_handler.c \
+imgsock_manager.h \
+jpipstream_manager.h \
+cache_manager.h \
+dec_clientmsg_handler.h
+
+libopenjpip_server_la_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip \
+@FCGI_CFLAGS@ \
+@LIBCURL_CFLAGS@ \
+-DSERVER
+libopenjpip_server_la_CFLAGS = @THREAD_CFLAGS@
+libopenjpip_server_la_LIBADD = @FCGI_LIBS@ @LIBCURL_LIBS@ @THREAD_LIBS@ -lm
+libopenjpip_server_la_LDFLAGS = -no-undefined -version-info @lt_version@
+libopenjpip_server_la_SOURCES = $(JPIP_SRC) $(SERVER_SRC)
+
+libopenjpip_local_la_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/applications/jpip/libopenjpip \
+-I$(top_builddir)/applications/jpip/libopenjpip \
+@LIBCURL_CFLAGS@
+libopenjpip_local_la_CFLAGS =
+libopenjpip_local_la_LIBADD = $(top_builddir)/libopenjpeg/libopenjpeg.la -lm
+libopenjpip_local_la_LDFLAGS = -no-undefined -version-info @lt_version@
+libopenjpip_local_la_SOURCES = $(JPIP_SRC) $(LOCAL_SRC)
+
+install-data-hook:
+if WANT_JPIP_SERVER
+ @echo -e " (LA)\t$(libdir)/libopenjpip_server.la" >> $(top_builddir)/report.txt
+if BUILD_SHARED
+ @( $(call solist_s) ) >> $(top_builddir)/report.txt
+endif
+if BUILD_STATIC
+ @echo -e " (A)\t$(base_s)/$(a_s)" >> $(top_builddir)/report.txt
+endif
+endif
+if WANT_JPIP
+ @echo -e " (LA)\t$(libdir)/libopenjpip_local.la" >> $(top_builddir)/report.txt
+if BUILD_SHARED
+ @( $(call solist_c) ) >> $(top_builddir)/report.txt
+endif
+if BUILD_STATIC
+ @echo -e " (A)\t$(base_c)/$(a_c)" >> $(top_builddir)/report.txt
+endif
+endif
+
+solist_s = $(foreach f, $(dll_s) $(so_s), echo -e ' $(SO_PREFIX)\t$(base_s)/$(f)' ;)
+get_tok_s = $(shell grep -E "^$(1)=" libopenjpip_server.la | cut -d "'" -f 2)
+base_s = $(call get_tok_s,libdir)
+so_s = $(call get_tok_s,library_names)
+a_s = $(call get_tok_s,old_library)
+
+solist_c = $(foreach f, $(dll_c) $(so_c), echo -e ' $(SO_PREFIX)\t$(base_c)/$(f)' ;)
+get_tok_c = $(shell grep -E "^$(1)=" libopenjpip_local.la | cut -d "'" -f 2)
+base_c = $(call get_tok_c,libdir)
+so_c = $(call get_tok_c,library_names)
+a_c = $(call get_tok_c,old_library)
+
+if HAVE_WIN32
+SO_PREFIX = (DLL)
+dll_s = $(call get_tok_s,dlname)
+dll_c = $(call get_tok_c,dlname)
+else
+if HAVE_DARWIN
+SO_PREFIX = (DY)
+dll_s =
+dll_c =
+else
+SO_PREFIX = (SO)
+dll_s =
+dll_c =
+endif
+endif
diff --git a/src/lib/openjpip/auxtrans_manager.c b/src/lib/openjpip/auxtrans_manager.c
new file mode 100644
index 00000000..91c06ac4
--- /dev/null
+++ b/src/lib/openjpip/auxtrans_manager.c
@@ -0,0 +1,267 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "auxtrans_manager.h"
+
+#ifdef _WIN32
+#include <process.h>
+#else
+#include <pthread.h>
+#endif
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport)
+{
+ auxtrans_param_t auxtrans;
+
+ auxtrans.tcpauxport = tcp_auxport;
+ auxtrans.udpauxport = udp_auxport;
+
+ if( 49152 <= tcp_auxport && tcp_auxport <= 65535)
+ auxtrans.tcplistensock = open_listeningsocket( (uint16_t)tcp_auxport);
+ else
+ auxtrans.tcplistensock = -1;
+
+ auxtrans.udplistensock = -1;
+ /* open listening socket for udp later */
+
+ return auxtrans;
+}
+
+void close_aux_transport( auxtrans_param_t auxtrans)
+{
+ if( auxtrans.tcplistensock != -1)
+ if( close_socket( auxtrans.tcplistensock) != 0)
+ perror("close");
+
+ if( auxtrans.udplistensock != -1)
+ if( close_socket( auxtrans.udplistensock) != 0)
+ perror("close");
+}
+
+
+/*!< auxiliary response parameters */
+typedef struct aux_response_param{
+ char *cid; /*!< channel ID */
+ unsigned char *data; /*!< sending data */
+ OPJ_SIZE_T datalen; /*!< length of data */
+ OPJ_SIZE_T maxlenPerFrame; /*!< maximum data length to send per frame */
+ SOCKET listensock; /*!< listeing socket */
+#ifdef _WIN32
+ HANDLE hTh; /*!< thread handle */
+#endif
+} aux_response_param_t;
+
+aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame);
+
+void delete_auxresponse( aux_response_param_t **auxresponse);
+
+
+#ifdef _WIN32
+unsigned __stdcall aux_streaming( void *arg);
+#else
+void * aux_streaming( void *arg);
+#endif
+
+void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame)
+{
+ aux_response_param_t *auxresponse;
+#ifdef _WIN32
+ unsigned int threadId;
+#else
+ pthread_t thread;
+ int status;
+#endif
+
+ if( istcp){
+ if( auxtrans.tcplistensock == -1){
+ fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), tcp listening socket no open\n");
+ return;
+ }
+
+ auxresponse = gene_auxresponse( istcp, auxtrans, cid, data, datalen, maxlenPerFrame);
+
+#ifdef _WIN32
+ auxresponse->hTh = (HANDLE)_beginthreadex( NULL, 0, &aux_streaming, auxresponse, 0, &threadId);
+ if( auxresponse->hTh == 0)
+ fprintf( FCGI_stderr,"ERRO: pthread_create() %s", strerror( (int)auxresponse->hTh));
+#else
+ status = pthread_create( &thread, NULL, &aux_streaming, auxresponse);
+ if( status != 0)
+ fprintf( FCGI_stderr,"ERROR: pthread_create() %s",strerror(status));
+#endif
+ }
+ else
+ fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), udp not implemented\n");
+}
+
+aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame)
+{
+ aux_response_param_t *auxresponse;
+
+ auxresponse = (aux_response_param_t *)malloc( sizeof(aux_response_param_t));
+
+ auxresponse->cid = strdup( cid);
+ auxresponse->data = data;
+ auxresponse->datalen = datalen;
+ auxresponse->maxlenPerFrame = maxlenPerFrame;
+ auxresponse->listensock = istcp ? auxtrans.tcplistensock : auxtrans.udplistensock;
+
+ return auxresponse;
+}
+
+void delete_auxresponse( aux_response_param_t **auxresponse)
+{
+ free( (*auxresponse)->cid);
+ free( (*auxresponse)->data);
+ free( *auxresponse);
+}
+
+/**
+ * Identify cid sent from client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] refcid refenrece channel ID
+ * @param [in] fp file pointer for log of aux stream
+ * @return true if identified, false otherwise
+ */
+bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp);
+
+bool recv_ack( SOCKET connected_socket, void *data);
+
+#ifdef _WIN32
+unsigned __stdcall aux_streaming( void *arg)
+#else
+void * aux_streaming( void *arg)
+#endif
+{
+ SOCKET connected_socket;
+ unsigned char *chunk, *ptr;
+ OPJ_SIZE_T maxLenOfBody, remlen, chunklen;
+ const OPJ_SIZE_T headlen = 8;
+
+ aux_response_param_t *auxresponse = (aux_response_param_t *)arg;
+
+#ifdef _WIN32
+ CloseHandle( auxresponse->hTh);
+#else
+ pthread_detach( pthread_self());
+#endif
+
+ chunk = (unsigned char *)malloc( auxresponse->maxlenPerFrame);
+ maxLenOfBody = auxresponse->maxlenPerFrame - headlen;
+ remlen = auxresponse->datalen;
+
+ while((connected_socket = accept_socket( auxresponse->listensock)) != -1){
+ if( identify_cid( connected_socket, auxresponse->cid, FCGI_stderr)){
+ ptr = auxresponse->data;
+ while( 0 < remlen){
+ memset( chunk, 0, auxresponse->maxlenPerFrame);
+
+ chunklen = remlen<maxLenOfBody?remlen:maxLenOfBody;
+ chunklen += headlen;
+
+ chunk[0] = (chunklen >> 8) & 0xff;
+ chunk[1] = chunklen & 0xff;
+
+ memcpy( chunk+headlen, ptr, chunklen-headlen);
+
+ do{
+ send_stream( connected_socket, chunk, chunklen);
+ }while( !recv_ack( connected_socket, chunk));
+
+ remlen -= maxLenOfBody;
+ ptr += maxLenOfBody;
+ }
+ if( close_socket( connected_socket) != 0)
+ perror("close");
+ break;
+ }
+ }
+ free( chunk);
+
+ delete_auxresponse( &auxresponse);
+
+#ifdef _WIN32
+ _endthreadex(0);
+#else
+ pthread_exit(0);
+#endif
+
+ return 0;
+}
+
+
+bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp)
+{
+ char *cid;
+ bool succeed;
+
+ if(!(cid = receive_string( connected_socket))){
+ fprintf( fp, "Error: error in identify_cid(), while receiving cid from client\n");
+ return false;
+ }
+
+ succeed = false;
+ if( strncmp( refcid, cid, strlen( refcid)) == 0)
+ succeed = true;
+
+ free( cid);
+
+ return succeed;
+}
+
+bool recv_ack( SOCKET connected_socket, void *data)
+{
+ char *header;
+ bool succeed;
+
+ header = receive_stream( connected_socket, 8);
+
+ if( memcmp( header, data, 8) != 0)
+ succeed = false;
+ else
+ succeed = true;
+
+ free( header);
+
+ return succeed;
+}
diff --git a/src/lib/openjpip/auxtrans_manager.h b/src/lib/openjpip/auxtrans_manager.h
new file mode 100644
index 00000000..c80988a9
--- /dev/null
+++ b/src/lib/openjpip/auxtrans_manager.h
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 AUXTRANS_MANAGER_H_
+# define AUXTRANS_MANAGER_H_
+
+#include "sock_manager.h"
+
+/** auxiliary transport setting parameters*/
+typedef struct auxtrans_param{
+ int tcpauxport; /**< tcp port*/
+ int udpauxport; /**< udp port*/
+ SOCKET tcplistensock; /**< listenning socket for aux tcp (-1 if not open)*/
+ SOCKET udplistensock; /**< listenning socket for aux udp (-1 if not open)*/
+} auxtrans_param_t;
+
+/**
+ * Initialize auxiliary transport server of JPIP server
+ *
+ * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152-65535)
+ * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152-65535)
+ * @return intialized transport parameters
+ */
+auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport);
+
+/**
+ * Close auxiliary transport server of JPIP server
+ *
+ * @param[in] auxtrans closing transport server
+ */
+void close_aux_transport( auxtrans_param_t auxtrans);
+
+/**
+ * Send response data on aux transport
+ *
+ * @param[in] istcp true if tcp, false if udp
+ * @param[in] auxtrans available transport parameters
+ * @param[in] cid channel ID
+ * @param[in] data sending data
+ * @param[in] length length of data
+ * @param[in] maxlenPerFrame maximum data length to send per frame
+ */
+void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T length, OPJ_SIZE_T maxlenPerFrame);
+
+#endif /* !AUXTRANS_MANAGER_H_ */
diff --git a/src/lib/openjpip/bool.h b/src/lib/openjpip/bool.h
new file mode 100644
index 00000000..c3adf580
--- /dev/null
+++ b/src/lib/openjpip/bool.h
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 BOOL_H_
+# define BOOL_H_
+
+#ifndef false
+#define false 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef true
+#define true (!false)
+#endif
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+typedef char bool;
+
+#endif /* !BOOL_H_ */
diff --git a/src/lib/openjpip/box_manager.c b/src/lib/openjpip/box_manager.c
new file mode 100644
index 00000000..87bb7756
--- /dev/null
+++ b/src/lib/openjpip/box_manager.c
@@ -0,0 +1,434 @@
+/*
+ * $Id: box_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
+#include "box_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+boxlist_param_t * gene_boxlist(void)
+{
+ boxlist_param_t *boxlist;
+
+ boxlist = (boxlist_param_t *)malloc( sizeof(boxlist_param_t));
+
+ boxlist->first = NULL;
+ boxlist->last = NULL;
+
+ return boxlist;
+}
+
+boxlist_param_t * get_boxstructure( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length)
+{
+ boxlist_param_t *boxlist;
+ box_param_t *box;
+ OPJ_OFF_T pos;
+
+ boxlist = NULL;
+ pos = offset;
+ assert( (OPJ_OFF_T)length>=0);
+ do{
+ if(!(box = gene_boxbyOffset( fd, pos)))
+ break;
+
+ assert( (OPJ_OFF_T)box->length >= 0);
+ pos += (OPJ_OFF_T)box->length;
+
+ if( !boxlist)
+ boxlist = gene_boxlist();
+ insert_box_into_list( box, boxlist);
+ }while( pos < offset+(OPJ_OFF_T)length);
+
+ return boxlist;
+}
+
+box_param_t * gene_boxbyOffset( int fd, OPJ_OFF_T offset)
+{
+ Byte_t *data;
+ Byte8_t boxlen;
+ Byte_t headlen;
+ char *boxtype;
+ box_param_t *box;
+
+ /* read LBox and TBox*/
+ if(!(data = fetch_bytes( fd, offset, 8))){
+ fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd, offset);
+ return NULL;
+ }
+
+ headlen = 8;
+ boxlen = (Byte8_t)big4(data);
+ boxtype = (char *)(data+4);
+
+ /* box type constraint*/
+ if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
+ (!isalnum(boxtype[2])&&!isspace(boxtype[2])) ||
+ (!isalpha(boxtype[3])&&!isspace(boxtype[3]))){
+ free( data);
+ return NULL;
+ }
+
+ if( boxlen == 1){
+ Byte_t *data2;
+ headlen = 16;
+ /* read XLBox*/
+ if((data2 = fetch_bytes( fd, offset+8, 8))){
+ boxlen = big8(data2);
+ free(data2);
+ }
+ else{
+ fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd, offset);
+ free( data);
+ return NULL;
+ }
+ }
+ box = (box_param_t *)malloc( sizeof( box_param_t));
+ box->fd = fd;
+ box->offset = offset;
+ box->headlen = headlen;
+ box->length = boxlen;
+ strncpy( box->type, boxtype, 4);
+ box->next = NULL;
+ free( data);
+ return box;
+}
+
+box_param_t * gene_boxbyOffinStream( Byte_t *stream, OPJ_OFF_T offset)
+{
+ Byte8_t boxlen;
+ Byte_t headlen;
+ char *boxtype;
+ box_param_t *box;
+
+ /* read LBox and TBox*/
+ headlen = 8;
+ boxlen = (Byte8_t)big4( stream);
+ boxtype = (char *)( stream+4);
+
+ /* box type constraint*/
+ if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) ||
+ (!isalnum(boxtype[2])&&!isspace(boxtype[2])) ||
+ (!isalpha(boxtype[3])&&!isspace(boxtype[3]))){
+ return NULL;
+ }
+
+ if( boxlen == 1){
+ headlen = 16;
+ boxlen = big8( stream+8); /* read XLBox*/
+ }
+ box = (box_param_t *)malloc( sizeof( box_param_t));
+ box->fd = -1;
+ box->offset = offset;
+ box->headlen = headlen;
+ box->length = boxlen;
+ strncpy( box->type, boxtype, 4);
+ box->next = NULL;
+
+ return box;
+}
+
+
+box_param_t * gene_boxbyType( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[])
+{
+ OPJ_OFF_T pos;
+ Byte_t *data;
+ Byte8_t boxlen;
+ Byte_t headlen;
+ char *boxtype;
+ box_param_t *foundbox;
+
+
+ if( length==0){ /* set the max length*/
+ if( get_filesize( fd) <= offset )
+ return NULL;
+ assert( get_filesize( fd) > offset );
+ assert( offset >= 0 );
+ length = (OPJ_SIZE_T)(get_filesize( fd) - offset);
+ }
+
+ pos = offset;
+ assert( pos >= 0 );
+ assert( (OPJ_OFF_T)length >= 0 );
+ while( pos < offset+(OPJ_OFF_T)length-7){ /* LBox+TBox-1=7*/
+
+ /* read LBox and TBox*/
+ if((data = fetch_bytes( fd, pos, 8))){
+ headlen = 8;
+ boxlen = (Byte8_t)big4(data);
+ boxtype = (char *)(data+4);
+
+ if( boxlen == 1){
+ Byte_t *data2;
+ headlen = 16;
+ /* read XLBox*/
+ if((data2 = fetch_bytes( fd, pos+8, 8))){
+ boxlen = big8(data2);
+ free(data2);
+ }
+ else{
+ fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64 ", %s)\n", fd, offset, length, TBox);
+ return NULL;
+ }
+ }
+ if( strncmp ( boxtype, TBox, 4) == 0){
+ foundbox = (box_param_t *)malloc( sizeof( box_param_t));
+ foundbox->fd = fd;
+ foundbox->offset = pos;
+ foundbox->headlen = headlen;
+ foundbox->length = boxlen;
+ strncpy( foundbox->type, TBox, 4);
+ foundbox->next = NULL;
+ free( data);
+ return foundbox;
+ }
+ free( data);
+ }
+ else{
+ fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64 ", %s)\n", fd, offset, length, TBox);
+ return NULL;
+ }
+ assert( ((Byte8_t)pos+boxlen)>=(Byte8_t)pos);
+ pos+= (OPJ_OFF_T)boxlen;
+ }
+ fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
+
+ return NULL;
+}
+
+box_param_t * gene_boxbyTypeinStream( Byte_t *stream, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[])
+{
+ OPJ_OFF_T pos;
+ Byte_t *data;
+ Byte8_t boxlen;
+ Byte_t headlen;
+ char *boxtype;
+ box_param_t *foundbox;
+
+ pos = offset;
+ assert( pos >= 0 );
+ assert( (OPJ_OFF_T)length >= 0 );
+ while( pos < offset+(OPJ_OFF_T)(length)-7){ /* LBox+TBox-1=7*/
+
+ /* read LBox and TBox*/
+ data = stream + pos;
+ headlen = 8;
+ boxlen = (Byte8_t)big4(data);
+ boxtype = (char *)(data+4);
+
+ if( boxlen == 1){
+ /* read XLBox*/
+ headlen = 16;
+ boxlen = big8( data+8);
+ }
+
+ if( strncmp ( boxtype, TBox, 4) == 0){
+ foundbox = (box_param_t *)malloc( sizeof( box_param_t));
+ foundbox->fd = -1;
+ foundbox->offset = pos;
+ foundbox->headlen = headlen;
+ foundbox->length = boxlen;
+ strncpy( foundbox->type, TBox, 4);
+ foundbox->next = NULL;
+ return foundbox;
+ }
+ assert( ((Byte8_t)pos+boxlen)>=(Byte8_t)pos);
+ pos+= (OPJ_OFF_T)boxlen;
+ }
+ fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox);
+
+ return NULL;
+}
+
+box_param_t * gene_childboxbyOffset( box_param_t *superbox, OPJ_OFF_T offset)
+{
+ return gene_boxbyOffset( superbox->fd, get_DBoxoff( superbox)+offset);
+}
+
+box_param_t * gene_childboxbyType( box_param_t *superbox, OPJ_OFF_T offset, const char TBox[])
+{
+ OPJ_SIZE_T DBOXlen = get_DBoxlen(superbox);
+ assert( offset >= 0 );
+ if( DBOXlen < (OPJ_SIZE_T)offset )
+ {
+ fprintf( FCGI_stderr, "Error: Impossible happen %lu < %ld\n", DBOXlen, offset);
+ return NULL;
+ }
+ return gene_boxbyType( superbox->fd, get_DBoxoff( superbox)+offset, DBOXlen-(OPJ_SIZE_T)offset, TBox);
+}
+
+OPJ_OFF_T get_DBoxoff( box_param_t *box)
+{
+ return box->offset+box->headlen;
+}
+
+OPJ_SIZE_T get_DBoxlen( box_param_t *box)
+{
+ return box->length - box->headlen;
+}
+
+Byte_t * fetch_headbytes( box_param_t *box)
+{
+ return fetch_bytes( box->fd, box->offset, box->headlen);
+}
+
+Byte_t * fetch_DBoxbytes( box_param_t *box, OPJ_OFF_T offset, OPJ_SIZE_T size)
+{
+ return fetch_bytes( box->fd, get_DBoxoff( box)+offset, size);
+}
+
+Byte_t fetch_DBox1byte( box_param_t *box, OPJ_OFF_T offset)
+{
+ return fetch_1byte( box->fd, get_DBoxoff( box)+offset);
+}
+
+Byte2_t fetch_DBox2bytebigendian( box_param_t *box, OPJ_OFF_T offset)
+{
+ return fetch_2bytebigendian( box->fd, get_DBoxoff( box)+offset);
+}
+
+Byte4_t fetch_DBox4bytebigendian( box_param_t *box, OPJ_OFF_T offset)
+{
+ return fetch_4bytebigendian( box->fd, get_DBoxoff( box)+offset);
+}
+
+Byte8_t fetch_DBox8bytebigendian( box_param_t *box, OPJ_OFF_T offset)
+{
+ return fetch_8bytebigendian( box->fd, get_DBoxoff( box)+offset);
+}
+
+box_param_t * search_box( const char type[], boxlist_param_t *boxlist)
+{
+ box_param_t *foundbox;
+
+ foundbox = boxlist->first;
+
+ while( foundbox != NULL){
+
+ if( strncmp( type, foundbox->type, 4) == 0)
+ return foundbox;
+
+ foundbox = foundbox->next;
+ }
+ fprintf( FCGI_stderr, "Error: Box %s not found\n", type);
+
+ return NULL;
+}
+
+void print_box( box_param_t *box)
+{
+ fprintf( logstream, "box info:\n"
+ "\t type: %.4s\n"
+ "\t offset: %" PRId64 " %#" PRIx64 "\n"
+ "\t header length: %d\n"
+ "\t length: %" PRId64 " %#" PRIx64 "\n", box->type, box->offset,
+ box->offset, box->headlen, box->length, box->length);
+}
+
+void print_allbox( boxlist_param_t *boxlist)
+{
+ box_param_t *ptr;
+
+ if( !boxlist)
+ return;
+
+ ptr = boxlist->first;
+ if( !ptr)
+ fprintf( logstream, "no box\n");
+
+ fprintf( logstream, "all box info: \n");
+ while( ptr != NULL){
+ print_box( ptr);
+ ptr=ptr->next;
+ }
+}
+
+void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist)
+{
+ box_param_t *ptr;
+
+ if( *box == boxlist->first)
+ boxlist->first = (*box)->next;
+ else{
+ ptr = boxlist->first;
+ while( ptr->next != *box){
+ ptr=ptr->next;
+ }
+ ptr->next = (*box)->next;
+
+ if( *box == boxlist->last)
+ boxlist->last = ptr;
+ }
+ free( *box);
+}
+
+void delete_box_in_list_by_type( const char type[], boxlist_param_t *boxlist)
+{
+ box_param_t *box;
+
+ box = search_box( type, boxlist);
+ delete_box_in_list( &box, boxlist);
+}
+
+void delete_boxlist( boxlist_param_t **boxlist)
+{
+ box_param_t *boxPtr, *boxNext;
+
+ if(!(*boxlist))
+ return;
+
+ boxPtr = (*boxlist)->first;
+ while( boxPtr != NULL){
+ boxNext=boxPtr->next;
+ free( boxPtr);
+ boxPtr=boxNext;
+ }
+ free( *boxlist);
+}
+
+void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist)
+{
+ if( boxlist->first)
+ boxlist->last->next = box;
+ else
+ boxlist->first = box;
+ boxlist->last = box;
+}
diff --git a/src/lib/openjpip/box_manager.h b/src/lib/openjpip/box_manager.h
new file mode 100644
index 00000000..88cd5336
--- /dev/null
+++ b/src/lib/openjpip/box_manager.h
@@ -0,0 +1,264 @@
+/*
+ * $Id: box_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 BOX_MANAGER_H_
+# define BOX_MANAGER_H_
+
+#include "byte_manager.h"
+
+/** box parameters*/
+typedef struct box_param{
+ int fd; /**< file descriptor*/
+ OPJ_OFF_T offset; /**< byte position of the whole Box (LBox) in the file*/
+ Byte_t headlen; /**< header length 8 or 16*/
+ Byte8_t length; /**< length of the whole Box*/
+ char type[4]; /**< type of information in the DBox*/
+ struct box_param *next; /**< pointer to the next box*/
+} box_param_t;
+
+
+/** Box list parameters*/
+typedef struct boxlist_param{
+ box_param_t *first; /**< first box pointer of the list*/
+ box_param_t *last; /**< last box pointer of the list*/
+} boxlist_param_t;
+
+
+/**
+ * generate a box list
+ *
+ * @return pointer to the generated box list
+ */
+boxlist_param_t * gene_boxlist(void);
+
+/**
+ * get box structure of JP2 file
+ *
+ * @param[in] fd file descriptor
+ * @param[in] offset offset of the decomposing region
+ * @param[in] length length of the decomposing region
+ * @return pointer to the generated boxlist
+ */
+boxlist_param_t * get_boxstructure( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length);
+
+
+/**
+ * generate box from JP2 file at the given offset
+ *
+ * @param[in] fd file discriptor of the JP2 file
+ * @param[in] offset Box offset
+ * @return pointer to the structure of generate box parameters
+ */
+box_param_t * gene_boxbyOffset( int fd, OPJ_OFF_T offset);
+
+
+/**
+ * generate box from code stream (JPP or JPT stream) at the given offset
+ *
+ * @param[in] stream code stream of a box
+ * @param[in] offset Box offset of the whole stream
+ * @return pointer to the structure of generate box parameters
+ */
+box_param_t * gene_boxbyOffinStream( Byte_t *stream, OPJ_OFF_T offset);
+
+/**
+ * generate(search) box from JP2 file
+ *
+ * @param[in] fd file discriptor of the JP2 file
+ * @param[in] offset start Byte position of the search
+ * @param[in] length Byte length of the search, if 0, size to the end of file
+ * @param[in] TBox Box Type
+ * @return pointer to the structure of generate/found box parameters
+ */
+box_param_t * gene_boxbyType( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]);
+
+/**
+ * generate(search) box from code stream
+ *
+ * @param[in] stream code stream ( from the first byte)
+ * @param[in] offset start Byte position of the search
+ * @param[in] length Byte length of the search, if 0, size to the end of file
+ * @param[in] TBox Box Type
+ * @return pointer to the structure of generate/found box parameters
+ */
+box_param_t * gene_boxbyTypeinStream( Byte_t *stream, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]);
+
+/**
+ * generate child box from JP2 file at the given offset
+ *
+ * @param[in] superbox super box pointer
+ * @param[in] offset offset from DBox first byte of superbox
+ * @return pointer to the structure of generate box parameters
+ */
+box_param_t * gene_childboxbyOffset( box_param_t *superbox, OPJ_OFF_T offset);
+
+/**
+ * generate(search) box from JP2 file
+ *
+ * @param[in] superbox super box pointer
+ * @param[in] offset offset from DBox first byte of superbox
+ * @param[in] TBox Box Type
+ * @return pointer to the structure of generate/found box parameters
+ */
+box_param_t * gene_childboxbyType( box_param_t *superbox, OPJ_OFF_T offset, const char TBox[]);
+
+/**
+ * get DBox offset
+ *
+ * @param[in] box box pointer
+ * @return DBox offset (byte position) in the file
+ */
+OPJ_OFF_T get_DBoxoff( box_param_t *box);
+
+
+/**
+ * get DBox length
+ *
+ * @param[in] box box pointer
+ * @return DBox length ( content length)
+ */
+OPJ_SIZE_T get_DBoxlen( box_param_t *box);
+
+
+/**
+ * fetch header bytes in file stream
+ *
+ * @param[in] box box pointer
+ * @return pointer to the fetched bytes
+ */
+Byte_t * fetch_headbytes( box_param_t *box);
+
+
+/**
+ * fetch DBox (Box Contents) bytes of data in file stream
+ *
+ * @param[in] box box pointer
+ * @param[in] offset start Byte position in DBox
+ * @param[in] size Byte length
+ * @return pointer to the fetched data
+ */
+Byte_t * fetch_DBoxbytes( box_param_t *box, OPJ_OFF_T offset, OPJ_SIZE_T size);
+
+/**
+ * fetch DBox (Box Contents) 1-byte Byte codes in file stream
+ *
+ * @param[in] box box pointer
+ * @param[in] offset start Byte position in DBox
+ * @return fetched code
+ */
+Byte_t fetch_DBox1byte( box_param_t *box, OPJ_OFF_T offset);
+
+/**
+ * fetch DBox (Box Contents) 2-byte big endian Byte codes in file stream
+ *
+ * @param[in] box box pointer
+ * @param[in] offset start Byte position in DBox
+ * @return fetched code
+ */
+Byte2_t fetch_DBox2bytebigendian( box_param_t *box, OPJ_OFF_T offset);
+
+/**
+ * fetch DBox (Box Contents) 4-byte big endian Byte codes in file stream
+ *
+ * @param[in] box box pointer
+ * @param[in] offset start Byte position in DBox
+ * @return fetched code
+ */
+Byte4_t fetch_DBox4bytebigendian( box_param_t *box, OPJ_OFF_T offset);
+
+/**
+ * fetch DBox (Box Contents) 8-byte big endian Byte codes in file stream
+ *
+ * @param[in] box box pointer
+ * @param[in] offset start Byte position in DBox
+ * @return fetched code
+ */
+Byte8_t fetch_DBox8bytebigendian( box_param_t *box, OPJ_OFF_T offset);
+
+
+/**
+ * search a box by box type
+ *
+ * @param[in] type box type
+ * @param[in] boxlist box list pointer
+ * @return found box pointer
+ */
+box_param_t * search_box( const char type[], boxlist_param_t *boxlist);
+
+/**
+ * print box parameters
+ *
+ * @param[in] box box pointer
+ */
+void print_box( box_param_t *box);
+
+
+/**
+ * print all box parameters
+ *
+ * @param[in] boxlist box list pointer
+ */
+void print_allbox( boxlist_param_t *boxlist);
+
+/**
+ * delete a box in list
+ *
+ * @param[in,out] box address of the deleting box pointer
+ * @param[in] boxlist box list pointer
+ */
+void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist);
+
+
+/**
+ * delete a box in list by Type
+ *
+ * @param[in,out] type box type
+ * @param[in] boxlist box list pointer
+ */
+void delete_box_in_list_by_type( const char type[], boxlist_param_t *boxlist);
+
+
+/**
+ * delete box list
+ *
+ * @param[in,out] boxlist address of the box list pointer
+ */
+void delete_boxlist( boxlist_param_t **boxlist);
+
+
+/**
+ * insert a box into list
+ *
+ * @param[in] box box pointer
+ * @param[in] boxlist box list pointer
+ */
+void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist);
+
+#endif /* !BOX_MANAGER_H_ */
diff --git a/src/lib/openjpip/boxheader_manager.c b/src/lib/openjpip/boxheader_manager.c
new file mode 100644
index 00000000..b345a96d
--- /dev/null
+++ b/src/lib/openjpip/boxheader_manager.c
@@ -0,0 +1,84 @@
+/*
+ * $Id: boxheader_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdlib.h>
+#include "boxheader_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+boxheader_param_t * gene_boxheader( int fd, OPJ_OFF_T offset)
+{
+ Byte8_t boxlen;
+ Byte_t headlen;
+ char *boxtype;
+ boxheader_param_t *boxheader;
+
+ boxlen = fetch_4bytebigendian( fd, offset);
+ boxtype = (char *)fetch_bytes( fd, offset+4, 4);
+ headlen = 8;
+
+ if( boxlen == 1){ /* read XLBox */
+ boxlen = fetch_8bytebigendian( fd, offset+8);
+ headlen = 16;
+ }
+
+ boxheader = (boxheader_param_t *)malloc( sizeof( boxheader_param_t));
+ boxheader->headlen = headlen;
+ boxheader->length = boxlen;
+ strncpy( boxheader->type, boxtype, 4);
+ boxheader->next = NULL;
+
+ free( boxtype);
+ return boxheader;
+}
+
+boxheader_param_t * gene_childboxheader( box_param_t *superbox, OPJ_OFF_T offset)
+{
+ return gene_boxheader( superbox->fd, get_DBoxoff(superbox)+offset);
+}
+
+void print_boxheader( boxheader_param_t *boxheader)
+{
+ fprintf( logstream, "boxheader info:\n"
+ "\t type: %.4s\n"
+ "\t length:%" PRId64 " %#" PRIx64 "\n", boxheader->type, boxheader->length, boxheader->length);
+}
diff --git a/src/lib/openjpip/boxheader_manager.h b/src/lib/openjpip/boxheader_manager.h
new file mode 100644
index 00000000..f8e48f39
--- /dev/null
+++ b/src/lib/openjpip/boxheader_manager.h
@@ -0,0 +1,71 @@
+/*
+ * $Id: boxheader_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 BOXHEADER_MANAGER_H_
+# define BOXHEADER_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+
+/** box header parameters*/
+typedef struct boxheader_param{
+ Byte_t headlen; /**< header length 8 or 16*/
+ Byte8_t length; /**< length of the reference Box*/
+ char type[4]; /**< type of information in the DBox*/
+ struct boxheader_param *next; /**< pointer to the next header box*/
+} boxheader_param_t;
+
+
+/**
+ * generate a box header at the given offset
+ *
+ * @param[in] fd file discriptor of the JP2 file
+ * @param[in] offset Box offset
+ * @return pointer to the structure of generate box header parameters
+ */
+boxheader_param_t * gene_boxheader( int fd, OPJ_OFF_T offset);
+
+/**
+ * generate a child box header at the given offset
+ *
+ * @param[in] superbox super box pointer
+ * @param[in] offset offset from DBox first byte of superbox
+ * @return pointer to the structure of generate box header parameters
+ */
+boxheader_param_t * gene_childboxheader( box_param_t *superbox, OPJ_OFF_T offset);
+
+/**
+ * print box header parameters
+ *
+ * @param[in] boxheader boxheader pointer
+ */
+void print_boxheader( boxheader_param_t *boxheader);
+
+#endif /* !BOXHEADER_MANAGER_H_ */
diff --git a/src/lib/openjpip/byte_manager.c b/src/lib/openjpip/byte_manager.c
new file mode 100644
index 00000000..502c26bd
--- /dev/null
+++ b/src/lib/openjpip/byte_manager.c
@@ -0,0 +1,172 @@
+/*
+ * $Id: byte_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "byte_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+Byte_t * fetch_bytes( int fd, OPJ_OFF_T offset, OPJ_SIZE_T size)
+{
+ Byte_t *data;
+
+ if( lseek( fd, offset, SEEK_SET)==-1){
+ fprintf( FCGI_stdout, "Reason: Target broken (fseek error)\r\n");
+ fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld, %lu)\n", fd, offset, size);
+ return NULL;
+ }
+
+ data = (Byte_t *)malloc( size);
+
+ if( (OPJ_SIZE_T)read( fd, data, size) != size){
+ free( data);
+ fprintf( FCGI_stdout, "Reason: Target broken (read error)\r\n");
+ fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld, %lu)\n", fd, offset, size);
+ return NULL;
+ }
+ return data;
+}
+
+Byte_t fetch_1byte( int fd, OPJ_OFF_T offset)
+{
+ Byte_t code;
+
+ if( lseek( fd, offset, SEEK_SET)==-1){
+ fprintf( FCGI_stdout, "Reason: Target broken (seek error)\r\n");
+ fprintf( FCGI_stderr, "Error: error in fetch_1byte( %d, %ld)\n", fd, offset);
+ return 0;
+ }
+
+ if( read( fd, &code, 1) != 1){
+ fprintf( FCGI_stdout, "Reason: Target broken (read error)\r\n");
+ fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld)\n", fd, offset);
+ return 0;
+ }
+ return code;
+}
+
+Byte2_t fetch_2bytebigendian( int fd, OPJ_OFF_T offset)
+{
+ Byte_t *data;
+ Byte2_t code;
+
+ if(!(data = fetch_bytes( fd, offset, 2))){
+ fprintf( FCGI_stderr, "Error: error in fetch_2bytebigendian( %d, %ld)\n", fd, offset);
+ return 0;
+ }
+ code = big2(data);
+ free( data);
+
+ return code;
+}
+
+Byte4_t fetch_4bytebigendian( int fd, OPJ_OFF_T offset)
+{
+ Byte_t *data;
+ Byte4_t code;
+
+ if(!(data = fetch_bytes( fd, offset, 4))){
+ fprintf( FCGI_stderr, "Error: error in fetch_4bytebigendian( %d, %ld)\n", fd, offset);
+ return 0;
+ }
+ code = big4(data);
+ free( data);
+
+ return code;
+}
+
+Byte8_t fetch_8bytebigendian( int fd, OPJ_OFF_T offset)
+{
+ Byte_t *data;
+ Byte8_t code;
+
+ if(!(data = fetch_bytes( fd, offset, 8))){
+ fprintf( FCGI_stderr, "Error: error in fetch_8bytebigendian( %d, %ld)\n", fd, offset);
+ return 0;
+ }
+ code = big8(data);
+ free( data);
+
+ return code;
+}
+
+
+Byte2_t big2( Byte_t *buf)
+{
+ return (Byte2_t)((((Byte2_t) buf[0]) << 8) + ((Byte2_t) buf[1]));
+}
+
+Byte4_t big4( Byte_t *buf)
+{
+ return (((((((Byte4_t) buf[0]) << 8) + ((Byte4_t) buf[1])) << 8)
+ + ((Byte4_t) buf[2])) << 8) + ((Byte4_t) buf[3]);
+}
+
+Byte8_t big8( Byte_t *buf)
+{
+ return (((Byte8_t) big4 (buf)) << 32)
+ + ((Byte8_t) big4 (buf + 4));
+}
+
+void modify_4Bytecode( Byte4_t code, Byte_t *stream)
+{
+ *stream = (Byte_t) ((Byte4_t)(code & 0xff000000) >> 24);
+ *(stream+1) = (Byte_t) ((Byte4_t)(code & 0x00ff0000) >> 16);
+ *(stream+2) = (Byte_t) ((Byte4_t)(code & 0x0000ff00) >> 8);
+ *(stream+3) = (Byte_t) (code & 0x000000ff);
+}
+
+OPJ_OFF_T get_filesize( int fd)
+{
+ struct stat sb;
+
+ if( fstat( fd, &sb) == -1){
+ fprintf( FCGI_stdout, "Reason: Target broken (fstat error)\r\n");
+ fprintf( FCGI_stderr, "Error: error in get_filesize( %d)\n", fd);
+ return 0;
+ }
+ return sb.st_size;
+}
diff --git a/src/lib/openjpip/byte_manager.h b/src/lib/openjpip/byte_manager.h
new file mode 100644
index 00000000..0a29503e
--- /dev/null
+++ b/src/lib/openjpip/byte_manager.h
@@ -0,0 +1,129 @@
+/*
+ * $Id: byte_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 BYTE_MANAGER_H_
+#define BYTE_MANAGER_H_
+
+#include <stddef.h>
+#include "opj_stdint.h"
+typedef uint8_t Byte_t;
+typedef uint16_t Byte2_t;
+typedef uint32_t Byte4_t;
+typedef uint64_t Byte8_t;
+
+/**
+ * fetch bytes of data in file stream
+ *
+ * @param[in] fd file discriptor
+ * @param[in] offset start Byte position
+ * @param[in] size Byte length
+ * @return pointer to the fetched data
+ */
+Byte_t * fetch_bytes( int fd, OPJ_OFF_T offset, OPJ_SIZE_T size);
+
+
+/**
+ * fetch a 1-byte Byte codes in file stream
+ *
+ * @param[in] fd file discriptor
+ * @param[in] offset start Byte position
+ * @return fetched codes
+ */
+Byte_t fetch_1byte( int fd, OPJ_OFF_T offset);
+
+/**
+ * fetch a 2-byte big endian Byte codes in file stream
+ *
+ * @param[in] fd file discriptor
+ * @param[in] offset start Byte position
+ * @return fetched codes
+ */
+Byte2_t fetch_2bytebigendian( int fd, OPJ_OFF_T offset);
+
+/**
+ * fetch a 4-byte big endian Byte codes in file stream
+ *
+ * @param[in] fd file discriptor
+ * @param[in] offset start Byte position
+ * @return fetched codes
+ */
+Byte4_t fetch_4bytebigendian( int fd, OPJ_OFF_T offset);
+
+/**
+ * fetch a 8-byte big endian Byte codes in file stream
+ *
+ * @param[in] fd file discriptor
+ * @param[in] offset start Byte position
+ * @return fetched codes
+ */
+Byte8_t fetch_8bytebigendian( int fd, OPJ_OFF_T offset);
+
+
+/**
+ * convert 2-byte big endian Byte codes to number
+ *
+ * @param[in] buf Byte codes
+ * @return resolved number
+ */
+Byte2_t big2( Byte_t *buf);
+
+/**
+ * convert 4-byte big endian Byte codes to number
+ *
+ * @param[in] buf Byte codes
+ * @return resolved number
+ */
+Byte4_t big4( Byte_t *buf);
+
+/**
+ * convert 8-byte big endian Byte codes to number
+ *
+ * @param[in] buf Byte codes
+ * @return resolved number
+ */
+Byte8_t big8( Byte_t *buf);
+
+/**
+ * modify 4Byte code in a codestream
+ *
+ * @param[in] code code value
+ * @param[out] stream modifying codestream
+ */
+void modify_4Bytecode( Byte4_t code, Byte_t *stream);
+
+/**
+ * Get file size
+ *
+ * @param[in] fd file discriptor
+ * @return file size
+ */
+OPJ_OFF_T get_filesize( int fd);
+
+#endif /* !BYTE_MANAGER_H_ */
diff --git a/src/lib/openjpip/cache_manager.c b/src/lib/openjpip/cache_manager.c
new file mode 100644
index 00000000..76f7b7b3
--- /dev/null
+++ b/src/lib/openjpip/cache_manager.c
@@ -0,0 +1,275 @@
+/*
+ * $Id: cache_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cache_manager.h"
+
+cachelist_param_t * gene_cachelist(void)
+{
+ cachelist_param_t *cachelist;
+
+ cachelist = (cachelist_param_t *)malloc( sizeof(cachelist_param_t));
+
+ cachelist->first = NULL;
+ cachelist->last = NULL;
+
+ return cachelist;
+}
+
+void delete_cachelist(cachelist_param_t **cachelist)
+{
+ cache_param_t *cachePtr, *cacheNext;
+
+ cachePtr = (*cachelist)->first;
+ while( cachePtr != NULL){
+ cacheNext=cachePtr->next;
+ delete_cache( &cachePtr);
+ cachePtr=cacheNext;
+ }
+ free( *cachelist);
+}
+
+cache_param_t * gene_cache( const char *targetname, int csn, char *tid, char *cid)
+{
+ cache_param_t *cache;
+
+ cache = (cache_param_t *)malloc( sizeof(cache_param_t));
+ cache->filename = strdup( targetname);
+ cache->tid = strdup( tid);
+ cache->csn = csn;
+ cache->cid = (char **)malloc( sizeof(char *));
+ *cache->cid = strdup( cid);
+ cache->numOfcid = 1;
+#if 1
+ cache->metadatalist = NULL;
+#else
+ cache->metadatalist = gene_metadatalist();
+#endif
+ cache->ihdrbox = NULL;
+ cache->next = NULL;
+
+ return cache;
+}
+
+void delete_cache( cache_param_t **cache)
+{
+ int i;
+
+ free( (*cache)->filename);
+ free( (*cache)->tid);
+
+ delete_metadatalist( &(*cache)->metadatalist);
+
+ if((*cache)->ihdrbox)
+ free((*cache)->ihdrbox);
+ for( i=0; i<(*cache)->numOfcid; i++)
+ free( (*cache)->cid[i]);
+ free( (*cache)->cid);
+ free( *cache);
+}
+
+void insert_cache_into_list( cache_param_t *cache, cachelist_param_t *cachelist)
+{
+ if( cachelist->first)
+ cachelist->last->next = cache;
+ else
+ cachelist->first = cache;
+ cachelist->last = cache;
+}
+
+cache_param_t * search_cache( const char targetname[], cachelist_param_t *cachelist)
+{
+ cache_param_t *foundcache;
+
+ if( !targetname)
+ return NULL;
+
+ foundcache = cachelist->first;
+
+ while( foundcache != NULL){
+
+ if( strcmp( targetname, foundcache->filename) == 0)
+ return foundcache;
+
+ foundcache = foundcache->next;
+ }
+ return NULL;
+}
+
+cache_param_t * search_cacheBycsn( int csn, cachelist_param_t *cachelist)
+{
+ cache_param_t *foundcache;
+
+ foundcache = cachelist->first;
+
+ while( foundcache != NULL){
+
+ if( csn == foundcache->csn)
+ return foundcache;
+ foundcache = foundcache->next;
+ }
+ return NULL;
+}
+
+cache_param_t * search_cacheBycid( const char cid[], cachelist_param_t *cachelist)
+{
+ cache_param_t *foundcache;
+ int i;
+
+ if( !cid)
+ return NULL;
+
+ foundcache = cachelist->first;
+
+ while( foundcache != NULL){
+ for( i=0; i<foundcache->numOfcid; i++)
+ if( strcmp( cid, foundcache->cid[i]) == 0)
+ return foundcache;
+ foundcache = foundcache->next;
+ }
+ return NULL;
+}
+
+cache_param_t * search_cacheBytid( const char tid[], cachelist_param_t *cachelist)
+{
+ cache_param_t *foundcache;
+
+ if( !tid)
+ return NULL;
+
+ foundcache = cachelist->first;
+
+ while( foundcache != NULL){
+ if( strcmp( tid, foundcache->tid) == 0)
+ return foundcache;
+ foundcache = foundcache->next;
+ }
+ return NULL;
+}
+
+void add_cachecid( const char *cid, cache_param_t *cache)
+{
+ if( !cid)
+ return;
+
+ if( (cache->cid = realloc( cache->cid, (OPJ_SIZE_T)(cache->numOfcid+1)*sizeof(char *))) == NULL){
+ fprintf( stderr, "failed to add new cid to cache table in add_cachecid()\n");
+ return;
+ }
+
+ cache->cid[ cache->numOfcid] = strdup( cid);
+
+ cache->numOfcid ++;
+}
+
+void update_cachetid( const char *tid, cache_param_t *cache)
+{
+ if( !tid)
+ return;
+
+ if( tid[0] != '0' && strcmp( tid, cache->tid) !=0){
+ fprintf( stderr, "tid is updated to %s for %s\n", tid, cache->filename);
+ free( cache->tid);
+ cache->tid = strdup( tid);
+ }
+}
+
+void remove_cidInCache( const char *cid, cache_param_t *cache);
+
+void remove_cachecid( const char *cid, cachelist_param_t *cachelist)
+{
+ cache_param_t *cache;
+
+ cache = search_cacheBycid( cid, cachelist);
+ remove_cidInCache( cid, cache);
+}
+
+void remove_cidInCache( const char *cid, cache_param_t *cache)
+{
+ int idx = -1;
+ char **tmp;
+ int i, j;
+
+ for( i=0; i<cache->numOfcid; i++)
+ if( strcmp( cid, cache->cid[i]) == 0){
+ idx = i;
+ break;
+ }
+
+ if( idx == -1){
+ fprintf( stderr, "cid: %s not found\n", cid);
+ return;
+ }
+
+ tmp = cache->cid;
+
+ cache->cid = (char **)malloc( (OPJ_SIZE_T)(cache->numOfcid-1)*sizeof(char *));
+
+ for( i=0, j=0; i<cache->numOfcid; i++){
+ if( i != idx){
+ cache->cid[j] = strdup( tmp[i]);
+ j++;
+ }
+ free( tmp[i]);
+ }
+ free( tmp);
+
+ cache->numOfcid --;
+}
+
+void print_cache( cache_param_t *cache)
+{
+ int i;
+
+ fprintf( stdout,"cache\n");
+ fprintf( stdout,"\t filename: %s\n", cache->filename);
+ fprintf( stdout,"\t tid: %s\n", cache->tid);
+ fprintf( stdout,"\t csn: %d\n", cache->csn);
+ fprintf( stdout,"\t cid:");
+
+ for( i=0; i<cache->numOfcid; i++)
+ fprintf( stdout," %s", cache->cid[i]);
+ fprintf( stdout,"\n");
+}
+
+void print_allcache( cachelist_param_t *cachelist)
+{
+ cache_param_t *ptr;
+
+ fprintf( stdout,"cache list\n");
+
+ ptr = cachelist->first;
+ while( ptr != NULL){
+ print_cache( ptr);
+ ptr=ptr->next;
+ }
+}
diff --git a/src/lib/openjpip/cache_manager.h b/src/lib/openjpip/cache_manager.h
new file mode 100644
index 00000000..0c9afb0b
--- /dev/null
+++ b/src/lib/openjpip/cache_manager.h
@@ -0,0 +1,177 @@
+/*
+ * $Id: cache_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 CACHE_MANAGER_H_
+# define CACHE_MANAGER_H_
+
+#include "metadata_manager.h"
+#include "ihdrbox_manager.h"
+
+/** cache parameters*/
+typedef struct cache_param{
+ char *filename; /**< file name*/
+ char *tid; /**< taregt identifier*/
+ int csn; /**< codestream number*/
+ char **cid; /**< dynamic array of channel identifiers*/
+ int numOfcid; /**< number of cids*/
+ metadatalist_param_t *metadatalist; /**< metadata-bin list*/
+ ihdrbox_param_t *ihdrbox; /**< ihdrbox*/
+ struct cache_param *next; /**< pointer to the next cache*/
+} cache_param_t;
+
+/**< cache list parameters*/
+typedef struct cachelist_param{
+ cache_param_t *first; /**< first cache pointer of the list*/
+ cache_param_t *last; /**< last cache pointer of the list*/
+} cachelist_param_t;
+
+
+/**
+ * generate a cache list
+ *
+ * @return pointer to the generated cache list
+ */
+cachelist_param_t * gene_cachelist(void);
+
+/**
+ * delete cache list
+ *
+ * @param[in,out] cachelist address of the cache list pointer
+ */
+void delete_cachelist(cachelist_param_t **cachelist);
+
+/**
+ * generate a cache
+ *
+ * @param[in] targetname target file name
+ * @param[in] csn codestream number
+ * @param[in] tid target identifier
+ * @param[in] cid channel identifier
+ * @return pointer to the generated cache
+ */
+cache_param_t * gene_cache( const char *targetname, int csn, char *tid, char *cid);
+
+/**
+ * delete a cache
+ *
+ * @param[in] cache address of the cache pointer
+ */
+void delete_cache( cache_param_t **cache);
+
+/**
+ * insert a cache into list
+ *
+ * @param[in] cache cache pointer
+ * @param[in] cachelist cache list pointer
+ */
+void insert_cache_into_list( cache_param_t *cache, cachelist_param_t *cachelist);
+
+
+/**
+ * search a cache by target name
+ *
+ * @param[in] targetname target filename
+ * @param[in] cachelist cache list pointer
+ * @return found cache pointer
+ */
+cache_param_t * search_cache( const char targetname[], cachelist_param_t *cachelist);
+
+
+/**
+ * search a cache by csn
+ *
+ * @param[in] csn codestream number
+ * @param[in] cachelist cache list pointer
+ * @return found cache pointer
+ */
+cache_param_t * search_cacheBycsn( int csn, cachelist_param_t *cachelist);
+
+
+/**
+ * search a cache by cid
+ *
+ * @param[in] cid channel identifer
+ * @param[in] cachelist cache list pointer
+ * @return found cache pointer
+ */
+cache_param_t * search_cacheBycid( const char cid[], cachelist_param_t *cachelist);
+
+
+/**
+ * search a cache by tid
+ *
+ * @param[in] tid target identifer
+ * @param[in] cachelist cache list pointer
+ * @return found cache pointer
+ */
+cache_param_t * search_cacheBytid( const char tid[], cachelist_param_t *cachelist);
+
+/**
+ * add cid into a cache
+ *
+ * @param[in] cid channel identifier
+ * @param[in] cache cache pointer
+ */
+void add_cachecid( const char *cid, cache_param_t *cache);
+
+
+/**
+ * update tid of a cache
+ *
+ * @param[in] tid target identifier
+ * @param[in] cache cache pointer
+ */
+void update_cachetid( const char *tid, cache_param_t *cache);
+
+
+/**
+ * remove cid in cache
+ *
+ * @param[in] cid channel identifier
+ * @param[in] cachelist cachelist pointer
+ */
+void remove_cachecid( const char *cid, cachelist_param_t *cachelist);
+
+
+/**
+ * print cache parameters
+ *
+ * @param[in] cache cache pointer
+ */
+void print_cache( cache_param_t *cache);
+
+/**
+ * print all cache parameters
+ *
+ * @param[in] cachelist cache list pointer
+ */
+void print_allcache( cachelist_param_t *cachelist);
+
+#endif /* !CACHE_MANAGER_H_ */
diff --git a/src/lib/openjpip/cachemodel_manager.c b/src/lib/openjpip/cachemodel_manager.c
new file mode 100644
index 00000000..1a84a6b8
--- /dev/null
+++ b/src/lib/openjpip/cachemodel_manager.c
@@ -0,0 +1,236 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "cachemodel_manager.h"
+#include "faixbox_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+cachemodellist_param_t * gene_cachemodellist(void)
+{
+ cachemodellist_param_t *cachemodellist;
+
+ cachemodellist = (cachemodellist_param_t *)malloc( sizeof(cachemodellist_param_t));
+
+ cachemodellist->first = NULL;
+ cachemodellist->last = NULL;
+
+ return cachemodellist;
+}
+
+cachemodel_param_t * gene_cachemodel( cachemodellist_param_t *cachemodellist, target_param_t *target, bool reqJPP)
+{
+ cachemodel_param_t *cachemodel;
+ faixbox_param_t *tilepart;
+ faixbox_param_t *precpacket;
+ size_t numOfelem;
+ Byte8_t numOftiles;
+ int i;
+
+ cachemodel = (cachemodel_param_t *)malloc( sizeof(cachemodel_param_t));
+
+ refer_target( target, &cachemodel->target);
+
+ if( reqJPP){
+ if( target->jppstream)
+ cachemodel->jppstream = true;
+ else
+ cachemodel->jppstream = false;
+ } else{ /* reqJPT */
+ if( target->jptstream)
+ cachemodel->jppstream = false;
+ else
+ cachemodel->jppstream = true;
+ }
+
+ cachemodel->mhead_model = false;
+
+ tilepart = target->codeidx->tilepart;
+ numOftiles = get_m( tilepart);
+ numOfelem = get_nmax( tilepart)*numOftiles;
+ cachemodel->tp_model = (bool *)calloc( 1, numOfelem*sizeof(bool));
+ cachemodel->th_model = (bool *)calloc( 1, numOftiles*sizeof(bool));
+ cachemodel->pp_model = (bool **)malloc( target->codeidx->SIZ.Csiz*sizeof(bool *));
+ for( i=0; i<target->codeidx->SIZ.Csiz; i++){
+ precpacket = target->codeidx->precpacket[i];
+ cachemodel->pp_model[i] = (bool *)calloc( 1, get_nmax(precpacket)*get_m(precpacket)*sizeof(bool));
+ }
+ cachemodel->next = NULL;
+
+ if( cachemodellist){
+ if( cachemodellist->first) /* there are one or more entries */
+ cachemodellist->last->next = cachemodel;
+ else /* first entry */
+ cachemodellist->first = cachemodel;
+ cachemodellist->last = cachemodel;
+ }
+
+#ifndef SERVER
+ fprintf( logstream, "local log: cachemodel generated\n");
+#endif
+
+ return cachemodel;
+}
+
+void print_cachemodel( cachemodel_param_t cachemodel)
+{
+ target_param_t *target;
+ Byte8_t TPnum; /* num of tile parts in each tile */
+ Byte8_t Pmax; /* max num of packets per tile */
+ Byte8_t i, j, k;
+ int n; /* FIXME: Is this large enough ? */
+
+ target = cachemodel.target;
+
+ fprintf( logstream, "target: %s\n", target->targetname);
+ fprintf( logstream, "\t main header model: %d\n", cachemodel.mhead_model);
+
+ fprintf( logstream, "\t tile part model:\n");
+ TPnum = get_nmax( target->codeidx->tilepart);
+
+ for( i=0, n=0; i<target->codeidx->SIZ.YTnum; i++){
+ for( j=0; j<target->codeidx->SIZ.XTnum; j++){
+ for( k=0; k<TPnum; k++)
+ fprintf( logstream, "%d", cachemodel.tp_model[n++]);
+ fprintf( logstream, " ");
+ }
+ fprintf( logstream, "\n");
+ }
+
+ fprintf( logstream, "\t tile header and precinct packet model:\n");
+ for( i=0; i<target->codeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){
+ fprintf( logstream, "\t tile.%" PRIu64 " %d\n", i, cachemodel.th_model[i]);
+ for( j=0; j<target->codeidx->SIZ.Csiz; j++){
+ fprintf( logstream, "\t compo.%" PRIu64 ": ", j);
+ Pmax = get_nmax( target->codeidx->precpacket[j]);
+ for( k=0; k<Pmax; k++)
+ fprintf( logstream, "%d", cachemodel.pp_model[j][i*Pmax+k]);
+ fprintf( logstream, "\n");
+ }
+ }
+}
+
+cachemodel_param_t * search_cachemodel( target_param_t *target, cachemodellist_param_t *cachemodellist)
+{
+ cachemodel_param_t *foundcachemodel;
+
+ foundcachemodel = cachemodellist->first;
+
+ while( foundcachemodel != NULL){
+
+ if( foundcachemodel->target == target)
+ return foundcachemodel;
+
+ foundcachemodel = foundcachemodel->next;
+ }
+ return NULL;
+}
+
+void delete_cachemodellist( cachemodellist_param_t **cachemodellist)
+{
+ cachemodel_param_t *cachemodelPtr, *cachemodelNext;
+
+ cachemodelPtr = (*cachemodellist)->first;
+ while( cachemodelPtr != NULL){
+ cachemodelNext=cachemodelPtr->next;
+ delete_cachemodel( &cachemodelPtr);
+ cachemodelPtr=cachemodelNext;
+ }
+ free(*cachemodellist);
+}
+
+void delete_cachemodel( cachemodel_param_t **cachemodel)
+{
+ int i;
+
+ unrefer_target( (*cachemodel)->target);
+
+ free( (*cachemodel)->tp_model);
+ free( (*cachemodel)->th_model);
+
+ for( i=0; i<(*cachemodel)->target->codeidx->SIZ.Csiz; i++)
+ free( (*cachemodel)->pp_model[i]);
+ free( (*cachemodel)->pp_model);
+
+#ifndef SERVER
+ fprintf( logstream, "local log: cachemodel deleted\n");
+#endif
+ free( *cachemodel);
+}
+
+bool is_allsent( cachemodel_param_t cachemodel)
+{
+ target_param_t *target;
+ Byte8_t TPnum; /* num of tile parts in each tile */
+ Byte8_t Pmax; /* max num of packets per tile */
+ Byte8_t i, j, k;
+ int n; /* FIXME: is this large enough ? */
+
+ target = cachemodel.target;
+
+ if( !cachemodel.mhead_model)
+ return false;
+
+ TPnum = get_nmax( target->codeidx->tilepart);
+
+ if( cachemodel.jppstream){
+ for( i=0; i<target->codeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){
+ if( !cachemodel.th_model[i])
+ return false;
+
+ for( j=0; j<target->codeidx->SIZ.Csiz; j++){
+ Pmax = get_nmax( target->codeidx->precpacket[j]);
+ for( k=0; k<Pmax; k++)
+ if( !cachemodel.pp_model[j][i*Pmax+k])
+ return false;
+ }
+ }
+ return true;
+ }
+ else{
+ for( i=0, n=0; i<target->codeidx->SIZ.YTnum; i++)
+ for( j=0; j<target->codeidx->SIZ.XTnum; j++)
+ for( k=0; k<TPnum; k++)
+ if( !cachemodel.tp_model[n++])
+ return false;
+ return true;
+ }
+}
diff --git a/src/lib/openjpip/cachemodel_manager.h b/src/lib/openjpip/cachemodel_manager.h
new file mode 100644
index 00000000..2c9dc540
--- /dev/null
+++ b/src/lib/openjpip/cachemodel_manager.h
@@ -0,0 +1,115 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 CACHEMODEL_MANAGER_H_
+# define CACHEMODEL_MANAGER_H_
+
+#include "bool.h"
+#include "target_manager.h"
+
+/** Cache model parameters*/
+typedef struct cachemodel_param{
+ target_param_t *target; /**< reference pointer to the target*/
+ bool jppstream; /**< return type, true: JPP-stream, false: JPT-stream*/
+ bool mhead_model; /**< main header model, if sent, 1, else 0*/
+ bool *tp_model; /**< dynamic array pointer of tile part model, if sent, 1, else 0*/
+ bool *th_model; /**< dynamic array pointer of tile header model*/
+ bool **pp_model; /**< dynamic array pointer of precint packet model*/
+ struct cachemodel_param *next; /**< pointer to the next cache model*/
+} cachemodel_param_t;
+
+/** Cache model list parameters*/
+typedef struct cachemodellist_param{
+ cachemodel_param_t *first; /**< first cache model pointer of the list*/
+ cachemodel_param_t *last; /**< last cache model pointer of the list*/
+} cachemodellist_param_t;
+
+
+/**
+ * generate a cache model list
+ *
+ * @return pointer to the generated cache model list
+ */
+cachemodellist_param_t * gene_cachemodellist(void);
+
+/**
+ * generate a cache model under a list
+ *
+ * @param[in] cachemodellist cachemodel list to insert the generated cache model, NULL for stateless
+ * @param[in] target pointer the reference target
+ * @param[in] reqJPP if JPP-stream is desired true, JPT-stream false
+ * @return pointer to the generated cache model
+ */
+cachemodel_param_t * gene_cachemodel( cachemodellist_param_t *cachemodellist, target_param_t *target, bool reqJPP);
+
+
+/**
+ * print cache model
+ *
+ * @param[in] cachemodel cache model
+ */
+void print_cachemodel( cachemodel_param_t cachemodel);
+
+
+/**
+ * search a cache model of a target
+ *
+ * @param[in] target refering target
+ * @param[in] cachemodellist cache model list
+ * @return found cache model pointer
+ */
+cachemodel_param_t * search_cachemodel( target_param_t *target, cachemodellist_param_t *cachemodellist);
+
+
+/**
+ * check if all data has been sent
+ *
+ * @param[in] cachemodel cache model
+ * @return true if sent all, false otherwise
+ */
+bool is_allsent( cachemodel_param_t cachemodel);
+
+
+/**
+ * delete a cache model
+ *
+ * @param[in] cachemodel address of the cachemodel pointer
+ */
+void delete_cachemodel( cachemodel_param_t **cachemodel);
+
+/**
+ * delete cachemodel list
+ *
+ * @param[in,out] cachemodellist address of the cachemodel list pointer
+ */
+void delete_cachemodellist( cachemodellist_param_t **cachemodellist);
+
+
+#endif /* !CACHEMODEL_MANAGER_H_ */
diff --git a/src/lib/openjpip/channel_manager.c b/src/lib/openjpip/channel_manager.c
new file mode 100644
index 00000000..313f8ced
--- /dev/null
+++ b/src/lib/openjpip/channel_manager.c
@@ -0,0 +1,180 @@
+/*
+ * $Id: channel_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "channel_manager.h"
+#ifdef _WIN32
+#define snprintf _snprintf /* Visual Studio */
+#endif
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+channellist_param_t * gene_channellist(void)
+{
+ channellist_param_t *channellist;
+
+ channellist = (channellist_param_t *)malloc( sizeof(channellist_param_t));
+
+ channellist->first = NULL;
+ channellist->last = NULL;
+
+ return channellist;
+}
+
+channel_param_t * gene_channel( query_param_t query_param, auxtrans_param_t auxtrans, cachemodel_param_t *cachemodel, channellist_param_t *channellist)
+{
+ channel_param_t *channel;
+ const char transport[4][10] = { "non", "http", "http-tcp", "http-udp"};
+
+ if( !cachemodel){
+ fprintf( FCGI_stdout, "Status: 404\r\n");
+ fprintf( FCGI_stdout, "Reason: cnew cancelled\r\n");
+ return NULL;
+ }
+
+ channel = (channel_param_t *)malloc( sizeof(channel_param_t));
+ channel->cachemodel = cachemodel;
+
+ /* set channel ID and get present time */
+ snprintf( channel->cid, MAX_LENOFCID, "%x%x", (unsigned int)time( &channel->start_tm), (unsigned int)rand());
+
+ channel->aux = query_param.cnew;
+
+ /* only tcp implemented for now */
+ if( channel->aux == udp)
+ channel->aux = tcp;
+
+ channel->next=NULL;
+
+ set_channel_variable_param( query_param, channel);
+
+ if( channellist->first != NULL)
+ channellist->last->next = channel;
+ else
+ channellist->first = channel;
+ channellist->last = channel;
+
+ fprintf( FCGI_stdout, "JPIP-cnew: cid=%s", channel->cid);
+ fprintf( FCGI_stdout, ",transport=%s", transport[channel->aux]);
+
+ if( channel->aux == tcp || channel->aux == udp)
+ fprintf( FCGI_stdout, ",auxport=%d", channel->aux==tcp ? auxtrans.tcpauxport : auxtrans.udpauxport);
+
+ fprintf( FCGI_stdout, "\r\n");
+
+ return channel;
+}
+
+
+void set_channel_variable_param( query_param_t query_param, channel_param_t *channel)
+{
+ /* set roi information */
+ (void)query_param;
+ (void)channel;
+}
+
+
+void delete_channel( channel_param_t **channel, channellist_param_t *channellist)
+{
+ channel_param_t *ptr;
+
+ if( *channel == channellist->first)
+ channellist->first = (*channel)->next;
+ else{
+ ptr = channellist->first;
+ while( ptr->next != *channel){
+ ptr=ptr->next;
+ }
+
+ ptr->next = (*channel)->next;
+
+ if( *channel == channellist->last)
+ channellist->last = ptr;
+ }
+#ifndef SERVER
+ fprintf( logstream, "local log: channel: %s deleted\n", (*channel)->cid);
+#endif
+ free(*channel);
+}
+
+void delete_channellist( channellist_param_t **channellist)
+{
+ channel_param_t *channelPtr, *channelNext;
+
+ channelPtr = (*channellist)->first;
+ while( channelPtr != NULL){
+ channelNext=channelPtr->next;
+#ifndef SERVER
+ fprintf( logstream, "local log: channel %s deleted!\n", channelPtr->cid);
+#endif
+ free(channelPtr);
+ channelPtr=channelNext;
+ }
+ free( *channellist);
+}
+
+void print_allchannel( channellist_param_t *channellist)
+{
+ channel_param_t *ptr;
+
+ ptr = channellist->first;
+ while( ptr != NULL){
+ fprintf( logstream,"channel-ID=%s \t target=%s\n", ptr->cid, ptr->cachemodel->target->targetname);
+ ptr=ptr->next;
+ }
+}
+
+channel_param_t * search_channel( const char cid[], channellist_param_t *channellist)
+{
+ channel_param_t *foundchannel;
+
+ foundchannel = channellist->first;
+
+ while( foundchannel != NULL){
+
+ if( strcmp( cid, foundchannel->cid) == 0)
+ return foundchannel;
+
+ foundchannel = foundchannel->next;
+ }
+ fprintf( FCGI_stdout, "Status: 503\r\n");
+ fprintf( FCGI_stdout, "Reason: Channel %s not found in this session\r\n", cid);
+
+ return NULL;
+}
diff --git a/src/lib/openjpip/channel_manager.h b/src/lib/openjpip/channel_manager.h
new file mode 100644
index 00000000..79cc0160
--- /dev/null
+++ b/src/lib/openjpip/channel_manager.h
@@ -0,0 +1,120 @@
+/*
+ * $Id: channel_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 CHANNEL_MANAGER_H_
+# define CHANNEL_MANAGER_H_
+
+#include <time.h>
+#include "query_parser.h"
+#include "cachemodel_manager.h"
+#include "auxtrans_manager.h"
+
+/** maximum length of channel identifier*/
+#define MAX_LENOFCID 30
+
+/** Channel parameters*/
+typedef struct channel_param{
+ cachemodel_param_t *cachemodel; /**< reference pointer to the cache model*/
+ char cid[MAX_LENOFCID]; /**< channel identifier*/
+ cnew_transport_t aux; /**< auxiliary transport*/
+ /* - a record of the client's capabilities and preferences to the extent that the server queues requests*/
+ time_t start_tm; /**< starting time*/
+ struct channel_param *next; /**< pointer to the next channel*/
+} channel_param_t;
+
+
+/** Channel list parameters*/
+typedef struct channellist_param{
+ channel_param_t *first; /**< first channel pointer of the list*/
+ channel_param_t *last; /**< last channel pointer of the list*/
+} channellist_param_t;
+
+
+/**
+ * generate a channel list
+ *
+ * @return pointer to the generated channel list
+ */
+channellist_param_t * gene_channellist(void);
+
+
+/**
+ * generate a channel under the channel list
+ *
+ * @param[in] query_param query parameters
+ * @param[in] auxtrans auxiliary transport
+ * @param[in] cachemodel reference cachemodel
+ * @param[in] channellist channel list pointer
+ * @return pointer to the generated channel
+ */
+channel_param_t * gene_channel( query_param_t query_param, auxtrans_param_t auxtrans, cachemodel_param_t *cachemodel, channellist_param_t *channellist);
+
+/**
+ * set channel variable parameters
+ *
+ * @param[in] query_param query parameters
+ * @param[in,out] channel pointer to the modifying channel
+ */
+void set_channel_variable_param( query_param_t query_param, channel_param_t *channel);
+
+/**
+ * delete a channel
+ *
+ * @param[in] channel address of the deleting channel pointer
+ * @param[in,out] channellist channel list pointer
+ */
+void delete_channel( channel_param_t **channel, channellist_param_t *channellist);
+
+
+/**
+ * delete channel list
+ *
+ * @param[in,out] channellist address of the channel list pointer
+ */
+void delete_channellist( channellist_param_t **channellist);
+
+
+/**
+ * print all channel parameters
+ *
+ * @param[in] channellist channel list pointer
+ */
+void print_allchannel( channellist_param_t *channellist);
+
+
+/**
+ * search a channel by channel ID
+ *
+ * @param[in] cid channel identifier
+ * @param[in] channellist channel list pointer
+ * @return found channel pointer
+ */
+channel_param_t * search_channel( const char cid[], channellist_param_t *channellist);
+#endif /* !CHANNEL_MANAGER_H_ */
diff --git a/src/lib/openjpip/codestream_manager.c b/src/lib/openjpip/codestream_manager.c
new file mode 100644
index 00000000..d7797c13
--- /dev/null
+++ b/src/lib/openjpip/codestream_manager.c
@@ -0,0 +1,81 @@
+/*
+ * $Id: codestream_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include "codestream_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+codestream_param_t set_codestream( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length)
+{
+ codestream_param_t cs;
+
+ cs.fd = fd;
+ cs.offset = offset;
+ cs.length = length;
+
+ return cs;
+}
+
+Byte_t * fetch_codestreambytes( codestream_param_t *cs, OPJ_OFF_T offset, OPJ_SIZE_T size)
+{
+ return fetch_bytes( cs->fd, cs->offset+offset, size);
+}
+
+Byte_t fetch_codestream1byte( codestream_param_t *cs, OPJ_OFF_T offset)
+{
+ return fetch_1byte( cs->fd, cs->offset+offset);
+}
+
+Byte2_t fetch_codestream2bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset)
+{
+ return fetch_2bytebigendian( cs->fd, cs->offset+offset);
+}
+
+Byte4_t fetch_codestream4bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset)
+{
+ return fetch_4bytebigendian( cs->fd, cs->offset+offset);
+}
+
+void print_codestream( codestream_param_t cs)
+{
+ fprintf( logstream, "codestream info:\n"
+ "\t fd: %d\n"
+ "\t offset: %#" PRIx64 "\n"
+ "\t length: %#" PRIx64 "\n", cs.fd, cs.offset, cs.length);
+}
diff --git a/src/lib/openjpip/codestream_manager.h b/src/lib/openjpip/codestream_manager.h
new file mode 100644
index 00000000..b600d8e5
--- /dev/null
+++ b/src/lib/openjpip/codestream_manager.h
@@ -0,0 +1,101 @@
+/*
+ * $Id: codestream_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 CODESTREAM_MANAGER_H_
+# define CODESTREAM_MANAGER_H_
+
+#include "byte_manager.h"
+
+/** codestream parameters*/
+typedef struct codestream_param{
+ int fd; /**< file descriptor*/
+ OPJ_OFF_T offset; /**< byte position of DBox (Box Contents) in the file*/
+ Byte8_t length; /**< content length*/
+} codestream_param_t;
+
+
+/**
+ * set codestream parameters from inputs
+ *
+ * @param[in] fd file descriptor
+ * @param[in] offset offset in the file
+ * @param[in] length codestream length
+ * @return structure of generated codestream parameters
+ */
+codestream_param_t set_codestream( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length);
+
+
+/**
+ * fetch Codestream bytes of data in file stream
+ *
+ * @param[in] cs codestream pointer
+ * @param[in] offset start Byte position in codestream
+ * @param[in] size Byte length
+ * @return pointer to the fetched data
+ */
+Byte_t * fetch_codestreambytes( codestream_param_t *cs, OPJ_OFF_T offset, OPJ_SIZE_T size);
+
+/**
+ * fetch Codestream 1-byte Byte code in file stream
+ *
+ * @param[in] cs codestream pointer
+ * @param[in] offset start Byte position in codestream
+ * @return fetched code
+ */
+Byte_t fetch_codestream1byte( codestream_param_t *cs, OPJ_OFF_T offset);
+
+/**
+ * fetch Codestream 2-byte big endian Byte codes in file stream
+ *
+ * @param[in] cs codestream pointer
+ * @param[in] offset start Byte position in codestream
+ * @return fetched code
+ */
+Byte2_t fetch_codestream2bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset);
+
+/**
+ * fetch Codestream 4-byte big endian Byte codes in file stream
+ *
+ * @param[in] cs codestream pointer
+ * @param[in] offset start Byte position in codestream
+ * @return fetched code
+ */
+Byte4_t fetch_codestream4bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset);
+
+
+/**
+ * print codestream parameters
+ *
+ * @param[in] cs codestream
+ */
+void print_codestream( codestream_param_t cs);
+
+
+#endif /* !CODESTREAM_MANAGER_H_ */
diff --git a/src/lib/openjpip/dec_clientmsg_handler.c b/src/lib/openjpip/dec_clientmsg_handler.c
new file mode 100644
index 00000000..20bd4f2b
--- /dev/null
+++ b/src/lib/openjpip/dec_clientmsg_handler.c
@@ -0,0 +1,253 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+#include "dec_clientmsg_handler.h"
+#include "ihdrbox_manager.h"
+#include "jpipstream_manager.h"
+#include "jp2k_encoder.h"
+#include "opj_inttypes.h"
+
+void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist,
+ Byte_t **jpipstream, OPJ_SIZE_T *streamlen, msgqueue_param_t *msgqueue)
+{
+ Byte_t *newjpipstream;
+ OPJ_SIZE_T newstreamlen = 0;
+ cache_param_t *cache;
+ char *target, *tid, *cid;
+ metadatalist_param_t *metadatalist;
+
+ newjpipstream = receive_JPIPstream( connected_socket, &target, &tid, &cid, &newstreamlen);
+
+ fprintf( stderr, "newjpipstream length: %" PRIu64 "\n", newstreamlen);
+
+ parse_JPIPstream( newjpipstream, newstreamlen, (OPJ_OFF_T)*streamlen, msgqueue);
+
+ *jpipstream = update_JPIPstream( newjpipstream, newstreamlen, *jpipstream, streamlen);
+ free( newjpipstream);
+
+ metadatalist = gene_metadatalist();
+ parse_metamsg( msgqueue, *jpipstream, *streamlen, metadatalist);
+
+ assert( msgqueue->last );
+ assert( msgqueue->last->csn < INT_MAX );
+ /* cid registration*/
+ if( target != NULL){
+ if((cache = search_cache( target, cachelist))){
+ if( tid != NULL)
+ update_cachetid( tid, cache);
+ if( cid != NULL)
+ add_cachecid( cid, cache);
+ }
+ else{
+ cache = gene_cache( target, (int)msgqueue->last->csn, tid, cid);
+ insert_cache_into_list( cache, cachelist);
+ }
+ }
+ else
+ cache = search_cacheBycsn( (int)msgqueue->last->csn, cachelist);
+
+ if( cache->metadatalist)
+ delete_metadatalist( &cache->metadatalist);
+ cache->metadatalist = metadatalist;
+
+ if( target) free( target);
+ if( tid) free( tid);
+ if( cid) free( cid);
+
+ response_signal( connected_socket, true);
+}
+
+void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist)
+{
+ Byte_t *pnmstream;
+ ihdrbox_param_t *ihdrbox;
+ char *CIDorTID, tmp[10];
+ cache_param_t *cache;
+ int fw, fh;
+ int maxval;
+
+ CIDorTID = receive_string( connected_socket);
+
+ if(!(cache = search_cacheBycid( CIDorTID, cachelist)))
+ if(!(cache = search_cacheBytid( CIDorTID, cachelist))){
+ free( CIDorTID);
+ return;
+ }
+
+ free( CIDorTID);
+
+ receive_line( connected_socket, tmp);
+ fw = atoi( tmp);
+
+ receive_line( connected_socket, tmp);
+ fh = atoi( tmp);
+
+ ihdrbox = NULL;
+ assert( cache->csn >= 0 );
+ pnmstream = jpipstream_to_pnm( jpipstream, msgqueue, (Byte8_t)cache->csn, fw, fh, &ihdrbox);
+
+ maxval = ihdrbox->bpc > 8 ? 255 : (1 << ihdrbox->bpc) - 1;
+ send_PNMstream( connected_socket, pnmstream, ihdrbox->width, ihdrbox->height, ihdrbox->nc, (Byte_t)maxval );
+
+ free( ihdrbox);
+ free( pnmstream);
+}
+
+void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist)
+{
+ char *cid;
+ cache_param_t *cache;
+ boxcontents_param_t *boxcontents;
+ Byte_t *xmlstream;
+
+ cid = receive_string( connected_socket);
+
+ if(!(cache = search_cacheBycid( cid, cachelist))){
+ free( cid);
+ return;
+ }
+
+ free( cid);
+
+ boxcontents = cache->metadatalist->last->boxcontents;
+ xmlstream = (Byte_t *)malloc( boxcontents->length);
+ memcpy( xmlstream, jpipstream+boxcontents->offset, boxcontents->length);
+ send_XMLstream( connected_socket, xmlstream, boxcontents->length);
+ free( xmlstream);
+}
+
+void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist)
+{
+ char *target, *tid = NULL;
+ cache_param_t *cache;
+ OPJ_SIZE_T tidlen = 0;
+
+ target = receive_string( connected_socket);
+ cache = search_cache( target, cachelist);
+
+ free( target);
+
+ if( cache){
+ tid = cache->tid;
+ tidlen = strlen(tid);
+ }
+ send_TIDstream( connected_socket, tid, tidlen);
+}
+
+void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist)
+{
+ char *target, *cid = NULL;
+ cache_param_t *cache;
+ OPJ_SIZE_T cidlen = 0;
+
+ target = receive_string( connected_socket);
+ cache = search_cache( target, cachelist);
+
+ free( target);
+
+ if( cache){
+ if( cache->numOfcid > 0){
+ cid = cache->cid[ cache->numOfcid-1];
+ cidlen = strlen(cid);
+ }
+ }
+ send_CIDstream( connected_socket, cid, cidlen);
+}
+
+void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist)
+{
+ char *cid;
+
+ cid = receive_string( connected_socket);
+ remove_cachecid( cid, cachelist);
+ response_signal( connected_socket, true);
+
+ free( cid);
+}
+
+void handle_SIZreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist)
+{
+ char *tid, *cid;
+ cache_param_t *cache;
+ Byte4_t width, height;
+
+ tid = receive_string( connected_socket);
+ cid = receive_string( connected_socket);
+
+ cache = NULL;
+
+ if( tid[0] != '0')
+ cache = search_cacheBytid( tid, cachelist);
+
+ if( !cache && cid[0] != '0')
+ cache = search_cacheBycid( cid, cachelist);
+
+ free( tid);
+ free( cid);
+
+ width = height = 0;
+ if( cache){
+ assert( cache->csn >= 0);
+ if( !cache->ihdrbox)
+ cache->ihdrbox = get_SIZ_from_jpipstream( jpipstream, msgqueue, (Byte8_t)cache->csn);
+ width = cache->ihdrbox->width;
+ height = cache->ihdrbox->height;
+ }
+ send_SIZstream( connected_socket, width, height);
+}
+
+void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream)
+{
+ char *cid;
+ cache_param_t *cache;
+ Byte_t *jp2stream;
+ Byte8_t jp2len;
+
+ cid = receive_string( connected_socket);
+ if(!(cache = search_cacheBycid( cid, cachelist))){
+ free( cid);
+ return;
+ }
+
+ free( cid);
+
+ assert( cache->csn >= 0);
+ jp2stream = recons_jp2( msgqueue, jpipstream, (Byte8_t)cache->csn, &jp2len);
+
+ if( jp2stream){
+ save_codestream( jp2stream, jp2len, "jp2");
+ free( jp2stream);
+ }
+}
diff --git a/src/lib/openjpip/dec_clientmsg_handler.h b/src/lib/openjpip/dec_clientmsg_handler.h
new file mode 100644
index 00000000..7929207a
--- /dev/null
+++ b/src/lib/openjpip/dec_clientmsg_handler.h
@@ -0,0 +1,113 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 DEC_CLIENTMSG_HANDLER_H_
+# define DEC_CLIENTMSG_HANDLER_H_
+
+#include "imgsock_manager.h"
+#include "cache_manager.h"
+#include "byte_manager.h"
+#include "msgqueue_manager.h"
+
+/**
+ * handle JPT- JPP- stream message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] cachelist cache list pointer
+ * @param[in,out] jpipstream address of JPT- JPP- stream pointer
+ * @param[in,out] streamlen address of stream length
+ * @param[in,out] msgqueue message queue pointer
+ */
+void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, Byte_t **jpipstream, OPJ_SIZE_T *streamlen, msgqueue_param_t *msgqueue);
+
+/**
+ * handle PNM request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] jpipstream jpipstream pointer
+ * @param[in] msgqueue message queue pointer
+ * @param[in] cachelist cache list pointer
+ */
+void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist);
+
+/**
+ * handle XML request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] jpipstream address of caching jpipstream pointer
+ * @param[in] cachelist cache list pointer
+ */
+void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist);
+
+/**
+ * handle TargetID request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] cachelist cache list pointer
+ */
+void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist);
+
+/**
+ * handle ChannelID request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] cachelist cache list pointer
+ */
+void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist);
+
+/**
+ * handle distroy ChannelID message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in,out] cachelist cache list pointer
+ */
+void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist);
+
+/**
+ * handle SIZ request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in,out] cachelist cache list pointer
+ */
+void handle_SIZreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist);
+
+/**
+ * handle saving JP2 file request message
+ *
+ * @param[in] connected_socket socket descriptor
+ * @param[in] cachelist cache list pointer
+ * @param[in] msgqueue message queue pointer
+ * @param[in] jpipstream address of caching jpipstream pointer
+ */
+void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream);
+
+
+#endif /* !DEC_CLIENTMSG_HANDLER_H_ */
diff --git a/src/lib/openjpip/faixbox_manager.c b/src/lib/openjpip/faixbox_manager.c
new file mode 100644
index 00000000..3c443832
--- /dev/null
+++ b/src/lib/openjpip/faixbox_manager.c
@@ -0,0 +1,195 @@
+/*
+ * $Id: faixbox_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "faixbox_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+faixbox_param_t * gene_faixbox( box_param_t *box)
+{
+ faixbox_param_t *faix;
+ size_t numOfelem;
+ long pos = 0;
+
+ faix = ( faixbox_param_t *)malloc( sizeof(faixbox_param_t));
+
+ faix->version = fetch_DBox1byte( box, (pos+=1)-1);
+
+ if( 3< faix->version){
+ fprintf( FCGI_stderr, "Error: version %d in faix box is reserved for ISO use.\n", faix->version);
+ free(faix);
+ return NULL;
+ }
+
+ if( faix->version%2){
+ subfaixbox8_param_t *subfaixbox;
+ size_t i;
+
+ faix->subfaixbox.byte8_params = (subfaixbox8_param_t *)malloc( sizeof(subfaixbox8_param_t));
+
+ subfaixbox = faix->subfaixbox.byte8_params;
+ subfaixbox->nmax = fetch_DBox8bytebigendian( box, (pos+=8)-8);
+ subfaixbox->m = fetch_DBox8bytebigendian( box, (pos+=8)-8);
+
+ numOfelem = subfaixbox->nmax*subfaixbox->m;
+
+ subfaixbox->elem = ( faixelem8_param_t *)malloc( numOfelem*sizeof(faixelem8_param_t));
+
+ if( faix->version == 3)
+ subfaixbox->aux = ( Byte4_t *)malloc( numOfelem*sizeof(Byte4_t));
+
+ for( i=0; i<numOfelem; i++){
+ subfaixbox->elem[i].off = fetch_DBox8bytebigendian( box, (pos+=8)-8);
+ subfaixbox->elem[i].len = fetch_DBox8bytebigendian( box, (pos+=8)-8);
+ if( faix->version == 3)
+ subfaixbox->aux[i] = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+ }
+ }
+ else{
+ subfaixbox4_param_t *subfaixbox;
+ size_t i;
+
+ faix->subfaixbox.byte4_params = (subfaixbox4_param_t *)malloc( sizeof(subfaixbox4_param_t));
+
+ subfaixbox = faix->subfaixbox.byte4_params;
+ subfaixbox->nmax = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+ subfaixbox->m = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+
+ numOfelem = subfaixbox->nmax*subfaixbox->m;
+
+ subfaixbox->elem = ( faixelem4_param_t *)malloc( numOfelem*sizeof(faixelem4_param_t));
+
+ if( faix->version == 2)
+ subfaixbox->aux = ( Byte4_t *)malloc( numOfelem*sizeof(Byte4_t));
+
+ for( i=0; i<numOfelem; i++){
+ subfaixbox->elem[i].off = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+ subfaixbox->elem[i].len = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+ if( faix->version == 2)
+ subfaixbox->aux[i] = fetch_DBox4bytebigendian( box, (pos+=4)-4);
+ }
+ }
+ return faix;
+}
+
+void print_faixbox( faixbox_param_t *faix)
+{
+ Byte8_t i, j;
+
+ fprintf( logstream, "faix box info\n");
+ fprintf( logstream, "\tversion: %d\n", faix->version);
+
+ fprintf( logstream, "\t nmax: %#" PRIx64 " = %" PRId64 "\n", get_nmax( faix), get_nmax( faix));
+ fprintf( logstream, "\t m: %#" PRIx64 " = %" PRId64 "\n", get_m( faix), get_m( faix));
+
+ for( i=0; i<get_m( faix); i++){
+ for( j=0; j<get_nmax( faix); j++){
+ fprintf( logstream, "\t off = %#" PRIx64 ", len = %#" PRIx64 "", get_elemOff( faix, j, i), get_elemLen( faix, j, i));
+ if( 2 <= faix->version)
+ fprintf( logstream, ", aux = %#x", get_elemAux( faix, j, i));
+ fprintf( logstream, "\n");
+ }
+ fprintf( logstream, "\n");
+ }
+}
+
+void delete_faixbox( faixbox_param_t **faix)
+{
+ if((*faix)->version%2){
+ free((*faix)->subfaixbox.byte8_params->elem);
+ if( (*faix)->version == 3)
+ free((*faix)->subfaixbox.byte8_params->aux);
+ free((*faix)->subfaixbox.byte8_params);
+ }
+ else{
+ free((*faix)->subfaixbox.byte4_params->elem);
+ if( (*faix)->version == 2)
+ free((*faix)->subfaixbox.byte4_params->aux);
+ free((*faix)->subfaixbox.byte4_params);
+ }
+ free( *faix);
+}
+
+Byte8_t get_nmax( faixbox_param_t *faix)
+{
+ if( faix->version%2)
+ return faix->subfaixbox.byte8_params->nmax;
+ else
+ return (Byte8_t)faix->subfaixbox.byte4_params->nmax;
+}
+
+Byte8_t get_m( faixbox_param_t *faix)
+{
+ if( faix->version%2)
+ return faix->subfaixbox.byte8_params->m;
+ else
+ return (Byte8_t)faix->subfaixbox.byte4_params->m;
+}
+
+Byte8_t get_elemOff( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id)
+{
+ Byte8_t nmax = get_nmax( faix);
+ if( faix->version%2)
+ return faix->subfaixbox.byte8_params->elem[ row_id*nmax+elem_id].off;
+ else
+ return (Byte8_t)faix->subfaixbox.byte4_params->elem[ row_id*nmax+elem_id].off;
+}
+
+Byte8_t get_elemLen( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id)
+{
+ Byte8_t nmax = get_nmax( faix);
+ if( faix->version%2)
+ return faix->subfaixbox.byte8_params->elem[ row_id*nmax+elem_id].len;
+ else
+ return (Byte8_t)faix->subfaixbox.byte4_params->elem[ row_id*nmax+elem_id].len;
+}
+
+Byte4_t get_elemAux( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id)
+{
+ Byte8_t nmax;
+ if( faix->version <2)
+ return (Byte4_t)-1;
+
+ nmax = get_nmax( faix);
+ if( faix->version%2)
+ return faix->subfaixbox.byte8_params->aux[ row_id*nmax+elem_id];
+ else
+ return faix->subfaixbox.byte4_params->aux[ row_id*nmax+elem_id];
+}
diff --git a/src/lib/openjpip/faixbox_manager.h b/src/lib/openjpip/faixbox_manager.h
new file mode 100644
index 00000000..45ea8c3e
--- /dev/null
+++ b/src/lib/openjpip/faixbox_manager.h
@@ -0,0 +1,146 @@
+/*
+ * $Id: faixbox_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 FAIXBOX_MANAGER_H_
+# define FAIXBOX_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+
+/** 4byte parameters of a faix element*/
+typedef struct faixelem4_param{
+ Byte4_t off; /**< offset*/
+ Byte4_t len; /**< length*/
+} faixelem4_param_t;
+
+/** 8byte parameters of a faix element*/
+typedef struct faixelem8_param{
+ Byte8_t off; /**< offset*/
+ Byte8_t len; /**< length*/
+} faixelem8_param_t;
+
+/** 4byte parameters of fragment array index box*/
+typedef struct subfaixbox4_param{
+ Byte4_t nmax; /**< maximum number of valid elements in any row of the array*/
+ Byte4_t m; /**< number of raws of the array*/
+ faixelem4_param_t *elem; /**< dynamic array pointer of faix elements*/
+ Byte4_t *aux; /**< dynamic array pointer of auxiliary*/
+ /**info in each element for version 2 or 3*/
+} subfaixbox4_param_t;
+
+/** 8byte parameters of fragment array index box*/
+typedef struct subfaixbox8_param{
+ Byte8_t nmax; /**< maximum number of valid elements in any row of the array*/
+ Byte8_t m; /**< number of raws of the array*/
+ faixelem8_param_t *elem; /**< dynamic array pointer of faix elements*/
+ Byte4_t *aux; /**< dynamic array pointer of auxiliary*/
+ /**info in each element for version 2 or 3*/
+} subfaixbox8_param_t;
+
+/** variable sized parameters in fragment array index box*/
+typedef union subfaixbox_param{
+ subfaixbox4_param_t *byte4_params; /**< parameters with 4byte codes for version 0 or 2*/
+ subfaixbox8_param_t *byte8_params; /**< parameters with 8byte codes for version 1 or 3*/
+} subfaixbox_param_t;
+
+/** fragment array index box parameters*/
+/** I.3.2.4.2 Fragment Array Index box*/
+typedef struct faixbox_param{
+ Byte_t version; /**< Refer to the Table I.3 - Version values*/
+ subfaixbox_param_t subfaixbox; /**< rest information in faixbox*/
+} faixbox_param_t;
+
+
+/**
+ * generate faix box
+ *
+ * @param[in] box pointer to the reference faix_box
+ * @return generated faixbox
+ */
+faixbox_param_t * gene_faixbox( box_param_t *box);
+
+
+/**
+ * print faix box parameters
+ *
+ * @param[in] faix faix box pointer
+ */
+void print_faixbox( faixbox_param_t *faix);
+
+
+/**
+ * delete faix box
+ *
+ * @param[in,out] faix addressof the faixbox pointer
+ */
+void delete_faixbox( faixbox_param_t **faix);
+
+/**
+ * get nmax parameter value from faix box
+ *
+ * @param[in] faix faix box pointer
+ */
+Byte8_t get_nmax( faixbox_param_t *faix);
+
+/**
+ * get m parameter value from faix box
+ *
+ * @param[in] faix faix box pointer
+ */
+Byte8_t get_m( faixbox_param_t *faix);
+
+/**
+ * get offset of a element from faix box
+ *
+ * @param[in] faix faix box pointer
+ * @param[in] elem_id element id in a row (0<= <nmax)
+ * @param[in] row_id row id (0<= <m)
+ */
+Byte8_t get_elemOff( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id);
+
+/**
+ * get length of a element from faix box
+ *
+ * @param[in] faix faix box pointer
+ * @param[in] elem_id element id in a row (0<= <nmax)
+ * @param[in] row_id row id (0<= <m)
+ */
+Byte8_t get_elemLen( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id);
+
+/**
+ * get aux of a element from faix box
+ *
+ * @param[in] faix faix box pointer
+ * @param[in] elem_id element id in a row (0<= <nmax)
+ * @param[in] row_id row id (0<= <m)
+ */
+Byte4_t get_elemAux( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id);
+
+#endif /* !FAIXBOX_MANAGER_H_ */
diff --git a/src/lib/openjpip/ihdrbox_manager.c b/src/lib/openjpip/ihdrbox_manager.c
new file mode 100644
index 00000000..d501b612
--- /dev/null
+++ b/src/lib/openjpip/ihdrbox_manager.c
@@ -0,0 +1,78 @@
+/*
+ * $Id: ihdrbox_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "ihdrbox_manager.h"
+
+ihdrbox_param_t * gene_ihdrbox( metadatalist_param_t *metadatalist, Byte_t *jpipstream)
+{
+ ihdrbox_param_t *ihdrbox;
+ metadata_param_t *meta;
+ box_param_t *jp2h, *ihdr;
+ int bpc_val;
+
+ jp2h = NULL;
+ meta = metadatalist->first;
+ while( meta){
+ if( meta->boxlist){
+ jp2h = search_box( "jp2h", meta->boxlist);
+ if( jp2h)
+ break;
+ }
+ meta = meta->next;
+ }
+ if( !jp2h){
+ fprintf( stderr, "jp2h box not found\n");
+ return NULL;
+ }
+
+ ihdr = gene_boxbyTypeinStream( jpipstream, get_DBoxoff( jp2h), get_DBoxlen( jp2h), "ihdr");
+
+ if( !ihdr){
+ fprintf( stderr, "ihdr box not found\n");
+ return NULL;
+ }
+
+ ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t));
+
+ ihdrbox->height = big4( jpipstream+get_DBoxoff(ihdr));
+ ihdrbox->width = big4( jpipstream+get_DBoxoff(ihdr)+4);
+ ihdrbox->nc = big2( jpipstream+get_DBoxoff(ihdr)+8);
+ bpc_val = *(jpipstream+get_DBoxoff(ihdr)+10)+1;
+ assert( bpc_val >= 0 && bpc_val <= 255 );
+ ihdrbox->bpc = (Byte_t)bpc_val;
+
+ free( ihdr);
+
+ return ihdrbox;
+}
+
diff --git a/src/lib/openjpip/ihdrbox_manager.h b/src/lib/openjpip/ihdrbox_manager.h
new file mode 100644
index 00000000..9fa9a830
--- /dev/null
+++ b/src/lib/openjpip/ihdrbox_manager.h
@@ -0,0 +1,56 @@
+/*
+ * $Id: ihdrbox_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 IHDRBOX_MANAGER_H_
+# define IHDRBOX_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+#include "metadata_manager.h"
+
+/** I.5.3.1 Image Header box*/
+typedef struct ihdrbox_param{
+ Byte4_t height;
+ Byte4_t width;
+ Byte2_t nc; /**< number of components*/
+ Byte_t bpc; /**< bits per component*/
+} ihdrbox_param_t;
+
+/**
+ * generate ihdr box
+ *
+ * @param[in] metadatalist metadata list pointer
+ * @param[in] jpipstream JPT/JPP stream
+ * @return pointer to generated ihdr box
+ */
+ihdrbox_param_t * gene_ihdrbox( metadatalist_param_t *metadatalist, Byte_t *jpipstream);
+
+
+#endif /* !IHDRBOX_MANAGER_H_ */
diff --git a/src/lib/openjpip/imgreg_manager.c b/src/lib/openjpip/imgreg_manager.c
new file mode 100644
index 00000000..3a713c32
--- /dev/null
+++ b/src/lib/openjpip/imgreg_manager.c
@@ -0,0 +1,157 @@
+/*
+ * $Id: imgreg_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "imgreg_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+imgreg_param_t map_viewin2imgreg( const int fx, const int fy,
+ const int rx, const int ry,
+ const int rw, const int rh,
+ const int XOsiz, const int YOsiz,
+ const int Xsiz, const int Ysiz,
+ const int numOfreslev)
+{
+ imgreg_param_t imgreg;
+ int px,py;
+ int xmax, ymax;
+
+ imgreg.xosiz = XOsiz;
+ imgreg.yosiz = YOsiz;
+ imgreg.fx = fx;
+ imgreg.fy = fy;
+ imgreg.level = 0;
+ xmax = Xsiz;
+ ymax = Ysiz;
+
+ find_level( numOfreslev, &imgreg.level, &imgreg.fx, &imgreg.fy, &imgreg.xosiz, &imgreg.yosiz, &xmax, &ymax);
+
+ if( rx == -1 || ry == -1){
+ imgreg.ox = 0;
+ imgreg.oy = 0;
+ }
+ else{
+ imgreg.ox = rx*imgreg.fx/fx;
+ imgreg.oy = ry*imgreg.fy/fy;
+ }
+
+ if( rw == -1 || rh == -1){
+ imgreg.sx = imgreg.fx;
+ imgreg.sy = imgreg.fy;
+ }
+ else{
+ px = (int)ceil((double)((rx+rw)*imgreg.fx)/(double)fx);
+ py = (int)ceil((double)((ry+rh)*imgreg.fy)/(double)fy);
+
+ if( imgreg.fx < px)
+ px = imgreg.fx;
+ if( imgreg.fy < py)
+ py = imgreg.fy;
+
+ imgreg.sx = px - imgreg.ox;
+ imgreg.sy = py - imgreg.oy;
+ }
+
+ if( fx != imgreg.fx || fy != imgreg.fy)
+ fprintf( FCGI_stdout, "JPIP-fsiz: %d,%d\r\n", imgreg.fx, imgreg.fy);
+
+ if( rw != imgreg.sx || rh != imgreg.sy)
+ fprintf( FCGI_stdout, "JPIP-rsiz: %d,%d\r\n", imgreg.sx, imgreg.sy);
+
+ if( rx != imgreg.ox || ry != imgreg.oy)
+ fprintf( FCGI_stdout, "JPIP-roff: %d,%d\r\n", imgreg.ox, imgreg.oy);
+
+ return imgreg;
+}
+
+void find_level( int maxlev, int *lev, int *fx, int *fy, int *xmin, int *ymin, int *xmax, int *ymax)
+{
+ int xwidth = *xmax - *xmin;
+ int ywidth = *ymax - *ymin;
+
+ /* Find smaller frame size for now (i.e. assume "round-down"). */
+ if ((*fx < 1 && xwidth != 0) || (*fy < 1 && ywidth != 0)){
+ fprintf( FCGI_stderr, "Frame size must be strictly positive");
+ exit(-1);
+ }
+ else if( *lev < maxlev-1 && ( *fx < xwidth || *fy < ywidth)) {
+ /* Simulate the ceil function. */
+ *xmin = (int)ceil((double)*xmin/(double)2.0);
+ *ymin = (int)ceil((double)*ymin/(double)2.0);
+ *xmax = (int)ceil((double)*xmax/(double)2.0);
+ *ymax = (int)ceil((double)*ymax/(double)2.0);
+
+ (*lev) ++;
+ find_level ( maxlev, lev, fx, fy, xmin, ymin, xmax, ymax);
+ } else {
+ *fx = xwidth;
+ *fy = ywidth;
+ }
+}
+
+int comp_decomplev( int fw, int fh, int Xsiz, int Ysiz)
+{
+ int level;
+ int xmin, xmax, ymin, ymax;
+
+ level = 0;
+ xmin = ymin = 0;
+ xmax = Xsiz;
+ ymax = Ysiz;
+
+ find_level( 1000, &level, &fw, &fh, &xmin, &ymin, &xmax, &ymax);
+
+ assert( level >= 0 );
+ return level;
+}
+
+void print_imgreg( imgreg_param_t imgreg)
+{
+#ifndef SERVER
+ fprintf( logstream, "codestream image region:\n");
+ fprintf( logstream, "\t fsiz: %d, %d\n", imgreg.fx, imgreg.fy);
+ fprintf( logstream, "\t roff: %d, %d\n", imgreg.ox, imgreg.oy);
+ fprintf( logstream, "\t rsiz: %d, %d\n", imgreg.sx, imgreg.sy);
+ fprintf( logstream, "\t level: %d\n", imgreg.level);
+#else
+ (void)imgreg;
+#endif
+}
diff --git a/src/lib/openjpip/imgreg_manager.h b/src/lib/openjpip/imgreg_manager.h
new file mode 100644
index 00000000..7967120b
--- /dev/null
+++ b/src/lib/openjpip/imgreg_manager.h
@@ -0,0 +1,101 @@
+/*
+ * $Id: imgreg_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 IMGREG_MANAGER_H_
+# define IMGREG_MANAGER_H_
+
+/** image region parameters */
+typedef struct imgreg_param{
+ int xosiz, yosiz; /** offset from the origin of the reference grid
+ at the decomposition level */
+ int fx, fy; /** frame size (fsiz) */
+ int ox, oy; /** offset (roff) */
+ int sx, sy; /** region size (rsiz) */
+ int level; /** decomposition level */
+} imgreg_param_t;
+
+
+/**
+ * map view-window requests to codestream image resolutions and regions
+ *
+ * @param[in] fx,fy frame size
+ * @param[in] rx,ry offset of region
+ * @param[in] rw,rh size of region
+ * @param[in] XOsiz,YOsiz offset from the origin of the reference grid to the left side of the image area
+ * @param[in] Xsiz,Ysiz size of the reference grid
+ * @param[in] numOfreslev number of resolution levels
+ * @return structure of image region parameters
+ */
+imgreg_param_t map_viewin2imgreg( const int fx, const int fy,
+ const int rx, const int ry,
+ const int rw, const int rh,
+ const int XOsiz, const int YOsiz,
+ const int Xsiz, const int Ysiz,
+ const int numOfreslev);
+
+
+/**
+ * find deconposition level and its resolution size
+ * C.4.1 Mapping view-window requests to codestream image resolution
+ * and regions
+ * Note: only round-down implemented
+ *
+ * @param[in] maxlev maximum decomposition level
+ * @param[in/out] lev decomposition level pointer
+ * @param[in/out] fx horizontal frame size pointer
+ * @param[in/out] fy vertical frame size pointer
+ * @param[in/out] xmin horizontal image offset pointer
+ * @param[in/out] ymin vertical image offset pointer
+ * @param[in/out] xmax horizontal image size pointer
+ * @param[in/out] ymax vertical image size pointer
+ */
+void find_level( int maxlev, int *lev, int *fx, int *fy, int *xmin, int *ymin, int *xmax, int *ymax);
+
+/**
+ * compute decomposition level (only to get the level
+ * use find_level for all parameters
+ *
+ * @param[in] fx horizontal frame size
+ * @param[in] fy vertical frame size
+ * @param[in] Xsiz image width
+ * @param[in] Ysiz image height
+ * @return decomposition level
+ */
+int comp_decomplev( int fw, int fh, int Xsiz, int Ysiz);
+
+/**
+ * print image region parameters
+ *
+ * @param[in] imgreg image region structure of parameters
+ */
+void print_imgreg( imgreg_param_t imgreg);
+
+
+#endif /* !IMGREG_MANAGER_H_ */
diff --git a/src/lib/openjpip/imgsock_manager.c b/src/lib/openjpip/imgsock_manager.c
new file mode 100644
index 00000000..612cb378
--- /dev/null
+++ b/src/lib/openjpip/imgsock_manager.c
@@ -0,0 +1,209 @@
+/*
+ * $Id: imgsock_manager.c 54 2011-05-10 13:22:47Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "imgsock_manager.h"
+#if _WIN32
+#define strncasecmp _strnicmp
+#endif
+
+msgtype_t identify_clientmsg( SOCKET connected_socket)
+{
+ OPJ_SIZE_T receive_size;
+ char buf[BUF_LEN];
+ static const char *magicid[] = { "JPIP-stream", "PNM request", "XML request",
+ "TID request", "CID request", "CID destroy", "SIZ request", "JP2 save",
+ "QUIT"};
+ int i;
+
+ receive_size = receive_line( connected_socket, buf);
+
+ if( receive_size == 0){
+ fprintf( stderr, "Error to receive the header of client message\n");
+ return MSGERROR;
+ }
+
+ for( i=0; i<NUM_OF_MSGTYPES; i++){
+ if( strncasecmp( magicid[i], buf, strlen(magicid[i])) == 0){
+ fprintf( stderr, "%s\n", magicid[i]);
+ return i;
+ }
+ }
+
+ fprintf( stderr, "Cannot identify client message type %s\n", buf);
+ return MSGERROR;
+}
+
+Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, OPJ_SIZE_T *streamlen)
+{
+ char buf[BUF_LEN];
+ const char versionstring[] = "version 1.2";
+ int idatalen;
+ OPJ_SIZE_T linelen, datalen;
+ Byte_t *jpipstream;
+
+ *target = *cid = *tid = NULL;
+
+ if((linelen = receive_line( connected_socket, buf)) == 0)
+ return NULL;
+ if( strncmp( versionstring, buf, strlen(versionstring))!=0){
+ fprintf( stderr, "Wrong format\n");
+ return NULL;
+ }
+
+ if((linelen = receive_line( connected_socket, buf)) == 0)
+ return NULL;
+
+ if( strstr( buf, "jp2")){
+ /* register cid option*/
+ *target = strdup( buf);
+
+ if((linelen = receive_line( connected_socket, buf)) == 0)
+ return NULL;
+ if( strcmp( buf, "0") != 0)
+ *tid = strdup( buf);
+
+ if((linelen = receive_line( connected_socket, buf)) == 0)
+ return NULL;
+ if( strcmp( buf, "0") != 0)
+ *cid = strdup( buf);
+
+ if((linelen = receive_line( connected_socket, buf)) == 0)
+ return NULL;
+ }
+
+ idatalen = atoi( buf);
+ if( idatalen < 0 )
+ {
+ fprintf( stderr, "Receive Data: %d Bytes\n", idatalen);
+ return NULL;
+ }
+ datalen = (OPJ_SIZE_T)idatalen;
+ fprintf( stdout, "Receive Data: %lu Bytes\n", datalen);
+
+ jpipstream = receive_stream( connected_socket, datalen);
+
+ /* check EOR*/
+ if( jpipstream[datalen-3] == 0x00 && ( jpipstream[datalen-2] == 0x01 || jpipstream[datalen-2] == 0x02))
+ *streamlen = datalen -3;
+ else
+ *streamlen = datalen;
+
+ return jpipstream;
+}
+
+void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, OPJ_SIZE_T length)
+{
+ Byte_t header[5];
+
+ header[0] = 'X';
+ header[1] = 'M';
+ header[2] = 'L';
+ header[3] = (Byte_t)((length >> 8) & 0xff);
+ header[4] = (Byte_t)(length & 0xff);
+
+ send_stream( connected_socket, header, 5);
+ send_stream( connected_socket, xmlstream, length);
+}
+
+void send_IDstream( SOCKET connected_socket, const char *id, OPJ_SIZE_T idlen, const char *label);
+
+void send_CIDstream( SOCKET connected_socket, const char *cid, OPJ_SIZE_T cidlen)
+{
+ send_IDstream( connected_socket, cid, cidlen, "CID");
+}
+
+void send_TIDstream( SOCKET connected_socket, const char *tid, OPJ_SIZE_T tidlen)
+{
+ send_IDstream( connected_socket, tid, tidlen, "TID");
+}
+
+void send_IDstream( SOCKET connected_socket, const char *id, OPJ_SIZE_T idlen, const char *label)
+{
+ char header[4];
+
+ header[0] = label[0];
+ header[1] = label[1];
+ header[2] = label[2];
+ header[3] = (char)(idlen & 0xff);
+
+ send_stream( connected_socket, header, 4);
+ send_stream( connected_socket, id, idlen);
+}
+
+void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int width, unsigned int height, unsigned int numofcomp, Byte_t maxval)
+{
+ OPJ_SIZE_T pnmlen = 0;
+ Byte_t header[7];
+
+ pnmlen = width*height*numofcomp;
+
+ header[0] = 'P';
+ header[1] = numofcomp==3 ? 6:5;
+ header[2] = (width >> 8) & 0xff;
+ header[3] = width & 0xff;
+ header[4] = (height >> 8) & 0xff;
+ header[5] = height & 0xff;
+ header[6] = maxval;
+
+ send_stream( connected_socket, header, 7);
+ send_stream( connected_socket, pnmstream, pnmlen);
+}
+
+void send_SIZstream( SOCKET connected_socket, unsigned int width, unsigned int height)
+{
+ Byte_t responce[9];
+
+ responce[0] = 'S';
+ responce[1] = 'I';
+ responce[2] = 'Z';
+ responce[3] = (width >> 16) & 0xff;
+ responce[4] = (width >> 8) & 0xff;
+ responce[5] = width & 0xff;
+ responce[6] = (height >> 16) & 0xff;
+ responce[7] = (height >> 8) & 0xff;
+ responce[8] = height & 0xff;
+
+ send_stream( connected_socket, responce, 9);
+}
+
+void response_signal( SOCKET connected_socket, bool succeed)
+{
+ Byte_t code;
+
+ if( succeed)
+ code = 1;
+ else
+ code = 0;
+
+ send_stream( connected_socket, &code, 1);
+}
diff --git a/src/lib/openjpip/imgsock_manager.h b/src/lib/openjpip/imgsock_manager.h
new file mode 100644
index 00000000..044bdc53
--- /dev/null
+++ b/src/lib/openjpip/imgsock_manager.h
@@ -0,0 +1,174 @@
+/*
+ * $Id: imgsock_manager.h 54 2011-05-10 13:22:47Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 IMGSOCK_MANAGER_H_
+# define IMGSOCK_MANAGER_H_
+
+#include "bool.h"
+#include "byte_manager.h"
+#include "sock_manager.h"
+
+#define NUM_OF_MSGTYPES 9
+typedef enum eMSGTYPE{ JPIPSTREAM, PNMREQ, XMLREQ, TIDREQ, CIDREQ, CIDDST, SIZREQ, JP2SAVE, QUIT, MSGERROR} msgtype_t;
+
+/**
+ * indeitify client message type
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @return message type
+ */
+msgtype_t identify_clientmsg( SOCKET connected_socket);
+
+/**
+ * receive a JPT- JPP- stream from client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [out] target address of received target file name string pointer ( malloced, if not received, NULL)
+ * @param [out] tid address of received target identifier string pointer ( malloced, if not received, null string)
+ * @param [out] cid address of received channel identifier string pointer ( malloced, if not received, null string)
+ * @param [out] streamlen length of the received codestream
+ * @return JPT- JPP- codestream
+ */
+Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, OPJ_SIZE_T *streamlen);
+
+/**
+ * send PGM/PPM image stream to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] pnmstream PGM/PPM image codestream
+ * @param [in] width width of the PGM/PPM image (different from the original image)
+ * @param [in] height height of the PGM/PPM image
+ * @param [in] numofcomp number of components of the image
+ * @param [in] maxval maximum value of the image (only 255 supported)
+ */
+void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int width, unsigned int height, unsigned int numofcomp, Byte_t maxval);
+
+/**
+ * send XML data stream to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] xmlstream xml data stream
+ * @param [in] length legnth of the xml data stream
+ */
+void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, OPJ_SIZE_T length);
+
+/**
+ * send TID data stream to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] tid tid string
+ * @param [in] tidlen legnth of the tid string
+ */
+void send_TIDstream( SOCKET connected_socket, const char *tid, OPJ_SIZE_T tidlen);
+
+/**
+ * send CID data stream to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] cid cid string
+ * @param [in] cidlen legnth of the cid string
+ */
+void send_CIDstream( SOCKET connected_socket, const char *cid, OPJ_SIZE_T cidlen);
+
+/**
+ * send SIZ data stream to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] width original width of the image
+ * @param [in] height original height of the image
+ */
+void send_SIZstream( SOCKET connected_socket, unsigned int width, unsigned int height);
+
+/**
+ * send response signal to the client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] succeed whether if the requested process succeeded
+ */
+void response_signal( SOCKET connected_socket, bool succeed);
+
+#endif /* !IMGSOCK_MANAGER_H_ */
+
+/*! \file
+ * PROTOCOL specification to communicate with opj_dec_server
+ *
+ *\section sec1 JPIP-stream
+ * Cache JPT- JPP- stream in server
+ *
+ * client -> server: JPIP-stream\\n version 1.1\\n (optional for cid registration: targetnamestring\\n tidstring\\n cidstring\\n) bytelengthvalue\\n data \n
+ * server -> client: 1 or 0 (of 1Byte response signal)
+ *
+ *\section sec2 PNM request
+ * Get decoded PGM/PPM image
+ *
+ * client -> server: PNM request\\n [cid/tid]string\\n fw\\n fh\\n \n
+ * server -> client: P6 or P5 (2Byte) width (2Byte Big endian) height (2Byte Big endian) maxval (1Byte) data
+ *
+ *\section sec3 XML request
+ * Get XML data
+ *
+ * client -> server: XML request\\n \n
+ * server -> client: XML (3Byte) length (2Byte Big endian) data
+ *
+ *\section sec4 TID request
+ * Get target ID of target image
+ *
+ * client -> server: TID request\\n targetname\\n \n
+ * server -> client: TID (3Byte) length (1Byte) tiddata
+ *
+ *\section sec5 CID request
+ * Get Channel ID of identical target image
+ *
+ * client -> server: CID request\\n targetname\\n \n
+ * server -> client: CID (3Byte) length (1Byte) ciddata
+ *
+ *\section sec6 CID destroy
+ * Close Channel ID
+ *
+ * client -> server: CID destroy\\n ciddata \n
+ * server -> client: 1 or 0 (of 1Byte response signal)
+ *
+ *\section sec7 SIZ request
+ * Get original size of image
+ *
+ * client -> server: SIZ request\\n tidstring\\n cidstring\\n \n
+ * server -> client: SIZ (3Byte) width (3Byte Big endian) height (3Byte Big endian)
+ *
+ *\section sec8 JP2 save
+ * Save in JP2 file format
+ *
+ * client -> server: JP2 save\\n ciddata \n
+ * server -> client: 1 or 0 (of 1Byte response signal)
+ *
+ *\section sec9 QUIT
+ * Quit the opj_dec_server program
+ *
+ * client -> server: quit or QUIT
+ */
diff --git a/src/lib/openjpip/index_manager.c b/src/lib/openjpip/index_manager.c
new file mode 100644
index 00000000..6f8357e9
--- /dev/null
+++ b/src/lib/openjpip/index_manager.c
@@ -0,0 +1,732 @@
+/*
+ * $Id: index_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "bool.h"
+#include "opj_inttypes.h"
+#include "index_manager.h"
+#include "box_manager.h"
+#include "manfbox_manager.h"
+#include "mhixbox_manager.h"
+#include "codestream_manager.h"
+#include "marker_manager.h"
+#include "faixbox_manager.h"
+#include "boxheader_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+/**
+ * chekc JP2 box indexing
+ *
+ * @param[in] toplev_boxlist top level box list
+ * @return if correct (true) or wrong (false)
+ */
+bool check_JP2boxidx( boxlist_param_t *toplev_boxlist);
+
+/**
+ * set code index parameters (parse cidx box)
+ * Annex I
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[out] codeidx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_cidxdata( box_param_t *cidx_box, index_param_t *codeidx);
+
+index_param_t * parse_jp2file( int fd)
+{
+ index_param_t *jp2idx;
+ box_param_t *cidx;
+ metadatalist_param_t *metadatalist;
+ boxlist_param_t *toplev_boxlist;
+ Byte8_t filesize;
+
+ if( !(filesize = (Byte8_t)get_filesize( fd)))
+ return NULL;
+
+ if( !(toplev_boxlist = get_boxstructure( fd, 0, filesize))){
+ fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n");
+ return NULL;
+ }
+
+ if( !check_JP2boxidx( toplev_boxlist)){
+ fprintf( FCGI_stderr, "Index format not supported\n");
+ delete_boxlist( &toplev_boxlist);
+ return NULL;
+ }
+
+ if( !(cidx = search_box( "cidx", toplev_boxlist))){
+ fprintf( FCGI_stderr, "Box cidx not found\n");
+ delete_boxlist( &toplev_boxlist);
+ return NULL;
+ }
+
+ jp2idx = (index_param_t *)malloc( sizeof(index_param_t));
+
+ if( !set_cidxdata( cidx, jp2idx)){
+ fprintf( FCGI_stderr, "Error: Not correctl format in cidx box\n");
+ free(jp2idx);
+ delete_boxlist( &toplev_boxlist);
+ return NULL;
+ }
+ delete_boxlist( &toplev_boxlist);
+
+ metadatalist = const_metadatalist( fd);
+ jp2idx->metadatalist = metadatalist;
+
+#ifndef SERVER
+ fprintf( logstream, "local log: code index created\n");
+#endif
+
+ return jp2idx;
+}
+
+void print_index( index_param_t index)
+{
+ int i;
+
+ fprintf( logstream, "index info:\n");
+ fprintf( logstream, "\tCodestream Offset: %#" PRIx64 "\n", index.offset);
+ fprintf( logstream, "\t Length: %#" PRIx64 "\n", index.length);
+ fprintf( logstream, "\tMain header Length: %#" PRIx64 "\n", index.mhead_length);
+
+ print_SIZ( index.SIZ);
+ print_COD( index.COD);
+
+ fprintf( logstream, "Tile part information: \n");
+ print_faixbox( index.tilepart);
+
+ fprintf( logstream, "Tile header information: \n");
+ for( i=0; i<(int)(index.SIZ.XTnum*index.SIZ.YTnum);i++)
+ print_mhixbox( index.tileheader[i]);
+
+ fprintf( logstream, "Precinct packet information: \n");
+ for( i=0; i<index.SIZ.Csiz; i++){
+ fprintf( logstream, "Component %d\n", i);
+ print_faixbox( index.precpacket[i]);
+ }
+
+ print_allmetadata( index.metadatalist);
+}
+
+void print_SIZ( SIZmarker_param_t SIZ)
+{
+ int i;
+
+ fprintf( logstream, "\tImage and Tile SIZ parameters\n");
+ fprintf( logstream, "\t Rsiz: %#x\n", SIZ.Rsiz);
+ fprintf( logstream, "\t Xsiz, Ysiz: (%d,%d) = (%#x, %#x)\n", SIZ.Xsiz, SIZ.Ysiz, SIZ.Xsiz, SIZ.Ysiz);
+ fprintf( logstream, "\t XOsiz, YOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XOsiz, SIZ.YOsiz, SIZ.XOsiz, SIZ.YOsiz);
+ fprintf( logstream, "\t XTsiz, YTsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTsiz, SIZ.YTsiz, SIZ.XTsiz, SIZ.YTsiz);
+ fprintf( logstream, "\t XTOsiz, YTOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTOsiz, SIZ.YTOsiz, SIZ.XTOsiz, SIZ.YTOsiz);
+ fprintf( logstream, "\t XTnum, YTnum: (%d,%d)\n", SIZ.XTnum, SIZ.YTnum);
+ fprintf( logstream, "\t Num of Components: %d\n", SIZ.Csiz);
+
+ for( i=0; i<SIZ.Csiz; i++)
+ fprintf( logstream, "\t[%d] (Ssiz, XRsiz, YRsiz): (%d, %d, %d) = (%#x, %#x, %#x)\n", i, SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i], SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i]);
+}
+
+void print_COD( CODmarker_param_t COD)
+{
+ int i;
+
+ fprintf( logstream, "\tCoding style default COD parameters\n");
+ fprintf( logstream, "\t Progression order: %d [ LRCP=0, RLCP=1, RPCL=2, PCRL=3, CPRL=4]\n", COD.prog_order);
+ fprintf( logstream, "\t Num of layers: %d\n", COD.numOflayers);
+ fprintf( logstream, "\t Decomposition lvl: %d\n", COD.numOfdecomp);
+
+ for( i=0; i<=((COD.Scod & 0x01) ? COD.numOfdecomp:0); i++){
+ fprintf( logstream, "\t [%d] XPsiz, YPsiz: (%d,%d) = (%#x, %#x)\n",i, COD.XPsiz[i], COD.YPsiz[i], COD.XPsiz[i], COD.YPsiz[i]);
+ }
+}
+
+void delete_index( index_param_t **index)
+{
+ int i;
+
+ delete_metadatalist( &((*index)->metadatalist));
+
+ delete_COD( (*index)->COD);
+
+ delete_faixbox( &((*index)->tilepart));
+
+ for( i=0; i< (int)((*index)->SIZ.XTnum*(*index)->SIZ.YTnum);i++)
+ delete_mhixbox( &((*index)->tileheader[i]));
+ free( (*index)->tileheader);
+
+ for( i=0; i<(*index)->SIZ.Csiz; i++)
+ delete_faixbox( &((*index)->precpacket[i]));
+ free( (*index)->precpacket);
+
+ free(*index);
+}
+
+void delete_COD( CODmarker_param_t COD)
+{
+ if( COD.XPsiz) free( COD.XPsiz);
+ if( COD.YPsiz) free( COD.YPsiz);
+}
+
+bool check_JP2boxidx( boxlist_param_t *toplev_boxlist)
+{
+ box_param_t *iptr, *fidx, *prxy;
+ box_param_t *cidx, *jp2c;
+ Byte8_t off;
+ Byte8_t len;
+ int pos;
+ Byte8_t ooff;
+ boxheader_param_t *obh;
+ Byte_t ni;
+ Byte8_t ioff;
+ boxheader_param_t *ibh;
+
+ iptr = search_box( "iptr", toplev_boxlist);
+ fidx = search_box( "fidx", toplev_boxlist);
+ cidx = search_box( "cidx", toplev_boxlist);
+ jp2c = search_box( "jp2c", toplev_boxlist);
+ prxy = gene_childboxbyType( fidx, 0, "prxy");
+
+ off = fetch_DBox8bytebigendian( iptr, 0);
+ if( off != (Byte8_t)fidx->offset)
+ fprintf( FCGI_stderr, "Reference File Index box offset in Index Finder box not correct\n");
+
+ len = fetch_DBox8bytebigendian( iptr, 8);
+ if( len != fidx->length)
+ fprintf( FCGI_stderr, "Reference File Index box length in Index Finder box not correct\n");
+
+ pos = 0;
+ ooff = fetch_DBox8bytebigendian( prxy, pos);
+ if( ooff != (Byte8_t)jp2c->offset)
+ fprintf( FCGI_stderr, "Reference jp2c offset in prxy box not correct\n");
+ pos += 8;
+
+ obh = gene_childboxheader( prxy, pos);
+ if( obh->length != jp2c->length || strncmp( obh->type, "jp2c",4)!=0)
+ fprintf( FCGI_stderr, "Reference jp2c header in prxy box not correct\n");
+ pos += obh->headlen;
+ free(obh);
+
+ ni = fetch_DBox1byte( prxy, pos);
+ if( ni != 1){
+ fprintf( FCGI_stderr, "Multiple indexes not supported\n");
+ return false;
+ }
+ pos += 1;
+
+ ioff = fetch_DBox8bytebigendian( prxy, pos);
+ if( ioff != (Byte8_t)cidx->offset)
+ fprintf( FCGI_stderr, "Reference cidx offset in prxy box not correct\n");
+ pos += 8;
+
+ ibh = gene_childboxheader( prxy, pos);
+ if( ibh->length != cidx->length || strncmp( ibh->type, "cidx",4)!=0)
+ fprintf( FCGI_stderr, "Reference cidx header in prxy box not correct\n");
+ pos += ibh->headlen;
+ free(ibh);
+
+ free(prxy);
+
+ return true;
+}
+
+/**
+ * set code index parameters from cptr box
+ * I.3.2.2 Codestream Finder box
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[out] jp2idx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx);
+
+/**
+ * set code index parameters from mhix box for main header
+ * I.3.2.4.3 Header Index Table box
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[in] codestream codestream parameters
+ * @param[out] jp2idx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx);
+
+/**
+ * set code index parameters from tpix box
+ * I.3.2.4.4 Tile-part Index Table box
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[out] jp2idx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx);
+
+/**
+ * set code index parameters from thix box
+ * I.3.2.4.5 Tile Header Index Table box
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[out] jp2idx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx);
+
+/**
+ * set code index parameters from ppix box
+ * I.3.2.4.6 Precinct Packet Index Table box
+ *
+ * @param[in] cidx_box pointer to the reference cidx_box
+ * @param[out] jp2idx pointer to index parameters
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx);
+
+bool set_cidxdata( box_param_t *cidx_box, index_param_t *jp2idx)
+{
+ box_param_t *manf_box;
+ manfbox_param_t *manf;
+ codestream_param_t codestream;
+
+ set_cptrdata( cidx_box, jp2idx);
+
+ codestream = set_codestream( cidx_box->fd, jp2idx->offset, jp2idx->length);
+
+ manf_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "manf");
+ manf = gene_manfbox( manf_box);
+
+ if( !search_boxheader( "mhix", manf)){
+ fprintf( FCGI_stderr, "Error: mhix box not present in manfbox\n");
+ free(jp2idx);
+ return false;
+ }
+ set_mainmhixdata( cidx_box, codestream, jp2idx);
+
+ if( !search_boxheader( "tpix", manf)){
+ fprintf( FCGI_stderr, "Error: tpix box not present in manfbox\n");
+ free(jp2idx);
+ return false;
+ }
+ set_tpixdata( cidx_box, jp2idx);
+
+ if( !search_boxheader( "thix", manf)){
+ fprintf( FCGI_stderr, "Error: thix box not present in manfbox\n");
+ free(jp2idx);
+ return false;
+ }
+ set_thixdata( cidx_box, jp2idx);
+
+ if( !search_boxheader( "ppix", manf)){
+ fprintf( FCGI_stderr, "Error: ppix box not present in manfbox\n");
+ free(jp2idx);
+ return false;
+ }
+ set_ppixdata( cidx_box, jp2idx);
+
+ delete_manfbox( &manf);
+ free( manf_box);
+
+ return true;
+}
+
+bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx)
+{
+ box_param_t *box; /**< cptr box*/
+ Byte2_t dr, cont;
+
+ if( !(box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "cptr")))
+ return false;
+
+ /* DR: Data Reference. */
+ /* If 0, the codestream or its Fragment Table box exists in the current file*/
+ if(( dr = fetch_DBox2bytebigendian( box, 0))){
+ fprintf( FCGI_stderr, "Error: Codestream not present in current file\n");
+ free( box);
+ return false;
+ }
+
+ /* CONT: Container Type*/
+ /* If 0, the entire codestream appears as a contiguous range of*/
+ /* bytes within its file or resource.*/
+ if(( cont = fetch_DBox2bytebigendian( box, 2))){
+ fprintf( FCGI_stderr, "Error: Can't cope with fragmented codestreams yet\n");
+ free( box);
+ return false;
+ }
+
+ jp2idx->offset = (OPJ_OFF_T)fetch_DBox8bytebigendian( box, 4);
+ jp2idx->length = fetch_DBox8bytebigendian( box, 12);
+
+ free( box);
+
+ return true;
+}
+
+
+/**
+ * set SIZ marker information
+ * A.5 Fixed information marker segment
+ * A.5.1 Image and tile size (SIZ)
+ *
+ * @param[in] sizmkidx pointer to SIZ marker index in mhix box
+ * @param[in] codestream codestream parameters
+ * @param[out] SIZ SIZ marker parameters pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ);
+
+/**
+ * set code index parameters from COD marker in codestream
+ * A.6 Functional marker segments
+ * A.6.1 Coding style default (COD)
+ *
+ * @param[in] codmkidx pointer to COD marker index in mhix box
+ * @param[in] codestream codestream parameters
+ * @param[out] COD COD marker parameters pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD);
+
+bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx)
+{
+ box_param_t *mhix_box;
+ mhixbox_param_t *mhix;
+ markeridx_param_t *sizmkidx;
+ markeridx_param_t *codmkidx;
+
+ if( !(mhix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "mhix")))
+ return false;
+
+ jp2idx->mhead_length = fetch_DBox8bytebigendian( mhix_box, 0);
+
+ mhix = gene_mhixbox( mhix_box);
+ free( mhix_box);
+
+ sizmkidx = search_markeridx( 0xff51, mhix);
+ set_SIZmkrdata( sizmkidx, codestream, &(jp2idx->SIZ));
+
+ codmkidx = search_markeridx( 0xff52, mhix);
+ set_CODmkrdata( codmkidx, codestream, &(jp2idx->COD));
+
+ delete_mhixbox( &mhix);
+
+ return true;
+}
+
+bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx)
+{
+ box_param_t *tpix_box; /**< tpix box*/
+ box_param_t *faix_box; /**< faix box*/
+
+ if( !(tpix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "tpix"))){
+ fprintf( FCGI_stderr, "Error: tpix box not present in cidx box\n");
+ return false;
+ }
+
+ if( !(faix_box = gene_boxbyType( tpix_box->fd, get_DBoxoff( tpix_box), get_DBoxlen( tpix_box), "faix"))){
+ fprintf( FCGI_stderr, "Error: faix box not present in tpix box\n");
+ return false;
+ }
+
+ jp2idx->tilepart = gene_faixbox( faix_box);
+
+ free( tpix_box);
+ free( faix_box);
+
+ return true;
+}
+
+bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx)
+{
+ box_param_t *thix_box, *manf_box, *mhix_box;
+ manfbox_param_t *manf;
+ boxheader_param_t *ptr;
+ mhixbox_param_t *mhix;
+ Byte8_t pos;
+ OPJ_OFF_T mhixseqoff;
+ Byte2_t tile_no;
+
+ if( !(thix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "thix"))){
+ fprintf( FCGI_stderr, "Error: thix box not present in cidx box\n");
+ return false;
+ }
+
+ if( !(manf_box = gene_boxbyType( thix_box->fd, get_DBoxoff( thix_box), get_DBoxlen( thix_box), "manf"))){
+ fprintf( FCGI_stderr, "Error: manf box not present in thix box\n");
+ free( thix_box);
+ return false;
+ }
+
+ manf = gene_manfbox( manf_box);
+ ptr = manf->first;
+ mhixseqoff = manf_box->offset+(OPJ_OFF_T)manf_box->length;
+ pos = 0;
+ tile_no = 0;
+ jp2idx->tileheader = (mhixbox_param_t **)malloc( jp2idx->SIZ.XTnum*jp2idx->SIZ.YTnum*sizeof(mhixbox_param_t *));
+
+ while( ptr){
+ if( !(mhix_box = gene_boxbyType( thix_box->fd, mhixseqoff+(OPJ_OFF_T)pos, get_DBoxlen( thix_box)-manf_box->length-pos, "mhix"))){
+ fprintf( FCGI_stderr, "Error: mhix box not present in thix box\n");
+ delete_manfbox( &manf);
+ free( manf_box);
+ free( thix_box);
+ return false;
+ }
+ mhix = gene_mhixbox( mhix_box);
+
+ pos += mhix_box->length;
+ ptr = ptr->next;
+
+ free( mhix_box);
+ jp2idx->tileheader[tile_no++] = mhix;
+ }
+
+ delete_manfbox( &manf);
+ free( manf_box);
+ free( thix_box);
+
+ return true;
+}
+
+bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx)
+{
+ box_param_t *ppix_box, *faix_box, *manf_box;
+ manfbox_param_t *manf; /**< manf*/
+ boxheader_param_t *bh; /**< box headers*/
+ faixbox_param_t *faix; /**< faix*/
+ OPJ_OFF_T inbox_offset;
+ int comp_idx;
+
+ if( !(ppix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "ppix"))){
+ fprintf( FCGI_stderr, "Error: ppix box not present in cidx box\n");
+ return false;
+ }
+
+ inbox_offset = get_DBoxoff( ppix_box);
+ if( !(manf_box = gene_boxbyType( ppix_box->fd, inbox_offset, get_DBoxlen( ppix_box), "manf"))){
+ fprintf( FCGI_stderr, "Error: manf box not present in ppix box\n");
+ free( ppix_box);
+ return false;
+ }
+
+ free( ppix_box);
+
+ manf = gene_manfbox( manf_box);
+ bh = search_boxheader( "faix", manf);
+ inbox_offset = manf_box->offset + (OPJ_OFF_T)manf_box->length;
+
+ free( manf_box);
+
+ jp2idx->precpacket = (faixbox_param_t **)malloc( jp2idx->SIZ.Csiz*sizeof(faixbox_param_t *));
+
+ for( comp_idx=0; bh!=NULL; bh=bh->next, comp_idx++){
+ if( jp2idx->SIZ.Csiz <= comp_idx ){
+ fprintf( FCGI_stderr, "Error: num of faix boxes is not identical to num of components in ppix box\n");
+ return false;
+ }
+
+ if( !(faix_box = gene_boxbyOffset( cidx_box->fd, inbox_offset))){
+ fprintf( FCGI_stderr, "Error: faix box not present in ppix box\n");
+ return false;
+ }
+
+ faix = gene_faixbox( faix_box);
+ jp2idx->precpacket[comp_idx] = faix;
+
+ inbox_offset = faix_box->offset + (OPJ_OFF_T)faix_box->length;
+ free( faix_box);
+ }
+
+ delete_manfbox( &manf);
+
+ return true;
+}
+
+bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ)
+{
+ marker_param_t sizmkr;
+ int i;
+
+ sizmkr = set_marker( codestream, sizmkidx->code, sizmkidx->offset, sizmkidx->length);
+
+ SIZ->Lsiz = fetch_marker2bytebigendian( sizmkr, 0);
+
+ if( sizmkidx->length != SIZ->Lsiz){
+ fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", sizmkidx->code);
+ return false;
+ }
+
+ SIZ->Rsiz = fetch_marker2bytebigendian( sizmkr, 2);
+ SIZ->Xsiz = fetch_marker4bytebigendian( sizmkr, 4);
+ SIZ->Ysiz = fetch_marker4bytebigendian( sizmkr, 8);
+ SIZ->XOsiz = fetch_marker4bytebigendian( sizmkr, 12);
+ SIZ->YOsiz = fetch_marker4bytebigendian( sizmkr, 16);
+ SIZ->XTsiz = fetch_marker4bytebigendian( sizmkr, 20);
+ SIZ->YTsiz = fetch_marker4bytebigendian( sizmkr, 24);
+ SIZ->XTOsiz = fetch_marker4bytebigendian( sizmkr, 28);
+ SIZ->YTOsiz = fetch_marker4bytebigendian( sizmkr, 32);
+ SIZ->Csiz = fetch_marker2bytebigendian( sizmkr, 36);
+
+ SIZ->XTnum = ( SIZ->Xsiz-SIZ->XTOsiz+SIZ->XTsiz-1)/SIZ->XTsiz;
+ SIZ->YTnum = ( SIZ->Ysiz-SIZ->YTOsiz+SIZ->YTsiz-1)/SIZ->YTsiz;
+
+ for( i=0; i<(int)SIZ->Csiz; i++){
+ SIZ->Ssiz[i] = fetch_marker1byte( sizmkr, 38+i*3);
+ SIZ->XRsiz[i] = fetch_marker1byte( sizmkr, 39+i*3);
+ SIZ->YRsiz[i] = fetch_marker1byte( sizmkr, 40+i*3);
+ }
+ return true;
+}
+
+bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD)
+{
+ marker_param_t codmkr;
+ int i;
+
+ codmkr = set_marker( codestream, codmkidx->code, codmkidx->offset, codmkidx->length);
+
+ COD->Lcod = fetch_marker2bytebigendian( codmkr, 0);
+
+ if( codmkidx->length != COD->Lcod){
+ fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", codmkidx->code);
+ return false;
+ }
+
+ COD->Scod = fetch_marker1byte( codmkr, 2);
+ COD->prog_order = fetch_marker1byte( codmkr, 3);
+ COD->numOflayers = fetch_marker2bytebigendian( codmkr, 4);
+ COD->numOfdecomp = fetch_marker1byte( codmkr, 7);
+
+ if(COD->Scod & 0x01){
+ COD->XPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD->numOfdecomp+1)*sizeof(Byte4_t));
+ COD->YPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD->numOfdecomp+1)*sizeof(Byte4_t));
+
+ for( i=0; i<=COD->numOfdecomp; i++){
+ /*precinct size*/
+ COD->XPsiz[i] = (Byte2_t)pow( 2, fetch_marker1byte( codmkr, 12+i) & 0x0F);
+ COD->YPsiz[i] = (Byte2_t)pow( 2,(fetch_marker1byte( codmkr, 12+i) & 0xF0) >> 4);
+ }
+ }
+ else{
+ COD->XPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
+ COD->YPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
+
+ COD->XPsiz[0] = COD->YPsiz[0] = pow(2,15);
+ }
+ return true;
+}
+
+
+/* very very generic name see NOMINMAX */
+#ifdef min
+#undef min
+#endif
+#ifdef max
+#undef max
+#endif
+Byte4_t max( Byte4_t n1, Byte4_t n2);
+Byte4_t min( Byte4_t n1, Byte4_t n2);
+
+range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level);
+
+range_param_t get_tile_Xrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
+{
+ return get_tile_range( SIZ.XOsiz, SIZ.Xsiz, SIZ.XTOsiz, SIZ.XTsiz, tile_id%SIZ.XTnum, level);
+}
+
+range_param_t get_tile_Yrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
+{
+ return get_tile_range( SIZ.YOsiz, SIZ.Ysiz, SIZ.YTOsiz, SIZ.YTsiz, tile_id/SIZ.XTnum, level);
+}
+
+range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level)
+{
+ range_param_t range;
+ int n;
+
+ range.minvalue = max( Osiz, TOsiz+tile_XYid*Tsiz);
+ range.maxvalue = min( siz, TOsiz+(tile_XYid+1)*Tsiz);
+
+ for( n=0; n<level; n++){
+ range.minvalue = (Byte4_t)ceil(range.minvalue/2.0);
+ range.maxvalue = (Byte4_t)ceil(range.maxvalue/2.0);
+ }
+ return range;
+}
+
+Byte4_t get_tile_XSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
+{
+ range_param_t tile_Xrange;
+
+ tile_Xrange = get_tile_Xrange( SIZ, tile_id, level);
+ return tile_Xrange.maxvalue - tile_Xrange.minvalue;
+}
+
+Byte4_t get_tile_YSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level)
+{
+ range_param_t tile_Yrange;
+
+ tile_Yrange = get_tile_Yrange( SIZ, tile_id, level);
+ return tile_Yrange.maxvalue - tile_Yrange.minvalue;
+}
+
+/* TODO: what is this code doing ? will all compiler be able to optimize the following ? */
+Byte4_t max( Byte4_t n1, Byte4_t n2)
+{
+ if( n1 < n2)
+ return n2;
+ else
+ return n1;
+}
+
+Byte4_t min( Byte4_t n1, Byte4_t n2)
+{
+ if( n1 < n2)
+ return n1;
+ else
+ return n2;
+}
+
+bool isJPTfeasible( index_param_t index)
+{
+ if( 1 < get_nmax( index.tilepart))
+ return true;
+ else
+ return false;
+}
diff --git a/src/lib/openjpip/index_manager.h b/src/lib/openjpip/index_manager.h
new file mode 100644
index 00000000..c1969fac
--- /dev/null
+++ b/src/lib/openjpip/index_manager.h
@@ -0,0 +1,187 @@
+/*
+ * $Id: index_manager.h 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 INDEX_MANAGER_H_
+# define INDEX_MANAGER_H_
+
+#include "byte_manager.h"
+#include "faixbox_manager.h"
+#include "metadata_manager.h"
+#include "mhixbox_manager.h"
+#include "bool.h"
+
+/** progression order */
+typedef enum porder {
+ PROG_UNKNOWN = -1, /**< place-holder */
+ LRCP = 0, /**< layer-resolution-component-precinct order */
+ RLCP = 1, /**< resolution-layer-component-precinct order */
+ RPCL = 2, /**< resolution-precinct-component-layer order */
+ PCRL = 3, /**< precinct-component-resolution-layer order */
+ CPRL = 4 /**< component-precinct-resolution-layer order */
+} porder_t;
+
+/** A.5.1 Image and tile size (SIZ)*/
+typedef struct SIZmarker_param{
+ Byte2_t Lsiz; /**< length of marker segment excluding the marker*/
+ Byte2_t Rsiz; /**< capabilities that a decoder needs*/
+ Byte4_t Xsiz; /**< width of the reference grid*/
+ Byte4_t Ysiz; /**< height of the reference grid*/
+ Byte4_t XOsiz; /**< horizontal offset from the origin of the reference grid to the left side of the image area*/
+ Byte4_t YOsiz; /**< vertical offset from the origin of the reference grid to the top side of the image area*/
+ Byte4_t XTsiz; /**< width of one reference tile with respect to the reference grid*/
+ Byte4_t YTsiz; /**< height of one reference tile with respect to the reference grid*/
+ Byte4_t XTOsiz; /**< horizontal offset from the origin of the reference grid to the left side of the first tile*/
+ Byte4_t YTOsiz; /**< vertical offset from the origin of the reference grid to the top side of the first tile*/
+ Byte4_t XTnum; /**< number of tiles in horizontal direction*/
+ Byte4_t YTnum; /**< number of tiles in vertical direction*/
+ Byte2_t Csiz; /**< number of the components in the image*/
+ Byte_t Ssiz[3]; /**< precision (depth) in bits and sign of the component samples*/
+ Byte_t XRsiz[3]; /**< horizontal separation of a sample of component with respect to the reference grid*/
+ Byte_t YRsiz[3]; /**< vertical separation of a sample of component with respect to the reference grid*/
+} SIZmarker_param_t;
+
+/** A.6.1 Coding style default (COD)*/
+typedef struct CODmarker_param{
+ Byte2_t Lcod; /**< length of marker segment excluding the marker*/
+ Byte_t Scod; /**< Coding style for all components*/
+ porder_t prog_order; /**< progression order*/
+ Byte2_t numOflayers; /**< number of layers*/
+ Byte_t numOfdecomp; /**< number of decompositions levels*/
+ Byte4_t *XPsiz; /**< dynamic array of precinct width at successive resolution level in order*/
+ Byte4_t *YPsiz; /**< dynamic array of precinct height at successive resolution level in order*/
+} CODmarker_param_t;
+
+/** index parameters*/
+typedef struct index_param{
+ metadatalist_param_t *metadatalist; /**< metadata-bin list*/
+ OPJ_OFF_T offset; /**< codestream offset*/
+ Byte8_t length; /**< codestream length */
+ Byte8_t mhead_length; /**< main header length */
+ SIZmarker_param_t SIZ; /**< SIZ marker information*/
+ CODmarker_param_t COD; /**< COD marker information*/
+ faixbox_param_t *tilepart; /**< tile part information from tpix box*/
+ mhixbox_param_t **tileheader; /**< dynamic array of tile header information from thix box*/
+ faixbox_param_t **precpacket; /**< dynamic array of precint packet information from ppix box*/
+} index_param_t;
+
+
+/**
+ * parse JP2 file
+ * AnnexI: Indexing JPEG2000 files for JPIP
+ *
+ * @param[in] fd file descriptor of the JP2 file
+ * @return pointer to the generated structure of index parameters
+ */
+index_param_t * parse_jp2file( int fd);
+
+/**
+ * print index parameters
+ *
+ * @param[in] index index parameters
+ */
+void print_index( index_param_t index);
+
+/**
+ * print Image and Tile SIZ parameters
+ *
+ * @param[in] SIZ SIZ marker information
+ */
+void print_SIZ( SIZmarker_param_t SIZ);
+
+/**
+ * print Coding style default COD parameters
+ *
+ * @param[in] COD COD marker information
+ */
+void print_COD( CODmarker_param_t COD);
+
+/**
+ * delete index
+ *
+ * @param[in,out] index addressof the index pointer
+ */
+void delete_index( index_param_t **index);
+
+/**
+ * delete dynamic arrays in COD marker
+ *
+ * @param[in] COD COD marker information
+ */
+void delete_COD( CODmarker_param_t COD);
+
+
+/** 1-dimensional range parameters*/
+typedef struct range_param{
+ Byte4_t minvalue; /**< minimal value*/
+ Byte4_t maxvalue; /**< maximal value*/
+} range_param_t;
+
+/**
+ * get horizontal range of the tile in reference grid
+ *
+ * @param[in] SIZ SIZ marker information
+ * @param[in] tile_id tile id
+ * @param[in] level decomposition level
+ * @return structured range parameter
+ */
+range_param_t get_tile_Xrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level);
+
+/**
+ * get vertical range of the tile in reference grid
+ *
+ * @param[in] SIZ SIZ marker information
+ * @param[in] tile_id tile id
+ * @param[in] level decomposition level
+ * @return structured range parameter
+ */
+range_param_t get_tile_Yrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level);
+
+
+/**
+ * get tile wdith at the decomposition level
+ *
+ * @param[in] SIZ SIZ marker information
+ * @param[in] tile_id tile id
+ * @param[in] level decomposition level
+ * @return tile width
+ */
+Byte4_t get_tile_XSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level);
+Byte4_t get_tile_YSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level);
+
+
+/**
+ * answers if the target is feasible to JPT-stream
+ *
+ * @param[in] index index parameters
+ * @return true if JPT-stream is feasible
+ */
+bool isJPTfeasible( index_param_t index);
+
+#endif /* !INDEX_MANAGER_H_ */
diff --git a/src/lib/openjpip/j2kheader_manager.c b/src/lib/openjpip/j2kheader_manager.c
new file mode 100644
index 00000000..5a6054cc
--- /dev/null
+++ b/src/lib/openjpip/j2kheader_manager.c
@@ -0,0 +1,295 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include "j2kheader_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+
+SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream);
+CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream);
+
+bool get_mainheader_from_j2kstream( Byte_t *j2kstream, SIZmarker_param_t *SIZ, CODmarker_param_t *COD)
+{
+ if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){
+ fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
+ return false;
+ }
+
+ if( SIZ){
+ *SIZ = get_SIZmkrdata_from_j2kstream( j2kstream);
+ if( SIZ->Lsiz == 0)
+ return false;
+
+ j2kstream += (SIZ->Lsiz+2);
+ }
+
+ if( COD){
+ if( !SIZ)
+ j2kstream += (big2( j2kstream+2) + 2);
+
+ *COD = get_CODmkrdata_from_j2kstream( j2kstream);
+ if( COD->Lcod == 0)
+ return false;
+ }
+ return true;
+}
+
+SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream)
+{
+ SIZmarker_param_t SIZ;
+ int i;
+
+ if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){
+ fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n");
+ memset( &SIZ, 0, sizeof( SIZ ) );
+ return SIZ;
+ }
+
+ SIZ.Lsiz = big2( SIZstream);
+ SIZ.Rsiz = big2( SIZstream+2);
+ SIZ.Xsiz = big4( SIZstream+4);
+ SIZ.Ysiz = big4( SIZstream+8);
+ SIZ.XOsiz = big4( SIZstream+12);
+ SIZ.YOsiz = big4( SIZstream+16);
+ SIZ.XTsiz = big4( SIZstream+20);
+ SIZ.YTsiz = big4( SIZstream+24);
+ SIZ.XTOsiz = big4( SIZstream+28);
+ SIZ.YTOsiz = big4( SIZstream+32);
+ SIZ.Csiz = big2( SIZstream+36);
+
+ SIZ.XTnum = ( SIZ.Xsiz-SIZ.XTOsiz+SIZ.XTsiz-1)/SIZ.XTsiz;
+ SIZ.YTnum = ( SIZ.Ysiz-SIZ.YTOsiz+SIZ.YTsiz-1)/SIZ.YTsiz;
+
+ for( i=0; i<(int)SIZ.Csiz; i++){
+ SIZ.Ssiz[i] = *(SIZstream+(38+i*3));
+ SIZ.XRsiz[i] = *(SIZstream+(39+i*3));
+ SIZ.YRsiz[i] = *(SIZstream+(40+i*3));
+ }
+
+ return SIZ;
+}
+
+CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream)
+{
+ CODmarker_param_t COD;
+ int i;
+
+ if( *CODstream++ != 0xff || *CODstream++ != 0x52){
+ fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n");
+ return COD;
+ }
+
+ COD.Lcod = big2( CODstream);
+ COD.Scod = *( CODstream+2);
+ COD.prog_order = *( CODstream+3);
+ COD.numOflayers = big2( CODstream+4);
+ COD.numOfdecomp = *( CODstream+7);
+
+ if(COD.Scod & 0x01){
+ COD.XPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t));
+ COD.YPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t));
+
+ for( i=0; i<=COD.numOfdecomp; i++){
+ /*precinct size */
+ COD.XPsiz[i] = (Byte4_t)pow( 2, *( CODstream+12+i) & 0x0F);
+ COD.YPsiz[i] = (Byte4_t)pow( 2, (*( CODstream+12+i) & 0xF0) >> 4);
+ }
+ }
+ else{
+ COD.XPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
+ COD.YPsiz = (Byte4_t *)malloc( sizeof(Byte4_t));
+ COD.XPsiz[0] = COD.YPsiz[0] = pow(2,15);
+ }
+ return COD;
+}
+
+
+bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream);
+Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream);
+
+bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen)
+{
+ Byte2_t newLcod;
+
+ if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){
+ fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n");
+ return false;
+ }
+
+ if(!modify_SIZmkrstream( SIZ, COD.numOfdecomp-numOfdecomp, j2kstream))
+ return false;
+
+ j2kstream += SIZ.Lsiz+2;
+ if( !(newLcod = modify_CODmkrstream( COD, numOfdecomp, j2kstream)))
+ return false;
+
+ memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, *j2klen - (Byte8_t)(SIZ.Lsiz+COD.Lcod+6));
+ *j2klen -= (Byte8_t)( COD.Lcod - newLcod);
+
+ return true;
+}
+
+bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream)
+{
+ int i;
+
+ if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){
+ fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n");
+ return false;
+ }
+
+ for( i=0; i<difOfdecomplev; i++){
+ SIZ.Xsiz = (Byte4_t)ceil( (double)SIZ.Xsiz/2.0);
+ SIZ.Ysiz = (Byte4_t)ceil( (double)SIZ.Ysiz/2.0);
+ SIZ.XOsiz = (Byte4_t)ceil( (double)SIZ.XOsiz/2.0);
+ SIZ.YOsiz = (Byte4_t)ceil( (double)SIZ.YOsiz/2.0);
+ SIZ.XTsiz = (Byte4_t)ceil( (double)SIZ.XTsiz/2.0);
+ SIZ.YTsiz = (Byte4_t)ceil( (double)SIZ.YTsiz/2.0);
+ SIZ.XTOsiz = (Byte4_t)ceil( (double)SIZ.XTOsiz/2.0);
+ SIZ.YTOsiz = (Byte4_t)ceil( (double)SIZ.YTOsiz/2.0);
+ }
+
+ SIZstream += 4; /* skip Lsiz + Rsiz */
+
+ modify_4Bytecode( SIZ.Xsiz, SIZstream);
+ modify_4Bytecode( SIZ.Ysiz, SIZstream+4);
+ modify_4Bytecode( SIZ.XOsiz, SIZstream+8);
+ modify_4Bytecode( SIZ.YOsiz, SIZstream+12);
+ modify_4Bytecode( SIZ.XTsiz, SIZstream+16);
+ modify_4Bytecode( SIZ.YTsiz, SIZstream+20);
+ modify_4Bytecode( SIZ.XTOsiz, SIZstream+24);
+ modify_4Bytecode( SIZ.YTOsiz, SIZstream+28);
+
+ return true;
+}
+
+Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream)
+{
+ Byte2_t newLcod;
+
+ assert( numOfdecomp >= 0 || numOfdecomp <= 255 );
+ if( *CODstream++ != 0xff || *CODstream++ != 0x52){
+ fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n");
+ return 0;
+ }
+
+ if( COD.Scod & 0x01){
+ newLcod = (Byte2_t)(13+numOfdecomp);
+
+ *CODstream++ = (Byte_t)((Byte2_t)(newLcod & 0xff00) >> 8);
+ *CODstream++ = (Byte_t)(newLcod & 0x00ff);
+ }
+ else{
+ newLcod = COD.Lcod;
+ CODstream += 2;
+ }
+
+ CODstream += 5; /* skip Scod & SGcod */
+
+ /* SPcod */
+ *CODstream++ = (Byte_t) numOfdecomp;
+
+ return newLcod;
+}
+
+bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc);
+
+bool modify_tileheader( Byte_t *j2kstream, Byte8_t SOToffset, int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen)
+{
+ Byte4_t Psot; /* tile part length ref A.4.2 Start of tile-part SOT */
+ Byte_t *thstream, *SOTstream, *Psot_stream;
+ Byte2_t oldLcoc, newLcoc;
+
+ SOTstream = thstream = j2kstream+SOToffset;
+
+ if( *SOTstream++ != 0xff || *SOTstream++ != 0x90){
+ fprintf( FCGI_stderr, "Error, thstream is not starting with SOT marker\n");
+ return false;
+ }
+
+ SOTstream += 4; /* skip Lsot & Isot */
+ Psot = (Byte4_t)((SOTstream[0]<<24)+(SOTstream[1]<<16)+(SOTstream[2]<<8)+(SOTstream[3]));
+ Psot_stream = SOTstream;
+
+ thstream += 12; /* move to next marker (SOT always 12bytes) */
+
+ while( !( *thstream == 0xff && *(thstream+1) == 0x93)){ /* search SOD */
+ if( numOfdecomp != -1 && *thstream == 0xff && *(thstream+1) == 0x53){ /* COC */
+ if( !modify_COCmkrstream( numOfdecomp, thstream, Csiz, &oldLcoc, &newLcoc))
+ return false;
+
+ memmove( thstream+newLcoc+2, thstream+oldLcoc+2, *j2klen - (Byte8_t)(thstream-j2kstream+oldLcoc+2));
+ *j2klen -= (Byte8_t)( oldLcoc - newLcoc);
+ }
+ thstream += 2;
+ thstream += ((thstream[0]<<8)+(thstream[1])); /* marker length */
+ }
+
+ if( (*j2klen)-SOToffset != Psot){
+ Psot = (Byte4_t)((*j2klen)-SOToffset);
+ modify_4Bytecode( Psot, Psot_stream);
+ }
+ return true;
+}
+
+bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc)
+{
+ if( numOfdecomp < 0 || numOfdecomp > 255 ) return false;
+ if( *COCstream++ != 0xff || *COCstream++ != 0x53){
+ fprintf( FCGI_stderr, "Error, COC marker not found in the reconstructed j2kstream\n");
+ return false;
+ }
+
+ *oldLcoc = big2( COCstream);
+ *newLcoc = (Byte2_t)((Csiz < 257 ? 10 : 11) + numOfdecomp);
+ *COCstream++ = (Byte_t)((Byte2_t)((*newLcoc) & 0xff00) >> 8);
+ *COCstream++ = (Byte_t)((*newLcoc) & 0x00ff);
+
+ if( Csiz < 257) COCstream +=2; /* skip Ccoc & Scoc */
+ else COCstream += 3;
+
+ *COCstream = (Byte_t)numOfdecomp;
+
+ return true;
+}
diff --git a/src/lib/openjpip/j2kheader_manager.h b/src/lib/openjpip/j2kheader_manager.h
new file mode 100644
index 00000000..a6146c64
--- /dev/null
+++ b/src/lib/openjpip/j2kheader_manager.h
@@ -0,0 +1,73 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 J2KHEADER_MANAGER_H_
+# define J2KHEADER_MANAGER_H_
+
+#include "bool.h"
+#include "byte_manager.h"
+#include "index_manager.h"
+
+/**
+ * get main header information from j2k codestream
+ *
+ * @param[in] j2kstream j2k codestream
+ * @param[out] SIZ SIZ marker pointer
+ * @param[out] COD COD marker pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool get_mainheader_from_j2kstream( Byte_t *j2kstream, SIZmarker_param_t *SIZ, CODmarker_param_t *COD);
+
+/**
+ * modify main header in j2k codestream to fit with the new number of decompositions
+ *
+ * @param[in] j2kstream j2k codestream
+ * @param[in] numOfdecomp the New number of decompositions
+ * @param[in] SIZ original SIZ marker information
+ * @param[in] COD original COD marker information
+ * @param[out] j2klen pointer to the length of j2k code stream
+ * @return if succeeded (true) or failed (false)
+ */
+bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen);
+
+/**
+ * modify tile header in j2k codestream to fit with the tile part length, and new number of decompositions for multi-componet images
+ *
+ * @param[in] j2kstream j2k codestream
+ * @param[in] SOToffset offset of SOT marker from the beginning of j2kstream
+ * @param[in] numOfdecomp the New number of decompositions, -1 if the same as original
+ * @param[in] Csiz number of components
+ * @param[out] j2klen pointer to the length of j2k code stream
+ * @return if succeeded (true) or failed (false)
+ */
+bool modify_tileheader( Byte_t *j2kstream, Byte8_t SOToffset, int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen);
+
+#endif /* !J2KHEADER_MANAGER_H_ */
diff --git a/src/lib/openjpip/jp2k_decoder.c b/src/lib/openjpip/jp2k_decoder.c
new file mode 100644
index 00000000..9d619b09
--- /dev/null
+++ b/src/lib/openjpip/jp2k_decoder.c
@@ -0,0 +1,236 @@
+/*
+ * $Id: jp2k_decoder.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <limits.h>
+#include "jp2k_decoder.h"
+#include "openjpeg.h"
+
+
+void error_callback(const char *msg, void *client_data);
+void warning_callback(const char *msg, void *client_data);
+void info_callback(const char *msg, void *client_data);
+
+Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox);
+
+Byte_t * j2k_to_pnm( FILE *fp, ihdrbox_param_t **ihdrbox)
+{
+ Byte_t *pnmstream = NULL;
+ opj_dparameters_t parameters; /* decompression parameters */
+ opj_image_t *image = NULL;
+ opj_codec_t *l_codec = NULL; /* handle to a decompressor */
+ opj_stream_t *l_stream = NULL;
+
+
+
+ /* set decoding parameters to default values */
+ opj_set_default_decoder_parameters(&parameters);
+
+ /* set a byte stream */
+ l_stream = opj_stream_create_default_file_stream( fp, 1);
+ if (!l_stream){
+ fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
+ return NULL;
+ }
+
+ /* decode the code-stream */
+ /* ---------------------- */
+
+ /* JPEG-2000 codestream */
+ /* get a decoder handle */
+ l_codec = opj_create_decompress(CODEC_J2K);
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_info_handler(l_codec, info_callback,00);
+ opj_set_warning_handler(l_codec, warning_callback,00);
+ opj_set_error_handler(l_codec, error_callback,00);
+
+ /* setup the decoder decoding parameters using user parameters */
+ if ( !opj_setup_decoder(l_codec, &parameters) ){
+ fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n");
+ return NULL;
+ }
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if(! opj_read_header( l_stream, l_codec, &image)){
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to read the header\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ return NULL;
+ }
+
+#ifdef TODO /*decode area could be set from j2k_to_pnm call, modify the protocol between JPIP viewer and opj_dec_server*/
+ if (! opj_set_decode_area( l_codec, image, parameters.DA_x0, parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ return NULL;
+ }
+#endif /*TODO*/
+
+ /* Get the decoded image */
+ if ( !( opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,l_stream) ) ) {
+ fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
+ opj_stream_destroy(l_stream);
+ opj_destroy_codec(l_codec);
+ opj_image_destroy(image);
+ return NULL;
+ }
+
+ fprintf(stderr, "image is decoded!\n");
+
+ /* close the byte stream */
+ opj_stream_destroy(l_stream);
+
+ /* create output image */
+ /* ------------------- */
+ if( (pnmstream = imagetopnm( image, ihdrbox))==NULL)
+ fprintf( stderr, "PNM image not generated\n");
+
+ /* free remaining structures */
+ if(l_codec) {
+ opj_destroy_codec(l_codec);
+ }
+
+ /* free image data structure */
+ opj_image_destroy(image);
+
+ return pnmstream;
+}
+
+
+/**
+ 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;
+ (void)msg;
+ /* fprintf(stdout, "[INFO] %s", msg); */
+}
+
+
+Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox)
+{
+ OPJ_UINT32 adjustR, adjustG=0, adjustB=0;
+ OPJ_SIZE_T datasize;
+ Byte_t *pix=NULL, *ptr=NULL;
+ OPJ_UINT32 i;
+
+ if(*ihdrbox){
+ if( (*ihdrbox)->nc != image->numcomps)
+ fprintf( stderr, "Exception: num of components not identical, codestream: %d, ihdrbox: %d\n", image->numcomps, (*ihdrbox)->nc);
+
+ if( (*ihdrbox)->width != image->comps[0].w)
+ (*ihdrbox)->width = image->comps[0].w;
+
+ if( (*ihdrbox)->height != image->comps[0].h)
+ (*ihdrbox)->height = image->comps[0].h;
+
+ if( (*ihdrbox)->bpc != image->comps[0].prec)
+ fprintf( stderr, "Exception: bits per component not identical, codestream: %d, ihdrbox: %d\n", image->comps[0].prec, (*ihdrbox)->bpc);
+ }
+ else{
+ *ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t));
+ (*ihdrbox)->width = image->comps[0].w;
+ (*ihdrbox)->height = image->comps[0].h;
+ assert( image->comps[0].prec < 256 );
+ (*ihdrbox)->bpc = (Byte_t)image->comps[0].prec;
+ assert( image->numcomps < USHRT_MAX );
+ (*ihdrbox)->nc = (Byte2_t)image->numcomps;
+ }
+
+ datasize = (image->numcomps)*(image->comps[0].w)*(image->comps[0].h);
+
+ 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->numcomps == 3){
+ 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;
+ }
+
+ pix = (Byte_t *)malloc( datasize);
+ ptr = pix;
+
+ for( i = 0; i < image->comps[0].w * image->comps[0].h; i++){
+ int r, g, b;
+ r = image->comps[0].data[i];
+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ /* if( adjustR > 0) */
+ *(ptr++) = (Byte_t) ((r >> adjustR)+((r >> (adjustR-1))%2));
+
+ if( image->numcomps == 3){
+ g = image->comps[1].data[i];
+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+ *(ptr++) = (Byte_t) ((g >> adjustG)+((g >> (adjustG-1))%2));
+
+ b = image->comps[2].data[i];
+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+ *(ptr++) = (Byte_t) ((b >> adjustB)+((b >> (adjustB-1))%2));
+ }
+ }
+
+ return pix;
+}
diff --git a/src/lib/openjpip/jp2k_decoder.h b/src/lib/openjpip/jp2k_decoder.h
new file mode 100644
index 00000000..c999cdf1
--- /dev/null
+++ b/src/lib/openjpip/jp2k_decoder.h
@@ -0,0 +1,39 @@
+/*
+ * $Id: jp2k_decoder.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 JP2K_DECODER_H_
+# define JP2K_DECODER_H_
+
+#include "byte_manager.h"
+#include "ihdrbox_manager.h"
+
+Byte_t * j2k_to_pnm( FILE *fp, ihdrbox_param_t **ihdrbox);
+
+#endif /* !JP2K_DECODER_H_ */
diff --git a/src/lib/openjpip/jp2k_encoder.c b/src/lib/openjpip/jp2k_encoder.c
new file mode 100644
index 00000000..23c8b2fe
--- /dev/null
+++ b/src/lib/openjpip/jp2k_encoder.c
@@ -0,0 +1,804 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include "jp2k_encoder.h"
+#include "j2kheader_manager.h"
+#include "imgreg_manager.h"
+#include "opj_inttypes.h"
+
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+/**
+ * search a message by class_id
+ *
+ * @param[in] class_id class identifiers
+ * @param[in] in_class_id in-class identifiers, -1 means any
+ * @param[in] csn codestream number
+ * @param[in] msg first message pointer of the searching list
+ * @return found message pointer
+ */
+message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg);
+
+/**
+ * reconstruct j2k codestream from JPT- (in future, JPP-) stream
+ *
+ * @param[in] msgqueue message queue pointer
+ * @param[in] jpipstream original JPT- JPP- stream
+ * @param[in] csn codestream number
+ * @param[in] fw reconstructing image frame width
+ * @param[in] fh reconstructing image frame height
+ * @param[out] codelen codestream length
+ * @return generated reconstructed j2k codestream
+ */
+Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *codelen);
+
+Byte_t * recons_j2k( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen)
+{
+ Byte_t *j2kstream = NULL;
+
+ if( !msgqueue)
+ return NULL;
+
+ j2kstream = recons_codestream( msgqueue, jpipstream, csn, fw, fh, j2klen);
+
+ return j2kstream;
+}
+
+Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len);
+Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen);
+
+Byte_t * recons_jp2( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *jp2len)
+{
+ message_param_t *ptr;
+ Byte_t *jp2stream = NULL;
+ Byte_t *codestream = NULL;
+ Byte8_t codelen;
+ Byte8_t jp2cDBoxOffset = 0, jp2cDBoxlen = 0;
+
+ *jp2len = 0;
+
+ if( !msgqueue)
+ return NULL;
+
+ ptr = msgqueue->first;
+ while(( ptr = search_message( METADATA_MSG, (Byte8_t)-1, csn, ptr))!=NULL){
+ if( ptr->phld){
+ if( strncmp( (char *)ptr->phld->OrigBH+4, "jp2c", 4) == 0){
+ jp2cDBoxOffset = *jp2len + ptr->phld->OrigBHlen;
+ jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); /* header only */
+ jp2cDBoxlen = *jp2len - jp2cDBoxOffset;
+ }
+ else
+ jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); /* header only */
+ }
+ jp2stream = add_msgstream( ptr, jpipstream, jp2stream, jp2len);
+ ptr = ptr->next;
+ }
+
+ codestream = recons_codestream( msgqueue, jpipstream, csn, 0, 0, &codelen);
+
+ if( jp2cDBoxOffset != 0 && codelen <= jp2cDBoxlen)
+ memcpy( jp2stream+jp2cDBoxOffset, codestream, codelen);
+
+ free( codestream);
+
+ return jp2stream;
+}
+
+bool isJPPstream( Byte8_t csn, msgqueue_param_t *msgqueue);
+
+Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen);
+Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen);
+
+Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen);
+
+Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *codelen)
+{
+ if( isJPPstream( csn, msgqueue))
+ return recons_codestream_from_JPPstream( msgqueue, jpipstream, csn, fw, fh, codelen);
+ else
+ return recons_codestream_from_JPTstream( msgqueue, jpipstream, csn, fw, fh, codelen);
+}
+
+bool isJPPstream( Byte8_t csn, msgqueue_param_t *msgqueue)
+{
+ message_param_t *msg;
+
+ msg = msgqueue->first;
+ while( msg){
+ if( msg->csn == csn){
+ if( msg->class_id <= 2)
+ return true;
+ else
+ if( msg->class_id == 4 || msg->class_id == 5)
+ return false;
+ }
+ msg = msg->next;
+ }
+
+ fprintf( FCGI_stderr, "Error, message of csn %" PRId64 " not found\n", csn);
+
+ return false;
+}
+
+Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, Byte_t *j2kstream, Byte8_t csn, Byte8_t *j2klen);
+Byte8_t get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn, bool isJPPstream);
+Byte_t * add_emptytilestream( const Byte8_t tileID, Byte_t *j2kstream, Byte8_t *j2klen);
+
+Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen)
+{
+ Byte_t *j2kstream = NULL;
+ Byte8_t last_tileID, tileID;
+ bool found;
+ Byte8_t binOffset;
+ message_param_t *ptr;
+ SIZmarker_param_t SIZ;
+ OPJ_SIZE_T mindeclev;
+
+ *j2klen = 0;
+ j2kstream = add_mainhead_msgstream( msgqueue, jpipstream, j2kstream, csn, j2klen);
+
+ if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, NULL))
+ return j2kstream;
+
+ if( fw <= 0 || fh <= 0)
+ mindeclev = 0;
+ else
+ mindeclev = (OPJ_SIZE_T)comp_decomplev( fw, fh, (int)SIZ.Xsiz, (int)SIZ.Ysiz);
+
+ last_tileID = get_last_tileID( msgqueue, csn, false);
+
+ for( tileID=0; tileID <= last_tileID; tileID++){
+ found = false;
+ binOffset = 0;
+
+ ptr = msgqueue->first;
+ while(( ptr = search_message( TILE_MSG, tileID, csn, ptr))!=NULL){
+ if( ptr->bin_offset == binOffset){
+ found = true;
+ j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen);
+ binOffset += ptr->length;
+ }
+ ptr = ptr->next;
+ }
+ ptr = msgqueue->first;
+ while(( ptr = search_message( EXT_TILE_MSG, tileID, csn, ptr))!=NULL){
+ if( ptr->aux > mindeclev){ /* FIXME: pointer comparison ? */
+ if( ptr->bin_offset == binOffset){
+ found = true;
+ j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen);
+ binOffset += ptr->length;
+ }
+ }
+ ptr = ptr->next;
+ }
+ if(!found)
+ j2kstream = add_emptytilestream( tileID, j2kstream, j2klen);
+ }
+
+ j2kstream = add_EOC( j2kstream, j2klen);
+
+ return j2kstream;
+}
+
+Byte_t * add_SOTmkr( Byte_t *j2kstream, Byte8_t *j2klen);
+
+Byte_t * recons_bitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen)
+{
+ Byte_t *j2kstream = NULL;
+ Byte8_t tileID, last_tileID;
+ Byte8_t SOToffset;
+ bool foundTH;
+ Byte8_t binOffset;
+ message_param_t *ptr;
+ SIZmarker_param_t SIZ;
+ CODmarker_param_t COD;
+ int max_reslev, mindeclev;
+
+ *j2klen = 0;
+ j2kstream = add_mainhead_msgstream( msgqueue, jpipstream, j2kstream, csn, j2klen);
+
+ if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, &COD))
+ return j2kstream;
+
+ if( fw == 0 || fh == 0)
+ mindeclev = 0;
+ else
+ mindeclev = comp_decomplev( fw, fh, (int)SIZ.Xsiz, (int)SIZ.Ysiz);
+
+ max_reslev = -1;
+ last_tileID = get_last_tileID( msgqueue, csn, true);
+
+ for( tileID=0; tileID <= last_tileID; tileID++){
+
+ ptr = msgqueue->first;
+ binOffset = 0;
+ foundTH = false;
+ SOToffset = *j2klen;
+ while(( ptr = search_message( TILE_HEADER_MSG, tileID, csn, ptr))!=NULL){
+ if( ptr->bin_offset == binOffset){
+ j2kstream = add_SOTmkr( j2kstream, j2klen);
+ j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen);
+ foundTH = true;
+ binOffset += ptr->length;
+ }
+ ptr = ptr->next;
+ }
+
+ if( foundTH){
+ j2kstream = recons_bitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, &max_reslev, j2klen);
+ modify_tileheader( j2kstream, SOToffset, (max_reslev<COD.numOfdecomp ? max_reslev : -1), SIZ.Csiz, j2klen);
+ }
+ else
+ j2kstream = add_emptytilestream( tileID, j2kstream, j2klen);
+ }
+
+ if( max_reslev < COD.numOfdecomp)
+ if( !modify_mainheader( j2kstream, max_reslev, SIZ, COD, j2klen)){
+ delete_COD( COD);
+ return j2kstream;
+ }
+
+ j2kstream = add_EOC( j2kstream, j2klen);
+ delete_COD( COD);
+
+ return j2kstream;
+}
+
+Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, Byte_t *j2kstream, Byte8_t csn, Byte8_t *j2klen)
+{
+ message_param_t *ptr;
+ Byte8_t binOffset;
+
+ ptr = msgqueue->first;
+ binOffset = 0;
+
+ while(( ptr = search_message( MAINHEADER_MSG, (Byte8_t)-1, csn, ptr))!=NULL){
+ if( ptr->bin_offset == binOffset){
+ j2kstream = add_msgstream( ptr, origstream, j2kstream, j2klen);
+ binOffset += ptr->length;
+ }
+ ptr = ptr->next;
+ }
+ return j2kstream;
+}
+
+Byte_t * add_SOTmkr( Byte_t *j2kstream, Byte8_t *j2klen)
+{
+ Byte_t *buf;
+ const Byte2_t SOT = 0x90ff;
+
+ buf = (Byte_t *)malloc(( *j2klen)+2);
+
+ memcpy( buf, j2kstream, *j2klen);
+ memcpy( buf+(*j2klen), &SOT, 2);
+
+ *j2klen += 2;
+
+ if(j2kstream) free(j2kstream);
+
+ return buf;
+}
+
+Byte_t * recons_LRCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_RLCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_PCRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_CPRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen);
+
+Byte_t * recons_bitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ switch( COD.prog_order){
+ case LRCP:
+ return recons_LRCPbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen);
+ case RLCP:
+ return recons_RLCPbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen);
+ case RPCL:
+ return recons_RPCLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen);
+ case PCRL:
+ return recons_PCRLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen);
+ case CPRL:
+ return recons_CPRLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen);
+ default:
+ fprintf( FCGI_stderr, "Error, progression order not supported\n");
+ }
+ return j2kstream;
+}
+
+int comp_numOfprcts( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r);
+Byte8_t comp_seqID( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r, int p);
+
+Byte_t * recons_packet( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev,
+ int comp_idx, int res_idx, int prct_idx, int lay_idx, Byte8_t *j2klen);
+
+Byte_t * recons_LRCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ int r, p, c, l, numOfprcts;
+
+ for( l=0; l<COD.numOflayers; l++)
+ for( r=0; r<=(COD.numOfdecomp-mindeclev); r++){
+ if( COD.Scod & 0x01)
+ numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r);
+ else
+ numOfprcts = 1;
+
+ for( c=0; c<SIZ.Csiz; c++)
+ for( p=0; p<numOfprcts; p++)
+ j2kstream = recons_packet( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, p, l, j2klen);
+ }
+
+ return j2kstream;
+}
+
+Byte_t * recons_RLCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ int r, p, c, l, numOfprcts;
+
+ for( r=0; r<=(COD.numOfdecomp-mindeclev); r++){
+ if( COD.Scod & 0x01)
+ numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r);
+ else
+ numOfprcts = 1;
+
+ for( l=0; l<COD.numOflayers; l++)
+ for( c=0; c<SIZ.Csiz; c++)
+ for( p=0; p<numOfprcts; p++)
+ j2kstream = recons_packet( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, p, l, j2klen);
+ }
+
+ return j2kstream;
+}
+
+Byte_t * recons_precinct( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev,
+ int comp_idx, int res_idx, Byte8_t seqID, Byte8_t *j2klen);
+
+Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ int r, p, c, numOfprcts;
+ Byte8_t seqID;
+
+ for( r=0, seqID=0; r<=(COD.numOfdecomp-mindeclev); r++){
+
+ if( COD.Scod & 0x01)
+ numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r);
+ else
+ numOfprcts = 1;
+
+ for( p=0; p<numOfprcts; p++, seqID++)
+ for( c=0; c<SIZ.Csiz; c++)
+ j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen);
+ }
+
+ return j2kstream;
+}
+
+Byte_t * recons_PCRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ int r, p, c, min_numOfprcts, numOfprcts, min_numOfres;
+ Byte8_t seqID;
+
+ min_numOfres = COD.numOfdecomp-mindeclev + 1;
+
+ if( COD.Scod & 0x01){
+ min_numOfprcts = 0;
+ for( r=0; r<min_numOfres; r++){
+ numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r);
+
+ if( numOfprcts < min_numOfprcts || min_numOfprcts == 0)
+ min_numOfprcts = numOfprcts;
+ }
+ }
+ else
+ min_numOfprcts = 1;
+
+ for( p=0; p<min_numOfprcts; p++)
+ for( c=0; c<SIZ.Csiz; c++)
+ for( r=0; r<min_numOfres; r++){
+ seqID = comp_seqID( tileID, SIZ, COD, r, p);
+ j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen);
+ }
+
+ return j2kstream;
+}
+
+
+Byte_t * recons_CPRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev,
+ int *max_reslev, Byte8_t *j2klen)
+{
+ int r, p, c, min_numOfprcts, numOfprcts, min_numOfres;
+ Byte8_t seqID;
+
+ min_numOfres = COD.numOfdecomp-mindeclev + 1;
+
+ if( COD.Scod & 0x01){
+ min_numOfprcts = 0;
+ for( r=0; r<min_numOfres; r++){
+ numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r);
+
+ if( numOfprcts < min_numOfprcts || min_numOfprcts == 0)
+ min_numOfprcts = numOfprcts;
+ }
+ }
+ else
+ min_numOfprcts = 1;
+
+ for( c=0; c<SIZ.Csiz; c++)
+ for( p=0; p<min_numOfprcts; p++)
+ for( r=0; r<min_numOfres; r++){
+ seqID = comp_seqID( tileID, SIZ, COD, r, p);
+ j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen);
+ }
+
+ return j2kstream;
+}
+
+int comp_numOfprcts( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r)
+{
+ int ret;
+ Byte4_t XTsiz, YTsiz;
+
+ XTsiz = get_tile_XSiz( SIZ, (Byte4_t)tileID, COD.numOfdecomp-r);
+ YTsiz = get_tile_YSiz( SIZ, (Byte4_t)tileID, COD.numOfdecomp-r);
+
+ ret = (int)(ceil((double)XTsiz/(double)COD.XPsiz[r])*ceil((double)YTsiz/(double)COD.YPsiz[r]));
+ assert( ret >= 0 );
+ return ret;
+}
+
+Byte_t * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen);
+
+Byte_t * recons_packet( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev,
+ int comp_idx, int res_idx, int prct_idx, int lay_idx, Byte8_t *j2klen)
+{
+ Byte8_t seqID, precID, binOffset;
+ message_param_t *ptr;
+ bool foundPrec;
+ int l;
+
+ seqID = comp_seqID( tileID, SIZ, COD, res_idx, prct_idx);
+ precID = comp_precinct_id( (int)tileID, comp_idx, (int)seqID, (int)SIZ.Csiz, (int)SIZ.XTnum*(int)SIZ.YTnum);
+
+ ptr = msgqueue->first;
+ binOffset = 0;
+ foundPrec = false;
+ l = 0;
+
+ while(( ptr = search_message( PRECINCT_MSG, precID, csn, ptr))!=NULL){
+ if( ptr->bin_offset == binOffset){
+ if( lay_idx == l){
+ j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen);
+ foundPrec = true;
+ if( *max_reslev < res_idx)
+ *max_reslev = res_idx;
+
+ break;
+ }
+ binOffset += ptr->length;
+ l++;
+ }
+ ptr = ptr->next;
+ }
+ if( !foundPrec && COD.Scod & 0x01)
+ j2kstream = add_padding( 1, j2kstream, j2klen);
+
+ return j2kstream;
+}
+
+
+Byte_t * recons_precinct( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn,
+ Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev,
+ int comp_idx, int res_idx, Byte8_t seqID, Byte8_t *j2klen)
+{
+ Byte8_t precID, binOffset;
+ message_param_t *ptr;
+ bool foundPrec;
+
+ precID = comp_precinct_id( (int)tileID, comp_idx, (int)seqID, (int)SIZ.Csiz, (int)SIZ.XTnum*(int)SIZ.YTnum);
+
+ ptr = msgqueue->first;
+ binOffset = 0;
+ foundPrec = false;
+
+ while(( ptr = search_message( PRECINCT_MSG, precID, csn, ptr))!=NULL){
+ if( ptr->bin_offset == binOffset){
+ j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen);
+
+ foundPrec = true;
+ binOffset += ptr->length;
+ if( *max_reslev < res_idx)
+ *max_reslev = res_idx;
+
+ if( ptr->last_byte)
+ break;
+ }
+ ptr = ptr->next;
+ }
+ if(!foundPrec && COD.Scod & 0x01)
+ j2kstream = add_padding( COD.numOflayers, j2kstream, j2klen);
+
+ return j2kstream;
+}
+
+Byte8_t comp_seqID( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r, int p)
+{
+ Byte8_t seqID = 0;
+ int rr;
+ assert( p >= 0);
+ assert( r >= 0);
+
+ for( rr=0; rr<r; rr++)
+ seqID += (Byte8_t)comp_numOfprcts( tileID, SIZ, COD, rr);
+
+ seqID += (Byte8_t)p;
+
+ return seqID;
+}
+
+Byte8_t get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn, bool isJPPstream)
+{
+ Byte8_t last_tileID = 0;
+ message_param_t *msg;
+
+ msg = msgqueue->first;
+ while( msg){
+ if( isJPPstream){
+ if((msg->class_id == TILE_HEADER_MSG) && msg->csn == csn && last_tileID < msg->in_class_id)
+ last_tileID = msg->in_class_id;
+ }
+ else{
+ if((msg->class_id == TILE_MSG || msg->class_id == EXT_TILE_MSG) && msg->csn == csn && last_tileID < msg->in_class_id)
+ last_tileID = msg->in_class_id;
+ }
+ msg = msg->next;
+ }
+ return last_tileID;
+}
+
+
+message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg)
+{
+ while( msg != NULL){
+ if( in_class_id == (Byte8_t)-1){
+ if( msg->class_id == class_id && msg->csn == csn)
+ return msg;
+ }
+ else{
+ if( msg->class_id == class_id && msg->in_class_id == in_class_id && msg->csn == csn)
+ return msg;
+ }
+ msg = msg->next;
+ }
+ return NULL;
+}
+
+
+Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length);
+Byte_t * gene_emptytilestream( const Byte8_t tileID, Byte8_t *length);
+
+Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen)
+{
+ Byte_t *newstream;
+ Byte8_t newlen;
+ Byte_t *buf;
+
+ if( !message)
+ return NULL;
+
+ newstream = gene_msgstream( message, origstream, &newlen);
+
+ buf = (Byte_t *)malloc(( *j2klen)+newlen);
+
+ memcpy( buf, j2kstream, *j2klen);
+ memcpy( buf+(*j2klen), newstream, newlen);
+
+ *j2klen += newlen;
+
+ free( newstream);
+ if(j2kstream) free(j2kstream);
+
+ return buf;
+}
+
+
+Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len)
+{
+ Byte_t *newstream;
+ Byte8_t newlen;
+ Byte_t *buf;
+
+ if( phld->OrigBHlen == 8)
+ newlen = big4(phld->OrigBH);
+ else
+ newlen = big8(phld->OrigBH+8);
+
+ newstream = (Byte_t *)malloc( newlen);
+ memset( newstream, 0, newlen);
+ memcpy( newstream, phld->OrigBH, phld->OrigBHlen);
+
+ buf = (Byte_t *)malloc(( *jp2len)+newlen);
+
+ memcpy( buf, jp2stream, *jp2len);
+ memcpy( buf+(*jp2len), newstream, newlen);
+
+ *jp2len += newlen;
+
+ free( newstream);
+ if(jp2stream) free(jp2stream);
+
+ return buf;
+}
+
+Byte_t * add_emptytilestream( const Byte8_t tileID, Byte_t *j2kstream, Byte8_t *j2klen)
+{
+ Byte_t *newstream;
+ Byte8_t newlen;
+ Byte_t *buf;
+
+ newstream = gene_emptytilestream( tileID, &newlen);
+
+ buf = (Byte_t *)malloc(( *j2klen)+newlen);
+
+ memcpy( buf, j2kstream, *j2klen);
+ memcpy( buf+(*j2klen), newstream, newlen);
+
+ *j2klen += newlen;
+
+ free( newstream);
+ if(j2kstream) free(j2kstream);
+
+ return buf;
+}
+
+Byte_t * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen)
+{
+ Byte_t *buf;
+
+ buf = (Byte_t *)malloc(( *j2klen)+padding);
+
+ memcpy( buf, j2kstream, *j2klen);
+ memset( buf+(*j2klen), 0, padding);
+
+ *j2klen += padding;
+
+ if(j2kstream) free(j2kstream);
+
+ return buf;
+}
+
+Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen)
+{
+ Byte2_t EOC = 0xd9ff;
+
+ Byte_t *buf;
+
+ buf = (Byte_t *)malloc(( *j2klen)+2);
+
+ memcpy( buf, j2kstream, *j2klen);
+ memcpy( buf+(*j2klen), &EOC, 2);
+
+ *j2klen += 2;
+
+ if(j2kstream) free(j2kstream);
+
+ return buf;
+}
+
+Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length)
+{
+ Byte_t *buf;
+
+ if( !message)
+ return NULL;
+
+ *length = message->length;
+ buf = (Byte_t *)malloc( *length);
+ memcpy( buf, stream+message->res_offset, *length);
+
+ return buf;
+}
+
+Byte_t * gene_emptytilestream( const Byte8_t tileID, Byte8_t *length)
+{
+ Byte_t *buf;
+ const Byte2_t SOT = 0x90ff;
+ const Byte2_t Lsot = 0xa << 8;
+ Byte2_t Isot;
+ const Byte4_t Psot = 0xe << 24;
+ const Byte_t TPsot = 0, TNsot = 1;
+ const Byte2_t SOD = 0x93ff;
+
+ *length = 14;
+ buf = (Byte_t *)malloc(*length);
+
+ Isot = (Byte2_t)((((Byte2_t)tileID) << 8) | ((((Byte2_t)tileID) & 0xf0) >> 8));
+
+ memcpy( buf, &SOT, 2);
+ memcpy( buf+2, &Lsot, 2);
+ memcpy( buf+4, &Isot, 2);
+ memcpy( buf+6, &Psot, 4);
+ memcpy( buf+10, &TPsot, 1);
+ memcpy( buf+11, &TNsot, 1);
+ memcpy( buf+12, &SOD, 2);
+
+ return buf;
+}
+
+Byte_t * recons_j2kmainhead( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *j2klen)
+{
+ *j2klen = 0;
+ return add_mainhead_msgstream( msgqueue, jpipstream, NULL, csn, j2klen);
+}
diff --git a/src/lib/openjpip/jp2k_encoder.h b/src/lib/openjpip/jp2k_encoder.h
new file mode 100644
index 00000000..3945e2a0
--- /dev/null
+++ b/src/lib/openjpip/jp2k_encoder.h
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 JP2K_ENCODER_H_
+# define JP2K_ENCODER_H_
+
+#include "byte_manager.h"
+#include "msgqueue_manager.h"
+
+/**
+ * reconstruct j2k codestream from message queue
+ *
+ * @param[in] msgqueue message queue pointer
+ * @param[in] jpipstream original jpt- jpp- stream
+ * @param[in] csn codestream number
+ * @param[in] fw reconstructing image frame width
+ * @param[in] fh reconstructing image frame height
+ * @param[out] j2klen pointer to the j2k codestream length
+ * @return generated reconstructed j2k codestream
+ */
+Byte_t * recons_j2k( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen);
+
+
+/**
+ * reconstruct jp2 file codestream from message queue
+ *
+ * @param[in] msgqueue message queue pointer
+ * @param[in] jpipstream original jpt- jpp- stream
+ * @param[in] csn codestream number
+ * @param[out] jp2len pointer to the jp2 codestream length
+ * @return generated reconstructed jp2 codestream
+ */
+Byte_t * recons_jp2( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *jp2len);
+
+/**
+ * reconstruct j2k codestream of mainheader from message queue
+ *
+ * @param[in] msgqueue message queue pointer
+ * @param[in] jpipstream original jpt- jpp- stream
+ * @param[in] csn codestream number
+ * @param[out] j2klen pointer to the j2k codestream length
+ * @return generated reconstructed j2k codestream
+ */
+Byte_t * recons_j2kmainhead( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *j2klen);
+
+#endif /* !JP2K_ENCODER_H_ */
diff --git a/src/lib/openjpip/jpip_parser.c b/src/lib/openjpip/jpip_parser.c
new file mode 100644
index 00000000..663214e4
--- /dev/null
+++ b/src/lib/openjpip/jpip_parser.c
@@ -0,0 +1,460 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "jpip_parser.h"
+#include "channel_manager.h"
+#include "imgreg_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target)
+{
+ if( query_param.tid){
+ if( strcmp( query_param.tid, "0") != 0 ){
+ if( query_param.cid[0] != '\0'){
+ fprintf( FCGI_stdout, "Reason: Target can not be specified both through tid and cid\r\n");
+ fprintf( FCGI_stdout, "Status: 400\r\n");
+ return false;
+ }
+ if( ( *target = search_targetBytid( query_param.tid, targetlist)))
+ return true;
+ }
+ }
+
+ if( query_param.target)
+ if( !( *target = search_target( query_param.target, targetlist)))
+ if(!( *target = gene_target( targetlist, query_param.target)))
+ return false;
+
+ if( *target){
+ fprintf( FCGI_stdout, "JPIP-tid: %s\r\n", (*target)->tid);
+ return true;
+ }
+ else{
+ fprintf( FCGI_stdout, "Reason: target not found\r\n");
+ fprintf( FCGI_stdout, "Status: 400\r\n");
+ return false;
+ }
+}
+
+bool associate_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ session_param_t **cursession,
+ channel_param_t **curchannel)
+{
+ if( search_session_and_channel( query_param.cid, sessionlist, cursession, curchannel)){
+
+ if( !query_param.cnew)
+ set_channel_variable_param( query_param, *curchannel);
+ }
+ else{
+ fprintf( FCGI_stderr, "Error: process canceled\n");
+ return false;
+ }
+ return true;
+}
+
+bool open_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ auxtrans_param_t auxtrans,
+ target_param_t *target,
+ session_param_t **cursession,
+ channel_param_t **curchannel)
+{
+ cachemodel_param_t *cachemodel = NULL;
+
+ if( target){
+ if( !(*cursession))
+ *cursession = gene_session( sessionlist);
+ if( !( cachemodel = search_cachemodel( target, (*cursession)->cachemodellist)))
+ if( !(cachemodel = gene_cachemodel( (*cursession)->cachemodellist, target, query_param.return_type==JPPstream)))
+ return false;
+ }
+ else
+ if( *curchannel)
+ cachemodel = (*curchannel)->cachemodel;
+
+ *curchannel = gene_channel( query_param, auxtrans, cachemodel, (*cursession)->channellist);
+ if( *curchannel == NULL)
+ return false;
+
+ return true;
+}
+
+bool close_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ session_param_t **cursession,
+ channel_param_t **curchannel)
+{
+ char *cclose;
+ int i;
+
+ if( query_param.cclose[0] =='*'){
+#ifndef SERVER
+ fprintf( logstream, "local log: close all\n");
+#endif
+ /* all channels associatd with the session will be closed */
+ if( !delete_session( cursession, sessionlist))
+ return false;
+ }
+ else{
+ /* check if all entry belonging to the same session */
+
+ for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){
+
+ /* In case of the first entry of close cid */
+ if( *cursession == NULL){
+ if( !search_session_and_channel( cclose, sessionlist, cursession, curchannel))
+ return false;
+ }
+ else /* second or more entry of close cid */
+ if( !(*curchannel=search_channel( cclose, (*cursession)->channellist))){
+ fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", cclose);
+ return false;
+ }
+ }
+
+ /* delete channels */
+ for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){
+ *curchannel = search_channel( cclose, (*cursession)->channellist);
+ delete_channel( curchannel, (*cursession)->channellist);
+ }
+
+ if( (*cursession)->channellist->first == NULL || (*cursession)->channellist->last == NULL)
+ /* In case of empty session */
+ delete_session( cursession, sessionlist);
+ }
+ return true;
+}
+
+
+/**
+ * enqueue tiles or precincts into the message queue
+ *
+ * @param[in] query_param structured query
+ * @param[in] msgqueue message queue pointer
+ */
+void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue);
+
+/**
+ * enqueue metadata bins into the message queue
+ *
+ * @param[in] query_param structured query
+ * @param[in] metadatalist pointer to metadata bin list
+ * @param[in,out] msgqueue message queue pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue);
+
+
+bool gene_JPIPstream( query_param_t query_param,
+ target_param_t *target,
+ session_param_t *cursession,
+ channel_param_t *curchannel,
+ msgqueue_param_t **msgqueue)
+{
+ index_param_t *codeidx;
+ cachemodel_param_t *cachemodel;
+
+ if( !cursession || !curchannel){ /* stateless */
+ if( !target)
+ return false;
+ if( !(cachemodel = gene_cachemodel( NULL, target, query_param.return_type==JPPstream)))
+ return false;
+ *msgqueue = gene_msgqueue( true, cachemodel);
+ }
+ else{ /* session */
+ cachemodel = curchannel->cachemodel;
+ target = cachemodel->target;
+ *msgqueue = gene_msgqueue( false, cachemodel);
+ }
+
+ codeidx = target->codeidx;
+
+ if( cachemodel->jppstream)
+ fprintf( FCGI_stdout, "Content-type: image/jpp-stream\r\n");
+ else
+ fprintf( FCGI_stdout, "Content-type: image/jpt-stream\r\n");
+
+ if( query_param.layers != -1){
+ if( query_param.layers > codeidx->COD.numOflayers){
+ fprintf( FCGI_stdout, "JPIP-layers: %d\r\n", codeidx->COD.numOflayers);
+ query_param.layers = codeidx->COD.numOflayers;
+ }
+ }
+
+ /*meta*/
+ if( query_param.box_type[0][0] != 0 && query_param.len != 0)
+ if( !enqueue_metabins( query_param, codeidx->metadatalist, *msgqueue))
+ return false;
+
+ if( query_param.metadata_only)
+ return true;
+
+ /* main header */
+ if( !cachemodel->mhead_model && query_param.len != 0)
+ enqueue_mainheader( *msgqueue);
+
+ /* image codestream */
+ if( (query_param.fx > 0 && query_param.fy > 0))
+ enqueue_imagedata( query_param, *msgqueue);
+
+ return true;
+}
+
+
+/**
+ * enqueue precinct data-bins into the queue
+ *
+ * @param[in] xmin min x coordinate in the tile at the decomposition level
+ * @param[in] xmax max x coordinate in the tile at the decomposition level
+ * @param[in] ymin min y coordinate in the tile at the decomposition level
+ * @param[in] ymax max y coordinate in the tile at the decomposition level
+ * @param[in] tile_id tile index
+ * @param[in] level decomposition level
+ * @param[in] lastcomp last component number
+ * @param[in] comps pointer to the array that stores the requested components
+ * @param[in] layers number of quality layers
+ * @param[in] msgqueue message queue
+ * @return
+ */
+void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue);
+
+/**
+ * enqueue all precincts inside a tile into the queue
+ *
+ * @param[in] tile_id tile index
+ * @param[in] level decomposition level
+ * @param[in] lastcomp last component number
+ * @param[in] comps pointer to the array that stores the requested components
+ * @param[in] layers number of quality layers
+ * @param[in] msgqueue message queue
+ * @return
+ */
+void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue);
+
+void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue)
+{
+ index_param_t *codeidx;
+ imgreg_param_t imgreg;
+ range_param_t tile_Xrange, tile_Yrange;
+ Byte4_t u, v, tile_id;
+ int xmin, xmax, ymin, ymax;
+ int numOfreslev;
+
+ codeidx = msgqueue->cachemodel->target->codeidx;
+
+ if( !(msgqueue->cachemodel->jppstream) && get_nmax( codeidx->tilepart) == 1) /* normally not the case */
+ numOfreslev = 1;
+ else
+ numOfreslev = codeidx->COD.numOfdecomp+1;
+
+ imgreg = map_viewin2imgreg( query_param.fx, query_param.fy,
+ query_param.rx, query_param.ry, query_param.rw, query_param.rh,
+ (int)codeidx->SIZ.XOsiz, (int)codeidx->SIZ.YOsiz, (int)codeidx->SIZ.Xsiz, (int)codeidx->SIZ.Ysiz,
+ numOfreslev );
+
+ if( query_param.len == 0)
+ return;
+
+ for( u=0, tile_id=0; u<codeidx->SIZ.YTnum; u++){
+ tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level);
+
+ for( v=0; v<codeidx->SIZ.XTnum; v++, tile_id++){
+ tile_Xrange = get_tile_Xrange( codeidx->SIZ, tile_id, imgreg.level);
+
+ if( tile_Xrange.minvalue < tile_Xrange.maxvalue && tile_Yrange.minvalue < tile_Yrange.maxvalue){
+ if( tile_Xrange.maxvalue <= (Byte4_t)(imgreg.xosiz + imgreg.ox) ||
+ tile_Xrange.minvalue >= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) ||
+ tile_Yrange.maxvalue <= (Byte4_t)(imgreg.yosiz + imgreg.oy) ||
+ tile_Yrange.minvalue >= (Byte4_t)(imgreg.yosiz + imgreg.oy + imgreg.sy)) {
+ /*printf("Tile completely excluded from view-window %d\n", tile_id);*/
+ /* Tile completely excluded from view-window */
+ }
+ else if( tile_Xrange.minvalue >= (Byte4_t)(imgreg.xosiz + imgreg.ox) &&
+ tile_Xrange.maxvalue <= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) &&
+ tile_Yrange.minvalue >= (Byte4_t)(imgreg.yosiz + imgreg.oy) &&
+ tile_Yrange.maxvalue <= (Byte4_t)(imgreg.yosiz + imgreg.oy + imgreg.sy)) {
+ /* Tile completely contained within view-window */
+ /* high priority */
+ /*printf("Tile completely contained within view-window %d\n", tile_id);*/
+ if( msgqueue->cachemodel->jppstream){
+ enqueue_tileheader( (int)tile_id, msgqueue);
+ enqueue_allprecincts( (int)tile_id, imgreg.level, query_param.lastcomp, query_param.comps, query_param.layers, msgqueue);
+ }
+ else
+ enqueue_tile( tile_id, imgreg.level, msgqueue);
+ }
+ else{
+ /* Tile partially overlaps view-window */
+ /* low priority */
+ /*printf("Tile partially overlaps view-window %d\n", tile_id);*/
+ if( msgqueue->cachemodel->jppstream){
+ enqueue_tileheader( (int)tile_id, msgqueue);
+
+ /* FIXME: The following code is suspicious it implicitely cast an unsigned int to int, which truncates values */
+ xmin = tile_Xrange.minvalue >= (Byte4_t)(imgreg.xosiz + imgreg.ox) ? 0 : imgreg.xosiz + imgreg.ox - (int)tile_Xrange.minvalue;
+ xmax = tile_Xrange.maxvalue <= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) ? (int)(tile_Xrange.maxvalue - tile_Xrange.minvalue -1) : (int)(imgreg.xosiz + imgreg.ox + imgreg.sx - (int)tile_Xrange.minvalue - 1);
+ ymin = tile_Yrange.minvalue >= (Byte4_t)(imgreg.yosiz + imgreg.oy) ? 0 : imgreg.yosiz + imgreg.oy - (int)tile_Yrange.minvalue;
+ ymax = tile_Yrange.maxvalue <= (Byte4_t)(imgreg.yosiz + imgreg.oy + imgreg.sy) ? (int)(tile_Yrange.maxvalue - tile_Yrange.minvalue - 1) : (int)(imgreg.yosiz + imgreg.oy + imgreg.sy - (int)tile_Yrange.minvalue - 1);
+ enqueue_precincts( xmin, xmax, ymin, ymax, (int)tile_id, imgreg.level, query_param.lastcomp, query_param.comps, query_param.layers, msgqueue);
+ }
+ else
+ enqueue_tile( tile_id, imgreg.level, msgqueue);
+ }
+ }
+ }
+ }
+}
+
+
+void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue)
+{
+ index_param_t *codeidx;
+ int c, u, v, res_lev, dec_lev;
+ int seq_id;
+ Byte4_t XTsiz, YTsiz;
+ Byte4_t XPsiz, YPsiz;
+ Byte4_t xminP, xmaxP, yminP, ymaxP;
+
+ codeidx = msgqueue->cachemodel->target->codeidx;
+ /* MM: shouldnt xmin/xmax be Byte4_t instead ? */
+ if( xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0)
+ return;
+ /* MM: I think the API should not really be int should it ? */
+ if( tile_id < 0 )
+ return;
+
+ for( c=0; c<codeidx->SIZ.Csiz; c++)
+ if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){
+ seq_id = 0;
+ for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){
+
+ XTsiz = get_tile_XSiz( codeidx->SIZ, (Byte4_t)tile_id, dec_lev);
+ YTsiz = get_tile_YSiz( codeidx->SIZ, (Byte4_t)tile_id, dec_lev);
+
+ XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz;
+ YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz;
+
+ for( u=0; u<ceil((double)YTsiz/(double)YPsiz); u++){
+ yminP = (Byte4_t)u*YPsiz;
+ ymaxP = (Byte4_t)(u+1)*YPsiz-1;
+ if( YTsiz <= ymaxP)
+ ymaxP = YTsiz-1;
+
+ for( v=0; v<ceil((double)XTsiz/(double)XPsiz); v++, seq_id++){
+ xminP = (Byte4_t)v*XPsiz;
+ xmaxP = (Byte4_t)(v+1)*XPsiz-1;
+ if( XTsiz <= xmaxP)
+ xmaxP = XTsiz-1;
+
+ if( xmaxP < (Byte4_t)xmin || xminP > (Byte4_t)xmax || ymaxP < (Byte4_t)ymin || yminP > (Byte4_t)ymax){
+ /* Precinct completely excluded from view-window */
+ }
+ else if( xminP >= (Byte4_t)xmin && xmaxP <= (Byte4_t)xmax && yminP >= (Byte4_t)ymin && ymaxP <= (Byte4_t)ymax){
+ /* Precinct completely contained within view-window
+ high priority */
+ enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue);
+ }
+ else{
+ /* Precinct partially overlaps view-window
+ low priority */
+ enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue);
+ }
+ }
+ }
+ }
+ }
+}
+
+void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue)
+{
+ index_param_t *codeidx;
+ int c, i, res_lev, dec_lev;
+ int seq_id;
+ Byte4_t XTsiz, YTsiz;
+ Byte4_t XPsiz, YPsiz;
+
+ codeidx = msgqueue->cachemodel->target->codeidx;
+ if( tile_id < 0 )
+ return;
+
+ for( c=0; c<codeidx->SIZ.Csiz; c++)
+ if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){
+ seq_id = 0;
+ for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){
+
+ XTsiz = get_tile_XSiz( codeidx->SIZ, (Byte4_t)tile_id, dec_lev);
+ YTsiz = get_tile_YSiz( codeidx->SIZ, (Byte4_t)tile_id, dec_lev);
+
+ XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz;
+ YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz;
+
+ for( i=0; i<ceil((double)YTsiz/(double)YPsiz)*ceil((double)XTsiz/(double)XPsiz); i++, seq_id++)
+ enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue);
+ }
+ }
+}
+
+bool enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue)
+{
+ int i;
+ for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
+ if( query_param.box_type[i][0] == '*'){
+ fprintf( FCGI_stdout, "Status: 501\r\n");
+ fprintf( FCGI_stdout, "Reason: metareq with all box-property * not implemented\r\n");
+ return false;
+ }
+ else{
+ Byte8_t idx = search_metadataidx( query_param.box_type[i], metadatalist);
+
+ if( idx != (Byte8_t)-1)
+ enqueue_metadata( idx, msgqueue);
+ else{
+ fprintf( FCGI_stdout, "Status: 400\r\n");
+ fprintf( FCGI_stdout, "Reason: box-type %.4s not found\r\n", query_param.box_type[i]);
+ return false;
+ }
+ }
+ }
+ return true;
+}
diff --git a/src/lib/openjpip/jpip_parser.h b/src/lib/openjpip/jpip_parser.h
new file mode 100644
index 00000000..8070c8a9
--- /dev/null
+++ b/src/lib/openjpip/jpip_parser.h
@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 JPIP_PARSER_H_
+# define JPIP_PARSER_H_
+
+#include "bool.h"
+#include "query_parser.h"
+#include "session_manager.h"
+#include "target_manager.h"
+#include "msgqueue_manager.h"
+#include "channel_manager.h"
+
+/**
+ * REQUEST: target identification by target or tid request
+ *
+ * @param[in] query_param structured query
+ * @param[in] targetlist target list pointer
+ * @param[out] target address of target pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target);
+
+/**
+ * REQUEST: channel association
+ * this must be processed before any process
+ *
+ * @param[in] query_param structured query
+ * @param[in] sessionlist session list pointer
+ * @param[out] cursession address of the associated session pointer
+ * @param[out] curchannel address of the associated channel pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool associate_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ session_param_t **cursession,
+ channel_param_t **curchannel);
+/**
+ * REQUEST: new channel (cnew) assignment
+ *
+ * @param[in] query_param structured query
+ * @param[in] sessionlist session list pointer
+ * @param[in] auxtrans auxiliary transport
+ * @param[in] target requested target pointer
+ * @param[in,out] cursession address of the associated/opened session pointer
+ * @param[in,out] curchannel address of the associated/opened channel pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool open_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ auxtrans_param_t auxtrans,
+ target_param_t *target,
+ session_param_t **cursession,
+ channel_param_t **curchannel);
+
+/**
+ * REQUEST: channel close (cclose)
+ *
+ * @param[in] query_param structured query
+ * @param[in] sessionlist session list pointer
+ * @param[in,out] cursession address of the session pointer of deleting channel
+ * @param[in,out] curchannel address of the deleting channel pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool close_channel( query_param_t query_param,
+ sessionlist_param_t *sessionlist,
+ session_param_t **cursession,
+ channel_param_t **curchannel);
+
+/**
+ * REQUEST: view-window (fsiz)
+ *
+ * @param[in] query_param structured query
+ * @param[in] target requested target pointer
+ * @param[in,out] cursession associated session pointer
+ * @param[in,out] curchannel associated channel pointer
+ * @param[out] msgqueue address of the message queue pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool gene_JPIPstream( query_param_t query_param,
+ target_param_t *target,
+ session_param_t *cursession,
+ channel_param_t *curchannel,
+ msgqueue_param_t **msgqueue);
+
+#endif /* !JPIP_PARSER_H_ */
diff --git a/src/lib/openjpip/jpipstream_manager.c b/src/lib/openjpip/jpipstream_manager.c
new file mode 100644
index 00000000..8cb2a77f
--- /dev/null
+++ b/src/lib/openjpip/jpipstream_manager.c
@@ -0,0 +1,120 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "jpipstream_manager.h"
+#include "jp2k_encoder.h"
+#include "jp2k_decoder.h"
+#include "ihdrbox_manager.h"
+#include "j2kheader_manager.h"
+
+Byte_t * update_JPIPstream( Byte_t *newstream, OPJ_SIZE_T newstreamlen, Byte_t *cache_stream, OPJ_SIZE_T *streamlen)
+{
+ Byte_t *stream = (Byte_t *)malloc( (*streamlen)+newstreamlen);
+ if( *streamlen > 0)
+ memcpy( stream, cache_stream, *streamlen);
+ memcpy( stream+(*streamlen), newstream, newstreamlen);
+ *streamlen += newstreamlen;
+
+ if(cache_stream)
+ free( cache_stream);
+
+ return stream;
+}
+
+void save_codestream( Byte_t *codestream, OPJ_SIZE_T streamlen, const char *fmt)
+{
+ time_t timer;
+ struct tm *t_st;
+ char filename[20];
+ FILE *fp;
+
+ time(&timer);
+ t_st = localtime( &timer);
+
+ sprintf( filename, "%4d%02d%02d%02d%02d%02d.%.3s", t_st->tm_year+1900, t_st->tm_mon+1, t_st->tm_mday, t_st->tm_hour, t_st->tm_min, t_st->tm_sec, fmt);
+
+ fp = fopen( filename, "wb");
+ if( fwrite( codestream, streamlen, 1, fp) != 1)
+ fprintf( stderr, "Error: failed to write codestream to file %s\n", filename);
+ fclose( fp);
+}
+
+
+Byte_t * jpipstream_to_pnm( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn, int fw, int fh, ihdrbox_param_t **ihdrbox)
+{
+ Byte_t *pnmstream;
+ Byte_t *j2kstream; /* j2k or jp2 codestream */
+ Byte8_t j2klen;
+ FILE *fp;
+ const char j2kfname[] = "tmp.j2k";
+
+ j2kstream = recons_j2k( msgqueue, jpipstream, csn, fw, fh, &j2klen);
+
+ fp = fopen( j2kfname, "w+b");
+ fwrite( j2kstream, j2klen, 1, fp);
+ free( j2kstream);
+ fseek( fp, 0, SEEK_SET);
+
+ pnmstream = j2k_to_pnm( fp, ihdrbox);
+
+ fclose( fp);
+ remove( j2kfname);
+
+ return pnmstream;
+}
+
+ihdrbox_param_t * get_SIZ_from_jpipstream( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn)
+{
+ ihdrbox_param_t *ihdrbox;
+ Byte_t *j2kstream;
+ Byte8_t j2klen;
+ SIZmarker_param_t SIZ;
+
+ j2kstream = recons_j2kmainhead( msgqueue, jpipstream, csn, &j2klen);
+ if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, NULL)){
+ free( j2kstream);
+ return NULL;
+ }
+
+ ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t));
+
+ ihdrbox->width = SIZ.Xsiz;
+ ihdrbox->height = SIZ.Ysiz;
+ ihdrbox->nc = SIZ.Csiz;
+ ihdrbox->bpc = SIZ.Ssiz[0];
+
+ free( j2kstream);
+
+ return ihdrbox;
+}
diff --git a/src/lib/openjpip/jpipstream_manager.h b/src/lib/openjpip/jpipstream_manager.h
new file mode 100644
index 00000000..5328be62
--- /dev/null
+++ b/src/lib/openjpip/jpipstream_manager.h
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 "byte_manager.h"
+#include "msgqueue_manager.h"
+#include "ihdrbox_manager.h"
+
+Byte_t * update_JPIPstream( Byte_t *newstream, OPJ_SIZE_T newstreamlen, Byte_t *cache_stream, OPJ_SIZE_T *streamlen);
+
+void save_codestream( Byte_t *codestream, OPJ_SIZE_T streamlen, const char *fmt);
+
+Byte_t * jpipstream_to_pnm( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn, int fw, int fh, ihdrbox_param_t **ihdrbox);
+
+ihdrbox_param_t * get_SIZ_from_jpipstream( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn);
diff --git a/src/lib/openjpip/manfbox_manager.c b/src/lib/openjpip/manfbox_manager.c
new file mode 100644
index 00000000..37472461
--- /dev/null
+++ b/src/lib/openjpip/manfbox_manager.c
@@ -0,0 +1,115 @@
+/*
+ * $Id: manfbox_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "manfbox_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+manfbox_param_t * gene_manfbox( box_param_t *box)
+{
+ manfbox_param_t *manf; /* manifest parameters */
+ boxheader_param_t *bh; /* current box pointer */
+ boxheader_param_t *last; /* last boxheader pointer of the list */
+ OPJ_OFF_T pos; /* current position in manf_box contents; */
+
+ manf = ( manfbox_param_t *)malloc( sizeof( manfbox_param_t));
+
+ pos = 0;
+ manf->first = last = NULL;
+
+ while( (OPJ_SIZE_T)pos < get_DBoxlen( box)){
+
+ bh = gene_childboxheader( box, pos);
+ pos += bh->headlen;
+
+ /* insert into the list */
+ if( manf->first)
+ last->next = bh;
+ else
+ manf->first = bh;
+ last = bh;
+ }
+ return manf;
+}
+
+void delete_manfbox( manfbox_param_t **manf)
+{
+ boxheader_param_t *bhPtr, *bhNext;
+
+ bhPtr = (*manf)->first;
+ while( bhPtr != NULL){
+ bhNext = bhPtr->next;
+#ifndef SERVER
+ /* fprintf( logstream, "local log: boxheader %.4s deleted!\n", bhPtr->type); */
+#endif
+ free(bhPtr);
+ bhPtr = bhNext;
+ }
+ free( *manf);
+}
+
+void print_manfbox( manfbox_param_t *manf)
+{
+ boxheader_param_t *ptr;
+
+ ptr = manf->first;
+ while( ptr != NULL){
+ print_boxheader( ptr);
+ ptr=ptr->next;
+ }
+}
+
+boxheader_param_t * search_boxheader( const char type[], manfbox_param_t *manf)
+{
+ boxheader_param_t *found;
+
+ found = manf->first;
+
+ while( found != NULL){
+
+ if( strncmp( type, found->type, 4) == 0)
+ return found;
+
+ found = found->next;
+ }
+ fprintf( FCGI_stderr, "Error: Boxheader %s not found\n", type);
+
+ return NULL;
+}
diff --git a/src/lib/openjpip/manfbox_manager.h b/src/lib/openjpip/manfbox_manager.h
new file mode 100644
index 00000000..ed4189e0
--- /dev/null
+++ b/src/lib/openjpip/manfbox_manager.h
@@ -0,0 +1,81 @@
+/*
+ * $Id: manfbox_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 MANFBOX_MANAGER_H_
+# define MANFBOX_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+#include "boxheader_manager.h"
+
+
+/** manifest box parameters*/
+/** I.3.2.3 Manifest box*/
+typedef struct manfbox_param{
+ boxheader_param_t *first; /**< top of the box header list*/
+} manfbox_param_t;
+
+
+/**
+ * generate manifest box
+ *
+ * @param[in] box pointer to the reference manf box
+ * @return generated manfbox
+ */
+manfbox_param_t * gene_manfbox( box_param_t *box);
+
+
+/**
+ * delete manifest box
+ *
+ * @param[in,out] manf addressof the manfbox pointer
+ */
+void delete_manfbox( manfbox_param_t **manf);
+
+
+/**
+ * print manf box parameters
+ *
+ * @param[in] manf manf box pointer
+ */
+void print_manfbox( manfbox_param_t *manf);
+
+
+/**
+ * search a boxheader by box type from manifest box
+ *
+ * @param[in] type box type
+ * @param[in] manf manf box pointer
+ * @return found box pointer
+ */
+boxheader_param_t * search_boxheader( const char type[], manfbox_param_t *manf);
+
+
+#endif /* !MANFBOX_MANAGER_H_ */
diff --git a/src/lib/openjpip/marker_manager.c b/src/lib/openjpip/marker_manager.c
new file mode 100644
index 00000000..766ecd6e
--- /dev/null
+++ b/src/lib/openjpip/marker_manager.c
@@ -0,0 +1,68 @@
+/*
+ * $Id: marker_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 "marker_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+marker_param_t set_marker( codestream_param_t cs, Byte2_t code, OPJ_OFF_T offset, Byte2_t length)
+{
+ marker_param_t mkr;
+
+ mkr.cs = cs;
+ mkr.code = code;
+ mkr.offset = offset;
+ mkr.length = length;
+
+ return mkr;
+}
+
+
+Byte_t fetch_marker1byte( marker_param_t marker, OPJ_OFF_T offset)
+{
+ return fetch_codestream1byte( &(marker.cs), marker.offset+offset);
+}
+
+Byte2_t fetch_marker2bytebigendian( marker_param_t marker, OPJ_OFF_T offset)
+{
+ return fetch_codestream2bytebigendian( &(marker.cs), marker.offset+offset);
+}
+
+Byte4_t fetch_marker4bytebigendian( marker_param_t marker, OPJ_OFF_T offset)
+{
+ return fetch_codestream4bytebigendian( &(marker.cs), marker.offset+offset);
+}
diff --git a/src/lib/openjpip/marker_manager.h b/src/lib/openjpip/marker_manager.h
new file mode 100644
index 00000000..68ea2a8b
--- /dev/null
+++ b/src/lib/openjpip/marker_manager.h
@@ -0,0 +1,87 @@
+/*
+ * $Id: marker_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 MARKER_MANAGER_H_
+# define MARKER_MANAGER_H_
+
+#include "codestream_manager.h"
+
+
+/** Marker parameters*/
+typedef struct marker_param{
+ codestream_param_t cs; /**< corresponding codestream*/
+ Byte2_t code; /**< marker code*/
+ OPJ_OFF_T offset; /**< offset relative to the start of the codestream ( including the length parameter but not the marker itself)*/
+ Byte2_t length; /**< marker segment length*/
+} marker_param_t;
+
+
+/**
+ * set marker parameters from inputs
+ *
+ * @param[in] cs marker code
+ * @param[in] code marker code
+ * @param[in] offset offset in the codestream
+ * @param[in] length marker segment length
+ * @return structure of generated marker parameters
+ */
+marker_param_t set_marker( codestream_param_t cs, Byte2_t code, OPJ_OFF_T offset, Byte2_t length);
+
+
+/**
+ * fetch marker content 1-bytes of data in file stream
+ *
+ * @param[in] marker marker structure
+ * @param[in] offset start Byte position in marker
+ * @param[in] size Byte length
+ * @return fetched code
+ */
+Byte_t fetch_marker1byte( marker_param_t marker, OPJ_OFF_T offset);
+
+/**
+ * fetch marker content 2-byte big endian Byte codes in file stream
+ *
+ * @param[in] marker marker structure
+ * @param[in] offset start Byte position in marker
+ * @return fetched code
+ */
+Byte2_t fetch_marker2bytebigendian( marker_param_t marker, OPJ_OFF_T offset);
+
+/**
+ * fetch marker content 4-byte big endian Byte codes in file stream
+ *
+ * @param[in] marker marker structure
+ * @param[in] offset start Byte position in marker
+ * @return fetched code
+ */
+Byte4_t fetch_marker4bytebigendian( marker_param_t marker, OPJ_OFF_T offset);
+
+
+#endif /* !MARKER_MANAGER_H_ */
diff --git a/src/lib/openjpip/metadata_manager.c b/src/lib/openjpip/metadata_manager.c
new file mode 100644
index 00000000..12b61efc
--- /dev/null
+++ b/src/lib/openjpip/metadata_manager.c
@@ -0,0 +1,253 @@
+/*
+ * $Id: metadata_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 "metadata_manager.h"
+#include "opj_inttypes.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+metadatalist_param_t * gene_metadatalist(void)
+{
+ metadatalist_param_t *list;
+
+ list = (metadatalist_param_t *)malloc( sizeof(metadatalist_param_t));
+
+ list->first = NULL;
+ list->last = NULL;
+
+ return list;
+}
+
+metadatalist_param_t * const_metadatalist( int fd)
+{
+ metadatalist_param_t *metadatalist;
+ metadata_param_t *metabin;
+ boxlist_param_t *toplev_boxlist;
+ box_param_t *box, *next;
+ placeholderlist_param_t *phldlist;
+ placeholder_param_t *phld;
+ Byte8_t idx;
+ Byte8_t filesize;
+
+ if(!(filesize = (Byte8_t)get_filesize( fd)))
+ return NULL;
+
+ if( !(toplev_boxlist = get_boxstructure( fd, 0, filesize))){
+ fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n");
+ return NULL;
+ }
+
+ phldlist = gene_placeholderlist();
+ metadatalist = gene_metadatalist();
+
+ box = toplev_boxlist->first;
+ idx = 0;
+ while( box){
+ next = box->next;
+ if( strncmp( box->type, "jP ",4)!=0 && strncmp( box->type, "ftyp",4)!=0 && strncmp( box->type, "jp2h",4)!=0){
+ boxlist_param_t *boxlist = NULL;
+ boxcontents_param_t *boxcontents = NULL;
+
+ phld = gene_placeholder( box, ++idx);
+ insert_placeholder_into_list( phld, phldlist);
+
+ boxlist = get_boxstructure( box->fd, get_DBoxoff( box), get_DBoxlen(box));
+ if( !boxlist)
+ boxcontents = gene_boxcontents( get_DBoxoff( box), get_DBoxlen(box));
+
+ delete_box_in_list( &box, toplev_boxlist);
+ metabin = gene_metadata( idx, boxlist, NULL, boxcontents);
+ insert_metadata_into_list( metabin, metadatalist);
+ }
+ box = next;
+ }
+
+ metabin = gene_metadata( 0, toplev_boxlist, phldlist, NULL);
+ insert_metadata_into_list( metabin, metadatalist);
+
+ return metadatalist;
+}
+
+void delete_metadatalist( metadatalist_param_t **list)
+{
+ metadata_param_t *ptr, *next;
+
+ ptr = (*list)->first;
+
+ while( ptr != NULL){
+ next=ptr->next;
+ delete_metadata( &ptr);
+ ptr=next;
+ }
+ free( *list);
+}
+
+metadata_param_t * gene_metadata( Byte8_t idx, boxlist_param_t *boxlist, placeholderlist_param_t *phldlist, boxcontents_param_t *boxcontents)
+{
+ metadata_param_t *bin;
+
+ bin = (metadata_param_t *)malloc( sizeof(metadata_param_t));
+ bin->idx = idx;
+ bin->boxlist = boxlist;
+ bin->placeholderlist = phldlist;
+ bin->boxcontents = boxcontents;
+ bin->next = NULL;
+
+ return bin;
+}
+
+void delete_metadata( metadata_param_t **metadata)
+{
+ delete_boxlist( &((*metadata)->boxlist));
+ delete_placeholderlist( &((*metadata)->placeholderlist));
+ if((*metadata)->boxcontents)
+ free((*metadata)->boxcontents);
+#ifndef SERVER
+ /* fprintf( logstream, "local log: Metadata-bin: %d deleted\n", (*metadata)->idx);*/
+#endif
+ free( *metadata);
+}
+
+void insert_metadata_into_list( metadata_param_t *metabin, metadatalist_param_t *metadatalist)
+{
+ if( metadatalist->first)
+ metadatalist->last->next = metabin;
+ else
+ metadatalist->first = metabin;
+ metadatalist->last = metabin;
+}
+
+void print_metadata( metadata_param_t *metadata)
+{
+ boxcontents_param_t *boxcont;
+ fprintf( logstream, "metadata-bin %" PRIu64 " info:\n", metadata->idx);
+ print_allbox( metadata->boxlist);
+ print_allplaceholder( metadata->placeholderlist);
+
+ boxcont = metadata->boxcontents;
+ if( boxcont)
+ fprintf( logstream, "box contents:\n"
+ "\t offset: %" PRId64 " %#" PRIx64 "\n"
+ "\t length: %" PRId64 " %#" PRIx64 "\n", boxcont->offset,
+ boxcont->offset, boxcont->length, boxcont->length);
+}
+
+void print_allmetadata( metadatalist_param_t *list)
+{
+ metadata_param_t *ptr;
+
+ fprintf( logstream, "all metadata info: \n");
+ ptr = list->first;
+ while( ptr != NULL){
+ print_metadata( ptr);
+ ptr=ptr->next;
+ }
+}
+
+boxcontents_param_t * gene_boxcontents( OPJ_OFF_T offset, OPJ_SIZE_T length)
+{
+ boxcontents_param_t *contents;
+
+ contents = (boxcontents_param_t *)malloc( sizeof(boxcontents_param_t));
+
+ contents->offset = offset;
+ contents->length = length;
+
+ return contents;
+}
+
+metadata_param_t * search_metadata( Byte8_t idx, metadatalist_param_t *list)
+{
+ metadata_param_t *found;
+
+ found = list->first;
+
+ while( found){
+
+ if( found->idx == idx)
+ return found;
+
+ found = found->next;
+ }
+ return NULL;
+}
+
+Byte8_t search_metadataidx( char boxtype[4], metadatalist_param_t *list)
+{
+ /* MM FIXME: what is the return type of this function ?
+ Byte8_t or int ? */
+ metadata_param_t *ptr;
+ int i;
+
+ for( i=0; i<4; i++)
+ if( boxtype[i] == '_')
+ boxtype[i] = ' ';
+
+ ptr = list->first;
+ while( ptr){
+ if( ptr->boxlist){
+ box_param_t *box = ptr->boxlist->first;
+ while( box){
+ if( strncmp ( boxtype, box->type, 4) == 0)
+ return ptr->idx;
+ box = box->next;
+ }
+ }
+ ptr = ptr->next;
+ }
+
+ ptr = list->first;
+ while( ptr){
+ if( ptr->placeholderlist){
+ placeholder_param_t *phld = ptr->placeholderlist->first;
+ while( phld){
+ if( strncmp ( boxtype, (char *)phld->OrigBH+4, 4) == 0){
+ return phld->OrigID;
+ }
+ phld = phld->next;
+ }
+ }
+ ptr = ptr->next;
+ }
+ return (Byte8_t)-1;
+}
diff --git a/src/lib/openjpip/metadata_manager.h b/src/lib/openjpip/metadata_manager.h
new file mode 100644
index 00000000..089b19a5
--- /dev/null
+++ b/src/lib/openjpip/metadata_manager.h
@@ -0,0 +1,151 @@
+/*
+ * $Id: metadata_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 METADATA_MANAGER_H_
+#define METADATA_MANAGER_H_
+
+#include "box_manager.h"
+#include "placeholder_manager.h"
+
+typedef struct boxcontents_param{
+ OPJ_OFF_T offset; /**< byte position of the box contents in the file*/
+ Byte8_t length; /**< length of the box contents*/
+} boxcontents_param_t;
+
+/** metadata-bin parameters*/
+typedef struct metadata_param{
+ Byte8_t idx; /**< index number*/
+ boxlist_param_t *boxlist; /**< box list*/
+ placeholderlist_param_t *placeholderlist; /**< placeholder box list*/
+ boxcontents_param_t *boxcontents; /**< box contens in case of no boxlist and placeholderlist*/
+ struct metadata_param *next; /**< pointer to the next metadata-bin*/
+} metadata_param_t;
+
+/** metadata-bin list parameters*/
+typedef struct metadatalist_param{
+ metadata_param_t *first; /**< first metadata-bin pointer of the list*/
+ metadata_param_t *last; /**< last metadata-bin pointer of the list*/
+} metadatalist_param_t;
+
+
+/**
+ * generate a metadata list
+ *
+ * @return pointer to the generated metadata list
+ */
+metadatalist_param_t * gene_metadatalist(void);
+
+
+/**
+ * construct metadata-bin list of JP2 file
+ *
+ * @param[in] fd file descriptor
+ * @return pointer to the generated metadata-bin list
+ */
+metadatalist_param_t * const_metadatalist( int fd);
+
+
+/**
+ * delete metadata list
+ *
+ * @param[in,out] list address of the metadata list pointer
+ */
+void delete_metadatalist( metadatalist_param_t **list);
+
+
+/**
+ * generate a metadata bin
+ *
+ * @param[in] idx metadata-bin index
+ * @param[in] boxlist box list pointer
+ * @param[in] phldlist placeholder list pointer
+ * @param[in] boxcontents boxcontents pointer
+ * @return pointer to the generated metadata bin
+ */
+metadata_param_t * gene_metadata( Byte8_t idx, boxlist_param_t *boxlist, placeholderlist_param_t *phldlist, boxcontents_param_t *boxcontents);
+
+/**
+ * delete a metadata bin
+ *
+ * @param[in,out] metadata address of the deleting metadata bin pointer
+ */
+void delete_metadata( metadata_param_t **metadata);
+
+/**
+ * generate box contents
+ *
+ * @return pointer to the box contents
+ */
+boxcontents_param_t * gene_boxcontents( OPJ_OFF_T offset, OPJ_SIZE_T length);
+
+/**
+ * print metadata-bin parameters
+ *
+ * @param[in] metadata metadata-bin pointer
+ */
+void print_metadata( metadata_param_t *metadata);
+
+/**
+ * print all metadata parameters
+ *
+ * @param[in] metadatalist metadata list pointer
+ */
+void print_allmetadata( metadatalist_param_t *list);
+
+
+/**
+ * search a metadata bin by index
+ *
+ * @param[in] idx index
+ * @param[in] list metadata-bin list pointer
+ * @return found metadata-bin pointer
+ */
+metadata_param_t * search_metadata( Byte8_t idx, metadatalist_param_t *list);
+
+
+/**
+ * search a metadata index by box-type
+ *
+ * @param[in] boxtype box-type
+ * @param[in] list metadata-bin list pointer
+ * @return found metadata-bin index, if not found, -1
+ */
+Byte8_t search_metadataidx( char boxtype[4], metadatalist_param_t *list);
+
+
+/**
+ * insert a metadata-bin into list
+ *
+ * @param[in] metabin metadata-bin pointer
+ * @param[in] metadatalist metadata list pointer
+ */
+void insert_metadata_into_list( metadata_param_t *metabin, metadatalist_param_t *metadatalist);
+
+#endif /* !METADATA_MANAGER_H_ */
diff --git a/src/lib/openjpip/mhixbox_manager.c b/src/lib/openjpip/mhixbox_manager.c
new file mode 100644
index 00000000..b311126b
--- /dev/null
+++ b/src/lib/openjpip/mhixbox_manager.c
@@ -0,0 +1,141 @@
+/*
+ * $Id: mhixbox_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "mhixbox_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+
+mhixbox_param_t * gene_mhixbox( box_param_t *box)
+{
+ mhixbox_param_t *mhix;
+ markeridx_param_t *mkridx, *lastmkidx;
+ OPJ_OFF_T pos = 0;
+
+ mhix = ( mhixbox_param_t *)malloc( sizeof( mhixbox_param_t));
+
+ mhix->tlen = fetch_DBox8bytebigendian( box, (pos+=8)-8);
+
+ mhix->first = lastmkidx = NULL;
+ while( (OPJ_SIZE_T)pos < get_DBoxlen( box)){
+
+ mkridx = ( markeridx_param_t *)malloc( sizeof( markeridx_param_t));
+ mkridx->code = fetch_DBox2bytebigendian( box, (pos+=2)-2);
+ mkridx->num_remain = fetch_DBox2bytebigendian( box, (pos+=2)-2);
+ mkridx->offset = (OPJ_OFF_T)fetch_DBox8bytebigendian( box, (pos+=8)-8);
+ mkridx->length = fetch_DBox2bytebigendian( box, (pos+=2)-2);
+ mkridx->next = NULL;
+
+ if( mhix->first)
+ lastmkidx->next = mkridx;
+ else
+ mhix->first = mkridx;
+ lastmkidx = mkridx;
+ }
+ return mhix;
+}
+
+
+markeridx_param_t * search_markeridx( Byte2_t code, mhixbox_param_t *mhix)
+{
+ markeridx_param_t *found;
+
+ found = mhix->first;
+
+ while( found != NULL){
+
+ if( code == found->code)
+ return found;
+
+ found = found->next;
+ }
+ fprintf( FCGI_stderr, "Error: Marker index %#x not found\n", code);
+
+ return NULL;
+}
+
+
+void print_mhixbox( mhixbox_param_t *mhix)
+{
+ markeridx_param_t *ptr;
+
+ fprintf( logstream, "mhix box info:\n");
+ fprintf( logstream, "\t tlen: %#" PRIx64 "\n", mhix->tlen);
+
+ ptr = mhix->first;
+ while( ptr != NULL){
+ fprintf( logstream, "marker index info:\n"
+ "\t code: %#x\n"
+ "\t num_remain: %#x\n"
+ "\t offset: %#" PRIx64 "\n"
+ "\t length: %#x\n", ptr->code, ptr->num_remain, ptr->offset, ptr->length);
+ ptr=ptr->next;
+ }
+}
+
+
+void print_markeridx( markeridx_param_t *markeridx)
+{
+ fprintf( logstream, "marker index info:\n"
+ "\t code: %#x\n"
+ "\t num_remain: %#x\n"
+ "\t offset: %#" PRIx64 "\n"
+ "\t length: %#x\n", markeridx->code, markeridx->num_remain, markeridx->offset, markeridx->length);
+}
+
+
+void delete_mhixbox( mhixbox_param_t **mhix)
+{
+ markeridx_param_t *mkPtr, *mkNext;
+
+ mkPtr = (*mhix)->first;
+ while( mkPtr != NULL){
+ mkNext=mkPtr->next;
+#ifndef SERVER
+ /* fprintf( logstream, "local log: marker index %#x deleted!\n", mkPtr->code); */
+#endif
+ free(mkPtr);
+ mkPtr=mkNext;
+ }
+ free(*mhix);
+}
+
+
diff --git a/src/lib/openjpip/mhixbox_manager.h b/src/lib/openjpip/mhixbox_manager.h
new file mode 100644
index 00000000..5905b25f
--- /dev/null
+++ b/src/lib/openjpip/mhixbox_manager.h
@@ -0,0 +1,102 @@
+/*
+ * $Id: mhixbox_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 MHIXBOX_MANAGER_H_
+# define MHIXBOX_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+
+/** Marker index parameters*/
+typedef struct markeridx_param{
+ Byte2_t code; /**< marker code*/
+ Byte2_t num_remain; /**< remining number of the same marker index segments listed immediately*/
+ OPJ_OFF_T offset; /**< offset relative to the start of the*/
+ /**codestream ( including the length*/
+ /**parameter but not the marker itself)*/
+ Byte2_t length; /**< marker segment length*/
+ struct markeridx_param *next; /**< pointer to the next markeridx*/
+} markeridx_param_t;
+
+
+
+/** header index table box parameters*/
+/** I.3.2.4.3 Header Index Table box*/
+typedef struct mhixbox_param{
+ Byte8_t tlen; /**< length ( total length of the main*/
+ /**header or of the first tile-part header)*/
+ markeridx_param_t *first; /**< first marker index pointer of the list*/
+} mhixbox_param_t;
+
+
+
+/**
+ * generate mhix box
+ *
+ * @param[in] box pointer to the reference mhix box
+ * @return generated mhixbox pointer
+ */
+mhixbox_param_t * gene_mhixbox( box_param_t *box);
+
+
+/**
+ * search a marker index by marker code from mhix box
+ *
+ * @param[in] code marker code
+ * @param[in] mhix mhix box pointer
+ * @return found marker index pointer
+ */
+markeridx_param_t * search_markeridx( Byte2_t code, mhixbox_param_t *mhix);
+
+
+/**
+ * print mhix box parameters
+ *
+ * @param[in] mhix mhix box pointer
+ */
+void print_mhixbox( mhixbox_param_t *mhix);
+
+
+/**
+ * print marker index parameters
+ *
+ * @param[in] markeridx marker index pointer
+ */
+void print_markeridx( markeridx_param_t *markeridx);
+
+
+/**
+ * delete mhix box
+ *
+ * @param[in,out] mhix address of the mhix box pointer
+ */
+void delete_mhixbox( mhixbox_param_t **mhix);
+
+#endif /* !MHIXBOX_MANAGER_H_ */
diff --git a/src/lib/openjpip/msgqueue_manager.c b/src/lib/openjpip/msgqueue_manager.c
new file mode 100644
index 00000000..29b64a26
--- /dev/null
+++ b/src/lib/openjpip/msgqueue_manager.c
@@ -0,0 +1,762 @@
+/*
+ * $Id: msgqueue_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include "msgqueue_manager.h"
+#include "metadata_manager.h"
+#include "index_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel)
+{
+ msgqueue_param_t *msgqueue;
+
+ msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t));
+
+ msgqueue->first = NULL;
+ msgqueue->last = NULL;
+
+ msgqueue->stateless = stateless;
+ msgqueue->cachemodel = cachemodel;
+
+ return msgqueue;
+}
+
+void delete_msgqueue( msgqueue_param_t **msgqueue)
+{
+ message_param_t *ptr, *next;
+
+ if( !(*msgqueue))
+ return;
+
+ ptr = (*msgqueue)->first;
+
+ while( ptr){
+ next = ptr->next;
+ free( ptr);
+ ptr = next;
+ }
+ if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
+ delete_cachemodel( &((*msgqueue)->cachemodel));
+
+ free(*msgqueue);
+}
+
+void print_msgqueue( msgqueue_param_t *msgqueue)
+{
+ message_param_t *ptr;
+ static const char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non",
+ "Tile", "Ext-Tile", "Main", "non", "Meta"};
+
+ if( !msgqueue)
+ return;
+
+ fprintf( logstream, "message queue:\n");
+ ptr = msgqueue->first;
+
+ while( ptr){
+ fprintf( logstream, "\t class_id: %" PRId64 " %s\n", ptr->class_id, message_class[ptr->class_id]);
+ fprintf( logstream, "\t in_class_id: %" PRId64 "\n", ptr->in_class_id );
+ fprintf( logstream, "\t csn: %" PRId64 "\n", ptr->csn );
+ fprintf( logstream, "\t bin_offset: %#" PRIx64 "\n", ptr->bin_offset );
+ fprintf( logstream, "\t length: %#" PRIx64 "\n", ptr->length );
+ if( ptr->class_id%2)
+ fprintf( logstream, "\t aux: %" PRId64 "\n", ptr->aux );
+ fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
+ if( ptr->phld)
+ print_placeholder( ptr->phld);
+ else
+ fprintf( logstream, "\t res_offset: %#" PRIx64 "\n", ptr->res_offset );
+ fprintf( logstream, "\n");
+
+ ptr = ptr->next;
+ }
+}
+
+void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
+
+void enqueue_mainheader( msgqueue_param_t *msgqueue)
+{
+ cachemodel_param_t *cachemodel;
+ target_param_t *target;
+ index_param_t *codeidx;
+ message_param_t *msg;
+
+ cachemodel = msgqueue->cachemodel;
+ target = cachemodel->target;
+ codeidx = target->codeidx;
+
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+
+ msg->last_byte = true;
+ msg->in_class_id = 0;
+ msg->class_id = MAINHEADER_MSG;
+ assert( target->csn >= 0 );
+ msg->csn = (Byte8_t)target->csn;
+ msg->bin_offset = 0;
+ msg->length = codeidx->mhead_length;
+ msg->aux = 0; /* non exist*/
+ msg->res_offset = codeidx->offset;
+ msg->phld = NULL;
+ msg->next = NULL;
+
+ enqueue_message( msg, msgqueue);
+
+ cachemodel->mhead_model = true;
+}
+
+void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
+{
+ cachemodel_param_t *cachemodel;
+ target_param_t *target;
+ index_param_t *codeidx;
+ message_param_t *msg;
+
+ cachemodel = msgqueue->cachemodel;
+ target = cachemodel->target;
+ codeidx = target->codeidx;
+
+ if( !cachemodel->th_model[ tile_id]){
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+ msg->last_byte = true;
+ assert( tile_id >= 0 );
+ msg->in_class_id = (Byte8_t)tile_id;
+ msg->class_id = TILE_HEADER_MSG;
+ assert( target->csn >= 0 );
+ msg->csn = (Byte8_t)target->csn;
+ msg->bin_offset = 0;
+ msg->length = codeidx->tileheader[tile_id]->tlen-2; /* SOT marker segment is removed*/
+ msg->aux = 0; /* non exist*/
+ msg->res_offset = codeidx->offset + (OPJ_OFF_T)get_elemOff(codeidx->tilepart, 0, (Byte8_t)tile_id) + 2; /* skip SOT marker seg*/
+ msg->phld = NULL;
+ msg->next = NULL;
+
+ enqueue_message( msg, msgqueue);
+ cachemodel->th_model[ tile_id] = true;
+ }
+}
+
+void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue)
+{
+ cachemodel_param_t *cachemodel;
+ target_param_t *target;
+ bool *tp_model;
+ Byte8_t numOftparts; /* num of tile parts par tile*/
+ Byte8_t numOftiles;
+ index_param_t *codeidx;
+ faixbox_param_t *tilepart;
+ message_param_t *msg;
+ Byte8_t binOffset, binLength, class_id;
+ Byte8_t i;
+
+ cachemodel = msgqueue->cachemodel;
+ target = cachemodel->target;
+ codeidx = target->codeidx;
+ tilepart = codeidx->tilepart;
+
+ numOftparts = get_nmax( tilepart);
+ numOftiles = get_m( tilepart);
+
+ class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
+
+ if( /*tile_id < 0 ||*/ numOftiles <= (Byte8_t)tile_id){
+ fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
+ return;
+ }
+
+ tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
+
+ binOffset=0;
+ for( i=0; i<numOftparts-(Byte8_t)level; i++){
+ binLength = get_elemLen( tilepart, i, tile_id);
+
+ if( !tp_model[i]){
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+
+ msg->last_byte = (i==numOftparts-1);
+ msg->in_class_id = tile_id;
+ msg->class_id = class_id;
+ assert( target->csn >= 0 );
+ msg->csn = (Byte8_t)target->csn;
+ msg->bin_offset = binOffset;
+ msg->length = binLength;
+ msg->aux = numOftparts-i;
+ msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( tilepart, i, tile_id)/*-1*/;
+ msg->phld = NULL;
+ msg->next = NULL;
+
+ enqueue_message( msg, msgqueue);
+
+ tp_model[i] = true;
+ }
+ binOffset += binLength;
+ }
+}
+
+void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
+{
+ cachemodel_param_t *cachemodel;
+ index_param_t *codeidx;
+ faixbox_param_t *precpacket;
+ message_param_t *msg;
+ Byte8_t nmax, binOffset, binLength;
+ int layer_id, numOflayers;
+
+ cachemodel = msgqueue->cachemodel;
+ codeidx = cachemodel->target->codeidx;
+ precpacket = codeidx->precpacket[ comp_id];
+ numOflayers = codeidx->COD.numOflayers;
+
+ nmax = get_nmax(precpacket);
+ assert( nmax < INT_MAX );
+ if( layers < 0)
+ layers = numOflayers;
+ assert( tile_id >= 0 );
+
+ binOffset = 0;
+ for( layer_id = 0; layer_id < layers; layer_id++){
+
+ binLength = get_elemLen( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
+
+ if( !cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id]){
+
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+ msg->last_byte = (layer_id == (numOflayers-1));
+ msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, (int)codeidx->SIZ.XTnum * (int) codeidx->SIZ.YTnum);
+ msg->class_id = PRECINCT_MSG;
+ msg->csn = (Byte8_t)cachemodel->target->csn;
+ msg->bin_offset = binOffset;
+ msg->length = binLength;
+ msg->aux = 0;
+ msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
+ msg->phld = NULL;
+ msg->next = NULL;
+
+ enqueue_message( msg, msgqueue);
+
+ cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id] = true;
+ }
+ binOffset += binLength;
+ }
+}
+
+/* MM FIXME: each params is coded on int, this is really not clear from the specs what it should be */
+Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles)
+{
+ return (Byte8_t)(t + (c + s * num_components ) * num_tiles);
+}
+
+void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
+void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
+void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
+
+void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue)
+{
+ metadatalist_param_t *metadatalist;
+ metadata_param_t *metadata;
+ Byte8_t binOffset;
+
+ metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
+ metadata = search_metadata( meta_id, metadatalist);
+
+ if( !metadata){
+ fprintf( FCGI_stderr, "Error: metadata-bin %" PRIu64 " not found\n", meta_id);
+ return;
+ }
+ binOffset = 0;
+
+ if( metadata->boxlist)
+ enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
+
+ if( metadata->placeholderlist)
+ enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
+
+ if( metadata->boxcontents)
+ enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
+
+ msgqueue->last->last_byte = true;
+}
+
+message_param_t * gene_metamsg( Byte8_t meta_id, Byte8_t binoffset, Byte8_t length, OPJ_OFF_T res_offset, placeholder_param_t *phld, Byte8_t csn);
+
+void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
+{
+ box_param_t *box;
+ message_param_t *msg;
+
+ box = boxlist->first;
+ assert( msgqueue->cachemodel->target->csn >= 0);
+ while( box){
+ msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn);
+ enqueue_message( msg, msgqueue);
+
+ *binOffset += box->length;
+ box = box->next;
+ }
+}
+
+void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
+{
+ placeholder_param_t *phld;
+ message_param_t *msg;
+
+ phld = phldlist->first;
+ assert( msgqueue->cachemodel->target->csn >= 0);
+ while( phld){
+ msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, (Byte8_t)msgqueue->cachemodel->target->csn);
+ enqueue_message( msg, msgqueue);
+
+ *binOffset += phld->LBox;
+ phld = phld->next;
+ }
+}
+
+void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
+{
+ message_param_t *msg;
+
+ assert(msgqueue->cachemodel->target->csn >= 0);
+ msg = gene_metamsg( meta_id, *binOffset, boxcontents->length,
+ boxcontents->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn);
+ enqueue_message( msg, msgqueue);
+
+ *binOffset += boxcontents->length;
+}
+
+message_param_t * gene_metamsg( Byte8_t meta_id, Byte8_t binOffset, Byte8_t length, OPJ_OFF_T res_offset, placeholder_param_t *phld, Byte8_t csn)
+{
+ message_param_t *msg;
+
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+
+ msg->last_byte = false;
+ msg->in_class_id = meta_id;
+ msg->class_id = METADATA_MSG;
+ msg->csn = csn;
+ msg->bin_offset = binOffset;
+ msg->length = length;
+ msg->aux = 0; /* non exist*/
+ msg->res_offset = res_offset;
+ msg->phld = phld;
+ msg->next = NULL;
+
+ return msg;
+}
+
+void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
+{
+ if( msgqueue->first)
+ msgqueue->last->next = msg;
+ else
+ msgqueue->first = msg;
+
+ msgqueue->last = msg;
+}
+
+void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd);
+void add_vbas_stream( Byte8_t code, int tmpfd);
+void add_body_stream( message_param_t *msg, int fd, int tmpfd);
+void add_placeholder_stream( placeholder_param_t *phld, int tmpfd);
+
+void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd)
+{
+ message_param_t *msg;
+ Byte8_t class_id, csn;
+ Byte_t bb, c;
+
+ if( !(msgqueue))
+ return;
+
+ msg = msgqueue->first;
+ class_id = (Byte8_t)-1;
+ csn = (Byte8_t)-1;
+ while( msg){
+ if( msg->csn == csn){
+ if( msg->class_id == class_id)
+ bb = 1;
+ else{
+ bb = 2;
+ class_id = msg->class_id;
+ }
+ }
+ else{
+ bb = 3;
+ class_id = msg->class_id;
+ csn = msg->csn;
+ }
+
+ c = msg->last_byte ? 1 : 0;
+
+ add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd);
+
+ if( bb >= 2)
+ add_vbas_stream( class_id, tmpfd);
+ if (bb == 3)
+ add_vbas_stream( csn, tmpfd);
+
+ add_vbas_stream( msg->bin_offset, tmpfd);
+ add_vbas_stream (msg->length, tmpfd);
+
+ if( msg->class_id%2) /* Aux is present only if the id is odd*/
+ add_vbas_stream( msg->aux, tmpfd);
+
+ if( msg->phld)
+ add_placeholder_stream( msg->phld, tmpfd);
+ else
+ add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd);
+
+ msg = msg->next;
+ }
+}
+
+void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd);
+void print_binarycode( Byte8_t n, int segmentlen);
+
+void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd)
+{
+ int bytelength;
+ Byte8_t tmp;
+
+ /* A.2.3 In-class identifiers */
+ /* 7k-3bits, where k is the number of bytes in the VBAS*/
+ bytelength = 1;
+ tmp = in_class_id >> 4;
+ while( tmp){
+ bytelength ++;
+ tmp >>= 7;
+ }
+
+ in_class_id |= (Byte8_t)((((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7));
+
+ add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd);
+}
+
+void add_vbas_stream( Byte8_t code, int tmpfd)
+{
+ int bytelength;
+ Byte8_t tmp;
+
+ bytelength = 1;
+ tmp = code;
+ while( tmp >>= 7)
+ bytelength ++;
+
+ add_vbas_with_bytelen_stream( code, bytelength, tmpfd);
+}
+
+void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd)
+{
+ int n;
+ Byte8_t seg;
+
+ n = bytelength - 1;
+ while( n >= 0) {
+ seg = ( code >> (n*7)) & 0x7f;
+ if( n)
+ seg |= 0x80;
+ if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
+ fprintf( FCGI_stderr, "Error: failed to write vbas\n");
+ return;
+ }
+ n--;
+ }
+}
+
+void add_body_stream( message_param_t *msg, int fd, int tmpfd)
+{
+ Byte_t *data;
+
+ if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
+ fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
+ return;
+ }
+
+ if( write( tmpfd, data, msg->length) < 1){
+ free( data);
+ fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n");
+ return;
+ }
+ free(data);
+}
+
+void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd);
+
+void add_placeholder_stream( placeholder_param_t *phld, int tmpfd)
+{
+ add_bigendian_bytestream( phld->LBox, 4, tmpfd);
+ if( write( tmpfd, phld->TBox, 4) < 1){
+ fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
+ return;
+ }
+ add_bigendian_bytestream( phld->Flags, 4, tmpfd);
+ add_bigendian_bytestream( phld->OrigID, 8, tmpfd);
+
+ if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){
+ fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
+ return;
+ }
+}
+
+void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd)
+{
+ int n;
+ Byte8_t seg;
+
+ n = bytelength - 1;
+ while( n >= 0) {
+ seg = ( code >> (n*8)) & 0xff;
+ if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
+ fprintf( FCGI_stderr, "ERROR: failed to write bigendian_bytestream\n");
+ return;
+ }
+ n--;
+ }
+}
+
+void print_binarycode( Byte8_t n, int segmentlen)
+{
+ char buf[256];
+ int i=0, j, k;
+
+ do{
+ buf[i++] = n%2 ? '1' : '0';
+ }while((n=n/2));
+
+ for( j=segmentlen-1; j>=i; j--)
+ putchar('0');
+
+ for( j=i-1, k=0; j>=0; j--, k++){
+ putchar( buf[j]);
+ if( !((k+1)%segmentlen))
+ printf(" ");
+ }
+ printf("\n");
+}
+
+Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
+Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
+
+void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue)
+{
+ Byte_t *ptr; /* stream pointer*/
+ message_param_t *msg;
+ Byte_t bb, c;
+ Byte8_t class_id, csn;
+
+ class_id = (Byte8_t)-1; /* dummy*/
+ csn = (Byte8_t)-1;
+ ptr = JPIPstream;
+ while( (Byte8_t)(ptr-JPIPstream) < streamlen){
+ msg = (message_param_t *)malloc( sizeof(message_param_t));
+
+ ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
+
+ msg->last_byte = c == 1 ? true : false;
+
+ if( bb >= 2)
+ ptr = parse_vbas( ptr, &class_id);
+
+ msg->class_id = class_id;
+
+ if (bb == 3)
+ ptr = parse_vbas( ptr, &csn);
+ msg->csn = csn;
+
+ ptr = parse_vbas( ptr, &msg->bin_offset);
+ ptr = parse_vbas( ptr, &msg->length);
+
+ if( msg->class_id%2) /* Aux is present only if the id is odd*/
+ ptr = parse_vbas( ptr, &msg->aux);
+ else
+ msg->aux = 0;
+
+ msg->res_offset = ptr-JPIPstream+offset;
+ msg->phld = NULL;
+ msg->next = NULL;
+
+ if(msgqueue->first)
+ msgqueue->last->next = msg;
+ else
+ msgqueue->first = msg;
+ msgqueue->last = msg;
+
+ ptr += msg->length;
+ }
+}
+
+void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
+
+void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
+{
+ message_param_t *msg;
+ (void)streamlen;
+
+ if( metadatalist == NULL)
+ return;
+
+ msg = msgqueue->first;
+ while( msg){
+ if( msg->class_id == METADATA_MSG){
+ metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
+ insert_metadata_into_list( metadata, metadatalist);
+ parse_metadata( metadata, msg, stream+msg->res_offset);
+ }
+ msg = msg->next;
+ }
+}
+
+placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
+
+void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
+{
+ box_param_t *box;
+ placeholder_param_t *phld;
+ char *boxtype = (char *)(datastream+4);
+
+ msg->phld = NULL;
+
+ if( strncmp( boxtype, "phld", 4) == 0){
+ if( !metadata->placeholderlist)
+ metadata->placeholderlist = gene_placeholderlist();
+
+ phld = parse_phld( datastream, msg->length);
+ msg->phld = phld;
+ insert_placeholder_into_list( phld, metadata->placeholderlist);
+ }
+ else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
+ (isalnum(boxtype[2])||isspace(boxtype[2])) &&
+ (isalpha(boxtype[3])||isspace(boxtype[3]))){
+ if( !metadata->boxlist)
+ metadata->boxlist = gene_boxlist();
+
+ box = gene_boxbyOffinStream( datastream, msg->res_offset);
+ insert_box_into_list( box, metadata->boxlist);
+ }
+ else
+ metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
+}
+
+placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
+{
+ placeholder_param_t *phld;
+
+ phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
+
+ phld->LBox = big4( datastream);
+ strcpy( phld->TBox, "phld");
+ phld->Flags = big4( datastream+8);
+ phld->OrigID = big8( datastream+12);
+ phld->OrigBHlen = (Byte_t)(metalength - 20);
+ phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen);
+ memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
+ phld->next = NULL;
+
+ return phld;
+}
+
+Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
+{
+ Byte_t code;
+ Byte_t *ptr;
+
+ ptr = streamptr;
+ code = *(ptr++);
+
+ *bb = (code >> 5) & 3;
+ *c = (code >> 4) & 1;
+
+ *in_class_id = code & 15;
+
+ while(code >> 7){
+ code = *(ptr++);
+ *in_class_id = (*in_class_id << 7) | (code & 0x7f);
+ }
+ return ptr;
+}
+
+Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
+{
+ Byte_t code;
+ Byte_t *ptr;
+
+ *elem = 0;
+ ptr = streamptr;
+ do{
+ code = *(ptr++);
+ *elem = (*elem << 7) | (code & 0x7f);
+ }while(code >> 7);
+
+ return ptr;
+}
+
+void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
+{
+ message_param_t *ptr;
+
+ if( !(*msg))
+ return;
+
+ if( *msg == msgqueue->first)
+ msgqueue->first = (*msg)->next;
+ else{
+ ptr = msgqueue->first;
+ while( ptr->next != *msg){
+ ptr=ptr->next;
+ }
+
+ ptr->next = (*msg)->next;
+
+ if( *msg == msgqueue->last)
+ msgqueue->last = ptr;
+ }
+ free( *msg);
+}
diff --git a/src/lib/openjpip/msgqueue_manager.h b/src/lib/openjpip/msgqueue_manager.h
new file mode 100644
index 00000000..e54f2dc1
--- /dev/null
+++ b/src/lib/openjpip/msgqueue_manager.h
@@ -0,0 +1,188 @@
+/*
+ * $Id: msgqueue_manager.h 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 MSGQUEUE_MANAGER_H_
+# define MSGQUEUE_MANAGER_H_
+
+#include "bool.h"
+#include "byte_manager.h"
+#include "cachemodel_manager.h"
+#include "placeholder_manager.h"
+
+#define PRECINCT_MSG 0
+#define EXT_PRECINCT_MSG 1
+#define TILE_HEADER_MSG 2
+#define TILE_MSG 4
+#define EXT_TILE_MSG 5
+#define MAINHEADER_MSG 6
+#define METADATA_MSG 8
+
+/** message parameters */
+typedef struct message_param{
+ bool last_byte; /**< if message contains the last byte of the data-bin*/
+ Byte8_t in_class_id; /**< in-class identifier A.2.3*/
+ Byte8_t class_id; /**< class identifiers */
+ Byte8_t csn; /**< index of the codestream*/
+ Byte8_t bin_offset; /**< offset of the data in this message from the start of the data-bin*/
+ Byte8_t length; /**< message byte length*/
+ Byte8_t aux; /**<*/
+ OPJ_OFF_T res_offset; /**< offset in the resource*/
+ placeholder_param_t *phld; /**< placeholder pointer in index*/
+ struct message_param *next; /**< pointer to the next message*/
+} message_param_t;
+
+/** message queue parameters */
+typedef struct msgqueue_param{
+ message_param_t *first; /**< first message pointer of the list*/
+ message_param_t *last; /**< last message pointer of the list*/
+ bool stateless; /**< if this is a stateless message queue*/
+ cachemodel_param_t *cachemodel; /**< reference cachemodel pointer*/
+} msgqueue_param_t;
+
+/**
+ * generate message queue
+ *
+ * @param[in] stateless if this is a stateless message queue
+ * @param[in] cachemodel cachemodel pointer
+ * @return generated message queue pointer
+ */
+msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel);
+
+/**
+ * delete message queue
+ *
+ * @param[in] msgqueue address of the message queue pointer
+ */
+void delete_msgqueue( msgqueue_param_t **msgqueue);
+
+/**
+ * delete a message in msgqueue
+ *
+ * @param[in] message address of the deleting message pointer
+ * @param[in] msgqueue message queue pointer
+ */
+void delete_message_in_msgqueue( message_param_t **message, msgqueue_param_t *msgqueue);
+
+/**
+ * print message queue
+ *
+ * @param[in] msgqueue message queue pointer
+ */
+void print_msgqueue( msgqueue_param_t *msgqueue);
+
+
+/**
+ * enqueue main header data-bin into message queue
+ *
+ * @param[in,out] msgqueue message queue pointer
+ */
+void enqueue_mainheader( msgqueue_param_t *msgqueue);
+
+/**
+ * enqueue tile headers data-bin into message queue
+ *
+ * @param[in] tile_id tile id starting from 0
+ * @param[in,out] msgqueue message queue pointer
+ */
+void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue);
+
+/**
+ * enqueue tile data-bin into message queue
+ *
+ * @param[in] tile_id tile id starting from 0
+ * @param[in] level decomposition level
+ * @param[in,out] msgqueue message queue pointer
+ */
+void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue);
+
+/**
+ * enqueue precinct data-bin into message queue
+ *
+ * @param[in] seq_id precinct sequence number within its tile
+ * @param[in] tile_id tile index
+ * @param[in] comp_id component number
+ * @param[in] layers num of layers
+ * @param[in,out] msgqueue message queue
+ */
+void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue);
+
+
+/**
+ * enqueue Metadata-bin into message queue
+ *
+ * @param[in] meta_id metadata-bin id
+ * @param[in,out] msgqueue message queue pointer
+ */
+void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue);
+
+
+/**
+ * reconstruct JPT/JPP-stream from message queue
+ *
+ * @param[in] msgqueue message queue pointer
+ * @param[in] tmpfd file discriptor to write JPT/JPP-stream
+ */
+void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd);
+
+
+/**
+ * parse JPT- JPP- stream to message queue
+ *
+ * @param[in] JPIPstream JPT- JPP- stream data pointer
+ * @param[in] streamlen JPIPstream length
+ * @param[in] offset offset of the stream from the whole beginning
+ * @param[in,out] msgqueue adding message queue pointer
+ */
+void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue);
+
+/**
+ * parse JPT- JPP- stream to message queue
+ *
+ * @param[in] msgqueue reference message queue pointer
+ * @param[in] stream stream data pointer
+ * @param[in] streamlen stream length
+ * @param[in] metadatalist adding metadata list pointer
+ */
+void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist);
+
+/**
+ * compute precinct ID A.3.2.1
+ *
+ * @param[in] t tile index
+ * @param[in] c component index
+ * @param[in] s sequence number
+ * @param[in] num_components total number of components
+ * @param[in] num_tiles total number of tiles
+ * @return precicnt id
+ */
+Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles);
+
+#endif /* !MSGQUEUE_MANAGER_H_ */
diff --git a/src/lib/openjpip/openjpip.c b/src/lib/openjpip/openjpip.c
new file mode 100644
index 00000000..de6293d4
--- /dev/null
+++ b/src/lib/openjpip/openjpip.c
@@ -0,0 +1,450 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include "openjpip.h"
+#include "jpip_parser.h"
+#include "channel_manager.h"
+#include "byte_manager.h"
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#ifdef SERVER
+#include "auxtrans_manager.h"
+#endif
+
+#include <stdio.h>
+#include "dec_clientmsg_handler.h"
+#include "jpipstream_manager.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "jp2k_encoder.h"
+
+#ifdef SERVER
+
+server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport)
+{
+ server_record_t *record = (server_record_t *)malloc( sizeof(server_record_t));
+
+ record->sessionlist = gene_sessionlist();
+ record->targetlist = gene_targetlist();
+ record->auxtrans = init_aux_transport( tcp_auxport, udp_auxport);
+
+ return record;
+}
+
+void terminate_JPIPserver( server_record_t **rec)
+{
+ delete_sessionlist( &(*rec)->sessionlist);
+ delete_targetlist( &(*rec)->targetlist);
+ close_aux_transport( (*rec)->auxtrans);
+
+ free( *rec);
+}
+
+QR_t * parse_querystring( const char *query_string)
+{
+ QR_t *qr;
+
+ qr = (QR_t *)malloc( sizeof(QR_t));
+
+ qr->query = parse_query( query_string);
+ qr->msgqueue = NULL;
+ qr->channel = NULL;
+
+ return qr;
+}
+
+bool process_JPIPrequest( server_record_t *rec, QR_t *qr)
+{
+ target_param_t *target = NULL;
+ session_param_t *cursession = NULL;
+ channel_param_t *curchannel = NULL;
+
+ if( qr->query->target || qr->query->tid){
+ if( !identify_target( *(qr->query), rec->targetlist, &target))
+ return false;
+ }
+
+ if( qr->query->cid){
+ if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
+ return false;
+ qr->channel = curchannel;
+ }
+
+ if( qr->query->cnew != non){
+ if( !open_channel( *(qr->query), rec->sessionlist, rec->auxtrans, target, &cursession, &curchannel))
+ return false;
+ qr->channel = curchannel;
+ }
+
+ if( qr->query->cclose)
+ if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
+ return false;
+
+ if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0 || qr->query->len > 0)
+ if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue))
+ return false;
+
+ return true;
+}
+
+void add_EORmsg( int fd, QR_t *qr);
+
+void send_responsedata( server_record_t *rec, QR_t *qr)
+{
+ int fd;
+ const char tmpfname[] = "tmpjpipstream.jpp";
+ Byte_t *jpipstream;
+ Byte8_t len_of_jpipstream;
+
+ if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){
+ fprintf( FCGI_stderr, "file open error %s", tmpfname);
+ fprintf( FCGI_stdout, "Status: 503\r\n");
+ fprintf( FCGI_stdout, "Reason: Implementation failed\r\n");
+ return;
+ }
+
+ recons_stream_from_msgqueue( qr->msgqueue, fd);
+
+ add_EORmsg( fd, qr); /* needed at least for tcp and udp */
+
+ len_of_jpipstream = (Byte8_t)get_filesize( fd);
+ jpipstream = fetch_bytes( fd, 0, len_of_jpipstream);
+
+ close( fd);
+ remove( tmpfname);
+
+ fprintf( FCGI_stdout, "\r\n");
+
+ if( len_of_jpipstream){
+
+ if( qr->channel)
+ if( qr->channel->aux == tcp || qr->channel->aux == udp){
+ send_responsedata_on_aux( qr->channel->aux==tcp, rec->auxtrans, qr->channel->cid, jpipstream, len_of_jpipstream, 1000); /* 1KB per frame*/
+ return;
+ }
+
+ if( fwrite( jpipstream, len_of_jpipstream, 1, FCGI_stdout) != 1)
+ fprintf( FCGI_stderr, "Error: failed to write jpipstream\n");
+ }
+
+ free( jpipstream);
+
+ return;
+}
+
+void add_EORmsg( int fd, QR_t *qr)
+{
+ unsigned char EOR[3];
+
+ if( qr->channel){
+ EOR[0] = 0x00;
+ EOR[1] = is_allsent( *(qr->channel->cachemodel)) ? 0x01 : 0x02;
+ EOR[2] = 0x00;
+ if( write( fd, EOR, 3) != 3)
+ fprintf( FCGI_stderr, "Error: failed to write EOR message\n");
+ }
+}
+
+void end_QRprocess( server_record_t *rec, QR_t **qr)
+{
+ /* TODO: record client preferences if necessary*/
+ (void)rec; /* unused */
+ delete_query( &((*qr)->query));
+ delete_msgqueue( &((*qr)->msgqueue));
+ free( *qr);
+}
+
+
+void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec)
+{
+ if( query)
+ print_queryparam( *qr->query);
+
+ if( messages)
+ print_msgqueue( qr->msgqueue);
+
+ if( sessions)
+ print_allsession( rec->sessionlist);
+
+ if( targets)
+ print_alltarget( rec->targetlist);
+}
+
+#endif /*SERVER*/
+
+#ifndef SERVER
+
+dec_server_record_t * init_dec_server( int port)
+{
+ dec_server_record_t *record = (dec_server_record_t *)malloc( sizeof(dec_server_record_t));
+
+ record->cachelist = gene_cachelist();
+ record->jpipstream = NULL;
+ record->jpipstreamlen = 0;
+ record->msgqueue = gene_msgqueue( true, NULL);
+ record->listening_socket = open_listeningsocket( (uint16_t)port);
+
+ return record;
+}
+
+void terminate_dec_server( dec_server_record_t **rec)
+{
+ delete_cachelist( &(*rec)->cachelist);
+ free( (*rec)->jpipstream);
+
+ if( (*rec)->msgqueue)
+ delete_msgqueue( &((*rec)->msgqueue));
+
+ if( close_socket( (*rec)->listening_socket) != 0)
+ perror("close");
+
+ free( *rec);
+}
+
+client_t accept_connection( dec_server_record_t *rec)
+{
+ client_t client;
+
+ client = accept_socket( rec->listening_socket);
+ if( client == -1)
+ fprintf( stderr, "error: failed to connect to client\n");
+
+ return client;
+}
+
+bool handle_clientreq( client_t client, dec_server_record_t *rec)
+{
+ bool quit = false;
+ msgtype_t msgtype = identify_clientmsg( client);
+
+ switch( msgtype){
+ case JPIPSTREAM:
+ handle_JPIPstreamMSG( client, rec->cachelist, &rec->jpipstream, &rec->jpipstreamlen, rec->msgqueue);
+ break;
+
+ case PNMREQ:
+ handle_PNMreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
+ break;
+
+ case XMLREQ:
+ handle_XMLreqMSG( client, rec->jpipstream, rec->cachelist);
+ break;
+
+ case TIDREQ:
+ handle_TIDreqMSG( client, rec->cachelist);
+ break;
+
+ case CIDREQ:
+ handle_CIDreqMSG( client, rec->cachelist);
+ break;
+
+ case CIDDST:
+ handle_dstCIDreqMSG( client, rec->cachelist);
+ break;
+
+ case SIZREQ:
+ handle_SIZreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
+ break;
+
+ case JP2SAVE:
+ handle_JP2saveMSG( client, rec->cachelist, rec->msgqueue, rec->jpipstream);
+ break;
+
+ case QUIT:
+ quit = true;
+ save_codestream( rec->jpipstream, rec->jpipstreamlen, "jpt");
+ break;
+ case MSGERROR:
+ break;
+ }
+
+ fprintf( stderr, "\t end of the connection\n\n");
+ if( close_socket(client) != 0){
+ perror("close");
+ return false;
+ }
+
+ if( quit)
+ return false;
+
+ return true;
+}
+
+
+jpip_dec_param_t * init_jpipdecoder( bool jp2)
+{
+ jpip_dec_param_t *dec;
+
+ dec = (jpip_dec_param_t *)calloc( 1, sizeof(jpip_dec_param_t));
+
+ dec->msgqueue = gene_msgqueue( true, NULL);
+
+ if( jp2)
+ dec->metadatalist = gene_metadatalist();
+
+ return dec;
+}
+
+
+bool fread_jpip( const char fname[], jpip_dec_param_t *dec)
+{
+ int infd;
+
+ if(( infd = open( fname, O_RDONLY)) == -1){
+ fprintf( stderr, "file %s not exist\n", fname);
+ return false;
+ }
+
+ if(!(dec->jpiplen = (Byte8_t)get_filesize(infd)))
+ return false;
+
+ dec->jpipstream = (Byte_t *)malloc( dec->jpiplen);
+
+ if( read( infd, dec->jpipstream, dec->jpiplen) != (int)dec->jpiplen){
+ fprintf( stderr, "file reading error\n");
+ free( dec->jpipstream);
+ return false;
+ }
+
+ close(infd);
+
+ return true;
+}
+
+void decode_jpip( jpip_dec_param_t *dec)
+{
+ parse_JPIPstream( dec->jpipstream, dec->jpiplen, 0, dec->msgqueue);
+
+ if( dec->metadatalist){ /* JP2 encoding*/
+ parse_metamsg( dec->msgqueue, dec->jpipstream, dec->jpiplen, dec->metadatalist);
+ dec->ihdrbox = gene_ihdrbox( dec->metadatalist, dec->jpipstream);
+
+ dec->jp2kstream = recons_jp2( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, &dec->jp2klen);
+ }
+ else /* J2k encoding */
+ /* Notice: arguments fw, fh need to be set for LRCP, PCRL, CPRL*/
+ dec->jp2kstream = recons_j2k( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, 0, 0, &dec->jp2klen);
+}
+
+bool fwrite_jp2k( const char fname[], jpip_dec_param_t *dec)
+{
+ int outfd;
+
+#ifdef _WIN32
+ if(( outfd = open( fname, O_WRONLY|O_CREAT, _S_IREAD | _S_IWRITE)) == -1){
+#else
+ if(( outfd = open( fname, O_WRONLY|O_CREAT, S_IRWXU|S_IRWXG)) == -1){
+#endif
+ fprintf( stderr, "file %s open error\n", fname);
+ return false;
+ }
+
+ if( write( outfd, dec->jp2kstream, dec->jp2klen) != (int)dec->jp2klen)
+ fprintf( stderr, "j2k file write error\n");
+
+ close(outfd);
+
+ return true;
+}
+
+void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec)
+{
+ if( messages)
+ print_msgqueue( dec->msgqueue);
+
+ if( metadata)
+ print_allmetadata( dec->metadatalist);
+
+ if( ihdrbox){
+ printf("W*H: %d*%d\n", dec->ihdrbox->height, dec->ihdrbox->width);
+ printf("NC: %d, bpc: %d\n", dec->ihdrbox->nc, dec->ihdrbox->bpc);
+ }
+}
+
+void destroy_jpipdecoder( jpip_dec_param_t **dec)
+{
+ free( (*dec)->jpipstream);
+ delete_msgqueue( &(*dec)->msgqueue);
+ if( (*dec)->metadatalist){
+ delete_metadatalist( &(*dec)->metadatalist);
+ free( (*dec)->ihdrbox);
+ }
+
+ free( (*dec)->jp2kstream);
+ free( *dec);
+}
+
+index_t * get_index_from_JP2file( int fd)
+{
+ char *data;
+
+ /* Check resource is a JP family file.*/
+ if( lseek( fd, 0, SEEK_SET)==-1){
+ fprintf( stderr, "Error: File broken (lseek error)\n");
+ return NULL;
+ }
+
+ data = (char *)malloc( 12); /* size of header*/
+ if( read( fd, data, 12) != 12){
+ free( data);
+ fprintf( stderr, "Error: File broken (read error)\n");
+ return NULL;
+ }
+
+ if( *data || *(data + 1) || *(data + 2) ||
+ *(data + 3) != 12 || strncmp (data + 4, "jP \r\n\x87\n", 8)){
+ free( data);
+ fprintf( stderr, "Error: No JPEG 2000 Signature box in this file\n");
+ return NULL;
+ }
+ free( data);
+
+ return parse_jp2file( fd);
+}
+
+void destroy_index( index_t **idx)
+{
+ delete_index( idx);
+}
+
+void output_index( index_t *index)
+{
+ print_index( *index);
+}
+
+#endif /*SERVER*/
diff --git a/src/lib/openjpip/openjpip.h b/src/lib/openjpip/openjpip.h
new file mode 100644
index 00000000..c08c3d86
--- /dev/null
+++ b/src/lib/openjpip/openjpip.h
@@ -0,0 +1,308 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 OPENJPIP_H_
+# define OPENJPIP_H_
+
+#include "session_manager.h"
+#include "target_manager.h"
+#include "query_parser.h"
+#include "msgqueue_manager.h"
+#include "bool.h"
+#include "sock_manager.h"
+#include "auxtrans_manager.h"
+
+#ifdef SERVER
+
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+
+#else
+
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+
+#include "cache_manager.h"
+#include "byte_manager.h"
+#include "imgsock_manager.h"
+
+#include "metadata_manager.h"
+#include "ihdrbox_manager.h"
+#include "index_manager.h"
+
+#endif /*SERVER*/
+
+/*
+ *==========================================================
+ * JPIP server API
+ *==========================================================
+ */
+
+ #ifdef SERVER
+
+/** Server static records*/
+typedef struct server_record{
+ sessionlist_param_t *sessionlist; /**< list of session records*/
+ targetlist_param_t *targetlist; /**< list of target records*/
+ auxtrans_param_t auxtrans;
+} server_record_t;
+
+/** Query/response data for each client*/
+typedef struct QR{
+ query_param_t *query; /**< query parameters*/
+ msgqueue_param_t *msgqueue; /**< message queue*/
+ channel_param_t *channel; /**< channel, (NULL if stateless)*/
+} QR_t;
+
+/**
+ * Initialize the JPIP server
+ *
+ * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152-65535)
+ * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152-65535)
+ * @return intialized server record pointer
+ */
+server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport);
+
+/**
+ * Terminate the JPIP server
+ *
+ * @param[in] rec address of deleting server static record pointer
+ */
+void terminate_JPIPserver( server_record_t **rec);
+
+/**
+ * 1st process per client request; parse query string
+ *
+ * @param[in] query_string request query string
+ * @return initialized query/response data pointer
+ */
+QR_t * parse_querystring( const char *query_string);
+
+/**
+ * 2nd process; process JPIP request and construct message queue
+ *
+ * @param[in] rec server static record pointer
+ * @param[in] qr query/response data pointer
+ * @return true if succeed, otherwise false
+ */
+bool process_JPIPrequest( server_record_t *rec, QR_t *qr);
+
+/**
+ * 3rd process; send response data JPT/JPP-stream
+ *
+ * @param[in] rec server static record pointer
+ * @param[in] qr query/response data pointer
+ */
+void send_responsedata( server_record_t *rec, QR_t *qr);
+
+/**
+ * 4th (last) process;
+ *
+ * @param[in] rec server static record pinter
+ * @param[in] qr address of query/response data pointer
+ */
+void end_QRprocess( server_record_t *rec, QR_t **qr);
+
+/**
+ * Option for local tests; print out parameter values to logstream (stderr)
+ *
+ * @param[in] query true if query parameters are to be printed out
+ * @param[in] messages true if queue of messages is to be printed out
+ * @param[in] sessions true if session list is to be printed out
+ * @param[in] targets true if target list is to be printed out
+ * @param[in] qr query/response data pointer
+ * @param[in] rec server static record pinter
+ */
+void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec);
+
+#endif /*SERVER*/
+
+/*
+ *==========================================================
+ * JPIP decoding server API
+ *==========================================================
+ */
+
+#ifndef SERVER
+
+/** Decoding server static records*/
+typedef struct dec_server_record{
+ cachelist_param_t *cachelist; /**< cache list*/
+ Byte_t *jpipstream; /**< JPT/JPP stream*/
+ OPJ_SIZE_T jpipstreamlen; /**< length of jpipstream*/
+ msgqueue_param_t *msgqueue; /**< parsed message queue of jpipstream*/
+ SOCKET listening_socket; /**< listenning socket*/
+} dec_server_record_t;
+
+
+/** Client socket identifier*/
+typedef SOCKET client_t;
+
+/**
+ * Initialize the image decoding server
+ *
+ * @param[in] port opening tcp port (valid No. 49152-65535)
+ * @return intialized decoding server record pointer
+ */
+dec_server_record_t * init_dec_server( int port);
+
+/**
+ * Terminate the image decoding server
+ *
+ * @param[in] rec address of deleting decoding server static record pointer
+ */
+void terminate_dec_server( dec_server_record_t **rec);
+
+/**
+ * Accept client connection
+ *
+ * @param[in] rec decoding server static record pointer
+ * @return client socket ID, -1 if failed
+ */
+client_t accept_connection( dec_server_record_t *rec);
+
+ /**
+ * Handle client request
+ *
+ * @param[in] client client socket ID
+ * @param[in] rec decoding server static record pointer
+ * @return true if succeed
+ */
+bool handle_clientreq( client_t client, dec_server_record_t *rec);
+
+#endif /*SERVER*/
+
+/*
+ *==========================================================
+ * JPIP tool API
+ *==========================================================
+ */
+
+#ifndef SERVER
+
+/*
+ * jpip to JP2 or J2K
+ */
+
+/** JPIP decoding parameters*/
+typedef struct jpip_dec_param{
+ Byte_t *jpipstream; /**< JPT/JPP-stream*/
+ Byte8_t jpiplen; /**< length of jpipstream*/
+ msgqueue_param_t *msgqueue; /**< message queue*/
+ metadatalist_param_t *metadatalist; /**< metadata list going into JP2 file*/
+ ihdrbox_param_t *ihdrbox; /**< ihdr box going into JP2 file*/
+ Byte_t *jp2kstream; /**< J2K codestream or JP2 file codestream*/
+ Byte8_t jp2klen; /**< length of j2kstream or JP2 file*/
+} jpip_dec_param_t;
+
+/**
+ * Initialize jpip decoder
+ *
+ * @param[in] jp2 true in case of jp2 file encoding, else j2k file encoding
+ * @return JPIP decoding parameters pointer
+ */
+jpip_dec_param_t * init_jpipdecoder( bool jp2);
+
+/**
+ * Destroy jpip decoding parameters
+ *
+ * @param[in] dec address of JPIP decoding parameters pointer
+ */
+void destroy_jpipdecoder( jpip_dec_param_t **dec);
+
+/**
+ * Read jpip codestream from a file
+ *
+ * @param[in] fname file name
+ * @param[in] dec JPIP decoding parameters pointer
+ * @return true if succeed
+ */
+bool fread_jpip( const char fname[], jpip_dec_param_t *dec);
+
+/**
+ * Decode jpip codestream
+ *
+ * @param[in] dec JPIP decoding parameters pointer
+ */
+void decode_jpip( jpip_dec_param_t *dec);
+
+/**
+ * Write J2K/JP2 codestream to a file
+ *
+ * @param[in] fname file name
+ * @param[in] dec JPIP decoding parameters pointer
+ * @return true if succeed
+ */
+bool fwrite_jp2k( const char fname[], jpip_dec_param_t *dec);
+
+/**
+ * Option; print out parameter values to stderr
+ *
+ * @param[in] messages true if queue of messages is to be printed out
+ * @param[in] metadata true if metadata is to be printed out
+ * @param[in] ihdrbox true if image header data is to be printed out
+ * @param[in] dec JPIP decoding parameters pointer
+ */
+void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec);
+
+/*
+ * test the format of index (cidx) box in JP2 file
+ */
+
+/** Redefinition of index parameters*/
+typedef index_param_t index_t;
+
+/**
+ * Parse JP2 file and get index information from cidx box inside
+ *
+ * @param[in] fd file descriptor of the JP2 file
+ * @return pointer to the generated structure of index parameters
+ */
+index_t * get_index_from_JP2file( int fd);
+
+/**
+ * Destroy index parameters
+ *
+ * @param[in,out] idx addressof the index pointer
+ */
+void destroy_index( index_t **idx);
+
+
+/**
+ * print index parameters
+ *
+ * @param[in] index index parameters
+ */
+void output_index( index_t *index);
+
+#endif /*SERVER*/
+
+#endif /* !OPENJPIP_H_ */
diff --git a/src/lib/openjpip/placeholder_manager.c b/src/lib/openjpip/placeholder_manager.c
new file mode 100644
index 00000000..4a37a13b
--- /dev/null
+++ b/src/lib/openjpip/placeholder_manager.c
@@ -0,0 +1,143 @@
+/*
+ * $Id: placeholder_manager.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "placeholder_manager.h"
+#include "opj_inttypes.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+
+placeholderlist_param_t * gene_placeholderlist(void)
+{
+ placeholderlist_param_t *list;
+
+ list = (placeholderlist_param_t *)malloc( sizeof(placeholderlist_param_t));
+
+ list->first = NULL;
+ list->last = NULL;
+
+ return list;
+}
+
+void delete_placeholderlist( placeholderlist_param_t **list)
+{
+ placeholder_param_t *ptr, *next;
+
+ if(!(*list))
+ return;
+
+ ptr = (*list)->first;
+
+ while( ptr){
+ next=ptr->next;
+ delete_placeholder( &ptr);
+ ptr=next;
+ }
+ free( *list);
+}
+
+placeholder_param_t * gene_placeholder( box_param_t *box, Byte8_t origID)
+{
+ placeholder_param_t *placeholder;
+
+ placeholder = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
+
+ strncpy( placeholder->TBox, "phld", 4);
+ placeholder->Flags = 1; /* only the access to the original contents of this box, for now */
+ placeholder->OrigID = origID;
+ placeholder->OrigBH = fetch_headbytes( box);
+ placeholder->OrigBHlen = box->headlen;
+ placeholder->LBox = 20+(Byte4_t)box->headlen;
+ placeholder->next = NULL;
+
+ return placeholder;
+}
+
+void delete_placeholder( placeholder_param_t **placeholder)
+{
+ if( (*placeholder)->OrigBH)
+ free((*placeholder)->OrigBH);
+ free(*placeholder);
+}
+
+void insert_placeholder_into_list( placeholder_param_t *phld, placeholderlist_param_t *phldlist)
+{
+ if( phldlist->first)
+ phldlist->last->next = phld;
+ else
+ phldlist->first = phld;
+ phldlist->last = phld;
+}
+
+void print_placeholder( placeholder_param_t *phld)
+{
+ int i;
+
+ fprintf( logstream, "placeholder info:\n");
+ fprintf( logstream, "\t LBox: %d %#x\n", phld->LBox, phld->LBox);
+ fprintf( logstream, "\t TBox: %.4s\n", phld->TBox);
+ fprintf( logstream, "\t Flags: %#x %#x\n", phld->Flags, phld->Flags);
+ fprintf( logstream, "\t OrigID: %" PRId64 "\n", phld->OrigID);
+ fprintf( logstream, "\t OrigBH: ");
+
+ for( i=0; i< phld->OrigBHlen; i++)
+ fprintf( logstream, "%02x ", phld->OrigBH[i]);
+ fprintf( logstream, "\t");
+
+ for( i=0; i< phld->OrigBHlen; i++)
+ fprintf( logstream, "%c", phld->OrigBH[i]);
+ fprintf( logstream, "\n");
+}
+
+void print_allplaceholder( placeholderlist_param_t *list)
+{
+ placeholder_param_t *ptr;
+
+ if( !list)
+ return;
+
+ fprintf( logstream, "all placeholder info: \n");
+ ptr = list->first;
+ while( ptr != NULL){
+ print_placeholder( ptr);
+ ptr=ptr->next;
+ }
+}
diff --git a/src/lib/openjpip/placeholder_manager.h b/src/lib/openjpip/placeholder_manager.h
new file mode 100644
index 00000000..ced20854
--- /dev/null
+++ b/src/lib/openjpip/placeholder_manager.h
@@ -0,0 +1,115 @@
+/*
+ * $Id: placeholder_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 PLACEHOLDER_MANAGER_H_
+# define PLACEHOLDER_MANAGER_H_
+
+#include "byte_manager.h"
+#include "box_manager.h"
+
+/** A.3.6.3 Placeholder box format*/
+/** placeholder box parameters*/
+typedef struct placeholder_param{
+ Byte4_t LBox;
+ char TBox[4];
+ Byte4_t Flags;
+ Byte8_t OrigID;
+ Byte_t *OrigBH; /**< dynamic memory pointer*/
+ Byte_t OrigBHlen; /**< length of OrigBH*/
+#ifdef AAA
+ Byte8_t EquivID;
+ Byte_t *EquivBH; /**< dynamic memory pointer*/
+ Byte_t EquivBHlen; /**< length of EquivBH*/
+ Byte8_t CSID;
+ Byte4_t NCS;
+#endif /*AAA*/
+ struct placeholder_param *next; /**< pointer to the next placeholder*/
+} placeholder_param_t;
+
+
+/** placeholder box list parameters*/
+typedef struct placeholderlist_param{
+ placeholder_param_t *first; /**< first placeholder pointer of the list*/
+ placeholder_param_t *last; /**< last placeholder pointer of the list*/
+} placeholderlist_param_t;
+
+
+/**
+ * generate a placeholder list
+ *
+ * @return pointer to the generated placeholder list
+ */
+placeholderlist_param_t * gene_placeholderlist(void);
+
+
+/**
+ * delete placeholder list
+ *
+ * @param[in,out] list address of the placeholder list pointer
+ */
+void delete_placeholderlist( placeholderlist_param_t **list);
+
+
+/**
+ * generate a placeholder of a box
+ *
+ * @param[in] box box pointer
+ * @param[in] origID metadata-bin ID of the bin containing the contents of the original box
+ * @return pointer to the generated placeholder
+ */
+placeholder_param_t * gene_placeholder( box_param_t *box, Byte8_t origID);
+
+
+/**
+ * delete a placeholder
+ *
+ * @param[in,out] placeholder address of the placeholder pointer
+ */
+void delete_placeholder( placeholder_param_t **placeholder);
+
+void insert_placeholder_into_list( placeholder_param_t *phld, placeholderlist_param_t *phldlist);
+
+
+/**
+ * print placeholder parameters
+ *
+ * @param[in] phld placeholder pointer
+ */
+void print_placeholder( placeholder_param_t *phld);
+
+
+/**
+ * print all placeholder parameters
+ *
+ * @param[in] list placeholder list pointer
+ */
+void print_allplaceholder( placeholderlist_param_t *list);
+
+#endif /* !PLACEHOLDER_MANAGER_H_ */
diff --git a/src/lib/openjpip/query_parser.c b/src/lib/openjpip/query_parser.c
new file mode 100644
index 00000000..460a5eb6
--- /dev/null
+++ b/src/lib/openjpip/query_parser.c
@@ -0,0 +1,429 @@
+/*
+ * $Id: query_parser.c 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 <windows.h>
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#else
+#include <strings.h>
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include "query_parser.h"
+#include "opj_stdint.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+
+/**
+ * Get initialized query parameters
+ *
+ * @return initial query parameters
+ */
+query_param_t * get_initquery(void);
+
+/*
+ * get a pair of field name and value from the string starting fieldname=fieldval&... format
+ *
+ * @param[in] stringptr pointer to the beginning of the parsing string
+ * @param[out] fieldname string to copy the field name, if not found, NULL
+ * @param[out] fieldval string to copy the field value, if not found, NULL
+ * @return pointer to the next field string, if there is none, NULL
+ */
+char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval);
+
+void parse_cclose( char *src, query_param_t *query_param);
+void parse_metareq( char *field, query_param_t *query_param);
+
+/* parse the requested components (parses forms like:a; a,b; a-b; a-b,c; a,b-c)*/
+void parse_comps( char *field, query_param_t *query_param);
+
+
+/** maximum length of field name*/
+#define MAX_LENOFFIELDNAME 10
+
+/** maximum length of field value*/
+#define MAX_LENOFFIELDVAL 128
+
+query_param_t * parse_query( const char *query_string)
+{
+ query_param_t *query_param;
+ const char *pquery;
+ char fieldname[MAX_LENOFFIELDNAME], fieldval[MAX_LENOFFIELDVAL];
+
+ query_param = get_initquery();
+
+ pquery = query_string;
+
+ while( pquery!=NULL) {
+
+ pquery = get_fieldparam( pquery, fieldname, fieldval);
+
+ if( fieldname[0] != '\0'){
+ if( strcasecmp( fieldname, "target") == 0)
+ query_param->target = strdup( fieldval);
+
+ else if( strcasecmp( fieldname, "tid") == 0)
+ query_param->tid = strdup( fieldval);
+
+ else if( strcasecmp( fieldname, "fsiz") == 0)
+ sscanf( fieldval, "%d,%d", &query_param->fx, &query_param->fy);
+
+ else if( strcasecmp( fieldname, "roff") == 0)
+ sscanf( fieldval, "%d,%d", &query_param->rx, &query_param->ry);
+
+ else if( strcasecmp( fieldname, "rsiz") == 0)
+ sscanf( fieldval, "%d,%d", &query_param->rw, &query_param->rh);
+
+ else if( strcasecmp( fieldname, "layers") == 0)
+ sscanf( fieldval, "%d", &query_param->layers);
+
+ else if( strcasecmp( fieldname, "cid") == 0)
+ query_param->cid = strdup( fieldval);
+
+ else if( strcasecmp( fieldname, "cnew") == 0){
+ if( strncasecmp( fieldval, "http-tcp", 8) == 0)
+ query_param->cnew = tcp;
+ else if( strncasecmp( fieldval, "http", 4) == 0)
+ query_param->cnew = http;
+ }
+
+ else if( strcasecmp( fieldname, "cclose") == 0)
+ parse_cclose( fieldval, query_param);
+
+ else if( strcasecmp( fieldname, "metareq") == 0)
+ parse_metareq( fieldval, query_param);
+
+ else if( strcasecmp( fieldname, "comps") == 0)
+ parse_comps( fieldval, query_param);
+
+ else if( strcasecmp( fieldname, "type") == 0){
+ if( strncasecmp( fieldval, "jpp-stream", 10) == 0)
+ query_param->return_type = JPPstream;
+ else if( strncasecmp( fieldval, "jpt-stream", 10) == 0)
+ query_param->return_type = JPTstream;
+ }
+
+ else if( strcasecmp( fieldname, "len") == 0){
+ sscanf( fieldval, "%d", &query_param->len);
+ if( query_param->len == 2000) /* for kakadu client*/
+ strncpy( query_param->box_type[0], "ftyp", 4);
+ }
+ }
+ }
+ return query_param;
+}
+
+query_param_t * get_initquery(void)
+{
+ query_param_t *query;
+ int i;
+
+ query = (query_param_t *)malloc( sizeof(query_param_t));
+
+ query->target = NULL;
+ query->tid = NULL;
+ query->fx = -1;
+ query->fy = -1;
+ query->rx = -1;
+ query->ry = -1;
+ query->rw = -1;
+ query->rh = -1;
+ query->layers = -1;
+ query->lastcomp = -1;
+ query->comps = NULL;
+ query->cid = NULL;
+ query->cnew = non;
+ query->cclose = NULL;
+ query->numOfcclose = 0;
+ memset( query->box_type, 0, MAX_NUMOFBOX*4);
+ memset( query->limit, 0, MAX_NUMOFBOX*sizeof(int));
+ for( i=0; i<MAX_NUMOFBOX; i++){
+ query->w[i] = false;
+ query->s[i] = false;
+ query->g[i] = false;
+ query->a[i] = false;
+ query->priority[i] = false;
+ }
+ query->root_bin = 0;
+ query->max_depth = -1;
+ query->metadata_only = false;
+ query->return_type = UNKNOWN;
+ query->len = -1;
+
+ return query;
+}
+
+
+char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval)
+{
+ char *eqp, *andp, *nexfieldptr;
+
+ if((eqp = strchr( stringptr, '='))==NULL){
+ fprintf( stderr, "= not found\n");
+ strcpy( fieldname, "");
+ strcpy( fieldval, "");
+ return NULL;
+ }
+ if((andp = strchr( stringptr, '&'))==NULL){
+ andp = strchr( stringptr, '\0');
+ nexfieldptr = NULL;
+ }
+ else
+ nexfieldptr = andp+1;
+
+ assert( (size_t)(eqp-stringptr));
+ strncpy( fieldname, stringptr, (size_t)(eqp-stringptr));
+ fieldname[eqp-stringptr]='\0';
+ assert( andp-eqp-1 >= 0);
+ strncpy( fieldval, eqp+1, (size_t)(andp-eqp-1));
+ fieldval[andp-eqp-1]='\0';
+
+ return nexfieldptr;
+}
+
+void print_queryparam( query_param_t query_param)
+{
+ int i;
+ char *cclose;
+
+ fprintf( logstream, "query parameters:\n");
+
+ if( query_param.target)
+ fprintf( logstream, "\t target: %s\n", query_param.target);
+
+ if( query_param.tid)
+ fprintf( logstream, "\t tid: %s\n", query_param.tid);
+
+ fprintf( logstream, "\t fx,fy: %d, %d\n", query_param.fx, query_param.fy);
+ fprintf( logstream, "\t rx,ry: %d, %d \t rw,rh: %d, %d\n", query_param.rx, query_param.ry, query_param.rw, query_param.rh);
+ fprintf( logstream, "\t layers: %d\n", query_param.layers);
+ fprintf( logstream, "\t components: ");
+
+ if( query_param.lastcomp == -1)
+ fprintf( logstream, "ALL\n");
+ else{
+ for( i=0; i<=query_param.lastcomp; i++)
+ if( query_param.comps[i])
+ fprintf( logstream, "%d ", i);
+ fprintf( logstream, "\n");
+ }
+ fprintf( logstream, "\t cnew: %d\n", query_param.cnew);
+
+ if( query_param.cid)
+ fprintf( logstream, "\t cid: %s\n", query_param.cid);
+
+ if( query_param.cclose){
+ fprintf( logstream, "\t cclose: ");
+
+ for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++){
+ fprintf( logstream, "%s ", cclose);
+ cclose += (strlen(cclose)+1);
+ }
+ fprintf(logstream, "\n");
+ }
+
+ fprintf( logstream, "\t req-box-prop\n");
+ for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){
+ fprintf( logstream, "\t\t box_type: %.4s limit: %d w:%d s:%d g:%d a:%d priority:%d\n", query_param.box_type[i], query_param.limit[i], query_param.w[i], query_param.s[i], query_param.g[i], query_param.a[i], query_param.priority[i]);
+ }
+
+ fprintf( logstream, "\t root-bin: %d\n", query_param.root_bin);
+ fprintf( logstream, "\t max-depth: %d\n", query_param.max_depth);
+ fprintf( logstream, "\t metadata-only: %d\n", query_param.metadata_only);
+ fprintf( logstream, "\t image return type: %d, [JPP-stream=0, JPT-stream=1, UNKNOWN=-1]\n", query_param.return_type);
+ fprintf( logstream, "\t len: %d\n", query_param.len);
+}
+
+void parse_cclose( char *src, query_param_t *query_param)
+{
+ size_t i;
+ size_t len;
+
+ len = strlen( src);
+ query_param->cclose = strdup( src);
+
+ for( i=0; i<len; i++)
+ if( query_param->cclose[i] == ','){
+ query_param->cclose[i] = '\0';
+ query_param->numOfcclose ++;
+ }
+
+ query_param->numOfcclose ++;
+}
+
+void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param);
+
+void parse_metareq( char *field, query_param_t *query_param)
+{
+ char req_box_prop[20];
+ char *ptr, *src;
+ int numofboxreq = 0;
+
+ memset( req_box_prop, 0, 20);
+
+ /* req-box-prop*/
+ ptr = strchr( field, '[');
+ ptr++;
+ src = ptr;
+ while( *ptr != ']'){
+ if( *ptr == ';'){
+ assert( ptr-src >= 0);
+ strncpy( req_box_prop, src, (size_t)(ptr-src));
+ parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
+ ptr++;
+ src = ptr;
+ memset( req_box_prop, 0, 20);
+ }
+ ptr++;
+ }
+ assert(ptr-src>=0);
+ strncpy( req_box_prop, src, (size_t)(ptr-src));
+
+ parse_req_box_prop( req_box_prop, numofboxreq++, query_param);
+
+ if(( ptr = strchr( field, 'R')))
+ sscanf( ptr+1, "%d", &(query_param->root_bin));
+
+ if(( ptr = strchr( field, 'D')))
+ sscanf( ptr+1, "%d", &(query_param->max_depth));
+
+ if(( ptr = strstr( field, "!!")))
+ query_param->metadata_only = true;
+}
+
+void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param)
+{
+ char *ptr;
+
+ if( *req_box_prop == '*')
+ query_param->box_type[idx][0]='*';
+ else
+ strncpy( query_param->box_type[idx], req_box_prop, 4);
+
+ if(( ptr = strchr( req_box_prop, ':'))){
+ if( *(ptr+1)=='r')
+ query_param->limit[idx] = -1;
+ else
+ sscanf( ptr+1, "%d", &(query_param->limit[idx]));
+ }
+
+ if(( ptr = strchr( req_box_prop, '/'))){
+ ptr++;
+ while( *ptr=='w' || *ptr=='s' || *ptr=='g' || *ptr=='a'){
+ switch( *ptr){
+ case 'w': query_param->w[idx] = true; break;
+ case 's': query_param->s[idx] = true; break;
+ case 'g': query_param->g[idx] = true; break;
+ case 'a': query_param->a[idx] = true; break;
+ }
+ ptr++;
+ }
+ }
+ else{
+ query_param->g[idx] = true;
+ query_param->s[idx] = true;
+ query_param->w[idx] = true;
+ }
+
+ if((ptr = strchr( req_box_prop, '!')))
+ query_param->priority[idx] = true;
+
+ idx++;
+}
+
+void parse_comps( char *field, query_param_t *query_param)
+{
+ int i,start,stop,aux = -1;
+ char *ptr1,*ptr2;
+
+ ptr1 = strchr( field, '-');
+ ptr2 = strchr( field, ',');
+
+ if( ptr1 && ptr2)
+ if( ptr1 > ptr2)
+ sscanf( field, "%d,%d-%d",&aux, &start, &stop);
+ else
+ sscanf( field, "%d-%d,%d", &start, &stop, &aux);
+ else
+ if(ptr1)
+ sscanf( field, "%d-%d", &start, &stop);
+ else if(ptr2){
+ sscanf( field, "%d,%d", &start, &stop);
+ aux = start;
+ start = stop;
+ }
+ else{
+ sscanf( field, "%d", &stop);
+ start = stop;
+ }
+
+ query_param->lastcomp = stop > aux ? stop : aux;
+ query_param->comps = (bool *)calloc( 1, (OPJ_SIZE_T)(query_param->lastcomp+1)*sizeof(bool));
+
+ for( i=start; i<=stop; i++)
+ query_param->comps[i]=true;
+
+ if(aux!=-1)
+ query_param->comps[aux] = true;
+}
+
+void delete_query( query_param_t **query)
+{
+ if( (*query)->target)
+ free( (*query)->target);
+
+ if( (*query)->tid)
+ free( (*query)->tid);
+
+ if( (*query)->comps)
+ free((*query)->comps);
+
+ if( (*query)->cid)
+ free( (*query)->cid);
+
+ if( (*query)->cclose)
+ free( (*query)->cclose);
+
+ free( *query);
+}
diff --git a/src/lib/openjpip/query_parser.h b/src/lib/openjpip/query_parser.h
new file mode 100644
index 00000000..d60cafe6
--- /dev/null
+++ b/src/lib/openjpip/query_parser.h
@@ -0,0 +1,97 @@
+/*
+ * $Id: query_parser.h 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * Copyright (c) 2011, Lucian Corlaciu, GSoC
+ * 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 QUERY_PARSER_H_
+# define QUERY_PARSER_H_
+
+#include "bool.h"
+
+/** maximum number of meta request box */
+#define MAX_NUMOFBOX 10
+
+/** cnew aux transport name */
+typedef enum cnew_transport { non, http, tcp, udp} cnew_transport_t;
+
+/** image return type */
+typedef enum image_return { JPPstream, JPTstream, UNKNOWN=-1} image_return_t;
+
+/** Query parameters */
+typedef struct query_param{
+ char *target; /**< target name */
+ char *tid; /**< target identifier */
+ int fx, fy; /**< frame size (fx,fy) */
+ int rx, ry, rw, rh; /**< roi region */
+ int layers; /**< quality layers */
+ int lastcomp; /**< last component number */
+ bool *comps; /**< components (dynamic array) for jpp-stream, null means all components */
+ char *cid; /**< channel identifier */
+ cnew_transport_t cnew; /**< transport name if there is new channel request, else non */
+ char *cclose; /**< list of closing channel identifiers, separated by '\0' */
+ int numOfcclose; /**< number of closing channels */
+ char box_type[MAX_NUMOFBOX][4]; /**< interested box-types */
+ int limit[MAX_NUMOFBOX]; /**< limit value, -1: skeleton request "r", 0: entire contents */
+ bool w[MAX_NUMOFBOX]; /**< Metadata request qualifier flags */
+ bool s[MAX_NUMOFBOX];
+ bool g[MAX_NUMOFBOX];
+ bool a[MAX_NUMOFBOX];
+ bool priority[MAX_NUMOFBOX]; /**< priority flag */
+ int root_bin; /**< root-bin */
+ int max_depth; /**< max-depth */
+ bool metadata_only; /**< metadata-only request */
+ image_return_t return_type; /**< image return type */
+ int len; /**< maximum response length */
+} query_param_t;
+
+
+/**
+ * parse query
+ *
+ * @param[in] query_string request query string
+ * @return pointer to query parameters
+ */
+query_param_t * parse_query( const char *query_string);
+
+/**
+ * print query parameters
+ *
+ * @param[in] query_param query parameters
+ */
+void print_queryparam( query_param_t query_param);
+
+
+/**
+ * delete query
+ *
+ * @param[in] query address of the deleting query pointer
+ */
+void delete_query( query_param_t **query);
+
+#endif /* !QUERY_PARSER_H_ */
diff --git a/src/lib/openjpip/session_manager.c b/src/lib/openjpip/session_manager.c
new file mode 100644
index 00000000..5c1d7588
--- /dev/null
+++ b/src/lib/openjpip/session_manager.c
@@ -0,0 +1,196 @@
+/*
+ * $Id: session_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "session_manager.h"
+#include "target_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER */
+
+
+sessionlist_param_t * gene_sessionlist(void)
+{
+ sessionlist_param_t *sessionlist;
+
+ sessionlist = (sessionlist_param_t *)malloc( sizeof(sessionlist_param_t));
+
+ sessionlist->first = NULL;
+ sessionlist->last = NULL;
+
+ return sessionlist;
+}
+
+session_param_t * gene_session( sessionlist_param_t *sessionlist)
+{
+ session_param_t *session;
+
+ session = (session_param_t *)malloc( sizeof(session_param_t));
+
+ session->channellist = gene_channellist();
+ session->cachemodellist = gene_cachemodellist();
+
+ session->next = NULL;
+
+ if( sessionlist->first) /* there are one or more entries */
+ sessionlist->last->next = session;
+ else /* first entry */
+ sessionlist->first = session;
+ sessionlist->last = session;
+
+ return session;
+}
+
+bool search_session_and_channel( char cid[],
+ sessionlist_param_t *sessionlist,
+ session_param_t **foundsession,
+ channel_param_t **foundchannel)
+{
+ *foundsession = sessionlist->first;
+
+ while( *foundsession != NULL){
+
+ *foundchannel = (*foundsession)->channellist->first;
+
+ while( *foundchannel != NULL){
+
+ if( strcmp( cid, (*foundchannel)->cid) == 0)
+ return true;
+
+ *foundchannel = (*foundchannel)->next;
+ }
+ *foundsession = (*foundsession)->next;
+ }
+
+ fprintf( FCGI_stdout, "Status: 503\r\n");
+ fprintf( FCGI_stdout, "Reason: Channel %s not found\r\n", cid);
+
+ return false;
+}
+
+void insert_cachemodel_into_session( session_param_t *session, cachemodel_param_t *cachemodel)
+{
+ if(!cachemodel)
+ return;
+
+#ifndef SERVER
+ fprintf( logstream, "local log: insert cachemodel into session\n");
+#endif
+ if( session->cachemodellist->first != NULL)
+ session->cachemodellist->last->next = cachemodel;
+ else
+ session->cachemodellist->first = cachemodel;
+ session->cachemodellist->last = cachemodel;
+}
+
+bool delete_session( session_param_t **session, sessionlist_param_t *sessionlist)
+{
+ session_param_t *ptr;
+
+ if( *session == NULL)
+ return false;
+
+
+ if( *session == sessionlist->first)
+ sessionlist->first = (*session)->next;
+ else{
+ ptr = sessionlist->first;
+ while( ptr->next != *session)
+ ptr = ptr->next;
+ ptr->next = (*session)->next;
+
+ if( *session == sessionlist->last)
+ sessionlist->last = ptr;
+ }
+
+ delete_channellist( &((*session)->channellist));
+ delete_cachemodellist( &((*session)->cachemodellist));
+
+#ifndef SERVER
+ fprintf( logstream, "local log: session: %p deleted!\n", (void *)(*session));
+#endif
+ free( *session);
+
+ return true;
+}
+
+void delete_sessionlist( sessionlist_param_t **sessionlist)
+{
+ session_param_t *sessionPtr, *sessionNext;
+
+ sessionPtr = (*sessionlist)->first;
+ while( sessionPtr != NULL){
+ sessionNext=sessionPtr->next;
+
+ delete_channellist( &(sessionPtr->channellist));
+ delete_cachemodellist( &(sessionPtr->cachemodellist));
+
+#ifndef SERVER
+ fprintf( logstream, "local log: session: %p deleted!\n", (void *)sessionPtr);
+#endif
+ free( sessionPtr);
+
+ sessionPtr=sessionNext;
+ }
+
+ (*sessionlist)->first = NULL;
+ (*sessionlist)->last = NULL;
+
+ free(*sessionlist);
+}
+
+void print_allsession( sessionlist_param_t *sessionlist)
+{
+ session_param_t *ptr;
+ cachemodel_param_t *cachemodel;
+ int i=0;
+
+ fprintf( logstream, "SESSIONS info:\n");
+
+ ptr = sessionlist->first;
+ while( ptr != NULL){
+ fprintf( logstream, "session No.%d\n", i++);
+ print_allchannel( ptr->channellist);
+ cachemodel = ptr->cachemodellist->first;
+ while( cachemodel){
+ print_target( cachemodel->target);
+ cachemodel = cachemodel->next;
+ }
+ ptr=ptr->next;
+ }
+}
diff --git a/src/lib/openjpip/session_manager.h b/src/lib/openjpip/session_manager.h
new file mode 100644
index 00000000..03df4f4b
--- /dev/null
+++ b/src/lib/openjpip/session_manager.h
@@ -0,0 +1,116 @@
+/*
+ * $Id: session_manager.h 53 2011-05-09 16:55:39Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 SESSION_MANAGER_H_
+# define SESSION_MANAGER_H_
+
+#include "bool.h"
+#include "channel_manager.h"
+#include "cachemodel_manager.h"
+
+/** Session parameters*/
+typedef struct session_param{
+ channellist_param_t *channellist; /**< channel list pointer*/
+ cachemodellist_param_t *cachemodellist; /**< cache list pointer*/
+ struct session_param *next; /**< pointer to the next session*/
+} session_param_t;
+
+/** Session list parameters*/
+typedef struct sessionlist_param{
+ session_param_t *first; /**< first session pointer of the list*/
+ session_param_t *last; /**< last session pointer of the list*/
+} sessionlist_param_t;
+
+
+/**
+ * generate a session list
+ *
+ * @return pointer to the generated session list
+ */
+sessionlist_param_t * gene_sessionlist(void);
+
+
+/**
+ * generate a session under the sesion list
+ *
+ * @param[in] sessionlist session list to insert the new session
+ * @return pointer to the generated session
+ */
+session_param_t * gene_session( sessionlist_param_t *sessionlist);
+
+/**
+ * search a channel and its belonging session by channel ID
+ *
+ * @param[in] cid channel identifier
+ * @param[in] sessionlist session list pointer
+ * @param[in,out] foundsession address of the found session pointer
+ * @param[in,out] foundchannel address of the found channel pointer
+ * @return if the channel is found (true) or not (false)
+ */
+bool search_session_and_channel( char cid[],
+ sessionlist_param_t *sessionlist,
+ session_param_t **foundsession,
+ channel_param_t **foundchannel);
+
+/**
+ * insert a cache model into a session
+ *
+ * @param[in] session session pointer
+ * @param[in] cachemodel cachemodel pointer
+ */
+void insert_cachemodel_into_session( session_param_t *session, cachemodel_param_t *cachemodel);
+
+
+/**
+ * delete a session
+ *
+ * @param[in] session address of the session pointer
+ * @param[in] sessionlist session list pointer
+ * @return if succeeded (true) or failed (false)
+ */
+bool delete_session( session_param_t **session, sessionlist_param_t *sessionlist);
+
+
+/**
+ * delete session list
+ *
+ * @param[in,out] sessionlist address of the session list pointer
+ */
+void delete_sessionlist( sessionlist_param_t **sessionlist);
+
+/**
+ * print all sessions
+ *
+ * @param[in] sessionlist session list pointer
+ */
+void print_allsession( sessionlist_param_t *sessionlist);
+
+
+#endif /* !SESSION_MANAGER_H_ */
diff --git a/src/lib/openjpip/sock_manager.c b/src/lib/openjpip/sock_manager.c
new file mode 100644
index 00000000..432b03fa
--- /dev/null
+++ b/src/lib/openjpip/sock_manager.c
@@ -0,0 +1,181 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "sock_manager.h"
+
+#ifdef SERVER
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+SOCKET open_listeningsocket( uint16_t port)
+{
+ SOCKET listening_socket;
+ struct sockaddr_in sin;
+ int sock_optval = 1;
+
+ listening_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if ( listening_socket == -1 ){
+ perror("socket");
+ exit(1);
+ }
+
+ if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&sock_optval, sizeof(sock_optval)) == -1 ){
+ perror("setsockopt");
+ exit(1);
+ }
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){
+ perror("bind");
+ close_socket(listening_socket);
+ exit(1);
+ }
+
+ if( listen(listening_socket, SOMAXCONN) == -1){
+ perror("listen");
+ close_socket(listening_socket);
+ exit(1);
+ }
+ fprintf( FCGI_stderr, "port %d is listened\n", port);
+
+ return listening_socket;
+}
+
+SOCKET accept_socket( SOCKET listening_socket)
+{
+ struct sockaddr_in peer_sin;
+ unsigned int addrlen = sizeof(peer_sin);
+
+ return accept( listening_socket, (struct sockaddr *)&peer_sin, &addrlen);
+}
+
+void send_stream( SOCKET connected_socket, const void *stream, OPJ_SIZE_T length)
+{
+ char *ptr = (char*)stream;
+ OPJ_SIZE_T remlen = length;
+
+ while( remlen > 0){
+ ssize_t sentlen = send( connected_socket, ptr, remlen, 0);
+ if( sentlen == -1){
+ fprintf( FCGI_stderr, "sending stream error\n");
+ break;
+ }
+ remlen = remlen - (OPJ_SIZE_T)sentlen;
+ ptr = ptr + sentlen;
+ }
+}
+
+void * receive_stream( SOCKET connected_socket, OPJ_SIZE_T length)
+{
+ char *stream, *ptr;
+ OPJ_SIZE_T remlen;
+
+ ptr = stream = malloc( length);
+ remlen = length;
+
+ while( remlen > 0){
+ ssize_t redlen = recv( connected_socket, ptr, remlen, 0);
+ if( redlen == -1){
+ fprintf( FCGI_stderr, "receive stream error\n");
+ free( stream);
+ stream = NULL;
+ break;
+ }
+ remlen -= (OPJ_SIZE_T)redlen;
+ ptr = ptr + redlen;
+ }
+ return stream;
+}
+
+OPJ_SIZE_T receive_line(SOCKET connected_socket, char *p)
+{
+ OPJ_SIZE_T len = 0;
+ while (1){
+ ssize_t ret;
+ ret = recv( connected_socket, p, 1, 0);
+ if ( ret == -1 ){
+ perror("receive");
+ exit(1);
+ } else if ( ret == 0 ){
+ break;
+ }
+ if ( *p == '\n' )
+ break;
+ p++;
+ len++;
+ }
+ *p = '\0';
+
+ if( len == 0)
+ fprintf( FCGI_stderr, "Header receive error\n");
+
+ return len;
+}
+
+char * receive_string( SOCKET connected_socket)
+{
+ char buf[BUF_LEN];
+
+ /* MM FIXME: there is a nasty bug here, size of buf if BUF_LEN which is never
+ indicated to downstream receive_line */
+ receive_line( connected_socket, buf);
+
+ return strdup(buf);
+}
+
+int close_socket( SOCKET sock)
+{
+#ifdef _WIN32
+ return closesocket( sock);
+#else
+ return close( sock);
+#endif
+}
diff --git a/src/lib/openjpip/sock_manager.h b/src/lib/openjpip/sock_manager.h
new file mode 100644
index 00000000..ee67131e
--- /dev/null
+++ b/src/lib/openjpip/sock_manager.h
@@ -0,0 +1,106 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 SOCK_MANAGER_H_
+# define SOCK_MANAGER_H_
+
+#include "bool.h"
+#include "byte_manager.h"
+#include "opj_stdint.h"
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+typedef int SOCKET;
+#endif /*_WIN32*/
+
+#define BUF_LEN 256
+
+/**
+ * open listening socket
+ *
+ * @param port opening port number
+ * @return new socket
+ */
+SOCKET open_listeningsocket( uint16_t port);
+
+/**
+ * accept a new connection to the listenning socket
+ *
+ * @param listening_socket listenning socket
+ * @return connected socket (-1 if error occurs)
+ */
+SOCKET accept_socket( SOCKET listening_socket);
+
+
+/**
+ * receive a string line (ending with '\n') from client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [out] buf string to be stored
+ * @return red size
+ */
+OPJ_SIZE_T receive_line(SOCKET connected_socket, char *buf);
+
+/**
+ * receive a string line (ending with '\n') from client, return malloc string
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @return pointer to the string (memory allocated)
+ */
+char * receive_string( SOCKET connected_socket);
+
+/**
+ * receive data stream to client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] length length of the receiving stream
+ * @return pointer to the data stream (memory allocated), NULL if failed
+ */
+void * receive_stream( SOCKET connected_socket, OPJ_SIZE_T length);
+
+/**
+ * send data stream to client
+ *
+ * @param [in] connected_socket file descriptor of the connected socket
+ * @param [in] stream data stream
+ * @param [in] length length of data stream
+ */
+void send_stream( SOCKET connected_socket, const void *stream, OPJ_SIZE_T length);
+
+/**
+ * close socket
+ *
+ * @param [in] sock closing socket
+ * @return 0 if succeed, -1 if failed
+ */
+int close_socket( SOCKET sock);
+
+#endif /* !SOCK_MANAGER_H_ */
diff --git a/src/lib/openjpip/target_manager.c b/src/lib/openjpip/target_manager.c
new file mode 100644
index 00000000..8b4763a5
--- /dev/null
+++ b/src/lib/openjpip/target_manager.c
@@ -0,0 +1,345 @@
+/*
+ * $Id: target_manager.c 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#ifdef _WIN32
+#define snprintf _snprintf /* Visual Studio */
+#include <io.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include "target_manager.h"
+
+#ifdef SERVER
+#include <curl/curl.h>
+#include "fcgi_stdio.h"
+#define logstream FCGI_stdout
+#else
+#define FCGI_stdout stdout
+#define FCGI_stderr stderr
+#define logstream stderr
+#endif /*SERVER*/
+
+targetlist_param_t * gene_targetlist(void)
+{
+ targetlist_param_t *targetlist;
+
+ targetlist = (targetlist_param_t *)malloc( sizeof(targetlist_param_t));
+
+ targetlist->first = NULL;
+ targetlist->last = NULL;
+
+ return targetlist;
+}
+
+
+/**
+ * open jp2 format image file
+ *
+ * @param[in] filepath file name (.jp2)
+ * @param[out] tmpfname new file name if filepath is a URL
+ * @return file descriptor
+ */
+int open_jp2file( const char filepath[], char tmpfname[]);
+
+target_param_t * gene_target( targetlist_param_t *targetlist, char *targetpath)
+{
+ target_param_t *target;
+ int fd;
+ index_param_t *jp2idx;
+ char tmpfname[MAX_LENOFTID];
+ static int last_csn = 0;
+
+ if( targetpath[0]=='\0'){
+ fprintf( FCGI_stderr, "Error: exception, no targetpath in gene_target()\n");
+ return NULL;
+ }
+
+ if((fd = open_jp2file( targetpath, tmpfname)) == -1){
+ fprintf( FCGI_stdout, "Status: 404\r\n");
+ return NULL;
+ }
+
+ if( !(jp2idx = parse_jp2file( fd))){
+ fprintf( FCGI_stdout, "Status: 501\r\n");
+ return NULL;
+ }
+
+ target = (target_param_t *)malloc( sizeof(target_param_t));
+ snprintf( target->tid, MAX_LENOFTID, "%x-%x", (unsigned int)time(NULL), (unsigned int)rand());
+ target->targetname = strdup( targetpath);
+ target->fd = fd;
+#ifdef SERVER
+ if( tmpfname[0])
+ target->tmpfname = strdup( tmpfname);
+ else
+ target->tmpfname = NULL;
+#endif
+ target->csn = last_csn++;
+ target->codeidx = jp2idx;
+ target->num_of_use = 0;
+ target->jppstream = true;
+ target->jptstream = isJPTfeasible( *jp2idx);
+ target->next=NULL;
+
+ if( targetlist->first) /* there are one or more entries*/
+ targetlist->last->next = target;
+ else /* first entry*/
+ targetlist->first = target;
+ targetlist->last = target;
+
+#ifndef SERVER
+ fprintf( logstream, "local log: target %s generated\n", targetpath);
+#endif
+
+ return target;
+}
+
+void refer_target( target_param_t *reftarget, target_param_t **ptr)
+{
+ *ptr = reftarget;
+ reftarget->num_of_use++;
+}
+
+void unrefer_target( target_param_t *target)
+{
+ target->num_of_use--;
+}
+
+void delete_target( target_param_t **target)
+{
+ close( (*target)->fd);
+
+#ifdef SERVER
+ if( (*target)->tmpfname){
+ fprintf( FCGI_stderr, "Temporal file %s is deleted\n", (*target)->tmpfname);
+ remove( (*target)->tmpfname);
+ }
+#endif
+
+ if( (*target)->codeidx)
+ delete_index ( &(*target)->codeidx);
+
+#ifndef SERVER
+ fprintf( logstream, "local log: target: %s deleted\n", (*target)->targetname);
+#endif
+
+ free( (*target)->targetname);
+
+ free(*target);
+}
+
+void delete_target_in_list( target_param_t **target, targetlist_param_t *targetlist)
+{
+ target_param_t *ptr;
+
+ if( *target == targetlist->first)
+ targetlist->first = (*target)->next;
+ else{
+ ptr = targetlist->first;
+ while( ptr->next != *target){
+ ptr=ptr->next;
+ }
+
+ ptr->next = (*target)->next;
+
+ if( *target == targetlist->last)
+ targetlist->last = ptr;
+ }
+ delete_target( target);
+}
+
+void delete_targetlist(targetlist_param_t **targetlist)
+{
+ target_param_t *targetPtr, *targetNext;
+
+ targetPtr = (*targetlist)->first;
+ while( targetPtr != NULL){
+ targetNext=targetPtr->next;
+ delete_target( &targetPtr);
+ targetPtr=targetNext;
+ }
+ free( *targetlist);
+}
+
+void print_target( target_param_t *target)
+{
+ fprintf( logstream, "target:\n");
+ fprintf( logstream, "\t tid=%s\n", target->tid);
+ fprintf( logstream, "\t csn=%d\n", target->csn);
+ fprintf( logstream, "\t target=%s\n\n", target->targetname);
+}
+
+void print_alltarget( targetlist_param_t *targetlist)
+{
+ target_param_t *ptr;
+
+ ptr = targetlist->first;
+ while( ptr != NULL){
+ print_target( ptr);
+ ptr=ptr->next;
+ }
+}
+
+target_param_t * search_target( const char targetname[], targetlist_param_t *targetlist)
+{
+ target_param_t *foundtarget;
+
+ foundtarget = targetlist->first;
+
+ while( foundtarget != NULL){
+
+ if( strcmp( targetname, foundtarget->targetname) == 0)
+ return foundtarget;
+
+ foundtarget = foundtarget->next;
+ }
+ return NULL;
+}
+
+target_param_t * search_targetBytid( const char tid[], targetlist_param_t *targetlist)
+{
+ target_param_t *foundtarget;
+
+ foundtarget = targetlist->first;
+
+ while( foundtarget != NULL){
+
+ if( strcmp( tid, foundtarget->tid) == 0)
+ return foundtarget;
+
+ foundtarget = foundtarget->next;
+ }
+
+ return NULL;
+}
+
+int open_remotefile( const char filepath[], char tmpfname[]);
+
+int open_jp2file( const char filepath[], char tmpfname[])
+{
+ int fd;
+ char *data;
+
+ /* download remote target file to local storage*/
+ if( strncmp( filepath, "http://", 7) == 0){
+ if( (fd = open_remotefile( filepath, tmpfname)) == -1)
+ return -1;
+ }
+ else{
+ tmpfname[0] = 0;
+ if( (fd = open( filepath, O_RDONLY)) == -1){
+ fprintf( FCGI_stdout, "Reason: Target %s not found\r\n", filepath);
+ return -1;
+ }
+ }
+ /* Check resource is a JP family file.*/
+ if( lseek( fd, 0, SEEK_SET)==-1){
+ close(fd);
+ fprintf( FCGI_stdout, "Reason: Target %s broken (lseek error)\r\n", filepath);
+ return -1;
+ }
+
+ data = (char *)malloc( 12); /* size of header*/
+
+ if( read( fd, data, 12) != 12){
+ free( data);
+ close(fd);
+ fprintf( FCGI_stdout, "Reason: Target %s broken (read error)\r\n", filepath);
+ return -1;
+ }
+
+ if( *data || *(data + 1) || *(data + 2) ||
+ *(data + 3) != 12 || strncmp (data + 4, "jP \r\n\x87\n", 8)){
+ free( data);
+ close(fd);
+ fprintf( FCGI_stdout, "Reason: No JPEG 2000 Signature box in target %s\r\n", filepath);
+ return -1;
+ }
+
+ free( data);
+
+ return fd;
+}
+
+#ifdef SERVER
+static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream);
+#endif
+
+int open_remotefile( const char filepath[], char tmpfname[])
+{
+#ifndef SERVER
+ (void)filepath;
+ (void)tmpfname;
+ fprintf( FCGI_stderr, "Remote file can not be opened in local mode\n");
+ return -1;
+
+#else
+
+ CURL *curl_handle;
+ int fd;
+
+ curl_handle = curl_easy_init();
+ curl_easy_setopt(curl_handle, CURLOPT_URL, filepath);
+ curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
+
+ snprintf( tmpfname, MAX_LENOFTID, "%x-%x.jp2", (unsigned int)time(NULL), (unsigned int)rand());
+ fprintf( FCGI_stderr, "%s is downloaded to a temporal new file %s\n", filepath, tmpfname);
+ if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){
+ fprintf( FCGI_stdout, "Reason: File open error %s\r\n", tmpfname);
+ curl_easy_cleanup(curl_handle);
+ return -1;
+ }
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd);
+ curl_easy_perform(curl_handle);
+ curl_easy_cleanup(curl_handle);
+
+ return fd;
+#endif /*SERVER*/
+}
+
+#ifdef SERVER
+static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ int *fd = (int *)stream;
+ ssize_t written = write( *fd, ptr, size*nmemb);
+ assert( written >= 0 );
+
+ return (size_t)written;
+}
+#endif /*SERVER*/
diff --git a/src/lib/openjpip/target_manager.h b/src/lib/openjpip/target_manager.h
new file mode 100644
index 00000000..275adc4a
--- /dev/null
+++ b/src/lib/openjpip/target_manager.h
@@ -0,0 +1,159 @@
+/*
+ * $Id: target_manager.h 44 2011-02-15 12:32:29Z kaori $
+ *
+ * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2011, Professor Benoit Macq
+ * Copyright (c) 2010-2011, Kaori Hagihara
+ * 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 TARGET_MANAGER_H_
+# define TARGET_MANAGER_H_
+
+#include "bool.h"
+#include "index_manager.h"
+
+/** maximum length of target identifier*/
+#define MAX_LENOFTID 30
+
+/** target parameters*/
+typedef struct target_param{
+ char tid[MAX_LENOFTID]; /**< target identifier*/
+ char *targetname; /**< local file path or URL ( URL is suported only with SERVER mode)*/
+ int fd; /**< file descriptor*/
+#ifdef SERVER
+ char *tmpfname; /**< temporal file name to download a remote target file*/
+#endif
+ int csn; /**< codestream number */
+ index_param_t *codeidx; /**< index information of codestream */
+ int num_of_use; /**< numbers of sessions refering to this target */
+ bool jppstream; /**< if this target can return JPP-stream */
+ bool jptstream; /**< if this target can return JPP-stream */
+ struct target_param *next; /**< pointer to the next target */
+} target_param_t;
+
+
+/** Target list parameters*/
+typedef struct targetlist_param{
+ target_param_t *first; /**< first target pointer of the list*/
+ target_param_t *last; /**< last target pointer of the list*/
+} targetlist_param_t;
+
+
+
+/**
+ * generate a target list
+ *
+ * @return pointer to the generated target list
+ */
+targetlist_param_t * gene_targetlist(void);
+
+
+/**
+ * generate a target
+ *
+ * @param[in] targetlist target list to insert the generated target
+ * @param[in] targetpath file path or URL of the target
+ * @return pointer to the generated target
+ */
+target_param_t * gene_target( targetlist_param_t *targetlist, char *targetpath);
+
+
+/**
+ * refer a target, used to make a new cache model
+ *
+ * @param[in] reftarget reference target pointer
+ * @param[out] ptr address of feeding target pointer
+ */
+void refer_target( target_param_t *reftarget, target_param_t **ptr);
+
+
+/**
+ * refer a target, used to make a new cache model
+ *
+ * @param[in] target reference pointer to the target
+ */
+void unrefer_target( target_param_t *target);
+
+/**
+ * delete a target
+ *
+ * @param[in,out] target address of the deleting target pointer
+ */
+void delete_target( target_param_t **target);
+
+
+/**
+ * delete a target in list
+ *
+ * @param[in,out] target address of the deleting target pointer
+ * @param[in] targetlist target list pointer
+ */
+void delete_target_in_list( target_param_t **target, targetlist_param_t *targetlist);
+
+
+/**
+ * delete target list
+ *
+ * @param[in,out] targetlist address of the target list pointer
+ */
+void delete_targetlist(targetlist_param_t **targetlist);
+
+
+/**
+ * print target parameters
+ *
+ * @param[in] target target pointer
+ */
+void print_target( target_param_t *target);
+
+/**
+ * print all target parameters
+ *
+ * @param[in] targetlist target list pointer
+ */
+void print_alltarget( targetlist_param_t *targetlist);
+
+
+/**
+ * search a target by target name
+ *
+ * @param[in] targetname target name
+ * @param[in] targetlist target list pointer
+ * @return found target pointer
+ */
+target_param_t * search_target( const char targetname[], targetlist_param_t *targetlist);
+
+
+/**
+ * search a target by tid
+ *
+ * @param[in] tid target identifier
+ * @param[in] targetlist target list pointer
+ * @return found target pointer
+ */
+target_param_t * search_targetBytid( const char tid[], targetlist_param_t *targetlist);
+
+#endif /* !TARGET_MANAGER_H_ */
+
diff --git a/src/lib/openjpwl/CMakeLists.txt b/src/lib/openjpwl/CMakeLists.txt
new file mode 100644
index 00000000..eccef4b5
--- /dev/null
+++ b/src/lib/openjpwl/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Makefile for the main JPWL OpenJPEG codecs: JPWL_ j2k_to_image and JPWL_image_to_j2k
+
+add_definitions(-DUSE_JPWL)
+
+set(OPENJPEG_SRCS
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/bio.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/cio.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/dwt.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/event.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/image.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/j2k.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/j2k_lib.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/jp2.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/jpt.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/mct.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/mqc.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/openjpeg.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/pi.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/raw.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/t1.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/t2.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tcd.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tgt.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/cidx_manager.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/phix_manager.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/ppix_manager.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/thix_manager.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/tpix_manager.c
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2/function_list.c
+)
+
+set(JPWL_SRCS crc.c jpwl.c jpwl_lib.c rs.c)
+if(APPLE)
+ set_source_files_properties(
+ rs.c
+ PROPERTIES
+ COMPILE_FLAGS -fno-common)
+endif()
+
+include_directories(
+ ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2
+ ${OPENJPEG_SOURCE_DIR}/src/lib
+ )
+
+# Build the library
+if(WIN32)
+ if(BUILD_SHARED_LIBS)
+ add_definitions(-DOPJ_EXPORTS)
+ else()
+ add_definitions(-DOPJ_STATIC)
+ endif()
+endif()
+add_library(${OPENJPEG_LIBRARY_NAME}_JPWL ${JPWL_SRCS} ${OPENJPEG_SRCS})
+set_target_properties(${OPENJPEG_LIBRARY_NAME}_JPWL
+ PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES})
+
+# Install library
+install(TARGETS ${OPENJPEG_LIBRARY_NAME}_JPWL
+ EXPORT OpenJPEGTargets
+ RUNTIME DESTINATION ${OPENJPEG_INSTALL_BIN_DIR} COMPONENT Applications
+ LIBRARY DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+ ARCHIVE DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries
+)
diff --git a/src/lib/openjpwl/Makefile.am b/src/lib/openjpwl/Makefile.am
new file mode 100644
index 00000000..26ab4eba
--- /dev/null
+++ b/src/lib/openjpwl/Makefile.am
@@ -0,0 +1,78 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+lib_LTLIBRARIES = libopenjpeg_JPWL.la
+
+OPJ_SRC = \
+../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 \
+../t1_generate_luts.c \
+../t2.c \
+../tcd.c \
+../tgt.c \
+../cidx_manager.c \
+../phix_manager.c \
+../ppix_manager.c \
+../thix_manager.c \
+../tpix_manager.c \
+../function_list.c
+
+libopenjpeg_JPWL_la_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/libopenjpeg \
+-I$(top_builddir)/libopenjpeg \
+-I$(top_srcdir)/libopenjpeg/jpwl \
+-I$(top_builddir)/libopenjpeg/jpwl \
+-DUSE_JPWL
+libopenjpeg_JPWL_la_CFLAGS =
+libopenjpeg_JPWL_la_LIBADD = -lm
+libopenjpeg_JPWL_la_LDFLAGS = -no-undefined -version-info @lt_version@
+libopenjpeg_JPWL_la_SOURCES = \
+$(OPJ_SRC) \
+crc.c \
+jpwl.c \
+jpwl_lib.c \
+rs.c \
+crc.h \
+jpwl.h \
+rs.h
+
+install-data-hook:
+ @echo -e " (LA)\t$(libdir)/libopenjpeg_JPWL.la" >> $(top_builddir)/report.txt
+if BUILD_SHARED
+ @( $(call solist) ) >> $(top_builddir)/report.txt
+endif
+if BUILD_STATIC
+ @echo -e " (A)\t$(base)/$(a)" >> $(top_builddir)/report.txt
+endif
+
+solist = $(foreach f, $(dll) $(so), echo -e ' $(SO_PREFIX)\t$(base)/$(f)' ;)
+get_tok = $(shell grep -E "^$(1)=" $(lib_LTLIBRARIES) | cut -d "'" -f 2)
+base = $(call get_tok,libdir)
+so = $(call get_tok,library_names)
+a = $(call get_tok,old_library)
+
+if HAVE_WIN32
+SO_PREFIX = (DLL)
+dll = $(call get_tok,dlname)
+else
+if HAVE_DARWIN
+SO_PREFIX = (DY)
+dll =
+else
+SO_PREFIX = (SO)
+dll =
+endif
+endif
diff --git a/src/lib/openjpwl/README.txt b/src/lib/openjpwl/README.txt
new file mode 100644
index 00000000..e289e9e4
--- /dev/null
+++ b/src/lib/openjpwl/README.txt
@@ -0,0 +1,136 @@
+===============================================================================
+ JPEG2000 Part 11 (ISO/IEC 15444-11 JPWL) Software
+
+
+
+ Version 20061213
+===============================================================================
+
+
+
+
+
+1. Scope
+=============
+
+This document describes the installation and use of the JPWL module in the framework of OpenJPEG library.
+
+This implementation has been developed from OpenJPEG implementation of JPEG2000 standard, and for this reason it is written in C language.
+
+If you find some bugs or if you have problems using the encoder/decoder, please send an e-mail to jpwl@diei.unipg.it
+
+
+2. Installing the code
+==========================
+
+The JPWL code is integrated with the standard OpenJPEG library and codecs: it is activated by setting the macro USE_JPWL to defined in the preprocessor configuration options of your preferred C compiler.
+
+2.1. Compiling the source code in Windows
+-------------------------------------------
+
+The "jpwl" directory is already populated with a couple of Visual C++ 6.0 workspaces
+
+ * JPWL_image_to_j2k.dsw - Creates the encoder with JPWL functionalities
+ * JPWL_j2k_to_image.dsw - Creates the decoder with JPWL functionalities
+
+2.2. Compiling the source code in Unix-like systems
+-----------------------------------------------------
+
+Under linux, enter the jpwl directory and type "make clean" and "make".
+
+
+3. Running the JPWL software
+=========================
+
+The options available at the command line are exactly the same of the base OpenJPEG codecs. In addition, there is a "-W" switch that activates JPWL functionalities.
+
+3.1. JPWL Encoder
+-------------------
+
+-W : adoption of JPWL (Part 11) capabilities (-W params)
+ The parameters can be written and repeated in any order:
+ [h<tile><=type>,s<tile><=method>,a=<addr>,z=<size>,g=<range>,...
+ ...,p<tile:pack><=type>]
+
+ h selects the header error protection (EPB): 'type' can be
+ [0=none 1,absent=predefined 16=CRC-16 32=CRC-32 37-128=RS]
+ if 'tile' is absent, it applies to main and tile headers
+ if 'tile' is present, it applies from that tile
+ onwards, up to the next h<tile> spec, or to the last tile
+ in the codestream (max. 16 specs)
+
+ p selects the packet error protection (EEP/UEP with EPBs)
+ to be applied to raw data: 'type' can be
+ [0=none 1,absent=predefined 16=CRC-16 32=CRC-32 37-128=RS]
+ if 'tile:pack' is absent, it starts from tile 0, packet 0
+ if 'tile:pack' is present, it applies from that tile
+ and that packet onwards, up to the next packet spec
+ or to the last packet in the last tile in the codestream
+ (max. 16 specs)
+
+ s enables sensitivity data insertion (ESD): 'method' can be
+ [-1=NO ESD 0=RELATIVE ERROR 1=MSE 2=MSE REDUCTION 3=PSNR
+ 4=PSNR INCREMENT 5=MAXERR 6=TSE 7=RESERVED]
+ if 'tile' is absent, it applies to main header only
+ if 'tile' is present, it applies from that tile
+ onwards, up to the next s<tile> spec, or to the last tile
+ in the codestream (max. 16 specs)
+
+ g determines the addressing mode: <range> can be
+ [0=PACKET 1=BYTE RANGE 2=PACKET RANGE]
+
+ a determines the size of data addressing: <addr> can be
+ 2/4 bytes (small/large codestreams). If not set, auto-mode
+
+ z determines the size of sensitivity values: <size> can be
+ 1/2 bytes, for the transformed pseudo-floating point value
+
+ ex.:
+ h,h0=64,h3=16,h5=32,p0=78,p0:24=56,p1,p3:0=0,p3:20=32,s=0,s0=6,s3=-1,a=0,g=1,z=1
+ means
+ predefined EPB in MH, rs(64,32) from TPH 0 to TPH 2,
+ CRC-16 in TPH 3 and TPH 4, CRC-32 in remaining TPHs,
+ UEP rs(78,32) for packets 0 to 23 of tile 0,
+ UEP rs(56,32) for packets 24 to the last of tile 0,
+ UEP rs default for packets of tile 1,
+ no UEP for packets 0 to 19 of tile 3,
+ UEP CRC-32 for packets 20 of tile 3 to last tile,
+ relative sensitivity ESD for MH,
+ TSE ESD from TPH 0 to TPH 2, byte range with automatic
+ size of addresses and 1 byte for each sensitivity value
+
+ ex.:
+ h,s,p
+ means
+ default protection to headers (MH and TPHs) as well as
+ data packets, one ESD in MH
+
+ N.B.: use the following recommendations when specifying
+ the JPWL parameters list
+ - when you use UEP, always pair the 'p' option with 'h'
+
+3.2. JPWL Decoder
+-------------------
+
+ -W <options>
+ Activates the JPWL correction capability, if the codestream complies.
+ Options can be a comma separated list of <param=val> tokens:
+ c, c=numcomps
+ numcomps is the number of expected components in the codestream
+ (search of first EPB rely upon this, default is 3)
+
+
+4. Known bugs and limitations
+===============================
+
+4.1. Bugs
+-----------
+
+* It is not possible to save a JPWL encoded codestream using the wrapped file format (i.e. JP2): only raw file format (i.e. J2K) is working
+
+4.2. Limitations
+------------------
+
+* When specifying an UEP protection, you need to activate even TPH protection for those tiles where there is a protection of the packets
+* RED insertion is not currently implemented at the decoder
+* JPWL at entropy coding level is not implemented
diff --git a/src/lib/openjpwl/crc.c b/src/lib/openjpwl/crc.c
new file mode 100644
index 00000000..6a4a7d8f
--- /dev/null
+++ b/src/lib/openjpwl/crc.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 USE_JPWL
+
+#include "crc.h"
+
+/**
+@file crc.c
+@brief Functions used to compute the 16- and 32-bit CRC of byte arrays
+
+*/
+
+/** file: CRC16.CPP
+ *
+ * CRC - Cyclic Redundancy Check (16-bit)
+ *
+ * A CRC-checksum is used to be sure, the data hasn't changed or is false.
+ * To create a CRC-checksum, initialise a check-variable (unsigned short),
+ * and set this to zero. Than call for every byte in the file (e.g.) the
+ * procedure updateCRC16 with this check-variable as the first parameter,
+ * and the byte as the second. At the end, the check-variable contains the
+ * CRC-checksum.
+ *
+ * implemented by Michael Neumann, 14.06.1998
+ *
+ */
+const unsigned short CRC16_table[256] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+void updateCRC16(unsigned short *crc, unsigned char data) {
+ *crc = CRC16_table[(*crc >> 8) & 0xFF] ^ (*crc << 8) ^ data;
+}
+
+
+/** file: CRC32.CPP
+ *
+ * CRC - Cyclic Redundancy Check (32-bit)
+ *
+ * A CRC-checksum is used to be sure, the data hasn't changed or is false.
+ * To create a CRC-checksum, initialise a check-variable (unsigned long),
+ * and set this to zero. Than call for every byte in the file (e.g.) the
+ * procedure updateCRC32 with this check-variable as the first parameter,
+ * and the byte as the second. At the end, the check-variable contains the
+ * CRC-checksum.
+ *
+ * implemented by Michael Neumann, 14.06.1998
+ *
+ */
+const unsigned long CRC32_table[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+void updateCRC32(unsigned long *crc, unsigned char data) {
+ *crc = CRC32_table[(unsigned char) *crc ^ data] ^ ((*crc >> 8) & 0x00FFFFFF);
+}
+
+#endif /* USE_JPWL */
diff --git a/src/lib/openjpwl/crc.h b/src/lib/openjpwl/crc.h
new file mode 100644
index 00000000..4ea2c4ce
--- /dev/null
+++ b/src/lib/openjpwl/crc.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 USE_JPWL
+
+/**
+@file crc.h
+@brief Functions used to compute the 16- and 32-bit CRC of byte arrays
+
+*/
+
+#ifndef __CRC16_HEADER__
+#define __CRC16_HEADER__
+
+/** file: CRC16.HPP
+ *
+ * CRC - Cyclic Redundancy Check (16-bit)
+ *
+ * A CRC-checksum is used to be sure, the data hasn't changed or is false.
+ * To create a CRC-checksum, initialise a check-variable (unsigned short),
+ * and set this to zero. Than call for every byte in the file (e.g.) the
+ * procedure updateCRC16 with this check-variable as the first parameter,
+ * and the byte as the second. At the end, the check-variable contains the
+ * CRC-checksum.
+ *
+ * implemented by Michael Neumann, 14.06.1998
+ *
+ */
+void updateCRC16(unsigned short *, unsigned char);
+
+#endif /* __CRC16_HEADER__ */
+
+
+#ifndef __CRC32_HEADER__
+#define __CRC32_HEADER__
+
+/** file: CRC32.HPP
+ *
+ * CRC - Cyclic Redundancy Check (32-bit)
+ *
+ * A CRC-checksum is used to be sure, the data hasn't changed or is false.
+ * To create a CRC-checksum, initialise a check-variable (unsigned short),
+ * and set this to zero. Than call for every byte in the file (e.g.) the
+ * procedure updateCRC32 with this check-variable as the first parameter,
+ * and the byte as the second. At the end, the check-variable contains the
+ * CRC-checksum.
+ *
+ * implemented by Michael Neumann, 14.06.1998
+ *
+ */
+void updateCRC32(unsigned long *, unsigned char);
+
+#endif /* __CRC32_HEADER__ */
+
+
+#endif /* USE_JPWL */
diff --git a/src/lib/openjpwl/jpwl.c b/src/lib/openjpwl/jpwl.c
new file mode 100644
index 00000000..ba8cac5a
--- /dev/null
+++ b/src/lib/openjpwl/jpwl.c
@@ -0,0 +1,1380 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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"
+
+#ifdef USE_JPWL
+
+/** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */
+/*@{*/
+
+/** @name Local static variables */
+/*@{*/
+
+/** number of JPWL prepared markers */
+static int jwmarker_num;
+/** properties of JPWL markers to insert */
+static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS];
+
+/*@}*/
+
+/*@}*/
+
+/** @name Local static functions */
+/*@{*/
+
+/** create an EPC marker segment
+@param j2k J2K compressor handle
+@param esd_on true if ESD is activated
+@param red_on true if RED is activated
+@param epb_on true if EPB is activated
+@param info_on true if informative techniques are activated
+@return returns the freshly created EPC
+*/
+jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on);
+
+/*@}*/
+
+/** create an EPC marker segment
+@param j2k J2K compressor handle
+@param comps considered component (-1=average, 0/1/2/...=component no.)
+@param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)
+@param ad_size size of addresses (2/4 bytes)
+@param senst sensitivity type
+@param se_size sensitivity values size (1/2 bytes)
+@param tileno tile where this ESD lies (-1 means MH)
+@param svalnum number of sensitivity values (if 0, they will be automatically filled)
+@param sensval pointer to an array of sensitivity values (if NULL, they will be automatically filled)
+@return returns the freshly created ESD
+*/
+jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comps,
+ unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, int se_size, int tileno,
+ unsigned long int svalnum, void *sensval);
+
+/** this function is used to compare two JPWL markers based on
+their relevant wishlist position
+@param arg1 pointer to first marker
+@param arg2 pointer to second marker
+@return 1 if arg1>arg2, 0 if arg1=arg2, -1 if arg1<arg2
+*/
+int jpwl_markcomp(const void *arg1, const void *arg2);
+
+/** write an EPB MS to a buffer
+@param j2k J2K compressor handle
+@param epbmark pointer to the EPB MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf);
+
+/** write an EPC MS to a buffer
+@param j2k J2K compressor handle
+@param epcmark pointer to the EPC MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epcmark, unsigned char *buf);
+
+/**
+ * write an ESD MS to a buffer
+@param j2k J2K compressor handle
+@param esd pointer to the ESD MS
+@param buf pointer to the memory buffer
+*/
+void jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);
+
+/*-----------------------------------------------------------------*/
+
+void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+ int mm;
+
+ /* let's reset some settings */
+
+ /* clear the existing markers */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+
+ switch (jwmarker[mm].id) {
+
+ case J2K_MS_EPB:
+ opj_free(jwmarker[mm].m.epbmark);
+ break;
+
+ case J2K_MS_EPC:
+ opj_free(jwmarker[mm].m.epcmark);
+ break;
+
+ case J2K_MS_ESD:
+ opj_free(jwmarker[mm].m.esdmark);
+ break;
+
+ case J2K_MS_RED:
+ opj_free(jwmarker[mm].m.redmark);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* clear the marker structure array */
+ memset(jwmarker, 0, sizeof(jpwl_marker_t) * JPWL_MAX_NO_MARKERS);
+
+ /* no more markers in the list */
+ jwmarker_num = 0;
+
+ /* let's begin creating a marker list, according to user wishes */
+ jpwl_prepare_marks(j2k, cio, image);
+
+ /* now we dump the JPWL markers on the codestream */
+ jpwl_dump_marks(j2k, cio, image);
+
+ /* do not know exactly what is this for,
+ but it gets called during index creation */
+ j2k->pos_correction = 0;
+
+}
+
+opj_bool j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
+
+ if (!cstr_info)
+ return OPJ_FALSE;
+
+ /* expand the list? */
+ if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {
+ opj_marker_info_t* new_marker;
+ cstr_info->maxmarknum += 100;
+ new_marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum * sizeof(opj_marker_info_t));
+ if (! new_marker)
+ {
+ opj_free(cstr_info->marker);
+ cstr_info->marker = 0;
+ cstr_info->marknum = 0;
+ cstr_info->maxmarknum = 0;
+ /* opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to add a marker\n"); */
+ /* TODO_test_add_marker_result;*/
+ return OPJ_FALSE;
+ }
+ cstr_info->marker = new_marker;
+ }
+
+ /* add the marker */
+ cstr_info->marker[cstr_info->marknum].type = type;
+ cstr_info->marker[cstr_info->marknum].pos = pos;
+ cstr_info->marker[cstr_info->marknum].len = len;
+ cstr_info->marknum++;
+ return OPJ_TRUE;
+
+}
+
+void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+ unsigned short int socsiz_len = 0;
+ int ciopos = cio_tell(cio), soc_pos = j2k->cstr_info->main_head_start;
+ unsigned char *socp = NULL;
+
+ int tileno, acc_tpno, tpno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;
+
+ jpwl_epb_ms_t *epb_mark;
+ jpwl_epc_ms_t *epc_mark;
+ jpwl_esd_ms_t *esd_mark;
+ (void)image;
+
+ /* find (SOC + SIZ) length */
+ /* I assume SIZ is always the first marker after SOC */
+ cio_seek(cio, soc_pos + 4);
+ socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */
+ cio_seek(cio, soc_pos + 0);
+ socp = cio_getbp(cio); /* pointer to SOC */
+
+ /*
+ EPC MS for Main Header: if we are here it's required
+ */
+ /* create the EPC */
+ if ((epc_mark = jpwl_epc_create(
+ j2k,
+ j2k->cp->esd_on, /* is ESD present? */
+ j2k->cp->red_on, /* is RED present? */
+ j2k->cp->epb_on, /* is EPB present? */
+ OPJ_FALSE /* are informative techniques present? */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (epc_mark) {
+ jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */
+ jwmarker[jwmarker_num].m.epcmark = epc_mark; /* the EPC */
+ jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
+ jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */
+ jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */
+ jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].parms_ready = OPJ_FALSE; /* not ready */
+ jwmarker[jwmarker_num].data_ready = OPJ_TRUE; /* ready */
+ jwmarker_num++;
+ };
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "MH EPC : setting %s%s%s\n",
+ j2k->cp->esd_on ? "ESD, " : "",
+ j2k->cp->red_on ? "RED, " : "",
+ j2k->cp->epb_on ? "EPB, " : ""
+ );
+
+ } else {
+ /* ooops, problems */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");
+ };
+
+ /*
+ ESD MS for Main Header
+ */
+ /* first of all, must MH have an ESD MS? */
+ if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {
+
+ /* Create the ESD */
+ if ((esd_mark = jpwl_esd_create(
+ j2k, /* this encoder handle */
+ -1, /* we are averaging over all components */
+ (unsigned char) j2k->cp->sens_range, /* range method */
+ (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */
+ (unsigned char) j2k->cp->sens_MH, /* sensitivity method */
+ j2k->cp->sens_size, /* sensitivity size */
+ -1, /* this ESD is in main header */
+ 0 /*j2k->cstr_info->num*/, /* number of packets in codestream */
+ NULL /*sensval*/ /* pointer to sensitivity data of packets */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
+ jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
+ jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* we choose to place it after SIZ */
+ jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
+ jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
+ jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* not ready, yet */
+ jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
+ jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+ jwmarker_num++;
+ }
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "MH ESDs: method %d\n",
+ j2k->cp->sens_MH
+ );
+
+ } else {
+ /* ooops, problems */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");
+ };
+
+ }
+
+ /*
+ ESD MSs for Tile Part Headers
+ */
+ /* cycle through tiles */
+ sens = -1; /* default spec: no ESD */
+ tilespec = 0; /* first tile spec */
+ acc_tpno = 0;
+ for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "Tile %d has %d tile part(s)\n",
+ tileno, j2k->cstr_info->tile[tileno].num_tps
+ );
+
+ /* for every tile part in the tile */
+ for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {
+
+ int sot_len, Psot, Psotp, mm;
+ unsigned long sot_pos, post_sod_pos;
+
+ unsigned long int left_THmarks_len;
+
+ /******* sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
+ sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
+ cio_seek(cio, sot_pos + 2);
+ sot_len = cio_read(cio, 2); /* SOT Len */
+ cio_skip(cio, 2);
+ Psotp = cio_tell(cio);
+ Psot = cio_read(cio, 4); /* tile length */
+
+ /******* post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
+ post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
+ left_THmarks_len = post_sod_pos - sot_pos;
+
+ /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+ if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
+ if (jwmarker[mm].len_ready)
+ left_THmarks_len += jwmarker[mm].len + 2;
+ else {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
+ jwmarker[mm].id, jwmarker[mm].dpos);
+ exit(1);
+ }
+ }
+ }
+
+ /******* if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno)) */
+ if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == acc_tpno))
+ /* we got a specification from this tile onwards */
+ sens = j2k->cp->sens_TPH[tilespec++];
+
+ /* must this TPH have an ESD MS? */
+ if (j2k->cp->esd_on && (sens >= 0)) {
+
+ /* Create the ESD */
+ if ((esd_mark = jpwl_esd_create(
+ j2k, /* this encoder handle */
+ -1, /* we are averaging over all components */
+ (unsigned char) j2k->cp->sens_range, /* range method */
+ (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */
+ (unsigned char) sens, /* sensitivity method */
+ j2k->cp->sens_size, /* sensitivity value size */
+ tileno, /* this ESD is in a tile */
+ 0, /* number of packets in codestream */
+ NULL /* pointer to sensitivity data of packets */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */
+ jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */
+ /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
+ jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
+ jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */
+ jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */
+ jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready, yet */
+ jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */
+ jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* ready */
+ jwmarker_num++;
+ }
+
+ /* update Psot of the tile */
+ cio_seek(cio, Psotp);
+ cio_write(cio, Psot + esd_mark->Lesd + 2, 4);
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ /******* "TPH ESDs: tile %02d, method %d\n", */
+ "TPH ESDs: tile %02d, part %02d, method %d\n",
+ /******* tileno, */
+ tileno, tpno,
+ sens
+ );
+
+ } else {
+ /* ooops, problems */
+ /***** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno); */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d,%d\n", tileno, tpno);
+ };
+
+ }
+
+ }
+
+ };
+
+ /*
+ EPB MS for Main Header
+ */
+ /* first of all, must MH have an EPB MS? */
+ if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {
+
+ int mm;
+
+ /* position of SOT */
+ unsigned int sot_pos = j2k->cstr_info->main_head_end + 1;
+
+ /* how much space is there between end of SIZ and beginning of SOT? */
+ int left_MHmarks_len = sot_pos - socsiz_len;
+
+ /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+ if ( jwmarker[mm].pos < sot_pos) { /* jwmarker[mm].pos >=0 since ulong */
+ if (jwmarker[mm].len_ready)
+ left_MHmarks_len += jwmarker[mm].len + 2;
+ else {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",
+ jwmarker[mm].id, jwmarker[mm].dpos);
+ exit(1);
+ }
+ }
+ }
+
+ /* Create the EPB */
+ if ((epb_mark = jpwl_epb_create(
+ j2k, /* this encoder handle */
+ OPJ_TRUE, /* is it the latest? */
+ OPJ_TRUE, /* is it packed? not for now */
+ -1, /* we are in main header */
+ 0, /* its index is 0 (first) */
+ j2k->cp->hprot_MH, /* protection type parameters of data */
+ socsiz_len, /* pre-data: only SOC+SIZ */
+ left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */
+ jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */
+ jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */
+ jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
+ jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
+ jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+ jwmarker_num++;
+ }
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "MH EPB : prot. %d\n",
+ j2k->cp->hprot_MH
+ );
+
+ } else {
+ /* ooops, problems */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");
+ };
+ }
+
+ /*
+ EPB MSs for Tile Parts
+ */
+ /* cycle through TPHs */
+ hprot = j2k->cp->hprot_MH; /* default spec */
+ tilespec = 0; /* first tile spec */
+ lastileno = 0;
+ packspec = 0;
+ pprot = -1;
+ acc_tpno = 0;
+ for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "Tile %d has %d tile part(s)\n",
+ tileno, j2k->cstr_info->tile[tileno].num_tps
+ );
+
+ /* for every tile part in the tile */
+ for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {
+
+ int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;
+ unsigned long sot_pos, post_sod_pos;
+ unsigned long int left_THmarks_len/*, epbs_len = 0*/;
+ int startpack = 0, stoppack = j2k->cstr_info->packno;
+ int first_tp_pack, last_tp_pack;
+ jpwl_epb_ms_t *tph_epb = NULL;
+
+ /****** sot_pos = j2k->cstr_info->tile[tileno].start_pos; */
+ sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;
+ cio_seek(cio, sot_pos + 2);
+ sot_len = cio_read(cio, 2); /* SOT Len */
+ cio_skip(cio, 2);
+ Psotp = cio_tell(cio);
+ Psot = cio_read(cio, 4); /* tile length */
+
+ /* a-priori length of the data dwelling between SOT and SOD */
+ /****** post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */
+ post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;
+ left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);
+
+ /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+ if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {
+ if (jwmarker[mm].len_ready)
+ left_THmarks_len += jwmarker[mm].len + 2;
+ else {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",
+ jwmarker[mm].id, jwmarker[mm].dpos);
+ exit(1);
+ }
+ }
+ }
+
+ /****** if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno)) */
+ if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == acc_tpno))
+ /* we got a specification from this tile part onwards */
+ hprot = j2k->cp->hprot_TPH[tilespec++];
+
+ /* must this TPH have an EPB MS? */
+ if (j2k->cp->epb_on && (hprot > 0)) {
+
+ /* Create the EPB */
+ if ((epb_mark = jpwl_epb_create(
+ j2k, /* this encoder handle */
+ OPJ_FALSE, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */
+ OPJ_TRUE, /* is it packed? yes for now */
+ tileno, /* we are in TPH */
+ epb_index++, /* its index is 0 (first) */
+ hprot, /* protection type parameters of following data */
+ sot_len + 2, /* pre-data length: only SOT */
+ left_THmarks_len /* post-data length: from SOT end to SOD inclusive */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */
+ jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */
+ /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */
+ jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */
+ jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */
+ jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */
+ jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
+ jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+ jwmarker_num++;
+ }
+
+ /* update Psot of the tile */
+ Psot += epb_mark->Lepb + 2;
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ /***** "TPH EPB : tile %02d, prot. %d\n", */
+ "TPH EPB : tile %02d, part %02d, prot. %d\n",
+ /***** tileno, */
+ tileno, tpno,
+ hprot
+ );
+
+ /* save this TPH EPB address */
+ tph_epb = epb_mark;
+
+ } else {
+ /* ooops, problems */
+ /****** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno); */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB in #%d,d\n", tileno, tpno);
+ };
+
+ }
+
+ startpack = 0;
+ /* EPB MSs for UEP packet data protection in Tile Parts */
+ /****** for (packno = 0; packno < j2k->cstr_info->num; packno++) { */
+ /*first_tp_pack = (tpno > 0) ? (first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno - 1].tp_numpacks) : 0;*/
+ first_tp_pack = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pack;
+ last_tp_pack = first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks - 1;
+ for (packno = 0; packno < j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks; packno++) {
+
+ /******** if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
+ (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) { */
+ if ((packspec < JPWL_MAX_NO_PACKSPECS) &&
+ (j2k->cp->pprot_tileno[packspec] == acc_tpno) && (j2k->cp->pprot_packno[packspec] == packno)) {
+
+ /* we got a specification from this tile and packet onwards */
+ /* print the previous spec */
+ if (packno > 0) {
+ stoppack = packno - 1;
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ /***** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
+ "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
+ /***** tileno, */
+ tileno, tpno,
+ startpack,
+ stoppack,
+ /***** j2k->cstr_info->tile[tileno].packet[startpack].start_pos, */
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
+ /***** j2k->cstr_info->tile[tileno].packet[stoppack].end_pos, */
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
+ pprot);
+
+ /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
+ j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
+ prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
+
+ /*
+ particular case: if this is the last header and the last packet,
+ then it is better to protect even the EOC marker
+ */
+ /****** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+ (stoppack == (j2k->cstr_info->num - 1))) */
+ if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+ (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
+ (stoppack == last_tp_pack))
+ /* add the EOC len */
+ prot_len += 2;
+
+ /* let's add the EPBs */
+ Psot += jpwl_epbs_add(
+ j2k, /* J2K handle */
+ jwmarker, /* pointer to JPWL markers list */
+ &jwmarker_num, /* pointer to the number of current markers */
+ OPJ_FALSE, /* latest */
+ OPJ_TRUE, /* packed */
+ OPJ_FALSE, /* inside MH */
+ &epb_index, /* pointer to EPB index */
+ pprot, /* protection type */
+ /****** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, */ /* position */
+ (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
+ tileno, /* number of tile */
+ 0, /* length of pre-data */
+ prot_len /*4000*/ /* length of post-data */
+ );
+ }
+
+ startpack = packno;
+ pprot = j2k->cp->pprot[packspec++];
+ }
+
+ /*printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);*/
+
+ }
+
+ /* we are at the end: print the remaining spec */
+ stoppack = packno - 1;
+ if (pprot >= 0) {
+
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ /**** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */
+ "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",
+ /**** tileno, */
+ tileno, tpno,
+ startpack,
+ stoppack,
+ /***** j2k->image_info->tile[tileno].packet[startpack].start_pos,
+ j2k->image_info->tile[tileno].packet[stoppack].end_pos, */
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,
+ pprot);
+
+ /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -
+ j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */
+ prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -
+ j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;
+
+ /*
+ particular case: if this is the last header and the last packet,
+ then it is better to protect even the EOC marker
+ */
+ /***** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+ (stoppack == (j2k->cstr_info->num - 1))) */
+ if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&
+ (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&
+ (stoppack == last_tp_pack))
+ /* add the EOC len */
+ prot_len += 2;
+
+ /* let's add the EPBs */
+ Psot += jpwl_epbs_add(
+ j2k, /* J2K handle */
+ jwmarker, /* pointer to JPWL markers list */
+ &jwmarker_num, /* pointer to the number of current markers */
+ OPJ_TRUE, /* latest */
+ OPJ_TRUE, /* packed */
+ OPJ_FALSE, /* inside MH */
+ &epb_index, /* pointer to EPB index */
+ pprot, /* protection type */
+ /***** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001,*/ /* position */
+ (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */
+ tileno, /* number of tile */
+ 0, /* length of pre-data */
+ prot_len /*4000*/ /* length of post-data */
+ );
+ }
+
+ /* we can now check if the TPH EPB was really the last one */
+ if (tph_epb && (epb_index == 1)) {
+ /* set the TPH EPB to be the last one in current header */
+ tph_epb->Depb |= (unsigned char) ((OPJ_TRUE & 0x0001) << 6);
+ tph_epb = NULL;
+ }
+
+ /* write back Psot */
+ cio_seek(cio, Psotp);
+ cio_write(cio, Psot, 4);
+
+ }
+
+ };
+
+ /* reset the position */
+ cio_seek(cio, ciopos);
+
+}
+
+void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {
+
+ int mm;
+ unsigned long int old_size = j2k->cstr_info->codestream_size;
+ unsigned long int new_size = old_size;
+ int /*ciopos = cio_tell(cio),*/ soc_pos = j2k->cstr_info->main_head_start;
+ unsigned char *jpwl_buf, *orig_buf;
+ unsigned long int orig_pos;
+ double epbcoding_time = 0.0, esdcoding_time = 0.0;
+ (void)image;
+
+ /* Order JPWL markers according to their wishlist position */
+ qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);
+
+ /* compute markers total size */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+ /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,
+ jwmarker[mm].dpos, jwmarker[mm].len);*/
+ new_size += jwmarker[mm].len + 2;
+ }
+
+ /* allocate a new buffer of proper size */
+ if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) (new_size + soc_pos) * sizeof(unsigned char)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL codestream buffer\n");
+ exit(1);
+ };
+
+ /* copy the jp2 part, if any */
+ orig_buf = jpwl_buf;
+ memcpy(jpwl_buf, cio->buffer, soc_pos);
+ jpwl_buf += soc_pos;
+
+ /* cycle through markers */
+ orig_pos = soc_pos + 0; /* start from the beginning */
+ cio_seek(cio, soc_pos + 0); /* rewind the original */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+
+ /*
+ need to copy a piece of the original codestream
+ if there is such
+ */
+ memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);
+ jpwl_buf += jwmarker[mm].pos - orig_pos;
+ orig_pos = jwmarker[mm].pos;
+ cio_seek(cio, orig_pos);
+
+ /*
+ then write down the marker
+ */
+ switch (jwmarker[mm].id) {
+
+ case J2K_MS_EPB:
+ jpwl_epb_write(j2k, jwmarker[mm].m.epbmark, jpwl_buf);
+ break;
+
+ case J2K_MS_EPC:
+ jpwl_epc_write(j2k, jwmarker[mm].m.epcmark, jpwl_buf);
+ break;
+
+ case J2K_MS_ESD:
+ jpwl_esd_write(j2k, jwmarker[mm].m.esdmark, jpwl_buf);
+ break;
+
+ case J2K_MS_RED:
+ memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */
+ break;
+
+ default:
+ break;
+ };
+
+ /* we update the markers struct */
+ if (j2k->cstr_info)
+ j2k->cstr_info->marker[j2k->cstr_info->marknum - 1].pos = (jpwl_buf - orig_buf);
+
+ /* we set the marker dpos to the new position in the JPWL codestream */
+ jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);
+
+ /* advance JPWL buffer position */
+ jpwl_buf += jwmarker[mm].len + 2;
+
+ }
+
+ /* finish remaining original codestream */
+ memcpy(jpwl_buf, cio_getbp(cio), old_size - (orig_pos - soc_pos));
+ jpwl_buf += old_size - (orig_pos - soc_pos);
+ cio_seek(cio, soc_pos + old_size);
+
+ /*
+ update info file based on added markers
+ */
+ if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ cstr_info structure\n");
+
+ /* now we need to repass some markers and fill their data fields */
+
+ /* first of all, DL and Pcrc in EPCs */
+ for (mm = 0; mm < jwmarker_num; mm++) {
+
+ /* find the EPCs */
+ if (jwmarker[mm].id == J2K_MS_EPC) {
+
+ int epc_pos = (int) jwmarker[mm].dpos, pp;
+ unsigned short int mycrc = 0x0000;
+
+ /* fix and fill the DL field */
+ jwmarker[mm].m.epcmark->DL = new_size;
+ orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 24);
+ orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 16);
+ orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 8);
+ orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 0);
+
+ /* compute the CRC field (excluding itself) */
+ for (pp = 0; pp < 4; pp++)
+ jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
+ for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)
+ jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);
+
+ /* fix and fill the CRC */
+ jwmarker[mm].m.epcmark->Pcrc = mycrc;
+ orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 8);
+ orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 0);
+
+ }
+ }
+
+ /* then, sensitivity data in ESDs */
+ esdcoding_time = opj_clock();
+ for (mm = 0; mm < jwmarker_num; mm++) {
+
+ /* find the ESDs */
+ if (jwmarker[mm].id == J2K_MS_ESD) {
+
+ /* remember that they are now in a new position (dpos) */
+ int esd_pos = (int) jwmarker[mm].dpos;
+
+ jpwl_esd_fill(j2k, jwmarker[mm].m.esdmark, &orig_buf[esd_pos]);
+
+ }
+
+ }
+ esdcoding_time = opj_clock() - esdcoding_time;
+ if (j2k->cp->esd_on)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);
+
+ /* finally, RS or CRC parity in EPBs */
+ epbcoding_time = opj_clock();
+ for (mm = 0; mm < jwmarker_num; mm++) {
+
+ /* find the EPBs */
+ if (jwmarker[mm].id == J2K_MS_EPB) {
+
+ /* remember that they are now in a new position (dpos) */
+ int nn, accum_len;
+
+ /* let's see how many EPBs are following this one, included itself */
+ /* for this to work, we suppose that the markers are correctly ordered */
+ /* and, overall, that they are in packed mode inside headers */
+ accum_len = 0;
+ for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
+ (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
+ accum_len += jwmarker[nn].m.epbmark->Lepb + 2;
+
+ /* fill the current (first) EPB with post-data starting from the computed position */
+ jpwl_epb_fill(j2k, jwmarker[mm].m.epbmark, &orig_buf[(int) jwmarker[mm].dpos],
+ &orig_buf[(int) jwmarker[mm].dpos + accum_len]);
+
+ /* fill the remaining EPBs in the header with post-data starting from the last position */
+ for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&
+ (jwmarker[nn].pos == jwmarker[mm].pos); nn++)
+ jpwl_epb_fill(j2k, jwmarker[nn].m.epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);
+
+ /* skip all the processed EPBs */
+ mm = nn - 1;
+ }
+
+ }
+ epbcoding_time = opj_clock() - epbcoding_time;
+ if (j2k->cp->epb_on)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);
+
+ /* free original cio buffer and set it to the JPWL one */
+ opj_free(cio->buffer);
+ cio->cinfo = cio->cinfo; /* no change */
+ cio->openmode = cio->openmode; /* no change */
+ cio->buffer = orig_buf;
+ cio->length = new_size + soc_pos;
+ cio->start = cio->buffer;
+ cio->end = cio->buffer + cio->length;
+ cio->bp = cio->buffer;
+ cio_seek(cio, soc_pos + new_size);
+
+}
+
+
+void j2k_read_epc(opj_j2k_t *j2k) {
+ unsigned long int DL, Lepcp, Pcrcp, l;
+ unsigned short int Lepc, Pcrc = 0x0000;
+ unsigned char Pepc;
+ opj_cio_t *cio = j2k->cio;
+ const char *ans1;
+
+ /* Simply read the EPC parameters */
+ Lepcp = cio_tell(cio);
+ Lepc = cio_read(cio, 2);
+ Pcrcp = cio_tell(cio);
+ cio_skip(cio, 2); /* Pcrc */
+ DL = cio_read(cio, 4);
+ Pepc = cio_read(cio, 1);
+
+ /* compute Pcrc */
+ cio_seek(cio, Lepcp - 2);
+
+ /* Marker */
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* Length */
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* skip Pcrc */
+ cio_skip(cio, 2);
+
+ /* read all remaining */
+ for (l = 4; l < Lepc; l++)
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* check Pcrc with the result */
+ cio_seek(cio, Pcrcp);
+ ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";
+
+ /* now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "EPC(%u,%d): %s, DL=%d%s %s %s\n",
+ Lepcp - 2,
+ Lepc,
+ ans1,
+ DL, /* data length this EPC is referring to */
+ (Pepc & 0x10) ? ", esd" : "", /* ESD is present */
+ (Pepc & 0x20) ? ", red" : "", /* RED is present */
+ (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */
+
+ cio_seek(cio, Lepcp + Lepc);
+}
+
+#if 0
+void j2k_write_epc(opj_j2k_t *j2k) {
+
+ unsigned long int DL, Lepcp, Pcrcp, l;
+ unsigned short int Lepc, Pcrc;
+ unsigned char Pepc;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_EPC, 2); /* EPC */
+ Lepcp = cio_tell(cio);
+ cio_skip(cio, 2);
+
+ /* CRC-16 word of the EPC */
+ Pcrc = 0x0000; /* initialize */
+ Pcrcp = cio_tell(cio);
+ cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/
+
+ /* data length of the EPC protection domain */
+ DL = 0x00000000; /* we leave this set to 0, as if the information is not available */
+ cio_write(cio, DL, 4); /* DL */
+
+ /* jpwl capabilities */
+ Pepc = 0x00;
+ cio_write(cio, Pepc, 1); /* Pepc */
+
+ /* ID section */
+ /* no ID's, as of now */
+
+ Lepc = (unsigned short) (cio_tell(cio) - Lepcp);
+ cio_seek(cio, Lepcp);
+ cio_write(cio, Lepc, 2); /* Lepc */
+
+ /* compute Pcrc */
+ cio_seek(cio, Lepcp - 2);
+
+ /* Marker */
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* Length */
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* skip Pcrc */
+ cio_skip(cio, 2);
+
+ /* read all remaining */
+ for (l = 4; l < Lepc; l++)
+ jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1));
+
+ /* fill Pcrc with the result */
+ cio_seek(cio, Pcrcp);
+ cio_write(cio, Pcrc, 2);
+
+ cio_seek(cio, Lepcp + Lepc);
+
+ /* marker struct update */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, Lepcp - 2, Lepc + 2);
+
+}
+#endif
+
+void j2k_read_epb(opj_j2k_t *j2k) {
+ unsigned long int LDPepb, Pepb;
+ unsigned short int Lepb;
+ unsigned char Depb;
+ char str1[25] = "";
+ opj_bool status;
+ static opj_bool first_in_tph = OPJ_TRUE;
+ int type, pre_len, post_len;
+ static unsigned char *redund = NULL;
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* B/W = 45, RGB = 51 */
+ /* SIZ SIZ_FIELDS SIZ_COMPS FOLLOWING_MARKER */
+ int skipnum = 2 + 38 + 3 * j2k->cp->exp_comps + 2;
+
+ if (j2k->cp->correct) {
+
+ /* go back to EPB marker value */
+ cio_seek(cio, cio_tell(cio) - 2);
+
+ /* we need to understand where we are */
+ if (j2k->state == J2K_STATE_MH) {
+ /* we are in MH */
+ type = 0; /* MH */
+ pre_len = skipnum; /* SOC+SIZ */
+ post_len = -1; /* auto */
+
+ } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {
+ /* we are in TPH */
+ type = 1; /* TPH */
+ pre_len = 12; /* SOC+SIZ */
+ first_in_tph = OPJ_FALSE;
+ post_len = -1; /* auto */
+
+ } else {
+ /* we are elsewhere */
+ type = 2; /* other */
+ pre_len = 0; /* nada */
+ post_len = -1; /* auto */
+
+ }
+
+ /* call EPB corrector */
+ /*printf("before %x, ", redund);*/
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ type, /* EPB type: MH */
+ pre_len, /* length of pre-data */
+ post_len, /* length of post-data: -1 means auto */
+ NULL, /* do everything auto */
+ &redund
+ );
+ /*printf("after %x\n", redund);*/
+
+ /* Read the (possibly corrected) EPB parameters */
+ cio_skip(cio, 2);
+ Lepb = cio_read(cio, 2);
+ Depb = cio_read(cio, 1);
+ LDPepb = cio_read(cio, 4);
+ Pepb = cio_read(cio, 4);
+
+ if (!status) {
+
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");
+
+ /* advance to EPB endpoint */
+ cio_skip(cio, Lepb + 2);
+
+ return;
+ }
+
+ /* last in current header? */
+ if (Depb & 0x40) {
+ redund = NULL; /* reset the pointer to L4 buffer */
+ first_in_tph = OPJ_TRUE;
+ }
+
+ /* advance to EPB endpoint */
+ cio_skip(cio, Lepb - 11);
+
+ } else {
+
+ /* Simply read the EPB parameters */
+ Lepb = cio_read(cio, 2);
+ Depb = cio_read(cio, 1);
+ LDPepb = cio_read(cio, 4);
+ Pepb = cio_read(cio, 4);
+
+ /* What does Pepb tells us about the protection method? */
+ if (((Pepb & 0xF0000000) >> 28) == 0)
+ sprintf(str1, "pred"); /* predefined */
+ else if (((Pepb & 0xF0000000) >> 28) == 1)
+ sprintf(str1, "crc-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
+ else if (((Pepb & 0xF0000000) >> 28) == 2)
+ sprintf(str1, "rs(%lu,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
+ else if (Pepb == 0xFFFFFFFF)
+ sprintf(str1, "nometh"); /* RS mode */
+ else
+ sprintf(str1, "unknown"); /* unknown */
+
+ /* Now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
+ cio_tell(cio) - 13,
+ (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
+ (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
+ (Depb & 0x3F), /* EPB index value */
+ LDPepb, /*length of the data protected by the EPB */
+ str1); /* protection method */
+
+ cio_skip(cio, Lepb - 11);
+ }
+}
+
+void j2k_write_epb(opj_j2k_t *j2k) {
+ unsigned long int LDPepb, Pepb, Lepbp;
+ unsigned short int Lepb;
+ unsigned char Depb;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_EPB, 2); /* EPB */
+ Lepbp = cio_tell(cio);
+ cio_skip(cio, 2);
+
+ /* EPB style */
+ Depb = 0x00; /* test */
+ cio_write(cio, Depb, 1); /* Depb */
+
+ /* length of the data to be protected by this EPB */
+ LDPepb = 0x00000000; /* test */
+ cio_write(cio, LDPepb, 4); /* LDPepb */
+
+ /* next error correction tool */
+ Pepb = 0x00000000; /* test */
+ cio_write(cio, Pepb, 4); /* Pepb */
+
+ /* EPB data */
+ /* no data, as of now */
+
+ Lepb = (unsigned short) (cio_tell(cio) - Lepbp);
+ cio_seek(cio, Lepbp);
+ cio_write(cio, Lepb, 2); /* Lepb */
+
+ cio_seek(cio, Lepbp + Lepb);
+
+ /* marker struct update */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, Lepbp - 2, Lepb + 2);
+}
+
+void j2k_read_esd(opj_j2k_t *j2k) {
+ unsigned short int Lesd, Cesd;
+ unsigned char Pesd;
+
+ int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;
+
+ char str1[4][4] = {"p", "br", "pr", "res"};
+ char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* Simply read the ESD parameters */
+ Lesd = cio_read(cio, 2);
+ Cesd = cio_read(cio, cesdsize);
+ Pesd = cio_read(cio, 1);
+
+ /* Now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "ESD(%d): c%d, %s, %s, %s, %s, %s\n",
+ cio_tell(cio) - (5 + cesdsize),
+ Cesd, /* component number for this ESD */
+ str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */
+ str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */
+ ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",
+ ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",
+ (Pesd & (unsigned char) 0x01) ? "avgc" : "");
+
+ cio_skip(cio, Lesd - (3 + cesdsize));
+}
+
+void j2k_read_red(opj_j2k_t *j2k) {
+ unsigned short int Lred;
+ unsigned char Pred;
+ char str1[4][4] = {"p", "br", "pr", "res"};
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* Simply read the RED parameters */
+ Lred = cio_read(cio, 2);
+ Pred = cio_read(cio, 1);
+
+ /* Now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "RED(%d): %s, %dc, %s, %s\n",
+ cio_tell(cio) - 5,
+ str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */
+ (Pred & (unsigned char) 0x38) >> 3, /* corruption level */
+ ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */
+ (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */
+
+ cio_skip(cio, Lred - 3);
+}
+
+opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {
+
+#ifdef oerhgierhgvhreit4u
+ /*
+ we navigate through the tile and find possible invalid parameters:
+ this saves a lot of crashes!!!!!
+ */
+ int compno, resno, precno, /*layno,*/ bandno, blockno;
+ int numprecincts, numblocks;
+
+ /* this is the selected tile */
+ opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);
+
+ /* will keep the component */
+ opj_tcd_tilecomp_t *comp = NULL;
+
+ /* will keep the resolution */
+ opj_tcd_resolution_t *res;
+
+ /* will keep the subband */
+ opj_tcd_band_t *band;
+
+ /* will keep the precinct */
+ opj_tcd_precinct_t *prec;
+
+ /* will keep the codeblock */
+ opj_tcd_cblk_t *block;
+
+ /* check all tile components */
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ comp = &(tile->comps[compno]);
+
+ /* check all component resolutions */
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ res = &(comp->resolutions[resno]);
+ numprecincts = res->pw * res->ph;
+
+ /* check all the subbands */
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ band = &(res->bands[bandno]);
+
+ /* check all the precincts */
+ for (precno = 0; precno < numprecincts; precno++) {
+ prec = &(band->precincts[precno]);
+ numblocks = prec->ch * prec->cw;
+
+ /* check all the codeblocks */
+ for (blockno = 0; blockno < numblocks; blockno++) {
+ block = &(prec->cblks[blockno]);
+
+ /* x-origin is invalid */
+ if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",
+ block->x0, prec->x0, prec->x1);
+ if (!JPWL_ASSUME || JPWL_ASSUME)
+ return OPJ_FALSE;
+ };
+ }
+ }
+ }
+ }
+ }
+
+#else
+ (void)j2k;
+ (void)tcd;
+ (void)tileno;
+#endif
+
+ return OPJ_TRUE;
+}
+
+/*@}*/
+
+#endif /* USE_JPWL */
+
+
+#ifdef USE_JPSEC
+
+/** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */
+/*@{*/
+
+
+/** @name Local static functions */
+/*@{*/
+
+void j2k_read_sec(opj_j2k_t *j2k) {
+ unsigned short int Lsec;
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* Simply read the SEC length */
+ Lsec = cio_read(cio, 2);
+
+ /* Now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "SEC(%d)\n",
+ cio_tell(cio) - 2
+ );
+
+ cio_skip(cio, Lsec - 2);
+}
+
+void j2k_write_sec(opj_j2k_t *j2k) {
+ unsigned short int Lsec = 24;
+ int i;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_SEC, 2); /* SEC */
+ cio_write(cio, Lsec, 2);
+
+ /* write dummy data */
+ for (i = 0; i < Lsec - 2; i++)
+ cio_write(cio, 0, 1);
+}
+
+void j2k_read_insec(opj_j2k_t *j2k) {
+ unsigned short int Linsec;
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* Simply read the INSEC length */
+ Linsec = cio_read(cio, 2);
+
+ /* Now we write them to screen */
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "INSEC(%d)\n",
+ cio_tell(cio) - 2
+ );
+
+ cio_skip(cio, Linsec - 2);
+}
+
+
+/*@}*/
+
+/*@}*/
+
+#endif /* USE_JPSEC */
+
diff --git a/src/lib/openjpwl/jpwl.h b/src/lib/openjpwl/jpwl.h
new file mode 100644
index 00000000..52c1fbc2
--- /dev/null
+++ b/src/lib/openjpwl/jpwl.h
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 __JPWL_H
+#define __JPWL_H
+
+#ifdef USE_JPWL
+
+#include "crc.h"
+#include "rs.h"
+
+/**
+@file jpwl.h
+@brief The JPEG-2000 Part11 (JPWL) marker segments manager
+
+The functions in JPWL.C have for goal to read/write the markers added by JPWL.
+*/
+
+/** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */
+/*@{*/
+
+/**
+Assume a basic codestream structure, so you can resort better from uncorrected errors
+*/
+#define JPWL_ASSUME OPJ_TRUE
+
+/**
+EPB (Error Protection Block) Marker segment
+*/
+typedef struct jpwl_epb_ms {
+ /**@name Private fields set by epb_create */
+ /*@{*/
+ /** is the latest in header? */
+ opj_bool latest;
+ /** is it in packed mode? */
+ opj_bool packed;
+ /** TH where this marker has been placed (-1 means MH) */
+ int tileno;
+ /** index in current header (0-63) */
+ unsigned char index;
+ /** error protection method [-1=absent 0=none 1=predefined 16=CRC-16 32=CRC-32 37-128=RS] */
+ int hprot;
+ /** message word length of pre-data */
+ int k_pre;
+ /** code word length of pre-data */
+ int n_pre;
+ /** length of pre-data */
+ int pre_len;
+ /** message word length of post-data */
+ int k_post;
+ /** code word length of post-data */
+ int n_post;
+ /** length of post-data */
+ int post_len;
+ /*@}*/
+ /**@name Marker segment fields */
+ /*@{*/
+ /** two bytes for the length of EPB MS, exluding the marker itself (11 to 65535 bytes) */
+ unsigned short int Lepb;
+ /** single byte for the style */
+ unsigned char Depb;
+ /** four bytes, from 0 to 2^31-1 */
+ unsigned long int LDPepb;
+ /** four bytes, next error management method */
+ unsigned long int Pepb;
+ /** EPB data, variable size */
+ unsigned char *data;
+ /*@}*/
+} jpwl_epb_ms_t;
+
+/**
+EPC (Error Protection Capability) Marker segment
+*/
+typedef struct jpwl_epc_ms {
+ /** is ESD active? */
+ opj_bool esd_on;
+ /** is RED active? */
+ opj_bool red_on;
+ /** is EPB active? */
+ opj_bool epb_on;
+ /** are informative techniques active? */
+ opj_bool info_on;
+ /**@name Marker segment fields */
+ /*@{*/
+ /** two bytes for the length of EPC MS, exluding the marker itself (9 to 65535 bytes) */
+ unsigned short int Lepc;
+ /** two bytes, CRC for the EPC, excluding Pcrc itself */
+ unsigned short int Pcrc;
+ /** four bytes, the codestream length from SOC to EOC */
+ unsigned long int DL;
+ /** one byte, signals JPWL techniques adoption */
+ unsigned char Pepc;
+ /** EPC data, variable length */
+ unsigned char *data;
+ /*@}*/
+} jpwl_epc_ms_t;
+
+/**
+ESD (Error Sensitivity Descriptor) Marker segment
+*/
+typedef struct jpwl_esd_ms {
+ /** codestream addressing mode [0=packet, 1=byte range, 2=packet range, 3=reserved] */
+ unsigned char addrm;
+ /** size of codestream addresses [2/4 bytes] */
+ unsigned char ad_size;
+ /** type of sensitivity
+ [0=relative error, 1=MSE, 2=MSE reduction, 3=PSNR, 4=PSNR increment,
+ 5=MAXERR (absolute peak error), 6=TSE (total squared error), 7=reserved */
+ unsigned char senst;
+ /** size of sensitivity data (1/2 bytes) */
+ unsigned char se_size;
+ /**@name Marker segment fields */
+ /*@{*/
+ /** two bytes for the length of ESD MS, exluding the marker itself (4 to 65535 bytes) */
+ unsigned short int Lesd;
+ /** two bytes, component of error sensitivity */
+ unsigned short int Cesd;
+ /** one byte, signals JPWL techniques adoption */
+ unsigned char Pesd;
+ /** ESD data, variable length */
+ unsigned char *data;
+ /*@}*/
+ /**@name Fields set by esd_create (only internal use) */
+ /*@{*/
+ /** number of components in the image */
+ int numcomps;
+ /** tile where this marker has been placed (-1 means MH) */
+ int tileno;
+ /** number of sensitivity values */
+ unsigned long int svalnum;
+ /** size of a single sensitivity pair (address+value) */
+ size_t sensval_size;
+ /*@}*/
+} jpwl_esd_ms_t;
+
+/**
+RED (Residual Error Descriptor) Marker segment
+*/
+typedef struct jpwl_red_ms {
+ /** two bytes for the length of RED MS, exluding the marker itself (3 to 65535 bytes) */
+ unsigned short int Lred;
+ /** one byte, signals JPWL techniques adoption */
+ unsigned char Pred;
+ /** RED data, variable length */
+ unsigned char *data;
+} jpwl_red_ms_t;
+
+/**
+Structure used to store JPWL markers temporary position and readyness
+*/
+typedef struct jpwl_marker {
+ /** marker value (J2K_MS_EPC, etc.) */
+ int id;
+ /** union keeping the pointer to the real marker struct */
+ union jpwl_marks {
+ /** pointer to EPB marker */
+ jpwl_epb_ms_t *epbmark;
+ /** pointer to EPC marker */
+ jpwl_epc_ms_t *epcmark;
+ /** pointer to ESD marker */
+ jpwl_esd_ms_t *esdmark;
+ /** pointer to RED marker */
+ jpwl_red_ms_t *redmark;
+ } m;
+ /** position where the marker should go, in the pre-JPWL codestream */
+ unsigned long int pos;
+ /** same as before, only written as a double, so we can sort it better */
+ double dpos;
+ /** length of the marker segment (marker excluded) */
+ unsigned short int len;
+ /** the marker length is ready or not? */
+ opj_bool len_ready;
+ /** the marker position is ready or not? */
+ opj_bool pos_ready;
+ /** the marker parameters are ready or not? */
+ opj_bool parms_ready;
+ /** are the written data ready or not */
+ opj_bool data_ready;
+} jpwl_marker_t;
+
+/**
+Encode according to JPWL specs
+@param j2k J2K handle
+@param cio codestream handle
+@param image image handle
+*/
+void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image);
+
+/**
+Prepare the list of JPWL markers, after the Part 1 codestream
+has been finalized (index struct is full)
+@param j2k J2K handle
+@param cio codestream handle
+@param image image handle
+*/
+void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image);
+
+/**
+Dump the list of JPWL markers, after it has been prepared
+@param j2k J2K handle
+@param cio codestream handle
+@param image image handle
+*/
+void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image);
+
+/**
+Read the EPC marker (Error Protection Capability)
+@param j2k J2K handle
+*/
+void j2k_read_epc(opj_j2k_t *j2k);
+
+/**
+Write the EPC marker (Error Protection Capability), BUT the DL field is always set to 0
+(this simplifies the management of EPBs and it is openly stated in the standard
+as a possible value, mening that the information is not available) and the informative techniques
+are not yet implemented
+@param j2k J2K handle
+*/
+#if 0
+void j2k_write_epc(opj_j2k_t *j2k);
+#endif
+
+/**
+Read the EPB marker (Error Protection Block)
+@param j2k J2K handle
+*/
+void j2k_read_epb(opj_j2k_t *j2k);
+
+/**
+Write the EPB marker (Error Protection Block)
+@param j2k J2K handle
+*/
+void j2k_write_epb(opj_j2k_t *j2k);
+
+/**
+Read the ESD marker (Error Sensitivity Descriptor)
+@param j2k J2K handle
+*/
+void j2k_read_esd(opj_j2k_t *j2k);
+
+/**
+Read the RED marker (Residual Error Descriptor)
+@param j2k J2K handle
+*/
+void j2k_read_red(opj_j2k_t *j2k);
+
+/** create an EPB marker segment
+@param j2k J2K compressor handle
+@param latest it is the latest EPB in the header
+@param packed EPB is in packed style
+@param tileno tile number where the marker has been placed (-1 means MH)
+@param idx current EPB running index
+@param hprot applied protection type (-1/0,1,16,32,37-128)
+@param pre_len length of pre-protected data
+@param post_len length of post-protected data
+@return returns the freshly created EPB
+*/
+jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, opj_bool latest, opj_bool packed, int tileno, int idx, int hprot,
+ unsigned long int pre_len, unsigned long int post_len);
+
+/** add a number of EPB marker segments
+@param j2k J2K compressor handle
+@param jwmarker pointer to the JPWL markers list
+@param jwmarker_num pointer to the number of JPWL markers (gets updated)
+@param latest it is the latest group of EPBs in the header
+@param packed EPBs are in packed style
+@param insideMH it is in the MH
+@param idx pointer to the starting EPB running index (gets updated)
+@param hprot applied protection type (-1/0,1,16,32,37-128)
+@param place_pos place in original codestream where EPBs should go
+@param tileno tile number of these EPBs
+@param pre_len length of pre-protected data
+@param post_len length of post-protected data
+@return returns the length of all added markers
+*/
+int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ opj_bool latest, opj_bool packed, opj_bool insideMH, int *idx, int hprot,
+ double place_pos, int tileno,
+ unsigned long int pre_len, unsigned long int post_len);
+
+/** add a number of ESD marker segments
+@param j2k J2K compressor handle
+@param jwmarker pointer to the JPWL markers list
+@param jwmarker_num pointer to the number of JPWL markers (gets updated)
+@param comps considered component (-1=average, 0/1/2/...=component no.)
+@param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)
+@param ad_size size of addresses (2/4 bytes)
+@param senst sensitivity type
+@param se_size sensitivity values size (1/2 bytes)
+@param place_pos place in original codestream where EPBs should go
+@param tileno tile number of these EPBs
+@return returns the length of all added markers
+*/
+int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ int comps, unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, unsigned char se_size,
+ double place_pos, int tileno);
+
+/** updates the information structure by modifying the positions and lengths
+@param j2k J2K compressor handle
+@param jwmarker pointer to JPWL markers list
+@param jwmarker_num number of JPWL markers
+@return returns true in case of success
+*/
+opj_bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num);
+
+
+opj_bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);
+
+opj_bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf, unsigned char *post_buf);
+
+opj_bool j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len);
+
+/** corrects the data in the JPWL codestream
+@param j2k J2K compressor handle
+@return true if correction is performed correctly
+*/
+opj_bool jpwl_correct(opj_j2k_t *j2k);
+
+/** corrects the data protected by an EPB
+@param j2k J2K compressor handle
+@param buffer pointer to the EPB position
+@param type type of EPB: 0=MH, 1=TPH, 2=other, 3=auto
+@param pre_len length of pre-data
+@param post_len length of post_data
+@param conn is a pointer to the length of all connected (packed) EPBs
+@param L4_bufp is a pointer to the buffer pointer of redundancy data
+@return returns true if correction could be succesfully performed
+*/
+opj_bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,
+ unsigned char **L4_bufp);
+
+/** check that a tile and its children have valid data
+@param j2k J2K decompressor handle
+@param tcd Tile decompressor handle
+@param tileno number of the tile to check
+*/
+opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno);
+
+/** Macro functions for CRC computation */
+
+/**
+Computes the CRC-16, as stated in JPWL specs
+@param CRC two bytes containing the CRC value (must be initialized with 0x0000)
+@param DATA byte for which the CRC is computed; call this on every byte of the sequence
+and get the CRC at the end
+*/
+#define jpwl_updateCRC16(CRC, DATA) updateCRC16(CRC, DATA)
+
+/**
+Computes the CRC-32, as stated in JPWL specs
+@param CRC four bytes containing the CRC value (must be initialized with 0x00000000)
+@param DATA byte for which the CRC is computed; call this on every byte of the sequence
+and get the CRC at the end
+*/
+#define jpwl_updateCRC32(CRC, DATA) updateCRC32(CRC, DATA)
+
+/**
+Computes the minimum between two integers
+@param a first integer to compare
+@param b second integer to compare
+@return returns the minimum integer between a and b
+*/
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+/*@}*/
+
+#endif /* USE_JPWL */
+
+#ifdef USE_JPSEC
+
+/** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */
+/*@{*/
+
+/**
+Read the SEC marker (SEcured Codestream)
+@param j2k J2K handle
+*/
+void j2k_read_sec(opj_j2k_t *j2k);
+
+/**
+Write the SEC marker (SEcured Codestream)
+@param j2k J2K handle
+*/
+void j2k_write_sec(opj_j2k_t *j2k);
+
+/**
+Read the INSEC marker (SEcured Codestream)
+@param j2k J2K handle
+*/
+void j2k_read_insec(opj_j2k_t *j2k);
+
+/*@}*/
+
+#endif /* USE_JPSEC */
+
+#endif /* __JPWL_H */
+
diff --git a/src/lib/openjpwl/jpwl_lib.c b/src/lib/openjpwl/jpwl_lib.c
new file mode 100644
index 00000000..b75cfdb1
--- /dev/null
+++ b/src/lib/openjpwl/jpwl_lib.c
@@ -0,0 +1,1797 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 USE_JPWL
+
+#include "opj_includes.h"
+#include <limits.h>
+
+/** Minimum and maximum values for the double->pfp conversion */
+#define MIN_V1 0.0
+#define MAX_V1 17293822569102704640.0
+#define MIN_V2 0.000030517578125
+#define MAX_V2 131040.0
+
+/** conversion between a double precision floating point
+number and the corresponding pseudo-floating point used
+to represent sensitivity values
+@param V the double precision value
+@param bytes the number of bytes of the representation
+@return the pseudo-floating point value (cast accordingly)
+*/
+unsigned short int jpwl_double_to_pfp(double V, int bytes);
+
+/** conversion between a pseudo-floating point used
+to represent sensitivity values and the corresponding
+double precision floating point number
+@param em the pseudo-floating point value (cast accordingly)
+@param bytes the number of bytes of the representation
+@return the double precision value
+*/
+double jpwl_pfp_to_double(unsigned short int em, int bytes);
+
+ /*-------------------------------------------------------------*/
+
+int jpwl_markcomp(const void *arg1, const void *arg2)
+{
+ /* Compare the two markers' positions */
+ double diff = (((jpwl_marker_t *) arg1)->dpos - ((jpwl_marker_t *) arg2)->dpos);
+
+ if (diff == 0.0)
+ return (0);
+ else if (diff < 0)
+ return (-1);
+ else
+ return (+1);
+}
+
+int jpwl_epbs_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ opj_bool latest, opj_bool packed, opj_bool insideMH, int *idx, int hprot,
+ double place_pos, int tileno,
+ unsigned long int pre_len, unsigned long int post_len) {
+
+ jpwl_epb_ms_t *epb_mark = NULL;
+
+ int k_pre, k_post, n_pre, n_post;
+
+ unsigned long int L1, L2, dL4, max_postlen, epbs_len = 0;
+
+ /* We find RS(n,k) for EPB parms and pre-data, if any */
+ if (insideMH && (*idx == 0)) {
+ /* First EPB in MH */
+ k_pre = 64;
+ n_pre = 160;
+ } else if (!insideMH && (*idx == 0)) {
+ /* First EPB in TH */
+ k_pre = 25;
+ n_pre = 80;
+ } else {
+ /* Following EPBs in MH or TH */
+ k_pre = 13;
+ n_pre = 40;
+ };
+
+ /* Find lengths, Figs. B3 and B4 */
+ /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+ L1 = pre_len + 13;
+
+ /* size of pre-data redundancy */
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L2 = (n_pre - k_pre) * (unsigned long int) ceil((double) L1 / (double) k_pre);
+
+ /* Find protection type for post data and its associated redundancy field length*/
+ if ((hprot == 16) || (hprot == 32)) {
+ /* there is a CRC for post-data */
+ k_post = post_len;
+ n_post = post_len + (hprot >> 3);
+ /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+ } else if ((hprot >= 37) && (hprot <= 128)) {
+ /* there is a RS for post-data */
+ k_post = 32;
+ n_post = hprot;
+
+ } else {
+ /* Use predefined codes */
+ n_post = n_pre;
+ k_post = k_pre;
+ };
+
+ /* Create the EPB(s) */
+ while (post_len > 0) {
+
+ /* maximum postlen in order to respect EPB size
+ (we use JPWL_MAXIMUM_EPB_ROOM instead of 65535 for keeping room for EPB parms)*/
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) JPWL_MAXIMUM_EPB_ROOM / (double) (n_post - k_post));
+
+ /* maximum postlen in order to respect EPB size */
+ if (*idx == 0)
+ /* (we use (JPWL_MAXIMUM_EPB_ROOM - L2) instead of 65535 for keeping room for EPB parms + pre-data) */
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) (JPWL_MAXIMUM_EPB_ROOM - L2) / (double) (n_post - k_post));
+
+ else
+ /* (we use JPWL_MAXIMUM_EPB_ROOM instead of 65535 for keeping room for EPB parms) */
+ /* (message word size) * (number of containable parity words) */
+ max_postlen = k_post * (unsigned long int) floor((double) JPWL_MAXIMUM_EPB_ROOM / (double) (n_post - k_post));
+
+ /* null protection case */
+ /* the max post length can be as large as the LDPepb field can host */
+ if (hprot == 0)
+ max_postlen = INT_MAX;
+
+ /* length to use */
+ dL4 = min(max_postlen, post_len);
+
+ if ((epb_mark = jpwl_epb_create(
+ j2k, /* this encoder handle */
+ latest ? (dL4 < max_postlen) : OPJ_FALSE, /* is it the latest? */
+ packed, /* is it packed? */
+ tileno, /* we are in TPH */
+ *idx, /* its index */
+ hprot, /* protection type parameters of following data */
+ 0, /* pre-data: nothing for now */
+ dL4 /* post-data: the stub computed previously */
+ ))) {
+
+ /* Add this marker to the 'insertanda' list */
+ if (*jwmarker_num < JPWL_MAX_NO_MARKERS) {
+ jwmarker[*jwmarker_num].id = J2K_MS_EPB; /* its type */
+ jwmarker[*jwmarker_num].m.epbmark = epb_mark; /* the EPB */
+ jwmarker[*jwmarker_num].pos = (int) place_pos; /* after SOT */
+ jwmarker[*jwmarker_num].dpos = place_pos + 0.0000001 * (double)(*idx); /* not very first! */
+ jwmarker[*jwmarker_num].len = epb_mark->Lepb; /* its length */
+ jwmarker[*jwmarker_num].len_ready = OPJ_TRUE; /* ready */
+ jwmarker[*jwmarker_num].pos_ready = OPJ_TRUE; /* ready */
+ jwmarker[*jwmarker_num].parms_ready = OPJ_TRUE; /* ready */
+ jwmarker[*jwmarker_num].data_ready = OPJ_FALSE; /* not ready */
+ (*jwmarker_num)++;
+ }
+
+ /* increment epb index */
+ (*idx)++;
+
+ /* decrease postlen */
+ post_len -= dL4;
+
+ /* increase the total length of EPBs */
+ epbs_len += epb_mark->Lepb + 2;
+
+ } else {
+ /* ooops, problems */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB for UEP in tile %d\n", tileno);
+ };
+ }
+
+ return epbs_len;
+}
+
+
+jpwl_epb_ms_t *jpwl_epb_create(opj_j2k_t *j2k, opj_bool latest, opj_bool packed, int tileno, int idx, int hprot,
+ unsigned long int pre_len, unsigned long int post_len) {
+
+ jpwl_epb_ms_t *epb = NULL;
+ /*unsigned short int data_len = 0;*/
+ unsigned short int L2, L3;
+ unsigned long int L1, L4;
+ /*unsigned char *predata_in = NULL;*/
+
+ opj_bool insideMH = (tileno == -1);
+
+ /* Alloc space */
+ if (!(epb = (jpwl_epb_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epb_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for one EPB MS\n");
+ return NULL;
+ };
+
+ /* We set RS(n,k) for EPB parms and pre-data, if any */
+ if (insideMH && (idx == 0)) {
+ /* First EPB in MH */
+ epb->k_pre = 64;
+ epb->n_pre = 160;
+ } else if (!insideMH && (idx == 0)) {
+ /* First EPB in TH */
+ epb->k_pre = 25;
+ epb->n_pre = 80;
+ } else {
+ /* Following EPBs in MH or TH */
+ epb->k_pre = 13;
+ epb->n_pre = 40;
+ };
+
+ /* Find lengths, Figs. B3 and B4 */
+ /* size of pre data: pre_buf(pre_len) + EPB(2) + Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) */
+ L1 = pre_len + 13;
+ epb->pre_len = pre_len;
+
+ /* size of pre-data redundancy */
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+ /* length of post-data */
+ L4 = post_len;
+ epb->post_len = post_len;
+
+ /* Find protection type for post data and its associated redundancy field length*/
+ if ((hprot == 16) || (hprot == 32)) {
+ /* there is a CRC for post-data */
+ epb->Pepb = 0x10000000 | ((unsigned long int) hprot >> 5); /* 0=CRC-16, 1=CRC-32 */
+ epb->k_post = post_len;
+ epb->n_post = post_len + (hprot >> 3);
+ /*L3 = hprot >> 3;*/ /* 2 (CRC-16) or 4 (CRC-32) bytes */
+
+ } else if ((hprot >= 37) && (hprot <= 128)) {
+ /* there is a RS for post-data */
+ epb->Pepb = 0x20000020 | (((unsigned long int) hprot & 0x000000FF) << 8);
+ epb->k_post = 32;
+ epb->n_post = hprot;
+
+ } else if (hprot == 1) {
+ /* Use predefined codes */
+ epb->Pepb = (unsigned long int) 0x00000000;
+ epb->n_post = epb->n_pre;
+ epb->k_post = epb->k_pre;
+
+ } else if (hprot == 0) {
+ /* Placeholder EPB: only protects its parameters, no protection method */
+ epb->Pepb = (unsigned long int) 0xFFFFFFFF;
+ epb->n_post = 1;
+ epb->k_post = 1;
+
+ } else {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Invalid protection value for EPB h = %d\n", hprot);
+ return NULL;
+ }
+
+ epb->hprot = hprot;
+
+ /* (redundancy per codeword) * (number of codewords, rounded up) */
+ L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+ /* private fields */
+ epb->tileno = tileno;
+
+ /* Fill some fields of the EPB */
+
+ /* total length of the EPB MS (less the EPB marker itself): */
+ /* Lepb(2) + Depb(1) + LDPepb(4) + Pepb(4) + pre_redundancy + post-redundancy */
+ epb->Lepb = 11 + L2 + L3;
+
+ /* EPB style */
+ epb->Depb = ((packed & 0x0001) << 7) | ((latest & 0x0001) << 6) | (idx & 0x003F);
+
+ /* length of data protected by EPB: */
+ epb->LDPepb = L1 + L4;
+
+ return epb;
+}
+
+void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_EPB >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_EPB >> 0);
+
+ /* Lepb */
+ *(buf++) = (unsigned char) (epb->Lepb >> 8);
+ *(buf++) = (unsigned char) (epb->Lepb >> 0);
+
+ /* Depb */
+ *(buf++) = (unsigned char) (epb->Depb >> 0);
+
+ /* LDPepb */
+ *(buf++) = (unsigned char) (epb->LDPepb >> 24);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 16);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 8);
+ *(buf++) = (unsigned char) (epb->LDPepb >> 0);
+
+ /* Pepb */
+ *(buf++) = (unsigned char) (epb->Pepb >> 24);
+ *(buf++) = (unsigned char) (epb->Pepb >> 16);
+ *(buf++) = (unsigned char) (epb->Pepb >> 8);
+ *(buf++) = (unsigned char) (epb->Pepb >> 0);
+
+ /* Data */
+ /*memcpy(buf, epb->data, (size_t) epb->Lepb - 11);*/
+ memset(buf, 0, (size_t) epb->Lepb - 11);
+
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, -1, epb->Lepb + 2);
+
+}
+
+
+jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on) {
+
+ jpwl_epc_ms_t *epc = NULL;
+
+ /* Alloc space */
+ if (!(epc = (jpwl_epc_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_epc_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for EPC MS\n");
+ return NULL;
+ };
+
+ /* Set the EPC parameters */
+ epc->esd_on = esd_on;
+ epc->epb_on = epb_on;
+ epc->red_on = red_on;
+ epc->info_on = info_on;
+
+ /* Fill the EPC fields with default values */
+ epc->Lepc = 9;
+ epc->Pcrc = 0x0000;
+ epc->DL = 0x00000000;
+ epc->Pepc = ((j2k->cp->esd_on & 0x0001) << 4) | ((j2k->cp->red_on & 0x0001) << 5) |
+ ((j2k->cp->epb_on & 0x0001) << 6) | ((j2k->cp->info_on & 0x0001) << 7);
+
+ return (epc);
+}
+
+opj_bool jpwl_epb_fill(opj_j2k_t *j2k, jpwl_epb_ms_t *epb, unsigned char *buf, unsigned char *post_buf) {
+
+ unsigned long int L1, L2, L3, L4;
+ int remaining;
+ unsigned long int P, NN_P;
+
+ /* Operating buffer */
+ static unsigned char codeword[NN], *parityword;
+
+ unsigned char *L1_buf, *L2_buf;
+ /* these ones are static, since we need to keep memory of
+ the exact place from one call to the other */
+ static unsigned char *L3_buf, *L4_buf;
+
+ /* some consistency check */
+ if (!buf) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs\n");
+ return OPJ_FALSE;
+ }
+
+ if (!post_buf && !L4_buf) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no operating buffer for EPBs data\n");
+ return OPJ_FALSE;
+ }
+
+ /*
+ * Compute parity bytes on pre-data, ALWAYS present (at least only for EPB parms)
+ */
+
+ /* Initialize RS structures */
+ P = epb->n_pre - epb->k_pre;
+ NN_P = NN - P;
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* pre-data begins pre_len bytes before of EPB buf */
+ L1_buf = buf - epb->pre_len;
+ L1 = epb->pre_len + 13;
+
+ /* redundancy for pre-data begins immediately after EPB parms */
+ L2_buf = buf + 13;
+ L2 = (epb->n_pre - epb->k_pre) * (unsigned short int) ceil((double) L1 / (double) epb->k_pre);
+
+ /* post-data
+ the position of L4 buffer can be:
+ 1) passed as a parameter: in that case use it
+ 2) null: in that case use the previous (static) one
+ */
+ if (post_buf)
+ L4_buf = post_buf;
+ L4 = epb->post_len;
+
+ /* post-data redundancy begins immediately after pre-data redundancy */
+ L3_buf = L2_buf + L2;
+ L3 = (epb->n_post - epb->k_post) * (unsigned short int) ceil((double) L4 / (double) epb->k_post);
+
+ /* let's check whether EPB length is sufficient to contain all these data */
+ if (epb->Lepb < (11 + L2 + L3))
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "There is no room in EPB data field for writing redundancy data\n");
+ /*printf("Env. %d, nec. %d (%d + %d)\n", epb->Lepb - 11, L2 + L3, L2, L3);*/
+
+ /* Compute redundancy of pre-data message words */
+ remaining = L1;
+ while (remaining) {
+
+ /* copy message data into codeword buffer */
+ if (remaining < epb->k_pre) {
+ /* the last message word is zero-padded */
+ memset(codeword, 0, NN);
+ memcpy(codeword, L1_buf, remaining);
+ L1_buf += remaining;
+ remaining = 0;
+
+ } else {
+ memcpy(codeword, L1_buf, epb->k_pre);
+ L1_buf += epb->k_pre;
+ remaining -= epb->k_pre;
+
+ }
+
+ /* Encode the buffer and obtain parity bytes */
+ if (encode_rs(codeword, parityword))
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible encoding error in codeword @ position #%d\n", (L1_buf - buf) / epb->k_pre);
+
+ /* copy parity bytes only in redundancy buffer */
+ memcpy(L2_buf, parityword, P);
+
+ /* advance parity buffer */
+ L2_buf += P;
+ }
+
+ /*
+ * Compute parity bytes on post-data, may be absent if there are no data
+ */
+ /*printf("Hprot is %d (tileno=%d, k_pre=%d, n_pre=%d, k_post=%d, n_post=%d, pre_len=%d, post_len=%d)\n",
+ epb->hprot, epb->tileno, epb->k_pre, epb->n_pre, epb->k_post, epb->n_post, epb->pre_len,
+ epb->post_len);*/
+ if (epb->hprot < 0) {
+
+ /* there should be no EPB */
+
+ } else if (epb->hprot == 0) {
+
+ /* no protection for the data */
+ /* advance anyway */
+ L4_buf += epb->post_len;
+
+ } else if (epb->hprot == 16) {
+
+ /* CRC-16 */
+ unsigned short int mycrc = 0x0000;
+
+ /* compute the CRC field (excluding itself) */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+ /* write the CRC field */
+ *(L3_buf++) = (unsigned char) (mycrc >> 8);
+ *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+ } else if (epb->hprot == 32) {
+
+ /* CRC-32 */
+ unsigned long int mycrc = 0x00000000;
+
+ /* compute the CRC field (excluding itself) */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+ /* write the CRC field */
+ *(L3_buf++) = (unsigned char) (mycrc >> 24);
+ *(L3_buf++) = (unsigned char) (mycrc >> 16);
+ *(L3_buf++) = (unsigned char) (mycrc >> 8);
+ *(L3_buf++) = (unsigned char) (mycrc >> 0);
+
+ } else {
+
+ /* RS */
+
+ /* Initialize RS structures */
+ P = epb->n_post - epb->k_post;
+ NN_P = NN - P;
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Compute redundancy of post-data message words */
+ remaining = L4;
+ while (remaining) {
+
+ /* copy message data into codeword buffer */
+ if (remaining < epb->k_post) {
+ /* the last message word is zero-padded */
+ memset(codeword, 0, NN);
+ memcpy(codeword, L4_buf, remaining);
+ L4_buf += remaining;
+ remaining = 0;
+
+ } else {
+ memcpy(codeword, L4_buf, epb->k_post);
+ L4_buf += epb->k_post;
+ remaining -= epb->k_post;
+
+ }
+
+ /* Encode the buffer and obtain parity bytes */
+ if (encode_rs(codeword, parityword))
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible encoding error in codeword @ position #%d\n", (L4_buf - buf) / epb->k_post);
+
+ /* copy parity bytes only in redundancy buffer */
+ memcpy(L3_buf, parityword, P);
+
+ /* advance parity buffer */
+ L3_buf += P;
+ }
+
+ }
+
+ return OPJ_TRUE;
+}
+
+
+opj_bool jpwl_correct(opj_j2k_t *j2k) {
+
+ opj_cio_t *cio = j2k->cio;
+ opj_bool status;
+ static opj_bool mh_done = OPJ_FALSE;
+ int mark_pos, id, len, skips, sot_pos;
+ unsigned long int Psot = 0;
+
+ /* go back to marker position */
+ mark_pos = cio_tell(cio) - 2;
+ cio_seek(cio, mark_pos);
+
+ if ((j2k->state == J2K_STATE_MHSOC) && !mh_done) {
+
+ int mark_val = 0, skipnum = 0;
+
+ /*
+ COLOR IMAGE
+ first thing to do, if we are here, is to look whether
+ 51 (skipnum) positions ahead there is an EPB, in case of MH
+ */
+ /*
+ B/W IMAGE
+ first thing to do, if we are here, is to look whether
+ 45 (skipnum) positions ahead there is an EPB, in case of MH
+ */
+ /* SIZ SIZ_FIELDS SIZ_COMPS FOLLOWING_MARKER */
+ skipnum = 2 + 38 + 3 * j2k->cp->exp_comps + 2;
+ if ((cio->bp + skipnum) < cio->end) {
+
+ cio_skip(cio, skipnum);
+
+ /* check that you are not going beyond the end of codestream */
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 0, /* EPB type: MH */
+ skipnum, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+
+ /* read the marker value */
+ mark_val = (*(cio->bp) << 8) | *(cio->bp + 1);
+
+ if (status && (mark_val == J2K_MS_EPB)) {
+ /* we found it! */
+ mh_done = OPJ_TRUE;
+ return OPJ_TRUE;
+ }
+
+ /* Disable correction in case of missing or bad head EPB */
+ /* We can't do better! */
+ /* PATCHED: 2008-01-25 */
+ /* MOVED UP: 2008-02-01 */
+ if (!status) {
+ j2k->cp->correct = OPJ_FALSE;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Couldn't find the MH EPB: disabling JPWL\n");
+ }
+
+ }
+
+ }
+
+ if (OPJ_TRUE /*(j2k->state == J2K_STATE_TPHSOT) || (j2k->state == J2K_STATE_TPH)*/) {
+ /* else, look if 12 positions ahead there is an EPB, in case of TPH */
+ cio_seek(cio, mark_pos);
+ if ((cio->bp + 12) < cio->end) {
+
+ cio_skip(cio, 12);
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 1, /* EPB type: TPH */
+ 12, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+ if (status)
+ /* we found it! */
+ return OPJ_TRUE;
+ }
+ }
+
+ return OPJ_FALSE;
+
+ /* for now, don't use this code */
+
+ /* else, look if here is an EPB, in case of other */
+ if (mark_pos > 64) {
+ /* it cannot stay before the first MH EPB */
+ cio_seek(cio, mark_pos);
+ cio_skip(cio, 0);
+
+ /* call EPB corrector */
+ status = jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ cio->bp, /* pointer to EPB in codestream buffer */
+ 2, /* EPB type: TPH */
+ 0, /* length of pre-data */
+ -1, /* length of post-data: -1 means auto */
+ NULL,
+ NULL
+ );
+ if (status)
+ /* we found it! */
+ return OPJ_TRUE;
+ }
+
+ /* nope, no EPBs probably, or they are so damaged that we can give up */
+ return OPJ_FALSE;
+
+ return OPJ_TRUE;
+
+ /* AN ATTEMPT OF PARSER */
+ /* NOT USED ACTUALLY */
+
+ /* go to the beginning of the file */
+ cio_seek(cio, 0);
+
+ /* let's begin */
+ j2k->state = J2K_STATE_MHSOC;
+
+ /* cycle all over the markers */
+ while (cio_tell(cio) < cio->length) {
+
+ /* read the marker */
+ mark_pos = cio_tell(cio);
+ id = cio_read(cio, 2);
+
+ /* details */
+ printf("Marker@%d: %X\n", cio_tell(cio) - 2, id);
+
+ /* do an action in response to the read marker */
+ switch (id) {
+
+ /* short markers */
+
+ /* SOC */
+ case J2K_MS_SOC:
+ j2k->state = J2K_STATE_MHSIZ;
+ len = 0;
+ skips = 0;
+ break;
+
+ /* EOC */
+ case J2K_MS_EOC:
+ j2k->state = J2K_STATE_MT;
+ len = 0;
+ skips = 0;
+ break;
+
+ /* particular case of SOD */
+ case J2K_MS_SOD:
+ len = Psot - (mark_pos - sot_pos) - 2;
+ skips = len;
+ break;
+
+ /* long markers */
+
+ /* SOT */
+ case J2K_MS_SOT:
+ j2k->state = J2K_STATE_TPH;
+ sot_pos = mark_pos; /* position of SOT */
+ len = cio_read(cio, 2); /* read the length field */
+ cio_skip(cio, 2); /* this field is unnecessary */
+ Psot = cio_read(cio, 4); /* tile length */
+ skips = len - 8;
+ break;
+
+ /* remaining */
+ case J2K_MS_SIZ:
+ j2k->state = J2K_STATE_MH;
+ /* read the length field */
+ len = cio_read(cio, 2);
+ skips = len - 2;
+ break;
+
+ /* remaining */
+ default:
+ /* read the length field */
+ len = cio_read(cio, 2);
+ skips = len - 2;
+ break;
+
+ }
+
+ /* skip to marker's end */
+ cio_skip(cio, skips);
+
+ }
+
+
+}
+
+opj_bool jpwl_epb_correct(opj_j2k_t *j2k, unsigned char *buffer, int type, int pre_len, int post_len, int *conn,
+ unsigned char **L4_bufp) {
+
+ /* Operating buffer */
+ unsigned char codeword[NN], *parityword;
+
+ unsigned long int P, NN_P;
+ unsigned long int L1, L4;
+ int remaining, n_pre, k_pre, n_post, k_post;
+
+ int status, tt;
+
+ int orig_pos = cio_tell(j2k->cio);
+
+ unsigned char *L1_buf, *L2_buf;
+ unsigned char *L3_buf, *L4_buf;
+
+ unsigned long int LDPepb, Pepb;
+ unsigned short int Lepb;
+ unsigned char Depb;
+ char str1[25] = "";
+ int myconn, errnum = 0;
+ opj_bool errflag = OPJ_FALSE;
+
+ opj_cio_t *cio = j2k->cio;
+
+ /* check for common errors */
+ if (!buffer) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "The EPB pointer is a NULL buffer\n");
+ return OPJ_FALSE;
+ }
+
+ /* set bignesses */
+ L1 = pre_len + 13;
+
+ /* pre-data correction */
+ switch (type) {
+
+ case 0:
+ /* MH EPB */
+ k_pre = 64;
+ n_pre = 160;
+ break;
+
+ case 1:
+ /* TPH EPB */
+ k_pre = 25;
+ n_pre = 80;
+ break;
+
+ case 2:
+ /* other EPBs */
+ k_pre = 13;
+ n_pre = 40;
+ break;
+
+ case 3:
+ /* automatic setup */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Auto. setup not yet implemented\n");
+ return OPJ_FALSE;
+ break;
+
+ default:
+ /* unknown type */
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Unknown expected EPB type\n");
+ return OPJ_FALSE;
+ break;
+
+ }
+
+ /* Initialize RS structures */
+ P = n_pre - k_pre;
+ NN_P = NN - P;
+ tt = (int) floor((float) P / 2.0F); /* correction capability of the code */
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Correct pre-data message words */
+ L1_buf = buffer - pre_len;
+ L2_buf = buffer + 13;
+ remaining = L1;
+ while (remaining) {
+
+ /* always zero-pad codewords */
+ /* (this is required, since after decoding the zeros in the long codeword
+ could change, and keep unchanged in subsequent calls) */
+ memset(codeword, 0, NN);
+
+ /* copy codeword buffer into message bytes */
+ if (remaining < k_pre)
+ memcpy(codeword, L1_buf, remaining);
+ else
+ memcpy(codeword, L1_buf, k_pre);
+
+ /* copy redundancy buffer in parity bytes */
+ memcpy(parityword, L2_buf, P);
+
+ /* Decode the buffer and possibly obtain corrected bytes */
+ status = eras_dec_rs(codeword, NULL, 0);
+ if (status == -1) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible decoding error in codeword @ position #%d\n", (L1_buf - buffer) / k_pre);*/
+ errflag = OPJ_TRUE;
+ /* we can try to safely get out from the function:
+ if we are here, either this is not an EPB or the first codeword
+ is too damaged to be helpful */
+ /*return OPJ_FALSE;*/
+
+ } else if (status == 0) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+ } else if (status <= tt) {
+ /* it has corrected 0 <= errs <= tt */
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+ errnum += status;
+
+ } else {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+ return OPJ_FALSE;*/
+ errflag = OPJ_TRUE;
+ }
+
+
+ /* advance parity buffer */
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected parity only if all is OK */
+ memcpy(L2_buf, parityword, P);
+ L2_buf += P;
+
+ /* advance message buffer */
+ if (remaining < k_pre) {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L1_buf, codeword, remaining);
+ L1_buf += remaining;
+ remaining = 0;
+
+ } else {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L1_buf, codeword, k_pre);
+ L1_buf += k_pre;
+ remaining -= k_pre;
+
+ }
+ }
+
+ /* print summary */
+ if (!conn) {
+
+ /*if (errnum)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "+ %d symbol errors corrected (Ps=%.1e)\n", errnum,
+ (float) errnum / ((float) n_pre * (float) L1 / (float) k_pre));*/
+ if (errflag) {
+ /*opj_event_msg(j2k->cinfo, EVT_INFO, "+ there were unrecoverable errors\n");*/
+ return OPJ_FALSE;
+ }
+
+ }
+
+ /* presumably, now, EPB parameters are correct */
+ /* let's get them */
+
+ /* Simply read the EPB parameters */
+ if (conn)
+ cio->bp = buffer;
+ cio_skip(cio, 2); /* the marker */
+ Lepb = cio_read(cio, 2);
+ Depb = cio_read(cio, 1);
+ LDPepb = cio_read(cio, 4);
+ Pepb = cio_read(cio, 4);
+
+ /* What does Pepb tells us about the protection method? */
+ if (((Pepb & 0xF0000000) >> 28) == 0)
+ sprintf(str1, "pred"); /* predefined */
+ else if (((Pepb & 0xF0000000) >> 28) == 1)
+ sprintf(str1, "crc-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */
+ else if (((Pepb & 0xF0000000) >> 28) == 2)
+ sprintf(str1, "rs(%lu,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */
+ else if (Pepb == 0xFFFFFFFF)
+ sprintf(str1, "nometh"); /* RS mode */
+ else
+ sprintf(str1, "unknown"); /* unknown */
+
+ /* Now we write them to screen */
+ if (!conn && post_len)
+ opj_event_msg(j2k->cinfo, EVT_INFO,
+ "EPB(%d): (%sl, %sp, %u), %lu, %s\n",
+ cio_tell(cio) - 13,
+ (Depb & 0x40) ? "" : "n", /* latest EPB or not? */
+ (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */
+ (Depb & 0x3F), /* EPB index value */
+ LDPepb, /*length of the data protected by the EPB */
+ str1); /* protection method */
+
+
+ /* well, we need to investigate how long is the connected length of packed EPBs */
+ myconn = Lepb + 2;
+ if ((Depb & 0x40) == 0) /* not latest in header */
+ jpwl_epb_correct(j2k, /* J2K decompressor handle */
+ buffer + Lepb + 2, /* pointer to next EPB in codestream buffer */
+ 2, /* EPB type: should be of other type */
+ 0, /* only EPB fields */
+ 0, /* do not look after */
+ &myconn,
+ NULL
+ );
+ if (conn)
+ *conn += myconn;
+
+ /*if (!conn)
+ printf("connected = %d\n", myconn);*/
+
+ /*cio_seek(j2k->cio, orig_pos);
+ return OPJ_TRUE;*/
+
+ /* post-data
+ the position of L4 buffer is at the end of currently connected EPBs
+ */
+ if (!(L4_bufp))
+ L4_buf = buffer + myconn;
+ else if (!(*L4_bufp))
+ L4_buf = buffer + myconn;
+ else
+ L4_buf = *L4_bufp;
+ if (post_len == -1)
+ L4 = LDPepb - pre_len - 13;
+ else if (post_len == 0)
+ L4 = 0;
+ else
+ L4 = post_len;
+
+ L3_buf = L2_buf;
+
+ /* Do a further check here on the read parameters */
+ if (L4 > (unsigned long) cio_numbytesleft(j2k->cio))
+ /* overflow */
+ return OPJ_FALSE;
+
+ /* we are ready for decoding the remaining data */
+ if (((Pepb & 0xF0000000) >> 28) == 1) {
+ /* CRC here */
+ if ((16 * ((Pepb & 0x00000001) + 1)) == 16) {
+
+ /* CRC-16 */
+ unsigned short int mycrc = 0x0000, filecrc = 0x0000;
+
+ /* compute the CRC field */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC16(&mycrc, *(L4_buf++));
+
+ /* read the CRC field */
+ filecrc = *(L3_buf++) << 8;
+ filecrc |= *(L3_buf++);
+
+ /* check the CRC field */
+ if (mycrc == filecrc) {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+ } else {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+ errflag = OPJ_TRUE;
+ }
+ }
+
+ if ((16 * ((Pepb & 0x00000001) + 1)) == 32) {
+
+ /* CRC-32 */
+ unsigned long int mycrc = 0x00000000, filecrc = 0x00000000;
+
+ /* compute the CRC field */
+ remaining = L4;
+ while (remaining--)
+ jpwl_updateCRC32(&mycrc, *(L4_buf++));
+
+ /* read the CRC field */
+ filecrc = *(L3_buf++) << 24;
+ filecrc |= *(L3_buf++) << 16;
+ filecrc |= *(L3_buf++) << 8;
+ filecrc |= *(L3_buf++);
+
+ /* check the CRC field */
+ if (mycrc == filecrc) {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- CRC is OK\n");
+ } else {
+ if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- CRC is KO (r=%d, c=%d)\n", filecrc, mycrc);
+ errflag = OPJ_TRUE;
+ }
+ }
+
+ } else if (Pepb == 0xFFFFFFFF) {
+ /* no method */
+
+ /* advance without doing anything */
+ remaining = L4;
+ while (remaining--)
+ L4_buf++;
+
+ } else if ((((Pepb & 0xF0000000) >> 28) == 2) || (((Pepb & 0xF0000000) >> 28) == 0)) {
+ /* RS coding here */
+
+ if (((Pepb & 0xF0000000) >> 28) == 0) {
+
+ k_post = k_pre;
+ n_post = n_pre;
+
+ } else {
+
+ k_post = 32;
+ n_post = (Pepb & 0x0000FF00) >> 8;
+ }
+
+ /* Initialize RS structures */
+ P = n_post - k_post;
+ NN_P = NN - P;
+ tt = (int) floor((float) P / 2.0F); /* again, correction capability */
+ memset(codeword, 0, NN);
+ parityword = codeword + NN_P;
+ init_rs(NN_P);
+
+ /* Correct post-data message words */
+ /*L4_buf = buffer + Lepb + 2;*/
+ L3_buf = L2_buf;
+ remaining = L4;
+ while (remaining) {
+
+ /* always zero-pad codewords */
+ /* (this is required, since after decoding the zeros in the long codeword
+ could change, and keep unchanged in subsequent calls) */
+ memset(codeword, 0, NN);
+
+ /* copy codeword buffer into message bytes */
+ if (remaining < k_post)
+ memcpy(codeword, L4_buf, remaining);
+ else
+ memcpy(codeword, L4_buf, k_post);
+
+ /* copy redundancy buffer in parity bytes */
+ memcpy(parityword, L3_buf, P);
+
+ /* Decode the buffer and possibly obtain corrected bytes */
+ status = eras_dec_rs(codeword, NULL, 0);
+ if (status == -1) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING,
+ "Possible decoding error in codeword @ position #%d\n", (L4_buf - (buffer + Lepb + 2)) / k_post);*/
+ errflag = OPJ_TRUE;
+
+ } else if (status == 0) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "codeword is correctly decoded\n");*/
+
+ } else if (status <= tt) {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "%d errors corrected in codeword\n", status);*/
+ errnum += status;
+
+ } else {
+ /*if (conn == NULL)
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "EPB correction capability exceeded\n");
+ return OPJ_FALSE;*/
+ errflag = OPJ_TRUE;
+ }
+
+
+ /* advance parity buffer */
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L3_buf, parityword, P);
+ L3_buf += P;
+
+ /* advance message buffer */
+ if (remaining < k_post) {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L4_buf, codeword, remaining);
+ L4_buf += remaining;
+ remaining = 0;
+
+ } else {
+ if ((status >= 0) && (status <= tt))
+ /* copy back corrected data only if all is OK */
+ memcpy(L4_buf, codeword, k_post);
+ L4_buf += k_post;
+ remaining -= k_post;
+
+ }
+ }
+ }
+
+ /* give back the L4_buf address */
+ if (L4_bufp)
+ *L4_bufp = L4_buf;
+
+ /* print summary */
+ if (!conn) {
+
+ if (errnum)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- %d symbol errors corrected (Ps=%.1e)\n", errnum,
+ (float) errnum / (float) LDPepb);
+ if (errflag)
+ opj_event_msg(j2k->cinfo, EVT_INFO, "- there were unrecoverable errors\n");
+
+ }
+
+ cio_seek(j2k->cio, orig_pos);
+
+ return OPJ_TRUE;
+}
+
+void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epc, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_EPC >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_EPC >> 0);
+
+ /* Lepc */
+ *(buf++) = (unsigned char) (epc->Lepc >> 8);
+ *(buf++) = (unsigned char) (epc->Lepc >> 0);
+
+ /* Pcrc */
+ *(buf++) = (unsigned char) (epc->Pcrc >> 8);
+ *(buf++) = (unsigned char) (epc->Pcrc >> 0);
+
+ /* DL */
+ *(buf++) = (unsigned char) (epc->DL >> 24);
+ *(buf++) = (unsigned char) (epc->DL >> 16);
+ *(buf++) = (unsigned char) (epc->DL >> 8);
+ *(buf++) = (unsigned char) (epc->DL >> 0);
+
+ /* Pepc */
+ *(buf++) = (unsigned char) (epc->Pepc >> 0);
+
+ /* Data */
+ /*memcpy(buf, epc->data, (size_t) epc->Lepc - 9);*/
+ memset(buf, 0, (size_t) epc->Lepc - 9);
+
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, -1, epc->Lepc + 2);
+
+}
+
+int jpwl_esds_add(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int *jwmarker_num,
+ int comps, unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, unsigned char se_size,
+ double place_pos, int tileno) {
+
+ return 0;
+}
+
+jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comp,
+ unsigned char addrm, unsigned char ad_size,
+ unsigned char senst, int se_size, int tileno,
+ unsigned long int svalnum, void *sensval) {
+
+ jpwl_esd_ms_t *esd = NULL;
+
+ /* Alloc space */
+ if (!(esd = (jpwl_esd_ms_t *) opj_malloc((size_t) 1 * sizeof (jpwl_esd_ms_t)))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for ESD MS\n");
+ return NULL;
+ };
+
+ /* if relative sensitivity, activate byte range mode */
+ if (senst == 0)
+ addrm = 1;
+
+ /* size of sensval's ... */
+ if ((ad_size != 0) && (ad_size != 2) && (ad_size != 4)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address size %d for ESD MS is forbidden\n", ad_size);
+ return NULL;
+ }
+ if ((se_size != 1) && (se_size != 2)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Sensitivity size %d for ESD MS is forbidden\n", se_size);
+ return NULL;
+ }
+
+ /* ... depends on the addressing mode */
+ switch (addrm) {
+
+ /* packet mode */
+ case (0):
+ ad_size = 0; /* as per the standard */
+ esd->sensval_size = (unsigned int)se_size;
+ break;
+
+ /* byte range */
+ case (1):
+ /* auto sense address size */
+ if (ad_size == 0)
+ /* if there are more than 66% of (2^16 - 1) bytes, switch to 4 bytes
+ (we keep space for possible EPBs being inserted) */
+ ad_size = (j2k->cstr_info->codestream_size > (1 * 65535 / 3)) ? 4 : 2;
+ esd->sensval_size = ad_size + ad_size + se_size;
+ break;
+
+ /* packet range */
+ case (2):
+ /* auto sense address size */
+ if (ad_size == 0)
+ /* if there are more than 2^16 - 1 packets, switch to 4 bytes */
+ ad_size = (j2k->cstr_info->packno > 65535) ? 4 : 2;
+ esd->sensval_size = ad_size + ad_size + se_size;
+ break;
+
+ case (3):
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is unimplemented\n", addrm);
+ return NULL;
+
+ default:
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Address mode %d for ESD MS is forbidden\n", addrm);
+ return NULL;
+ }
+
+ /* set or unset sensitivity values */
+ if (svalnum <= 0) {
+
+ switch (senst) {
+
+ /* just based on the portions of a codestream */
+ case (0):
+ /* MH + no. of THs + no. of packets */
+ svalnum = 1 + (j2k->cstr_info->tw * j2k->cstr_info->th) * (1 + j2k->cstr_info->packno);
+ break;
+
+ /* all the ones that are based on the packets */
+ default:
+ if (tileno < 0)
+ /* MH: all the packets and all the tiles info is written */
+ svalnum = j2k->cstr_info->tw * j2k->cstr_info->th * j2k->cstr_info->packno;
+ else
+ /* TPH: only that tile info is written */
+ svalnum = j2k->cstr_info->packno;
+ break;
+
+ }
+ }
+
+ /* fill private fields */
+ esd->senst = senst;
+ esd->ad_size = ad_size;
+ esd->se_size = se_size;
+ esd->addrm = addrm;
+ esd->svalnum = svalnum;
+ esd->numcomps = j2k->image->numcomps;
+ esd->tileno = tileno;
+
+ /* Set the ESD parameters */
+ /* length, excluding data field */
+ if (esd->numcomps < 257)
+ esd->Lesd = 4 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+ else
+ esd->Lesd = 5 + (unsigned short int) (esd->svalnum * esd->sensval_size);
+
+ /* component data field */
+ if (comp >= 0)
+ esd->Cesd = comp;
+ else
+ /* we are averaging */
+ esd->Cesd = 0;
+
+ /* Pesd field */
+ esd->Pesd = 0x00;
+ esd->Pesd |= (esd->addrm & 0x03) << 6; /* addressing mode */
+ esd->Pesd |= (esd->senst & 0x07) << 3; /* sensitivity type */
+ esd->Pesd |= ((esd->se_size >> 1) & 0x01) << 2; /* sensitivity size */
+ esd->Pesd |= ((esd->ad_size >> 2) & 0x01) << 1; /* addressing size */
+ esd->Pesd |= (comp < 0) ? 0x01 : 0x00; /* averaging components */
+
+ /* if pointer to sensval is NULL, we can fill data field by ourselves */
+ if (!sensval) {
+
+ /* old code moved to jpwl_esd_fill() */
+ esd->data = NULL;
+
+ } else {
+ /* we set the data field as the sensitivity values poinnter passed to the function */
+ esd->data = (unsigned char *) sensval;
+ }
+
+ return (esd);
+}
+
+opj_bool jpwl_esd_fill(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+ int i;
+ unsigned long int vv;
+ unsigned long int addr1 = 0L, addr2 = 0L;
+ double dvalue = 0.0, Omax2, tmp, TSE = 0.0, MSE, oldMSE = 0.0, PSNR, oldPSNR = 0.0;
+ unsigned short int pfpvalue;
+ unsigned long int addrmask = 0x00000000;
+ opj_bool doneMH = OPJ_FALSE, doneTPH = OPJ_FALSE;
+
+ /* sensitivity values in image info are as follows:
+ - for each tile, distotile is the starting distortion for that tile, sum of all components
+ - for each packet in a tile, disto is the distortion reduction caused by that packet to that tile
+ - the TSE for a single tile should be given by distotile - sum(disto) , for all components
+ - the MSE for a single tile is given by TSE / nbpix , for all components
+ - the PSNR for a single tile is given by 10*log10( Omax^2 / MSE) , for all components
+ (Omax is given by 2^bpp - 1 for unsigned images and by 2^(bpp - 1) - 1 for signed images
+ */
+
+ /* browse all components and find Omax */
+ Omax2 = 0.0;
+ for (i = 0; i < j2k->image->numcomps; i++) {
+ tmp = pow(2.0, (double) (j2k->image->comps[i].sgnd ?
+ (j2k->image->comps[i].bpp - 1) : (j2k->image->comps[i].bpp))) - 1;
+ if (tmp > Omax2)
+ Omax2 = tmp;
+ }
+ Omax2 = Omax2 * Omax2;
+
+ /* if pointer of esd->data is not null, simply write down all the values byte by byte */
+ if (esd->data) {
+ for (i = 0; i < (int) esd->svalnum; i++)
+ *(buf++) = esd->data[i];
+ return OPJ_TRUE;
+ }
+
+ /* addressing mask */
+ if (esd->ad_size == 2)
+ addrmask = 0x0000FFFF; /* two bytes */
+ else
+ addrmask = 0xFFFFFFFF; /* four bytes */
+
+ /* set on precise point where sensitivity starts */
+ if (esd->numcomps < 257)
+ buf += 6;
+ else
+ buf += 7;
+
+ /* let's fill the data fields */
+ for (vv = (esd->tileno < 0) ? 0 : (j2k->cstr_info->packno * esd->tileno); vv < esd->svalnum; vv++) {
+
+ int thistile = vv / j2k->cstr_info->packno, thispacket = vv % j2k->cstr_info->packno;
+
+ /* skip for the hack some lines below */
+ if (thistile == j2k->cstr_info->tw * j2k->cstr_info->th)
+ break;
+
+ /* starting tile distortion */
+ if (thispacket == 0) {
+ TSE = j2k->cstr_info->tile[thistile].distotile;
+ oldMSE = TSE / j2k->cstr_info->tile[thistile].numpix;
+ oldPSNR = 10.0 * log10(Omax2 / oldMSE);
+ }
+
+ /* TSE */
+ TSE -= j2k->cstr_info->tile[thistile].packet[thispacket].disto;
+
+ /* MSE */
+ MSE = TSE / j2k->cstr_info->tile[thistile].numpix;
+
+ /* PSNR */
+ PSNR = 10.0 * log10(Omax2 / MSE);
+
+ /* fill the address range */
+ switch (esd->addrm) {
+
+ /* packet mode */
+ case (0):
+ /* nothing, there is none */
+ break;
+
+ /* byte range */
+ case (1):
+ /* start address of packet */
+ addr1 = (j2k->cstr_info->tile[thistile].packet[thispacket].start_pos) & addrmask;
+ /* end address of packet */
+ addr2 = (j2k->cstr_info->tile[thistile].packet[thispacket].end_pos) & addrmask;
+ break;
+
+ /* packet range */
+ case (2):
+ /* not implemented here */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Addressing mode packet_range is not implemented\n");
+ break;
+
+ /* unknown addressing method */
+ default:
+ /* not implemented here */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown addressing mode\n");
+ break;
+
+ }
+
+ /* hack for writing relative sensitivity of MH and TPHs */
+ if ((esd->senst == 0) && (thispacket == 0)) {
+
+ /* possible MH */
+ if ((thistile == 0) && !doneMH) {
+ /* we have to manage MH addresses */
+ addr1 = 0; /* start of MH */
+ addr2 = j2k->cstr_info->main_head_end; /* end of MH */
+ /* set special dvalue for this MH */
+ dvalue = -10.0;
+ doneMH = OPJ_TRUE; /* don't come here anymore */
+ vv--; /* wrap back loop counter */
+
+ } else if (!doneTPH) {
+ /* we have to manage TPH addresses */
+ addr1 = j2k->cstr_info->tile[thistile].start_pos;
+ addr2 = j2k->cstr_info->tile[thistile].end_header;
+ /* set special dvalue for this TPH */
+ dvalue = -1.0;
+ doneTPH = OPJ_TRUE; /* don't come here till the next tile */
+ vv--; /* wrap back loop counter */
+ }
+
+ } else
+ doneTPH = OPJ_FALSE; /* reset TPH counter */
+
+ /* write the addresses to the buffer */
+ switch (esd->ad_size) {
+
+ case (0):
+ /* do nothing */
+ break;
+
+ case (2):
+ /* two bytes */
+ *(buf++) = (unsigned char) (addr1 >> 8);
+ *(buf++) = (unsigned char) (addr1 >> 0);
+ *(buf++) = (unsigned char) (addr2 >> 8);
+ *(buf++) = (unsigned char) (addr2 >> 0);
+ break;
+
+ case (4):
+ /* four bytes */
+ *(buf++) = (unsigned char) (addr1 >> 24);
+ *(buf++) = (unsigned char) (addr1 >> 16);
+ *(buf++) = (unsigned char) (addr1 >> 8);
+ *(buf++) = (unsigned char) (addr1 >> 0);
+ *(buf++) = (unsigned char) (addr2 >> 24);
+ *(buf++) = (unsigned char) (addr2 >> 16);
+ *(buf++) = (unsigned char) (addr2 >> 8);
+ *(buf++) = (unsigned char) (addr2 >> 0);
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+
+ /* let's fill the value field */
+ switch (esd->senst) {
+
+ /* relative sensitivity */
+ case (0):
+ /* we just write down the packet ordering */
+ if (dvalue == -10)
+ /* MH */
+ dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+ else if (dvalue == -1)
+ /* TPH */
+ dvalue = MAX_V1 + 1000.0; /* this will cause pfpvalue set to 0xFFFF */
+ else
+ /* packet: first is most important, and then in decreasing order
+ down to the last, which counts for 1 */
+ dvalue = jpwl_pfp_to_double((unsigned short) (j2k->cstr_info->packno - thispacket), esd->se_size);
+ break;
+
+ /* MSE */
+ case (1):
+ /* !!! WRONG: let's put here disto field of packets !!! */
+ dvalue = MSE;
+ break;
+
+ /* MSE reduction */
+ case (2):
+ dvalue = oldMSE - MSE;
+ oldMSE = MSE;
+ break;
+
+ /* PSNR */
+ case (3):
+ dvalue = PSNR;
+ break;
+
+ /* PSNR increase */
+ case (4):
+ dvalue = PSNR - oldPSNR;
+ oldPSNR = PSNR;
+ break;
+
+ /* MAXERR */
+ case (5):
+ dvalue = 0.0;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "MAXERR sensitivity mode is not implemented\n");
+ break;
+
+ /* TSE */
+ case (6):
+ dvalue = TSE;
+ break;
+
+ /* reserved */
+ case (7):
+ dvalue = 0.0;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Reserved sensitivity mode is not implemented\n");
+ break;
+
+ default:
+ dvalue = 0.0;
+ break;
+ }
+
+ /* compute the pseudo-floating point value */
+ pfpvalue = jpwl_double_to_pfp(dvalue, esd->se_size);
+
+ /* write the pfp value to the buffer */
+ switch (esd->se_size) {
+
+ case (1):
+ /* one byte */
+ *(buf++) = (unsigned char) (pfpvalue >> 0);
+ break;
+
+ case (2):
+ /* two bytes */
+ *(buf++) = (unsigned char) (pfpvalue >> 8);
+ *(buf++) = (unsigned char) (pfpvalue >> 0);
+ break;
+ }
+
+ }
+
+ return OPJ_TRUE;
+}
+
+opj_bool jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esd, unsigned char *buf) {
+
+ /* Marker */
+ *(buf++) = (unsigned char) (J2K_MS_ESD >> 8);
+ *(buf++) = (unsigned char) (J2K_MS_ESD >> 0);
+
+ /* Lesd */
+ *(buf++) = (unsigned char) (esd->Lesd >> 8);
+ *(buf++) = (unsigned char) (esd->Lesd >> 0);
+
+ /* Cesd */
+ if (esd->numcomps >= 257)
+ *(buf++) = (unsigned char) (esd->Cesd >> 8);
+ *(buf++) = (unsigned char) (esd->Cesd >> 0);
+
+ /* Pesd */
+ *(buf++) = (unsigned char) (esd->Pesd >> 0);
+
+ /* Data */
+ if (esd->numcomps < 257)
+ memset(buf, 0xAA, (size_t) esd->Lesd - 4);
+ /*memcpy(buf, esd->data, (size_t) esd->Lesd - 4);*/
+ else
+ memset(buf, 0xAA, (size_t) esd->Lesd - 5);
+ /*memcpy(buf, esd->data, (size_t) esd->Lesd - 5);*/
+
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_ESD, -1, esd->Lesd + 2);
+
+}
+
+unsigned short int jpwl_double_to_pfp(double V, int bytes) {
+
+ unsigned short int em, e, m;
+
+ switch (bytes) {
+
+ case (1):
+
+ if (V < MIN_V1) {
+ e = 0x0000;
+ m = 0x0000;
+ } else if (V > MAX_V1) {
+ e = 0x000F;
+ m = 0x000F;
+ } else {
+ e = (unsigned short int) (floor(log(V) * 1.44269504088896) / 4.0);
+ m = (unsigned short int) (0.5 + (V / (pow(2.0, (double) (4 * e)))));
+ }
+ em = ((e & 0x000F) << 4) + (m & 0x000F);
+ break;
+
+ case (2):
+
+ if (V < MIN_V2) {
+ e = 0x0000;
+ m = 0x0000;
+ } else if (V > MAX_V2) {
+ e = 0x001F;
+ m = 0x07FF;
+ } else {
+ e = (unsigned short int) floor(log(V) * 1.44269504088896) + 15;
+ m = (unsigned short int) (0.5 + 2048.0 * ((V / (pow(2.0, (double) e - 15.0))) - 1.0));
+ }
+ em = ((e & 0x001F) << 11) + (m & 0x07FF);
+ break;
+
+ default:
+
+ em = 0x0000;
+ break;
+ };
+
+ return em;
+}
+
+double jpwl_pfp_to_double(unsigned short int em, int bytes) {
+
+ double V;
+
+ switch (bytes) {
+
+ case 1:
+ V = (double) (em & 0x0F) * pow(2.0, (double) (em & 0xF0));
+ break;
+
+ case 2:
+
+ V = pow(2.0, (double) ((em & 0xF800) >> 11) - 15.0) * (1.0 + (double) (em & 0x07FF) / 2048.0);
+ break;
+
+ default:
+ V = 0.0;
+ break;
+
+ }
+
+ return V;
+
+}
+
+opj_bool jpwl_update_info(opj_j2k_t *j2k, jpwl_marker_t *jwmarker, int jwmarker_num) {
+
+ int mm;
+ unsigned long int addlen;
+
+ opj_codestream_info_t *info = j2k->cstr_info;
+ int tileno, tpno, packno, numtiles = info->th * info->tw, numpacks = info->packno;
+
+ if (!j2k || !jwmarker ) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "J2K handle or JPWL markers list badly allocated\n");
+ return OPJ_FALSE;
+ }
+
+ /* main_head_end: how many markers are there before? */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->main_head_end)
+ addlen += jwmarker[mm].len + 2;
+ info->main_head_end += addlen;
+
+ /* codestream_size: always increment with all markers */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ addlen += jwmarker[mm].len + 2;
+ info->codestream_size += addlen;
+
+ /* navigate through all the tiles */
+ for (tileno = 0; tileno < numtiles; tileno++) {
+
+ /* start_pos: increment with markers before SOT */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].start_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].start_pos += addlen;
+
+ /* end_header: increment with markers before of it */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_header)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].end_header += addlen;
+
+ /* end_pos: increment with markers before the end of this tile */
+ /* code is disabled, since according to JPWL no markers can be beyond TPH */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].end_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].end_pos += addlen;
+
+ /* navigate through all the tile parts */
+ for (tpno = 0; tpno < info->tile[tileno].num_tps; tpno++) {
+
+ /* start_pos: increment with markers before SOT */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].tp[tpno].tp_start_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].tp[tpno].tp_start_pos += addlen;
+
+ /* end_header: increment with markers before of it */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].tp[tpno].tp_end_header)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].tp[tpno].tp_end_header += addlen;
+
+ /* end_pos: increment with markers before the end of this tile part */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].tp[tpno].tp_end_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].tp[tpno].tp_end_pos += addlen;
+
+ }
+
+ /* navigate through all the packets in this tile */
+ for (packno = 0; packno < numpacks; packno++) {
+
+ /* start_pos: increment with markers before the packet */
+ /* disabled for the same reason as before */
+ addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos <= (unsigned long int) info->tile[tileno].packet[packno].start_pos)
+ addlen += jwmarker[mm].len + 2;
+ info->tile[tileno].packet[packno].start_pos += addlen;
+
+ /* end_ph_pos: increment with markers before the packet */
+ /* disabled for the same reason as before */
+ /*addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_ph_pos)
+ addlen += jwmarker[mm].len + 2;*/
+ info->tile[tileno].packet[packno].end_ph_pos += addlen;
+
+ /* end_pos: increment if marker is before the end of packet */
+ /* disabled for the same reason as before */
+ /*addlen = 0;
+ for (mm = 0; mm < jwmarker_num; mm++)
+ if (jwmarker[mm].pos < (unsigned long int) info->tile[tileno].packet[packno].end_pos)
+ addlen += jwmarker[mm].len + 2;*/
+ info->tile[tileno].packet[packno].end_pos += addlen;
+
+ }
+ }
+
+ /* reorder the markers list */
+
+ return OPJ_TRUE;
+}
+
+#endif /* USE_JPWL */
diff --git a/src/lib/openjpwl/rs.c b/src/lib/openjpwl/rs.c
new file mode 100644
index 00000000..0841c637
--- /dev/null
+++ b/src/lib/openjpwl/rs.c
@@ -0,0 +1,597 @@
+ /*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 USE_JPWL
+
+/**
+@file rs.c
+@brief Functions used to compute the Reed-Solomon parity and check of byte arrays
+
+*/
+
+/**
+ * Reed-Solomon coding and decoding
+ * Phil Karn (karn@ka9q.ampr.org) September 1996
+ *
+ * This file is derived from the program "new_rs_erasures.c" by Robert
+ * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy
+ * (harit@spectra.eng.hawaii.edu), Aug 1995
+ *
+ * I've made changes to improve performance, clean up the code and make it
+ * easier to follow. Data is now passed to the encoding and decoding functions
+ * through arguments rather than in global arrays. The decode function returns
+ * the number of corrected symbols, or -1 if the word is uncorrectable.
+ *
+ * This code supports a symbol size from 2 bits up to 16 bits,
+ * implying a block size of 3 2-bit symbols (6 bits) up to 65535
+ * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h.
+ *
+ * Note that if symbols larger than 8 bits are used, the type of each
+ * data array element switches from unsigned char to unsigned int. The
+ * caller must ensure that elements larger than the symbol range are
+ * not passed to the encoder or decoder.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include "rs.h"
+
+/* This defines the type used to store an element of the Galois Field
+ * used by the code. Make sure this is something larger than a char if
+ * if anything larger than GF(256) is used.
+ *
+ * Note: unsigned char will work up to GF(256) but int seems to run
+ * faster on the Pentium.
+ */
+typedef int gf;
+
+/* KK = number of information symbols */
+static int KK;
+
+/* Primitive polynomials - see Lin & Costello, Appendix A,
+ * and Lee & Messerschmitt, p. 453.
+ */
+#if(MM == 2)/* Admittedly silly */
+int Pp[MM+1] = { 1, 1, 1 };
+
+#elif(MM == 3)
+/* 1 + x + x^3 */
+int Pp[MM+1] = { 1, 1, 0, 1 };
+
+#elif(MM == 4)
+/* 1 + x + x^4 */
+int Pp[MM+1] = { 1, 1, 0, 0, 1 };
+
+#elif(MM == 5)
+/* 1 + x^2 + x^5 */
+int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };
+
+#elif(MM == 6)
+/* 1 + x + x^6 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };
+
+#elif(MM == 7)
+/* 1 + x^3 + x^7 */
+int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };
+
+#elif(MM == 8)
+/* 1+x^2+x^3+x^4+x^8 */
+int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };
+
+#elif(MM == 9)
+/* 1+x^4+x^9 */
+int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
+
+#elif(MM == 10)
+/* 1+x^3+x^10 */
+int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 11)
+/* 1+x^2+x^11 */
+int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 12)
+/* 1+x+x^4+x^6+x^12 */
+int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 13)
+/* 1+x+x^3+x^4+x^13 */
+int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 14)
+/* 1+x+x^6+x^10+x^14 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };
+
+#elif(MM == 15)
+/* 1+x+x^15 */
+int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+
+#elif(MM == 16)
+/* 1+x+x^3+x^12+x^16 */
+int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
+
+#else
+#error "MM must be in range 2-16"
+#endif
+
+/* Alpha exponent for the first root of the generator polynomial */
+#define B0 0 /* Different from the default 1 */
+
+/* index->polynomial form conversion table */
+gf Alpha_to[NN + 1];
+
+/* Polynomial->index form conversion table */
+gf Index_of[NN + 1];
+
+/* No legal value in index form represents zero, so
+ * we need a special value for this purpose
+ */
+#define A0 (NN)
+
+/* Generator polynomial g(x)
+ * Degree of g(x) = 2*TT
+ * has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)
+ */
+/*gf Gg[NN - KK + 1];*/
+gf Gg[NN - 1];
+
+/* Compute x % NN, where NN is 2**MM - 1,
+ * without a slow divide
+ */
+static /*inline*/ gf
+modnn(int x)
+{
+ while (x >= NN) {
+ x -= NN;
+ x = (x >> MM) + (x & NN);
+ }
+ return x;
+}
+
+/*#define min(a,b) ((a) < (b) ? (a) : (b))*/
+
+#define CLEAR(a,n) {\
+ int ci;\
+ for(ci=(n)-1;ci >=0;ci--)\
+ (a)[ci] = 0;\
+ }
+
+#define COPY(a,b,n) {\
+ int ci;\
+ for(ci=(n)-1;ci >=0;ci--)\
+ (a)[ci] = (b)[ci];\
+ }
+#define COPYDOWN(a,b,n) {\
+ int ci;\
+ for(ci=(n)-1;ci >=0;ci--)\
+ (a)[ci] = (b)[ci];\
+ }
+
+void init_rs(int k)
+{
+ KK = k;
+ if (KK >= NN) {
+ printf("KK must be less than 2**MM - 1\n");
+ exit(1);
+ }
+
+ generate_gf();
+ gen_poly();
+}
+
+/* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
+ lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;
+ polynomial form -> index form index_of[j=alpha**i] = i
+ alpha=2 is the primitive element of GF(2**m)
+ HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
+ Let @ represent the primitive element commonly called "alpha" that
+ is the root of the primitive polynomial p(x). Then in GF(2^m), for any
+ 0 <= i <= 2^m-2,
+ @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+ where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
+ of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
+ example the polynomial representation of @^5 would be given by the binary
+ representation of the integer "alpha_to[5]".
+ Similarily, index_of[] can be used as follows:
+ As above, let @ represent the primitive element of GF(2^m) that is
+ the root of the primitive polynomial p(x). In order to find the power
+ of @ (alpha) that has the polynomial representation
+ a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
+ we consider the integer "i" whose binary representation with a(0) being LSB
+ and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
+ "index_of[i]". Now, @^index_of[i] is that element whose polynomial
+ representation is (a(0),a(1),a(2),...,a(m-1)).
+ NOTE:
+ The element alpha_to[2^m-1] = 0 always signifying that the
+ representation of "@^infinity" = 0 is (0,0,0,...,0).
+ Similarily, the element index_of[0] = A0 always signifying
+ that the power of alpha which has the polynomial representation
+ (0,0,...,0) is "infinity".
+
+*/
+
+void
+generate_gf(void)
+{
+ register int i, mask;
+
+ mask = 1;
+ Alpha_to[MM] = 0;
+ for (i = 0; i < MM; i++) {
+ Alpha_to[i] = mask;
+ Index_of[Alpha_to[i]] = i;
+ /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
+ if (Pp[i] != 0)
+ Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */
+ mask <<= 1; /* single left-shift */
+ }
+ Index_of[Alpha_to[MM]] = MM;
+ /*
+ * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
+ * poly-repr of @^i shifted left one-bit and accounting for any @^MM
+ * term that may occur when poly-repr of @^i is shifted.
+ */
+ mask >>= 1;
+ for (i = MM + 1; i < NN; i++) {
+ if (Alpha_to[i - 1] >= mask)
+ Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
+ else
+ Alpha_to[i] = Alpha_to[i - 1] << 1;
+ Index_of[Alpha_to[i]] = i;
+ }
+ Index_of[0] = A0;
+ Alpha_to[NN] = 0;
+}
+
+
+/*
+ * Obtain the generator polynomial of the TT-error correcting, length
+ * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,
+ * ... ,(2*TT-1)
+ *
+ * Examples:
+ *
+ * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.
+ * g(x) = (x+@) (x+@**2)
+ *
+ * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.
+ * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)
+ */
+void
+gen_poly(void)
+{
+ register int i, j;
+
+ Gg[0] = Alpha_to[B0];
+ Gg[1] = 1; /* g(x) = (X+@**B0) initially */
+ for (i = 2; i <= NN - KK; i++) {
+ Gg[i] = 1;
+ /*
+ * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
+ * (@**(B0+i-1) + x)
+ */
+ for (j = i - 1; j > 0; j--)
+ if (Gg[j] != 0)
+ Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];
+ else
+ Gg[j] = Gg[j - 1];
+ /* Gg[0] can never be zero */
+ Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];
+ }
+ /* convert Gg[] to index form for quicker encoding */
+ for (i = 0; i <= NN - KK; i++)
+ Gg[i] = Index_of[Gg[i]];
+}
+
+
+/*
+ * take the string of symbols in data[i], i=0..(k-1) and encode
+ * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[]
+ * is input and bb[] is output in polynomial form. Encoding is done by using
+ * a feedback shift register with appropriate connections specified by the
+ * elements of Gg[], which was generated above. Codeword is c(X) =
+ * data(X)*X**(NN-KK)+ b(X)
+ */
+int
+encode_rs(dtype *data, dtype *bb)
+{
+ register int i, j;
+ gf feedback;
+
+ CLEAR(bb,NN-KK);
+ for (i = KK - 1; i >= 0; i--) {
+#if (MM != 8)
+ if(data[i] > NN)
+ return -1; /* Illegal symbol */
+#endif
+ feedback = Index_of[data[i] ^ bb[NN - KK - 1]];
+ if (feedback != A0) { /* feedback term is non-zero */
+ for (j = NN - KK - 1; j > 0; j--)
+ if (Gg[j] != A0)
+ bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];
+ else
+ bb[j] = bb[j - 1];
+ bb[0] = Alpha_to[modnn(Gg[0] + feedback)];
+ } else { /* feedback term is zero. encoder becomes a
+ * single-byte shifter */
+ for (j = NN - KK - 1; j > 0; j--)
+ bb[j] = bb[j - 1];
+ bb[0] = 0;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,
+ * writes the codeword into data[] itself. Otherwise data[] is unaltered.
+ *
+ * Return number of symbols corrected, or -1 if codeword is illegal
+ * or uncorrectable.
+ *
+ * First "no_eras" erasures are declared by the calling program. Then, the
+ * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
+ * If the number of channel errors is not greater than "t_after_eras" the
+ * transmitted codeword will be recovered. Details of algorithm can be found
+ * in R. Blahut's "Theory ... of Error-Correcting Codes".
+ */
+int
+eras_dec_rs(dtype *data, int *eras_pos, int no_eras)
+{
+ int deg_lambda, el, deg_omega;
+ int i, j, r;
+ gf u,q,tmp,num1,num2,den,discr_r;
+ gf recd[NN];
+ /* Err+Eras Locator poly and syndrome poly */
+ /*gf lambda[NN-KK + 1], s[NN-KK + 1];
+ gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
+ gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];*/
+ gf lambda[NN + 1], s[NN + 1];
+ gf b[NN + 1], t[NN + 1], omega[NN + 1];
+ gf root[NN], reg[NN + 1], loc[NN];
+ int syn_error, count;
+
+ /* data[] is in polynomial form, copy and convert to index form */
+ for (i = NN-1; i >= 0; i--){
+#if (MM != 8)
+ if(data[i] > NN)
+ return -1; /* Illegal symbol */
+#endif
+ recd[i] = Index_of[data[i]];
+ }
+ /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)
+ * namely @**(B0+i), i = 0, ... ,(NN-KK-1)
+ */
+ syn_error = 0;
+ for (i = 1; i <= NN-KK; i++) {
+ tmp = 0;
+ for (j = 0; j < NN; j++)
+ if (recd[j] != A0) /* recd[j] in index form */
+ tmp ^= Alpha_to[modnn(recd[j] + (B0+i-1)*j)];
+ syn_error |= tmp; /* set flag if non-zero syndrome =>
+ * error */
+ /* store syndrome in index form */
+ s[i] = Index_of[tmp];
+ }
+ if (!syn_error) {
+ /*
+ * if syndrome is zero, data[] is a codeword and there are no
+ * errors to correct. So return data[] unmodified
+ */
+ return 0;
+ }
+ CLEAR(&lambda[1],NN-KK);
+ lambda[0] = 1;
+ if (no_eras > 0) {
+ /* Init lambda to be the erasure locator polynomial */
+ lambda[1] = Alpha_to[eras_pos[0]];
+ for (i = 1; i < no_eras; i++) {
+ u = eras_pos[i];
+ for (j = i+1; j > 0; j--) {
+ tmp = Index_of[lambda[j - 1]];
+ if(tmp != A0)
+ lambda[j] ^= Alpha_to[modnn(u + tmp)];
+ }
+ }
+#ifdef ERASURE_DEBUG
+ /* find roots of the erasure location polynomial */
+ for(i=1;i<=no_eras;i++)
+ reg[i] = Index_of[lambda[i]];
+ count = 0;
+ for (i = 1; i <= NN; i++) {
+ q = 1;
+ for (j = 1; j <= no_eras; j++)
+ if (reg[j] != A0) {
+ reg[j] = modnn(reg[j] + j);
+ q ^= Alpha_to[reg[j]];
+ }
+ if (!q) {
+ /* store root and error location
+ * number indices
+ */
+ root[count] = i;
+ loc[count] = NN - i;
+ count++;
+ }
+ }
+ if (count != no_eras) {
+ printf("\n lambda(x) is WRONG\n");
+ return -1;
+ }
+#ifndef NO_PRINT
+ printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
+ for (i = 0; i < count; i++)
+ printf("%d ", loc[i]);
+ printf("\n");
+#endif
+#endif
+ }
+ for(i=0;i<NN-KK+1;i++)
+ b[i] = Index_of[lambda[i]];
+
+ /*
+ * Begin Berlekamp-Massey algorithm to determine error+erasure
+ * locator polynomial
+ */
+ r = no_eras;
+ el = no_eras;
+ while (++r <= NN-KK) { /* r is the step number */
+ /* Compute discrepancy at the r-th step in poly-form */
+ discr_r = 0;
+ for (i = 0; i < r; i++){
+ if ((lambda[i] != 0) && (s[r - i] != A0)) {
+ discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
+ }
+ }
+ discr_r = Index_of[discr_r]; /* Index form */
+ if (discr_r == A0) {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ COPYDOWN(&b[1],b,NN-KK);
+ b[0] = A0;
+ } else {
+ /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+ t[0] = lambda[0];
+ for (i = 0 ; i < NN-KK; i++) {
+ if(b[i] != A0)
+ t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
+ else
+ t[i+1] = lambda[i+1];
+ }
+ if (2 * el <= r + no_eras - 1) {
+ el = r + no_eras - el;
+ /*
+ * 2 lines below: B(x) <-- inv(discr_r) *
+ * lambda(x)
+ */
+ for (i = 0; i <= NN-KK; i++)
+ b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
+ } else {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ COPYDOWN(&b[1],b,NN-KK);
+ b[0] = A0;
+ }
+ COPY(lambda,t,NN-KK+1);
+ }
+ }
+
+ /* Convert lambda to index form and compute deg(lambda(x)) */
+ deg_lambda = 0;
+ for(i=0;i<NN-KK+1;i++){
+ lambda[i] = Index_of[lambda[i]];
+ if(lambda[i] != A0)
+ deg_lambda = i;
+ }
+ /*
+ * Find roots of the error+erasure locator polynomial. By Chien
+ * Search
+ */
+ COPY(&reg[1],&lambda[1],NN-KK);
+ count = 0; /* Number of roots of lambda(x) */
+ for (i = 1; i <= NN; i++) {
+ q = 1;
+ for (j = deg_lambda; j > 0; j--)
+ if (reg[j] != A0) {
+ reg[j] = modnn(reg[j] + j);
+ q ^= Alpha_to[reg[j]];
+ }
+ if (!q) {
+ /* store root (index-form) and error location number */
+ root[count] = i;
+ loc[count] = NN - i;
+ count++;
+ }
+ }
+
+#ifdef DEBUG
+ printf("\n Final error positions:\t");
+ for (i = 0; i < count; i++)
+ printf("%d ", loc[i]);
+ printf("\n");
+#endif
+ if (deg_lambda != count) {
+ /*
+ * deg(lambda) unequal to number of roots => uncorrectable
+ * error detected
+ */
+ return -1;
+ }
+ /*
+ * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+ * x**(NN-KK)). in index form. Also find deg(omega).
+ */
+ deg_omega = 0;
+ for (i = 0; i < NN-KK;i++){
+ tmp = 0;
+ j = (deg_lambda < i) ? deg_lambda : i;
+ for(;j >= 0; j--){
+ if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
+ tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
+ }
+ if(tmp != 0)
+ deg_omega = i;
+ omega[i] = Index_of[tmp];
+ }
+ omega[NN-KK] = A0;
+
+ /*
+ * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+ * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
+ */
+ for (j = count-1; j >=0; j--) {
+ num1 = 0;
+ for (i = deg_omega; i >= 0; i--) {
+ if (omega[i] != A0)
+ num1 ^= Alpha_to[modnn(omega[i] + i * root[j])];
+ }
+ num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
+ den = 0;
+
+ /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+ for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
+ if(lambda[i+1] != A0)
+ den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
+ }
+ if (den == 0) {
+#ifdef DEBUG
+ printf("\n ERROR: denominator = 0\n");
+#endif
+ return -1;
+ }
+ /* Apply error to data */
+ if (num1 != 0) {
+ data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
+ }
+ }
+ return count;
+}
+
+
+#endif /* USE_JPWL */
diff --git a/src/lib/openjpwl/rs.h b/src/lib/openjpwl/rs.h
new file mode 100644
index 00000000..7d02a477
--- /dev/null
+++ b/src/lib/openjpwl/rs.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy
+ * 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 USE_JPWL
+
+/**
+@file rs.h
+@brief Functions used to compute Reed-Solomon parity and check of byte arrays
+
+*/
+
+#ifndef __RS_HEADER__
+#define __RS_HEADER__
+
+/** Global definitions for Reed-Solomon encoder/decoder
+ * Phil Karn KA9Q, September 1996
+ *
+ * The parameters MM and KK specify the Reed-Solomon code parameters.
+ *
+ * Set MM to be the size of each code symbol in bits. The Reed-Solomon
+ * block size will then be NN = 2**M - 1 symbols. Supported values are
+ * defined in rs.c.
+ *
+ * Set KK to be the number of data symbols in each block, which must be
+ * less than the block size. The code will then be able to correct up
+ * to NN-KK erasures or (NN-KK)/2 errors, or combinations thereof with
+ * each error counting as two erasures.
+ */
+#define MM 8 /* RS code over GF(2**MM) - change to suit */
+
+/* KK defined in rs.c */
+
+#define NN ((1 << MM) - 1)
+
+#if (MM <= 8)
+typedef unsigned char dtype;
+#else
+typedef unsigned int dtype;
+#endif
+
+/** Initialization function */
+void init_rs(int);
+
+/** These two functions *must* be called in this order (e.g.,
+ * by init_rs()) before any encoding/decoding
+ */
+void generate_gf(void); /* Generate Galois Field */
+void gen_poly(void); /* Generate generator polynomial */
+
+/** Reed-Solomon encoding
+ * data[] is the input block, parity symbols are placed in bb[]
+ * bb[] may lie past the end of the data, e.g., for (255,223):
+ * encode_rs(&data[0],&data[223]);
+ */
+int encode_rs(dtype data[], dtype bb[]);
+
+/** Reed-Solomon erasures-and-errors decoding
+ * The received block goes into data[], and a list of zero-origin
+ * erasure positions, if any, goes in eras_pos[] with a count in no_eras.
+ *
+ * The decoder corrects the symbols in place, if possible and returns
+ * the number of corrected symbols. If the codeword is illegal or
+ * uncorrectible, the data array is unchanged and -1 is returned
+ */
+int eras_dec_rs(dtype data[], int eras_pos[], int no_eras);
+
+/**
+Computes the minimum between two integers
+@param a first integer to compare
+@param b second integer to compare
+@return returns the minimum integer between a and b
+*/
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+#endif /* __RS_HEADER__ */
+
+
+#endif /* USE_JPWL */