add hardlight and softlight chops

This commit is contained in:
Dag Wästberg 2019-11-22 14:03:59 +01:00 committed by Andrew Murray
parent 2d4b4576aa
commit 5e5dfbad81
5 changed files with 104 additions and 10 deletions

View File

@ -38,6 +38,9 @@ def test_sanity():
ImageChops.blend(im, im, 0.5)
ImageChops.composite(im, im, im)
ImageChops.softlight(im, im)
ImageChops.hardlight(im, im)
ImageChops.offset(im, 10)
ImageChops.offset(im, 10, 20)
@ -319,9 +322,9 @@ def test_subtract_scale_offset():
# Act
new = ImageChops.subtract(im1, im2, scale=2.5, offset=100)
# Assert
assert new.getbbox() == (0, 0, 100, 100)
assert new.getpixel((50, 50)) == (100, 202, 100)
# Assert
assert new.getbbox() == (0, 0, 100, 100)
assert new.getpixel((50, 50)) == (100, 202, 100)
def test_subtract_clip():
@ -332,8 +335,8 @@ def test_subtract_clip():
# Act
new = ImageChops.subtract(im1, im2)
# Assert
assert new.getpixel((50, 50)) == (0, 0, 127)
# Assert
assert new.getpixel((50, 50)) == (0, 0, 127)
def test_subtract_modulo():
@ -344,10 +347,10 @@ def test_subtract_modulo():
# Act
new = ImageChops.subtract_modulo(im1, im2)
# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
def test_subtract_modulo_no_clip():
@ -358,8 +361,34 @@ def test_subtract_modulo_no_clip():
# Act
new = ImageChops.subtract_modulo(im1, im2)
# Assert
assert new.getpixel((50, 50)) == (241, 167, 127)
def test_softlight(self):
# Arrange
im1 = Image.open("Tests/images/hopper.png")
im2 = Image.open("Tests/images/hopper-XYZ.png")
# Act
new = ImageChops.softlight(im1, im2)
# Assert
assert new.getpixel((50, 50)) == (241, 167, 127)
self.assertEqual(new.getpixel((64, 64)), (163, 54, 32))
self.assertEqual(new.getpixel((15, 100)), (1, 1, 3))
def test_hardlight(self):
# Arrange
im1 = Image.open("Tests/images/hopper.png")
im2 = Image.open("Tests/images/hopper-XYZ.png")
# Act
new = ImageChops.hardlight(im1, im2)
# Assert
self.assertEqual(new.getpixel((64, 64)), (144, 50, 27))
self.assertEqual(new.getpixel((15, 100)), (1, 1, 2))
def test_logical():

View File

@ -138,6 +138,27 @@ def screen(image1, image2):
image2.load()
return image1._new(image1.im.chop_screen(image2.im))
def softlight(image1, image2):
"""
Superimposes two images on top of each other using the Soft Light algorithm
:rtype: :py:class:`~PIL.Image.Image`
"""
image1.load()
image2.load()
return image1._new(image1.im.chop_softlight(image2.im))
def hardlight(image1, image2):
"""
Superimposes two images on top of each other using the Hard Light algorithm
:rtype: :py:class:`~PIL.Image.Image`
"""
image1.load()
image2.load()
return image1._new(image1.im.chop_hardlight(image2.im))
def add(image1, image2, scale=1.0, offset=0):
"""

View File

@ -2406,6 +2406,27 @@ _chop_subtract_modulo(ImagingObject* self, PyObject* args)
return PyImagingNew(ImagingChopSubtractModulo(self->image, imagep->image));
}
static PyObject*
_chop_softlight(ImagingObject* self, PyObject* args)
{
ImagingObject* imagep;
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
return NULL;
return PyImagingNew(ImagingChopSoftLight(self->image, imagep->image));
}
static PyObject*
_chop_hardlight(ImagingObject* self, PyObject* args)
{
ImagingObject* imagep;
if (!PyArg_ParseTuple(args, "O!", &Imaging_Type, &imagep))
return NULL;
return PyImagingNew(ImagingChopHardLight(self->image, imagep->image));
}
#endif
@ -3325,6 +3346,9 @@ static struct PyMethodDef methods[] = {
{"chop_and", (PyCFunction)_chop_and, 1},
{"chop_or", (PyCFunction)_chop_or, 1},
{"chop_xor", (PyCFunction)_chop_xor, 1},
{"chop_softlight", (PyCFunction)_chop_softlight, 1},
{"chop_hardlight", (PyCFunction)_chop_hardlight, 1},
#endif
#ifdef WITH_UNSHARPMASK

View File

@ -146,3 +146,21 @@ ImagingChopSubtractModulo(Imaging imIn1, Imaging imIn2)
{
CHOP2(in1[x] - in2[x], NULL);
}
Imaging
ImagingChopSoftLight(Imaging imIn1, Imaging imIn2)
{
// CHOP2( ( ( (255-in1[x]) * (in1[x]*in2[x]) ) / 65536) +
// ((in1[x] * (255 - ((255 - in1[1]) * (255 - in2[x]) / 255 ) )) / 255), NULL );
CHOP2( (((255-in1[x]) * (in1[x]*in2[x]) ) / 65536) +
(in1[x] * ( 255 - ( (255 - in1[x]) * (255 - in2[x] ) / 255) )) / 255
, NULL );
}
Imaging
ImagingChopHardLight(Imaging imIn1, Imaging imIn2)
{
CHOP2( (in2[x]<128) ? ( (in1[x]*in2[x])/127)
: 255 - ( ((255-in2[x]) * (255-in1[x])) / 127)
, NULL);
}

View File

@ -339,6 +339,8 @@ extern Imaging ImagingChopSubtract(
Imaging imIn1, Imaging imIn2, float scale, int offset);
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);
/* "1" images only */
extern Imaging ImagingChopAnd(Imaging imIn1, Imaging imIn2);