mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-26 09:14:27 +03:00
Merge pull request #5910 from radarhere/putdata
Improved putdata() documentation and data handling
This commit is contained in:
commit
8e631e4cd9
|
@ -1,6 +1,8 @@
|
|||
import sys
|
||||
from array import array
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from .helper import assert_image_equal, hopper
|
||||
|
@ -47,6 +49,12 @@ def test_pypy_performance():
|
|||
im.putdata(list(range(256)) * 256)
|
||||
|
||||
|
||||
def test_mode_with_L_with_float():
|
||||
im = Image.new("L", (1, 1), 0)
|
||||
im.putdata([2.0])
|
||||
assert im.getpixel((0, 0)) == 2
|
||||
|
||||
|
||||
def test_mode_i():
|
||||
src = hopper("L")
|
||||
data = list(src.getdata())
|
||||
|
@ -87,3 +95,18 @@ def test_array_F():
|
|||
im.putdata(arr)
|
||||
|
||||
assert len(im.getdata()) == len(arr)
|
||||
|
||||
|
||||
def test_not_flattened():
|
||||
im = Image.new("L", (1, 1))
|
||||
with pytest.raises(TypeError):
|
||||
im.putdata([[0]])
|
||||
with pytest.raises(TypeError):
|
||||
im.putdata([[0]], 2)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
im = Image.new("I", (1, 1))
|
||||
im.putdata([[0]])
|
||||
with pytest.raises(TypeError):
|
||||
im = Image.new("F", (1, 1))
|
||||
im.putdata([[0]])
|
||||
|
|
|
@ -1705,13 +1705,14 @@ class Image:
|
|||
|
||||
def putdata(self, data, scale=1.0, offset=0.0):
|
||||
"""
|
||||
Copies pixel data to this image. This method copies data from a
|
||||
sequence object into the image, starting at the upper left
|
||||
corner (0, 0), and continuing until either the image or the
|
||||
sequence ends. The scale and offset values are used to adjust
|
||||
the sequence values: **pixel = value*scale + offset**.
|
||||
Copies pixel data from a flattened sequence object into the image. The
|
||||
values should start at the upper left corner (0, 0), continue to the
|
||||
end of the line, followed directly by the first value of the second
|
||||
line, and so on. Data will be read until either the image or the
|
||||
sequence ends. The scale and offset values are used to adjust the
|
||||
sequence values: **pixel = value*scale + offset**.
|
||||
|
||||
:param data: A sequence object.
|
||||
:param data: A flattened sequence object.
|
||||
:param scale: An optional scale value. The default is 1.0.
|
||||
:param offset: An optional offset value. The default is 0.0.
|
||||
"""
|
||||
|
|
|
@ -1494,6 +1494,14 @@ _putdata(ImagingObject *self, PyObject *args) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define set_value_to_item(seq, i) \
|
||||
op = PySequence_Fast_GET_ITEM(seq, i); \
|
||||
if (PySequence_Check(op)) { \
|
||||
PyErr_SetString(PyExc_TypeError, "sequence must be flattened"); \
|
||||
return NULL; \
|
||||
} else { \
|
||||
value = PyFloat_AsDouble(op); \
|
||||
}
|
||||
if (image->image8) {
|
||||
if (PyBytes_Check(data)) {
|
||||
unsigned char *p;
|
||||
|
@ -1522,11 +1530,12 @@ _putdata(ImagingObject *self, PyObject *args) {
|
|||
PyErr_SetString(PyExc_TypeError, must_be_sequence);
|
||||
return NULL;
|
||||
}
|
||||
double value;
|
||||
if (scale == 1.0 && offset == 0.0) {
|
||||
/* Clipped data */
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
op = PySequence_Fast_GET_ITEM(seq, i);
|
||||
image->image8[y][x] = (UINT8)CLIP8(PyLong_AsLong(op));
|
||||
set_value_to_item(seq, i);
|
||||
image->image8[y][x] = (UINT8)CLIP8(value);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
|
@ -1535,9 +1544,8 @@ _putdata(ImagingObject *self, PyObject *args) {
|
|||
} else {
|
||||
/* Scaled and clipped data */
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
PyObject *op = PySequence_Fast_GET_ITEM(seq, i);
|
||||
image->image8[y][x] =
|
||||
CLIP8((int)(PyFloat_AsDouble(op) * scale + offset));
|
||||
set_value_to_item(seq, i);
|
||||
image->image8[y][x] = CLIP8(value * scale + offset);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
|
@ -1555,9 +1563,10 @@ _putdata(ImagingObject *self, PyObject *args) {
|
|||
switch (image->type) {
|
||||
case IMAGING_TYPE_INT32:
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
op = PySequence_Fast_GET_ITEM(seq, i);
|
||||
double value;
|
||||
set_value_to_item(seq, i);
|
||||
IMAGING_PIXEL_INT32(image, x, y) =
|
||||
(INT32)(PyFloat_AsDouble(op) * scale + offset);
|
||||
(INT32)(value * scale + offset);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
|
@ -1566,9 +1575,10 @@ _putdata(ImagingObject *self, PyObject *args) {
|
|||
break;
|
||||
case IMAGING_TYPE_FLOAT32:
|
||||
for (i = x = y = 0; i < n; i++) {
|
||||
op = PySequence_Fast_GET_ITEM(seq, i);
|
||||
double value;
|
||||
set_value_to_item(seq, i);
|
||||
IMAGING_PIXEL_FLOAT32(image, x, y) =
|
||||
(FLOAT32)(PyFloat_AsDouble(op) * scale + offset);
|
||||
(FLOAT32)(value * scale + offset);
|
||||
if (++x >= (int)image->xsize) {
|
||||
x = 0, y++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user