Skip to content

Commit

Permalink
Merge cf66ae5 into 1c5f2a4
Browse files Browse the repository at this point in the history
  • Loading branch information
fflewddur committed Apr 28, 2015
2 parents 1c5f2a4 + cf66ae5 commit 1a1099e
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
55 changes: 54 additions & 1 deletion tests/image_test.py
Expand Up @@ -15,7 +15,7 @@
from wand.compat import PY3, string_type, text, text_type
from wand.exceptions import MissingDelegateError
from wand.font import Font

from wand.version import QUANTUM_DEPTH

try:
filesystem_encoding = sys.getfilesystemencoding()
Expand Down Expand Up @@ -1248,6 +1248,59 @@ def test_normalize_channel(fx_asset):
assert getattr(img[-1, 0], c) == getattr(right_top, c)
assert getattr(img[-1, -1], c) == getattr(right_bottom, c)

def test_level_default(fx_asset):
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust the levels to make this image entirely black
img.level(1, 1)
with img[0, 0] as dark:
assert dark.red_int8 <= dark.green_int8 <= dark.blue_int8 <= 0
with img[0, -1] as dark:
assert dark.red_int8 <= dark.green_int8 <= dark.blue_int8 <= 0
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust the levels to make this image entirely white
img.level(0, 0)
with img[0, 0] as light:
assert light.red_int8 >= light.green_int8 >= light.blue_int8 >= 255
with img[0, -1] as light:
assert light.red_int8 >= light.green_int8 >= light.blue_int8 >= 255
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust the image's gamma to darken its midtones
img.level(0, 1, 0.5)
with img[0, len(img) // 2] as light:
assert light.red_int8 <= light.green_int8 <= light.blue_int8 <= 65
assert light.red_int8 >= light.green_int8 >= light.blue_int8 >= 60
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust the image's gamma to lighten its midtones
img.level(0, 1, 2.5)
with img[0, len(img) // 2] as light:
assert light.red_int8 <= light.green_int8 <= light.blue_int8 <= 195
assert light.red_int8 >= light.green_int8 >= light.blue_int8 >= 190

def test_level_channel(fx_asset):
for chan in ('red', 'green', 'blue'):
c = chan + '_int8'
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust each channel level to make it entirely black
img.level(1, 1, channel=chan)
assert(getattr(img[0, 0], c) <= 0)
assert(getattr(img[0, -1], c) <= 0)
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust each channel level to make it entirely white
img.level(0, 0, channel=chan)
assert(getattr(img[0, 0], c) >= 255)
assert(getattr(img[0, -1], c) >= 255)
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust each channel's gamma to darken its midtones
img.level(0, 1, 0.5, chan)
with img[0, len(img) // 2] as light:
assert(getattr(light, c) <= 65)
assert(getattr(light, c) >= 60)
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
# Adjust each channel's gamma to lighten its midtones
img.level(0, 1, 2.5, chan)
with img[0, len(img) // 2] as light:
assert(getattr(light, c) >= 190)
assert(getattr(light, c) <= 195)

def test_equalize(fx_asset):
with Image(filename=str(fx_asset.join('gray_range.jpg'))) as img:
Expand Down
11 changes: 11 additions & 0 deletions wand/api.py
Expand Up @@ -473,6 +473,17 @@ class AffineMatrix(ctypes.Structure):

library.MagickSetImageType.argtypes = [ctypes.c_void_p, ctypes.c_int]

library.MagickLevelImage.argtypes = [ctypes.c_void_p,
ctypes.c_double,
ctypes.c_double,
ctypes.c_double]

library.MagickLevelImageChannel.argtypes = [ctypes.c_void_p,
ctypes.c_int,
ctypes.c_double,
ctypes.c_double,
ctypes.c_double]

library.MagickEvaluateImageChannel.argtypes = [ctypes.c_void_p,
ctypes.c_int,
ctypes.c_int,
Expand Down
38 changes: 38 additions & 0 deletions wand/image.py
Expand Up @@ -2127,6 +2127,44 @@ def clear(self):
"""
library.ClearMagickWand(self.wand)

def level(self, black=0.0, white=1.0, gamma=1.0, channel=None):
"""Adjusts the levels of an image by scaling the colors falling
between specified black and white points to the full available
quantum range.
:param black: Black point, as a percentage of the system's quantum
range. Defaults to 0.
:type black: :class:`numbers.Real`
:param white: White point, as a percentage of the system's quantum
range. Defaults to 1.0.
:type white: :class:`numbers.Real`
:param gamma: Optional gamma adjustment. Values > 1.0 lighten the
image's midtones while values < 1.0 darken them.
:type gamma: :class:`numbers.Real`
:param channel: The channel type. Available values can be found
in the :const:`CHANNELS` mapping. If ``None``,
normalize all channels.
:type channel: :class:`basestring`
.. versionadded:: 0.4.1
"""

bp = float(self.quantum_range * black)
wp = float(self.quantum_range * white)
if channel:
try:
ch_const = CHANNELS[channel]
except KeyError:
raise ValueError(repr(channel) + ' is an invalid channel type'
'; see wand.image.CHANNELS dictionary')
r = library.MagickLevelImageChannel(self.wand, ch_const, bp, gamma, wp)
else:
r = library.MagickLevelImage(self.wand, bp, gamma, wp)

if not r:
self.raise_exception()

@property
def format(self):
"""(:class:`basestring`) The image format.
Expand Down

0 comments on commit 1a1099e

Please sign in to comment.