diff --git a/PIL/Jpeg2KImagePlugin.py b/PIL/Jpeg2KImagePlugin.py index f57f4a784..048fe2af1 100644 --- a/PIL/Jpeg2KImagePlugin.py +++ b/PIL/Jpeg2KImagePlugin.py @@ -76,6 +76,7 @@ def _parse_jp2_header(fp): size = None mode = None + bpc = None hio = io.BytesIO(header) while True: @@ -93,7 +94,9 @@ def _parse_jp2_header(fp): = struct.unpack('>IIHBBBB', content) size = (width, height) if unkc: - if nc == 1: + if nc == 1 and bpc == 15: + mode = 'I' + elif nc == 1: mode = 'L' elif nc == 2: mode = 'LA' @@ -113,7 +116,9 @@ def _parse_jp2_header(fp): mode = 'RGBA' break elif cs == 17: # grayscale - if nc == 1: + if nc == 1 and bpc == 15: + mode = 'I' + elif nc == 1: mode = 'L' elif nc == 2: mode = 'LA' @@ -122,7 +127,7 @@ def _parse_jp2_header(fp): if nc == 3: mode = 'RGB' elif nc == 4: - mode == 'RGBA' + mode = 'RGBA' break return (size, mode) diff --git a/libImaging/Jpeg2KDecode.c b/libImaging/Jpeg2KDecode.c index 6b6176c78..89ad10136 100644 --- a/libImaging/Jpeg2KDecode.c +++ b/libImaging/Jpeg2KDecode.c @@ -135,6 +135,56 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, } } + +static void +j2ku_gray_i(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, + const UINT8 *tiledata, Imaging im) +{ + unsigned x0 = tileinfo->x0 - in->x0, y0 = tileinfo->y0 - in->y0; + unsigned w = tileinfo->x1 - tileinfo->x0; + unsigned h = tileinfo->y1 - tileinfo->y0; + + int shift = 16 - in->comps[0].prec; + int offset = in->comps[0].sgnd ? 1 << (in->comps[0].prec - 1) : 0; + int csiz = (in->comps[0].prec + 7) >> 3; + + unsigned x, y; + + if (csiz == 3) + csiz = 4; + + if (shift < 0) + offset += 1 << (-shift - 1); + + switch (csiz) { + case 1: + for (y = 0; y < h; ++y) { + const UINT8 *data = &tiledata[y * w]; + UINT32 *row = (UINT32 *)im->image[y0 + y] + x0; + for (x = 0; x < w; ++x) + *row++ = j2ku_shift(offset + *data++, shift); + } + break; + case 2: + for (y = 0; y < h; ++y) { + const UINT16 *data = (const UINT16 *)&tiledata[2 * y * w]; + UINT32 *row = (UINT32 *)im->image[y0 + y] + x0; + for (x = 0; x < w; ++x) + *row++ = j2ku_shift(offset + *data++, shift); + } + break; + case 4: + for (y = 0; y < h; ++y) { + const UINT32 *data = (const UINT32 *)&tiledata[4 * y * w]; + UINT32 *row = (UINT32 *)im->image[y0 + y] + x0; + for (x = 0; x < w; ++x) + *row++ = j2ku_shift(offset + *data++, shift); + } + break; + } +} + + static void j2ku_gray_rgb(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, const UINT8 *tiledata, Imaging im) @@ -466,6 +516,7 @@ j2ku_sycca_rgba(opj_image_t *in, const JPEG2KTILEINFO *tileinfo, static const struct j2k_decode_unpacker j2k_unpackers[] = { { "L", OPJ_CLRSPC_GRAY, 1, j2ku_gray_l }, + { "I", OPJ_CLRSPC_GRAY, 1, j2ku_gray_i }, { "LA", OPJ_CLRSPC_GRAY, 2, j2ku_graya_la }, { "RGB", OPJ_CLRSPC_GRAY, 1, j2ku_gray_rgb }, { "RGB", OPJ_CLRSPC_GRAY, 2, j2ku_gray_rgb }, diff --git a/libImaging/Jpeg2KEncode.c b/libImaging/Jpeg2KEncode.c index 502a0de68..d84ff4f8f 100644 --- a/libImaging/Jpeg2KEncode.c +++ b/libImaging/Jpeg2KEncode.c @@ -97,25 +97,8 @@ j2k_pack_i16(Imaging im, UINT8 *buf, for (y = 0; y < h; ++y) { UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); for (x = 0; x < w; ++x) { - *ptr++ = data[1]; - *ptr++ = data[0]; - data += 2; - } - } -} - -static void -j2k_pack_i16b(Imaging im, UINT8 *buf, - unsigned x0, unsigned y0, unsigned w, unsigned h) -{ - UINT8 *ptr = buf; - unsigned x,y; - for (y = 0; y < h; ++y) { - UINT8 *data = (UINT8 *)(im->image[y + y0] + x0); - for (x = 0; x < w; ++x) { - *ptr++ = data[0]; - *ptr++ = data[1]; - data += 2; + *ptr++ = *data++; + *ptr++ = *data++; } } } @@ -310,7 +293,7 @@ j2k_encode_entry(Imaging im, ImagingCodecState state, } else if (strcmp (im->mode, "I;16B") == 0) { components = 1; color_space = OPJ_CLRSPC_GRAY; - pack = j2k_pack_i16b; + pack = j2k_pack_i16; prec = 16; bpp = 12; } else if (strcmp (im->mode, "LA") == 0) {