-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_transparent
executable file
·114 lines (75 loc) · 3.68 KB
/
check_transparent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python2.6
import cStringIO, datetime, os, glob, re, subprocess, sys
from optparse import OptionParser
from alppng import *
def my_exec( cmd, no_assert = False ):
pipe = subprocess.Popen( ( cmd if isinstance( cmd, str ) else ' '.join( cmd ) ),
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE )
ret = ( pipe.stdout.read(), pipe.stderr.read(), pipe.wait(), )
if not no_assert:
assert ret[2] == 0
return ret
def main( argv ):
parser = OptionParser(usage="""usage: %prog file
Examples:
check_transparent <filename>
Checks if a png image file contains some transparency.
Returns 1 if yes, 0 otherwise.
""")
(options, args) = parser.parse_args()
argc = len( args )
if argc == 0:
parser.print_help()
sys.exit(1)
filename = args[ 0 ]
png = alppng.Png( filename )
ihdr = alppng.Png_get_ihdr_chunk( png )
npixels = ihdr[ alppng.WIDTH ] * ihdr[ alppng.HEIGHT ]
try:
b = alppng.Png_has_plte_index_and_is_transparent( png )
if b == True: # Transparent
sys.exit(1)
if b == False: # Opaque
sys.exit(0)
except AssertionError, e: # e.g. when filter_type != 0 (rare)
pass
# At this point, ALPPNG says : "may be opaque, may be transparent, I do not know".
IDENTIFY = '/usr/bin/identify'
if not os.path.exists( IDENTIFY ):
r = my_exec( '/usr/bin/which identify' )
IDENTIFY = ( r[0] if ( r[2] == 0 ) else None )
rx_alpha = re.compile( '^\s*[Aa]lpha\s*:\s*(\d+)-bit\W', re.MULTILINE | re.IGNORECASE )
# Try the fallback: Image Magick
if not IDENTIFY:
sys.exit(0)
out,err,code = my_exec( IDENTIFY + ' -verbose ' + filename, True )
if code != 0:
sys.exit(0)
mo_alpha = rx_alpha.search( out )
if mo_alpha == None:
# Image Magick says: is opaque.
sys.exit(0)
# Now we are sure that the image has an alpha channel.
# Let us check the histogram first, maybe we can say right away that the image is fully transparent.
rx_full_transp = re.compile( r'Histogram\s*:[\s\r\n]*{npixels}\s*:\s+\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*0\s*\)\s+#[a-zA-Z0-9]{{6,6}}00\s+'.format( **vars() ) )
if None == rx_full_transp.search( out ):
# Now let us check the rest of the information, to detect non-transparent pixels.
rx_alpha_opaque_1bit = re.compile( '^[\s\r\n]*Alpha[\s\r\n]*:[\s\r\n]*min[\s\r\n]*:[\s\r\n]*0[\s\r\n]*\(0\)[\s\r\n]*max[\s\r\n]*:[\s\r\n]*0[\s\r\n]*\(0\)[\s\r\n]+', re.MULTILINE | re.IGNORECASE )
rx_alpha_opaque = re.compile( '^[\s\r\n]*Alpha[\s\r\n]*:[\s\r\n]*min[\s\r\n]*:[\s\r\n]*255[\s\r\n]*\(1\)[\s\r\n]*max[\s\r\n]*:[\s\r\n]*255[\s\r\n]*\(1\)[\s\r\n]+', re.MULTILINE | re.IGNORECASE )
rx_alpha_opaque_2 = re.compile( '^[\s\r\n]*Opacity[\s\r\n]*:[\s\r\n]*min[\s\r\n]*:[\s\r\n]*0[\s\r\n]*\(0\)[\s\r\n]*max[\s\r\n]*:[\s\r\n]*0[\s\r\n]*\(0\)[\s\r\n]+', re.MULTILINE | re.IGNORECASE )
im_says_opaque = False
if mo_alpha.group(1) == '1': # 1-bit case
im_says_opaque = rx_alpha_opaque_1bit.search( out ) != None
if not im_says_opaque:
im_says_opaque = (rx_alpha_opaque.search( out ) != None) or (rx_alpha_opaque_2.search( out ) != None)
if im_says_opaque:
# Image Magick says: has opaque content.
# (has alpha channel with: min = max = 255
# or opacity with: min = max = 0).
sys.exit(0)
sys.exit(1)
if __name__ == '__main__':
main( sys.argv )