From 2ecbcce4156c21b8a40a0c85c89c1b9f7cd33610 Mon Sep 17 00:00:00 2001 From: Arjen Nienhuis Date: Sat, 6 Aug 2016 10:54:58 +0200 Subject: [PATCH 1/5] add unpacking from BRGa --- Tests/test_lib_pack.py | 2 ++ libImaging/Unpack.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 461d0bf8e..5c2af8d04 100644 --- a/Tests/test_lib_pack.py +++ b/Tests/test_lib_pack.py @@ -122,7 +122,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/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}, From 124e42ade36c06931057789f4b2cf646c9cc65b3 Mon Sep 17 00:00:00 2001 From: Arjen Nienhuis Date: Sun, 7 Aug 2016 02:17:16 +0200 Subject: [PATCH 2/5] Improved error message for missing packer It's not that the raw mode does not exist. There is just no direct conversion. --- encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; } From 916ea9405278b2fb979da184c9ea65f8a96548f7 Mon Sep 17 00:00:00 2001 From: Arjen Nienhuis Date: Sun, 7 Aug 2016 15:34:45 +0200 Subject: [PATCH 3/5] Add packing from RGBA to BGRa --- Tests/test_mode_bgra.py | 23 +++++++++++++++++++++++ libImaging/Pack.c | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 Tests/test_mode_bgra.py diff --git a/Tests/test_mode_bgra.py b/Tests/test_mode_bgra.py new file mode 100644 index 000000000..331be4d93 --- /dev/null +++ b/Tests/test_mode_bgra.py @@ -0,0 +1,23 @@ +from helper import unittest, PillowTestCase + +from PIL import Image + + +class TestBGRa(PillowTestCase): + + def test_bgra(self): + RGBA_RED_50 = b'\xff\x00\x00\x80' # 50% red RGBA + BGRa_RED_50 = b'\x00\x00\x80\x80' # 50% red BGRa + RGBa_RED_50 = b'\x80\x00\x00\x80' # 50% red RGBa + + im = Image.frombuffer("RGBA", (1, 1), BGRa_RED_50, "raw", "BGRa", 4, 1) + self.assertEqual(im.tobytes(), RGBA_RED_50) + self.assertEqual(im.tobytes('raw', 'BGRa'), BGRa_RED_50) + + im = Image.frombuffer("RGBa", (1, 1), BGRa_RED_50, "raw", "BGRa", 4, 1) + self.assertEqual(im.tobytes(), RGBa_RED_50) + self.assertEqual(im.tobytes('raw', 'BGRa'), BGRa_RED_50) + + +if __name__ == '__main__': + unittest.main() diff --git a/libImaging/Pack.c b/libImaging/Pack.c index d83cb8284..acbfc8143 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}, From 28ede3a3272126907626d6c4d0a8ce00ccea39d5 Mon Sep 17 00:00:00 2001 From: Arjen Nienhuis Date: Mon, 8 Aug 2016 00:07:08 +0200 Subject: [PATCH 4/5] Merged BGRa test into Tests/test_lib_pack.py --- Tests/test_lib_pack.py | 8 +++++--- Tests/test_mode_bgra.py | 23 ----------------------- 2 files changed, 5 insertions(+), 26 deletions(-) delete mode 100644 Tests/test_mode_bgra.py diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py index 5c2af8d04..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]) diff --git a/Tests/test_mode_bgra.py b/Tests/test_mode_bgra.py deleted file mode 100644 index 331be4d93..000000000 --- a/Tests/test_mode_bgra.py +++ /dev/null @@ -1,23 +0,0 @@ -from helper import unittest, PillowTestCase - -from PIL import Image - - -class TestBGRa(PillowTestCase): - - def test_bgra(self): - RGBA_RED_50 = b'\xff\x00\x00\x80' # 50% red RGBA - BGRa_RED_50 = b'\x00\x00\x80\x80' # 50% red BGRa - RGBa_RED_50 = b'\x80\x00\x00\x80' # 50% red RGBa - - im = Image.frombuffer("RGBA", (1, 1), BGRa_RED_50, "raw", "BGRa", 4, 1) - self.assertEqual(im.tobytes(), RGBA_RED_50) - self.assertEqual(im.tobytes('raw', 'BGRa'), BGRa_RED_50) - - im = Image.frombuffer("RGBa", (1, 1), BGRa_RED_50, "raw", "BGRa", 4, 1) - self.assertEqual(im.tobytes(), RGBa_RED_50) - self.assertEqual(im.tobytes('raw', 'BGRa'), BGRa_RED_50) - - -if __name__ == '__main__': - unittest.main() From 299713313ae80e62f62d1b83fa35bb9a9c4b0b84 Mon Sep 17 00:00:00 2001 From: Arjen Nienhuis Date: Mon, 8 Aug 2016 00:09:55 +0200 Subject: [PATCH 5/5] Fixed whitespace issue --- libImaging/Pack.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libImaging/Pack.c b/libImaging/Pack.c index acbfc8143..a19252e88 100644 --- a/libImaging/Pack.c +++ b/libImaging/Pack.c @@ -325,12 +325,12 @@ 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; + 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; } }