[poppler] 3 commits - CMakeLists.txt cmake/modules configure.ac poppler/JPEG2000Stream.cc poppler/JPEG2000Stream.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Jan 4 13:54:55 PST 2015


 CMakeLists.txt                       |   56 ++++-
 cmake/modules/FindLIBOPENJPEG2.cmake |   30 ++
 configure.ac                         |   80 +++++--
 poppler/JPEG2000Stream.cc            |  366 +++++++++++++++++++++++++++++------
 poppler/JPEG2000Stream.h             |   41 +--
 5 files changed, 453 insertions(+), 120 deletions(-)

New commits:
commit e499fdab2e96cb3069db7ac8ffa0df20ccccddc9
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Sun Jan 4 20:23:39 2015 +0100

    extended openjpeg2 support

diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc
index 77a153b..2d48899 100644
--- a/poppler/JPEG2000Stream.cc
+++ b/poppler/JPEG2000Stream.cc
@@ -6,6 +6,7 @@
 //
 // Copyright 2008-2010, 2012 Albert Astals Cid <aacid at kde.org>
 // Copyright 2011 Daniel Glöckner <daniel-gl at gmx.net>
+// Copyright 2014 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright 2013,2014 Adrian Johnson <ajohnson at redneon.com>
 //
 // Licensed under GPLv2 or later
@@ -44,7 +45,7 @@ struct JPXStreamPrivate {
   void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format);
 #endif
 #ifdef USE_OPENJPEG2
-  void init2(opj_stream_t *stream, OPJ_CODEC_FORMAT format);
+  void init2(OPJ_CODEC_FORMAT format, unsigned char *data, int length);
 #endif
 };
 
@@ -140,6 +141,8 @@ void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMo
   *bitsPerComponent = 8;
   if (priv->image && priv->image->numcomps == 3)
     *csMode = streamCSDeviceRGB;
+  else if (priv->image && priv->image->numcomps == 4)
+    *csMode = streamCSDeviceCMYK;
   else
     *csMode = streamCSDeviceGray;
 }
@@ -225,7 +228,6 @@ void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT fo
   /* Get the decoder handle of the format */
   dinfo = opj_create_decompress(format);
   if (dinfo == NULL) goto error;
-
   /* Catch events using our callbacks */
   opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
 
@@ -260,35 +262,64 @@ error:
 
 
 #ifdef USE_OPENJPEG2
