Last active
June 7, 2018 23:50
-
-
Save rodnaxel/8d4473c0f8329a63f4dfb1f738704717 to your computer and use it in GitHub Desktop.
image converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python3.6 | |
# Name: imagehex | |
# Description: This programm to used convert image to hex sequence | |
# Author: Aleksandr Smirnov ([email protected]) | |
import sys, os | |
from fileinput import filename | |
from PIL import Image | |
from PyQt5 import QtCore | |
from PyQt5.QtGui import * | |
from PyQt5.QtWidgets import * | |
import inspect | |
def whoami(param=False): | |
func_info = "L{0}:{1}()".format(*inspect.stack()[1][2:4]) | |
values = "param={}".format(inspect.getargvalues(inspect.stack()[1][0]).locals) | |
return (func_info + " " + values) if param else (func_info) | |
# I have 4 range of color [0:63], [64:127], [128:191], [192:255] | |
# format RGBAsp = 00_00_00_00 (8 bit color) | |
# | | | +- "b" | |
# | | +---- "g" | |
# | +------- "r" | |
# +---------- "a" | |
class ImageHex: | |
def __init__(self, filename, mode): | |
self.img = Image.open(filename).convert(mode) | |
self.height, self.width = self.img.size | |
def _convert_hex(self, rgba): | |
r, g, b, a = rgba | |
return format((a << 6) | (r << 4) | (g << 2) | b, '#04x') | |
def _get_gradient(self, value): | |
if (value <= 127): | |
return 0 if (value < 63) else 1 | |
else: | |
return 3 if (value > 191) else 2 | |
def _compress_pixel(self, pixel): | |
res = [] | |
for channel in pixel: | |
res.append(self._get_gradient(channel)) | |
return res | |
def compress(self): | |
res = [] | |
for row in range(self.height): | |
line = [] | |
for col in range(self.width): | |
pixel = self.img.getpixel((row, col)) | |
line.append(self._convert_hex(self._compress_pixel(pixel))) | |
res.append(line) | |
return res | |
def get_size(self): | |
return self.img.size | |
def report(seq, filename='output.txt'): | |
with open(filename, 'w') as f: | |
for line in seq: | |
s = 'db' + ' ' + ",".join(line) + ';' + '\n' | |
f.write(s) | |
class ImageApp(QMainWindow): | |
def __init__(self): | |
super().__init__() | |
self.setWindowTitle("Image Converter") | |
self.setMaximumSize(380, 380) | |
self.paths = {'source': '', 'output': ''} | |
self.image = None | |
self.seq = [] | |
self.createUI() | |
def createUI(self): | |
centralWgt = QWidget(self) | |
self.setCentralWidget(centralWgt) | |
# File dialog | |
pathbox = QGroupBox("Directories") | |
fl = QFormLayout(pathbox) | |
self.lines = dict(source=QLineEdit(), output=QLineEdit()) | |
for k,v in self.lines.items(): | |
v.setReadOnly(True) | |
v.setDisabled(True) | |
fl.addRow('{}:'.format(k.capitalize()), v) | |
# Tuner | |
tbox = QGroupBox("Tuner") | |
tbox.setCheckable(True) | |
tbox.setChecked(False) | |
tlayout = QHBoxLayout(tbox) | |
self.sliders = {} | |
for name in ('r', 'g', 'b', 'a'): | |
vbox = QVBoxLayout() | |
slider = QSlider(tbox) | |
slider.setFixedHeight(100) | |
slider.setRange(0,3) | |
slider.setTickPosition(QSlider.TicksBothSides) | |
self.sliders[name] = slider | |
vbox.addWidget(QLabel(name), QtCore.Qt.AlignTop) | |
vbox.addWidget(slider, QtCore.Qt.AlignLeft) | |
tlayout.addLayout(vbox) | |
# Buttons | |
btnWidget = QWidget(self) | |
btnLayout = QHBoxLayout(btnWidget) | |
self.buttons = {} | |
for (name, action) in ( | |
("Open", self.onOpen ), | |
("Convert", self.onConvert), | |
("Report", self.onReport), | |
("About", self.onQuit), | |
("Quit", self.onQuit) | |
): | |
btn = QPushButton(name) | |
btn.clicked.connect(action) | |
btnLayout.addWidget(btn) | |
#if (name == "Convert") or (name == "Report"): | |
# btn.setDisabled(True) | |
self.buttons[name] = btn | |
# Status bar | |
sbar = QWidget() | |
#sbar.setFixedHeight(10) | |
self.image_size = QLabel("unknown") | |
size_layout = QFormLayout(sbar) | |
size_layout.addRow("size:", self.image_size) | |
self.statusBar().addWidget(sbar,2) | |
# Layouts | |
centralLayout = QVBoxLayout(centralWgt) | |
centralLayout.addWidget(pathbox) | |
centralLayout.addWidget(tbox) | |
centralLayout.addWidget(btnWidget, 2) | |
self._center() | |
print(self.height(), self.width()) | |
def _center(self): | |
frameGm = self.frameGeometry() | |
screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos()) | |
centerPoint = QApplication.desktop().screenGeometry(screen).center() | |
frameGm.moveCenter(centerPoint) | |
self.move(frameGm.topLeft()) | |
def closeEvent(self, event): | |
self.onQuit() | |
def onOpen(self): | |
self.paths['source'] = QFileDialog.getOpenFileName(self, "Open Image", "", | |
"Image Files (*.png *.jpg *.bmp)")[0]; | |
self.paths['output'] = os.path.join(os.path.dirname(self.paths['source']), 'output.txt') | |
for k,v in self.lines.items(): | |
self.lines[k].setEnabled(True) | |
self.lines[k].setText(self.paths[k]) | |
self.lines[k].setToolTip(self.paths[k]) | |
self.image = ImageHex(self.paths['source'], mode="RGBA") | |
self.image_size.setText('{} x {}'.format(*self.image.get_size())) | |
self.buttons["Convert"].setEnabled(True) | |
def onConvert(self): | |
self.seq = self.image.compress() | |
report(self.seq, self.paths['output']) | |
self.buttons["Report"].setEnabled(True) | |
def onReport(self): | |
if os.path.exists(self.paths['output']): | |
self.open_report() | |
else: | |
self.statusBar().showMessage("Error! Don't exist file", 1000) | |
def open_report(self): | |
if sys.platform == 'win32': | |
cmd = "start" | |
else: | |
cmd = "xdg-open" | |
if (os.system(" ".join([cmd, self.paths['output']])) != 0): | |
self.statusBar().showMessage("Error. Can't open otput file") | |
def onQuit(self): | |
QtCore.QCoreApplication.exit(0) | |
if __name__ == "__main__": | |
app = QApplication(sys.argv) | |
image_app = ImageApp() | |
image_app.show() | |
sys.exit(app.exec_()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment