mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
initial merge of wiredfool/Python-Imaging-Library-G4-Tiff-Support
This commit is contained in:
parent
e782fe721e
commit
5ba6564e26
|
@ -50,6 +50,7 @@ from PIL import _binary
|
|||
import array, sys
|
||||
import collections
|
||||
import itertools
|
||||
import os
|
||||
|
||||
II = b"II" # little-endian (intel-style)
|
||||
MM = b"MM" # big-endian (motorola-style)
|
||||
|
@ -121,6 +122,8 @@ COMPRESSION_INFO = {
|
|||
32773: "packbits"
|
||||
}
|
||||
|
||||
COMPRESSION_INFO_REV = dict([(v,k) for (k,v) in COMPRESSION_INFO.items()])
|
||||
|
||||
OPEN_INFO = {
|
||||
# (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
|
||||
# ExtraSamples) => mode, rawmode
|
||||
|
@ -532,6 +535,11 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.__frame = -1
|
||||
self.__fp = self.fp
|
||||
|
||||
if Image.DEBUG:
|
||||
print "*** TiffImageFile._open ***"
|
||||
print "- __first:", self.__first
|
||||
print "- ifh: ", ifh
|
||||
|
||||
# and load the first frame
|
||||
self._seek(0)
|
||||
|
||||
|
@ -567,7 +575,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
|
||||
return self.__frame
|
||||
|
||||
def _decoder(self, rawmode, layer):
|
||||
def _decoder(self, rawmode, layer, tile=None):
|
||||
"Setup decoder contexts"
|
||||
|
||||
args = None
|
||||
|
@ -594,6 +602,63 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
|
||||
return args
|
||||
|
||||
def _load_libtiff(self):
|
||||
""" Overload method triggered when we detect a g3/g4 tiff
|
||||
Calls out to lib tiff """
|
||||
|
||||
pixel = Image.Image.load(self)
|
||||
|
||||
if self.tile is None:
|
||||
raise IOError("cannot load this image")
|
||||
if not self.tile:
|
||||
return pixel
|
||||
|
||||
self.load_prepare()
|
||||
|
||||
if not len(self.tile) == 1:
|
||||
raise IOError("Not exactly one tile")
|
||||
|
||||
d, e, o, a = self.tile[0]
|
||||
d = Image._getdecoder(self.mode, d, a, self.decoderconfig)
|
||||
try:
|
||||
d.setimage(self.im, e)
|
||||
except ValueError:
|
||||
raise IOError("Couldn't set the image")
|
||||
|
||||
if hasattr(self.fp, "fileno"):
|
||||
# we've got a actual file on disk, pass in the fp.
|
||||
if Image.DEBUG:
|
||||
print "have fileno, calling fileno version of the decoder."
|
||||
self.fp.seek(0)
|
||||
n,e = d.decode("fpfp") # 4 bytes, otherwise the trace might error out
|
||||
elif hasattr(self.fp, "getvalue"):
|
||||
# We've got a stringio like thing passed in. Yay for all in memory.
|
||||
# The decoder needs the entire file in one shot, so there's not
|
||||
# a lot we can do here other than give it the entire file.
|
||||
# unless we could do something like get the address of the underlying
|
||||
# string for stringio.
|
||||
if Image.DEBUG:
|
||||
print "have getvalue. just sending in a string from getvalue"
|
||||
n,e = d.decode(self.fp.getvalue())
|
||||
else:
|
||||
# we have something else.
|
||||
if Image.DEBUG:
|
||||
print "don't have fileno or getvalue. just reading"
|
||||
# UNDONE -- so much for that buffer size thing.
|
||||
n, e = d.decode(self.fp.read())
|
||||
|
||||
|
||||
self.tile = []
|
||||
self.readonly = 0
|
||||
self.fp = None # might be shared
|
||||
|
||||
if e < 0:
|
||||
raise_ioerror(e)
|
||||
|
||||
self.load_end()
|
||||
|
||||
return Image.Image.load(self)
|
||||
|
||||
def _setup(self):
|
||||
"Setup this image object based on current tags"
|
||||
|
||||
|
@ -669,16 +734,49 @@ class TiffImageFile(ImageFile.ImageFile):
|
|||
self.tile = []
|
||||
if STRIPOFFSETS in self.tag:
|
||||
# striped image
|
||||
offsets = self.tag[STRIPOFFSETS]
|
||||
h = getscalar(ROWSPERSTRIP, ysize)
|
||||
w = self.size[0]
|
||||
if self._compression in ["tiff_ccitt", "group3",
|
||||
"group4", "tiff_raw_16"]:
|
||||
if Image.DEBUG:
|
||||
print "Activating g4 compression for whole file"
|
||||
|
||||
# Decoder expects entire file as one tile.
|
||||
# There's a buffer size limit in load (64k)
|
||||
# so large g4 images will fail if we use that
|
||||
# function.
|
||||
#
|
||||
# Setup the one tile for the whole image, then
|
||||
# replace the existing load function with our
|
||||
# _load_libtiff function.
|
||||
|
||||
self.load = self._load_libtiff
|
||||
|
||||
# To be nice on memory footprint, if there's a
|
||||
# file descriptor, use that instead of reading
|
||||
# into a string in python.
|
||||
|
||||
# libtiff closes the file descriptor, so pass in a dup.
|
||||
fp = hasattr(self.fp, "fileno") and os.dup(self.fp.fileno())
|
||||
|
||||
# Offset in the tile tuple is 0, we go from 0,0 to
|
||||
# w,h, and we only do this once -- eds
|
||||
a = (rawmode, self._compression, fp )
|
||||
self.tile.append(
|
||||
(self._compression,
|
||||
(0, 0, w, ysize),
|
||||
0, a))
|
||||
a = None
|
||||
for o in self.tag[STRIPOFFSETS]:
|
||||
if not a:
|
||||
a = self._decoder(rawmode, l)
|
||||
|
||||
else:
|
||||
for i in range(len(offsets)):
|
||||
a = self._decoder(rawmode, l, i)
|
||||
self.tile.append(
|
||||
(self._compression,
|
||||
(0, min(y, ysize), w, min(y+h, ysize)),
|
||||
o, a))
|
||||
offsets[i], a))
|
||||
print "tiles: %s" % self.tile
|
||||
y = y + h
|
||||
if y >= self.size[1]:
|
||||
x = y = 0
|
||||
|
@ -764,8 +862,12 @@ def _save(im, fp, filename):
|
|||
|
||||
ifd = ImageFileDirectory(prefix)
|
||||
|
||||
compression = im.info.get('compression','raw')
|
||||
libtiff = compression in ["tiff_ccitt", "group3",
|
||||
"group4", "tiff_raw_16"]
|
||||
|
||||
# -- multi-page -- skip TIFF header on subsequent pages
|
||||
if fp.tell() == 0:
|
||||
if not libtiff and fp.tell() == 0:
|
||||
# tiff header (write via IFD to get everything right)
|
||||
# PIL always starts the first IFD at offset 8
|
||||
fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
|
||||
|
@ -842,8 +944,60 @@ def _save(im, fp, filename):
|
|||
ifd[ROWSPERSTRIP] = im.size[1]
|
||||
ifd[STRIPBYTECOUNTS] = stride * im.size[1]
|
||||
ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
|
||||
ifd[COMPRESSION] = 1 # no compression
|
||||
ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression,1) # no compression by default
|
||||
|
||||
if libtiff:
|
||||
if Image.DEBUG:
|
||||
print "Saving using libtiff encoder"
|
||||
print ifd.items()
|
||||
_fp = 0
|
||||
if hasattr(fp, "fileno"):
|
||||
fp.seek(0)
|
||||
_fp = os.dup(fp.fileno())
|
||||
|
||||
blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes.
|
||||
atts = dict([(k,v) for (k,(v,)) in ifd.items() if k not in blocklist])
|
||||
try:
|
||||
# pull in more bits from the original file, e.g x,y resolution
|
||||
# so that we can save(load('')) == original file.
|
||||
for k,v in im.ifd.items():
|
||||
if k not in atts and k not in blocklist:
|
||||
if type(v[0]) == tuple and len(v) > 1:
|
||||
# A tuple of more than one rational tuples
|
||||
# flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL
|
||||
atts[k] = [float(elt[0])/float(elt[1]) for elt in v]
|
||||
continue
|
||||
if type(v[0]) == tuple and len(v) == 1:
|
||||
# A tuple of one rational tuples
|
||||
# flatten to floats, following tiffcp.c->cpTag->TIFF_RATIONAL
|
||||
atts[k] = float(v[0][0])/float(v[0][1])
|
||||
continue
|
||||
if type(v) == tuple and len(v) == 1:
|
||||
# int or similar
|
||||
atts[k] = v[0]
|
||||
continue
|
||||
if type(v) == str:
|
||||
atts[k] = v
|
||||
continue
|
||||
|
||||
except:
|
||||
# if we don't have an ifd here, just punt.
|
||||
pass
|
||||
if Image.DEBUG:
|
||||
print atts
|
||||
a = (rawmode, compression, _fp, filename, atts)
|
||||
e = Image._getencoder(im.mode, compression, a, im.encoderconfig)
|
||||
e.setimage(im.im, (0,0)+im.size)
|
||||
while 1:
|
||||
l, s, d = e.encode(16*1024) # undone, change to self.decodermaxblock
|
||||
if not _fp:
|
||||
fp.write(d)
|
||||
if s:
|
||||
break
|
||||
if s < 0:
|
||||
raise IOError("encoder error %d when writing image file" % s)
|
||||
|
||||
else:
|
||||
offset = ifd.save(fp)
|
||||
|
||||
ImageFile._save(im, fp, [
|
||||
|
|
13
_imaging.c
13
_imaging.c
|
@ -3205,6 +3205,7 @@ extern PyObject* PyImaging_GifDecoderNew(PyObject* self, PyObject* args);
|
|||
extern PyObject* PyImaging_HexDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_JpegDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_MspDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_PackbitsDecoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_PcdDecoderNew(PyObject* self, PyObject* args);
|
||||
|
@ -3223,6 +3224,7 @@ extern PyObject* PyImaging_PcxEncoderNew(PyObject* self, PyObject* args);
|
|||
extern PyObject* PyImaging_RawEncoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_XbmEncoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_ZipEncoderNew(PyObject* self, PyObject* args);
|
||||
extern PyObject* PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args);
|
||||
|
||||
/* Display support etc (in display.c) */
|
||||
#ifdef WIN32
|
||||
|
@ -3272,6 +3274,17 @@ static PyMethodDef functions[] = {
|
|||
{"jpeg_encoder", (PyCFunction)PyImaging_JpegEncoderNew, 1},
|
||||
#endif
|
||||
{"tiff_lzw_decoder", (PyCFunction)PyImaging_TiffLzwDecoderNew, 1},
|
||||
#ifdef HAVE_LIBTIFF
|
||||
{"tiff_ccitt_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||
{"group3_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||
{"group4_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||
{"tiff_raw_16_decoder", (PyCFunction)PyImaging_LibTiffDecoderNew, 1},
|
||||
|
||||
{"tiff_ccitt_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||
{"group3_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||
{"group4_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||
{"tiff_raw_16_encoder", (PyCFunction)PyImaging_LibTiffEncoderNew, 1},
|
||||
#endif
|
||||
{"msp_decoder", (PyCFunction)PyImaging_MspDecoderNew, 1},
|
||||
{"packbits_decoder", (PyCFunction)PyImaging_PackbitsDecoderNew, 1},
|
||||
{"pcd_decoder", (PyCFunction)PyImaging_PcdDecoderNew, 1},
|
||||
|
|
69
decode.c
69
decode.c
|
@ -388,6 +388,75 @@ PyImaging_TiffLzwDecoderNew(PyObject* self, PyObject* args)
|
|||
return (PyObject*) decoder;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LibTiff */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef HAVE_LIBTIFF
|
||||
|
||||
#include "Tiff.h"
|
||||
|
||||
#include <string.h>
|
||||
#ifdef __WIN32__
|
||||
#define strcasecmp(s1, s2) stricmp(s1, s2)
|
||||
#endif
|
||||
|
||||
PyObject*
|
||||
PyImaging_LibTiffDecoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingDecoderObject* decoder;
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char* compname;
|
||||
int compression;
|
||||
int fp;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "sssi", &mode, &rawmode, &compname, &fp))
|
||||
return NULL;
|
||||
|
||||
TRACE(("new tiff decoder %s\n", compname));
|
||||
|
||||
/* UNDONE -- we can probably do almost any arbitrary compression here,
|
||||
* since we're effective passing in the whole file in one shot and
|
||||
* getting back the data row by row. V2 maybe
|
||||
*/
|
||||
|
||||
if (strcasecmp(compname, "tiff_ccitt") == 0) {
|
||||
compression = COMPRESSION_CCITTRLE;
|
||||
|
||||
} else if (strcasecmp(compname, "group3") == 0) {
|
||||
compression = COMPRESSION_CCITTFAX3;
|
||||
|
||||
} else if (strcasecmp(compname, "group4") == 0) {
|
||||
compression = COMPRESSION_CCITTFAX4;
|
||||
|
||||
} else if (strcasecmp(compname, "tiff_raw_16") == 0) {
|
||||
compression = COMPRESSION_CCITTRLEW;
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "unknown compession");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder = PyImaging_DecoderNew(sizeof(TIFFSTATE));
|
||||
if (decoder == NULL)
|
||||
return NULL;
|
||||
|
||||
if (get_unpacker(decoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
|
||||
if (! ImagingLibTiffInit(&decoder->state, compression, fp)) {
|
||||
Py_DECREF(decoder);
|
||||
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder->decode = ImagingLibTiffDecode;
|
||||
|
||||
return (PyObject*) decoder;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* MSP */
|
||||
|
|
130
encode.c
130
encode.c
|
@ -644,3 +644,133 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* LibTiff */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#ifdef HAVE_LIBTIFF
|
||||
|
||||
#include "Tiff.h"
|
||||
|
||||
#include <string.h>
|
||||
#ifdef __WIN32__
|
||||
#define strcasecmp(s1, s2) stricmp(s1, s2)
|
||||
#endif
|
||||
|
||||
PyObject*
|
||||
PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||
{
|
||||
ImagingEncoderObject* encoder;
|
||||
|
||||
char* mode;
|
||||
char* rawmode;
|
||||
char* compname;
|
||||
char* filename;
|
||||
int compression;
|
||||
int fp;
|
||||
|
||||
PyObject *dir;
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
int status;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "sssisO", &mode, &rawmode, &compname, &fp, &filename, &dir)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyDict_Check(dir)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid Dictionary");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRACE(("new tiff encoder %s fp: %d, filename: %s \n", compname, fp, filename));
|
||||
|
||||
/* UNDONE -- we can probably do almost any arbitrary compression here,
|
||||
* so long as we're doing row/stripe based actions and not tiles.
|
||||
*/
|
||||
|
||||
if (strcasecmp(compname, "tiff_ccitt") == 0) {
|
||||
compression = COMPRESSION_CCITTRLE;
|
||||
|
||||
} else if (strcasecmp(compname, "group3") == 0) {
|
||||
compression = COMPRESSION_CCITTFAX3;
|
||||
|
||||
} else if (strcasecmp(compname, "group4") == 0) {
|
||||
compression = COMPRESSION_CCITTFAX4;
|
||||
|
||||
} else if (strcasecmp(compname, "tiff_raw_16") == 0) {
|
||||
compression = COMPRESSION_CCITTRLEW;
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "unknown compession");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoder = PyImaging_EncoderNew(sizeof(TIFFSTATE));
|
||||
if (encoder == NULL)
|
||||
return NULL;
|
||||
|
||||
if (get_packer(encoder, mode, rawmode) < 0)
|
||||
return NULL;
|
||||
|
||||
if (! ImagingLibTiffEncodeInit(&encoder->state, filename, fp)) {
|
||||
Py_DECREF(encoder);
|
||||
PyErr_SetString(PyExc_RuntimeError, "tiff codec initialization failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (PyDict_Next(dir, &pos, &key, &value)) {
|
||||
status = 0;
|
||||
if (PyInt_Check(value)) {
|
||||
TRACE(("Setting from Int: %d %ld \n", (int)PyInt_AsLong(key),PyInt_AsLong(value)));
|
||||
status = ImagingLibTiffSetField(&encoder->state,
|
||||
(ttag_t) PyInt_AsLong(key),
|
||||
PyInt_AsLong(value));
|
||||
} else if(PyString_Check(value)) {
|
||||
TRACE(("Setting from String: %d, %s \n", (int)PyInt_AsLong(key),PyString_AsString(value)));
|
||||
status = ImagingLibTiffSetField(&encoder->state,
|
||||
(ttag_t) PyInt_AsLong(key),
|
||||
PyString_AsString(value));
|
||||
|
||||
} else if(PyList_Check(value)) {
|
||||
int len,i;
|
||||
float *floatav;
|
||||
TRACE(("Setting from List: %d \n", (int)PyInt_AsLong(key)));
|
||||
len = (int)PyList_Size(value);
|
||||
TRACE((" %d elements, setting as floats \n", len));
|
||||
floatav = malloc(sizeof(float)*len);
|
||||
if (floatav) {
|
||||
for (i=0;i<len;i++) {
|
||||
floatav[i] = (float)PyFloat_AsDouble(PyList_GetItem(value,i));
|
||||
}
|
||||
status = ImagingLibTiffSetField(&encoder->state,
|
||||
(ttag_t) PyInt_AsLong(key),
|
||||
floatav);
|
||||
free(floatav);
|
||||
}
|
||||
} else if (PyFloat_Check(value)) {
|
||||
TRACE(("Setting from String: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
|
||||
status = ImagingLibTiffSetField(&encoder->state,
|
||||
(ttag_t) PyInt_AsLong(key),
|
||||
(float)PyFloat_AsDouble(value));
|
||||
} else {
|
||||
TRACE(("Unhandled type for key %d : %s ",
|
||||
(int)PyInt_AsLong(key),
|
||||
PyString_AsString(PyObject_Str(value))));
|
||||
}
|
||||
if (!status) {
|
||||
TRACE(("Error setting Field\n"));
|
||||
Py_DECREF(encoder);
|
||||
PyErr_SetString(PyExc_RuntimeError, "Error setting from dictionary");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
encoder->encode = ImagingLibTiffEncode;
|
||||
|
||||
return (PyObject*) encoder;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -420,6 +420,12 @@ extern int ImagingJpegEncode(Imaging im, ImagingCodecState state,
|
|||
#endif
|
||||
extern int ImagingLzwDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
#ifdef HAVE_LIBTIFF
|
||||
extern int ImagingLibTiffDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
extern int ImagingLibTiffEncode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
#endif
|
||||
#ifdef HAVE_LIBMPEG
|
||||
extern int ImagingMpegDecode(Imaging im, ImagingCodecState state,
|
||||
UINT8* buffer, int bytes);
|
||||
|
|
|
@ -186,6 +186,7 @@ if __name__ == "__main__":
|
|||
check_module("TKINTER", "_imagingtk")
|
||||
check_codec("JPEG", "jpeg")
|
||||
check_codec("ZLIB (PNG/ZIP)", "zip")
|
||||
check_codec("G4 TIFF", "group4")
|
||||
check_module("FREETYPE2", "_imagingft")
|
||||
check_module("LITTLECMS", "_imagingcms")
|
||||
print("-"*68)
|
||||
|
@ -201,3 +202,4 @@ if __name__ == "__main__":
|
|||
print("--- %s tests passed." % status[1])
|
||||
|
||||
sys.exit(exit_status)
|
||||
|
||||
|
|
13
setup.py
13
setup.py
|
@ -26,7 +26,7 @@ _LIB_IMAGING = (
|
|||
"QuantHeap", "PcdDecode", "PcxDecode", "PcxEncode", "Point",
|
||||
"RankFilter", "RawDecode", "RawEncode", "Storage", "SunRleDecode",
|
||||
"TgaRleDecode", "Unpack", "UnpackYCC", "UnsharpMask", "XbmDecode",
|
||||
"XbmEncode", "ZipDecode", "ZipEncode")
|
||||
"XbmEncode", "ZipDecode", "ZipEncode", "TiffDecode")
|
||||
|
||||
|
||||
def _add_directory(path, dir, where=None):
|
||||
|
@ -156,6 +156,7 @@ class pil_build_ext(build_ext):
|
|||
#
|
||||
# locate tkinter libraries
|
||||
|
||||
|
||||
if _tkinter:
|
||||
TCL_VERSION = _tkinter.TCL_VERSION[:3]
|
||||
|
||||
|
@ -184,6 +185,7 @@ class pil_build_ext(build_ext):
|
|||
else:
|
||||
TCL_ROOT = None
|
||||
|
||||
|
||||
#
|
||||
# add standard directories
|
||||
|
||||
|
@ -229,6 +231,10 @@ class pil_build_ext(build_ext):
|
|||
|
||||
if _find_library_file(self, "tiff"):
|
||||
feature.tiff = "tiff"
|
||||
if sys.platform == "win32" and find_library_file(self, "libtiff"):
|
||||
feature.tiff = "libtiff"
|
||||
if sys.platform == "darwin" and find_library_file(self, "libtiff"):
|
||||
feature.tiff = "libtiff"
|
||||
|
||||
if _find_library_file(self, "freetype"):
|
||||
# look for freetype2 include files
|
||||
|
@ -284,6 +290,9 @@ class pil_build_ext(build_ext):
|
|||
if feature.zlib:
|
||||
libs.append(feature.zlib)
|
||||
defs.append(("HAVE_LIBZ", None))
|
||||
if feature.tiff:
|
||||
libs.append(feature.tiff)
|
||||
defs.append(("HAVE_LIBTIFF", None))
|
||||
if sys.platform == "win32":
|
||||
libs.extend(["kernel32", "user32", "gdi32"])
|
||||
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
|
||||
|
@ -373,7 +382,7 @@ class pil_build_ext(build_ext):
|
|||
(feature.tcl and feature.tk, "TKINTER"),
|
||||
(feature.jpeg, "JPEG"),
|
||||
(feature.zlib, "ZLIB (PNG/ZIP)"),
|
||||
# (feature.tiff, "experimental TIFF G3/G4 read"),
|
||||
(feature.tiff, "experimental TIFF G3/G4 read"),
|
||||
(feature.freetype, "FREETYPE2"),
|
||||
(feature.lcms, "LITTLECMS"),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user