-static OPJ_SIZE_T readStream_callback(void *buffer, OPJ_SIZE_T nBytes, void *userData)
+typedef struct JPXData_s
+{
+  unsigned char *data;
+  int size;
+  int pos;
+} JPXData;
+
+#define BUFFER_INITIAL_SIZE 4096
+
+static OPJ_SIZE_T jpxRead_callback(void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
 {
+  JPXData *jpxData = (JPXData *)p_user_data;
   int len;
-  JPXStream *p = (JPXStream *)userData;
 
-  len = p->readStream(nBytes, (Guchar*)buffer);
+  len = jpxData->size - jpxData->pos;
+  if (len < 0)
+    len = 0;
   if (len == 0)
-    return (OPJ_SIZE_T)-1;
-  else
-    return len;
+    return (OPJ_SIZE_T)-1;  /* End of file! */
+  if ((OPJ_SIZE_T)len > p_nb_bytes)
+    len = p_nb_bytes;
+  memcpy(p_buffer, jpxData->data + jpxData->pos, len);
+  jpxData->pos += len;
+  return len;
 }
 
-void JPXStream::init()
+static OPJ_OFF_T jpxSkip_callback(OPJ_OFF_T skip, void * p_user_data)
 {
-  opj_stream_t *stream;
+  JPXData *jpxData = (JPXData *)p_user_data;
 
-  str->reset();
-  stream = opj_stream_default_create(OPJ_TRUE);
+  jpxData->pos += (skip > jpxData->size - jpxData->pos) ? jpxData->size - jpxData->pos : skip;
+  /* Always return input value to avoid "Problem with skipping JPEG2000 box, stream error" */
+  return skip;
+}
 
-#if OPENJPEG_VERSION >= OPENJPEG_VERSION_ENCODE(2, 1, 0)
-  opj_stream_set_user_data (stream, this, NULL);
-#else
-  opj_stream_set_user_data (stream, this);
-#endif
+static OPJ_BOOL jpxSeek_callback(OPJ_OFF_T seek_pos, void * p_user_data)
+{
+  JPXData *jpxData = (JPXData *)p_user_data;
 
-  opj_stream_set_read_function(stream, readStream_callback);
-  priv->init2(stream, OPJ_CODEC_JP2);
+  if (seek_pos > jpxData->size)
+    return OPJ_FALSE;
+  jpxData->pos = seek_pos;
+  return OPJ_TRUE;
+}
 
-  opj_stream_destroy(stream);
+void JPXStream::init()
+{
+  Object oLen;
+  if (getDict()) getDict()->lookup("Length", &oLen);
+
+  int bufSize = BUFFER_INITIAL_SIZE;
+  if (oLen.isInt()) bufSize = oLen.getInt();
+  oLen.free();
+
+  int length = 0;
+  unsigned char *buf = str->toUnsignedChars(&length, bufSize);
+  priv->init2(OPJ_CODEC_JP2, buf, length);
+  gfree(buf);
 
   if (priv->image) {
     priv->npixels = priv->image->comps[0].w * priv->image->comps[0].h;
@@ -325,8 +356,30 @@ void JPXStream::init()
   priv->inited = gTrue;
 }
 
-void JPXStreamPrivate::init2(opj_stream_t *stream, OPJ_CODEC_FORMAT format)
+void JPXStreamPrivate::init2(OPJ_CODEC_FORMAT format, unsigned char *buf, int length)
 {
+  JPXData jpxData;
+
+  jpxData.data = buf;
+  jpxData.pos = 0;
+  jpxData.size = length;
+
+  opj_stream_t *stream;
+
+  stream = opj_stream_default_create(OPJ_TRUE);
+
+#if OPENJPEG_VERSION >= OPENJPEG_VERSION_ENCODE(2, 1, 0)
+  opj_stream_set_user_data (stream, &jpxData, NULL);
+#else
+  opj_stream_set_user_data (stream, &jpxData);
+#endif
+
+  opj_stream_set_read_function(stream, jpxRead_callback);
+  opj_stream_set_skip_function(stream, jpxSkip_callback);
+  opj_stream_set_seek_function(stream, jpxSeek_callback);
+  /* Set the length to avoid an assert */
+  opj_stream_set_user_data_length(stream, length);
+
   opj_codec_t *decoder;
 
   /* Use default decompression parameters */
@@ -372,17 +425,19 @@ void JPXStreamPrivate::init2(opj_stream_t *stream, OPJ_CODEC_FORMAT format)
   }
 
   opj_destroy_codec(decoder);
+  opj_stream_destroy(stream);
 
   if (image != NULL)
     return;
 
 error:
+  opj_destroy_codec(decoder);
   if (format == OPJ_CODEC_JP2) {
     error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as JP2, trying as J2K.");
-    init2(stream, OPJ_CODEC_J2K);
+    init2(OPJ_CODEC_J2K, buf, length);
   } else if (format == OPJ_CODEC_J2K) {
     error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as J2K, trying as JPT.");
-    init2(stream, OPJ_CODEC_JPT);
+    init2(OPJ_CODEC_JPT, buf, length);
   } else {
     error(errSyntaxError, -1, "Did no succeed opening JPX Stream.");
   }
commit 2841f3c34dd6366a70e4d6d307a08b3fbc3e9897
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jan 4 20:22:47 2015 +0100

    Cmake support for openjpeg2
    
    With some tweaks from Albert

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7fdb49a..8845d00 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ option(BUILD_CPP_TESTS "Whether compile the CPP test programs." ON)
 option(ENABLE_SPLASH "Build the Splash graphics backend." ON)
 option(ENABLE_UTILS "Compile poppler command line utils." ON)
 option(ENABLE_CPP "Compile poppler cpp wrapper." ON)
-option(ENABLE_LIBOPENJPEG "Use libopenjpeg for JPX streams." ON)
+set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2. 'auto' prefers openjpeg1 over openjpeg2 if both are available. Unset to not use openjpeg.")
 set(ENABLE_CMS "auto" CACHE STRING "Use color management system. Possible values: auto, lcms1, lcms2. 'auto' prefers lcms2 over lcms1 if both are available. Unset to disable color management system.")
 option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF)
 option(ENABLE_ZLIB "Build with zlib (not totally safe)." OFF)
@@ -151,11 +151,26 @@ if(ENABLE_ZLIB)
   endif(ZLIB_FOUND)
   set(ENABLE_ZLIB ${ZLIB_FOUND})
 endif(ENABLE_ZLIB)
-if(ENABLE_LIBOPENJPEG)
+set(USE_OPENJPEG1 FALSE)
+set(USE_OPENJPEG2 FALSE)
+if(ENABLE_LIBOPENJPEG STREQUAL "auto")
   find_package(LIBOPENJPEG)
-  set(ENABLE_LIBOPENJPEG ${LIBOPENJPEG_FOUND})
-  set(HAVE_OPENJPEG_H ON)
-endif(ENABLE_LIBOPENJPEG)
+  set(USE_OPENJPEG1 ${LIBOPENJPEG_FOUND})
+  set(WITH_OPENJPEG ${LIBOPENJPEG_FOUND})
+  if(NOT LIBOPENJPEG_FOUND)
+    find_package(LIBOPENJPEG2)
+    set(USE_OPENJPEG2 ${LIBOPENJPEG2_FOUND})
+    set(WITH_OPENJPEG ${LIBOPENJPEG2_FOUND})
+  endif()
+elseif(ENABLE_LIBOPENJPEG STREQUAL "openjpeg1")
+  find_package(LIBOPENJPEG)
+  set(USE_OPENJPEG1 ${LIBOPENJPEG_FOUND})
+  set(WITH_OPENJPEG ${LIBOPENJPEG_FOUND})
+elseif(ENABLE_LIBOPENJPEG STREQUAL "openjpeg2")
+  find_package(LIBOPENJPEG2)
+  set(USE_OPENJPEG2 ${LIBOPENJPEG2_FOUND})
+  set(WITH_OPENJPEG ${LIBOPENJPEG2_FOUND})
+endif()
 if(ENABLE_CMS STREQUAL "auto")
   find_package(LCMS2)
   set(USE_CMS ${LCMS2_FOUND})
@@ -225,6 +240,9 @@ endif(TIFF_FOUND)
 if(LIBOPENJPEG_FOUND)
   include_directories(${LIBOPENJPEG_INCLUDE_DIR})
 endif(LIBOPENJPEG_FOUND)
+if(LIBOPENJPEG2_FOUND)
+  include_directories(${LIBOPENJPEG2_INCLUDE_DIRS})
+endif()
 if(LCMS_FOUND)
   include_directories(${LCMS_INCLUDE_DIR})
 endif(LCMS_FOUND)
@@ -409,11 +427,19 @@ if(LIBOPENJPEG_FOUND)
     poppler/JPEG2000Stream.cc
   )
   set(poppler_LIBS ${poppler_LIBS} ${LIBOPENJPEG_LIBRARIES})
