mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 10:16:17 +03:00
Added support for OpenJPEG 2.1.
This commit is contained in:
parent
8a8aec534b
commit
1011e51083
|
@ -155,15 +155,25 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
self.layers = 0
|
self.layers = 0
|
||||||
|
|
||||||
fd = -1
|
fd = -1
|
||||||
|
length = -1
|
||||||
|
|
||||||
if hasattr(self.fp, "fileno"):
|
if hasattr(self.fp, "fileno"):
|
||||||
try:
|
try:
|
||||||
fd = self.fp.fileno()
|
fd = self.fp.fileno()
|
||||||
|
length = os.fstat(fd).st_size
|
||||||
except:
|
except:
|
||||||
fd = -1
|
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.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):
|
def load(self):
|
||||||
if self.reduce:
|
if self.reduce:
|
||||||
|
@ -175,7 +185,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
|
||||||
if self.tile:
|
if self.tile:
|
||||||
# Update the reduce and layers settings
|
# Update the reduce and layers settings
|
||||||
t = self.tile[0]
|
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)]
|
self.tile = [(t[0], (0, 0) + self.size, t[2], t3)]
|
||||||
|
|
||||||
ImageFile.ImageFile.load(self)
|
ImageFile.ImageFile.load(self)
|
||||||
|
|
6
decode.c
6
decode.c
|
@ -797,8 +797,9 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
|
||||||
int reduce = 0;
|
int reduce = 0;
|
||||||
int layers = 0;
|
int layers = 0;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
if (!PyArg_ParseTuple(args, "ss|iii", &mode, &format,
|
PY_LONG_LONG length = -1;
|
||||||
&reduce, &layers, &fd))
|
if (!PyArg_ParseTuple(args, "ss|iiiL", &mode, &format,
|
||||||
|
&reduce, &layers, &fd, &length))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (strcmp(format, "j2k") == 0)
|
if (strcmp(format, "j2k") == 0)
|
||||||
|
@ -821,6 +822,7 @@ PyImaging_Jpeg2KDecoderNew(PyObject* self, PyObject* args)
|
||||||
context = (JPEG2KDECODESTATE *)decoder->state.context;
|
context = (JPEG2KDECODESTATE *)decoder->state.context;
|
||||||
|
|
||||||
context->fd = fd;
|
context->fd = fd;
|
||||||
|
context->length = (off_t)length;
|
||||||
context->format = codec_format;
|
context->format = codec_format;
|
||||||
context->reduce = reduce;
|
context->reduce = reduce;
|
||||||
context->layers = layers;
|
context->layers = layers;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Copyright (c) 2014 by Alastair Houghton
|
* Copyright (c) 2014 by Alastair Houghton
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <openjpeg-2.0/openjpeg.h>
|
#include <openjpeg.h>
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/* Decoder */
|
/* Decoder */
|
||||||
|
@ -20,6 +20,9 @@ typedef struct {
|
||||||
/* File descriptor, if available; otherwise, -1 */
|
/* File descriptor, if available; otherwise, -1 */
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
/* Length of data, if available; otherwise, -1 */
|
||||||
|
off_t length;
|
||||||
|
|
||||||
/* Specify the desired format */
|
/* Specify the desired format */
|
||||||
OPJ_CODEC_FORMAT format;
|
OPJ_CODEC_FORMAT format;
|
||||||
|
|
||||||
|
|
|
@ -517,7 +517,20 @@ j2k_decode_entry(Imaging im, ImagingCodecState state,
|
||||||
opj_stream_set_read_function(stream, j2k_read);
|
opj_stream_set_read_function(stream, j2k_read);
|
||||||
opj_stream_set_skip_function(stream, j2k_skip);
|
opj_stream_set_skip_function(stream, j2k_skip);
|
||||||
|
|
||||||
|
#if OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 0
|
||||||
opj_stream_set_user_data(stream, decoder);
|
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 */
|
/* Setup decompression context */
|
||||||
context->error_msg = NULL;
|
context->error_msg = NULL;
|
||||||
|
|
|
@ -259,7 +259,11 @@ j2k_encode_entry(Imaging im, ImagingCodecState state,
|
||||||
opj_stream_set_skip_function(stream, j2k_skip);
|
opj_stream_set_skip_function(stream, j2k_skip);
|
||||||
opj_stream_set_seek_function(stream, j2k_seek);
|
opj_stream_set_seek_function(stream, j2k_seek);
|
||||||
|
|
||||||
|
#if OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR == 0
|
||||||
opj_stream_set_user_data(stream, encoder);
|
opj_stream_set_user_data(stream, encoder);
|
||||||
|
#else
|
||||||
|
opj_stream_set_user_data(stream, encoder, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Setup an opj_image */
|
/* Setup an opj_image */
|
||||||
if (strcmp (im->mode, "L") == 0) {
|
if (strcmp (im->mode, "L") == 0) {
|
||||||
|
|
56
setup.py
56
setup.py
|
@ -337,14 +337,23 @@ class pil_build_ext(build_ext):
|
||||||
_add_directory(include_dirs, "/usr/include")
|
_add_directory(include_dirs, "/usr/include")
|
||||||
|
|
||||||
# on Windows, look for the OpenJPEG libraries in the location that
|
# 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":
|
if sys.platform == "win32":
|
||||||
_add_directory(library_dirs,
|
program_files = os.environ.get('ProgramFiles', '')
|
||||||
os.path.join(os.environ.get("ProgramFiles", ""),
|
best_version = (0, 0)
|
||||||
"OpenJPEG 2.0", "lib"))
|
best_path = None
|
||||||
_add_directory(include_dirs,
|
for name in os.listdir(program_files):
|
||||||
os.path.join(os.environ.get("ProgramFiles", ""),
|
if name.startswith('OpenJPEG '):
|
||||||
"OpenJPEG 2.0", "include"))
|
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
|
# insert new dirs *before* default libs, to avoid conflicts
|
||||||
|
@ -375,10 +384,28 @@ class pil_build_ext(build_ext):
|
||||||
feature.jpeg = "libjpeg" # alternative name
|
feature.jpeg = "libjpeg" # alternative name
|
||||||
|
|
||||||
if feature.want('jpeg2000'):
|
if feature.want('jpeg2000'):
|
||||||
if _find_include_file(self, "openjpeg-2.0/openjpeg.h"):
|
best_version = None
|
||||||
if _find_library_file(self, "openjp2"):
|
best_path = None
|
||||||
feature.jpeg2000 = "openjp2"
|
|
||||||
|
# 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
|
||||||
|
# <openjpeg.h> 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 feature.want('tiff'):
|
||||||
if _find_library_file(self, "tiff"):
|
if _find_library_file(self, "tiff"):
|
||||||
feature.tiff = "tiff"
|
feature.tiff = "tiff"
|
||||||
|
@ -572,7 +599,7 @@ class pil_build_ext(build_ext):
|
||||||
options = [
|
options = [
|
||||||
(feature.tcl and feature.tk, "TKINTER"),
|
(feature.tcl and feature.tk, "TKINTER"),
|
||||||
(feature.jpeg, "JPEG"),
|
(feature.jpeg, "JPEG"),
|
||||||
(feature.jpeg2000, "OPENJPEG (JPEG2000)"),
|
(feature.jpeg2000, "OPENJPEG (JPEG2000)", feature.openjpeg_version),
|
||||||
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
||||||
(feature.tiff, "LIBTIFF"),
|
(feature.tiff, "LIBTIFF"),
|
||||||
(feature.freetype, "FREETYPE2"),
|
(feature.freetype, "FREETYPE2"),
|
||||||
|
@ -583,7 +610,10 @@ class pil_build_ext(build_ext):
|
||||||
all = 1
|
all = 1
|
||||||
for option in options:
|
for option in options:
|
||||||
if option[0]:
|
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:
|
else:
|
||||||
print("*** %s support not available" % option[1])
|
print("*** %s support not available" % option[1])
|
||||||
if option[1] == "TKINTER" and _tkinter:
|
if option[1] == "TKINTER" and _tkinter:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user