cleanup
This commit is contained in:
parent
3fbdc87de4
commit
b8ff014e8c
|
@ -76,7 +76,6 @@ def _loadimg(im,blen=None):
|
|||
depth=im.depth
|
||||
# raw pixels
|
||||
# bytearray
|
||||
#pixels=im.make_blob()
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen)
|
||||
palette=b''
|
||||
|
||||
|
@ -91,113 +90,6 @@ def _loadimg(im,blen=None):
|
|||
|
||||
return geometry,bpp,depth,fmt,croplen,DataBuffer(pixels,palette)
|
||||
|
||||
def _loadimg2(im,blen=None):
|
||||
# load all useful and only useful infomation from Image object.
|
||||
# should called after Image.read() operation in the same process and thread.
|
||||
|
||||
# width, height, page width, page height, offset x, offset y
|
||||
# unsigned long long, 'Q', for very very large image
|
||||
width,height=im.size
|
||||
page_width,page_height,*offset=im.page
|
||||
geometry=width,height,(page_width or width),(page_height or height),*offset
|
||||
# bytes per pixel
|
||||
# unsigned char, 'B'
|
||||
bpp=im.bpp
|
||||
# bits per color
|
||||
# unsigned char, 'B'
|
||||
depth=im.depth
|
||||
# color format name
|
||||
# string
|
||||
fmt=im.fmt
|
||||
# raw pixels and palette, do override if needed.
|
||||
# color in palette should always be RGBA
|
||||
# bytes
|
||||
pixels=palette=b''
|
||||
|
||||
match (fmt,bpp,depth):
|
||||
|
||||
case ('GRAY',1,1):
|
||||
# override: (for low memory usage)
|
||||
# pixels and bpp*depth are ok, but generate palette and change fmt to INDEX.
|
||||
# palette only contains two color, black and white.
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
palette=bytes((0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff))
|
||||
fmt='INDEX'
|
||||
|
||||
case ('GRAY',1,8):
|
||||
# override: (for low memory usage)
|
||||
# generate palette from pixels, remap pixels and change fmt to INDEX
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
palette=tuple(sorted(set(pixels)))
|
||||
if len(palette)<0xff:
|
||||
# NOTE: only 8 depth GRAY could do remap in this way
|
||||
# (both pixel and index are 1 bytes char)
|
||||
pairs=((p,n) for n,p in enumerate(palette) if n!=p)
|
||||
pixels=pixels.translate(bytes.maketrans(*map(bytes,zip(*pairs))))
|
||||
palette=bytes(c for pixel in ((l,l,l,255) for l in palette) for c in pixel)
|
||||
fmt='INDEX'
|
||||
|
||||
case ('GRAYA',2,8):
|
||||
# override:
|
||||
# convert to 32 depth RGBA. no hack.
|
||||
# TODO: pass pixels as-is to ui process
|
||||
bpp=4
|
||||
fmt='RGBA'
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
|
||||
case ('INDEX',1,8):
|
||||
# override: (for low memory usage while acceptable performance)
|
||||
# generate palette from pixels and remap pixels.
|
||||
# avoid call ctype function in loop (such as im.color_map). that costs to much.
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt='RGBA')
|
||||
pixels=iter(pixels)
|
||||
pixels=tuple(map(bytes,zip(*(pixels,)*4))) # 4 color in each pixel
|
||||
palette=sorted(set(pixels))
|
||||
d={p:n for n,p in enumerate(palette)}
|
||||
pixels=bytes(d[p] for p in pixels)
|
||||
palette=b''.join(palette)
|
||||
|
||||
case ('RGB',3,8):
|
||||
# no override
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
case ('RGBA',4,8):
|
||||
# no override
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
|
||||
case ('CMYK',4,8):
|
||||
# override:
|
||||
# convert to 24 depth RGB. no hack.
|
||||
bpp=3
|
||||
fmt='RGB'
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
case ('CMYKA',5,8):
|
||||
# override:
|
||||
# convert to 24 depth RGB. no hack.
|
||||
bpp=4
|
||||
fmt='RGBA'
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
|
||||
case _:
|
||||
assert warn(__name__,'unknown pixel depth or color format:'
|
||||
f'{bpp=} {depth=} {fmt=}')
|
||||
bpp=4
|
||||
depth=im.depth=8
|
||||
fmt='RGBA'
|
||||
pixels,croplen=_makeblob(im,width,height,blen=blen,fmt=fmt)
|
||||
|
||||
length=len(pixels)
|
||||
size=width*height*bpp
|
||||
# assert: pixels amount
|
||||
assert length==size,f'pixel amount not match {length} {size}'
|
||||
# assert: provide RGBA palette only for INDEX color format
|
||||
if fmt=='INDEX':
|
||||
assert palette,'no palette with INDEX pixfmt'
|
||||
assert not len(palette)%4,'palette not in RGBA format'
|
||||
else:
|
||||
assert not palette,f'palette with {fmt} pixfmt'
|
||||
|
||||
return geometry,bpp,depth,fmt,croplen,DataBuffer(pixels,palette)
|
||||
|
||||
def py_padding_rgb24(pixels,width):
|
||||
src_pitch=width*3
|
||||
padding_len=(4-src_pitch)%4
|
||||
|
@ -427,7 +319,15 @@ def generator_Anime(im,options=None,shrink=None):
|
|||
assert trace(__name__,'generator_Anime: start')
|
||||
n_frames=im.iterator_length()
|
||||
first_size=None
|
||||
for n,frame in enumerate(im.iter_frames(),1):
|
||||
im.iterator_reset()
|
||||
n=0
|
||||
has_next=True
|
||||
while has_next:
|
||||
n+=1
|
||||
frame=im.image_get()
|
||||
if not im.iterator_next():
|
||||
im.close()
|
||||
has_next=False
|
||||
if n==1 and shrink is not None:
|
||||
# use value instead of reference
|
||||
first_size=im.width,im.height
|
||||
|
@ -446,10 +346,17 @@ def generator_Signle(im,options=None,shrink=None,blen=None):
|
|||
# generator of (0, 1) and image raw data
|
||||
assert (p:=Pref.start(name=f'{__name__}: generator'))
|
||||
assert trace(__name__,'generator: start')
|
||||
with im:
|
||||
if im.iterator_length()>1:
|
||||
# only load first frame
|
||||
im.iterator_reset()
|
||||
frame=im.image_get()
|
||||
im.close()
|
||||
assert p.record(name='get first frame')
|
||||
# frame will be closed by load_single_frame
|
||||
yield load_single_frame(im.image_get(),shrink=shrink,blen=blen)
|
||||
yield load_single_frame(frame,shrink=shrink,blen=blen)
|
||||
else:
|
||||
# image will be closed by load_single_frame
|
||||
yield load_single_frame(im,shrink=shrink,blen=blen)
|
||||
assert p.record(name='end')
|
||||
assert trace(__name__,'generator: end')
|
||||
assert p.log()
|
||||
|
|
|
@ -25,7 +25,7 @@ library.MagickIdentifyImageType.restype = c_int
|
|||
class Image(_Image):
|
||||
supported_formats=tuple(formats())
|
||||
_fmtmap={
|
||||
# format of image type, ignore 'alpha'/'matte' type
|
||||
# format of image type, ignore 'alpha'/'matte' in palette type
|
||||
'bilevel':'GRAY',
|
||||
'grayscale':'GRAY',
|
||||
'grayscalealpha':'GRAYA',
|
||||
|
@ -50,6 +50,11 @@ class Image(_Image):
|
|||
'CMYKA':5, # need verify
|
||||
}
|
||||
|
||||
def __new__(cls,*args,**kwds):
|
||||
instance=super().__new__(cls)
|
||||
instance._identified_type=None
|
||||
return instance
|
||||
|
||||
def __init__(self,*args,file=None,filename=None,blob=None,options=None,**kwds):
|
||||
blob_is_bytearray=isinstance(blob,bytearray)
|
||||
if not options and not blob_is_bytearray or \
|
||||
|
@ -68,9 +73,10 @@ class Image(_Image):
|
|||
else:
|
||||
self.read(file=file,filename=filename,blob=blob,**kwds)
|
||||
|
||||
identified_type=self.identified_type
|
||||
if identified_type!=self.type:
|
||||
if (identified_type:=self.identified_type)!=self.type:
|
||||
self.type=identified_type
|
||||
self.format=('RGBA' if self.alpha_channel else 'RGB') \
|
||||
if self.fmt=='INDEX' else self.fmt
|
||||
|
||||
@classmethod
|
||||
def ping(cls,file=None,filename=None,blob=None,**kwds):
|
||||
|
@ -93,9 +99,12 @@ class Image(_Image):
|
|||
@property
|
||||
def identified_type(self):
|
||||
# identified image type
|
||||
if index:=library.MagickIdentifyImageType(self.wand):
|
||||
return IMAGE_TYPES[index]
|
||||
self.raise_exception()
|
||||
if self._identified_type is None:
|
||||
if index:=library.MagickIdentifyImageType(self.wand):
|
||||
self._identified_type=IMAGE_TYPES[index]
|
||||
else:
|
||||
self.raise_exception()
|
||||
return self._identified_type
|
||||
|
||||
@property
|
||||
def fmt(self):
|
||||
|
@ -122,13 +131,6 @@ class Image(_Image):
|
|||
def clone(self):
|
||||
return Image(image=self)
|
||||
|
||||
def iter_frames(self):
|
||||
# iterator of each frame in animation
|
||||
self.iterator_reset()
|
||||
yield self.image_get()
|
||||
while self.iterator_next():
|
||||
yield self.image_get()
|
||||
|
||||
SUPPORTED_FORMATS=tuple(
|
||||
(f,bytes.fromhex('ff'*len(s) if m is None else m),s) for f,m,s in (
|
||||
('BMP', None, b'BM'),
|
||||
|
|
|
@ -503,7 +503,9 @@ class ENV(NonWidget):
|
|||
assert note(__name__,f'{self}: anime stop',prettypath(*path))
|
||||
self._animes.discard(path)
|
||||
return
|
||||
canvas=self.getcanvas(path)
|
||||
if (canvas:=self.getcanvas(path)) is None:
|
||||
self._animes.discard(path)
|
||||
return
|
||||
if not canvas.next_frame() and canvas.n_loop:
|
||||
loop_count+=1
|
||||
if loop_count>=canvas.n_loop:
|
||||
|
|
Loading…
Reference in New Issue