Converted png2bcd tool to python [Andrew Gardner]

This commit is contained in:
Miodrag Milanovic 2015-01-10 11:35:34 +01:00
parent 739811854e
commit fb5c151082
6 changed files with 3116 additions and 455 deletions

1
.gitignore vendored
View file

@ -15,3 +15,4 @@
src/regtests/chdman/temp
src/regtests/jedutil/output
/sta
*.pyc

View file

@ -991,9 +991,9 @@ $(OBJ)/%.lh: $(SRC)/%.lay $(SRC)/build/file2str.py
@echo Converting $<...
@$(PYTHON) $(SRC)/build/file2str.py $< $@ layout_$(basename $(notdir $<))
$(OBJ)/%.fh: $(SRC)/%.png $(PNG2BDC_TARGET) $(SRC)/build/file2str.py
$(OBJ)/%.fh: $(SRC)/%.png $(SRC)/build/png2bdc.py $(SRC)/build/file2str.py
@echo Converting $<...
@$(PNG2BDC) $< $(OBJ)/temp.bdc
@$(PYTHON) $(SRC)/build/png2bdc.py $< $(OBJ)/temp.bdc
@$(PYTHON) $(SRC)/build/file2str.py $(OBJ)/temp.bdc $@ font_$(basename $(notdir $<)) UINT8
$(DRIVLISTOBJ): $(DRIVLISTSRC)

View file

@ -21,13 +21,11 @@ OBJDIRS += \
MAKEDEP_TARGET = $(BUILDOUT)/makedep$(BUILD_EXE)
MAKEMAK_TARGET = $(BUILDOUT)/makemak$(BUILD_EXE)
MAKELIST_TARGET = $(BUILDOUT)/makelist$(BUILD_EXE)
PNG2BDC_TARGET = $(BUILDOUT)/png2bdc$(BUILD_EXE)
VERINFO_TARGET = $(BUILDOUT)/verinfo$(BUILD_EXE)
MAKEDEP = $(MAKEDEP_TARGET)
MAKEMAK = $(MAKEMAK_TARGET)
MAKELIST = $(MAKELIST_TARGET)
PNG2BDC = $(PNG2BDC_TARGET)
VERINFO = $(VERINFO_TARGET)
ifneq ($(TERM),cygwin)
@ -35,7 +33,6 @@ ifeq ($(OS),Windows_NT)
MAKEDEP = $(subst /,\,$(MAKEDEP_TARGET))
MAKEMAK = $(subst /,\,$(MAKEMAK_TARGET))
MAKELIST = $(subst /,\,$(MAKELIST_TARGET))
PNG2BDC = $(subst /,\,$(PNG2BDC_TARGET))
VERINFO = $(subst /,\,$(VERINFO_TARGET))
endif
endif
@ -45,7 +42,6 @@ BUILD += \
$(MAKEDEP_TARGET) \
$(MAKEMAK_TARGET) \
$(MAKELIST_TARGET) \
$(PNG2BDC_TARGET) \
$(VERINFO_TARGET) \
@ -106,26 +102,6 @@ $(MAKELIST_TARGET): $(MAKELISTOBJS) $(LIBOCORE) $(ZLIB)
#-------------------------------------------------
# png2bdc
#-------------------------------------------------
PNG2BDCOBJS = \
$(BUILDOBJ)/png2bdc.o \
$(OBJ)/lib/util/astring.o \
$(OBJ)/lib/util/corefile.o \
$(OBJ)/lib/util/corealloc.o \
$(OBJ)/lib/util/bitmap.o \
$(OBJ)/lib/util/png.o \
$(OBJ)/lib/util/palette.o \
$(OBJ)/lib/util/unicode.o \
$(PNG2BDC_TARGET): $(PNG2BDCOBJS) $(LIBOCORE) $(ZLIB)
@echo Linking $@...
$(LD) $(LDFLAGS) $^ $(BASELIBS) -o $@
#-------------------------------------------------
# verinfo
#-------------------------------------------------
@ -147,9 +123,6 @@ $(MAKEDEP_TARGET):
$(MAKELIST_TARGET):
@echo $@ should be built natively. Nothing to do.
$(PNG2BDC_TARGET):
@echo $@ should be built natively. Nothing to do.
$(VERINFO_TARGET):
@echo $@ should be built natively. Nothing to do.

