[gimp] openraster: Implements exporting and loading group layers.
- From: João Sebastião de Oliveira Bueno Calligaris <jsbueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] openraster: Implements exporting and loading group layers.
- Date: Thu, 26 Feb 2015 14:40:15 +0000 (UTC)
commit 0fad7bb1262e248c26617a29018c50bd493ae3b8
Author: Joao S. O. Bueno <gwidion gmail com>
Date: Thu Feb 26 11:29:07 2015 -0300
openraster: Implements exporting and loading group layers.
This preserves the layer structure and
brings it in pair to MyPaint development branch
(allowing interchange of .ora files with group layers).
Previous behavior on load was oppening all
sub-layers in a flat-space, with no groups,
and flatten layer groups on export.
The implemented behavior accords to the
openraster spec.
plug-ins/pygimp/plug-ins/file-openraster.py | 154 +++++++++++++++++++++------
1 files changed, 121 insertions(+), 33 deletions(-)
---
diff --git a/plug-ins/pygimp/plug-ins/file-openraster.py b/plug-ins/pygimp/plug-ins/file-openraster.py
index 424ebfc..135b9b4 100755
--- a/plug-ins/pygimp/plug-ins/file-openraster.py
+++ b/plug-ins/pygimp/plug-ins/file-openraster.py
@@ -16,8 +16,12 @@
import os, sys, tempfile, zipfile
import xml.etree.ElementTree as ET
+
from gimpfu import *
+NESTED_STACK_END = object()
+
+
layermodes_map = {
"svg:src-over": NORMAL_MODE,
"svg:multiply": MULTIPLY_MODE,
@@ -62,6 +66,17 @@ def get_layer_attributes(layer):
return path, name, x, y, opac, visible, layer_mode
+def get_group_layer_attributes(layer):
+ a = layer.attrib
+ name = a.get('name', '')
+ x = int(a.get('x', '0'))
+ y = int(a.get('y', '0'))
+ opac = float(a.get('opacity', '1.0'))
+ visible = a.get('visibility', 'visible') != 'hidden'
+ m = a.get('composite-op', 'svg:src-over')
+ layer_mode = layermodes_map.get(m, NORMAL_MODE)
+
+ return name, x, y, opac, visible, layer_mode
def thumbnail_ora(filename, thumb_size):
# FIXME: Untested. Does not seem to be used at all? should be run
@@ -89,7 +104,7 @@ def save_ora(img, drawable, filename, raw_filename):
# work around a permission bug in the zipfile library:
# http://bugs.python.org/issue3394
zi = zipfile.ZipInfo(fname)
- zi.external_attr = 0100644 << 16
+ zi.external_attr = int("100644", 8) << 16
zfile.writestr(zi, data)
tempdir = tempfile.mkdtemp('gimp-plugin-file-openraster')
@@ -126,11 +141,11 @@ def save_ora(img, drawable, filename, raw_filename):
orafile.write(tmp, path)
os.remove(tmp)
- def add_layer(x, y, opac, gimp_layer, path, visible=True):
+ def add_layer(parent, x, y, opac, gimp_layer, path, visible=True):
store_layer(img, gimp_layer, path)
# create layer attributes
layer = ET.Element('layer')
- stack.append(layer)
+ parent.append(layer)
a = layer.attrib
a['src'] = path
a['name'] = gimp_layer.name
@@ -141,11 +156,59 @@ def save_ora(img, drawable, filename, raw_filename):
a['composite-op'] = reverse_map(layermodes_map).get(gimp_layer.mode, 'svg:src-over')
return layer
+ def add_group_layer(parent, x, y, opac, gimp_layer, visible=True):
+ # create layer attributes
+ group_layer = ET.Element('stack')
+ parent.append(group_layer)
+ a = group_layer.attrib
+ a['name'] = gimp_layer.name
+ if x:
+ a['x'] = str(x)
+ if y:
+ a['y'] = str(y)
+ a['opacity'] = str(opac)
+ a['visibility'] = 'visible' if visible else 'hidden'
+ a['composite-op'] = reverse_map(layermodes_map).get(gimp_layer.mode, 'svg:src-over')
+ return group_layer
+
+
+ def enumerate_layers(group):
+ for layer in group.layers:
+ if not isinstance(layer, gimp.GroupLayer):
+ yield layer
+ else:
+ yield layer
+ for sublayer in enumerate_layers(layer):
+ yield sublayer
+ yield NESTED_STACK_END
+
# save layers
- for i, lay in enumerate(img.layers):
+ parent_groups = []
+ i = 0
+ for lay in enumerate_layers(img):
+ if lay is NESTED_STACK_END:
+ parent_groups.pop()
+ continue
x, y = lay.offsets
opac = lay.opacity / 100.0 # needs to be between 0.0 and 1.0
- add_layer(x, y, opac, lay, 'data/%03d.png' % i, lay.visible)
+
+ if not parent_groups:
+ path_name = 'data/{:03d}.png'.format(i)
+ i += 1
+ else:
+ path_name = 'data/{}-{:03d}.png'.format(
+ parent_groups[-1][1], parent_groups[-1][2])
+ parent_groups[-1][2] += 1
+
+ parent = stack if not parent_groups else parent_groups[-1][0]
+
+ if isinstance(lay, gimp.GroupLayer):
+ group = add_group_layer(parent, x, y, opac, lay, lay.visible)
+ group_path = ("{:03d}".format(i) if not parent_groups else
+ parent_groups[-1][1] + "-{:03d}".format(parent_groups[-1][2]))
+ parent_groups.append([group, group_path , 0])
+ else:
+ add_layer(parent, x, y, opac, lay, path_name, lay.visible)
# save thumbnail
w, h = img.width, img.height
@@ -171,6 +234,7 @@ def save_ora(img, drawable, filename, raw_filename):
os.remove(filename) # win32 needs that
os.rename(filename + tmp_sufix, filename)
+
def load_ora(filename, raw_filename):
tempdir = tempfile.mkdtemp('gimp-plugin-file-openraster')
original_name = filename
@@ -188,47 +252,71 @@ def load_ora(filename, raw_filename):
img.filename = filename
def get_layers(root):
- """returns a flattened list of all layers under root"""
- res = []
+ """iterates over layers and nested stacks"""
for item in root:
if item.tag == 'layer':
- res.append(item)
+ yield item
elif item.tag == 'stack':
- res += get_layers(item)
- return res
+ yield item
+ for subitem in get_layers(item):
+ yield subitem
+ yield NESTED_STACK_END
+
+ parent_groups = []
- for layer_no, layer in enumerate(get_layers(stack)):
- path, name, x, y, opac, visible, layer_mode = get_layer_attributes(layer)
+ layer_no = 0
+ for item in get_layers(stack):
- if not path.lower().endswith('.png'):
+ if item is NESTED_STACK_END:
+ parent_groups.pop()
continue
- if not name:
- # use the filename without extension as name
- n = os.path.basename(path)
- name = os.path.splitext(n)[0]
- # create temp file. Needed because gimp cannot load files from inside a zip file
- tmp = os.path.join(tempdir, 'tmp.png')
- f = open(tmp, 'wb')
- try:
- data = orafile.read(path)
- except KeyError:
- # support for bad zip files (saved by old versions of this plugin)
- data = orafile.read(path.encode('utf-8'))
- print 'WARNING: bad OpenRaster ZIP file. There is an utf-8 encoded filename that does not have
the utf-8 flag set:', repr(path)
- f.write(data)
- f.close()
-
- # import layer, set attributes and add to image
- gimp_layer = pdb['gimp-file-load-layer'](img, tmp)
+ if item.tag == 'stack':
+ name, x, y, opac, visible, layer_mode = get_group_layer_attributes(item)
+ gimp_layer = gimp.GroupLayer(img)
+
+ else:
+ path, name, x, y, opac, visible, layer_mode = get_layer_attributes(item)
+
+ if not path.lower().endswith('.png'):
+ continue
+ if not name:
+ # use the filename without extension as name
+ n = os.path.basename(path)
+ name = os.path.splitext(n)[0]
+
+ # create temp file. Needed because gimp cannot load files from inside a zip file
+ tmp = os.path.join(tempdir, 'tmp.png')
+ f = open(tmp, 'wb')
+ try:
+ data = orafile.read(path)
+ except KeyError:
+ # support for bad zip files (saved by old versions of this plugin)
+ data = orafile.read(path.encode('utf-8'))
+ print 'WARNING: bad OpenRaster ZIP file. There is an utf-8 encoded filename that does not
have the utf-8 flag set:', repr(path)
+ f.write(data)
+ f.close()
+
+ # import layer, set attributes and add to image
+ gimp_layer = pdb['gimp-file-load-layer'](img, tmp)
+ os.remove(tmp)
gimp_layer.name = name
gimp_layer.mode = layer_mode
gimp_layer.set_offsets(x, y) # move to correct position
gimp_layer.opacity = opac * 100 # a float between 0 and 100
gimp_layer.visible = visible
- img.add_layer(gimp_layer, layer_no)
- os.remove(tmp)
+ pdb.gimp_image_insert_layer(img, gimp_layer,
+ parent_groups[-1][0] if parent_groups else None,
+ parent_groups[-1][1] if parent_groups else layer_no)
+ if parent_groups:
+ parent_groups[-1][1] += 1
+ else:
+ layer_no += 1
+
+ if isinstance(gimp_layer, gimp.GroupLayer):
+ parent_groups.append([gimp_layer, 0])
+
os.rmdir(tempdir)
return img
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]