From d42362b328019e106b1b6bfb267ada7844158b6e Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Sun, 26 Jun 2016 07:22:22 +0200 Subject: Support J2K/JP2 files in CBZ. --- include/mupdf/fitz/compressed-buffer.h | 2 +- include/mupdf/fitz/image.h | 1 + source/cbz/mucbz.c | 2 +- source/cbz/muimg.c | 9 +++- source/fitz/image.c | 15 ++++++- source/fitz/load-jpx.c | 75 ++++++++++++++++++++++------------ 6 files changed, 72 insertions(+), 32 deletions(-) diff --git a/include/mupdf/fitz/compressed-buffer.h b/include/mupdf/fitz/compressed-buffer.h index 092d5fe3..1eef070d 100644 --- a/include/mupdf/fitz/compressed-buffer.h +++ b/include/mupdf/fitz/compressed-buffer.h @@ -19,7 +19,7 @@ enum { FZ_IMAGE_UNKNOWN = 0, FZ_IMAGE_JPEG = 1, - FZ_IMAGE_JPX = 2, /* Placeholder until supported */ + FZ_IMAGE_JPX = 2, FZ_IMAGE_FAX = 3, FZ_IMAGE_JBIG2 = 4, FZ_IMAGE_RAW = 5, diff --git a/include/mupdf/fitz/image.h b/include/mupdf/fitz/image.h index 337fd075..bc2879d9 100644 --- a/include/mupdf/fitz/image.h +++ b/include/mupdf/fitz/image.h @@ -115,6 +115,7 @@ fz_pixmap *fz_load_gif(fz_context *ctx, unsigned char *data, size_t size); fz_pixmap *fz_load_bmp(fz_context *ctx, unsigned char *data, size_t size); void fz_load_jpeg_info(fz_context *ctx, unsigned char *data, size_t size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); +void fz_load_jpx_info(fz_context *ctx, unsigned char *data, size_t size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); void fz_load_png_info(fz_context *ctx, unsigned char *data, size_t size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); void fz_load_tiff_info(fz_context *ctx, unsigned char *data, size_t size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); void fz_load_jxr_info(fz_context *ctx, unsigned char *data, size_t size, int *w, int *h, int *xres, int *yres, fz_colorspace **cspace); diff --git a/source/cbz/mucbz.c b/source/cbz/mucbz.c index 74b96268..0b7b4d10 100644 --- a/source/cbz/mucbz.c +++ b/source/cbz/mucbz.c @@ -6,7 +6,7 @@ typedef struct cbz_document_s cbz_document; typedef struct cbz_page_s cbz_page; static const char *cbz_ext_list[] = { - ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tif", ".tiff", + ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tif", ".tiff", ".jpx", ".jp2", ".j2k", NULL }; diff --git a/source/cbz/muimg.c b/source/cbz/muimg.c index d0087fa7..4e0f97df 100644 --- a/source/cbz/muimg.c +++ b/source/cbz/muimg.c @@ -159,7 +159,9 @@ img_recognize(fz_context *doc, const char *magic) if (!fz_strcasecmp(ext, ".png") || !fz_strcasecmp(ext, ".jpg") || !fz_strcasecmp(ext, ".jpeg") || !fz_strcasecmp(ext, ".jfif") || !fz_strcasecmp(ext, ".jfif-tbnl") || !fz_strcasecmp(ext, ".jpe") || - !fz_strcasecmp(ext, ".gif") || !fz_strcasecmp(ext, ".bmp")) + !fz_strcasecmp(ext, ".gif") || !fz_strcasecmp(ext, ".bmp") || + !fz_strcasecmp(ext, ".jpx") || !fz_strcasecmp(ext, ".jp2") || + !fz_strcasecmp(ext, ".j2k")) return 100; } if (!strcmp(magic, "png") || !strcmp(magic, "image/png") || @@ -167,7 +169,10 @@ img_recognize(fz_context *doc, const char *magic) !strcmp(magic, "jpeg") || !strcmp(magic, "image/pjpeg") || !strcmp(magic, "jpe") || !strcmp(magic, "jfif") || !strcmp(magic, "gif") || !strcmp(magic, "image/gif") || - !strcmp(magic, "bmp") || !strcmp(magic, "image/bmp")) + !strcmp(magic, "bmp") || !strcmp(magic, "image/bmp") || + !strcmp(magic, "jpx") || !strcmp(magic, "image/jpx") || + !strcmp(magic, "jp2") || !strcmp(magic, "image/jp2") || + !strcmp(magic, "j2k")) return 100; return 0; diff --git a/source/fitz/image.c b/source/fitz/image.c index b4314480..6919808a 100644 --- a/source/fitz/image.c +++ b/source/fitz/image.c @@ -410,6 +410,9 @@ compressed_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea case FZ_IMAGE_JXR: tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len); break; + case FZ_IMAGE_JPX: + tile = fz_load_jpx(ctx, image->buffer->buffer->data, image->buffer->buffer->len, NULL, 0); + break; case FZ_IMAGE_JPEG: /* Scan JPEG stream and patch missing height values in header */ { @@ -912,7 +915,17 @@ fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer) bc = fz_malloc_struct(ctx, fz_compressed_buffer); bc->buffer = fz_keep_buffer(ctx, buffer); - if (buf[0] == 0xff && buf[1] == 0xd8) + if (buf[0] == 0xff && buf[1] == 0x4f) + { + bc->params.type = FZ_IMAGE_JPX; + fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace); + } + else if (buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x00 && buf[3] == 0x0c && buf[4] == 0x6a && buf[5] == 0x50 && buf[6] == 0x20 && buf[7] == 0x20) + { + bc->params.type = FZ_IMAGE_JPX; + fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace); + } + else if (buf[0] == 0xff && buf[1] == 0xd8) { bc->params.type = FZ_IMAGE_JPEG; bc->params.u.jpeg.color_transform = -1; diff --git a/source/fitz/load-jpx.c b/source/fitz/load-jpx.c index ab0fb822..c1ed831a 100644 --- a/source/fitz/load-jpx.c +++ b/source/fitz/load-jpx.c @@ -69,8 +69,8 @@ static OPJ_BOOL fz_opj_stream_seek(OPJ_OFF_T seek_pos, void * p_user_data) return OPJ_TRUE; } -fz_pixmap * -fz_load_jpx(fz_context *ctx, unsigned char *data, size_t size, fz_colorspace *defcs, int indexed) +static fz_pixmap * +jpx_read_image(fz_context *ctx, unsigned char *data, size_t size, fz_colorspace *defcs, int indexed, int onlymeta) { fz_pixmap *img; opj_dparameters_t params; @@ -210,40 +210,61 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, size_t size, fz_colorspace *de fz_rethrow(ctx); } - p = img->samples; - stride = img->stride - w * (n + a); - for (y = 0; y < h; y++) + if (!onlymeta) { - for (x = 0; x < w; x++) + p = img->samples; + stride = img->stride - w * (n + a); + for (y = 0; y < h; y++) { - for (k = 0; k < n + a; k++) + for (x = 0; x < w; x++) { - v = jpx->comps[k].data[y * w + x]; - if (sgnd) - v = v + (1 << (depth - 1)); - if (depth > 8) - v = v >> (depth - 8); - else if (depth < 8) - v = v << (8 - depth); - *p++ = v; + for (k = 0; k < n + a; k++) + { + v = jpx->comps[k].data[y * w + x]; + if (sgnd) + v = v + (1 << (depth - 1)); + if (depth > 8) + v = v >> (depth - 8); + else if (depth < 8) + v = v << (8 - depth); + *p++ = v; + } } + p += stride; } - p += stride; - } - - opj_image_destroy(jpx); - if (a) - { - if (n == 4) + if (a) { - fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h, 1); - fz_convert_pixmap(ctx, tmp, img); - fz_drop_pixmap(ctx, img); - img = tmp; + if (n == 4) + { + fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h, 1); + fz_convert_pixmap(ctx, tmp, img); + fz_drop_pixmap(ctx, img); + img = tmp; + } + fz_premultiply_pixmap(ctx, img); } - fz_premultiply_pixmap(ctx, img); } + opj_image_destroy(jpx); + return img; } + +fz_pixmap * +fz_load_jpx(fz_context *ctx, unsigned char *data, size_t size, fz_colorspace *defcs, int indexed) +{ + return jpx_read_image(ctx, data, size, defcs, indexed, 0); +} + +void +fz_load_jpx_info(fz_context *ctx, unsigned char *data, size_t size, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep) +{ + fz_pixmap *img = jpx_read_image(ctx, data, size, NULL, 0, 1); + + *cspacep = fz_keep_colorspace(ctx, img->colorspace); + *wp = img->w; + *hp = img->h; + *xresp = 72; /* openjpeg does not read the JPEG 2000 resc box */ + *yresp = 72; /* openjpeg does not read the JPEG 2000 resc box */ +} -- cgit v1.2.3