improve upon premultiplied alpha tests in a51678d307
This commit is contained in:
parent
9a51b31e01
commit
6aa9043352
1 changed files with 97 additions and 33 deletions
|
@ -11,49 +11,77 @@ def setup():
|
|||
# from another directory we need to chdir()
|
||||
os.chdir(execution_path('.'))
|
||||
|
||||
def validate_pixels_are_demultiplied(image):
|
||||
bad_pixels = []
|
||||
def is_pre(color,alpha):
|
||||
return (color*255.0/alpha) <= 255
|
||||
|
||||
def debug_image(image,step=2):
|
||||
for x in range(0,image.width(),step):
|
||||
for y in range(0,image.height(),step):
|
||||
pixel = image.get_pixel(x,y)
|
||||
alpha = (pixel >> 24) & 0xff
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
print "rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y)
|
||||
|
||||
# note: it is impossible to know for all pixel colors
|
||||
# we can only detect likely cases of non premultiplied colors
|
||||
def validate_pixels_are_not_premultiplied(image):
|
||||
over_alpha = False
|
||||
transparent = True
|
||||
fully_opaque = True
|
||||
for x in range(0,image.width(),2):
|
||||
for y in range(0,image.height(),2):
|
||||
pixel = image.get_pixel(x,y)
|
||||
r = pixel & 0xff
|
||||
g = (pixel >> 8) & 0xff
|
||||
b = (pixel >> 16) & 0xff
|
||||
a = (pixel >> 24) & 0xff
|
||||
is_valid = (r >=0 and r < 256) and \
|
||||
(g >=0 and g < 256) and \
|
||||
(b >=0 and b < 256) and \
|
||||
(a >=0 and a < 256)
|
||||
if not is_valid:
|
||||
bad_pixels.append("rgba(%s,%s,%s,%s) at %s,%s" % (r,g,b,a,x,y))
|
||||
num_bad = len(bad_pixels)
|
||||
return (num_bad == 0,num_bad)
|
||||
alpha = (pixel >> 24) & 0xff
|
||||
if alpha > 0:
|
||||
transparent = False
|
||||
if alpha < 255:
|
||||
fully_opaque = False
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
color_max = max(red,green,blue)
|
||||
if color_max > alpha:
|
||||
over_alpha = True
|
||||
return over_alpha or transparent or fully_opaque
|
||||
|
||||
def validate_pixels_are_not_premultiplied2(image):
|
||||
looks_not_multiplied = False
|
||||
for x in range(0,image.width(),2):
|
||||
for y in range(0,image.height(),2):
|
||||
pixel = image.get_pixel(x,y)
|
||||
alpha = (pixel >> 24) & 0xff
|
||||
#each value of the color channels will never be bigger than that of the alpha channel.
|
||||
if alpha > 0:
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
if red > 0 and red > alpha:
|
||||
print 'red: %s, a: %s' % (red,alpha)
|
||||
looks_not_multiplied = True
|
||||
return looks_not_multiplied
|
||||
|
||||
def validate_pixels_are_premultiplied(image):
|
||||
bad_pixels = []
|
||||
for x in range(0,image.width(),2):
|
||||
for y in range(0,image.height(),2):
|
||||
pixel = image.get_pixel(x,y)
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
alpha = (pixel >> 24) & 0xff
|
||||
a2 = alpha
|
||||
if a2 == 0:
|
||||
a2 = 1
|
||||
else:
|
||||
a2 = a2*256
|
||||
is_valid = (red >=0 and red/a2 < 256) and \
|
||||
(green >=0 and red/a2 < 256) and \
|
||||
(blue >=0 and red/a2 < 256) and \
|
||||
(alpha >=0 and alpha < 256)
|
||||
if not is_valid:
|
||||
import pdb;pdb.set_trace()
|
||||
bad_pixels.append("rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y))
|
||||
if alpha > 0:
|
||||
pixel = image.get_pixel(x,y)
|
||||
red = pixel & 0xff
|
||||
green = (pixel >> 8) & 0xff
|
||||
blue = (pixel >> 16) & 0xff
|
||||
is_valid = ((0 <= red <= alpha) and is_pre(red,alpha)) \
|
||||
and ((0 <= green <= alpha) and is_pre(green,alpha)) \
|
||||
and ((0 <= blue <= alpha) and is_pre(blue,alpha)) \
|
||||
and (alpha >= 0 and alpha <= 255)
|
||||
if not is_valid:
|
||||
bad_pixels.append("rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y))
|
||||
num_bad = len(bad_pixels)
|
||||
return (num_bad == 0,bad_pixels)
|
||||
|
||||
|
||||
def test_compare_images():
|
||||
b = mapnik.Image.open('./images/support/b.png')
|
||||
b.premultiply()
|
||||
|
@ -67,9 +95,8 @@ def test_compare_images():
|
|||
if not valid[0]:
|
||||
print '%s not validly pre-:\n\t%s pixels (%s)' % (name,len(valid[1]),valid[1][0])
|
||||
a.demultiply()
|
||||
valid = validate_pixels_are_demultiplied(a)
|
||||
if not valid[0]:
|
||||
print '%s not validly de-:\n\t%s pixels (%s)' % (name,len(valid[1]),valid[1][0])
|
||||
if not validate_pixels_are_not_premultiplied(a):
|
||||
print '%s not validly demultiplied' % (name)
|
||||
a.save(actual)
|
||||
expected_im = mapnik.Image.open(expected)
|
||||
# compare them
|
||||
|
@ -81,6 +108,43 @@ def test_compare_images():
|
|||
#b.save('/tmp/mapnik-comp-op-test-original-mask.png')
|
||||
#eq_(b.tostring(),expected_b.tostring(), '/tmp/mapnik-comp-op-test-original-mask.png is no longer equivalent to original mask: ./images/support/b.png')
|
||||
|
||||
def test_pre_multiply_status():
|
||||
b = mapnik.Image.open('./images/support/b.png')
|
||||
# not premultiplied yet, should appear that way
|
||||
result = validate_pixels_are_not_premultiplied(b)
|
||||
eq_(result,True)
|
||||
# not yet premultiplied therefore should return false
|
||||
result = validate_pixels_are_premultiplied(b)
|
||||
eq_(result[0],False)
|
||||
# now actually premultiply the pixels
|
||||
b.premultiply()
|
||||
# now checking if premultiplied should succeed
|
||||
result = validate_pixels_are_premultiplied(b)
|
||||
eq_(result[0],True)
|
||||
# should now not appear to look not premultiplied
|
||||
result = validate_pixels_are_not_premultiplied(b)
|
||||
eq_(result,False)
|
||||
# now actually demultiply the pixels
|
||||
b.demultiply()
|
||||
# should now appear demultiplied
|
||||
result = validate_pixels_are_not_premultiplied(b)
|
||||
eq_(result,True)
|
||||
|
||||
def test_pre_multiply_status_of_map1():
|
||||
m = mapnik.Map(256,256)
|
||||
im = mapnik.Image(m.width,m.height)
|
||||
eq_(validate_pixels_are_not_premultiplied(im),True)
|
||||
mapnik.render(m,im)
|
||||
eq_(validate_pixels_are_not_premultiplied(im),True)
|
||||
|
||||
def test_pre_multiply_status_of_map2():
|
||||
m = mapnik.Map(256,256)
|
||||
m.background = mapnik.Color(1,1,1,255)
|
||||
im = mapnik.Image(m.width,m.height)
|
||||
eq_(validate_pixels_are_not_premultiplied(im),True)
|
||||
mapnik.render(m,im)
|
||||
eq_(validate_pixels_are_not_premultiplied(im),True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
setup()
|
||||
|
|
Loading…
Reference in a new issue