gimp/plug-ins/python/colorxhtml.py

241 lines
8.0 KiB
Python
Executable File

#!/usr/bin/env python3
# Gimp-Python - allows the writing of Gimp plugins in Python.
# Copyright (C) 2003, 2005 Manish Singh <yosh@gimp.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import string
import struct
import os.path
import sys
import gi
gi.require_version('Gimp', '3.0')
from gi.repository import Gimp
gi.require_version('GimpUi', '3.0')
from gi.repository import GimpUi
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import Gio
def N_(message): return message
def _(message): return GLib.dgettext(None, message)
escape_table = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;'
}
style_def = """body {
width: 100%%;
font-size: %dpx;
background-color: #000000;
color: #ffffff;
}
"""
preamble = """<!DOCTYPE html>
<html>
<head>
<title>CSS Color XHTML written by GIMP</title>
%s
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<pre>
"""
postamble = """\n</pre>\n</body>\n</html>\n"""
def export_colorxhtml(procedure, run_mode, image, file, options, metadata, config, data):
if file is None:
error = 'No file given'
return procedure.new_return_values(Gimp.PDBStatusType.CALLING_ERROR,
GLib.Error(error))
if run_mode == Gimp.RunMode.INTERACTIVE:
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
GimpUi.init ("file-colorxhtml-export")
dialog = GimpUi.ProcedureDialog.new(procedure, config, _("Save as colored HTML text..."))
dialog.fill_frame("file-frame", "source-file", False, "aux-file")
# Set the characters text field as not enabled when the user chooses a file
dialog.set_sensitive("characters", True, config, "source-file", True)
dialog.fill(["characters", "file-frame", "font-size", "separate"])
if not dialog.run():
return procedure.new_return_values(Gimp.PDBStatusType.CANCEL,
GLib.Error())
source_file = config.get_property("source-file")
characters = config.get_property("characters")
size = config.get_property("font-size");
separate = config.get_property("separate")
aux_file = config.get_property("aux-file")
if source_file and aux_file:
characters = aux_file.get_path()
#For now, work with a single layer
layer = image.get_layers()[0]
width = layer.get_width()
height = layer.get_height()
bpp = layer.get_bpp()
html = open(file.peek_path(), 'w')
if separate:
dirname, cssfile = os.path.split(file.peek_path())
cssfile = os.path.splitext(cssfile)[0] + '.css'
cssname = os.path.join(dirname, cssfile)
css = open(cssname, 'w')
if source_file:
characters_file = open(characters, 'r')
chars = characters_file.read()
characters_file.close()
else:
chars = characters
# Remove unprintable characters from "chars".
# TODO: This only handles ascii files. It would be nice to handle unicode
# files, so this could work for any language.
goodchars = string.digits + string.ascii_letters + string.punctuation
badchars = ''.join(chr(i) for i in range(256) if chr(i) not in goodchars)
allchars = str.maketrans('', '', badchars)
chars = chars.translate(allchars)
data = [escape_table.get(c, c) for c in chars]
if data:
data.reverse()
else:
data = list('X' * 80)
Gimp.progress_init(_("Saving as colored XHTML"))
style = style_def % size
if separate:
ss = '<link rel="stylesheet" type="text/css" href="%s" />' % cssfile
css.write(style)
else:
ss = '<style type="text/css">\n%s</style>' % style
html.write(preamble % ss)
colors = {}
chars = []
for y in range(0, height):
# The characters in "chars" will be used to draw the next row.
# Lets fill "chars" with data so it has at least enough characters.
while len(chars) < width:
chars[0:0] = data
for x in range(0, width):
pixel_color = layer.get_pixel(x, y)
pixel_rgb = pixel_color.get_rgba()
pixel_tuple = (int(pixel_rgb[0] * 255),
int(pixel_rgb[1] * 255),
int(pixel_rgb[2] * 255))
color = '%02x%02x%02x' % pixel_tuple
style = 'background-color:black; color:#%s;' % color
char = chars.pop()
if separate:
if color not in colors:
css.write('span.N%s { %s }\n' % (color, style))
colors[color] = 1
html.write('<span class="N%s">%s</span>' % (color, char))
else:
html.write('<span style="%s">%s</span>' % (style, char))
html.write('\n')
Gimp.progress_update(y / float(height))
html.write(postamble)
html.close()
if separate:
css.close()
return Gimp.ValueArray.new_from_values([
GObject.Value(Gimp.PDBStatusType, Gimp.PDBStatusType.SUCCESS)
])
class ColorXhtml(Gimp.PlugIn):
## GimpPlugIn virtual methods ##
def do_set_i18n(self, procname):
return True, 'gimp30-python', None
def do_query_procedures(self):
return [ 'file-colorxhtml-export' ]
def do_create_procedure(self, name):
procedure = None
if name == 'file-colorxhtml-export':
procedure = Gimp.ExportProcedure.new(self, name,
Gimp.PDBProcType.PLUGIN,
False, export_colorxhtml, None)
procedure.set_image_types("RGB")
procedure.set_documentation (
_("Save as colored HTML text"),
"Saves the image as colored XHTML text (based on Perl version by Marc Lehmann)",
name)
procedure.set_menu_label(_("Colored HTML text"))
procedure.set_attribution("Manish Singh and Carol Spears",
"(c) GPL V3.0 or later",
"2003")
procedure.set_extensions ("html,xhtml");
procedure.add_boolean_argument ("source-file",
_("Rea_d characters from file"),
_("Read characters from file, if true, or use text entry"),
False, GObject.ParamFlags.READWRITE)
procedure.add_string_argument ("characters", _("Charac_ters"),
_("Characters that will be used as colored pixels."),
"foo", GObject.ParamFlags.READWRITE)
procedure.add_int_argument ("font-size", _("Fo_nt size in pixels"),
_("Font size in pixels"), 5, 100, 10,
GObject.ParamFlags.READWRITE)
procedure.add_boolean_argument ("separate", _("_Write a separate CSS file"),
_("Write a separate CSS file"),
False, GObject.ParamFlags.READWRITE)
#GUI only, used to create a widget to open a file if source-file is enabled
procedure.add_file_aux_argument ("aux-file", _("Choose File"),
"", GObject.ParamFlags.READWRITE)
return procedure
Gimp.main(ColorXhtml.__gtype__, sys.argv)