Skip to content

Instantly share code, notes, and snippets.

@TomoshibiAkira
Created January 6, 2022 14:03
Show Gist options
  • Save TomoshibiAkira/782bbe57bd5e77ddbf0836a63a107e04 to your computer and use it in GitHub Desktop.
Save TomoshibiAkira/782bbe57bd5e77ddbf0836a63a107e04 to your computer and use it in GitHub Desktop.
A Python script for converting images to AWBMv2 (Award BIOS Bitmap V2).
import os
import argparse
import numpy as np
from PIL import Image
# Format description from: http://fileformats.archiveteam.org/wiki/Award_BIOS_logo
MAGIC = b'AWBM'
PALMAGIC = b'RGB '
def parse():
parser = argparse.ArgumentParser(description='img2awbmv2')
parser.add_argument('file')
parser.add_argument('--format', '-f',
default='auto', choices=['auto', '4', '8'],
help='use 4 or 8-bit variant. default: auto (deduce from the input image)')
parser.add_argument('--save', '-s', default='')
args = parser.parse_args()
return args
def main(args):
assert os.path.exists(args.file), "File not found!"
if len(args.save) == 0:
args.save = os.path.basename(
os.path.splitext(args.file)[0]+'.awbm',
)
if os.path.dirname(args.save) != '':
os.makedirs(os.path.dirname(args.save), exist_ok=True)
# read image
im = Image.open(args.file)
nim = np.asarray(im)
if nim.ndim == 2:
nim = nim[:, :, None]
unique_colors = np.unique(nim.reshape(-1, nim.shape[-1]), axis=0)
# detect colors
if args.format == 'auto':
if unique_colors.shape[0] <= 16:
colors = 16
else:
colors = 256
print ('Total {} unique colors found, using {} colors.'.format(
unique_colors.shape[0], colors
))
elif args.format == '4':
colors = 16
elif args.format == '8':
colors = 256
sw = np.uint16(im.width).tobytes()
sh = np.uint16(im.height).tobytes()
pim = im.convert('P', palette=Image.ADAPTIVE, colors=colors)
# RGB palette
palette = np.asarray(pim.getpalette()[:colors*3], dtype=np.uint8) // 4
if colors == 16: # 4bit
# convert to BGR
palette = palette.reshape(16, 3)[:, ::-1].reshape(-1)
# preparing data
npim = np.asarray(pim)
assert npim.ndim == 2
cmp = 0x1
fs = []
for _ in range(4):
f = np.packbits(npim & cmp, axis=-1)
fs.append(f)
cmp = cmp << 1
data = np.concatenate(fs, axis=1).tobytes()
else: # 8bit
data = pim.tobytes()
assert len(data) == im.width * im.height
# assemble
paldata = palette.tobytes()
with open(args.save, mode='wb') as f:
f.write(MAGIC)
f.write(sw)
f.write(sh)
f.write(data)
f.write(PALMAGIC)
f.write(paldata)
print ('Saved to {}.'.format(args.save))
if __name__ == '__main__':
args = parse()
main(args)
@TomoshibiAkira
Copy link
Author

Some quirks and tips:

  1. Since AWBMv2 only supports 6bit intensity (0..63), there is an 8bit to 6bit quantization (L56).
  2. The ``ADAPTIVE'' RGB to Palette conversion in PIL is usable but not the best. The index mode conversion in Photoshop has better visual quality IMO.
  3. One can convert AWBM back to conventional formats (PNG) to validate the result. deark is pretty handy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment