mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-11 07:44:46 +03:00
delegate Image.mode and Image.size to the values on Image.im when available
When setting the values on Image also try to update the values on Image.im. There isn't currently a way to update values in the other direction.
This commit is contained in:
parent
95257dff87
commit
919dbbe1f1
|
@ -662,7 +662,7 @@ class TestImage:
|
||||||
blank_pa.palette = None
|
blank_pa.palette = None
|
||||||
|
|
||||||
def _make_new(base_image, im, palette_result=None):
|
def _make_new(base_image, im, palette_result=None):
|
||||||
new_im = base_image._new(im)
|
new_im = base_image._new(im.im)
|
||||||
assert new_im.mode == im.mode
|
assert new_im.mode == im.mode
|
||||||
assert new_im.size == im.size
|
assert new_im.size == im.size
|
||||||
assert new_im.info == base_image.info
|
assert new_im.info == base_image.info
|
||||||
|
|
|
@ -328,8 +328,8 @@ class GifImageFile(ImageFile.ImageFile):
|
||||||
self._mode = "RGBA"
|
self._mode = "RGBA"
|
||||||
del self.info["transparency"]
|
del self.info["transparency"]
|
||||||
else:
|
else:
|
||||||
self._mode = "RGB"
|
|
||||||
self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG)
|
self.im = self.im.convert("RGB", Image.Dither.FLOYDSTEINBERG)
|
||||||
|
self._mode = "RGB"
|
||||||
|
|
||||||
def _rgb(color):
|
def _rgb(color):
|
||||||
if self._frame_palette:
|
if self._frame_palette:
|
||||||
|
|
|
@ -261,11 +261,7 @@ class IcnsImageFile(ImageFile.ImageFile):
|
||||||
self.best_size[1] * self.best_size[2],
|
self.best_size[1] * self.best_size[2],
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@Image.Image.size.setter
|
||||||
def size(self):
|
|
||||||
return self._size
|
|
||||||
|
|
||||||
@size.setter
|
|
||||||
def size(self, value):
|
def size(self, value):
|
||||||
info_size = value
|
info_size = value
|
||||||
if info_size not in self.info["sizes"] and len(info_size) == 2:
|
if info_size not in self.info["sizes"] and len(info_size) == 2:
|
||||||
|
@ -283,7 +279,10 @@ class IcnsImageFile(ImageFile.ImageFile):
|
||||||
if info_size not in self.info["sizes"]:
|
if info_size not in self.info["sizes"]:
|
||||||
msg = "This is not one of the allowed sizes of this image"
|
msg = "This is not one of the allowed sizes of this image"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
self._size = value
|
if value != self.size:
|
||||||
|
self.im = None
|
||||||
|
self.pyaccess = None
|
||||||
|
self._size = value
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
if len(self.size) == 3:
|
if len(self.size) == 3:
|
||||||
|
@ -306,7 +305,7 @@ class IcnsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.im = im.im
|
self.im = im.im
|
||||||
self._mode = im.mode
|
self._mode = im.mode
|
||||||
self.size = im.size
|
self._size = im.size
|
||||||
|
|
||||||
return px
|
return px
|
||||||
|
|
||||||
|
|
|
@ -310,36 +310,36 @@ class IcoImageFile(ImageFile.ImageFile):
|
||||||
self.size = self.ico.entry[0]["dim"]
|
self.size = self.ico.entry[0]["dim"]
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
@property
|
@Image.Image.size.setter
|
||||||
def size(self):
|
|
||||||
return self._size
|
|
||||||
|
|
||||||
@size.setter
|
|
||||||
def size(self, value):
|
def size(self, value):
|
||||||
if value not in self.info["sizes"]:
|
if value not in self.info["sizes"]:
|
||||||
msg = "This is not one of the allowed sizes of this image"
|
msg = "This is not one of the allowed sizes of this image"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
self._size = value
|
if value != self.size:
|
||||||
|
self.im = None
|
||||||
|
self.pyaccess = None
|
||||||
|
self._size = value
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
if self.im is not None and self.im.size == self.size:
|
if self.im is not None and self.im.size == self.size:
|
||||||
# Already loaded
|
# Already loaded
|
||||||
return Image.Image.load(self)
|
return Image.Image.load(self)
|
||||||
im = self.ico.getimage(self.size)
|
size_to_load = self.size
|
||||||
|
im = self.ico.getimage(size_to_load)
|
||||||
# if tile is PNG, it won't really be loaded yet
|
# if tile is PNG, it won't really be loaded yet
|
||||||
im.load()
|
im.load()
|
||||||
self.im = im.im
|
self.im = im.im
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
self._mode = im.mode
|
self._mode = im.mode
|
||||||
if im.size != self.size:
|
if im.size != size_to_load:
|
||||||
warnings.warn("Image was not the expected size")
|
warnings.warn("Image was not the expected size")
|
||||||
|
|
||||||
index = self.ico.getentryindex(self.size)
|
index = self.ico.getentryindex(size_to_load)
|
||||||
sizes = list(self.info["sizes"])
|
sizes = list(self.info["sizes"])
|
||||||
sizes[index] = im.size
|
sizes[index] = im.size
|
||||||
self.info["sizes"] = set(sizes)
|
self.info["sizes"] = set(sizes)
|
||||||
|
|
||||||
self.size = im.size
|
self._size = im.size
|
||||||
|
|
||||||
def load_seek(self):
|
def load_seek(self):
|
||||||
# Flag the ImageFile.Parser so that it
|
# Flag the ImageFile.Parser so that it
|
||||||
|
|
|
@ -480,16 +480,21 @@ class Image:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# FIXME: take "new" parameters / other image?
|
# FIXME: take "new" parameters / other image?
|
||||||
# FIXME: turn mode and size into delegating properties?
|
|
||||||
self.im = None
|
self.im = None
|
||||||
self._mode = ""
|
# do not directly change __mode; use _mode instead
|
||||||
self._size = (0, 0)
|
self.__mode = ""
|
||||||
|
# do not directly change __size; use _size instead
|
||||||
|
self.__size = (0, 0)
|
||||||
self.palette = None
|
self.palette = None
|
||||||
self.info = {}
|
self.info = {}
|
||||||
self.readonly = 0
|
self.readonly = 0
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
self._exif = None
|
self._exif = None
|
||||||
|
|
||||||
|
def _use_im_values(self):
|
||||||
|
''' Whether or not to try using values from self.im in addition to the values in this class. '''
|
||||||
|
return self.im is not None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self):
|
def width(self):
|
||||||
return self.size[0]
|
return self.size[0]
|
||||||
|
@ -502,10 +507,36 @@ class Image:
|
||||||
def size(self):
|
def size(self):
|
||||||
return self._size
|
return self._size
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _size(self):
|
||||||
|
if self._use_im_values():
|
||||||
|
return self.im.size
|
||||||
|
return self.__size
|
||||||
|
|
||||||
|
@_size.setter
|
||||||
|
def _size(self, value):
|
||||||
|
# set im.size first in case it raises an excepton
|
||||||
|
if self._use_im_values():
|
||||||
|
self.im.size = value
|
||||||
|
self.__size = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode(self):
|
def mode(self):
|
||||||
return self._mode
|
return self._mode
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _mode(self):
|
||||||
|
if self._use_im_values():
|
||||||
|
return self.im.mode
|
||||||
|
return self.__mode
|
||||||
|
|
||||||
|
@_mode.setter
|
||||||
|
def _mode(self, value):
|
||||||
|
# set im.mode first in case it raises an excepton
|
||||||
|
if self._use_im_values():
|
||||||
|
self.im.mode = value
|
||||||
|
self.__mode = value
|
||||||
|
|
||||||
def _new(self, im):
|
def _new(self, im):
|
||||||
new = Image()
|
new = Image()
|
||||||
new.im = im
|
new.im = im
|
||||||
|
|
|
@ -139,6 +139,9 @@ class ImageFile(Image.Image):
|
||||||
if self.format is not None:
|
if self.format is not None:
|
||||||
return Image.MIME.get(self.format.upper())
|
return Image.MIME.get(self.format.upper())
|
||||||
|
|
||||||
|
def _use_im_values(self):
|
||||||
|
return self.tile is None and self.im is not None
|
||||||
|
|
||||||
def __setstate__(self, state):
|
def __setstate__(self, state):
|
||||||
self.tile = []
|
self.tile = []
|
||||||
super().__setstate__(state)
|
super().__setstate__(state)
|
||||||
|
|
|
@ -3646,11 +3646,49 @@ _getattr_mode(ImagingObject *self, void *closure) {
|
||||||
return PyUnicode_FromString(self->image->mode);
|
return PyUnicode_FromString(self->image->mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_setattr_mode(ImagingObject *self, PyObject *value, void *closure) {
|
||||||
|
if (value == NULL) {
|
||||||
|
self->image->mode[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mode = PyUnicode_AsUTF8(value);
|
||||||
|
if (mode == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strlen(mode) >= IMAGING_MODE_LENGTH) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "given mode name is too long");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(self->image->mode, mode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_getattr_size(ImagingObject *self, void *closure) {
|
_getattr_size(ImagingObject *self, void *closure) {
|
||||||
return Py_BuildValue("ii", self->image->xsize, self->image->ysize);
|
return Py_BuildValue("ii", self->image->xsize, self->image->ysize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_setattr_size(ImagingObject *self, PyObject *value, void *closure) {
|
||||||
|
if (value == NULL) {
|
||||||
|
self->image->xsize = 0;
|
||||||
|
self->image->ysize = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xsize, ysize;
|
||||||
|
if (!PyArg_ParseTuple(value, "ii", &xsize, &ysize)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->image->xsize = xsize;
|
||||||
|
self->image->ysize = ysize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_getattr_bands(ImagingObject *self, void *closure) {
|
_getattr_bands(ImagingObject *self, void *closure) {
|
||||||
return PyLong_FromLong(self->image->bands);
|
return PyLong_FromLong(self->image->bands);
|
||||||
|
@ -3679,13 +3717,14 @@ _getattr_unsafe_ptrs(ImagingObject *self, void *closure) {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct PyGetSetDef getsetters[] = {
|
static struct PyGetSetDef getsetters[] = {
|
||||||
{"mode", (getter)_getattr_mode},
|
{"mode", (getter)_getattr_mode, (setter)_setattr_mode},
|
||||||
{"size", (getter)_getattr_size},
|
{"size", (getter)_getattr_size, (setter)_setattr_size},
|
||||||
{"bands", (getter)_getattr_bands},
|
{"bands", (getter)_getattr_bands},
|
||||||
{"id", (getter)_getattr_id},
|
{"id", (getter)_getattr_id},
|
||||||
{"ptr", (getter)_getattr_ptr},
|
{"ptr", (getter)_getattr_ptr},
|
||||||
{"unsafe_ptrs", (getter)_getattr_unsafe_ptrs},
|
{"unsafe_ptrs", (getter)_getattr_unsafe_ptrs},
|
||||||
{NULL}};
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
/* basic sequence semantics */
|
/* basic sequence semantics */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user