newbitmaps: Speed up image conversion by using PIL.

Running ImageMagick + PIL is a redundant task; we should let PIL
do flatten, resize, and exporting to different format.

Before: real 11m54s, user 37m10s.
After: real 8m3s, user 16m33s.

BRANCH=none
BUG=none
TEST=make

Change-Id: I65f1e5b769161650310abca46851824755402d9b
Reviewed-on: https://gerrit.chromium.org/gerrit/37200
Tested-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Ready: Hung-Te Lin <hungte@chromium.org>
This commit is contained in:
Hung-Te Lin
2012-11-02 17:49:22 +08:00
committed by Gerrit
parent 7909cb8293
commit 3f9857420f
4 changed files with 99 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -14,54 +14,23 @@ BACKGROUND_IMAGE=Background_white.png
# Output file name.
BMPBLK_OUTPUT="bmpblock.bin"
SCRIPT_BASE="$(dirname $(readlink -f "$0"))"
die() {
echo "ERROR: $*" >&2
exit 1
}
convert_to_bmp3() {
local input="$1"
local folder="$2"
local param="$3"
local output="$(basename "$input")"
local folder="$1"
local param="$2"
shift
shift
# Always output as .bmp
output="${output%.*}.bmp"
mkdir -p "$folder"
# convert_to_bmp3.py takes '--scale' while ImageMagic takes '-scale'.
[ -n "$param" ] && param="-$param"
# TODO(hungte) Use PIL to replace ImageMagic.
# When input has Alpha channel, we need to fill the background properly
# otherwise ImageMagick will fill it with black. The operation (-flatten) is
# so slow so we only want to do that if the input source really has
# transparency.
if [ "$#" -gt 3 ]; then
flatten="$4"
else
# Auto-detect
if [ "$(identify -format "%A" "$input")" = "True" ]; then
flatten="-background $BACKGROUND_COLOR -flatten"
else
flatten=""
fi
fi
echo "$input -> $folder/$output $flatten"
convert "$input" $flatten \
-compress none -alpha off -colors 256 \
$param "BMP3:$folder/$output"
# ImageMagic quantization may choose arbitrary color depth, even if we assign
# -depth or -colors; so a single-color background may become 1 bit per pixel
# after convertion. To workaround that, we use Python Image Library which
# always generates 8bpp BMP file.
# TODO(hungte) Find a better way to decide if PIL is required. Unfortunately,
# ImageMagic identify "%z" is not always what we're looking for...
local fn="$folder/$output"
# Converting from '1' to 'P' may be not supported by PIL, so converting to
# 'RGB' mode first is required.
local param="convert('RGB').convert('P', dither=None, palette=Image.ADAPTIVE)"
python -c "import Image;Image.open('$fn').$param.save('$fn')"
$SCRIPT_BASE/convert_to_bmp3.py $param --outdir "$folder" "$@"
}
main() {
@@ -163,9 +132,9 @@ main() {
# Url.bmp by <span foreground="blue">http://</span>.
for X in *.png assets/*.png; do
if [ "$X" = "$BACKGROUND_IMAGE" ]; then
convert_to_bmp3 "$X" "$output" "$background_scale_param"
convert_to_bmp3 "$output" "$background_scale_param" "$X"
else
convert_to_bmp3 "$X" "$output" "$scale_param"
convert_to_bmp3 "$output" "$scale_param" "$X"
fi
done
@@ -174,9 +143,7 @@ main() {
# speed up.
echo "Preparing common strings..."
base="../strings"
for X in $base/*.png; do
convert_to_bmp3 "$X" "$output" "$scale_param" ""
done
convert_to_bmp3 "$output" "$scale_param" $base/*.png
echo "Preparing localized messages... $LOCALES"
base="../strings/localized_text"
@@ -191,9 +158,7 @@ main() {
fi
for locale in $LOCALES; do
# Prepare all locales.
for X in $base/$locale/*.png; do
convert_to_bmp3 "$X" "$output/locale/$locale" "$scale_param" ""
done
convert_to_bmp3 "$output/locale/$locale" "$scale_param" $base/$locale/*.png
done
if [ -n "$replace_files" ]; then
@@ -210,9 +175,7 @@ main() {
echo "Preparing fonts..."
base="../strings/font"
for X in $base/*.png; do
convert_to_bmp3 "$X" "$output/font" "$scale_param" ""
done
convert_to_bmp3 "$output/font" "$scale_param" $base/*.png
bmpblk_font --outfile "$output/hwid_fonts.bin" "$output"/font/*.bmp
# Create YAML file.

View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import getopt
import os
import re
import sys
import Image
BACKGROUND_COLOR = (255, 255, 255)
DEFAULT_OUTPUT_EXT = '.bmp'
def parse_scale_factor(pattern, original_size):
# Format: w%xh%, or wxh!
factor = re.findall(r'^([0-9]+)%x([0-9]+)%$', pattern)
if factor:
w, h = factor[0]
return (int(int(w) / 100.0 * original_size[0]),
int(int(h) / 100.0 * original_size[1]))
factor = re.findall(r'^([0-9]+)x([0-9]+)!?$', pattern)
if factor:
return map(int, factor[0])
raise Exception('Unknown scaling parameter: %s', pattern)
def convert_to_bmp(input_file, scale, outdir, background=BACKGROUND_COLOR):
source = Image.open(input_file)
output_file = os.path.join(
outdir,
os.path.basename(input_file).rpartition('.')[0] + DEFAULT_OUTPUT_EXT)
# Process alpha channel and transparency.
if source.mode == 'RGBA':
target = Image.new('RGB', source.size, background)
source.load() # required for source.split()
mask = source.split()[-1]
target.paste(source, mask=mask)
elif (source.mode == 'P') and ('transparency' in source.info):
exit('Sorry, PNG with RGBA palette is not supported.')
elif source.mode != 'RGB':
target = source.convert('RGB')
else:
target = source
# Process scaling
if scale:
new_size = parse_scale_factor(scale, source.size)
target = target.resize(new_size, Image.BICUBIC)
# Export and downsample color space.
target.convert('P', dither=None, palette=Image.ADAPTIVE).save(output_file)
def main(argv):
scale_param = ''
outdir = ''
try:
opts, args = getopt.getopt(argv[1:], '', ('scale=', 'outdir='))
for key, value in opts:
if key == '--scale':
scale_param = value
elif key == '--outdir':
outdir = value
if len(args) < 1:
raise Exception('need more param')
except:
exit('Usage: ' + argv[0] +
' [--scale WxH!|--scale W%xH%] [--outdir DIR] files(s)...')
if outdir and not os.path.isdir(outdir):
os.makedirs(outdir)
for source_file in args:
convert_to_bmp(source_file, scale_param, outdir)
if __name__ == '__main__':
main(sys.argv)