-else (LIBOPENJPEG_FOUND)
+  add_definitions(-DUSE_OPENJPEG1)
+elseif (LIBOPENJPEG2_FOUND)
+  set(poppler_SRCS ${poppler_SRCS}
+    poppler/JPEG2000Stream.cc
+  )
+  add_definitions(-DUSE_OPENJPEG2)
+MESSAGE(${LIBOPENJPEG2_LIBRARIES})
+  set(poppler_LIBS ${poppler_LIBS} ${LIBOPENJPEG2_LIBRARIES})
+else ()
   set(poppler_SRCS ${poppler_SRCS}
     poppler/JPXStream.cc
   )
-endif(LIBOPENJPEG_FOUND)
+endif()
 if(USE_CMS)
   if(LCMS_FOUND)
     set(poppler_LIBS ${poppler_LIBS} ${LCMS_LIBRARIES})
@@ -574,11 +600,15 @@ if(ENABLE_XPDF_HEADERS)
     install(FILES
       poppler/JPEG2000Stream.h
       DESTINATION include/poppler)
-  else(LIBOPENJPEG_FOUND)
+  elseif(LIBOPENJPEG2_FOUND)
+    install(FILES
+      poppler/JPEG2000Stream.h
+      DESTINATION include/poppler)
+  else()
     install(FILES
       poppler/JPXStream.h
       DESTINATION include/poppler)
