diff --git a/python-pillow.spec b/python-pillow.spec index 9108517..3a747d7 100644 --- a/python-pillow.spec +++ b/python-pillow.spec @@ -6,7 +6,7 @@ %global name3 python3-pillow # bootstrap building docs (pillow is required by docutils, docutils are # required by sphinx; pillow build-requires sphinx) -%global with_docs 1 +%global with_docs 0 # RHEL-7 doesn't have python 3 %if 0%{?rhel} == 7 @@ -28,7 +28,7 @@ Name: python-pillow Version: 2.4.0 -Release: 8%{?snap}%{?dist} +Release: 9%{?snap}%{?dist} Summary: Python image processing library # License: see http://www.pythonware.com/products/pil/license.htm @@ -43,7 +43,8 @@ Source0: https://github.com/python-imaging/Pillow/tarball/%{commit}/pytho Patch0: python-imaging-Pillow_ghostscript.patch # Have the tempfile use a suffix with a dot Patch1: python-pillow_tmpsuffix.patch - +# openjpeg-2.1.0 compatibility +Patch2: python-pillow_openjpeg-2.1.0.patch BuildRequires: tk-devel BuildRequires: libjpeg-devel @@ -220,6 +221,7 @@ PIL image wrapper for Qt. %setup -q -n python-imaging-Pillow-%{shortcommit} %patch0 -p1 %patch1 -p1 +%patch2 -p1 # Running test fails, see #921706#c38 rm -f Tests/test_file_eps.py @@ -386,6 +388,9 @@ popd %endif %changelog +* Tue May 27 2014 Sandro Mani - 2.4.0-9 +- Rebuild against openjpeg-2.1.0 + * Fri May 23 2014 Dan HorĂ¡k - 2.4.0-8 - skip jpeg2k tests on big endian arches (#1100762) diff --git a/python-pillow_openjpeg-2.1.0.patch b/python-pillow_openjpeg-2.1.0.patch new file mode 100644 index 0000000..8e11a85 --- /dev/null +++ b/python-pillow_openjpeg-2.1.0.patch @@ -0,0 +1,213 @@ +diff -rupN python-imaging-Pillow-72de37c/decode.c python-imaging-Pillow-72de37c-new/decode.c +--- python-imaging-Pillow-72de37c/decode.c 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/decode.c 2014-05-27 14:12:58.913340062 +0200 +@@ -800,8 +800,9 @@ PyImaging_Jpeg2KDecoderNew(PyObject* sel + int reduce = 0; + int layers = 0; + int fd = -1; +- if (!PyArg_ParseTuple(args, "ss|iii", &mode, &format, +- &reduce, &layers, &fd)) ++ PY_LONG_LONG length = -1; ++ if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format, ++ &reduce, &layers, &fd, &length)) + return NULL; + + if (strcmp(format, "j2k") == 0) +@@ -824,6 +825,7 @@ PyImaging_Jpeg2KDecoderNew(PyObject* sel + context = (JPEG2KDECODESTATE *)decoder->state.context; + + context->fd = fd; ++ context->length = (off_t)length; + context->format = codec_format; + context->reduce = reduce; + context->layers = layers; +diff -rupN python-imaging-Pillow-72de37c/libImaging/Jpeg2KDecode.c python-imaging-Pillow-72de37c-new/libImaging/Jpeg2KDecode.c +--- python-imaging-Pillow-72de37c/libImaging/Jpeg2KDecode.c 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/libImaging/Jpeg2KDecode.c 2014-05-27 14:14:02.756806143 +0200 +@@ -517,7 +517,21 @@ j2k_decode_entry(Imaging im, ImagingCode + opj_stream_set_read_function(stream, j2k_read); + opj_stream_set_skip_function(stream, j2k_skip); + ++/* OpenJPEG 2.0 doesn't have OPJ_VERSION_MAJOR */ ++#ifndef OPJ_VERSION_MAJOR + opj_stream_set_user_data(stream, decoder); ++#else ++ opj_stream_set_user_data(stream, decoder, NULL); ++ ++ /* Hack: if we don't know the length, the largest file we can ++ possibly support is 4GB. We can't go larger than this, because ++ OpenJPEG truncates this value for the final box in the file, and ++ the box lengths in OpenJPEG are currently 32 bit. */ ++ if (context->length < 0) ++ opj_stream_set_user_data_length(stream, 0xffffffff); ++ else ++ opj_stream_set_user_data_length(stream, context->length); ++#endif + + /* Setup decompression context */ + context->error_msg = NULL; +diff -rupN python-imaging-Pillow-72de37c/libImaging/Jpeg2KEncode.c python-imaging-Pillow-72de37c-new/libImaging/Jpeg2KEncode.c +--- python-imaging-Pillow-72de37c/libImaging/Jpeg2KEncode.c 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/libImaging/Jpeg2KEncode.c 2014-05-27 14:12:58.915340109 +0200 +@@ -259,7 +259,11 @@ j2k_encode_entry(Imaging im, ImagingCode + opj_stream_set_skip_function(stream, j2k_skip); + opj_stream_set_seek_function(stream, j2k_seek); + ++#if OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 0 + opj_stream_set_user_data(stream, encoder); ++#else ++ opj_stream_set_user_data(stream, encoder, NULL); ++#endif + + /* Setup an opj_image */ + if (strcmp (im->mode, "L") == 0) { +diff -rupN python-imaging-Pillow-72de37c/libImaging/Jpeg2K.h python-imaging-Pillow-72de37c-new/libImaging/Jpeg2K.h +--- python-imaging-Pillow-72de37c/libImaging/Jpeg2K.h 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/libImaging/Jpeg2K.h 2014-05-27 14:12:58.913340062 +0200 +@@ -8,7 +8,7 @@ + * Copyright (c) 2014 by Alastair Houghton + */ + +-#include ++#include + + /* -------------------------------------------------------------------- */ + /* Decoder */ +@@ -20,6 +20,9 @@ typedef struct { + /* File descriptor, if available; otherwise, -1 */ + int fd; + ++ /* Length of data, if available; otherwise, -1 */ ++ off_t length; ++ + /* Specify the desired format */ + OPJ_CODEC_FORMAT format; + +diff -rupN python-imaging-Pillow-72de37c/PIL/Jpeg2KImagePlugin.py python-imaging-Pillow-72de37c-new/PIL/Jpeg2KImagePlugin.py +--- python-imaging-Pillow-72de37c/PIL/Jpeg2KImagePlugin.py 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/PIL/Jpeg2KImagePlugin.py 2014-05-27 14:12:58.912340040 +0200 +@@ -155,15 +155,25 @@ class Jpeg2KImageFile(ImageFile.ImageFil + self.layers = 0 + + fd = -1 ++ length = -1 + + if hasattr(self.fp, "fileno"): + try: + fd = self.fp.fileno() ++ length = os.fstat(fd).st_size + except: + fd = -1 +- ++ elif hasattr(self.fp, "seek"): ++ try: ++ pos = f.tell() ++ seek(0, 2) ++ length = f.tell() ++ seek(pos, 0) ++ except: ++ length = -1 ++ + self.tile = [('jpeg2k', (0, 0) + self.size, 0, +- (self.codec, self.reduce, self.layers, fd))] ++ (self.codec, self.reduce, self.layers, fd, length))] + + def load(self): + if self.reduce: +@@ -175,7 +185,7 @@ class Jpeg2KImageFile(ImageFile.ImageFil + if self.tile: + # Update the reduce and layers settings + t = self.tile[0] +- t3 = (t[3][0], self.reduce, self.layers, t[3][3]) ++ t3 = (t[3][0], self.reduce, self.layers, t[3][3], t[3][4]) + self.tile = [(t[0], (0, 0) + self.size, t[2], t3)] + + ImageFile.ImageFile.load(self) +diff -rupN python-imaging-Pillow-72de37c/setup.py python-imaging-Pillow-72de37c-new/setup.py +--- python-imaging-Pillow-72de37c/setup.py 2014-04-02 00:31:55.000000000 +0200 ++++ python-imaging-Pillow-72de37c-new/setup.py 2014-05-27 14:12:58.916340132 +0200 +@@ -331,14 +331,23 @@ class pil_build_ext(build_ext): + _add_directory(include_dirs, "/usr/include") + + # on Windows, look for the OpenJPEG libraries in the location that +- # the official installed puts them ++ # the official installer puts them + if sys.platform == "win32": +- _add_directory(library_dirs, +- os.path.join(os.environ.get("ProgramFiles", ""), +- "OpenJPEG 2.0", "lib")) +- _add_directory(include_dirs, +- os.path.join(os.environ.get("ProgramFiles", ""), +- "OpenJPEG 2.0", "include")) ++ program_files = os.environ.get('ProgramFiles', '') ++ best_version = (0, 0) ++ best_path = None ++ for name in os.listdir(program_files): ++ if name.startswith('OpenJPEG '): ++ version = tuple([int(x) for x in name[9:].strip().split('.')]) ++ if version > best_version: ++ best_version = version ++ best_path = os.path.join(program_files, name) ++ ++ if best_path: ++ _add_directory(library_dirs, ++ os.path.join(best_path, 'lib')) ++ _add_directory(include_dirs, ++ os.path.join(best_path, 'include')) + + # + # insert new dirs *before* default libs, to avoid conflicts +@@ -369,10 +378,28 @@ class pil_build_ext(build_ext): + feature.jpeg = "libjpeg" # alternative name + + if feature.want('jpeg2000'): +- if _find_include_file(self, "openjpeg-2.0/openjpeg.h"): +- if _find_library_file(self, "openjp2"): +- feature.jpeg2000 = "openjp2" +- ++ best_version = None ++ best_path = None ++ ++ # Find the best version ++ for directory in self.compiler.include_dirs: ++ for name in os.listdir(directory): ++ if name.startswith('openjpeg-') and \ ++ os.path.isfile(os.path.join(directory, name, ++ 'openjpeg.h')): ++ version = tuple([int(x) for x in name[9:].split('.')]) ++ if best_version is None or version > best_version: ++ best_version = version ++ best_path = os.path.join(directory, name) ++ ++ if best_version and _find_library_file(self, 'openjp2'): ++ # Add the directory to the include path so we can include ++ # rather than having to cope with the versioned ++ # include path ++ _add_directory(self.compiler.include_dirs, best_path, 0) ++ feature.jpeg2000 = 'openjp2' ++ feature.openjpeg_version = '.'.join([str(x) for x in best_version]) ++ + if feature.want('tiff'): + if _find_library_file(self, "tiff"): + feature.tiff = "tiff" +@@ -566,7 +593,7 @@ class pil_build_ext(build_ext): + options = [ + (feature.tcl and feature.tk, "TKINTER"), + (feature.jpeg, "JPEG"), +- (feature.jpeg2000, "OPENJPEG (JPEG2000)"), ++ (feature.jpeg2000, "OPENJPEG (JPEG2000)", feature.openjpeg_version), + (feature.zlib, "ZLIB (PNG/ZIP)"), + (feature.tiff, "LIBTIFF"), + (feature.freetype, "FREETYPE2"), +@@ -577,7 +604,10 @@ class pil_build_ext(build_ext): + all = 1 + for option in options: + if option[0]: +- print("--- %s support available" % option[1]) ++ version = '' ++ if len(option) >= 3: ++ version = ' (%s)' % option[2] ++ print("--- %s support available%s" % (option[1], version)) + else: + print("*** %s support not available" % option[1]) + if option[1] == "TKINTER" and _tkinter: