mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14:27 +03:00
commit
a635a1dcb1
|
@ -248,7 +248,12 @@ def _save(im, fp, filename):
|
||||||
rawmode = "L"
|
rawmode = "L"
|
||||||
|
|
||||||
# header
|
# header
|
||||||
for s in getheader(imOut, im.encoderinfo):
|
try:
|
||||||
|
palette = im.encoderinfo["palette"]
|
||||||
|
except KeyError:
|
||||||
|
palette = None
|
||||||
|
|
||||||
|
for s in getheader(imOut, palette, im.encoderinfo):
|
||||||
fp.write(s)
|
fp.write(s)
|
||||||
|
|
||||||
flags = 0
|
flags = 0
|
||||||
|
@ -319,7 +324,7 @@ def _save_netpbm(im, fp, filename):
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
# GIF utilities
|
# GIF utilities
|
||||||
|
|
||||||
def getheader(im, info=None):
|
def getheader(im, palette, info=None):
|
||||||
"""Return a list of strings representing a GIF header"""
|
"""Return a list of strings representing a GIF header"""
|
||||||
|
|
||||||
optimize = info and info.get("optimize", 0)
|
optimize = info and info.get("optimize", 0)
|
||||||
|
@ -347,7 +352,13 @@ def getheader(im, info=None):
|
||||||
# global palette
|
# global palette
|
||||||
if im.mode == "P":
|
if im.mode == "P":
|
||||||
# colour palette
|
# colour palette
|
||||||
s.append(im.im.getpalette("RGB")[:maxcolor*3])
|
if palette is not None and Image.isBytesType(palette):
|
||||||
|
paletteBytes = palette
|
||||||
|
else:
|
||||||
|
paletteBytes =im.im.getpalette("RGB")[:maxcolor*3]
|
||||||
|
|
||||||
|
s.append(paletteBytes)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# greyscale
|
# greyscale
|
||||||
for i in range(maxcolor):
|
for i in range(maxcolor):
|
||||||
|
|
|
@ -35,6 +35,8 @@ MAXBLOCK = 65536
|
||||||
|
|
||||||
SAFEBLOCK = 1024*1024
|
SAFEBLOCK = 1024*1024
|
||||||
|
|
||||||
|
LOAD_TRUNCATED_IMAGES = False
|
||||||
|
|
||||||
ERRORS = {
|
ERRORS = {
|
||||||
-1: "image buffer overrun error",
|
-1: "image buffer overrun error",
|
||||||
-2: "decoding error",
|
-2: "decoding error",
|
||||||
|
@ -196,10 +198,22 @@ class ImageFile(Image.Image):
|
||||||
b = prefix
|
b = prefix
|
||||||
t = len(b)
|
t = len(b)
|
||||||
while True:
|
while True:
|
||||||
s = read(self.decodermaxblock)
|
try:
|
||||||
if not s:
|
s = read(self.decodermaxblock)
|
||||||
|
except IndexError as ie: # truncated png/gif
|
||||||
|
if LOAD_TRUNCATED_IMAGES:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise IndexError(ie)
|
||||||
|
|
||||||
|
if not s: # truncated jpeg
|
||||||
self.tile = []
|
self.tile = []
|
||||||
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
|
|
||||||
|
if LOAD_TRUNCATED_IMAGES:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
|
||||||
|
|
||||||
b = b + s
|
b = b + s
|
||||||
n, e = d.decode(b)
|
n, e = d.decode(b)
|
||||||
if n < 0:
|
if n < 0:
|
||||||
|
@ -212,7 +226,9 @@ class ImageFile(Image.Image):
|
||||||
|
|
||||||
self.fp = None # might be shared
|
self.fp = None # might be shared
|
||||||
|
|
||||||
if not self.map and e < 0:
|
if not LOAD_TRUNCATED_IMAGES and not self.map and e < 0:
|
||||||
|
# Note: If loading a truncated image results in an all black Image,
|
||||||
|
# the decoder wasn't able to decode anything.
|
||||||
raise_ioerror(e)
|
raise_ioerror(e)
|
||||||
|
|
||||||
# post processing
|
# post processing
|
||||||
|
|
|
@ -465,6 +465,7 @@ def _save(im, fp, filename):
|
||||||
dpi[0], dpi[1],
|
dpi[0], dpi[1],
|
||||||
subsampling,
|
subsampling,
|
||||||
extra,
|
extra,
|
||||||
|
info.get("exif", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
|
ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
|
||||||
|
|
|
@ -522,19 +522,19 @@ static struct PyMethodDef cms_profile_methods[] = {
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cms_profile_getattr_product_name(CmsProfileObject* self, void* closure)
|
cms_profile_getattr_product_name(CmsProfileObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(cmsTakeProductName(self->profile));
|
return PyUnicode_DecodeFSDefault(cmsTakeProductName(self->profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cms_profile_getattr_product_desc(CmsProfileObject* self, void* closure)
|
cms_profile_getattr_product_desc(CmsProfileObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(cmsTakeProductDesc(self->profile));
|
return PyUnicode_DecodeFSDefault(cmsTakeProductDesc(self->profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cms_profile_getattr_product_info(CmsProfileObject* self, void* closure)
|
cms_profile_getattr_product_info(CmsProfileObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(cmsTakeProductInfo(self->profile));
|
return PyUnicode_DecodeFSDefault(cmsTakeProductInfo(self->profile));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
@ -546,13 +546,13 @@ cms_profile_getattr_rendering_intent(CmsProfileObject* self, void* closure)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cms_profile_getattr_pcs(CmsProfileObject* self, void* closure)
|
cms_profile_getattr_pcs(CmsProfileObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(findICmode(cmsGetPCS(self->profile)));
|
return PyUnicode_DecodeFSDefault(findICmode(cmsGetPCS(self->profile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
cms_profile_getattr_color_space(CmsProfileObject* self, void* closure)
|
cms_profile_getattr_color_space(CmsProfileObject* self, void* closure)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromString(findICmode(cmsGetColorSpace(self->profile)));
|
return PyUnicode_DecodeFSDefault(findICmode(cmsGetColorSpace(self->profile)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: add more properties (creation_datetime etc) */
|
/* FIXME: add more properties (creation_datetime etc) */
|
||||||
|
|
26
encode.c
26
encode.c
|
@ -15,7 +15,7 @@
|
||||||
* 1999-02-07 fl Added PCX encoder
|
* 1999-02-07 fl Added PCX encoder
|
||||||
*
|
*
|
||||||
* Copyright (c) 1997-2001 by Secret Labs AB
|
* Copyright (c) 1997-2001 by Secret Labs AB
|
||||||
* Copyright (c) 1996-1997 by Fredrik Lundh
|
* Copyright (c) 1996-1997 by Fredrik Lundh
|
||||||
*
|
*
|
||||||
* See the README file for information on usage and redistribution.
|
* See the README file for information on usage and redistribution.
|
||||||
*/
|
*/
|
||||||
|
@ -93,7 +93,7 @@ _dealloc(ImagingEncoderObject* encoder)
|
||||||
PyObject_Del(encoder);
|
PyObject_Del(encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_encode(ImagingEncoderObject* encoder, PyObject* args)
|
_encode(ImagingEncoderObject* encoder, PyObject* args)
|
||||||
{
|
{
|
||||||
PyObject* buf;
|
PyObject* buf;
|
||||||
|
@ -125,7 +125,7 @@ _encode(ImagingEncoderObject* encoder, PyObject* args)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
|
_encode_to_file(ImagingEncoderObject* encoder, PyObject* args)
|
||||||
{
|
{
|
||||||
UINT8* buf;
|
UINT8* buf;
|
||||||
|
@ -520,11 +520,16 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */
|
int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */
|
||||||
int xdpi = 0, ydpi = 0;
|
int xdpi = 0, ydpi = 0;
|
||||||
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
|
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
|
||||||
char* extra = NULL; int extra_size;
|
char* extra = NULL;
|
||||||
|
int extra_size;
|
||||||
|
char* rawExif = NULL;
|
||||||
|
int rawExifLen = 0;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "ss|iiiiiiii"PY_ARG_BYTES_LENGTH,
|
if (!PyArg_ParseTuple(args, "ss|iiiiiiii"PY_ARG_BYTES_LENGTH,
|
||||||
&mode, &rawmode, &quality,
|
&mode, &rawmode, &quality,
|
||||||
&progressive, &smooth, &optimize, &streamtype,
|
&progressive, &smooth, &optimize, &streamtype,
|
||||||
&xdpi, &ydpi, &subsampling, &extra, &extra_size))
|
&xdpi, &ydpi, &subsampling, &extra, &extra_size,
|
||||||
|
&rawExif, &rawExifLen))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
|
encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
|
||||||
|
@ -543,6 +548,15 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
} else
|
} else
|
||||||
extra = NULL;
|
extra = NULL;
|
||||||
|
|
||||||
|
if (rawExif && rawExifLen > 0) {
|
||||||
|
char* pp = malloc(rawExifLen);
|
||||||
|
if (!pp)
|
||||||
|
return PyErr_NoMemory();
|
||||||
|
memcpy(pp, rawExif, rawExifLen);
|
||||||
|
rawExif = pp;
|
||||||
|
} else
|
||||||
|
rawExif = NULL;
|
||||||
|
|
||||||
encoder->encode = ImagingJpegEncode;
|
encoder->encode = ImagingJpegEncode;
|
||||||
|
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
|
((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
|
||||||
|
@ -555,6 +569,8 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->ydpi = ydpi;
|
((JPEGENCODERSTATE*)encoder->state.context)->ydpi = ydpi;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->extra = extra;
|
((JPEGENCODERSTATE*)encoder->state.context)->extra = extra;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->extra_size = extra_size;
|
((JPEGENCODERSTATE*)encoder->state.context)->extra_size = extra_size;
|
||||||
|
((JPEGENCODERSTATE*)encoder->state.context)->rawExif = rawExif;
|
||||||
|
((JPEGENCODERSTATE*)encoder->state.context)->rawExifLen = rawExifLen;
|
||||||
|
|
||||||
return (PyObject*) encoder;
|
return (PyObject*) encoder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,5 +100,8 @@ typedef struct {
|
||||||
JPEGDESTINATION destination;
|
JPEGDESTINATION destination;
|
||||||
|
|
||||||
int extra_offset;
|
int extra_offset;
|
||||||
|
|
||||||
|
int rawExifLen; /* EXIF data length */
|
||||||
|
char* rawExif; /* EXIF buffer pointer */
|
||||||
|
|
||||||
} JPEGENCODERSTATE;
|
} JPEGENCODERSTATE;
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
|
|
||||||
#ifdef HAVE_LIBJPEG
|
#ifdef HAVE_LIBJPEG
|
||||||
|
|
||||||
#undef HAVE_PROTOTYPES
|
#undef HAVE_PROTOTYPES
|
||||||
#undef HAVE_STDLIB_H
|
#undef HAVE_STDLIB_H
|
||||||
#undef HAVE_STDDEF_H
|
#undef HAVE_STDDEF_H
|
||||||
#undef UINT8
|
#undef UINT8
|
||||||
#undef UINT16
|
#undef UINT16
|
||||||
#undef UINT32
|
#undef UINT32
|
||||||
|
@ -145,7 +145,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
jpeg_set_defaults(&context->cinfo);
|
jpeg_set_defaults(&context->cinfo);
|
||||||
if (context->quality > 0)
|
if (context->quality > 0)
|
||||||
jpeg_set_quality(&context->cinfo, context->quality, 1);
|
jpeg_set_quality(&context->cinfo, context->quality, 1);
|
||||||
|
|
||||||
/* Set subsampling options */
|
/* Set subsampling options */
|
||||||
switch (context->subsampling)
|
switch (context->subsampling)
|
||||||
{
|
{
|
||||||
|
@ -205,11 +205,19 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
jpeg_start_compress(&context->cinfo, FALSE);
|
jpeg_start_compress(&context->cinfo, FALSE);
|
||||||
/* suppress extra section */
|
/* suppress extra section */
|
||||||
context->extra_offset = context->extra_size;
|
context->extra_offset = context->extra_size;
|
||||||
|
//add exif header
|
||||||
|
if (context->rawExifLen > 0)
|
||||||
|
jpeg_write_marker(&context->cinfo, JPEG_APP0+1, context->rawExif, context->rawExifLen);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* interchange stream */
|
/* interchange stream */
|
||||||
jpeg_start_compress(&context->cinfo, TRUE);
|
jpeg_start_compress(&context->cinfo, TRUE);
|
||||||
break;
|
//add exif header
|
||||||
|
if (context->rawExifLen > 0)
|
||||||
|
jpeg_write_marker(&context->cinfo, JPEG_APP0+1, context->rawExif, context->rawExifLen);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
state->state++;
|
state->state++;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
6
py3.h
6
py3.h
|
@ -11,7 +11,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if PY_VERSION_HEX >= 0x03000000
|
#if PY_VERSION_HEX >= 0x03000000
|
||||||
#define PY_ARG_BYTES_LENGTH "y#"
|
#define PY_ARG_BYTES_LENGTH "y#y#"
|
||||||
|
|
||||||
/* Map PyInt -> PyLong */
|
/* Map PyInt -> PyLong */
|
||||||
#define PyInt_AsLong PyLong_AsLong
|
#define PyInt_AsLong PyLong_AsLong
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
#define PyInt_AS_LONG PyLong_AS_LONG
|
#define PyInt_AS_LONG PyLong_AS_LONG
|
||||||
|
|
||||||
#else /* PY_VERSION_HEX < 0x03000000 */
|
#else /* PY_VERSION_HEX < 0x03000000 */
|
||||||
#define PY_ARG_BYTES_LENGTH "s#"
|
#define PY_ARG_BYTES_LENGTH "s#s#"
|
||||||
|
|
||||||
#if !defined(KEEP_PY_UNICODE)
|
#if !defined(KEEP_PY_UNICODE)
|
||||||
/* Map PyUnicode -> PyString */
|
/* Map PyUnicode -> PyString */
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#undef PyUnicode_FromStringAndSize
|
#undef PyUnicode_FromStringAndSize
|
||||||
#undef PyUnicode_FromString
|
#undef PyUnicode_FromString
|
||||||
#undef PyUnicode_FromFormat
|
#undef PyUnicode_FromFormat
|
||||||
|
#undef PyUnicode_DecodeFSDefault
|
||||||
|
|
||||||
#define PyUnicode_AsString PyString_AsString
|
#define PyUnicode_AsString PyString_AsString
|
||||||
#define PyUnicode_AS_STRING PyString_AS_STRING
|
#define PyUnicode_AS_STRING PyString_AS_STRING
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
#define PyUnicode_FromStringAndSize PyString_FromStringAndSize
|
#define PyUnicode_FromStringAndSize PyString_FromStringAndSize
|
||||||
#define PyUnicode_FromString PyString_FromString
|
#define PyUnicode_FromString PyString_FromString
|
||||||
#define PyUnicode_FromFormat PyString_FromFormat
|
#define PyUnicode_FromFormat PyString_FromFormat
|
||||||
|
#define PyUnicode_DecodeFSDefault PyString_FromString
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Map PyBytes -> PyString */
|
/* Map PyBytes -> PyString */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user