-  endif(LIBOPENJPEG_FOUND)
+  endif()
   if(ENABLE_SPLASH)
     install(FILES
       poppler/SplashOutputDev.h
@@ -678,7 +708,13 @@ show_end_message_yesno("use libpng" ENABLE_LIBPNG)
 show_end_message_yesno("use libtiff" ENABLE_LIBTIFF)
 show_end_message_yesno("use zlib" ENABLE_ZLIB)
 show_end_message_yesno("use curl" ENABLE_LIBCURL)
-show_end_message_yesno("use libopenjpeg" LIBOPENJPEG_FOUND)
+show_end_message_yesno("use libopenjpeg" WITH_OPENJPEG)
+if(USE_OPENJPEG1)
+  message("      with openjpeg1")
+endif()
+if(USE_OPENJPEG2)
+  message("      with openjpeg2")
+endif()
 show_end_message_yesno("use cms" USE_CMS)
 if(LCMS_FOUND)
   message("      with lcms1")
diff --git a/cmake/modules/FindLIBOPENJPEG2.cmake b/cmake/modules/FindLIBOPENJPEG2.cmake
new file mode 100644
index 0000000..f18bd3c
--- /dev/null
+++ b/cmake/modules/FindLIBOPENJPEG2.cmake
@@ -0,0 +1,30 @@
+# - Try to find the libopenjpeg2 library
+# Once done this will define
+#
+#  LIBOPENJPEG2_FOUND - system has libopenjpeg
+#  LIBOPENJPEG2_INCLUDE_DIRS - the libopenjpeg include directories
+#  LIBOPENJPEG2_LIBRARIES - Link these to use libopenjpeg
+
+# Copyright (c) 2008, Albert Astals Cid, <aacid at kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+if (LIBOPENJPEG2_LIBRARIES AND LIBOPENJPEG2_INCLUDE_DIR)
+
+  # in cache already
+  set(LIBOPENJPEG2_FOUND TRUE)
+
+else ()
+
+  set(LIBOPENJPEG2_FOUND FALSE)
+  set(LIBOPENJPEG2_INCLUDE_DIRS)
+  set(LIBOPENJPEG2_LIBRARIES)
+
+  find_package(PkgConfig REQUIRED)
+  pkg_check_modules(LIBOPENJPEG2 libopenjp2)
+  if (LIBOPENJPEG2_FOUND)
+    add_definitions(-DUSE_OPENJPEG2)
+  endif ()
+endif ()
commit 117af9c6bbd923954ef7de63adec8c22d51da1e4
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jan 4 19:42:34 2015 +0100

    Initial attempt at libopenjpeg2 support
    
    OpenJPEG 2 has a new pkg-config name and API.
    
    - Update configure.ac to find openjpeg 2 and provide V1/v2 macros
    - Update JPEG2000Stream to use new API depending on openjpeg v1/v2 macros
    - OpenJPEG 2.1 changed the API so provide a version macro to make it easier
      to handle the the 2.1 change and any future changes.
    - Move openjpeg.h into the .cc file

diff --git a/configure.ac b/configure.ac
index 54dacf1..47e8aac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -147,32 +147,57 @@ then
 fi
 
 
-dnl Test for libopenjpeg. Versions prior to 1.4 do not provide a pkgconfig file.
+dnl ##### Test for libopenjpeg. Versions prior to 1.4 do not provide a pkgconfig file.
+openjpeg1="no"
+openjpeg2="no"
 AC_ARG_ENABLE(libopenjpeg,
-	      AC_HELP_STRING([--disable-libopenjpeg],
-	                     [Don't build against libopenjpeg.]),
-              enable_libopenjpeg=$enableval,
-              enable_libopenjpeg="try")
-if test x$enable_libopenjpeg = xyes; then
-  PKG_CHECK_MODULES(LIBOPENJPEG, libopenjpeg,
-  		    [],
-    		    [AC_CHECK_LIB([openjpeg], [opj_cio_open],
-  			LIBOPENJPEG_LIBS="-lopenjpeg",
-		        AC_MSG_ERROR("*** libopenjpeg library not found ***"))
-		     AC_CHECK_HEADERS([openjpeg.h],,
-		     	AC_MSG_ERROR("*** libopenjpeg headers not found ***"))])
-elif test x$enable_libopenjpeg = xtry; then
+	      AC_HELP_STRING([--enable-libopenjpeg=@<:@auto/openjpeg1/openjpeg2/none@:>@],
+                             [Use openjpeg for JPEG2000 images. 'auto' prefers openjpeg1 over openjpeg2 if both are available due to regressions in openjpeg2 [[default=auto]]]),
+              [enable_libopenjpeg=$enableval],
+              [enable_libopenjpeg="auto"])
+
+openjpeg_header=yes
+
+dnl test for libopenjpeg1
+if test x$enable_libopenjpeg = xopenjpeg1 || test x$enable_libopenjpeg = xauto; then
   PKG_CHECK_MODULES(LIBOPENJPEG, libopenjpeg,
-                    [enable_libopenjpeg="yes"],
-  		    [AC_CHECK_LIB([openjpeg], [opj_cio_open],
-		        [enable_libopenjpeg="yes"
-  			 LIBOPENJPEG_LIBS="-lopenjpeg"],
-	                [enable_libopenjpeg="no"])
-		     AC_CHECK_HEADERS([openjpeg.h],,
-		         [enable_libopenjpeg="no"])])
+    [openjpeg1="yes"],
+    [AC_CHECK_LIB([openjpeg], [opj_cio_open],
+      [openjpeg1="yes"
+       LIBOPENJPEG_LIBS="-lopenjpeg"],[openjpeg_header=no])
+     AC_CHECK_HEADERS([openjpeg.h],,
+		      [openjpeg="no"])])
+fi
+
+dnl test for libopenjpeg2
+if test x$openjpeg1 = xno; then
+  if test x$enable_libopenjpeg = xopenjpeg2 || test x$enable_libopenjpeg = xauto; then
+    PKG_CHECK_MODULES(LIBOPENJPEG, libopenjp2,
+                      [openjpeg2=yes],[])
+  fi
 fi
 
-if test x$enable_libopenjpeg = xyes; then
+if test x$enable_libopenjpeg = xopenjpeg1 && test x$openjpeg1 = xno; then
+  if test x$openjpeg_header = xno; then
+    AC_MSG_ERROR("*** libopenjpeg headers not found ***")
+  else
+    AC_MSG_ERROR("*** libopenjpeg library not found ***")
+  fi
+fi
+
+if test x$enable_libopenjpeg = xopenjpeg2 && test x$openjpeg2 = xno; then
+  AC_MSG_ERROR("*** libopenjp2 library not found ***")
+fi
+
+if test x$openjpeg1 = xyes || test x$openjpeg2 = xyes; then
+  enable_libopenjpeg=yes
+  if test x$openjpeg1 = xyes; then
+    AC_DEFINE(USE_OPENJPEG1, 1, [Defined if using openjpeg1])
+  fi
+  if test x$openjpeg2 = xyes; then
+    AC_DEFINE(USE_OPENJPEG2, 1, [Defined if using openjpeg2])
+  fi
+
   AC_SUBST(LIBOPENJPEG_CFLAGS)
   AC_SUBST(LIBOPENJPEG_LIBS)
   AC_DEFINE(ENABLE_LIBOPENJPEG)
@@ -182,9 +207,11 @@ if test x$enable_libopenjpeg = xyes; then
        [AC_DEFINE(WITH_OPENJPEG_IGNORE_PCLR_CMAP_CDEF_FLAG, 1, [OpenJPEG with the OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG flag.])],
        [])
       ])
