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/image.py

202 lines
7.2 KiB
Python

from os.path import join, basename, splitext
from math import sqrt, floor
from PyQt4 import QtGui
from color.colors import *
from color import spaces
from color import mixers
from palette.image import PaletteImage
from palette.palette import *
from palette.storage.storage import *
from palette.storage.cluster import *
from palette.storage.table import parse_color_table
from matching.transform import rho, get_center
LOAD_MORE = 1
LOAD_LESS_COMMON = 2
LOAD_LESS_FAREST = 3
LOAD_TABLE = 4
print("Ok")
class DialogOptions(object):
def __init__(self, method):
self.method = method
self.border_x = 10
self.border_y = 10
self.gap_x = 10
self.gap_y = 10
self.size_x = 5
self.size_y = 5
class Image(Storage):
name = 'image'
title = _("Raster image")
filters = ["*.jpg", "*.png", "*.gif"]
can_load = image_loading_supported
can_save = True
@staticmethod
def check(filename):
return True
@staticmethod
def get_options_widget(dialog, filename):
if use_sklearn:
return None
def dependencies():
if dialog.options is None or dialog.options.method != LOAD_TABLE:
table_w.setVisible(False)
else:
table_w.setVisible(True)
def on_method_changed(checked):
method = None
if dialog._more_button.isChecked():
method = LOAD_MORE
elif dialog._less_button.isChecked():
method = LOAD_LESS_COMMON
elif dialog._less_farest.isChecked():
method = LOAD_LESS_FAREST
elif dialog._table.isChecked():
method = LOAD_TABLE
dialog.options = DialogOptions(method)
if method == LOAD_TABLE:
dialog.options.border_x = dialog._border_x.value()
dialog.options.border_y = dialog._border_y.value()
dialog.options.gap_x = dialog._gap_x.value()
dialog.options.gap_y = dialog._gap_y.value()
dialog.options.size_x = dialog._size_x.value()
dialog.options.size_y = dialog._size_y.value()
dependencies()
dialog.on_current_changed(filename)
group_box = QtGui.QGroupBox(_("Loading method"))
dialog._more_button = more = QtGui.QRadioButton(_("Use 49 most used colors"))
dialog._less_button = less = QtGui.QRadioButton(_("Use 9 most used colors and mix them"))
dialog._less_farest = less_farest = QtGui.QRadioButton(_("Use 9 most different colors and mix them"))
dialog._table = table = QtGui.QRadioButton(_("Load table of colors"))
table_w = QtGui.QWidget(dialog)
table_form = QtGui.QFormLayout(table_w)
dialog._border_x = QtGui.QSpinBox(table_w)
dialog._border_x.valueChanged.connect(on_method_changed)
table_form.addRow(_("Border from right/left side, px"), dialog._border_x)
dialog._border_y = QtGui.QSpinBox(table_w)
dialog._border_y.valueChanged.connect(on_method_changed)
table_form.addRow(_("Border from top/bottom side, px"), dialog._border_y)
dialog._gap_x = QtGui.QSpinBox(table_w)
dialog._gap_x.valueChanged.connect(on_method_changed)
table_form.addRow(_("Width of gap between cells, px"), dialog._gap_x)
dialog._gap_y = QtGui.QSpinBox(table_w)
dialog._gap_y.valueChanged.connect(on_method_changed)
table_form.addRow(_("Height of gap between cells, px"), dialog._gap_y)
dialog._size_x = QtGui.QSpinBox(table_w)
dialog._size_x.setValue(5)
dialog._size_x.valueChanged.connect(on_method_changed)
table_form.addRow(_("Number of columns in the table"), dialog._size_x)
dialog._size_y = QtGui.QSpinBox(table_w)
dialog._size_y.setValue(5)
dialog._size_y.valueChanged.connect(on_method_changed)
table_form.addRow(_("Number of rows in the table"), dialog._size_y)
table_w.setLayout(table_form)
dependencies()
more.toggled.connect(on_method_changed)
less.toggled.connect(on_method_changed)
less_farest.toggled.connect(on_method_changed)
table.toggled.connect(on_method_changed)
if dialog.options is None or dialog.options.method == LOAD_MORE:
more.setChecked(True)
elif dialog.options.method == LOAD_LESS_COMMON:
less.setChecked(True)
elif dialog.options.method == LOAD_TABLE:
table.setChecked(True)
else:
less_farest.setChecked(True)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(more)
vbox.addWidget(less)
vbox.addWidget(less_farest)
vbox.addWidget(table)
vbox.addWidget(table_w)
group_box.setLayout(vbox)
return group_box
def save(self, file_w):
w,h = self.palette.ncols * 48, self.palette.nrows * 48
image = PaletteImage( self.palette ).get(w,h)
print("Writing image: " + file_w)
res = image.save(file_w)
if not res:
image.save(file_w, format='PNG')
def load(self, mixer, file_r, options=None):
def _cmp(clr1,clr2):
h1,s1,v1 = clr1.getHSV()
h2,s2,v2 = clr2.getHSV()
x = cmp(h1,h2)
if x != 0:
return x
x = cmp(v1,v2)
if x != 0:
return x
return cmp(s1,s2)
def get_farest(space, colors, n=9):
points = [space.getCoords(c) for c in colors]
center = get_center(points)
srt = sorted(points, key = lambda c: -rho(center, c))
farest = srt[:n]
return [space.fromCoords(c) for c in farest]
if use_sklearn or options is None or options.method is None or options.method == LOAD_MORE:
colors = get_common_colors(file_r)
colors.sort(cmp=_cmp)
self.palette = create_palette(colors, mixer)
return self.palette
elif options.method == LOAD_TABLE:
self.palette = palette = Palette(mixer, nrows=options.size_y, ncols=options.size_x)
colors = parse_color_table(file_r, options)
for i in range(0, options.size_y):
for j in range(0, options.size_x):
palette.paint(i, j, colors[i][j])
return palette
else:
if options.method == LOAD_LESS_FAREST:
colors = get_common_colors(file_r)
colors = get_farest(spaces.RGB, colors)
else:
colors = get_common_colors(file_r, n_clusters=9)
self.palette = palette = Palette(mixer, nrows=7, ncols=7)
palette.paint(0, 0, colors[0])
palette.paint(0, 3, colors[1])
palette.paint(0, 6, colors[2])
palette.paint(3, 0, colors[3])
palette.paint(3, 3, colors[4])
palette.paint(3, 6, colors[5])
palette.paint(6, 0, colors[6])
palette.paint(6, 3, colors[7])
palette.paint(6, 6, colors[8])
palette.need_recalc_colors = True
palette.recalc()
name,ext = splitext(basename(file_r))
self.palette.meta["SourceFormat"] = ext
return palette