diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 461d0bf8e..83872c5d1 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -10,11 +10,11 @@ class TestLibPack(PillowTestCase): def test_pack(self): - def pack(mode, rawmode): + def pack(mode, rawmode, in_data=(1, 2, 3, 4)): if len(mode) == 1: - im = Image.new(mode, (1, 1), 1) + im = Image.new(mode, (1, 1), in_data[0]) else: - im = Image.new(mode, (1, 1), (1, 2, 3, 4)[:len(mode)]) + im = Image.new(mode, (1, 1), in_data[:len(mode)]) if py3: return list(im.tobytes("raw", rawmode)) @@ -47,6 +47,8 @@ class TestLibPack(PillowTestCase): self.assertEqual(pack("RGBX", "RGBX"), [1, 2, 3, 4]) # 4->255? self.assertEqual(pack("RGBA", "RGBA"), [1, 2, 3, 4]) + self.assertEqual(pack("RGBA", "BGRa"), [0, 0, 0, 4]) + self.assertEqual(pack("RGBA", "BGRa", in_data=(20, 30, 40, 50)), [8, 6, 4, 50]) self.assertEqual(pack("RGBa", "RGBa"), [1, 2, 3, 4]) self.assertEqual(pack("RGBa", "BGRa"), [3, 2, 1, 4]) @@ -122,7 +124,9 @@ class TestLibPack(PillowTestCase): self.assertEqual(unpack("RGB", "XBGR", 4), (4, 3, 2)) self.assertEqual(unpack("RGBA", "RGBA", 4), (1, 2, 3, 4)) + self.assertEqual(unpack("RGBA", "RGBa", 4), (63, 127, 191, 4)) self.assertEqual(unpack("RGBA", "BGRA", 4), (3, 2, 1, 4)) + self.assertEqual(unpack("RGBA", "BGRa", 4), (191, 127, 63, 4)) self.assertEqual(unpack("RGBA", "ARGB", 4), (2, 3, 4, 1)) self.assertEqual(unpack("RGBA", "ABGR", 4), (4, 3, 2, 1)) self.assertEqual(unpack("RGBA", "RGBA;15", 2), (8, 131, 0, 0)) diff --git a/encode.c b/encode.c index b08a9aa57..9a0dd2446 100644 --- a/encode.c +++ b/encode.c @@ -365,7 +365,7 @@ get_packer(ImagingEncoderObject* encoder, const char* mode, pack = ImagingFindPacker(mode, rawmode, &bits); if (!pack) { Py_DECREF(encoder); - PyErr_SetString(PyExc_SystemError, "unknown raw mode"); + PyErr_Format(PyExc_ValueError, "No packer found from %s to %s", mode, rawmode); return -1; } diff --git a/libImaging/Pack.c b/libImaging/Pack.c index d83cb8284..a19252e88 100644 --- a/libImaging/Pack.c +++ b/libImaging/Pack.c @@ -72,6 +72,10 @@ #define C64L C64N #endif +/* like (a * b + 127) / 255), but much faster on most platforms */ +#define MULDIV255(a, b, tmp)\ + (tmp = (a) * (b) + 128, ((((tmp) >> 8) + (tmp)) >> 8)) + static void pack1(UINT8* out, const UINT8* in, int pixels) { @@ -315,6 +319,21 @@ ImagingPackABGR(UINT8* out, const UINT8* in, int pixels) } } +void +ImagingPackBGRa(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* BGRa, reversed bytes with premultiplied alplha */ + for (i = 0; i < pixels; i++) { + int alpha = out[3] = in[A]; + int tmp; + out[0] = MULDIV255(in[B], alpha, tmp); + out[1] = MULDIV255(in[G], alpha, tmp); + out[2] = MULDIV255(in[R], alpha, tmp); + out += 4; in += 4; + } +} + static void packRGBL(UINT8* out, const UINT8* in, int pixels) { @@ -525,6 +544,7 @@ static struct { {"RGBA", "BGR", 24, ImagingPackBGR}, {"RGBA", "BGRA", 32, ImagingPackBGRA}, {"RGBA", "ABGR", 32, ImagingPackABGR}, + {"RGBA", "BGRa", 32, ImagingPackBGRa}, {"RGBA", "R", 8, band0}, {"RGBA", "G", 8, band1}, {"RGBA", "B", 8, band2}, diff --git a/libImaging/Unpack.c b/libImaging/Unpack.c index 702bc9f1f..8112afd8d 100644 --- a/libImaging/Unpack.c +++ b/libImaging/Unpack.c @@ -747,6 +747,30 @@ unpackRGBa(UINT8* out, const UINT8* in, int pixels) } } +static void +unpackBGRa(UINT8* out, const UINT8* in, int pixels) +{ + int i; + /* premultiplied BGRA */ + for (i = 0; i < pixels; i++) { + int a = in[3]; + if (!a) + out[R] = out[G] = out[B] = out[A] = 0; + else if (a == 255) { + out[R] = in[2]; + out[G] = in[1]; + out[B] = in[0]; + out[A] = a; + } else { + out[R] = CLIP(in[2] * 255 / a); + out[G] = CLIP(in[1] * 255 / a); + out[B] = CLIP(in[0] * 255 / a); + out[A] = a; + } + out += 4; in += 4; + } +} + static void unpackRGBAI(UINT8* out, const UINT8* in, int pixels) { @@ -1206,6 +1230,7 @@ static struct { {"RGBA", "LA;16B", 32, unpackRGBALA16B}, {"RGBA", "RGBA", 32, copy4}, {"RGBA", "RGBa", 32, unpackRGBa}, + {"RGBA", "BGRa", 32, unpackBGRa}, {"RGBA", "RGBA;I", 32, unpackRGBAI}, {"RGBA", "RGBA;L", 32, unpackRGBAL}, {"RGBA", "RGBA;15", 16, ImagingUnpackRGBA15},