From 13c1b7070d26d0cc76eab802a85e4024ef1485c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag=20W=C3=A4stberg?= Date: Fri, 22 Nov 2019 14:30:43 +0100 Subject: [PATCH] add Overlay chop --- Tests/test_imagechops.py | 14 ++++++++++++++ docs/reference/ImageChops.rst | 1 + src/PIL/ImageChops.py | 11 +++++++++++ src/_imaging.c | 12 ++++++++++++ src/libImaging/Chops.c | 8 ++++++++ src/libImaging/Imaging.h | 1 + 6 files changed, 47 insertions(+) diff --git a/Tests/test_imagechops.py b/Tests/test_imagechops.py index 82e469cc1..cfdf9365d 100644 --- a/Tests/test_imagechops.py +++ b/Tests/test_imagechops.py @@ -40,6 +40,7 @@ def test_sanity(): ImageChops.softlight(im, im) ImageChops.hardlight(im, im) + ImageChops.overlay(im, im) ImageChops.offset(im, 10) ImageChops.offset(im, 10, 20) @@ -391,6 +392,19 @@ def test_hardlight(self): self.assertEqual(new.getpixel((15, 100)), (1, 1, 2)) +def test_overlay(self): + # Arrange + im1 = Image.open("Tests/images/hopper.png") + im2 = Image.open("Tests/images/hopper-XYZ.png") + + # Act + new = ImageChops.overlay(im1, im2) + + # Assert + self.assertEqual(new.getpixel((64, 64)), (159, 50, 27)) + self.assertEqual(new.getpixel((15, 100)), (1, 1, 2)) + + def test_logical(): def table(op, a, b): out = [] diff --git a/docs/reference/ImageChops.rst b/docs/reference/ImageChops.rst index d9b14002d..31142cc3f 100644 --- a/docs/reference/ImageChops.rst +++ b/docs/reference/ImageChops.rst @@ -38,6 +38,7 @@ operations in this module). .. autofunction:: PIL.ImageChops.multiply .. autofunction:: PIL.ImageChops.softlight .. autofunction:: PIL.ImageChops.hardlight +.. autofunction:: PIL.ImageChops.overlay .. py:method:: PIL.ImageChops.offset(image, xoffset, yoffset=None) Returns a copy of the image where data has been offset by the given diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index d33186fb2..bfc6e80d8 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -160,6 +160,17 @@ def hardlight(image1, image2): image2.load() return image1._new(image1.im.chop_hardlight(image2.im)) +def overlay(image1, image2): + """ + Superimposes two images on top of each other using the Overlay algorithm + + :rtype: :py:class:`~PIL.Image.Image` + """ + + image1.load() + image2.load() + return image1._new(image1.im.chop_overlay(image2.im)) + def add(image1, image2, scale=1.0, offset=0): """ Adds two images, dividing the result by scale and adding the diff --git a/src/_imaging.c b/src/_imaging.c index c146a975f..7875ae278 100644 --- a/src/_imaging.c +++ b/src/_imaging.c @@ -2427,6 +2427,17 @@ _chop_hardlight(ImagingObject* self, PyObject* args) return PyImagingNew(ImagingChopHardLight(self->image, imagep->image)); } + +static PyObject* +_chop_overlay(ImagingObject* self, PyObject* args) +{ + ImagingObject* imagep; + + if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep)) + return NULL; + + return PyImagingNew(ImagingOverlay(self->image, imagep->image)); +} #endif @@ -3348,6 +3359,7 @@ static struct PyMethodDef methods[] = { {"chop_xor", (PyCFunction)_chop_xor, 1}, {"chop_softlight", (PyCFunction)_chop_softlight, 1}, {"chop_hardlight", (PyCFunction)_chop_hardlight, 1}, + {"chop_overlay", (PyCFunction)_chop_overlay, 1}, #endif diff --git a/src/libImaging/Chops.c b/src/libImaging/Chops.c index 302a8c2b9..cbd65b196 100644 --- a/src/libImaging/Chops.c +++ b/src/libImaging/Chops.c @@ -163,4 +163,12 @@ ImagingChopHardLight(Imaging imIn1, Imaging imIn2) CHOP2( (in2[x]<128) ? ( (in1[x]*in2[x])/127) : 255 - ( ((255-in2[x]) * (255-in1[x])) / 127) , NULL); +} + +Imaging +ImagingOverlay(Imaging imIn1, Imaging imIn2) +{ + CHOP2( (in1[x]<128) ? ( (in1[x]*in2[x])/127) + : 255 - ( ((255-in1[x]) * (255-in2[x])) / 127) + , NULL); } \ No newline at end of file diff --git a/src/libImaging/Imaging.h b/src/libImaging/Imaging.h index 99ce6d6d6..9032fcf07 100644 --- a/src/libImaging/Imaging.h +++ b/src/libImaging/Imaging.h @@ -341,6 +341,7 @@ extern Imaging ImagingChopAddModulo(Imaging imIn1, Imaging imIn2); extern Imaging ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2); extern Imaging ImagingChopSoftLight(Imaging imIn1, Imaging imIn2); extern Imaging ImagingChopHardLight(Imaging imIn1, Imaging imIn2); +extern Imaging ImagingOverlay(Imaging imIn1, Imaging imIn2); /* "1" images only */ extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2);