When saving, allow alpha differences to indicate different frames

This commit is contained in:
Andrew Murray 2023-04-29 15:02:11 +10:00
parent d1731b35fe
commit ebd3c47425
5 changed files with 30 additions and 9 deletions

View File

@ -374,6 +374,20 @@ def test_apng_save(tmp_path):
assert im.getpixel((64, 32)) == (0, 255, 0, 255)
def test_apng_save_alpha(tmp_path):
test_file = str(tmp_path / "temp.png")
im = Image.new("RGBA", (1, 1), (255, 0, 0, 255))
im2 = Image.new("RGBA", (1, 1), (255, 0, 0, 127))
im.save(test_file, save_all=True, append_images=[im2])
with Image.open(test_file) as reloaded:
assert reloaded.getpixel((0, 0)) == (255, 0, 0, 255)
reloaded.seek(1)
assert reloaded.getpixel((0, 0)) == (255, 0, 0, 127)
def test_apng_save_split_fdat(tmp_path):
# test to make sure we do not generate sequence errors when writing
# frames with image data spanning multiple fdAT chunks (in this case

View File

@ -1138,9 +1138,9 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
else:
base_im = previous["im"]
delta = ImageChops.subtract_modulo(
im_frame.convert("RGB"), base_im.convert("RGB")
im_frame.convert("RGBA"), base_im.convert("RGBA")
)
bbox = delta.getbbox()
bbox = delta.im.getbbox(False)
if (
not bbox
and prev_disposal == encoderinfo.get("disposal")

View File

@ -2160,9 +2160,15 @@ _isblock(ImagingObject *self) {
}
static PyObject *
_getbbox(ImagingObject *self) {
_getbbox(ImagingObject *self, PyObject *args) {
int bbox[4];
if (!ImagingGetBBox(self->image, bbox)) {
int consider_alpha = 1;
if (!PyArg_ParseTuple(args, "|i", &consider_alpha)) {
return NULL;
}
if (!ImagingGetBBox(self->image, bbox, consider_alpha)) {
Py_INCREF(Py_None);
return Py_None;
}
@ -3574,7 +3580,7 @@ static struct PyMethodDef methods[] = {
{"isblock", (PyCFunction)_isblock, METH_NOARGS},
{"getbbox", (PyCFunction)_getbbox, METH_NOARGS},
{"getbbox", (PyCFunction)_getbbox, METH_VARARGS},
{"getcolors", (PyCFunction)_getcolors, METH_VARARGS},
{"getextrema", (PyCFunction)_getextrema, METH_NOARGS},
{"getprojection", (PyCFunction)_getprojection, METH_NOARGS},

View File

@ -19,7 +19,7 @@
#include "Imaging.h"
int
ImagingGetBBox(Imaging im, int bbox[4]) {
ImagingGetBBox(Imaging im, int bbox[4], int consider_alpha) {
/* Get the bounding box for any non-zero data in the image.*/
int x, y;
@ -58,10 +58,11 @@ ImagingGetBBox(Imaging im, int bbox[4]) {
INT32 mask = 0xffffffff;
if (im->bands == 3) {
((UINT8 *)&mask)[3] = 0;
} else if (
} else if (consider_alpha && (
strcmp(im->mode, "RGBa") == 0 || strcmp(im->mode, "RGBA") == 0 ||
strcmp(im->mode, "La") == 0 || strcmp(im->mode, "LA") == 0 ||
strcmp(im->mode, "PA") == 0) {
strcmp(im->mode, "PA") == 0
)) {
#ifdef WORDS_BIGENDIAN
mask = 0x000000ff;
#else

View File

@ -317,7 +317,7 @@ ImagingMerge(const char *mode, Imaging bands[4]);
extern int
ImagingSplit(Imaging im, Imaging bands[4]);
extern int
ImagingGetBBox(Imaging im, int bbox[4]);
ImagingGetBBox(Imaging im, int bbox[4], int consider_alpha);
typedef struct {
int x, y;
INT32 count;