<s> import argparse <EOL> from collections import namedtuple <EOL> from PIL import Image , ImageDraw <EOL> import sys <EOL> BBox = namedtuple ( "<STR_LIT>" , '<STR_LIT>' ) <EOL> Regions = namedtuple ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> class BlockType : <EOL> OPAQUE = <NUM_LIT:1> <EOL> EMPTY = <NUM_LIT:2> <EOL> ALPHA = <NUM_LIT:3> <EOL> UNKNOWN = <NUM_LIT:4> <EOL> def BlockName ( block ) : <EOL> if block == BlockType . OPAQUE : <EOL> return "<STR_LIT>" <EOL> elif block == BlockType . EMPTY : <EOL> return "<STR_LIT>" <EOL> elif block == BlockType . ALPHA : <EOL> return "<STR_LIT>" <EOL> return "<STR_LIT>" <EOL> def Analyze ( im , bbox ) : <EOL> numalpha = <NUM_LIT:0> <EOL> numblank = <NUM_LIT:0> <EOL> numopaque = <NUM_LIT:0> <EOL> pixels = im . load ( ) <EOL> for y in range ( bbox . y , bbox . y + bbox . h ) : <EOL> for x in range ( bbox . x , bbox . x + bbox . w ) : <EOL> p = pixels [ x , y ] <EOL> if p [ <NUM_LIT:3> ] == <NUM_LIT:0> : <EOL> numblank += <NUM_LIT:1> <EOL> elif p [ <NUM_LIT:3> ] == <NUM_LIT:255> : <EOL> numopaque += <NUM_LIT:1> <EOL> else : <EOL> numalpha += <NUM_LIT:1> <EOL> if numalpha == <NUM_LIT:0> and numblank == <NUM_LIT:0> : <EOL> return BlockType . OPAQUE <EOL> elif numalpha == <NUM_LIT:0> and numopaque == <NUM_LIT:0> : <EOL> return BlockType . EMPTY <EOL> else : <EOL> return BlockType . ALPHA <EOL> class QuadTreeNode : <EOL> def __init__ ( self ) : <EOL> pass <EOL> def __init__ ( self , im , bbox = None , depth = <NUM_LIT:0> , blocksize = <NUM_LIT:32> ) : <EOL> if bbox == None : <EOL> bbox = BBox ( <NUM_LIT:0> , <NUM_LIT:0> , im . size [ <NUM_LIT:0> ] , im . size [ <NUM_LIT:1> ] ) <EOL> self . blocksize = blocksize <EOL> self . depth = depth <EOL> self . bbox = bbox <EOL> self . im = im <EOL> self . children = None <EOL> self . type = BlockType . UNKNOWN <EOL> if bbox . w > self . blocksize and bbox . h > self . blocksize : <EOL> childboxes = [ BBox ( bbox . x , bbox . y , bbox . w / <NUM_LIT:2> , bbox . h / <NUM_LIT:2> ) , <EOL> BBox ( bbox . x + bbox . w / <NUM_LIT:2> , bbox . y , bbox . w - bbox . w / <NUM_LIT:2> , bbox . h / <NUM_LIT:2> ) , <EOL> BBox ( bbox . x , bbox . y + bbox . h / <NUM_LIT:2> , bbox . w / <NUM_LIT:2> , bbox . h - bbox . h / <NUM_LIT:2> ) , <EOL> BBox ( bbox . x + bbox . w / <NUM_LIT:2> , bbox . y + bbox . h / <NUM_LIT:2> , bbox . w - bbox . w / <NUM_LIT:2> , bbox . h - bbox . h / <NUM_LIT:2> ) ] <EOL> childtypes = [ Analyze ( im , childboxes [ <NUM_LIT:0> ] ) , <EOL> Analyze ( im , childboxes [ <NUM_LIT:1> ] ) , <EOL> Analyze ( im , childboxes [ <NUM_LIT:2> ] ) , <EOL> Analyze ( im , childboxes [ <NUM_LIT:3> ] ) ] <EOL> same_type = childtypes [ <NUM_LIT:0> ] == childtypes [ <NUM_LIT:1> ] == childtypes [ <NUM_LIT:2> ] == childtypes [ <NUM_LIT:3> ] <EOL> last_div = bbox . w / <NUM_LIT:2> < self . blocksize or bbox . h / <NUM_LIT:2> < self . blocksize <EOL> if same_type and ( childtypes [ <NUM_LIT:0> ] != BlockType . ALPHA or last_div ) : <EOL> self . type = childtypes [ <NUM_LIT:0> ] <EOL> else : <EOL> self . children = ( <EOL> QuadTreeNode ( im , childboxes [ <NUM_LIT:0> ] , depth + <NUM_LIT:1> , self . blocksize ) , <EOL> QuadTreeNode ( im , childboxes [ <NUM_LIT:1> ] , depth + <NUM_LIT:1> , self . blocksize ) , <EOL> QuadTreeNode ( im , childboxes [ <NUM_LIT:2> ] , depth + <NUM_LIT:1> , self . blocksize ) , <EOL> QuadTreeNode ( im , childboxes [ <NUM_LIT:3> ] , depth + <NUM_LIT:1> , self . blocksize ) ) <EOL> if self . children and len ( self . children ) == <NUM_LIT:4> and self . children [ <NUM_LIT:0> ] . type == self . children [ <NUM_LIT:1> ] . type == self . children [ <NUM_LIT:2> ] . type == self . children [ <NUM_LIT:3> ] . type == BlockType . ALPHA : <EOL> self . children = None <EOL> self . type = BlockType . ALPHA <EOL> else : <EOL> self . type = Analyze ( im , bbox ) <EOL> def __repr__ ( self ) : <EOL> if self . children == None : <EOL> return "<STR_LIT:\t>" * self . depth + BlockName ( self . type ) + "<STR_LIT:U+0020>" + str ( self . bbox ) <EOL> else : <EOL> l = [ str ( x ) for x in self . children ] <EOL> return "<STR_LIT:\t>" * self . depth + "<STR_LIT>" + "<STR_LIT:\n>" . join ( l ) <EOL> def printme ( self ) : <EOL> print "<STR_LIT:\t>" * self . depth + BlockName ( self . type ) + "<STR_LIT:U+0020>" + str ( self . bbox ) <EOL> if self . children : <EOL> for child in self . children : <EOL> child . printme ( ) <EOL> def GetBBox ( self , fn ) : <EOL> if self . children != None : <EOL> ret = [ ] <EOL> for child in self . children : <EOL> op = child . GetBBox ( fn ) <EOL> if op != None : <EOL> ret . extend ( op ) <EOL> if len ( ret ) > <NUM_LIT:0> : <EOL> return ret <EOL> elif fn ( self ) : <EOL> return [ self . bbox ] <EOL> return [ ] <EOL> def doopt ( orig ) : <EOL> while True : <EOL> newlist = optlist ( orig ) <EOL> if len ( newlist ) == len ( orig ) : <EOL> return newlist <EOL> orig = newlist <EOL> def optlist ( orig ) : <EOL> newlist = [ ] <EOL> for o in orig : <EOL> added = False <EOL> for n in newlist : <EOL> if n . w == o . w and n . x == o . x and ( n . y + n . h == o . y or o . y + o . h == n . y ) : <EOL> newlist . remove ( n ) <EOL> newlist . append ( BBox ( n . x , min ( o . y , n . y ) , n . w , o . h + n . h ) ) <EOL> added = True <EOL> break <EOL> if n . h == o . h and n . y == o . y and ( n . x + n . w == o . x or o . x + o . w == n . x ) : <EOL> newlist . remove ( n ) <EOL> newlist . append ( BBox ( min ( o . x , n . x ) , n . y , n . w + o . w , o . h ) ) <EOL> added = True <EOL> break <EOL> if not added : <EOL> newlist . append ( o ) <EOL> return newlist <EOL> def GetImageRegions ( img , blocksize = <NUM_LIT:16> ) : <EOL> rootNode = QuadTreeNode ( img , None , <NUM_LIT:0> , blocksize ) <EOL> opaque = doopt ( sorted ( rootNode . GetBBox ( lambda x : x . type == BlockType . OPAQUE ) , key = lambda x : x . w * x . h , reverse = True ) ) <EOL> alpha = doopt ( sorted ( rootNode . GetBBox ( lambda x : x . type == BlockType . ALPHA ) , key = lambda x : x . w * x . h , reverse = True ) ) <EOL> return Regions ( alpha , opaque ) </s>