2752
src/build/png.py Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,426 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
png2bdc.c
Super-simple PNG to BDC file generator
****************************************************************************
Format of PNG data:
Multiple rows of characters. A black pixel means "on". All other colors
mean "off". Each row looks like this:
* 8888 *** *
* 4444 * * **
* 2222 * * *
* 1111 * * *
* * * *
** *** ***
*
*
****** ****
The column of pixels on the left-hand side (column 0) indicates the
character cell height. This column must be present on each row and
the height must be consistent for each row.
Protruding one pixel into column 1 is the baseline indicator. There
should only be one row with a pixel in column 1 for each line, and
that pixel row index should be consistent for each row.
In columns 2-5 are a 4-hex-digit starting character index number. This
is encoded as binary value. Each column is 4 pixels tall and represents
one binary digit. The character index number is the unicode character
number of the first character encoded in this row; subsequent
characters in the row are at increasing character indices.
Starting in column 6 and beyond are the actual character bitmaps.
Below them, in the second row after the last row of the character,
is a solid line that indicates the width of the character, and also
where the character bitmap begins and ends.
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <new>
#include "png.h"
//**************************************************************************
// CONSTANTS & DEFINES
//**************************************************************************
#define CACHED_CHAR_SIZE 12
#define CACHED_HEADER_SIZE 16
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// a render_font contains information about a single character in a font
struct render_font_char
{
render_font_char() : width(0), xoffs(0), yoffs(0), bmwidth(0), bmheight(0) { }
INT32 width; // width from this character to the next
INT32 xoffs, yoffs; // X and Y offset from baseline to top,left of bitmap
INT32 bmwidth, bmheight; // width and height of bitmap
bitmap_argb32 * bitmap; // pointer to the bitmap containing the raw data
};
// a render_font contains information about a font
struct render_font
{
render_font() : height(0), yoffs(0) { }
int height; // height of the font, from ascent to descent
int yoffs; // y offset from baseline to descent
render_font_char chars[65536]; // array of characters
};
//**************************************************************************
// INLINE FUNCTIONS
//**************************************************************************
inline int pixel_is_set(bitmap_argb32 &bitmap, int y, int x)
{
return (bitmap.pix32(y, x) & 0xffffff) == 0;
}
//**************************************************************************
// MAIN
//**************************************************************************
//-------------------------------------------------
// write_data - write data to the given file and
// throw an exception if an error occurs
//-------------------------------------------------
static void write_data(core_file &file, UINT8 *base, UINT8 *end)
{
UINT32 bytes_written = core_fwrite(&file, base, end - base);
if (bytes_written != end - base)
{
fprintf(stderr, "Error writing to destination file\n");
throw;
}
}
//-------------------------------------------------
// render_font_save_cached - write the cached
// data out to the file
//-------------------------------------------------
static bool render_font_save_cached(render_font &font, const char *filename, UINT32 hash)
{
// attempt to open the file
core_file *file;
file_error filerr = core_fopen(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
if (filerr != FILERR_NONE)
return true;
try
{
// determine the number of characters
int numchars = 0;
for (int chnum = 0; chnum < 65536; chnum++)
if (font.chars[chnum].width > 0)
numchars++;
// write the header
dynamic_buffer tempbuffer(65536);
UINT8 *dest = &tempbuffer[0];
*dest++ = 'f';
*dest++ = 'o';
*dest++ = 'n';
*dest++ = 't';
*dest++ = hash >> 24;
*dest++ = hash >> 16;
*dest++ = hash >> 8;
*dest++ = hash & 0xff;
*dest++ = font.height >> 8;
*dest++ = font.height & 0xff;
*dest++ = font.yoffs >> 8;
*dest++ = font.yoffs & 0xff;
*dest++ = numchars >> 24;
*dest++ = numchars >> 16;
*dest++ = numchars >> 8;
*dest++ = numchars & 0xff;
write_data(*file, tempbuffer, dest);
// write the empty table to the beginning of the file
dynamic_buffer chartable(numchars * CACHED_CHAR_SIZE + 1, 0);
write_data(*file, &chartable[0], &chartable[numchars * CACHED_CHAR_SIZE]);
// loop over all characters
int tableindex = 0;
for (int chnum = 0; chnum < 65536; chnum++)
{
render_font_char &ch = font.chars[chnum];
if (ch.width > 0)
{
// write out a bit-compressed bitmap if we have one
if (ch.bitmap != NULL)
{
// write the data to the tempbuffer
dest = tempbuffer;
UINT8 accum = 0;
UINT8 accbit = 7;
// bit-encode the character data
for (int y = 0; y < ch.bmheight; y++)
{
int desty = y + font.height + font.yoffs - ch.yoffs - ch.bmheight;
const UINT32 *src = (desty >= 0 && desty < font.height) ? &ch.bitmap->pix32(desty) : NULL;
for (int x = 0; x < ch.bmwidth; x++)
{
if (src != NULL && src[x] != 0)
accum |= 1 << accbit;
if (accbit-- == 0)
{
*dest++ = accum;
accum = 0;
accbit = 7;
}
}
}
// flush any extra
if (accbit != 7)
*dest++ = accum;
// write the data
write_data(*file, tempbuffer, dest);
// free the bitmap and texture
global_free(ch.bitmap);
ch.bitmap = NULL;
}
// compute the table entry
dest = &chartable[tableindex++ * CACHED_CHAR_SIZE];
*dest++ = chnum >> 8;
*dest++ = chnum & 0xff;
*dest++ = ch.width >> 8;
*dest++ = ch.width & 0xff;
*dest++ = ch.xoffs >> 8;
*dest++ = ch.xoffs & 0xff;
*dest++ = ch.yoffs >> 8;
*dest++ = ch.yoffs & 0xff;
*dest++ = ch.bmwidth >> 8;
*dest++ = ch.bmwidth & 0xff;
*dest++ = ch.bmheight >> 8;
*dest++ = ch.bmheight & 0xff;
}
}
// seek back to the beginning and rewrite the table
core_fseek(file, CACHED_HEADER_SIZE, SEEK_SET);
write_data(*file, &chartable[0], &chartable[numchars * CACHED_CHAR_SIZE]);
// all done
core_fclose(file);
return false;
}
catch (...)
{
core_fclose(file);
osd_rmfile(filename);
return true;
}
}
//-------------------------------------------------
// bitmap_to_chars - convert a bitmap to
// characters in the given font
//-------------------------------------------------
static bool bitmap_to_chars(bitmap_argb32 &bitmap, render_font &font)
{
// loop over rows
int rowstart = 0;
while (rowstart < bitmap.height())
{
// find the top of the row
for ( ; rowstart < bitmap.height(); rowstart++)
if (pixel_is_set(bitmap, rowstart, 0))
break;
if (rowstart >= bitmap.height())
break;
// find the bottom of the row
int rowend;
for (rowend = rowstart + 1; rowend < bitmap.height(); rowend++)
if (!pixel_is_set(bitmap, rowend, 0))
{
rowend--;
break;
}
// find the baseline
int baseline;
for (baseline = rowstart; baseline <= rowend; baseline++)
if (pixel_is_set(bitmap, baseline, 1))
break;
if (baseline > rowend)
{
fprintf(stderr, "No baseline found between rows %d-%d\n", rowstart, rowend);
break;
}
// set or confirm the height
if (font.height == 0)
{
font.height = rowend - rowstart + 1;
font.yoffs = baseline - rowend;
}
else
{
if (font.height != rowend - rowstart + 1)
{
fprintf(stderr, "Inconsistent font height at rows %d-%d\n", rowstart, rowend);
break;
}
if (font.yoffs != baseline - rowend)
{
fprintf(stderr, "Inconsistent baseline at rows %d-%d\n", rowstart, rowend);
break;
}
}
// decode the starting character
int chstart = 0;
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++)
chstart = (chstart << 1) | pixel_is_set(bitmap, rowstart + y, 2 + x);
// print info
// printf("Row %d-%d, baseline %d, character start %X\n", rowstart, rowend, baseline, chstart);
// scan the column to find characters
int colstart = 0;
while (colstart < bitmap.width())
{
render_font_char &ch = font.chars[chstart];
// find the start of the character
for ( ; colstart < bitmap.width(); colstart++)
if (pixel_is_set(bitmap, rowend + 2, colstart))
break;
if (colstart >= bitmap.width())
break;
// find the end of the character
int colend;
for (colend = colstart + 1; colend < bitmap.width(); colend++)
if (!pixel_is_set(bitmap, rowend + 2, colend))
{
colend--;
break;
}
// skip char which code is already registered
if (ch.width <= 0)
{
// print info
// printf(" Character %X - width = %d\n", chstart, colend - colstart + 1);
// allocate a bitmap
ch.bitmap = global_alloc(bitmap_argb32(colend - colstart + 1, font.height));
// plot the character
for (int y = rowstart; y <= rowend; y++)
for (int x = colstart; x <= colend; x++)
ch.bitmap->pix32(y - rowstart, x - colstart) = pixel_is_set(bitmap, y, x) ? 0xffffffff : 0x00000000;
// set the character parameters
ch.width = colend - colstart + 1;
ch.xoffs = 0;
ch.yoffs = font.yoffs;
ch.bmwidth = ch.bitmap->width();
ch.bmheight = ch.bitmap->height();
}
// next character
chstart++;
colstart = colend + 1;
}
// next row
rowstart = rowend + 1;
}
// return non-zero (TRUE) if we errored
return (rowstart < bitmap.height());
}
//-------------------------------------------------
// main - main entry point
//-------------------------------------------------
int main(int argc, char *argv[])
{
// validate arguments
if (argc < 3)
{
fprintf(stderr, "Usage:\n%s <input.png> [<input2.png> [...]] <output.bdc>\n", argv[0]);
return 1;
}
const char *bdcname = argv[argc - 1];
// iterate over input files
static render_font font;
bool error = false;
for (int curarg = 1; curarg < argc - 1; curarg++)
{
// load the png file
const char *pngname = argv[curarg];
core_file *file;
file_error filerr = core_fopen(pngname, OPEN_FLAG_READ, &file);
if (filerr != FILERR_NONE)
{
fprintf(stderr, "Error %d attempting to open PNG file\n", filerr);
error = true;
break;
}
bitmap_argb32 bitmap;
png_error pngerr = png_read_bitmap(file, bitmap);
core_fclose(file);
if (pngerr != PNGERR_NONE)
{
fprintf(stderr, "Error %d reading PNG file\n", pngerr);
error = true;
break;
}
// parse the PNG into characters
error = bitmap_to_chars(bitmap, font);
if (error)
break;
}
// write out the resulting font
if (!error)
error = render_font_save_cached(font, bdcname, 0);
// cleanup after ourselves
return error ? 1 : 0;
}

