mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-10-31 16:07:30 +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