mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 18:56:17 +03:00
Merge with master
This commit is contained in:
commit
ab87302560
|
@ -40,9 +40,7 @@ script:
|
||||||
- CFLAGS="-coverage" python setup.py build_ext --inplace
|
- CFLAGS="-coverage" python setup.py build_ext --inplace
|
||||||
|
|
||||||
- coverage run --append --include=PIL/* selftest.py
|
- coverage run --append --include=PIL/* selftest.py
|
||||||
# Temporarily remove fail-fast
|
- coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py
|
||||||
# - coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py
|
|
||||||
- coverage run --append --include=PIL/* -m nose -v Tests/test_*.py
|
|
||||||
|
|
||||||
after_success:
|
after_success:
|
||||||
# gather the coverage data
|
# gather the coverage data
|
||||||
|
|
|
@ -4,6 +4,9 @@ Changelog (Pillow)
|
||||||
2.6.0 (unreleased)
|
2.6.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Image.tobytes() and Image.tostring() documentation update #916 #917
|
||||||
|
[mgedmin]
|
||||||
|
|
||||||
- On Windows, do not execute convert.exe without specifying path #912
|
- On Windows, do not execute convert.exe without specifying path #912
|
||||||
[cgohlke]
|
[cgohlke]
|
||||||
|
|
||||||
|
|
|
@ -664,6 +664,10 @@ class Image:
|
||||||
|
|
||||||
# Declare tostring as alias to tobytes
|
# Declare tostring as alias to tobytes
|
||||||
def tostring(self, *args, **kw):
|
def tostring(self, *args, **kw):
|
||||||
|
"""Deprecated alias to tobytes.
|
||||||
|
|
||||||
|
.. deprecated:: 2.0
|
||||||
|
"""
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
'tostring() is deprecated. Please call tobytes() instead.',
|
'tostring() is deprecated. Please call tobytes() instead.',
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
|
|
|
@ -23,23 +23,26 @@ from PIL import Image
|
||||||
|
|
||||||
class HDC:
|
class HDC:
|
||||||
"""
|
"""
|
||||||
Wraps a HDC integer. The resulting object can be passed to the
|
Wraps an HDC integer. The resulting object can be passed to the
|
||||||
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
||||||
methods.
|
methods.
|
||||||
"""
|
"""
|
||||||
def __init__(self, dc):
|
def __init__(self, dc):
|
||||||
self.dc = dc
|
self.dc = dc
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
return self.dc
|
return self.dc
|
||||||
|
|
||||||
|
|
||||||
class HWND:
|
class HWND:
|
||||||
"""
|
"""
|
||||||
Wraps a HWND integer. The resulting object can be passed to the
|
Wraps an HWND integer. The resulting object can be passed to the
|
||||||
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
:py:meth:`~PIL.ImageWin.Dib.draw` and :py:meth:`~PIL.ImageWin.Dib.expose`
|
||||||
methods, instead of a DC.
|
methods, instead of a DC.
|
||||||
"""
|
"""
|
||||||
def __init__(self, wnd):
|
def __init__(self, wnd):
|
||||||
self.wnd = wnd
|
self.wnd = wnd
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
return self.wnd
|
return self.wnd
|
||||||
|
|
||||||
|
@ -79,13 +82,12 @@ class Dib:
|
||||||
if image:
|
if image:
|
||||||
self.paste(image)
|
self.paste(image)
|
||||||
|
|
||||||
|
|
||||||
def expose(self, handle):
|
def expose(self, handle):
|
||||||
"""
|
"""
|
||||||
Copy the bitmap contents to a device context.
|
Copy the bitmap contents to a device context.
|
||||||
|
|
||||||
:param handle: Device context (HDC), cast to a Python integer, or a HDC
|
:param handle: Device context (HDC), cast to a Python integer, or an
|
||||||
or HWND instance. In PythonWin, you can use the
|
HDC or HWND instance. In PythonWin, you can use the
|
||||||
:py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
|
:py:meth:`CDC.GetHandleAttrib` to get a suitable handle.
|
||||||
"""
|
"""
|
||||||
if isinstance(handle, HWND):
|
if isinstance(handle, HWND):
|
||||||
|
@ -109,7 +111,7 @@ class Dib:
|
||||||
necessary.
|
necessary.
|
||||||
"""
|
"""
|
||||||
if not src:
|
if not src:
|
||||||
src = (0,0) + self.size
|
src = (0, 0) + self.size
|
||||||
if isinstance(handle, HWND):
|
if isinstance(handle, HWND):
|
||||||
dc = self.image.getdc(handle)
|
dc = self.image.getdc(handle)
|
||||||
try:
|
try:
|
||||||
|
@ -120,7 +122,6 @@ class Dib:
|
||||||
result = self.image.draw(handle, dst, src)
|
result = self.image.draw(handle, dst, src)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def query_palette(self, handle):
|
def query_palette(self, handle):
|
||||||
"""
|
"""
|
||||||
Installs the palette associated with the image in the given device
|
Installs the palette associated with the image in the given device
|
||||||
|
@ -146,7 +147,6 @@ class Dib:
|
||||||
result = self.image.query_palette(handle)
|
result = self.image.query_palette(handle)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def paste(self, im, box=None):
|
def paste(self, im, box=None):
|
||||||
"""
|
"""
|
||||||
Paste a PIL image into the bitmap image.
|
Paste a PIL image into the bitmap image.
|
||||||
|
@ -166,7 +166,6 @@ class Dib:
|
||||||
else:
|
else:
|
||||||
self.image.paste(im.im)
|
self.image.paste(im.im)
|
||||||
|
|
||||||
|
|
||||||
def frombytes(self, buffer):
|
def frombytes(self, buffer):
|
||||||
"""
|
"""
|
||||||
Load display memory contents from byte data.
|
Load display memory contents from byte data.
|
||||||
|
@ -176,7 +175,6 @@ class Dib:
|
||||||
"""
|
"""
|
||||||
return self.image.frombytes(buffer)
|
return self.image.frombytes(buffer)
|
||||||
|
|
||||||
|
|
||||||
def tobytes(self):
|
def tobytes(self):
|
||||||
"""
|
"""
|
||||||
Copy display memory contents to bytes object.
|
Copy display memory contents to bytes object.
|
||||||
|
@ -204,6 +202,7 @@ class Dib:
|
||||||
)
|
)
|
||||||
return self.tobytes()
|
return self.tobytes()
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Create a Window with the given title size.
|
# Create a Window with the given title size.
|
||||||
|
|
||||||
|
@ -235,6 +234,7 @@ class Window:
|
||||||
def mainloop(self):
|
def mainloop(self):
|
||||||
Image.core.eventloop()
|
Image.core.eventloop()
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Create an image window which displays the given image.
|
# Create an image window which displays the given image.
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,123 @@
|
||||||
from helper import unittest, PillowTestCase
|
from helper import unittest, PillowTestCase, hopper
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
from PIL import ImageWin
|
from PIL import ImageWin
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class TestImageWin(PillowTestCase):
|
class TestImageWin(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
dir(Image)
|
|
||||||
dir(ImageWin)
|
dir(ImageWin)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_hdc(self):
|
||||||
|
# Arrange
|
||||||
|
dc = 50
|
||||||
|
|
||||||
|
# Act
|
||||||
|
hdc = ImageWin.HDC(dc)
|
||||||
|
dc2 = int(hdc)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(dc2, 50)
|
||||||
|
|
||||||
|
def test_hwnd(self):
|
||||||
|
# Arrange
|
||||||
|
wnd = 50
|
||||||
|
|
||||||
|
# Act
|
||||||
|
hwnd = ImageWin.HWND(wnd)
|
||||||
|
wnd2 = int(hwnd)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(wnd2, 50)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(sys.platform.startswith('win32'), "Windows only")
|
||||||
|
class TestImageWinDib(PillowTestCase):
|
||||||
|
|
||||||
|
def test_dib_image(self):
|
||||||
|
# Arrange
|
||||||
|
im = hopper()
|
||||||
|
|
||||||
|
# Act
|
||||||
|
dib = ImageWin.Dib(im)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(dib.size, im.size)
|
||||||
|
|
||||||
|
def test_dib_mode_string(self):
|
||||||
|
# Arrange
|
||||||
|
mode = "RGBA"
|
||||||
|
size = (128, 128)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
dib = ImageWin.Dib(mode, size)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(dib.size, (128, 128))
|
||||||
|
|
||||||
|
def test_dib_paste(self):
|
||||||
|
# Arrange
|
||||||
|
im = hopper()
|
||||||
|
|
||||||
|
mode = "RGBA"
|
||||||
|
size = (128, 128)
|
||||||
|
dib = ImageWin.Dib(mode, size)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
dib.paste(im)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(dib.size, (128, 128))
|
||||||
|
|
||||||
|
def test_dib_paste_bbox(self):
|
||||||
|
# Arrange
|
||||||
|
im = hopper()
|
||||||
|
bbox = (0, 0, 10, 10)
|
||||||
|
|
||||||
|
mode = "RGBA"
|
||||||
|
size = (128, 128)
|
||||||
|
dib = ImageWin.Dib(mode, size)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
dib.paste(im, bbox)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
self.assertEqual(dib.size, (128, 128))
|
||||||
|
|
||||||
|
def test_dib_frombytes_tobytes_roundtrip(self):
|
||||||
|
# Arrange
|
||||||
|
# Make two different DIB images
|
||||||
|
im = hopper()
|
||||||
|
dib1 = ImageWin.Dib(im)
|
||||||
|
|
||||||
|
mode = "RGB"
|
||||||
|
size = (128, 128)
|
||||||
|
dib2 = ImageWin.Dib(mode, size)
|
||||||
|
|
||||||
|
# Confirm they're different
|
||||||
|
self.assertNotEqual(dib1.tobytes(), dib2.tobytes())
|
||||||
|
|
||||||
|
# Act
|
||||||
|
# Make one the same as the using tobytes()/frombytes()
|
||||||
|
buffer = dib1.tobytes()
|
||||||
|
dib2.frombytes(buffer)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
# Confirm they're the same
|
||||||
|
self.assertEqual(dib1.tobytes(), dib2.tobytes())
|
||||||
|
|
||||||
|
def test_dib_fromstring_tostring_deprecated(self):
|
||||||
|
# Arrange
|
||||||
|
im = hopper()
|
||||||
|
dib = ImageWin.Dib(im)
|
||||||
|
buffer = dib.tobytes()
|
||||||
|
|
||||||
|
# Act/Assert
|
||||||
|
self.assert_warning(DeprecationWarning, lambda: dib.tostring())
|
||||||
|
self.assert_warning(DeprecationWarning, lambda: dib.fromstring(buffer))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -135,6 +135,7 @@ ITU-R 709, using the D65 luminant) to the CIE XYZ color space:
|
||||||
.. automethod:: PIL.Image.Image.tell
|
.. automethod:: PIL.Image.Image.tell
|
||||||
.. automethod:: PIL.Image.Image.thumbnail
|
.. automethod:: PIL.Image.Image.thumbnail
|
||||||
.. automethod:: PIL.Image.Image.tobitmap
|
.. automethod:: PIL.Image.Image.tobitmap
|
||||||
|
.. automethod:: PIL.Image.Image.tobytes
|
||||||
.. automethod:: PIL.Image.Image.tostring
|
.. automethod:: PIL.Image.Image.tostring
|
||||||
.. automethod:: PIL.Image.Image.transform
|
.. automethod:: PIL.Image.Image.transform
|
||||||
.. automethod:: PIL.Image.Image.transpose
|
.. automethod:: PIL.Image.Image.transpose
|
||||||
|
|
7
encode.c
7
encode.c
|
@ -535,7 +535,7 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
#include "Jpeg.h"
|
#include "Jpeg.h"
|
||||||
|
|
||||||
static unsigned int** get_qtables_arrays(PyObject* qtables) {
|
static unsigned int** get_qtables_arrays(PyObject* qtables, int* qtablesLen) {
|
||||||
PyObject* tables;
|
PyObject* tables;
|
||||||
PyObject* table;
|
PyObject* table;
|
||||||
PyObject* table_data;
|
PyObject* table_data;
|
||||||
|
@ -588,6 +588,7 @@ static unsigned int** get_qtables_arrays(PyObject* qtables) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(tables);
|
Py_DECREF(tables);
|
||||||
|
*qtablesLen = num_tables;
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
PyMem_Free(qarrays);
|
PyMem_Free(qarrays);
|
||||||
|
@ -614,6 +615,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
|
int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
|
||||||
PyObject* qtables=NULL;
|
PyObject* qtables=NULL;
|
||||||
unsigned int **qarrays = NULL;
|
unsigned int **qarrays = NULL;
|
||||||
|
int qtablesLen = 0;
|
||||||
char* extra = NULL;
|
char* extra = NULL;
|
||||||
int extra_size;
|
int extra_size;
|
||||||
char* rawExif = NULL;
|
char* rawExif = NULL;
|
||||||
|
@ -633,7 +635,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
if (get_packer(encoder, mode, rawmode) < 0)
|
if (get_packer(encoder, mode, rawmode) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
qarrays = get_qtables_arrays(qtables);
|
qarrays = get_qtables_arrays(qtables, &qtablesLen);
|
||||||
|
|
||||||
if (extra && extra_size > 0) {
|
if (extra && extra_size > 0) {
|
||||||
char* p = malloc(extra_size);
|
char* p = malloc(extra_size);
|
||||||
|
@ -657,6 +659,7 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
|
((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->qtables = qarrays;
|
((JPEGENCODERSTATE*)encoder->state.context)->qtables = qarrays;
|
||||||
|
((JPEGENCODERSTATE*)encoder->state.context)->qtablesLen = qtablesLen;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->subsampling = subsampling;
|
((JPEGENCODERSTATE*)encoder->state.context)->subsampling = subsampling;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive;
|
((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive;
|
||||||
((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth;
|
((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth;
|
||||||
|
|
|
@ -90,6 +90,7 @@ typedef struct {
|
||||||
|
|
||||||
/* Custom quantization tables () */
|
/* Custom quantization tables () */
|
||||||
unsigned int **qtables;
|
unsigned int **qtables;
|
||||||
|
int qtablesLen;
|
||||||
|
|
||||||
/* Extra data (to be injected after header) */
|
/* Extra data (to be injected after header) */
|
||||||
char* extra; int extra_size;
|
char* extra; int extra_size;
|
||||||
|
|
|
@ -151,7 +151,7 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8* buf, int bytes)
|
||||||
if (context->quality > 0) {
|
if (context->quality > 0) {
|
||||||
quality = context->quality;
|
quality = context->quality;
|
||||||
}
|
}
|
||||||
for (i = 0; i < sizeof(context->qtables)/sizeof(unsigned int); i++) {
|
for (i = 0; i < context->qtablesLen; i++) {
|
||||||
// TODO: Should add support for none baseline
|
// TODO: Should add support for none baseline
|
||||||
jpeg_add_quant_table(&context->cinfo, i, context->qtables[i],
|
jpeg_add_quant_table(&context->cinfo, i, context->qtables[i],
|
||||||
quality, TRUE);
|
quality, TRUE);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user