This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
mightyscape-1.1-deprecated/extensions/fablabchemnitz/color_harmony/color_harmony/storage/kpl.py

179 lines
6.1 KiB
Python

from os.path import join, basename
from PyQt4 import QtGui
from lxml import etree as ET
from zipfile import ZipFile, ZIP_DEFLATED
from color.colors import *
from color import mixers
from palette.storage.storage import *
MIMETYPE = "application/x-krita-palette"
DEFAULT_GROUP_NAME = "Default (root)"
class KplPalette(Storage):
name = 'kpl'
title = _("Krita 4.0+ palette format")
filters = ["*.kpl"]
can_load = True
can_save = True
@staticmethod
def check(filename):
try:
with ZipFile(filename, 'r') as zf:
mimetype = zf.read("mimetype")
return (mimetype == MIMETYPE)
except Exception as e:
print(e)
return False
@staticmethod
def get_group_names(filename):
result = [DEFAULT_GROUP_NAME]
with ZipFile(filename, 'r') as zf:
colorset_str = zf.read("colorset.xml")
colorset = ET.fromstring(colorset_str)
for xmlgrp in colorset.xpath("//Group"):
name = xmlgrp.attrib['name']
if name is not None:
result.append(name)
return result
@staticmethod
def get_options_widget(dialog, filename):
dialog.options = DEFAULT_GROUP_NAME
def on_group_changed(selector):
def handler():
dialog.options = selector.currentText()
dialog.on_current_changed(filename)
return handler
widget = QtGui.QWidget()
box = QtGui.QHBoxLayout()
label = QtGui.QLabel(_("Group: "))
selector = QtGui.QComboBox()
for group_name in KplPalette.get_group_names(filename):
selector.addItem(group_name)
selector.currentIndexChanged.connect(on_group_changed(selector))
selector.setCurrentIndex(0)
box.addWidget(label)
box.addWidget(selector)
widget.setLayout(box)
return widget
def load(self, mixer, file_r, group_name):
if group_name is None:
group_name = DEFAULT_GROUP_NAME
def find_group(xml):
if group_name == DEFAULT_GROUP_NAME:
return xml
for xmlgrp in xml.xpath("//Group"):
if xmlgrp.attrib['name'] == group_name:
return xmlgrp
return None
self.palette = Palette(mixer)
with ZipFile(file_r, 'r') as zf:
mimetype = zf.read("mimetype")
if mimetype != MIMETYPE:
raise Exception("This is not a valid Krita palette file")
colorset_str = zf.read("colorset.xml")
colorset = ET.fromstring(colorset_str)
self.palette.ncols = int( colorset.attrib['columns'] )
self.palette.name = colorset.attrib.get('name', "Untitled")
group = find_group(colorset)
if group is None:
print(u"Cannot find group by name {}".format(group_name).encode('utf-8'))
return None
else:
self.palette.name = self.palette.name + " - " + group.attrib.get('name', 'Untitled')
all_slots = []
n_colors = 0
for xmlclr in group.findall('ColorSetEntry'):
name = xmlclr.attrib['name']
if xmlclr.attrib['bitdepth'] != 'U8':
print("Skip color {}: unsupported bitdepth".format(name))
continue
rgb = xmlclr.find('RGB')
if rgb is None:
rgb = xmlclr.find('sRGB')
if rgb is None:
print("Skip color {}: no RGB representation".format(name))
continue
r = float(rgb.attrib['r'].replace(',', '.'))
g = float(rgb.attrib['g'].replace(',', '.'))
b = float(rgb.attrib['b'].replace(',', '.'))
clr = Color()
clr.setRGB1((r,g,b))
clr.name = name
slot = Slot(clr)
slot.mode = USER_DEFINED
all_slots.append(slot)
n_colors += 1
if n_colors < DEFAULT_GROUP_SIZE:
self.palette.ncols = n_colors
if not self.palette.ncols:
if n_colors > MAX_COLS:
self.palette.ncols = MAX_COLS
else:
self.palette.ncols = n_colors
#print("Loaded colors: {}".format(len(all_slots)))
self.palette.setSlots(all_slots)
self.palette.meta["SourceFormat"] = "KRITA KPL"
print("Loaded palette: {}x{}".format( self.palette.nrows, self.palette.ncols ))
return self.palette
def save(self, file_w=None):
with ZipFile(file_w, 'w', ZIP_DEFLATED) as zf:
zf.writestr("mimetype", MIMETYPE)
xml = ET.Element("Colorset")
xml.attrib['version'] = '1.0'
xml.attrib['columns'] = str(self.palette.ncols)
xml.attrib['name'] = self.palette.name
xml.attrib['comment'] = self.palette.meta.get("Comment", "Generated by Palette Editor")
for i,row in enumerate(self.palette.slots):
for j,slot in enumerate(row):
color = slot.color
name = color.name
default_name = "Swatch-{}-{}".format(i,j)
if not name:
name = default_name
elem = ET.SubElement(xml, "ColorSetEntry")
elem.attrib['spot'] = color.meta.get("Spot", "false")
elem.attrib['id'] = default_name
elem.attrib['name'] = name
elem.attrib['bitdepth'] = 'U8'
r,g,b = color.getRGB1()
srgb = ET.SubElement(elem, "sRGB")
srgb.attrib['r'] = str(r)
srgb.attrib['g'] = str(g)
srgb.attrib['b'] = str(b)
tree = ET.ElementTree(xml)
tree_str = ET.tostring(tree, encoding='utf-8', pretty_print=True, xml_declaration=False)
zf.writestr("colorset.xml", tree_str)