+else
+  enable_libopenjpeg=no
 fi
 
-AM_CONDITIONAL(BUILD_LIBOPENJPEG, test x$enable_libopenjpeg = xyes)
+AM_CONDITIONAL(BUILD_LIBOPENJPEG, test x$openjpeg1 = xyes || test x$openjpeg2 = xyes)
 AH_TEMPLATE([ENABLE_LIBOPENJPEG],
 	    [Use libopenjpeg instead of builtin jpeg2000 decoder.])
 
@@ -924,6 +951,13 @@ echo "  use libtiff:        $enable_libtiff"
 echo "  use zlib:           $enable_zlib"
 echo "  use libcurl:        $enable_libcurl"
 echo "  use libopenjpeg:    $enable_libopenjpeg"
+if test x$enable_libopenjpeg = xyes;then
+    if test x$openjpeg1 = xyes;then
+        echo "      with openjpeg1"
+    else
+        echo "      with openjpeg2"
+    fi
+fi
 echo "  use cms:            $enable_cms"
 if test x$enable_cms = xyes;then
     if test x$lcms1 = xyes;then
diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc
index 703d471..77a153b 100644
--- a/poppler/JPEG2000Stream.cc
+++ b/poppler/JPEG2000Stream.cc
@@ -6,49 +6,87 @@
 //
 // Copyright 2008-2010, 2012 Albert Astals Cid <aacid at kde.org>
 // Copyright 2011 Daniel Glöckner <daniel-gl at gmx.net>
-// Copyright 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright 2013,2014 Adrian Johnson <ajohnson at redneon.com>
 //
 // Licensed under GPLv2 or later
 //
 //========================================================================
 
-#include "JPEG2000Stream.h"
-
 #include "config.h"
+#include "JPEG2000Stream.h"
+#include <openjpeg.h>
+
+#define OPENJPEG_VERSION_ENCODE(major, minor, micro) (	\
+	  ((major) * 10000)				\
+	+ ((minor) *   100)				\
+	+ ((micro) *     1))
+
+#ifdef USE_OPENJPEG2
+#ifdef OPJ_VERSION_MAJOR
+#define OPENJPEG_VERSION OPENJPEG_VERSION_ENCODE(OPJ_VERSION_MAJOR, OPJ_VERSION_MINOR, OPJ_VERSION_BUILD)
+#else
+// OpenJPEG started providing version macros in version 2.1.
+// If the version macro is not found, set the version to 2.0.0 and
+// assume there will be no API changes in 2.0.x.
+#define OPENJPEG_VERSION OPENJPEG_VERSION_ENCODE(2, 0, 0)
+#endif
+#endif
 
