You've already forked pokecrystal-board
mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2025-09-08 08:13:02 -07:00
gfx: handling for <4-color pngs when converting to 2bpp
without a .pal file as reference, palettes are sorted by luminance. pokemon crystal reads palettes exactly 4 colors in length. if an image used fewer than 4 colors, invalid palettes were produced. instead, dummy colors are inserted to pad out the palette.
This commit is contained in:
@@ -1184,6 +1184,12 @@ def dmg2rgb(word):
|
|||||||
alpha = 255
|
alpha = 255
|
||||||
return ((red<<3)+0b100, (green<<3)+0b100, (blue<<3)+0b100, alpha)
|
return ((red<<3)+0b100, (green<<3)+0b100, (blue<<3)+0b100, alpha)
|
||||||
|
|
||||||
|
def rgb_to_dmg(color):
|
||||||
|
word = (color['r'] / 8) << 10
|
||||||
|
word += (color['g'] / 8) << 5
|
||||||
|
word += (color['b'] / 8)
|
||||||
|
return word
|
||||||
|
|
||||||
|
|
||||||
def png_pal(filename):
|
def png_pal(filename):
|
||||||
palette = []
|
palette = []
|
||||||
@@ -1303,17 +1309,13 @@ def to_2bpp(filein, fileout=None, palout=None):
|
|||||||
greyscale = info[3]['greyscale']
|
greyscale = info[3]['greyscale']
|
||||||
|
|
||||||
|
|
||||||
# commented out for the moment
|
|
||||||
|
|
||||||
padding = { 'left': 0,
|
padding = { 'left': 0,
|
||||||
'right': 0,
|
'right': 0,
|
||||||
'top': 0,
|
'top': 0,
|
||||||
'bottom': 0, }
|
'bottom': 0, }
|
||||||
|
|
||||||
#if width % 8 != 0:
|
#if width % 8 != 0:
|
||||||
# padding['left'] = int(ceil((width / 8 + 8 - width) / 2))
|
# padding['left'] = int(ceil((width / 8 + 8 - width) / 2))
|
||||||
# padding['right'] = int(floor((width / 8 + 8 - width) / 2))
|
# padding['right'] = int(floor((width / 8 + 8 - width) / 2))
|
||||||
|
|
||||||
#if height % 8 != 0:
|
#if height % 8 != 0:
|
||||||
# padding['top'] = int(ceil((height / 8 + 8 - height) / 2))
|
# padding['top'] = int(ceil((height / 8 + 8 - height) / 2))
|
||||||
# padding['bottom'] = int(floor((height / 8 + 8 - height) / 2))
|
# padding['bottom'] = int(floor((height / 8 + 8 - height) / 2))
|
||||||
@@ -1331,53 +1333,49 @@ def to_2bpp(filein, fileout=None, palout=None):
|
|||||||
for line in rgba:
|
for line in rgba:
|
||||||
newline = []
|
newline = []
|
||||||
for pixel in range(len(line)/pixel_length):
|
for pixel in range(len(line)/pixel_length):
|
||||||
i = pixel*pixel_length
|
i = pixel * pixel_length
|
||||||
color = { 'r': line[i ],
|
color = { 'r': line[i ],
|
||||||
'g': line[i+1],
|
'g': line[i+1],
|
||||||
'b': line[i+2],
|
'b': line[i+2],
|
||||||
'a': line[i+3], }
|
'a': line[i+3], }
|
||||||
newline.append(color)
|
newline += [color]
|
||||||
if color not in palette: palette.append(color)
|
if color not in palette: palette += [color]
|
||||||
image.append(newline)
|
image.append(newline)
|
||||||
|
|
||||||
|
# pad out any small palettes
|
||||||
|
hues = {
|
||||||
|
'white': { 'r': 0xff, 'g': 0xff, 'b': 0xff, 'a': 0xff },
|
||||||
|
'black': { 'r': 0x00, 'g': 0x00, 'b': 0x00, 'a': 0xff },
|
||||||
|
'grey': { 'r': 0x55, 'g': 0x55, 'b': 0x55, 'a': 0xff },
|
||||||
|
'gray': { 'r': 0xaa, 'g': 0xaa, 'b': 0xaa, 'a': 0xff },
|
||||||
|
}
|
||||||
|
while len(palette) < 4:
|
||||||
|
for hue in hues.values():
|
||||||
|
if not any(color is hue for color in palette):
|
||||||
|
palette += [hue]
|
||||||
|
if len(palette) >= 4: break
|
||||||
|
|
||||||
# sort by luminance, because we can
|
assert len(palette) <= 4, 'Palette should be 4 colors, is really ' + str(len(palette))
|
||||||
|
|
||||||
|
# sort by luminance
|
||||||
def luminance(color):
|
def luminance(color):
|
||||||
# this is actually in reverse, thanks to dmg/cgb palette ordering
|
# this is actually in reverse, thanks to dmg/cgb palette ordering
|
||||||
rough = { 'r': 4.7,
|
rough = { 'r': 4.7,
|
||||||
'g': 1.4,
|
'g': 1.4,
|
||||||
'b': 13.8, }
|
'b': 13.8, }
|
||||||
return sum(color[key] * -rough[key] for key in rough.keys())
|
return sum(color[key] * -rough[key] for key in rough.keys())
|
||||||
|
palette = sorted(palette, key=luminance)
|
||||||
|
|
||||||
palette = sorted(palette, key = lambda x:luminance(x))
|
# spit out new .pal file
|
||||||
|
#if palout != None:
|
||||||
# no palette fixing for now
|
# output = []
|
||||||
|
# for color in palette[1:3]:
|
||||||
assert len(palette) <= 4, 'Palette should be 4 colors, is really ' + str(len(palette))
|
# word = rgb_to_dmg(color)
|
||||||
|
# output += [word & 0xff]
|
||||||
|
# output += [word >> 8]
|
||||||
# spit out new palette (disabled for now)
|
# to_file(palout, output)
|
||||||
|
|
||||||
def rgb_to_dmg(color):
|
|
||||||
word = (color['r'] / 8) << 10
|
|
||||||
word += (color['g'] / 8) << 5
|
|
||||||
word += (color['b'] / 8)
|
|
||||||
return word
|
|
||||||
|
|
||||||
palout = None
|
|
||||||
|
|
||||||
if palout != None:
|
|
||||||
output = []
|
|
||||||
for color in palette[1:3]:
|
|
||||||
word = rgb_to_dmg(color)
|
|
||||||
output.append(word>>8)
|
|
||||||
output.append(word&0xff)
|
|
||||||
to_file(palout, output)
|
|
||||||
|
|
||||||
|
|
||||||
# create a new map consisting of quaternary color ids
|
|
||||||
|
|
||||||
|
# create a new map of quaternary color ids
|
||||||
map = []
|
map = []
|
||||||
if padding['top']: map += [0] * (width + padding['left'] + padding['right']) * padding['top']
|
if padding['top']: map += [0] * (width + padding['left'] + padding['right']) * padding['top']
|
||||||
for line in image:
|
for line in image:
|
||||||
@@ -1388,12 +1386,9 @@ def to_2bpp(filein, fileout=None, palout=None):
|
|||||||
if padding['bottom']: map += [0] * (width + padding['left'] + padding['right']) * padding['bottom']
|
if padding['bottom']: map += [0] * (width + padding['left'] + padding['right']) * padding['bottom']
|
||||||
|
|
||||||
# split it into strips of 8, and make them planar
|
# split it into strips of 8, and make them planar
|
||||||
|
|
||||||
num_columns = width / 8
|
num_columns = width / 8
|
||||||
num_rows = height / 8
|
num_rows = height / 8
|
||||||
|
|
||||||
tile = 8 * 8
|
tile = 8 * 8
|
||||||
|
|
||||||
image = []
|
image = []
|
||||||
for row in range(num_rows):
|
for row in range(num_rows):
|
||||||
for column in range(num_columns):
|
for column in range(num_columns):
|
||||||
|
Reference in New Issue
Block a user