mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
reorganized gif optimize to work with palette parameter
This commit is contained in:
parent
b9ab3f5bf4
commit
c9df9d0b23
|
@ -343,70 +343,71 @@ def getheader(im, palette=None, info=None):
|
|||
|
||||
optimize = info and info.get("optimize", 0)
|
||||
|
||||
# start of header
|
||||
# Header Block
|
||||
# http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
|
||||
header = [
|
||||
b"GIF87a" + # magic
|
||||
o16(im.size[0]) + # size
|
||||
o16(im.size[1])
|
||||
b"GIF87a" + # signature + version
|
||||
o16(im.size[0]) + # canvas width
|
||||
o16(im.size[1]) # canvas height
|
||||
]
|
||||
|
||||
# if the user adds a palette, use it
|
||||
usedPaletteColors = None
|
||||
|
||||
if palette is not None and isinstance(palette, bytes):
|
||||
paletteBytes = palette[:768]
|
||||
if im.mode == "P":
|
||||
if palette and isinstance(palette, bytes):
|
||||
sourcePalette = palette[:768]
|
||||
else:
|
||||
usedPaletteColors = []
|
||||
sourcePalette = im.im.getpalette("RGB")[:768]
|
||||
else: # L-mode
|
||||
sourcePalette = bytearray([i//3 for i in range(768)])
|
||||
|
||||
usedPaletteColors = paletteBytes = None
|
||||
|
||||
if optimize:
|
||||
# minimize color palette if wanted
|
||||
usedPaletteColors = []
|
||||
|
||||
# check which colors are used
|
||||
i = 0
|
||||
for count in im.histogram():
|
||||
if count:
|
||||
usedPaletteColors.append(i)
|
||||
i += 1
|
||||
|
||||
countUsedPaletteColors = len(usedPaletteColors)
|
||||
|
||||
# create the global palette
|
||||
if im.mode == "P":
|
||||
# colour palette
|
||||
if countUsedPaletteColors > 0 and countUsedPaletteColors < 256:
|
||||
# create the new palette if not every color is used
|
||||
if len(usedPaletteColors) < 256:
|
||||
paletteBytes = b"";
|
||||
|
||||
if im.mode == "P":
|
||||
# pick only the used colors from the palette
|
||||
for i in usedPaletteColors:
|
||||
paletteBytes += im.im.getpalette("RGB")[i*3:i*3+3]
|
||||
paletteBytes += sourcePalette[i*3:i*3+3]
|
||||
else:
|
||||
paletteBytes = im.im.getpalette("RGB")[:768]
|
||||
else:
|
||||
# greyscale
|
||||
if countUsedPaletteColors > 0 and countUsedPaletteColors < 256:
|
||||
paletteBytes = b"";
|
||||
# add only the used grayscales to the palette
|
||||
for i in usedPaletteColors:
|
||||
paletteBytes += o8(i)*3
|
||||
else :
|
||||
paletteBytes = bytearray([i//3 for i in range(768)])
|
||||
|
||||
# TODO improve this, maybe add numpy support
|
||||
# replace the palette color id of all pixel with the new id
|
||||
if countUsedPaletteColors > 0 and countUsedPaletteColors < 256:
|
||||
imageBytes = bytearray(im.tobytes())
|
||||
for i in range(len(imageBytes)):
|
||||
for newI in range(countUsedPaletteColors):
|
||||
for newI in range(len(usedPaletteColors)):
|
||||
if imageBytes[i] == usedPaletteColors[newI]:
|
||||
imageBytes[i] = newI
|
||||
break
|
||||
|
||||
im.frombytes(bytes(imageBytes))
|
||||
|
||||
if not paletteBytes:
|
||||
paletteBytes = sourcePalette
|
||||
|
||||
# Logical Screen Descriptor
|
||||
# calculate the palette size for the header
|
||||
import math
|
||||
colorTableSize = int(math.ceil(math.log(len(paletteBytes)//3, 2)))-1
|
||||
if colorTableSize < 0: colorTableSize = 0
|
||||
header.append(o8(colorTableSize + 128)) # size of global color table + global color table flag
|
||||
header.append(o8(0) + o8(0)) # background + reserved/aspect
|
||||
# end of screen descriptor header
|
||||
# size of global color table + global color table flag
|
||||
header.append(o8(colorTableSize + 128))
|
||||
# background + reserved/aspect
|
||||
header.append(o8(0) + o8(0))
|
||||
# end of Logical Screen Descriptor
|
||||
|
||||
# add the missing amount of bytes
|
||||
# the palette has to be 2<<n in size
|
||||
|
@ -414,7 +415,7 @@ def getheader(im, palette=None, info=None):
|
|||
if actualTargetSizeDiff > 0:
|
||||
paletteBytes += o8(0) * 3 * actualTargetSizeDiff
|
||||
|
||||
# global color palette
|
||||
# Header + Logical Screen Descriptor + Global Color Table
|
||||
header.append(paletteBytes)
|
||||
return header, usedPaletteColors
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user