diff --git a/src/decode.c b/src/decode.c index 51d0aced2..00ecf555d 100644 --- a/src/decode.c +++ b/src/decode.c @@ -800,74 +800,6 @@ PyImaging_ZipDecoderNew(PyObject *self, PyObject *args) { } #endif -/* -------------------------------------------------------------------- */ -/* JPEG */ -/* -------------------------------------------------------------------- */ - -#ifdef HAVE_LIBJPEG - -/* We better define this decoder last in this file, so the following - undef's won't mess things up for the Imaging library proper. */ - -#undef HAVE_PROTOTYPES -#undef HAVE_STDDEF_H -#undef HAVE_STDLIB_H -#undef UINT8 -#undef UINT16 -#undef UINT32 -#undef INT8 -#undef INT16 -#undef INT32 - -#include "libImaging/Jpeg.h" - -PyObject * -PyImaging_JpegDecoderNew(PyObject *self, PyObject *args) { - ImagingDecoderObject *decoder; - - char *mode; - char *rawmode; /* what we want from the decoder */ - char *jpegmode; /* what's in the file */ - int scale = 1; - int draft = 0; - - if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, &scale, &draft)) { - return NULL; - } - - if (!jpegmode) { - jpegmode = ""; - } - - decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE)); - if (decoder == NULL) { - return NULL; - } - - // libjpeg-turbo supports different output formats. - // We are choosing Pillow's native format (3 color bytes + 1 padding) - // to avoid extra conversion in Unpack.c. - if (ImagingJpegUseJCSExtensions() && strcmp(rawmode, "RGB") == 0) { - rawmode = "RGBX"; - } - - if (get_unpacker(decoder, mode, rawmode) < 0) { - return NULL; - } - - decoder->decode = ImagingJpegDecode; - decoder->cleanup = ImagingJpegDecodeCleanup; - - strncpy(((JPEGSTATE *)decoder->state.context)->rawmode, rawmode, 8); - strncpy(((JPEGSTATE *)decoder->state.context)->jpegmode, jpegmode, 8); - - ((JPEGSTATE *)decoder->state.context)->scale = scale; - ((JPEGSTATE *)decoder->state.context)->draft = draft; - - return (PyObject *)decoder; -} -#endif - /* -------------------------------------------------------------------- */ /* JPEG 2000 */ /* -------------------------------------------------------------------- */ @@ -925,3 +857,61 @@ PyImaging_Jpeg2KDecoderNew(PyObject *self, PyObject *args) { return (PyObject *)decoder; } #endif /* HAVE_OPENJPEG */ + +/* -------------------------------------------------------------------- */ +/* JPEG */ +/* -------------------------------------------------------------------- */ + +#ifdef HAVE_LIBJPEG + +/* We better define this decoder last in this file, so the undef's + in Jpeg.h won't mess things up for the Imaging library proper. */ + +#include "libImaging/Jpeg.h" + +PyObject * +PyImaging_JpegDecoderNew(PyObject *self, PyObject *args) { + ImagingDecoderObject *decoder; + + char *mode; + char *rawmode; /* what we want from the decoder */ + char *jpegmode; /* what's in the file */ + int scale = 1; + int draft = 0; + + if (!PyArg_ParseTuple(args, "ssz|ii", &mode, &rawmode, &jpegmode, &scale, &draft)) { + return NULL; + } + + if (!jpegmode) { + jpegmode = ""; + } + + decoder = PyImaging_DecoderNew(sizeof(JPEGSTATE)); + if (decoder == NULL) { + return NULL; + } + + // libjpeg-turbo supports different output formats. + // We are choosing Pillow's native format (3 color bytes + 1 padding) + // to avoid extra conversion in Unpack.c. + if (ImagingJpegUseJCSExtensions() && strcmp(rawmode, "RGB") == 0) { + rawmode = "RGBX"; + } + + if (get_unpacker(decoder, mode, rawmode) < 0) { + return NULL; + } + + decoder->decode = ImagingJpegDecode; + decoder->cleanup = ImagingJpegDecodeCleanup; + + strncpy(((JPEGSTATE *)decoder->state.context)->rawmode, rawmode, 8); + strncpy(((JPEGSTATE *)decoder->state.context)->jpegmode, jpegmode, 8); + + ((JPEGSTATE *)decoder->state.context)->scale = scale; + ((JPEGSTATE *)decoder->state.context)->draft = draft; + + return (PyObject *)decoder; +} +#endif diff --git a/src/encode.c b/src/encode.c index 1a4cd489d..fa6c3a51c 100644 --- a/src/encode.c +++ b/src/encode.c @@ -982,24 +982,213 @@ PyImaging_LibTiffEncoderNew(PyObject *self, PyObject *args) { #endif +/* -------------------------------------------------------------------- */ +/* JPEG 2000 */ +/* -------------------------------------------------------------------- */ + +#ifdef HAVE_OPENJPEG + +#include "libImaging/Jpeg2K.h" + +static void +j2k_decode_coord_tuple(PyObject *tuple, int *x, int *y) { + *x = *y = 0; + + if (tuple && PyTuple_Check(tuple) && PyTuple_GET_SIZE(tuple) == 2) { + *x = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0)); + *y = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1)); + + if (*x < 0) { + *x = 0; + } + if (*y < 0) { + *y = 0; + } + } +} + +PyObject * +PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) { + ImagingEncoderObject *encoder; + JPEG2KENCODESTATE *context; + + char *mode; + char *format; + OPJ_CODEC_FORMAT codec_format; + PyObject *offset = NULL, *tile_offset = NULL, *tile_size = NULL; + char *quality_mode = "rates"; + PyObject *quality_layers = NULL; + Py_ssize_t num_resolutions = 0; + PyObject *cblk_size = NULL, *precinct_size = NULL; + PyObject *irreversible = NULL; + char *progression = "LRCP"; + OPJ_PROG_ORDER prog_order; + char *cinema_mode = "no"; + OPJ_CINEMA_MODE cine_mode; + char mct = 0; + int sgnd = 0; + Py_ssize_t fd = -1; + char *comment; + Py_ssize_t comment_size; + int plt = 0; + + if (!PyArg_ParseTuple( + args, + "ss|OOOsOnOOOssbbnz#p", + &mode, + &format, + &offset, + &tile_offset, + &tile_size, + &quality_mode, + &quality_layers, + &num_resolutions, + &cblk_size, + &precinct_size, + &irreversible, + &progression, + &cinema_mode, + &mct, + &sgnd, + &fd, + &comment, + &comment_size, + &plt + )) { + return NULL; + } + + if (strcmp(format, "j2k") == 0) { + codec_format = OPJ_CODEC_J2K; + } else if (strcmp(format, "jpt") == 0) { + codec_format = OPJ_CODEC_JPT; + } else if (strcmp(format, "jp2") == 0) { + codec_format = OPJ_CODEC_JP2; + } else { + return NULL; + } + + if (strcmp(progression, "LRCP") == 0) { + prog_order = OPJ_LRCP; + } else if (strcmp(progression, "RLCP") == 0) { + prog_order = OPJ_RLCP; + } else if (strcmp(progression, "RPCL") == 0) { + prog_order = OPJ_RPCL; + } else if (strcmp(progression, "PCRL") == 0) { + prog_order = OPJ_PCRL; + } else if (strcmp(progression, "CPRL") == 0) { + prog_order = OPJ_CPRL; + } else { + return NULL; + } + + if (strcmp(cinema_mode, "no") == 0) { + cine_mode = OPJ_OFF; + } else if (strcmp(cinema_mode, "cinema2k-24") == 0) { + cine_mode = OPJ_CINEMA2K_24; + } else if (strcmp(cinema_mode, "cinema2k-48") == 0) { + cine_mode = OPJ_CINEMA2K_48; + } else if (strcmp(cinema_mode, "cinema4k-24") == 0) { + cine_mode = OPJ_CINEMA4K_24; + } else { + return NULL; + } + + encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE)); + if (!encoder) { + return NULL; + } + + encoder->encode = ImagingJpeg2KEncode; + encoder->cleanup = ImagingJpeg2KEncodeCleanup; + encoder->pushes_fd = 1; + + context = (JPEG2KENCODESTATE *)encoder->state.context; + + context->fd = fd; + context->format = codec_format; + context->offset_x = context->offset_y = 0; + + j2k_decode_coord_tuple(offset, &context->offset_x, &context->offset_y); + j2k_decode_coord_tuple( + tile_offset, &context->tile_offset_x, &context->tile_offset_y + ); + j2k_decode_coord_tuple(tile_size, &context->tile_size_x, &context->tile_size_y); + + /* Error on illegal tile offsets */ + if (context->tile_size_x && context->tile_size_y) { + if (context->tile_offset_x <= context->offset_x - context->tile_size_x || + context->tile_offset_y <= context->offset_y - context->tile_size_y) { + PyErr_SetString( + PyExc_ValueError, + "JPEG 2000 tile offset too small; top left tile must " + "intersect image area" + ); + Py_DECREF(encoder); + return NULL; + } + + if (context->tile_offset_x > context->offset_x || + context->tile_offset_y > context->offset_y) { + PyErr_SetString( + PyExc_ValueError, "JPEG 2000 tile offset too large to cover image area" + ); + Py_DECREF(encoder); + return NULL; + } + } + + if (comment && comment_size > 0) { + /* Size is stored as as an uint16, subtract 4 bytes for the header */ + if (comment_size >= 65532) { + PyErr_SetString(PyExc_ValueError, "JPEG 2000 comment is too long"); + Py_DECREF(encoder); + return NULL; + } + + char *p = malloc(comment_size + 1); + if (!p) { + Py_DECREF(encoder); + return ImagingError_MemoryError(); + } + memcpy(p, comment, comment_size); + p[comment_size] = '\0'; + context->comment = p; + } + + if (quality_layers && PySequence_Check(quality_layers)) { + context->quality_is_in_db = strcmp(quality_mode, "dB") == 0; + context->quality_layers = quality_layers; + Py_INCREF(quality_layers); + } + + context->num_resolutions = num_resolutions; + + j2k_decode_coord_tuple(cblk_size, &context->cblk_width, &context->cblk_height); + j2k_decode_coord_tuple( + precinct_size, &context->precinct_width, &context->precinct_height + ); + + context->irreversible = PyObject_IsTrue(irreversible); + context->progression = prog_order; + context->cinema_mode = cine_mode; + context->mct = mct; + context->sgnd = sgnd; + context->plt = plt; + + return (PyObject *)encoder; +} + +#endif + /* -------------------------------------------------------------------- */ /* JPEG */ /* -------------------------------------------------------------------- */ #ifdef HAVE_LIBJPEG -/* We better define this encoder last in this file, so the following - undef's won't mess things up for the Imaging library proper. */ - -#undef HAVE_PROTOTYPES -#undef HAVE_STDDEF_H -#undef HAVE_STDLIB_H -#undef UINT8 -#undef UINT16 -#undef UINT32 -#undef INT8 -#undef INT16 -#undef INT32 +/* We better define this decoder last in this file, so the undef's + in Jpeg.h won't mess things up for the Imaging library proper. */ #include "libImaging/Jpeg.h" @@ -1212,202 +1401,3 @@ PyImaging_JpegEncoderNew(PyObject *self, PyObject *args) { } #endif - -/* -------------------------------------------------------------------- */ -/* JPEG 2000 */ -/* -------------------------------------------------------------------- */ - -#ifdef HAVE_OPENJPEG - -#include "libImaging/Jpeg2K.h" - -static void -j2k_decode_coord_tuple(PyObject *tuple, int *x, int *y) { - *x = *y = 0; - - if (tuple && PyTuple_Check(tuple) && PyTuple_GET_SIZE(tuple) == 2) { - *x = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 0)); - *y = (int)PyLong_AsLong(PyTuple_GET_ITEM(tuple, 1)); - - if (*x < 0) { - *x = 0; - } - if (*y < 0) { - *y = 0; - } - } -} - -PyObject * -PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args) { - ImagingEncoderObject *encoder; - JPEG2KENCODESTATE *context; - - char *mode; - char *format; - OPJ_CODEC_FORMAT codec_format; - PyObject *offset = NULL, *tile_offset = NULL, *tile_size = NULL; - char *quality_mode = "rates"; - PyObject *quality_layers = NULL; - Py_ssize_t num_resolutions = 0; - PyObject *cblk_size = NULL, *precinct_size = NULL; - PyObject *irreversible = NULL; - char *progression = "LRCP"; - OPJ_PROG_ORDER prog_order; - char *cinema_mode = "no"; - OPJ_CINEMA_MODE cine_mode; - char mct = 0; - int sgnd = 0; - Py_ssize_t fd = -1; - char *comment; - Py_ssize_t comment_size; - int plt = 0; - - if (!PyArg_ParseTuple( - args, - "ss|OOOsOnOOOssbbnz#p", - &mode, - &format, - &offset, - &tile_offset, - &tile_size, - &quality_mode, - &quality_layers, - &num_resolutions, - &cblk_size, - &precinct_size, - &irreversible, - &progression, - &cinema_mode, - &mct, - &sgnd, - &fd, - &comment, - &comment_size, - &plt - )) { - return NULL; - } - - if (strcmp(format, "j2k") == 0) { - codec_format = OPJ_CODEC_J2K; - } else if (strcmp(format, "jpt") == 0) { - codec_format = OPJ_CODEC_JPT; - } else if (strcmp(format, "jp2") == 0) { - codec_format = OPJ_CODEC_JP2; - } else { - return NULL; - } - - if (strcmp(progression, "LRCP") == 0) { - prog_order = OPJ_LRCP; - } else if (strcmp(progression, "RLCP") == 0) { - prog_order = OPJ_RLCP; - } else if (strcmp(progression, "RPCL") == 0) { - prog_order = OPJ_RPCL; - } else if (strcmp(progression, "PCRL") == 0) { - prog_order = OPJ_PCRL; - } else if (strcmp(progression, "CPRL") == 0) { - prog_order = OPJ_CPRL; - } else { - return NULL; - } - - if (strcmp(cinema_mode, "no") == 0) { - cine_mode = OPJ_OFF; - } else if (strcmp(cinema_mode, "cinema2k-24") == 0) { - cine_mode = OPJ_CINEMA2K_24; - } else if (strcmp(cinema_mode, "cinema2k-48") == 0) { - cine_mode = OPJ_CINEMA2K_48; - } else if (strcmp(cinema_mode, "cinema4k-24") == 0) { - cine_mode = OPJ_CINEMA4K_24; - } else { - return NULL; - } - - encoder = PyImaging_EncoderNew(sizeof(JPEG2KENCODESTATE)); - if (!encoder) { - return NULL; - } - - encoder->encode = ImagingJpeg2KEncode; - encoder->cleanup = ImagingJpeg2KEncodeCleanup; - encoder->pushes_fd = 1; - - context = (JPEG2KENCODESTATE *)encoder->state.context; - - context->fd = fd; - context->format = codec_format; - context->offset_x = context->offset_y = 0; - - j2k_decode_coord_tuple(offset, &context->offset_x, &context->offset_y); - j2k_decode_coord_tuple( - tile_offset, &context->tile_offset_x, &context->tile_offset_y - ); - j2k_decode_coord_tuple(tile_size, &context->tile_size_x, &context->tile_size_y); - - /* Error on illegal tile offsets */ - if (context->tile_size_x && context->tile_size_y) { - if (context->tile_offset_x <= context->offset_x - context->tile_size_x || - context->tile_offset_y <= context->offset_y - context->tile_size_y) { - PyErr_SetString( - PyExc_ValueError, - "JPEG 2000 tile offset too small; top left tile must " - "intersect image area" - ); - Py_DECREF(encoder); - return NULL; - } - - if (context->tile_offset_x > context->offset_x || - context->tile_offset_y > context->offset_y) { - PyErr_SetString( - PyExc_ValueError, "JPEG 2000 tile offset too large to cover image area" - ); - Py_DECREF(encoder); - return NULL; - } - } - - if (comment && comment_size > 0) { - /* Size is stored as as an uint16, subtract 4 bytes for the header */ - if (comment_size >= 65532) { - PyErr_SetString(PyExc_ValueError, "JPEG 2000 comment is too long"); - Py_DECREF(encoder); - return NULL; - } - - char *p = malloc(comment_size + 1); - if (!p) { - Py_DECREF(encoder); - return ImagingError_MemoryError(); - } - memcpy(p, comment, comment_size); - p[comment_size] = '\0'; - context->comment = p; - } - - if (quality_layers && PySequence_Check(quality_layers)) { - context->quality_is_in_db = strcmp(quality_mode, "dB") == 0; - context->quality_layers = quality_layers; - Py_INCREF(quality_layers); - } - - context->num_resolutions = num_resolutions; - - j2k_decode_coord_tuple(cblk_size, &context->cblk_width, &context->cblk_height); - j2k_decode_coord_tuple( - precinct_size, &context->precinct_width, &context->precinct_height - ); - - context->irreversible = PyObject_IsTrue(irreversible); - context->progression = prog_order; - context->cinema_mode = cine_mode; - context->mct = mct; - context->sgnd = sgnd; - context->plt = plt; - - return (PyObject *)encoder; -} - -#endif diff --git a/src/libImaging/Jpeg.h b/src/libImaging/Jpeg.h index 7cdba9022..d4604f84f 100644 --- a/src/libImaging/Jpeg.h +++ b/src/libImaging/Jpeg.h @@ -8,7 +8,16 @@ * Copyright (c) 1995-1996 by Fredrik Lundh */ -#include "jpeglib.h" +/* This undefs ruquired for libjpeg v8 and below */ + +#undef UINT8 +#undef UINT16 +#undef UINT32 +#undef INT8 +#undef INT16 +#undef INT32 + +#include #include diff --git a/src/libImaging/JpegDecode.c b/src/libImaging/JpegDecode.c index 2970f56d1..838a7483c 100644 --- a/src/libImaging/JpegDecode.c +++ b/src/libImaging/JpegDecode.c @@ -25,15 +25,6 @@ #ifdef HAVE_LIBJPEG -#undef HAVE_PROTOTYPES -#undef HAVE_STDLIB_H -#undef HAVE_STDDEF_H -#undef UINT8 -#undef UINT16 -#undef UINT32 -#undef INT16 -#undef INT32 - #include "Jpeg.h" #define STRINGIFY(x) #x diff --git a/src/libImaging/JpegEncode.c b/src/libImaging/JpegEncode.c index 4372d51d5..880a31117 100644 --- a/src/libImaging/JpegEncode.c +++ b/src/libImaging/JpegEncode.c @@ -23,15 +23,6 @@ #ifdef HAVE_LIBJPEG -#undef HAVE_PROTOTYPES -#undef HAVE_STDLIB_H -#undef HAVE_STDDEF_H -#undef UINT8 -#undef UINT16 -#undef UINT32 -#undef INT16 -#undef INT32 - #include "Jpeg.h" /* -------------------------------------------------------------------- */