361
src/build/png2bdc.py Normal file
View file

@ -0,0 +1,361 @@
#!/usr/bin/env python
##
## license:BSD-3-Clause
## copyright-holders:Aaron Giles, Andrew Gardner
## ****************************************************************************
##
## png2bdc.c
##
## Super-simple PNG to BDC file generator
##
## ****************************************************************************
##
## Format of PNG data:
##
## Multiple rows of characters. A black pixel means "on". All other colors
## mean "off". Each row looks like this:
##
## * 8888 *** *
## * 4444 * * **
## * 2222 * * *
## * 1111 * * *
## * * * *
## ** *** ***
## *
## *
##
## ****** ****
##
## The column of pixels on the left-hand side (column 0) indicates the
## character cell height. This column must be present on each row and
## the height must be consistent for each row.
##
## Protruding one pixel into column 1 is the baseline indicator. There
## should only be one row with a pixel in column 1 for each line, and
## that pixel row index should be consistent for each row.
##
## In columns 2-5 are a 4-hex-digit starting character index number. This
## is encoded as binary value. Each column is 4 pixels tall and represents
## one binary digit. The character index number is the unicode character
## number of the first character encoded in this row; subsequent
## characters in the row are at increasing character indices.
##
## Starting in column 6 and beyond are the actual character bitmaps.
## Below them, in the second row after the last row of the character,
## is a solid line that indicates the width of the character, and also
## where the character bitmap begins and ends.
##
## ***************************************************************************
##
## Python note:
## This is a near-literal translation of the original C++ code. As such there
## are some very non-pythonic things done throughout. The conversion was done
## this way so as to insure compatibility as much as possible given the small
## number of test cases.
##
import os
import png
import sys
########################################
## Helper classes
########################################
class RenderFontChar:
"""
Contains information about a single character in a font.
"""
def __init__(self):
"""
"""
self.width = 0 # width from this character to the next
self.xOffs = 0 # X offset from baseline to top,left of bitmap
self.yOffs = 0 # Y offset from baseline to top,left of bitmap
self.bmWidth = 0 # width of bitmap
self.bmHeight = 0 # height of bitmap
self.bitmap = None # pointer to the bitmap containing the raw data
class RenderFont:
"""
Contains information about a font
"""
def __init__(self):
self.height = 0 # height of the font, from ascent to descent
self.yOffs = 0 # y offset from baseline to descent
self.chars = list() # array of characters
for i in range(0, 65536):
self.chars.append(RenderFontChar())
########################################
## Helper functions
########################################
def pixelIsSet(value):
return (value & 0xffffff) == 0
def renderFontSaveCached(font, filename, hash32):
"""
"""
fp = open(filename, "wb")
if not fp:
return 1
# Write the header
numChars = 0
for c in font.chars:
if c.width > 0:
numChars += 1
CACHED_CHAR_SIZE = 12
CACHED_HEADER_SIZE = 16
try:
fp.write('f')
fp.write('o')
fp.write('n')
fp.write('t')
fp.write(bytearray([hash32 >> 24 & 0xff]))
fp.write(bytearray([hash32 >> 16 & 0xff]))
fp.write(bytearray([hash32 >> 8 & 0xff]))
fp.write(bytearray([hash32 >> 0 & 0xff]))
fp.write(bytearray([font.height >> 8 & 0xff]))
fp.write(bytearray([font.height >> 0 & 0xff]))
fp.write(bytearray([font.yOffs >> 8 & 0xff]))
fp.write(bytearray([font.yOffs >> 0 & 0xff]))
fp.write(bytearray([numChars >> 24 & 0xff]))
fp.write(bytearray([numChars >> 16 & 0xff]))
fp.write(bytearray([numChars >> 8 & 0xff]))
fp.write(bytearray([numChars >> 0 & 0xff]))
# Write a blank table at first (?)
charTable = [0]*(numChars * CACHED_CHAR_SIZE)
fp.write(bytearray(charTable))
# Loop over all characters
tableIndex = 0
for i in range(len(font.chars)):
c = font.chars[i]
if c.width == 0:
continue
if c.bitmap:
dBuffer = list()
accum = 0
accbit = 7
# Bit-encode the character data
for y in range(0, c.bmHeight):
src = None
desty = y + font.height + font.yOffs - c.yOffs - c.bmHeight
if desty >= 0 and desty < font.height:
src = c.bitmap[desty]
for x in range(0, c.bmWidth):
if src is not None and src[x] != 0:
accum |= 1 << accbit
accbit -= 1
if accbit+1 == 0:
dBuffer.append(accum)
accum = 0
accbit = 7
# Flush any extra
if accbit != 7:
dBuffer.append(accum)
# Write the data
fp.write(bytearray(dBuffer))
destIndex = tableIndex * CACHED_CHAR_SIZE
charTable[destIndex + 0] = i >> 8 & 0xff
charTable[destIndex + 1] = i >> 0 & 0xff
charTable[destIndex + 2] = c.width >> 8 & 0xff
charTable[destIndex + 3] = c.width >> 0 & 0xff
charTable[destIndex + 4] = c.xOffs >> 8 & 0xff
charTable[destIndex + 5] = c.xOffs >> 0 & 0xff
charTable[destIndex + 6] = c.yOffs >> 8 & 0xff
charTable[destIndex + 7] = c.yOffs >> 0 & 0xff
charTable[destIndex + 8] = c.bmWidth >> 8 & 0xff
charTable[destIndex + 9] = c.bmWidth >> 0 & 0xff
charTable[destIndex + 10] = c.bmHeight >> 8 & 0xff
charTable[destIndex + 11] = c.bmHeight >> 0 & 0xff
tableIndex += 1
# Seek back to the beginning and rewrite the table
fp.seek(CACHED_HEADER_SIZE, 0)
fp.write(bytearray(charTable))
fp.close()
return 0
except:
return 1
def bitmapToChars(pngObject, font):
"""
Convert a bitmap to characters in the given font
"""
# Just cache the bitmap into a list of lists since random access is paramount
bitmap = list()
width = pngObject.asRGBA8()[0]
height = pngObject.asRGBA8()[1]
rowGenerator = pngObject.asRGBA8()[2]
for row in rowGenerator:
cRow = list()
irpd = iter(row)
for r,g,b,a in zip(irpd, irpd, irpd, irpd):
cRow.append(a << 24 | r << 16 | g << 8 | b)
bitmap.append(cRow)
rowStart = 0
while rowStart < height:
# Find the top of the row
for i in range(rowStart, height):
if pixelIsSet(bitmap[rowStart][0]):
break
rowStart += 1
if rowStart >= height:
break
# Find the bottom of the row
rowEnd = rowStart + 1
for i in range(rowEnd, height):
if not pixelIsSet(bitmap[rowEnd][0]):
rowEnd -= 1
break
rowEnd += 1
# Find the baseline
baseline = rowStart
for i in range(rowStart, rowEnd+1):
if pixelIsSet(bitmap[baseline][1]):
break
baseline += 1
if baseline > rowEnd:
sys.stderr.write("No baseline found between rows %d-%d\n" % (rowStart, rowEnd))
break
# Set or confirm the height
if font.height == 0:
font.height = rowEnd - rowStart + 1
font.yOffs = baseline - rowEnd
else:
if font.height != (rowEnd - rowStart + 1):
sys.stderr.write("Inconsistent font height at rows %d-%d\n" % (rowStart, rowEnd))
break
if font.yOffs != (baseline - rowEnd):
sys.stderr.write("Inconsistent baseline at rows %d-%d\n" % (rowStart, rowEnd))
break
# decode the starting character
chStart = 0
for x in range(0, 4):
for y in range(0, 4):
chStart = (chStart << 1) | pixelIsSet(bitmap[rowStart+y][2+x])
# Print debug info
# print("Row %d-%d, baseline %d, character start %X" % (rowStart, rowEnd, baseline, chStart))
# scan the column to find characters
colStart = 0
while (colStart < width):
ch = RenderFontChar()
# Find the start of the character
for i in range(colStart, width):
if pixelIsSet(bitmap[rowEnd+2][colStart]):
break
colStart += 1
if colStart >= width:
break
# Find the end of the character
colEnd = colStart + 1
for i in range(colEnd, width):
if not pixelIsSet(bitmap[rowEnd+2][colEnd]):
colEnd -= 1
break
colEnd += 1
# Skip char which code is already registered
if ch.width <= 0:
# Print debug info
# print " Character %X - width = %d" % (chStart, colEnd - colStart + 1)
# Plot the character
ch.bitmap = list()
for y in range(rowStart, rowEnd+1):
ch.bitmap.append(list())
for x in range(colStart, colEnd+1):
if pixelIsSet(bitmap[y][x]):
ch.bitmap[-1].append(0xffffffff)
else:
ch.bitmap[-1].append(0x00000000)
# Set the character parameters
ch.width = colEnd - colStart + 1
ch.xOffs = 0
ch.yOffs = font.yOffs
ch.bmWidth = len(ch.bitmap[0])
ch.bmHeight = len(ch.bitmap)
# Insert the character into the list
font.chars[chStart] = ch
# Next character
chStart += 1
colStart = colEnd + 1
# Next row
rowStart = rowEnd + 1
# Return non-zero if we errored
return (rowStart < height)
########################################
## Main
########################################
def main():
if len(sys.argv) < 3:
sys.stderr.write("Usage:\n%s <input.png> [<input2.png> [...]] <output.bdc>\n" % sys.argv[0])
return 1
bdcName = sys.argv[-1]
font = RenderFont()
for i in range(1, len(sys.argv)-1):
filename = sys.argv[i]
if not os.path.exists(filename):
sys.stderr.write("Error attempting to open PNG file.\n")
return 1
pngObject = png.Reader(filename)
try:
pngObject.validate_signature()
except:
sys.stderr.write("Error reading PNG file.\n")
return 1
error = bitmapToChars(pngObject, font)
if error:
return 1
error = renderFontSaveCached(font, bdcName, 0)
return error
########################################
## Program entry point
########################################
if __name__ == "__main__":
sys.exit(main())