test-kivy-app/kivy_venv/lib/python3.11/site-packages/kivy/tools/image-testsuite/gimp28-testsuite.py

330 lines
12 KiB
Python
Raw Normal View History

2024-09-15 12:12:16 +00:00
#!/usr/bin/env python
# flake8: noqa
import os
import re
import random
from gimpfu import *
# Test suite configuration - key is test name, values are:
#
# alpha....: global alpha, used for all pixels except 't'
# patterns.: allowed v0 pattern characters (+ force include and exclude)
# *_IMAGE..: gimp layer types to export for this test, w/target extensions
TESTSUITE_CONFIG = {
'OPAQUE': {
'alpha': [255],
'patterns': ('wxrgbcyp', None, None),
RGB_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'ppm',
'sgi', 'pcx', 'fits', 'ras'],
INDEXED_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'ppm', 'gif', 'ras'],
},
'GRAY-OPAQUE': {
'alpha': [255],
'patterns': ('0123456789ABCDEF', None, None),
GRAY_IMAGE: ['xcf', 'png', 'tga', 'tiff',
'pgm', 'sgi', 'fits', 'ras'],
INDEXED_IMAGE: ['xcf', 'png', 'tga', 'tiff', 'pgm', 'fits', 'ras'],
},
'BINARY': {
'alpha': [255],
'patterns': ('twrgbcyp', 't', None),
RGBA_IMAGE: ['xcf', 'png', 'tga', 'ico', 'sgi'],
INDEXEDA_IMAGE: ['xcf', 'png', 'tga', 'gif'],
},
'GRAY-BINARY': {
'alpha': [255],
'patterns': ('t123456789ABCDEF', 't', None),
GRAYA_IMAGE: ['xcf', 'tga', 'png', 'sgi'],
INDEXEDA_IMAGE: ['xcf', 'tga', 'png'],
},
"ALPHA": {
'alpha': [0x7F, 0xF0],
'patterns': ('twxrgbcyp', None, None),
RGBA_IMAGE: ['xcf', 'png', 'tga', 'sgi'],
},
'GRAY-ALPHA': {
'alpha': [0x7F, 0xF0],
'patterns': ('t0123456789ABCDEF', None, None),
GRAYA_IMAGE: ['xcf', 'png', 'tga', 'sgi'],
},
}
# kivy image test protocol v0 data: key is pattern char, value is pixel w/o a
v0_PIXELS = {
'w': [0xFF, 0xFF, 0xFF], 'x': [0x00, 0x00, 0x00], 'r': [0xFF, 0x00, 0x00],
'g': [0x00, 0xFF, 0x00], 'b': [0x00, 0x00, 0xFF], 'y': [0xFF, 0xFF, 0x00],
'c': [0x00, 0xFF, 0xFF], 'p': [0xFF, 0x00, 0xFF], '0': [0x00, 0x00, 0x00],
'1': [0x11, 0x11, 0x11], '2': [0x22, 0x22, 0x22], '3': [0x33, 0x33, 0x33],
'4': [0x44, 0x44, 0x44], '5': [0x55, 0x55, 0x55], '6': [0x66, 0x66, 0x66],
'7': [0x77, 0x77, 0x77], '8': [0x88, 0x88, 0x88], '9': [0x99, 0x99, 0x99],
'A': [0xAA, 0xAA, 0xAA], 'B': [0xBB, 0xBB, 0xBB], 'C': [0xCC, 0xCC, 0xCC],
'D': [0xDD, 0xDD, 0xDD], 'E': [0xEE, 0xEE, 0xEE], 'F': [0xFF, 0xFF, 0xFF]}
# kivy image test protocol v0: return pixel data for given pattern char
def v0_pattern_pixel(char, alpha, fmt):
if fmt == 'rgba':
if char == 't':
return [0, 0, 0, 0]
return v0_PIXELS[char] + [alpha]
if fmt == 'rgb':
if char == 't':
return [0, 0, 0]
return v0_PIXELS[char]
if fmt == 'gray':
assert char in '0123456789ABCDEF'
return [v0_PIXELS[char][0]]
if fmt == 'graya':
assert char in 't0123456789ABCDEF'
if char == 't':
return [0, 0]
return [v0_PIXELS[char][0]] + [alpha]
raise Exception('v0_pattern_pixel: unknown format {}'.format(fmt))
# kivy image test protocol v0: filename
def v0_filename(w, h, pat, alpha, fmtinfo, testname, ext):
return 'v0_{}x{}_{}_{:02X}_{}_{}_gimp.{}'.format(
w, h, pat, alpha, fmtinfo, testname, ext)
# Saves an image to one or more files. We can't specify these details when
# saving by extension. (This declaration is PEP8 compliant, 's all good)
def save_image(dirname, img, lyr, w, h, pat, alpha, v0_fmtinfo, testname, ext):
def filename(fmtinfo_in=None):
fmtinfo = fmtinfo_in and v0_fmtinfo + '-' + fmtinfo_in or v0_fmtinfo
return v0_filename(w, h, pat, alpha, fmtinfo, testname, ext)
def savepath(fn):
return os.path.join(dirname, fn)
if ext in ('ppm', 'pgm', 'pbm', 'pnm', 'pam'):
fn = filename('ASCII')
pdb.file_pnm_save(img, lyr, savepath(fn), fn, 0)
fn = filename('RAW')
pdb.file_pnm_save(img, lyr, savepath(fn), fn, 1)
elif ext == 'tga':
# FIXME: Last argument to file_tga_save is undocumented, not sure what
fn = filename('RAW')
pdb.file_tga_save(img, lyr, savepath(fn), fn, 0, 0)
fn = filename('RLE')
pdb.file_tga_save(img, lyr, savepath(fn), fn, 1, 0)
elif ext == 'gif':
fn = filename('I0')
pdb.file_gif_save(img, lyr, savepath(fn), fn, 0, 0, 0, 0)
fn = filename('I1')
pdb.file_gif_save(img, lyr, savepath(fn), fn, 1, 0, 0, 0)
elif ext == 'png':
bits = [0, 1]
# interlaced, bkgd block, gama block
for i, b, g in [(i, b, g) for i in bits for b in bits for g in bits]:
fn = filename('I{}B{}G{}'.format(i, b, g))
pdb.file_png_save(img, lyr, savepath(fn), fn, i, 9, b, g, 1, 1, 1)
elif ext == 'sgi':
fn = filename('RAW')
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 0)
fn = filename('RLE')
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 1)
fn = filename('ARLE')
pdb.file_sgi_save(img, lyr, savepath(fn), fn, 2)
elif ext == 'tiff':
fn = filename('RAW')
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 0)
fn = filename('LZW')
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 1)
fn = filename('PACKBITS')
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 2)
fn = filename('DEFLATE')
pdb.file_tiff_save(img, lyr, savepath(fn), fn, 3)
elif ext == 'ras':
fn = filename('RAW')
pdb.file_sunras_save(img, lyr, savepath(fn), fn, 0)
fn = filename('RLE')
pdb.file_sunras_save(img, lyr, savepath(fn), fn, 1)
else:
fn = filename()
pdb.gimp_file_save(img, lyr, savepath(fn), fn)
# Draw pattern on layer, helper for make_images() below
def draw_pattern(lyr, pat, alpha, direction, pixelgetter):
assert 0 <= alpha <= 255
assert re.match('[twxrgbycp0-9A-F]+$', pat)
assert direction in ('x', 'y', 'width', 'height')
dirx = direction in ('x', 'width')
for i in range(0, len(pat)):
pixel = pixelgetter(pat[i], alpha)
if dirx:
pdb.gimp_drawable_set_pixel(lyr, i, 0, len(pixel), pixel)
else:
pdb.gimp_drawable_set_pixel(lyr, 0, i, len(pixel), pixel)
# Create an image from the given pattern, with the specified layertype_in*,
# draw the pattern with given alpha, and save to the given extensions. Gimp
# adjust the encoder accordingly.
# * cheat for indexed formats: draw in RGB(A) and let gimp make palette
def make_images(testname, pattern, alpha, layertype_in, extensions, dirname):
assert testname.upper() == testname
assert len(pattern) > 0
assert len(extensions) > 0
assert isinstance(extensions, (list, tuple))
assert re.match('[wxtrgbcypA-F0-9]+$', pattern)
test_alpha = 'ALPHA' in testname or 'BINARY' in testname
grayscale = 'GRAY' in testname
# Indexed layer types are drawn in RGB/RGBA, and converted later
imgtype, v0_fmtinfo = {
GRAY_IMAGE: (GRAY, 'BPP1G'),
GRAYA_IMAGE: (GRAY, 'BPP2GA'),
RGB_IMAGE: (RGB, 'BPP3'),
RGBA_IMAGE: (RGB, 'BPP4'),
INDEXED_IMAGE: (grayscale and GRAY or RGB, 'IX'),
INDEXEDA_IMAGE: (grayscale and GRAY or RGB, 'IXA'),
}[layertype_in]
# We need to supply pixels of the format of the layer
PP = v0_pattern_pixel
pixelgetter = {
GRAY_IMAGE: lambda c, a: PP(c, a, 'gray'),
GRAYA_IMAGE: lambda c, a: PP(c, a, 'graya'),
RGB_IMAGE: lambda c, a: PP(c, a, 'rgb'),
RGBA_IMAGE: lambda c, a: PP(c, a, 'rgba'),
INDEXED_IMAGE: lambda c, a: PP(c, a, grayscale and 'gray' or 'rgb'),
INDEXEDA_IMAGE: lambda c, a: PP(c, a, grayscale and 'graya' or 'rgba'),
}[layertype_in]
# Pick the correct layer type for indexed formats
layertype = {
INDEXED_IMAGE: grayscale and GRAY_IMAGE or RGB_IMAGE,
INDEXEDA_IMAGE: grayscale and GRAYA_IMAGE or RGBA_IMAGE,
}.get(layertype_in, layertype_in)
# Draw pattern Nx1 and 1xN variations
for direction in 'xy':
# Create the gimp image, and the layer we will draw on
w, h = (direction == 'x') and (len(pattern), 1) or (1, len(pattern))
img = pdb.gimp_image_new(w, h, imgtype)
lyr = pdb.gimp_layer_new(img, w, h, layertype, 'P', 100, NORMAL_MODE)
# Add alpha layer if we are planning on encoding alpha information
if test_alpha:
pdb.gimp_layer_add_alpha(lyr)
pdb.gimp_drawable_fill(lyr, TRANSPARENT_FILL)
pdb.gimp_image_add_layer(img, lyr, 0)
# Draw it
draw_pattern(lyr, pattern, alpha, direction, pixelgetter)
# Convert to indexed before saving, if needed
if layertype_in in (INDEXED_IMAGE, INDEXEDA_IMAGE):
colors = len(set(pattern)) + (test_alpha and 1 or 0)
pdb.gimp_convert_indexed(img, 0, 0, colors, 0, 0, "ignored")
# Save each individual extension
for ext in extensions:
save_image(dirname, img, lyr,
w, h, pattern, alpha, v0_fmtinfo, testname, ext)
# FIXME: this fails?
# pdb.gimp_image_delete(img)
# FIXME: pattern generation needs thought, this sucks..
def makepatterns(allow, include=None, exclude=None):
src = set()
src.update([x for x in allow])
src.update([allow[:i] for i in range(1, len(allow) + 1)])
for i in range(len(allow)):
pick1, pick2 = random.choice(allow), random.choice(allow)
src.update([pick1 + pick2])
for i in range(3, 11) + range(14, 18) + range(31, 34):
src.update([''.join([random.choice(allow) for k in range(i)])])
out = []
for srcpat in src:
if exclude and exclude in srcpat:
continue
if include and include not in srcpat:
out.append(include + srcpat[1:])
continue
out.append(srcpat)
return list(set(out))
def plugin_main(dirname, do_opaque, do_binary, do_alpha):
if not dirname:
pdb.gimp_message("No output directory selected, aborting")
return
if not os.path.isdir(dirname) or not os.access(dirname, os.W_OK):
pdb.gimp_message("Invalid / non-writeable output directory, aborting")
return
tests = []
tests.extend({
0: ['OPAQUE', 'GRAY-OPAQUE'],
2: ['OPAQUE'],
3: ['GRAY-OPAQUE'],
}.get(do_opaque, []))
tests.extend({
0: ['BINARY', 'GRAY-BINARY'],
2: ['BINARY'],
3: ['GRAY-BINARY'],
}.get(do_binary, []))
tests.extend({
0: ['ALPHA', 'GRAY-ALPHA'],
2: ['ALPHA'],
3: ['GRAY-ALPHA'],
}.get(do_alpha, []))
suite_cfg = dict(TESTSUITE_CONFIG)
for testname, cfg in suite_cfg.items():
if testname not in tests:
continue
pchars, inc, exc = cfg.pop('patterns')
if not pchars:
continue
patterns = makepatterns(pchars, inc, exc)
for alpha in cfg.pop('alpha', [255]):
for layertype, exts in cfg.items():
if not exts:
continue
for p in patterns:
make_images(testname, p, alpha, layertype, exts, dirname)
register(
proc_name="kivy_image_testsuite",
help="Creates image test suite for Kivy ImageLoader",
blurb=("Creates image test suite for Kivy ImageLoader. "
"Warning: This will create thousands of images"),
author="For kivy.org, Terje Skjaeveland",
copyright="Copyright 2017 kivy.org (MIT license)",
date="2017",
imagetypes="",
params=[
(PF_DIRNAME, "outputdir", "Output directory:", 0),
(PF_OPTION, "opaque", "OPAQUE tests?", 0,
["All", "None", "OPAQUE", "GRAY-OPAQUE"]),
(PF_OPTION, "binary", "BINARY tests?", 0,
["All", "None", "BINARY", "GRAY-BINARY"]),
(PF_OPTION, "alpha", "ALPHA tests?", 0,
["All", "None", "ALPHA", "GRAY-ALPHA"]),
],
results=[],
function=plugin_main,
menu="<Image>/Tools/_Kivy image testsuite...",
label="Generate images...")
main()