2016/11/20(日) [n年前の日記]
#1 [python] GIMPのパレットファイルをプレビューするPySideのスクリプト
PySideを使って、GIMPのパレットファイル(.gpl)を読み込んで表示できるスクリプトを書いてたり。
_palette_select.py

スクリプト + パレットファイル群(*.gpl)を、zipでまとめて置いておくです。スクリプトは CC0 / Public Domain ってことで。
_paletteselect_20161121.zip
_palette_select.py
u"""
GIMPのgplファイルを読み込んでパレットを表示してみるテスト.
動作確認環境 : Windows10 x64 + Python 2.7.12 + PySide 1.2.4
"""
import os
import re
import sys
from PySide.QtCore import * # NOQA
from PySide.QtGui import * # NOQA
class PalettePreview(QGraphicsView):
u"""パレットプレビュー用QGraphicsView."""
valueGetted = Signal(QColor)
def __init__(self, *argv, **keywords):
"""init."""
super(PalettePreview, self).__init__(*argv, **keywords)
self.rgb_data = []
self.w = 256
self.h = 128
self.columns = 16
self.rows = 8
self.cw = self.w / self.columns
self.ch = self.h / self.rows
self.select_color = QColor(Qt.black)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setFixedSize(self.w, self.h)
self.setBackgroundBrush(QBrush(self.get_bg_chip_image()))
self.setScene(QGraphicsScene(self))
pm = QPixmap(self.w, self.h)
pm.fill(Qt.black)
self.pal_canvas_item = QGraphicsPixmapItem(pm)
self.scene().addItem(self.pal_canvas_item)
self.pal_canvas_item.setOffset(0, 0)
def make_palette_preview(self, columns, rgb_data):
u"""パレットプレビュー画像を生成."""
self.rgb_data = rgb_data
self.columns = columns
n = len(rgb_data)
self.rows = n / columns
if n % columns != 0 or n < columns:
self.rows += 1
self.cw = self.w / self.columns
self.ch = self.h / self.rows
# QPixmapに描画
pm = QPixmap(self.w, self. h)
pm.fill(QColor(0, 0, 0, 0))
x, y = 0, 0
for d in self.rgb_data:
r, g, b, _ = d
self.draw_one_palette(pm, x, y, self.cw, self.ch, (r, g, b))
x += self.cw
if x >= self.w or x + self.cw > self.w:
x = 0
y += self.ch
self.pal_canvas_item.setPixmap(pm)
self.scene().setSceneRect(QRectF(0, 0, self.w, self.h))
def draw_one_palette(self, pm, x, y, w, h, rgb):
r, g, b = rgb
brush = QPixmap(w, h)
brush.fill(QColor(r, g, b, 255))
qp = QPainter()
qp.begin(pm)
qp.drawPixmap(x, y, brush)
qp.end()
del qp
del brush
def get_bg_chip_image(self):
u"""背景塗りつぶし用のパターンを作成して返す."""
c0, c1 = 128, 80
im = QImage(16, 16, QImage.Format_ARGB32)
qp = QPainter()
qp.begin(im)
qp.fillRect(0, 0, 16, 16, QColor(c0, c0, c0, 255))
qp.fillRect(0, 0, 8, 8, QColor(c1, c1, c1, 255))
qp.fillRect(8, 8, 8, 8, QColor(c1, c1, c1, 255))
qp.end()
del qp
return im
def mousePressEvent(self, event):
u"""マウスボタンが押された時の処理."""
if event.button() == Qt.LeftButton:
scene_pos = self.mapToScene(event.pos())
x = int(scene_pos.x())
y = int(scene_pos.y())
if x < 0 or x >= self.w or y < 0 or y >= self.h:
return
idx = (y / self.ch) * self.columns + (x / self.cw)
if idx < len(self.rgb_data):
r, g, b, _ = self.rgb_data[idx]
self.select_color.setRgb(r, g, b, 255)
self.valueGetted.emit(self.select_color)
@Slot(QColor)
def changedValue(self, value):
"""get color."""
pass
class PaletteSelect(QWidget):
u"""パレット選択ウィジェット."""
PAL_DIR = "./palettes"
DEF_PAL_NAME = "pet2015"
valueGetted = Signal(QColor)
def __init__(self, *argv, **keywords):
"""init."""
super(PaletteSelect, self).__init__(*argv, **keywords)
self.gpl_data = self.get_gpl_data()
self.gview = PalettePreview(self)
idx = 0
self.combo = QComboBox(self)
lst = sorted(self.gpl_data.keys())
for (i, key) in enumerate(lst):
self.combo.addItem(key)
if key == PaletteSelect.DEF_PAL_NAME:
idx = i
vl = QVBoxLayout()
vl.addWidget(self.combo)
vl.addWidget(self.gview)
self.setLayout(vl)
self.combo.activated[str].connect(self.change_combo)
self.gview.valueGetted[QColor].connect(self.clicked_palette_view)
self.combo.setCurrentIndex(idx)
self.update_preview(PaletteSelect.DEF_PAL_NAME)
def change_combo(self, str):
u"""comboboxが変更された時に呼ばれる処理."""
self.update_preview(str)
def clicked_palette_view(self, col):
u"""パレットプレビューがクリックされた時に呼ばれる処理."""
self.valueGetted.emit(col)
def update_preview(self, pal_name):
u"""パレットプレビューを更新."""
_, columns, rgb_data = self.gpl_data[pal_name]
self.gview.make_palette_preview(columns, rgb_data)
def get_gpl_data(self):
u"""パレットファイル(.gpl)を読み込み."""
dir = PaletteSelect.PAL_DIR
dt = {}
for fname in os.listdir(dir):
path, ext = os.path.splitext(fname)
if ext.lower() == ".gpl":
d = self.read_gpl_file(dir, fname)
if d is not None:
fname, name, columns, rgb_data = d
name = name.lower()
dt[name] = (fname, columns, rgb_data)
return dt
def read_gpl_file(self, dir, fname):
u"""gplファイルを1つ読み込んで内容をタブルで返す."""
name = fname
columns = 16
rgb_data = []
fpath = os.path.join(dir, fname).replace(os.path.sep, '/')
r1 = re.compile(r"Name:\s+(.+)$")
r2 = re.compile(r"Columns:\s+(\d+)$")
r4 = re.compile(r"^\s*(\d+)\s+(\d+)\s+(\d+)\s+(.+)$")
r5 = re.compile(r"^\s*$")
f = open(fpath, 'r')
for (i, s) in enumerate(f):
s = s.rstrip()
if i == 0:
if s != "GIMP Palette":
return None
elif i == 1:
m = r1.match(s)
if m:
name = m.group(1)
else:
print("Error : %s" & s)
return None
elif i == 2:
m = r2.match(s)
if m:
columns = int(m.group(1))
else:
print("Error : %s" & s)
return None
elif s.find("#") == 0:
continue
elif r5.match(s):
continue
else:
m = r4.match(s)
if m:
r, g, b, colname = m.groups()
rgb_data.append([int(r), int(g), int(b), colname])
else:
print("Error : %s" & s)
return None
f.close()
return (fname, name, columns, rgb_data)
class MyWidget(QWidget):
u"""メインウインドウ相当."""
def __init__(self, *argv, **keywords):
"""init."""
super(MyWidget, self).__init__(*argv, **keywords)
self.palview = PaletteSelect(self)
self.lbl = QLabel("Ready.")
l = QVBoxLayout()
l.addWidget(self.palview)
l.addWidget(self.lbl)
self.setLayout(l)
self.palview.valueGetted[QColor].connect(self.clicked_palette)
def clicked_palette(self, col):
u"""パレットプレビューがクリックされた時の処理."""
r, g, b = col.red(), col.green(), col.blue()
self.lbl.setText("RGB=(%d, %d, %d)" % (r, g, b))
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())

スクリプト + パレットファイル群(*.gpl)を、zipでまとめて置いておくです。スクリプトは CC0 / Public Domain ってことで。
_paletteselect_20161121.zip
[ ツッコむ ]
以上、1 日分です。