Add JPEG 2000 support.

Signed-off-by: yzrh <yzrh@noema.org>
This commit is contained in:
yzrh 2022-12-29 00:18:07 +00:00
parent abce2fd2e4
commit 8083b30530
5 changed files with 168 additions and 6 deletions

View file

@ -9,8 +9,6 @@ Development
Currently, CAJ, KDH, and HN can be converted. Please report Currently, CAJ, KDH, and HN can be converted. Please report
any failures with a sample that can reproduce the behaviour. any failures with a sample that can reproduce the behaviour.
HN support does not support JPEG 2000 yet.
Dependency Dependency
---------- ----------
@ -19,6 +17,7 @@ Dependency
3. zlib 3. zlib
4. jbig2dec 4. jbig2dec
5. libjpeg-turbo 5. libjpeg-turbo
6. openjpeg
Usage Usage
===== =====
@ -36,7 +35,7 @@ Options
Specify output file Specify output file
-b, --buffer -b, --buffer
Set buffer size (default 512k) Set input buffer size (default 512k)
-v, --verbose -v, --verbose
Print more information (twice for even more, three times for HN image processing information as well) Print more information (twice for even more, three times for HN image processing information as well)

View file

@ -4,11 +4,11 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
# #
src = melon.c iconv.c zlib.c jbig.c jbig2.c jpeg.c \ src = melon.c iconv.c zlib.c jbig.c jbig2.c jpeg.c jp2.c \
cnki_caj.c cnki_hn.c cnki_kdh.c cnki_outline_tree.c \ cnki_caj.c cnki_hn.c cnki_kdh.c cnki_outline_tree.c \
cnki_pdf.c cnki_zlib.c cnki_jbig.c cnki_jbig2.c cnki.c \ cnki_pdf.c cnki_zlib.c cnki_jbig.c cnki_jbig2.c cnki.c \
pdf_cnki.c pdf_get.c pdf_parser.c pdf_writer.c pdf.c pdf_cnki.c pdf_get.c pdf_parser.c pdf_writer.c pdf.c
inc = extern.h version.h iconv.h zlib.h jbig.h jbig2.h jpeg.h \ inc = extern.h version.h iconv.h zlib.h jbig.h jbig2.h jpeg.h jp2.h \
cnki.h pdf_cnki.h cnki_jbig.h pdf.h cnki.h pdf_cnki.h cnki_jbig.h pdf.h
obj = ${src:.c=.o} obj = ${src:.c=.o}
@ -16,7 +16,7 @@ obj = ${src:.c=.o}
PREFIX = /usr/local PREFIX = /usr/local
CFLAGS = -O2 -pipe -flto -Wall -Wextra CFLAGS = -O2 -pipe -flto -Wall -Wextra
LDFLAGS = -Wl,-O2 -lcrypto -liconv -lz -ljbig2dec -ljpeg -Wl,--as-needed LDFLAGS = -Wl,-O2 -lcrypto -liconv -lz -ljbig2dec -ljpeg -lopenjp2 -Wl,--as-needed
CFLAGS += -I/usr/local/include CFLAGS += -I/usr/local/include
LDFLAGS += -L/usr/local/lib LDFLAGS += -L/usr/local/lib

View file

@ -11,6 +11,7 @@
#include "iconv.h" #include "iconv.h"
#include "zlib.h" #include "zlib.h"
#include "jpeg.h" #include "jpeg.h"
#include "jp2.h"
#include "pdf.h" #include "pdf.h"
#include "pdf_cnki.h" #include "pdf_cnki.h"
@ -660,6 +661,41 @@ cnki_pdf_hn(cnki_t **param)
dim[i * 2 + 1] = info[1]; dim[i * 2 + 1] = info[1];
break; break;
case JPX: case JPX:
ret = strinfo_jp2_dim(&info[0],
&info[1],
ptr->image_data[i].image,
ptr->image_data[i].size);
if (ret != 0) {
dim[i * 2] = 0;
dim[i * 2 + 1] = 0;
break;
}
stream_size = ptr->image_data[i].size;
stream = malloc(stream_size);
if (stream == NULL) {
free(root_kid);
free(ids);
free(dim);
free(dictionary);
return 1;
}
memcpy(stream, ptr->image_data[i].image, stream_size);
snprintf(buf, 64, "/Width %d\n/Height %d\n",
info[0], info[1]);
strcat(dictionary, buf);
snprintf(buf, 64, "/Length %d\n",
stream_size);
strcat(dictionary, buf);
strcat(dictionary, "/Filter /JPXDecode\n");
dim[i * 2] = info[0];
dim[i * 2 + 1] = info[1];
break;
default: default:
ret = -1; ret = -1;
dim[i * 2] = -1; dim[i * 2] = -1;

