summaryrefslogtreecommitdiffstats
path: root/plug-ins/pygimp/plug-ins/py-slice.py
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/pygimp/plug-ins/py-slice.py')
-rwxr-xr-xplug-ins/pygimp/plug-ins/py-slice.py457
1 files changed, 457 insertions, 0 deletions
diff --git a/plug-ins/pygimp/plug-ins/py-slice.py b/plug-ins/pygimp/plug-ins/py-slice.py
new file mode 100755
index 0000000..90159aa
--- /dev/null
+++ b/plug-ins/pygimp/plug-ins/py-slice.py
@@ -0,0 +1,457 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+#Copyright (c) Manish Singh
+#javascript animation support by Joao S. O. Bueno Calligaris (2004)
+
+# 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/>.
+
+# (c) 2003 Manish Singh.
+#"Guillotine implemented ala python, with html output
+# (based on perlotine by Seth Burgess)",
+# Modified by João S. O. Bueno Calligaris to allow dhtml animations (2005)
+
+import os
+
+from gimpfu import *
+import os.path
+
+gettext.install("gimp20-python", gimp.locale_directory, unicode=True)
+
+def pyslice(image, drawable, save_path, html_filename,
+ image_basename, image_extension, separate,
+ image_path, cellspacing, animate, skip_caps):
+
+ cellspacing = int (cellspacing)
+
+ if animate:
+ count = 0
+ drw = []
+ #image.layers is a reversed list of the layers on the image
+ #so, count indexes from number of layers to 0.
+ for i in xrange (len (image.layers) -1, -1, -1):
+ if image.layers[i].visible:
+ drw.append(image.layers[i])
+ count += 1
+ if count == 3:
+ break
+
+
+ vert, horz = get_guides(image)
+
+ if len(vert) == 0 and len(horz) == 0:
+ return
+
+ gimp.progress_init(_("Slice"))
+ progress_increment = 1 / ((len(horz) + 1) * (len(vert) + 1))
+ progress = 0.0
+
+ def check_path(path):
+ path = os.path.abspath(path)
+
+ if not os.path.exists(path):
+ os.mkdir(path)
+
+ return path
+
+ save_path = check_path(save_path)
+
+ if not os.path.isdir(save_path):
+ save_path = os.path.dirname(save_path)
+
+ if separate:
+ image_relative_path = image_path
+ if not image_relative_path.endswith("/"):
+ image_relative_path += "/"
+ image_path = check_path(os.path.join(save_path, image_path))
+ else:
+ image_relative_path = ''
+ image_path = save_path
+
+ tw = TableWriter(os.path.join(save_path, html_filename),
+ cellspacing=cellspacing, animate=animate)
+
+ top = 0
+
+ for i in range(0, len(horz) + 1):
+ if i == len(horz):
+ bottom = image.height
+ else:
+ bottom = image.get_guide_position(horz[i])
+
+ tw.row_start()
+
+ left = 0
+
+ for j in range(0, len(vert) + 1):
+ if j == len(vert):
+ right = image.width
+ else:
+ right = image.get_guide_position(vert[j])
+ if (skip_caps and
+ (
+ (len(horz) >= 2 and (i == 0 or i == len(horz) )) or
+ (len(vert) >= 2 and (j == 0 or j == len(vert) ))
+ )
+ ):
+ skip_stub = True
+ else:
+ skip_stub = False
+
+ if (not animate or skip_stub):
+ src = (image_relative_path +
+ slice (image, None, image_path,
+ image_basename, image_extension,
+ left, right, top, bottom, i, j, ""))
+ else:
+ src = []
+ for layer, postfix in zip (drw, ("", "hover", "clicked")):
+ src.append (image_relative_path +
+ slice(image, layer, image_path,
+ image_basename, image_extension,
+ left, right, top, bottom, i, j, postfix))
+
+ tw.cell(src, right - left, bottom - top, i, j, skip_stub)
+
+ left = right + cellspacing
+
+ progress += progress_increment
+ gimp.progress_update(progress)
+
+ tw.row_end()
+
+ top = bottom + cellspacing
+
+ tw.close()
+
+def slice(image, drawable, image_path, image_basename, image_extension,
+ left, right, top, bottom, i, j, postfix):
+ if postfix:
+ postfix = "_" + postfix
+ src = "%s_%d_%d%s.%s" % (image_basename, i, j, postfix, image_extension)
+ filename = os.path.join(image_path, src)
+
+ if not drawable:
+ temp_image = image.duplicate()
+ temp_drawable = temp_image.active_layer
+ else:
+ if image.base_type == INDEXED:
+ #gimp_layer_new_from_drawable doesn't work for indexed images.
+ #(no colormap on new images)
+ original_active = image.active_layer
+ image.active_layer = drawable
+ temp_image = image.duplicate()
+ temp_drawable = temp_image.active_layer
+ image.active_layer = original_active
+ temp_image.disable_undo()
+ #remove all layers but the intended one
+ while len (temp_image.layers) > 1:
+ if temp_image.layers[0] != temp_drawable:
+ pdb.gimp_image_remove_layer (temp_image, temp_image.layers[0])
+ else:
+ pdb.gimp_image_remove_layer (temp_image, temp_image.layers[1])
+ else:
+ temp_image = pdb.gimp_image_new (drawable.width, drawable.height,
+ image.base_type)
+ temp_drawable = pdb.gimp_layer_new_from_drawable (drawable, temp_image)
+ temp_image.insert_layer (temp_drawable)
+
+ temp_image.disable_undo()
+ temp_image.crop(right - left, bottom - top, left, top)
+ if image_extension == "gif" and image.base_type == RGB:
+ pdb.gimp_image_convert_indexed (temp_image, CONVERT_DITHER_NONE,
+ CONVERT_PALETTE_GENERATE, 255,
+ True, False, False)
+ if image_extension == "jpg" and image.base_type == INDEXED:
+ pdb.gimp_image_convert_rgb (temp_image)
+
+ pdb.gimp_file_save(temp_image, temp_drawable, filename, filename)
+
+ gimp.delete(temp_image)
+ return src
+
+class GuideIter:
+ def __init__(self, image):
+ self.image = image
+ self.guide = 0
+
+ def __iter__(self):
+ return iter(self.next_guide, 0)
+
+ def next_guide(self):
+ self.guide = self.image.find_next_guide(self.guide)
+ return self.guide
+
+def get_guides(image):
+ vguides = []
+ hguides = []
+
+ for guide in GuideIter(image):
+ orientation = image.get_guide_orientation(guide)
+
+ guide_position = image.get_guide_position(guide)
+
+ if guide_position > 0:
+ if orientation == ORIENTATION_VERTICAL:
+ if guide_position < image.width:
+ vguides.append((guide_position, guide))
+ elif orientation == ORIENTATION_HORIZONTAL:
+ if guide_position < image.height:
+ hguides.append((guide_position, guide))
+
+ def position_sort(x, y):
+ return cmp(x[0], y[0])
+
+ vguides.sort(position_sort)
+ hguides.sort(position_sort)
+
+ vguides = [g[1] for g in vguides]
+ hguides = [g[1] for g in hguides]
+
+ return vguides, hguides
+
+class TableWriter:
+ def __init__(self, filename, cellpadding=0, cellspacing=0, border=0,
+ animate=False):
+
+ self.filename = filename
+ self.table_attrs = {}
+
+ #Hellraisen IE 6 doesn't support CSS for table control.
+ self.table_attrs['cellpadding'] = cellpadding
+ self.table_attrs['cellspacing'] = cellspacing
+ self.table_attrs['border'] = border
+
+ self.image_prefix = os.path.basename (filename)
+ self.image_prefix = self.image_prefix.split(".")[0]
+ self.image_prefix = self.image_prefix.replace ("-", "_")
+ self.image_prefix = self.image_prefix.replace (" ", "_")
+
+
+ if animate:
+ self.animate = True
+ self.images = []
+ else:
+ self.animate = False
+
+ if os.path.exists (filename):
+ #The plug-in is running to overwrite a previous
+ #version of the file. This will parse the href targets already
+ #in the file to preserve them.
+ self.urls = self.parse_urls ()
+ else:
+ self.urls = []
+
+ self.url_index = 0
+
+ self.html = open(filename, 'wt')
+ self.open()
+
+ def next_url (self):
+ if self.url_index < len (self.urls):
+ self.url_index += 1
+ return self.urls [self.url_index - 1]
+ else:
+ #Default url to use in the anchor tags:
+ return ("#")
+
+ def write(self, s, vals=None):
+ if vals:
+ s = s % vals
+
+ self.html.write(s + '\n')
+
+ def open(self):
+ out = '''<!--HTML SNIPPET GENERATED BY GIMP
+
+WARNING!! This is NOT a fully valid HTML document, it is rather a piece of
+HTML generated by GIMP's py-slice plugin that should be embedded in an HTML
+or XHTML document to be valid.
+
+Replace the href targets in the anchor (<a >) for your URLS to have it working
+as a menu.
+ -->\n'''
+ out += '<table'
+
+ for attr, value in self.table_attrs.iteritems():
+ out += ' %s="%s"' % (attr, value)
+
+ out += '>'
+
+ self.write(out)
+
+ def close(self):
+ self.write('</table>\n')
+ prefix = self.image_prefix
+ if self.animate:
+ out = """
+<script language="javascript" type="text/javascript">
+/* Made with GIMP */
+
+/* Preload images: */
+ images_%s = new Array();
+ \n""" % prefix
+ for image in self.images:
+ for type_ in ("plain", "hover", "clicked"):
+ if image.has_key(type_):
+ image_index = ("%d_%d_%s" %
+ (image["index"][0],
+ image["index"][1], type_))
+ out += (" images_%s[\"%s\"] = new Image();\n" %
+ (prefix, image_index))
+ out += (" images_%s[\"%s\"].src = \"%s\";\n" %
+ (prefix, image_index, image[type_]))
+
+ out+= """
+function exchange (image, images_array_name, event)
+ {
+ name = image.name;
+ images = eval (images_array_name);
+
+ switch (event)
+ {
+ case 0:
+ image.src = images[name + "_plain"].src;
+ break;
+ case 1:
+ image.src = images[name + "_hover"].src;
+ break;
+ case 2:
+ image.src = images[name + "_clicked"].src;
+ break;
+ case 3:
+ image.src = images[name + "_hover"].src;
+ break;
+ }
+
+ }
+</script>
+<!--
+End of the part generated by GIMP
+-->
+"""
+ self.write (out)
+
+
+ def row_start(self):
+ self.write(' <tr>')
+
+ def row_end(self):
+ self.write('</tr>\n')
+
+ def cell(self, src, width, height, row=0, col=0, skip_stub = False):
+ if isinstance (src, list):
+ prefix = "images_%s" % self.image_prefix
+ self.images.append ({"index" : (row, col), "plain" : src[0]})
+
+ out = (' <td><a href="%s"><img alt="" src="%s" ' +
+ 'style="width: %dpx; height: %dpx; border-width: 0px" \n') %\
+ (self.next_url(), src[0], width, height)
+ out += 'name="%d_%d" \n' % (row, col)
+ if len(src) >= 2:
+ self.images[-1]["hover"] = src [1]
+ out += """ onmouseout="exchange(this, '%s', 0);"\n""" % \
+ prefix
+ out += """ onmouseover="exchange(this, '%s', 1);"\n""" % \
+ prefix
+ if len(src) >= 3:
+ self.images[-1]["clicked"] = src [2]
+ out += """ onmousedown="exchange(this, '%s', 2);"\n""" % \
+ prefix
+ out += """ onmouseup="exchange(this, '%s', 3);"\n""" % \
+ prefix
+
+
+
+ out += "/></a></td>\n"
+
+ else:
+ if skip_stub:
+ out = (' <td><img alt=" " src="%s" style="width: %dpx; ' +
+ ' height: %dpx; border-width: 0px;"></td>') % \
+ (src, width, height)
+ else:
+ out = (' <td><a href="#"><img alt=" " src="%s" ' +
+ ' style="width: %dpx; height: %dpx; border-width: 0px;">' +
+ '</a></td>') % (src, width, height)
+ self.write(out)
+ def parse_urls (self):
+ """
+ This will parse any url targets in the href="XX" fields
+ of the given file and return then as a list
+ """
+ import re
+ url_list = []
+ try:
+ html_file = open (self.filename)
+
+ # Regular expression to pick everything up to the next
+ # doublequote character after finding the sequence 'href="'.
+ # The found sequences will be returned as a list by the
+ # "findall" method.
+ expr = re.compile (r"""href\=\"([^\"]*?)\"""")
+ url_list = expr.findall (html_file.read (2 ** 18))
+ html_file.close()
+
+ except:
+ # silently ignore any errors parsing this. The file being
+ # overwritten may not be a file created by py-slice.
+ pass
+
+ return url_list
+
+
+register(
+ "python-fu-slice",
+ # table snippet means a small piece of HTML code here
+ N_("Cuts an image along its guides, creates images and a HTML table snippet"),
+ """Add guides to an image. Then run this. It will cut along the guides,
+ and give you the html to reassemble the resulting images. If you
+ choose to generate javascript for onmouseover and clicked events, it
+ will use the lower three visible layers on the image for normal,
+ onmouseover and clicked states, in that order. If skip caps is
+ enabled, table cells on the edge of the table won't become animated,
+ and its images will be taken from the active layer.""",
+ "Manish Singh",
+ "Manish Singh",
+ "2003",
+ _("_Slice..."),
+ "*",
+ [
+ (PF_IMAGE, "image", "Input image", None),
+ (PF_DRAWABLE, "drawable", "Input drawable", None),
+ (PF_DIRNAME, "save-path", _("Path for HTML export"), os.getcwd()),
+ (PF_STRING, "html-filename", _("Filename for export"), "slice.html"),
+ (PF_STRING, "image-basename", _("Image name prefix"), "slice"),
+ (PF_RADIO, "image-extension", _("Image format"), "gif", (("gif", "gif"), ("jpg", "jpg"), ("png", "png"))),
+ (PF_TOGGLE, "separate-image-dir", _("Separate image folder"),
+ False),
+ (PF_STRING, "relative-image-path", _("Folder for image export"), "images"),
+ (PF_SPINNER, "cellspacing", _("Space between table elements"), 0,
+ (0,15,1)),
+ (PF_TOGGLE, "animate", _("Javascript for onmouseover and clicked"),
+ False),
+ # table caps are table cells on the edge of the table
+ (PF_TOGGLE, "skip-caps", _("Skip animation for table caps"), True)
+ ],
+ [],
+ pyslice,
+ menu="<Image>/Filters/Web",
+ domain=("gimp20-python", gimp.locale_directory)
+ )
+
+main()