-JPXStream::JPXStream(Stream *strA) : FilterStream(strA)
-{
-  inited = gFalse;
-  image = NULL;
-  dinfo = NULL;
-  npixels = 0;
-  ncomps = 0;
+struct JPXStreamPrivate {
+  opj_image_t *image;
+  int counter;
+  int ccounter;
+  int npixels;
+  int ncomps;
+  GBool inited;
+#ifdef USE_OPENJPEG1
+  opj_dinfo_t *dinfo;
+  void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format);
+#endif
+#ifdef USE_OPENJPEG2
+  void init2(opj_stream_t *stream, OPJ_CODEC_FORMAT format);
+#endif
+};
+
+JPXStream::JPXStream(Stream *strA) : FilterStream(strA) {
+  priv = new JPXStreamPrivate;
+  priv->inited = gFalse;
+  priv->image = NULL;
+  priv->npixels = 0;
+  priv->ncomps = 0;
+#ifdef USE_OPENJPEG1
+  priv->dinfo = NULL;
+#endif
 }
 
 JPXStream::~JPXStream() {
   delete str;
   close();
+  delete priv;
 }
 
 void JPXStream::reset() {
-  counter = 0;
-  ccounter = 0;
+  priv->counter = 0;
+  priv->ccounter = 0;
 }
 
 void JPXStream::close() {
-  if (image != NULL) {
-    opj_image_destroy(image);
-    image = NULL;
-    npixels = 0;
+  if (priv->image != NULL) {
+    opj_image_destroy(priv->image);
+    priv->image = NULL;
+    priv->npixels = 0;
   }
-  if (dinfo != NULL) {
-    opj_destroy_decompress(dinfo);
-    dinfo = NULL;
+
+#ifdef USE_OPENJPEG1
+  if (priv->dinfo != NULL) {
+    opj_destroy_decompress(priv->dinfo);
+    priv->dinfo = NULL;
   }
+#endif
 }
 
 Goffset JPXStream::getPos() {
-  return counter * ncomps + ccounter;
+  return priv->counter * priv->ncomps + priv->ccounter;
 }
 
 int JPXStream::getChars(int nChars, Guchar *buffer) {
@@ -64,6 +102,59 @@ int JPXStream::getChar() {
   return doGetChar();
 }
 
+int JPXStream::doLookChar() {
+  if (unlikely(priv->inited == gFalse))
+    init();
+
+  if (unlikely(priv->counter >= priv->npixels))
+    return EOF;
+
+  return ((unsigned char *)priv->image->comps[priv->ccounter].data)[priv->counter];
+}
+
+int JPXStream::lookChar() {
+  return doLookChar();
+}
+
+int JPXStream::doGetChar() {
+  int result = doLookChar();
+  if (++priv->ccounter == priv->ncomps) {
+    priv->ccounter = 0;
+    ++priv->counter;
+  }
+  return result;
+}
+
+GooString *JPXStream::getPSFilter(int psLevel, const char *indent) {
+  return NULL;
+}
+
+GBool JPXStream::isBinary(GBool last) {
+  return str->isBinary(gTrue);
+}
+
+void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode) {
+  if (priv->inited == gFalse)
+    init();
+
+  *bitsPerComponent = 8;
+  if (priv->image && priv->image->numcomps == 3)
+    *csMode = streamCSDeviceRGB;
+  else
+    *csMode = streamCSDeviceGray;
+}
+
+
+static void libopenjpeg_error_callback(const char *msg, void * /*client_data*/) {
+  error(errSyntaxError, -1, "{0:s}", msg);
+}
+
+static void libopenjpeg_warning_callback(const char *msg, void * /*client_data*/) {
+  error(errSyntaxWarning, -1, "{0:s}", msg);
+}
+
+#ifdef USE_OPENJPEG1
+
 #define BUFFER_INITIAL_SIZE 4096
 
 void JPXStream::init()
@@ -75,29 +166,28 @@ void JPXStream::init()
   if (oLen.isInt()) bufSize = oLen.getInt();
   oLen.free();
 
-  
   int length = 0;
   unsigned char *buf = str->toUnsignedChars(&length, bufSize);
-  init2(buf, length, CODEC_JP2);
+  priv->init2(buf, length, CODEC_JP2);
   free(buf);
 
-  if (image) {
-    npixels = image->comps[0].w * image->comps[0].h;
-    ncomps = image->numcomps;
-    for (int component = 0; component < ncomps; component++) {
-      if (image->comps[component].data == NULL) {
+  if (priv->image) {
+    priv->npixels = priv->image->comps[0].w * priv->image->comps[0].h;
+    priv->ncomps = priv->image->numcomps;
+    for (int component = 0; component < priv->ncomps; component++) {
+      if (priv->image->comps[component].data == NULL) {
         close();
         break;
       }
-      unsigned char *cdata = (unsigned char *)image->comps[component].data;
+      unsigned char *cdata = (unsigned char *)priv->image->comps[component].data;
       int adjust = 0;
-      if (image->comps[component].prec > 8)
-	adjust = image->comps[component].prec - 8;
+      if (priv->image->comps[component].prec > 8)
+	adjust = priv->image->comps[component].prec - 8;
       int sgndcorr = 0;
-      if (image->comps[component].sgnd)
-	sgndcorr = 1 << (image->comps[0].prec - 1);
-      for (int i = 0; i < npixels; i++) {
-	int r = image->comps[component].data[i];
+      if (priv->image->comps[component].sgnd)
+	sgndcorr = 1 << (priv->image->comps[0].prec - 1);
+      for (int i = 0; i < priv->npixels; i++) {
+	int r = priv->image->comps[component].data[i];
 	r += sgndcorr;
 	if (adjust) {
 	  r = (r >> adjust)+((r >> (adjust-1))%2);
@@ -108,22 +198,14 @@ void JPXStream::init()
       }
     }
   } else
-    npixels = 0;
+    priv->npixels = 0;
 
-  counter = 0;
-  ccounter = 0;
-  inited = gTrue;
+  priv->counter = 0;
+  priv->ccounter = 0;
+  priv->inited = gTrue;
 }
 
-static void libopenjpeg_error_callback(const char *msg, void * /*client_data*/) {
-  error(errSyntaxError, -1, "{0:s}", msg);
-}
-
-static void libopenjpeg_warning_callback(const char *msg, void * /*client_data*/) {
-  error(errSyntaxWarning, -1, "{0:s}", msg);
-}
-
-void JPXStream::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format)
+void JPXStreamPrivate::init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format)
 {
   opj_cio_t *cio = NULL;
 
@@ -174,24 +256,135 @@ error:
     error(errSyntaxError, -1, "Did no succeed opening JPX Stream.");
   }
 }
+#endif
 
-int JPXStream::lookChar() {
-  return doLookChar();
-}
 
-GooString *JPXStream::getPSFilter(int psLevel, const char *indent) {
-  return NULL;
+#ifdef USE_OPENJPEG2
+static OPJ_SIZE_T readStream_callback(void *buffer, OPJ_SIZE_T nBytes, void *userData)
+{
+  int len;
+  JPXStream *p = (JPXStream *)userData;
+
+  len = p->readStream(nBytes, (Guchar*)buffer);
+  if (len == 0)
+    return (OPJ_SIZE_T)-1;
+  else
+    return len;
 }
 
-GBool JPXStream::isBinary(GBool last) {
-  return str->isBinary(gTrue);
-}
+void JPXStream::init()
+{
+  opj_stream_t *stream;
 
-void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode) {
-  if (inited == gFalse) init();
+  str->reset();
+  stream = opj_stream_default_create(OPJ_TRUE);
 
-  *bitsPerComponent = 8;
-  if (image && image->numcomps == 3) *csMode = streamCSDeviceRGB;
-  else *csMode = streamCSDeviceGray;
+#if OPENJPEG_VERSION >= OPENJPEG_VERSION_ENCODE(2, 1, 0)
+  opj_stream_set_user_data (stream, this, NULL);
+#else
+  opj_stream_set_user_data (stream, this);
+#endif
+
+  opj_stream_set_read_function(stream, readStream_callback);
+  priv->init2(stream, OPJ_CODEC_JP2);
+
+  opj_stream_destroy(stream);
+
+  if (priv->image) {
+    priv->npixels = priv->image->comps[0].w * priv->image->comps[0].h;
+    priv->ncomps = priv->image->numcomps;
+    for (int component = 0; component < priv->ncomps; component++) {
+      if (priv->image->comps[component].data == NULL) {
+        close();
+        break;
+      }
+      unsigned char *cdata = (unsigned char *)priv->image->comps[component].data;
+      int adjust = 0;
+      if (priv->image->comps[component].prec > 8)
+	adjust = priv->image->comps[component].prec - 8;
+      int sgndcorr = 0;
+      if (priv->image->comps[component].sgnd)
+	sgndcorr = 1 << (priv->image->comps[0].prec - 1);
+      for (int i = 0; i < priv->npixels; i++) {
+	int r = priv->image->comps[component].data[i];
+	r += sgndcorr;
+	if (adjust) {
+	  r = (r >> adjust)+((r >> (adjust-1))%2);
+	  if (unlikely(r > 255))
+	    r = 255;
+        }
+	*(cdata++) = r;
+      }
+    }
+  } else {
+    priv->npixels = 0;
+  }
+
+  priv->counter = 0;
+  priv->ccounter = 0;
+  priv->inited = gTrue;
 }
 
+void JPXStreamPrivate::init2(opj_stream_t *stream, OPJ_CODEC_FORMAT format)
+{
+  opj_codec_t *decoder;
+
+  /* Use default decompression parameters */
+  opj_dparameters_t parameters;
+  opj_set_default_decoder_parameters(&parameters);
+  parameters.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
+
+  /* Get the decoder handle of the format */
+  decoder = opj_create_decompress(format);
+  if (decoder == NULL) {
+    error(errSyntaxWarning, -1, "Unable to create decoder");
+    goto error;
+  }
+
+  /* Catch events using our callbacks */
+  opj_set_warning_handler(decoder, libopenjpeg_warning_callback, NULL);
+  opj_set_error_handler(decoder, libopenjpeg_error_callback, NULL);
+
+  /* Setup the decoder decoding parameters */
+  if (!opj_setup_decoder(decoder, &parameters)) {
+    error(errSyntaxWarning, -1, "Unable to set decoder parameters");
+    goto error;
+  }
+
+  /* Decode the stream and fill the image structure */
+  image = NULL;
+  if (!opj_read_header(stream, decoder, &image)) {
+    error(errSyntaxWarning, -1, "Unable to read header");
+    goto error;
+  }
+
+  /* Optional if you want decode the entire image */
+  if (!opj_set_decode_area(decoder, image, parameters.DA_x0,
+                           parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){
+    error(errSyntaxWarning, -1, "X2");
+    goto error;
+  }
+
+  /* Get the decoded image */
+  if (!(opj_decode(decoder, stream, image) && opj_end_decompress(decoder, stream))) {
+    error(errSyntaxWarning, -1, "Unable to decode image");
+    goto error;
+  }
+
+  opj_destroy_codec(decoder);
+
+  if (image != NULL)
+    return;
+
+error:
+  if (format == OPJ_CODEC_JP2) {
+    error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as JP2, trying as J2K.");
+    init2(stream, OPJ_CODEC_J2K);
+  } else if (format == OPJ_CODEC_J2K) {
+    error(errSyntaxWarning, -1, "Did no succeed opening JPX Stream as J2K, trying as JPT.");
+    init2(stream, OPJ_CODEC_JPT);
+  } else {
+    error(errSyntaxError, -1, "Did no succeed opening JPX Stream.");
+  }
+}
+#endif
diff --git a/poppler/JPEG2000Stream.h b/poppler/JPEG2000Stream.h
index 3feccbe..50b7586 100644
--- a/poppler/JPEG2000Stream.h
+++ b/poppler/JPEG2000Stream.h
@@ -6,7 +6,7 @@
 //
 // Copyright 2008, 2010 Albert Astals Cid <aacid at kde.org>
 // Copyright 2011 Daniel Glöckner <daniel-gl at gmx.net>
-// Copyright 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright 2013,2014 Adrian Johnson <ajohnson at redneon.com>
 //
 // Licensed under GPLv2 or later
 //
@@ -16,12 +16,13 @@
 #ifndef JPEG2000STREAM_H
 #define JPEG2000STREAM_H
 
-#include <openjpeg.h>
-
+#include "config.h"
 #include "goo/gtypes.h"
 #include "Object.h"
 #include "Stream.h"
 
+struct JPXStreamPrivate;
+
 class JPXStream: public FilterStream {
 public:
 
@@ -37,37 +38,21 @@ public:
   virtual GBool isBinary(GBool last = gTrue);
   virtual void getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode);
 
+  int readStream(int nChars, Guchar *buffer) {
+    return str->doGetChars(nChars, buffer);
+  }
 private:
-  void init();
-  void init2(unsigned char *buf, int bufLen, OPJ_CODEC_FORMAT format);
+  JPXStream(const JPXStream &other);
+  JPXStream& operator=(const JPXStream &other);
+  JPXStreamPrivate *priv;
 
+  void init();
   virtual GBool hasGetChars() { return true; }
   virtual int getChars(int nChars, Guchar *buffer);
 
-  inline int doGetChar() {
-    int result = doLookChar();
-    if (++ccounter == ncomps) {
-      ccounter = 0;
-      ++counter;
-    }
-    return result;
-  }
-
-  inline int doLookChar() {
-    if (unlikely(inited == gFalse)) init();
-
-    if (unlikely(counter >= npixels)) return EOF;
-
-    return ((unsigned char *)image->comps[ccounter].data)[counter];
-  }
+  int doGetChar();
 
-  opj_image_t *image;
-  opj_dinfo_t *dinfo;
-  int counter;
-  int ccounter;
-  int npixels;
-  int ncomps;
-  GBool inited;
+  int doLookChar();
 };
 
 #endif


More information about the poppler mailing list