python: Add import/export support for ORA extensions

The OpenRaster specification has two official extensions
for layers - storing if they are pixel locked, and if they are
selected. Krita and MyPaint already support these extensions
on import and export. This patch adds that support to GIMP
as well.
This commit is contained in:
Alx Sa 2025-06-01 15:25:43 +00:00
parent ede910abce
commit 9ab17bf034

View file

@ -141,8 +141,10 @@ def get_layer_attributes(layer):
visible = a.get('visibility', 'visible') != 'hidden' visible = a.get('visibility', 'visible') != 'hidden'
m = a.get('composite-op', 'svg:src-over') m = a.get('composite-op', 'svg:src-over')
layer_mode = layermodes_map.get(m, Gimp.LayerMode.NORMAL) layer_mode = layermodes_map.get(m, Gimp.LayerMode.NORMAL)
selected = a.get('selected', 'false') == 'true'
locked = a.get('edit-locked', 'false') == 'true'
return path, name, x, y, opac, visible, layer_mode return path, name, x, y, opac, visible, layer_mode, selected, locked
def get_group_layer_attributes(layer): def get_group_layer_attributes(layer):
a = layer.attrib a = layer.attrib
@ -151,8 +153,10 @@ def get_group_layer_attributes(layer):
visible = a.get('visibility', 'visible') != 'hidden' visible = a.get('visibility', 'visible') != 'hidden'
m = a.get('composite-op', 'svg:src-over') m = a.get('composite-op', 'svg:src-over')
layer_mode = layermodes_map.get(m, Gimp.LayerMode.NORMAL) layer_mode = layermodes_map.get(m, Gimp.LayerMode.NORMAL)
selected = a.get('selected', 'false') == 'true'
locked = a.get('edit-locked', 'false') == 'true'
return name, 0, 0, opac, visible, layer_mode return name, 0, 0, opac, visible, layer_mode, selected, locked
def thumbnail_ora(procedure, file, thumb_size, args, data): def thumbnail_ora(procedure, file, thumb_size, args, data):
tempdir = tempfile.mkdtemp('gimp-plugin-file-openraster') tempdir = tempfile.mkdtemp('gimp-plugin-file-openraster')
@ -222,6 +226,7 @@ def export_ora(procedure, run_mode, image, file, options, metadata, config, data
tmp_img.set_palette(image.get_palette()) tmp_img.set_palette(image.get_palette())
tmp_layer = Gimp.Layer.new_from_drawable (drawable, tmp_img) tmp_layer = Gimp.Layer.new_from_drawable (drawable, tmp_img)
tmp_layer.set_visible (False)
tmp_img.insert_layer (tmp_layer, None, 0) tmp_img.insert_layer (tmp_layer, None, 0)
pdb_proc = Gimp.get_pdb().lookup_procedure('file-png-export') pdb_proc = Gimp.get_pdb().lookup_procedure('file-png-export')
@ -260,6 +265,12 @@ def export_ora(procedure, run_mode, image, file, options, metadata, config, data
a['opacity'] = str(opac) a['opacity'] = str(opac)
a['visibility'] = 'visible' if visible else 'hidden' a['visibility'] = 'visible' if visible else 'hidden'
a['composite-op'] = gimp_layermodes_map.get(gimp_layer.get_mode(), 'svg:src-over') a['composite-op'] = gimp_layermodes_map.get(gimp_layer.get_mode(), 'svg:src-over')
# ORA Specification extensions
if gimp_layer in image.get_selected_layers():
a['selected'] = "true"
if gimp_layer.get_lock_content():
a['edit-locked'] = "true"
return layer return layer
def add_group_layer(parent, opac, gimp_layer, visible=True): def add_group_layer(parent, opac, gimp_layer, visible=True):
@ -271,6 +282,12 @@ def export_ora(procedure, run_mode, image, file, options, metadata, config, data
a['opacity'] = str(opac) a['opacity'] = str(opac)
a['visibility'] = 'visible' if visible else 'hidden' a['visibility'] = 'visible' if visible else 'hidden'
a['composite-op'] = gimp_layermodes_map.get(gimp_layer.get_mode(), 'svg:src-over') a['composite-op'] = gimp_layermodes_map.get(gimp_layer.get_mode(), 'svg:src-over')
# ORA Specification extensions
if gimp_layer in image.get_selected_layers():
a['selected'] = "true"
if gimp_layer.get_lock_content():
a['edit-locked'] = "true"
return group_layer return group_layer
@ -383,6 +400,7 @@ def load_ora(procedure, run_mode, file, metadata, flags, config, data):
lay_cnt = len(stack) lay_cnt = len(stack)
layer_no = 0 layer_no = 0
selected_layers = []
for item in get_layers(stack): for item in get_layers(stack):
prev_lay = layer_no prev_lay = layer_no
@ -391,11 +409,11 @@ def load_ora(procedure, run_mode, file, metadata, flags, config, data):
continue continue
if item.tag == 'stack': if item.tag == 'stack':
name, x, y, opac, visible, layer_mode = get_group_layer_attributes(item) name, x, y, opac, visible, layer_mode, selected, locked = get_group_layer_attributes(item)
gimp_layer = Gimp.GroupLayer.new(img, name) gimp_layer = Gimp.GroupLayer.new(img, name)
else: else:
path, name, x, y, opac, visible, layer_mode = get_layer_attributes(item) path, name, x, y, opac, visible, layer_mode, selected, locked = get_layer_attributes(item)
if not path.lower().endswith('.png'): if not path.lower().endswith('.png'):
continue continue
@ -433,6 +451,9 @@ def load_ora(procedure, run_mode, file, metadata, flags, config, data):
gimp_layer.set_offsets(x, y) # move to correct position gimp_layer.set_offsets(x, y) # move to correct position
gimp_layer.set_opacity(opac * 100) # a float between 0 and 100 gimp_layer.set_opacity(opac * 100) # a float between 0 and 100
gimp_layer.set_visible(visible) gimp_layer.set_visible(visible)
gimp_layer.set_lock_content(locked)
if selected:
selected_layers.append(gimp_layer)
img.insert_layer(gimp_layer, img.insert_layer(gimp_layer,
parent_groups[-1][0] if parent_groups else None, parent_groups[-1][0] if parent_groups else None,
@ -448,6 +469,9 @@ def load_ora(procedure, run_mode, file, metadata, flags, config, data):
if (layer_no > prev_lay): if (layer_no > prev_lay):
Gimp.progress_update(layer_no/lay_cnt) Gimp.progress_update(layer_no/lay_cnt)
if len(selected_layers) > 0:
img.set_selected_layers(selected_layers)
Gimp.progress_end() Gimp.progress_end()
os.rmdir(tempdir) os.rmdir(tempdir)