[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(¶meters);
+ 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, ¶meters)) {
+ 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