119
src/jp2.c Normal file
View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2022, yzrh <yzrh@noema.org>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#ifdef __linux__
#include <openjpeg.h>
#else
#include <openjpeg-2.5/openjpeg.h>
#endif
typedef struct _stream_user_data {
OPJ_SIZE_T pos;
OPJ_SIZE_T size;
const unsigned char *data;
} stream_user_data;
static OPJ_SIZE_T
_opj_stream_read(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
{
stream_user_data *d = (stream_user_data *) p_user_data;
if (d->pos >= d->size)
return (OPJ_SIZE_T) - 1;
OPJ_SIZE_T ret_size = p_nb_bytes;
if (d->pos + ret_size > d->size)
ret_size = d->size - d->pos;
memcpy(p_buffer, d->data + d->pos, ret_size);
d->pos += ret_size;
return ret_size;
}
static OPJ_OFF_T
_opj_stream_skip(OPJ_OFF_T p_nb_bytes, void *p_user_data)
{
stream_user_data *d = (stream_user_data *) p_user_data;
if (d->pos + p_nb_bytes <= d->size)
d->pos += p_nb_bytes;
else
d->pos = d->size;
return d->pos;
}
static OPJ_BOOL
_opj_stream_seek(OPJ_OFF_T p_nb_bytes, void *p_user_data)
{
stream_user_data *d = (stream_user_data *) p_user_data;
if (p_nb_bytes <= (OPJ_OFF_T) d->size) {
d->pos = p_nb_bytes;
return OPJ_TRUE;
}
return OPJ_FALSE;
}
int
strinfo_jp2_dim(int *jp2_width, int *jp2_height,
const char * restrict data, int data_size)
{
opj_codec_t *codec;
opj_dparameters_t param;
opj_stream_t *stream;
opj_image_t *image;
stream_user_data d;
if (data_size < 2)
return 1;
opj_set_default_decoder_parameters(&param);
if ((unsigned char) data[0] == 0xff && (unsigned char) data[1] == 0x4f)
codec = opj_create_decompress(OPJ_CODEC_J2K);
else
codec = opj_create_decompress(OPJ_CODEC_JP2);
if (!opj_setup_decoder(codec, &param)) {
opj_destroy_codec(codec);
return 1;
}
stream = opj_stream_default_create(OPJ_TRUE);
d.pos = 0;
d.size = data_size;
d.data = (unsigned char *) data;
opj_stream_set_read_function(stream, _opj_stream_read);
opj_stream_set_skip_function(stream, _opj_stream_skip);
opj_stream_set_seek_function(stream, _opj_stream_seek);
opj_stream_set_user_data(stream, &d, NULL);
opj_stream_set_user_data_length(stream, data_size);
if (!opj_read_header(stream, codec, &image)) {
opj_destroy_codec(codec);
opj_stream_destroy(stream);
return 1;
}
opj_destroy_codec(codec);
opj_stream_destroy(stream);
*jp2_width = image->x1 - image->x0;
*jp2_height = image->y1 - image->y0;
opj_image_destroy(image);
return 0;
}

8
src/jp2.h Normal file
View file

@ -0,0 +1,8 @@
/*
* Copyright (c) 2022, yzrh <yzrh@noema.org>
*
* SPDX-License-Identifier: Apache-2.0
*/
int strinfo_jp2_dim(int *jp2_width, int *jp2_height,
const char * restrict data, int data_size);