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@kde.org>
// Copyright 2011 Daniel Glöckner <daniel-gl@gmx.net>
+// Copyright 2014 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright 2013,2014 Adrian Johnson <ajohnson@redneon.com>
//
// Licensed under GPLv2 or later
@@ -44,7 +45,7 @@
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 @@
*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 @@
/* 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 @@
#ifdef USE_OPENJPEG2
-static OPJ_SIZE_T readStream_callback(void *buffer, OPJ_SIZE_T nBytes, void *userData)
+typedef struct JPXData_s
{
- int len;
- JPXStream *p = (JPXStream *)userData;
+ unsigned char *data;
+ int size;
+ int pos;
+} JPXData;
- len = p->readStream(nBytes, (Guchar*)buffer);
+#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;
+
+ 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;
+}
+
+static OPJ_OFF_T jpxSkip_callback(OPJ_OFF_T skip, void * p_user_data)
+{
+ JPXData *jpxData = (JPXData *)p_user_data;
+
+ 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;
+}
+
+static OPJ_BOOL jpxSeek_callback(OPJ_OFF_T seek_pos, void * p_user_data)
+{
+ JPXData *jpxData = (JPXData *)p_user_data;
+
+ if (seek_pos > jpxData->size)
+ return OPJ_FALSE;
+ jpxData->pos = seek_pos;
+ return OPJ_TRUE;
}
void JPXStream::init()
{
- opj_stream_t *stream;
+ Object oLen;
+ if (getDict()) getDict()->lookup("Length", &oLen);
- str->reset();
- stream = opj_stream_default_create(OPJ_TRUE);
+ int bufSize = BUFFER_INITIAL_SIZE;
+ if (oLen.isInt()) bufSize = oLen.getInt();
+ oLen.free();
-#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);
+ 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 @@
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 @@
}
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.");
}