def saveQDataStream(self): error = None fh = None try: fh = QFile(self.__fname) if not fh.open(QIODevice.WriteOnly): raise IOError(str(fh.errorString())) stream = QDataStream(fh) stream.writeInt32(MovieContainer.MAGIC_NUMBER) stream.writeInt32(MovieContainer.FILE_VERSION) stream.setVersion(QDataStream.Qt_4_2) for key, movie in self.__movies: stream << movie.title stream.writeInt16(movie.year) stream.writeInt16(movie.minutes) stream << movie.acquired << movie.notes except EnvironmentError as e: error = "Failed to save: {0}".format(e) finally: if fh is not None: fh.close() if error is not None: return False, error self.__dirty = False return True, "Saved {0} movie records to {1}".format( len(self.__movies), QFileInfo(self.__fname).fileName())
def saveQDataStream(self): error = None fh = None try: fh = QFile(self.__fname) if not fh.open(QIODevice.WriteOnly): raise IOError(str(fh.errorString())) stream = QDataStream(fh) stream.writeInt32(MovieContainer.MAGIC_NUMBER) stream.writeInt32(MovieContainer.FILE_VERSION) stream.setVersion(QDataStream.Qt_4_2) for key, movie in self.__movies: stream << movie.title stream.writeInt16(movie.year) stream.writeInt16(movie.minutes) stream << movie.acquired << movie.location \ << movie.notes except EnvironmentError as e: error = "Failed to save: {0}".format(e) finally: if fh is not None: fh.close() if error is not None: return False, error self.__dirty = False return True, "Saved {0} movie records to {1}".format( len(self.__movies), QFileInfo(self.__fname).fileName())
def save(self): exception = None fh = None try: if self.filename.isEmpty(): raise IOError("no filename specified for saving") fh = QFile(self.filename) if not fh.open(QIODevice.WriteOnly): raise IOError(str(fh.errorString())) stream = QDataStream(fh) stream.writeInt32(MAGIC_NUMBER) stream.writeInt16(FILE_VERSION) stream.setVersion(QDataStream.Qt_4_1) for ship in self.ships: stream << ship.name << ship.owner << ship.country \ << ship.description stream.writeInt32(ship.teu) self.dirty = False except IOError as e: exception = e finally: if fh is not None: fh.close() if exception is not None: raise exception
def changeResolution(self): fileName = QFileDialog.getOpenFileName( self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open', QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadWrite): QMessageBox.warning( self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) headerVersion = data.readInt32() xdpi = data.readInt32() ydpi = data.readInt32() dialog = ChangeResolutionDialog(xdpi, ydpi, self) if dialog.exec_(): file.seek(4) data.writeInt32(dialog.sbXdpi.value()) data.writeInt32(dialog.sbYdpi.value()) self.status.showMessage("Resolution changed successful", 7000) file.close()
def save_project(canvas, colors, activeSymbol, settings, saveFileName): """ Toplevel writer routine. """ # prepare data structures patternGridItems = get_patternGridItems(canvas) legendItems = canvas.gridLegend.values() patternRepeats = get_patternRepeats(canvas) repeatLegends = canvas.repeatLegend rowRepeats = canvas.rowRepeatTracker rowLabels = canvas.rowLabels columnLabels = canvas.columnLabels textItems = canvas.canvasTextBoxes assert(len(patternRepeats) == len(repeatLegends)) status = None handle = None try: handle = QFile(saveFileName) if not handle.open(QIODevice.WriteOnly | QIODevice.Truncate): raise IOError(unicode(handle.errorString())) stream = QDataStream(handle) # write header stream.writeInt32(MAGIC_NUMBER) stream.writeInt32(API_VERSION) stream.setVersion(QDataStream.Qt_4_5) # write content write_patternGridItems(stream, patternGridItems) write_legendItems(stream, legendItems) write_colors(stream, colors) write_active_symbol(stream, activeSymbol) write_patternRepeats(stream, patternRepeats) write_repeatLegends(stream, repeatLegends) write_rowRepeats(stream, rowRepeats) write_textItems(stream, textItems) write_row_labels(stream, rowLabels) write_column_labels(stream, columnLabels) write_settings(stream, settings) except (IOError, OSError) as e: status = "Failed to save: %s " % e finally: if handle is not None: handle.close() if status is not None: return (False, status) return (True, None)
def save_project(canvas, colors, activeSymbol, settings, saveFileName): """ Toplevel writer routine. """ # prepare data structures patternGridItems = get_patternGridItems(canvas) legendItems = canvas.gridLegend.values() patternRepeats = get_patternRepeats(canvas) repeatLegends = canvas.repeatLegend rowRepeats = canvas.rowRepeatTracker rowLabels = canvas.rowLabels columnLabels = canvas.columnLabels textItems = canvas.canvasTextBoxes assert (len(patternRepeats) == len(repeatLegends)) status = None handle = None try: handle = QFile(saveFileName) if not handle.open(QIODevice.WriteOnly | QIODevice.Truncate): raise IOError(unicode(handle.errorString())) stream = QDataStream(handle) # write header stream.writeInt32(MAGIC_NUMBER) stream.writeInt32(API_VERSION) stream.setVersion(QDataStream.Qt_4_5) # write content write_patternGridItems(stream, patternGridItems) write_legendItems(stream, legendItems) write_colors(stream, colors) write_active_symbol(stream, activeSymbol) write_patternRepeats(stream, patternRepeats) write_repeatLegends(stream, repeatLegends) write_rowRepeats(stream, rowRepeats) write_textItems(stream, textItems) write_row_labels(stream, rowLabels) write_column_labels(stream, columnLabels) write_settings(stream, settings) except (IOError, OSError) as e: status = "Failed to save: %s " % e finally: if handle is not None: handle.close() if status is not None: return (False, status) return (True, None)
def save(self): exception = None fh = None try: if self.filename.isEmpty(): raise IOError, "no filename specified for saving" fh = QFile(self.filename) if not fh.open(QIODevice.WriteOnly): raise IOError, unicode(fh.errorString()) stream = QDataStream(fh) stream.writeInt32(MAGIC_NUMBER) stream.writeInt16(FILE_VERSION) stream.setVersion(QDataStream.Qt_4_1) for ship in self.ships.values(): stream << ship.name << ship.owner << ship.country stream << ship.description stream.writeInt32(ship.teu) self.dirty = False except IOError, err: exception = err
def sendMessage(self, msg, args, id = None): """Sends a message. msg -- The message type. args -- List of message arguments. id -- An optional socket descriptor. If specified, then the message will only be sent if this connection's socket descriptor matches id.""" if id: if self.socketDescriptor() != id: return msg = Message.fromInt(msg) if not msg.validateArgs(args): log.warning("Message %d and args %s have invalid types. Message not sent.", msg, args) return if self.client: log.debug("Sending %s %s", msg, args) elif self.player and self.player.name: log.debug("Sending %s %s to %s", msg, args, self.player) else: log.debug("Sending %s %s to %s", msg, args, self.peerAddress().toString()) data = QByteArray() stream = QDataStream(data, self.WriteOnly) stream.writeInt32(int(msg)) for arg in args: if type(arg) == str: stream.writeInt32(len(arg)) stream.writeRawData(arg) elif type(arg) == int: stream.writeInt32(arg) elif type(arg) == long: stream.writeInt64(arg) self.write(data) self.messageSent.emit(msg, args)
def changeResolution(self): fileName = QFileDialog.getOpenFileName(self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open',QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadWrite): QMessageBox.warning(self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) headerVersion = data.readInt32() xdpi = data.readInt32() ydpi = data.readInt32() dialog = ChangeResolutionDialog(xdpi, ydpi, self) if dialog.exec_(): file.seek(4) data.writeInt32(dialog.sbXdpi.value()) data.writeInt32(dialog.sbYdpi.value()) self.status.showMessage("Resolution changed successful", 7000) file.close()
def save(self): if self.filename.isEmpty(): path = "." fname = QFileDialog.getSaveFileName(self, "Page Designer - Save As", path, "Page Designer Files (*.pgd)") if fname.isEmpty(): return self.filename = fname fh = None try: fh = QFile(self.filename) if not fh.open(QIODevice.WriteOnly): raise IOError, unicode(fh.errorString()) self.scene.clearSelection() stream = QDataStream(fh) stream.setVersion(QDataStream.Qt_4_2) stream.writeInt32(MagicNumber) stream.writeInt16(FileVersion) for item in self.scene.items(): self.writeItemToStream(stream, item) except IOError, e: QMessageBox.warning(self, "Page Designer -- Save Error", "Failed to save {0}: {1}".format(self.filename, e))
class MainWindow(QMainWindow): STD_RIP_FILE = 0x1111FFFF NEW_RIP_FILE = 0x2222FFFF CALDERA_RIP_FILE = 0xFFFF1111 ver = '1.3.10' colors = {'Black':'K', 'Cyan':'C', 'Magenta':'M', 'Yellow':'Y', 'Light Cyan':'c', 'Light Magenta':'m', 'White': 'W', 'Varnish':'V', 'Orange':'O', 'Green':'G', 'Gold':'D', 'Silver':'S', 'Medium Black':'k', 'Light Gray':'g', 'Red':'R', 'Blue':'B', 'Violet':'v', 'Spot Color 1':'1', 'Spot Color 2':'2', 'Spot Color 3':'3', 'Spot Color 4':'4', 'Spot Color 5':'5', 'Spot Color 6':'6', 'Spot Color 7':'7', 'Spot Color 8':'8', 'Spot Color 9':'9'} listColors = ['Black', 'Cyan', 'Magenta', 'Yellow', 'Light Cyan', 'Light Magenta', 'White', 'Varnish', 'Orange', 'Red', 'Green', 'Blue', 'Violet', 'Gold', 'Silver', 'Medium Black', 'Light Gray', 'Spot Color 1', 'Spot Color 2', 'Spot Color 3', 'Spot Color 4', 'Spot Color 5', 'Spot Color 6', 'Spot Color 7', 'Spot Color 8', 'Spot Color 9'] levelGS = {'1 bit per drop (Binary)':1, '2 bit per drop':2, '4 bit per drop (not used)':4 } acceptedFormats = ['tif', 'bmp'] listGSLevel = ['1 bit per drop (Binary)', '2 bit per drop']#,'4 bit per drop (not used)'] black = qRgb(0, 0, 0) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # self.stackLayout = QStackedLayout() self.settings = QSettings('settings.ini', QSettings.IniFormat) self.vLayout = QVBoxLayout() self.toolBar = QToolBar('mainToolBar') self.addToolBar(Qt.RightToolBarArea, self.toolBar) self.centralWidget = QSplitter(Qt.Vertical) self.setCentralWidget(self.centralWidget) self.status = self.statusBar() self.colorWidgets = {} self.levelWidgets = {} self.cmbGS = QComboBox() self.cmbGS.addItems(self.listGSLevel) self.connect(self.cmbGS, SIGNAL("currentIndexChanged(int)"), self.fillCmbGSLevel) self.gsLevel = self.levelGS[self.cmbGS.currentText()] self.xdpiCmbBox = QComboBox() self.xdpiCmbBox.addItems(['720', '600', '360', '300', '180', '150']) self.ydpiCmbBox = QComboBox() self.ydpiCmbBox.addItems(['360', '300', '180', '150', '90', '75']) self.table = QTableWidget(0,4) self.connect(self.table, SIGNAL("cellClicked(int, int)"), self.tableCellActivated) self.table.setHorizontalHeaderLabels(['Filename', 'Color', 'GS Level', 'Size']) self._table = TableWidget(self.table, self.cmbGS, self.xdpiCmbBox, self.ydpiCmbBox) self.connect(self._table, SIGNAL("insertRowAfter(int)"), self.addFile) self.connect(self._table, SIGNAL("removeRowAt(int)"), self.removeFile) # self._table.setAcceptDrops(True) self.table.setAcceptDrops(True) self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.scale = False self.chkBoxScale = QCheckBox("See the Whole") self.connect(self.chkBoxScale, SIGNAL("toggled(bool)"), self.setScale) self.centralWidget.addWidget(self._table) vbox = QVBoxLayout() vbox.addWidget(self.chkBoxScale) vbox.addWidget(self.view) widget = QWidget() widget.setLayout(vbox) self.centralWidget.addWidget(widget) # self.centralWidget.addWidget(self.statusBar) savePrnAction = self.createAction('Create .prn',self.savePrnFile, QKeySequence.Save, 'save_as', 'Create test file') self.toolBar.addAction(savePrnAction) unpackPrnAction = self.createAction('Unpack .prn', self.unpackPrnFile, QKeySequence.Open, 'analyze', 'Unpack prn file') self.toolBar.addAction(unpackPrnAction) editHeaderAction = self.createAction('Edit .prn', self.changeResolution, QKeySequence(Qt.CTRL+Qt.Key_E), 'edit', 'Change print resolution in prn file') self.toolBar.addAction(editHeaderAction) self.pix = QPixmap() self.pix.convertFromImage(QImage()) self.grPixmap = QGraphicsPixmapItem(self.pix) self.scene.addItem(self.grPixmap) # self.view.scale(0.3, 0.3) self.setWindowTitle('PRN Creator {}'.format(self.ver)) self.setWindowIcon(QIcon('icons/icon.png')) desktop = QApplication.desktop() rect = desktop.availableGeometry() pos = self.settings.value('window/pos', QPoint(0,0)) if pos.x() < rect.left(): x = rect.left() else: x = pos.x() if pos.y() < rect.top(): y = rect.top() else: y = pos.y() self.resize(self.settings.value('window/size', QSize(640, 480))) self.move(x, y) self.setWindowState(Qt.WindowState(int(self.settings.value('window/state', 0)))) def setScale(self, scaleBool): if not self.scene.sceneRect().size().isEmpty(): scaleX = self.view.size().width()/self.scene.sceneRect().size().width() scaleY = self.view.size().height()/self.scene.sceneRect().size().height() self.view.resetMatrix() if scaleBool: self.view.scale(min(scaleX, scaleY), min(scaleX, scaleY)) def dragEnterEvent(self, event): event.acceptProposedAction() def dropEvent(self, event): for file in event.mimeData().urls(): fi = QFileInfo(QFile(file.toLocalFile())) if fi.suffix() in self.acceptedFormats: self.addImageToTable(fi.filePath(), self.table.rowCount()) else: self.statusBar.showMessage('File format of {} not supported'.format(fi.fileName()), 5000) event.accept() def createColorComboBox(self, index): self.colorWidgets[index] = QComboBox() for color in self.listColors: self.colorWidgets[index].addItem(QIcon('icons/colors/{}.png'.format(self.colors[color] if color != 'Light Cyan' and color != 'Light Magenta' and color != 'Violet' and color != 'Medium Black' and color != 'Light Gray' else self.colors[color]+'_')), color) return self.colorWidgets[index] def createLevelComboBox(self, index): self.levelWidgets[index] = QComboBox() for level in range(1, 2**self.gsLevel): self.levelWidgets[index].addItem("Level {}".format(level), level) return self.levelWidgets[index] def tableCellActivated(self, row, column): self.scene.removeItem(self.grPixmap) image = self.table.item(row, 0).data(Qt.UserRole) self.pix.convertFromImage(image) self.grPixmap = QGraphicsPixmapItem(self.pix) self.scene.addItem(self.grPixmap) self.scene.setSceneRect(0,0, float(image.width()), float(image.height())) self.setScale(self.chkBoxScale.isChecked()) def closeEvent(self, event): self.settings.setValue('window/size', self.size()) self.settings.setValue('window/pos', self.pos()) self.settings.setValue('window/state', self.windowState()) event.accept() def addFile(self, index): file = QFileDialog.getOpenFileName(self, 'Load image', directory=self.settings.value('directories/dir_open',QDir.currentPath()), filter='Bitmap graphics (*.tif *.bmp);;All (*)') if not file: return self.settings.setValue('directories/dir_open', QFileInfo(file).path()) self.settings.sync() self.addImageToTable(file, index) def addImageToTable(self, file, index): image = QImage(file) if image.format() == QImage.Format_Mono: self.table.insertRow(index) self.table.setItem(index, 0, QTableWidgetItem(QFileInfo(file).fileName())) self.table.item(index, 0).setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled|Qt.ItemIsSelectable) self.table.item(index,0).setData(Qt.UserRole, image) self.table.item(index, 0).setToolTip(file) self.table.setCellWidget(index, 1, self.createColorComboBox(index)) self.table.setCellWidget(index, 2, self.createLevelComboBox(index)) self.table.setCurrentCell(index, 0) self.table.setItem(index, 3, QTableWidgetItem("{}x{}".format(image.width(), image.height()))) self.table.item(index, 3).setFlags(Qt.ItemIsSelectable) else: self.statusBar.showMessage("Tiff file not monochrome ({})".format(image.format())) def removeFile(self, index): self.table.removeRow(index) self.table.setCurrentCell(index-1, 0) try: del self.colorWidgets[index] del self.levelWidgets[index] except (KeyError, IndexError) as err: pass def fillCmbGSLevel(self, index): """ Фунция для заполнения списка уровней значениями. Вызывается при выборе уровня GS """ self.gsLevel = self.levelGS[self.cmbGS.currentText()] for widget in self.levelWidgets: if self.levelWidgets[widget] is not None: self.levelWidgets[widget].clear() for level in range(1, 2**self.gsLevel): self.levelWidgets[widget].addItem("Level {}".format(level), level) def savePrnFile(self): width = 0 height = 0 images = {} for index in range(self.table.rowCount()): image = self.table.item(index, 0).data(Qt.UserRole) color = self.colors[self.table.cellWidget(index, 1).currentText()] if color not in images: images[color] = {} levelCmb = self.table.cellWidget(index, 2) level = levelCmb.itemData(levelCmb.currentIndex()) if level in images[color]: QMessageBox.warning(self, "Error!", "Duplicated GS Level for color!") return else: images[color][level] = image if width != 0: if width != image.width(): QMessageBox.warning(self, "Error!", "Width of images does not match!") return else: width = image.width() if height != 0: if height != image.height(): QMessageBox.warning(self, "Error!", "Height of images does not match!") return else: height = image.height() fileName = QFileDialog.getSaveFileName(self, "Save .prn file", self.settings.value('directories/dir_save', QDir.currentPath()), "PRN Files (*.prn);;BIN Files (*.bin)") if not fileName: return file = QFile(fileName) if not file.open(QFile.WriteOnly): QMessageBox.warning(self, "Prn Creator", "Unable to write file {}:\n{}.".format(self.fileName, file.errorString())) return self.settings.setValue('directories/dir_save', QFileInfo(file).path()) self.testName, status = QInputDialog.getText(self, "Test name", "Enter name of the test to write into file:", text="Test") if not status: QMessageBox.warning(self, "Prn Creator", "Name changed to 'Test'") self.testName = "Test" self.fileName = QFileInfo(file).fileName() self.out = QDataStream(file) self.out.setByteOrder(QDataStream.LittleEndian) colors = '' for color in images: colors+=color self.imgwidth = width self.imgheight = height self.bytesPerLine = int((self.gsLevel*self.imgwidth+31)/32)*4 self.writeNewHeader(colors) pd = QProgressDialog('Writing file ...', 'Cancel', 0, self.imgheight-1, self) pd.setWindowTitle('Creating file...') pd.open() tmp = 0 # Записывать данные будем построчно for row in range(self.imgheight): # обходим по порядку цветов, как расположены в файле for color in colors: # Добиваем строку до длины, кратной 32м байтам for column in range (int(self.bytesPerLine/self.gsLevel*8)): shift = 7-column+int(column/8)*8 pixel = 0 # Упорядочиваем уровни (на всякий) levels = sorted(list(images[color].keys())) # Если изображение меньше длины строки, то if column < self.imgwidth: for level in levels: # Выбираем максимальный уровень из тех, что указаны в данном пикселе на всех слоях if images[color][level].pixel(column, row) == self.black: pixel = level tmp |= (pixel<<shift*self.gsLevel) # Как только сдвиг обнулится, то записываем в файл if not shift: self.out.writeRawData(tmp.to_bytes(self.gsLevel, 'big')) tmp=0 pd.setValue(row) if pd.wasCanceled(): pd.close() file.close() return pd.close() file.close() self.status.showMessage("File created successful", 7000) def writeNewHeader(self, colors): xdpi = int(self.xdpiCmbBox.currentText()) ydpi = int(self.ydpiCmbBox.currentText()) self.paperWidth = 0 colorOrder = colors.encode() while len(colorOrder) < 16: colorOrder += bytes.fromhex('00') self.out.writeInt32(self.NEW_RIP_FILE) self.out.writeInt32(xdpi) self.out.writeInt32(ydpi) self.out.writeInt32(self.bytesPerLine) self.out.writeInt32(self.imgheight) self.out.writeInt32(self.imgwidth) self.out.writeInt32(self.paperWidth) self.out.writeInt32(len(colors)) self.out.writeInt32(self.gsLevel) self.out.writeRawData(colorOrder) name = self.testName.encode(encoding='utf_16')[2:514] # Удаляем первые два байта сигнатуры UTF-16 while len(name) < 256*2: # Дополняем до 256 символов WCHAR name += bytes.fromhex('00') self.out.writeRawData(name) self.out.writeInt32(0) # Зарезервировано def unpackPrnFile(self): fileName = QFileDialog.getOpenFileName(self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open',QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadOnly): QMessageBox.warning(self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) file_name = QFileInfo(file).fileName() headerVersion = int.from_bytes(data.readRawData(4), 'little', signed=False) self.status.showMessage("Header Type: {:#X}".format(headerVersion)) if headerVersion == self.NEW_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) name = b'\xff\xfe' + data.readRawData(512) name = name.decode('utf-16').replace(chr(0), '') zero = data.readInt32() elif headerVersion == self.STD_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() if not bitsperdrop: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) zero = data.readInt32() name = 'Not used in this format' elif headerVersion == self.CALDERA_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() if not bitsperdrop: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) zero = data.readInt32() name = 'Not used in this format' else: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colors = {} for color in colorList: colors[color] = {} for level in range(1, 2**bitsperdrop): colors[color][level] = QImage(imgw, imgh , QImage.Format_Mono) colors[color][level].setColor(0, qRgb(255, 255, 255)) colors[color][level].setColor(1, qRgb(0, 0, 0)) colors[color][level].fill(0) pd = QProgressDialog('Analyze file ...', 'Cancel', 0, imgh-1, self) pd.setWindowTitle('Analyze ...') pd.open() mask = 0xFF>>(8-bitsperdrop) # Получаем маску для текущего количества бит на каплю for row in range(imgh): for color in colorList: for bytenum in range(0, bpl, bitsperdrop): # Получаем номер байта, с которого будем читать byte = int.from_bytes(data.readRawData(bitsperdrop), 'big') for pix in range(8): shift = (7 - pix)*bitsperdrop pixel = (byte>>shift)&mask if pixel > 0: numofpix = 8*bytenum/bitsperdrop + pix if numofpix < imgw: colors[color][pixel].setPixel(numofpix, row, 1) pd.setValue(row) if pd.wasCanceled(): pd.close() file.close() return pd.close() file.close() catalog = QFileDialog.getExistingDirectory(self, directory=self.settings.value('unpacker/dir_save',QDir.currentPath())) if catalog is None: return self.settings.setValue('unpacker/dir_save', catalog) file = QFile("{}\{}_{}.txt".format(catalog, file_name, colorOrder)) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(self, "Prn creator", "Unable create file {}:\n{}.".format(name, file.errorString())) return text = QTextStream(file) text << "Filename: {}\n".format(file_name) text << "Test Name: {}\n\n".format(name) text << "X Resolution: {} dpi\n".format(xdpi) text << "Y Resolution: {} dpi\n".format(ydpi) text << "Image Width: {} pix\n".format(imgw) text << "Image Height: {} pix\n\n".format(imgh) text << "Bits Per Drop: {}\n".format(bitsperdrop) text << "Bytes Per Line: {}\n\n".format(bpl) text << "Number Of Colors: {}\n".format(colnum) text << "Order Of Colors: {}\n\n".format(colorOrder) text << "Paper Width: {}\n".format(ppw) for color in colorList: for level in range(1, 2**bitsperdrop): colors[color][level].save("{}\{}.{}.gs{}.tif".format(catalog, file_name, "{}".format(color) if color.isupper() else "_{}".format(color), level)) self.status.showMessage("Unpacking finished", 7000) def changeResolution(self): fileName = QFileDialog.getOpenFileName(self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open',QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadWrite): QMessageBox.warning(self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) headerVersion = data.readInt32() xdpi = data.readInt32() ydpi = data.readInt32() dialog = ChangeResolutionDialog(xdpi, ydpi, self) if dialog.exec_(): file.seek(4) data.writeInt32(dialog.sbXdpi.value()) data.writeInt32(dialog.sbYdpi.value()) self.status.showMessage("Resolution changed successful", 7000) file.close() def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal='triggered()'): action = QAction(text, self) if icon is not None: action.setIcon(QIcon('icons/{}.png'.format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action
class MainWindow(QMainWindow): STD_RIP_FILE = 0x1111FFFF NEW_RIP_FILE = 0x2222FFFF CALDERA_RIP_FILE = 0xFFFF1111 ver = '1.3.10' colors = { 'Black': 'K', 'Cyan': 'C', 'Magenta': 'M', 'Yellow': 'Y', 'Light Cyan': 'c', 'Light Magenta': 'm', 'White': 'W', 'Varnish': 'V', 'Orange': 'O', 'Green': 'G', 'Gold': 'D', 'Silver': 'S', 'Medium Black': 'k', 'Light Gray': 'g', 'Red': 'R', 'Blue': 'B', 'Violet': 'v', 'Spot Color 1': '1', 'Spot Color 2': '2', 'Spot Color 3': '3', 'Spot Color 4': '4', 'Spot Color 5': '5', 'Spot Color 6': '6', 'Spot Color 7': '7', 'Spot Color 8': '8', 'Spot Color 9': '9' } listColors = [ 'Black', 'Cyan', 'Magenta', 'Yellow', 'Light Cyan', 'Light Magenta', 'White', 'Varnish', 'Orange', 'Red', 'Green', 'Blue', 'Violet', 'Gold', 'Silver', 'Medium Black', 'Light Gray', 'Spot Color 1', 'Spot Color 2', 'Spot Color 3', 'Spot Color 4', 'Spot Color 5', 'Spot Color 6', 'Spot Color 7', 'Spot Color 8', 'Spot Color 9' ] levelGS = { '1 bit per drop (Binary)': 1, '2 bit per drop': 2, '4 bit per drop (not used)': 4 } acceptedFormats = ['tif', 'bmp'] listGSLevel = ['1 bit per drop (Binary)', '2 bit per drop'] #,'4 bit per drop (not used)'] black = qRgb(0, 0, 0) def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # self.stackLayout = QStackedLayout() self.settings = QSettings('settings.ini', QSettings.IniFormat) self.vLayout = QVBoxLayout() self.toolBar = QToolBar('mainToolBar') self.addToolBar(Qt.RightToolBarArea, self.toolBar) self.centralWidget = QSplitter(Qt.Vertical) self.setCentralWidget(self.centralWidget) self.status = self.statusBar() self.colorWidgets = {} self.levelWidgets = {} self.cmbGS = QComboBox() self.cmbGS.addItems(self.listGSLevel) self.connect(self.cmbGS, SIGNAL("currentIndexChanged(int)"), self.fillCmbGSLevel) self.gsLevel = self.levelGS[self.cmbGS.currentText()] self.xdpiCmbBox = QComboBox() self.xdpiCmbBox.addItems(['720', '600', '360', '300', '180', '150']) self.ydpiCmbBox = QComboBox() self.ydpiCmbBox.addItems(['360', '300', '180', '150', '90', '75']) self.table = QTableWidget(0, 4) self.connect(self.table, SIGNAL("cellClicked(int, int)"), self.tableCellActivated) self.table.setHorizontalHeaderLabels( ['Filename', 'Color', 'GS Level', 'Size']) self._table = TableWidget(self.table, self.cmbGS, self.xdpiCmbBox, self.ydpiCmbBox) self.connect(self._table, SIGNAL("insertRowAfter(int)"), self.addFile) self.connect(self._table, SIGNAL("removeRowAt(int)"), self.removeFile) # self._table.setAcceptDrops(True) self.table.setAcceptDrops(True) self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.scale = False self.chkBoxScale = QCheckBox("See the Whole") self.connect(self.chkBoxScale, SIGNAL("toggled(bool)"), self.setScale) self.centralWidget.addWidget(self._table) vbox = QVBoxLayout() vbox.addWidget(self.chkBoxScale) vbox.addWidget(self.view) widget = QWidget() widget.setLayout(vbox) self.centralWidget.addWidget(widget) # self.centralWidget.addWidget(self.statusBar) savePrnAction = self.createAction('Create .prn', self.savePrnFile, QKeySequence.Save, 'save_as', 'Create test file') self.toolBar.addAction(savePrnAction) unpackPrnAction = self.createAction('Unpack .prn', self.unpackPrnFile, QKeySequence.Open, 'analyze', 'Unpack prn file') self.toolBar.addAction(unpackPrnAction) editHeaderAction = self.createAction( 'Edit .prn', self.changeResolution, QKeySequence(Qt.CTRL + Qt.Key_E), 'edit', 'Change print resolution in prn file') self.toolBar.addAction(editHeaderAction) self.pix = QPixmap() self.pix.convertFromImage(QImage()) self.grPixmap = QGraphicsPixmapItem(self.pix) self.scene.addItem(self.grPixmap) # self.view.scale(0.3, 0.3) self.setWindowTitle('PRN Creator {}'.format(self.ver)) self.setWindowIcon(QIcon('icons/icon.png')) desktop = QApplication.desktop() rect = desktop.availableGeometry() pos = self.settings.value('window/pos', QPoint(0, 0)) if pos.x() < rect.left(): x = rect.left() else: x = pos.x() if pos.y() < rect.top(): y = rect.top() else: y = pos.y() self.resize(self.settings.value('window/size', QSize(640, 480))) self.move(x, y) self.setWindowState( Qt.WindowState(int(self.settings.value('window/state', 0)))) def setScale(self, scaleBool): if not self.scene.sceneRect().size().isEmpty(): scaleX = self.view.size().width() / self.scene.sceneRect().size( ).width() scaleY = self.view.size().height() / self.scene.sceneRect().size( ).height() self.view.resetMatrix() if scaleBool: self.view.scale(min(scaleX, scaleY), min(scaleX, scaleY)) def dragEnterEvent(self, event): event.acceptProposedAction() def dropEvent(self, event): for file in event.mimeData().urls(): fi = QFileInfo(QFile(file.toLocalFile())) if fi.suffix() in self.acceptedFormats: self.addImageToTable(fi.filePath(), self.table.rowCount()) else: self.statusBar.showMessage( 'File format of {} not supported'.format(fi.fileName()), 5000) event.accept() def createColorComboBox(self, index): self.colorWidgets[index] = QComboBox() for color in self.listColors: self.colorWidgets[index].addItem( QIcon('icons/colors/{}.png'.format( self.colors[color] if color != 'Light Cyan' and color != 'Light Magenta' and color != 'Violet' and color != 'Medium Black' and color != 'Light Gray' else self.colors[color] + '_')), color) return self.colorWidgets[index] def createLevelComboBox(self, index): self.levelWidgets[index] = QComboBox() for level in range(1, 2**self.gsLevel): self.levelWidgets[index].addItem("Level {}".format(level), level) return self.levelWidgets[index] def tableCellActivated(self, row, column): self.scene.removeItem(self.grPixmap) image = self.table.item(row, 0).data(Qt.UserRole) self.pix.convertFromImage(image) self.grPixmap = QGraphicsPixmapItem(self.pix) self.scene.addItem(self.grPixmap) self.scene.setSceneRect(0, 0, float(image.width()), float(image.height())) self.setScale(self.chkBoxScale.isChecked()) def closeEvent(self, event): self.settings.setValue('window/size', self.size()) self.settings.setValue('window/pos', self.pos()) self.settings.setValue('window/state', self.windowState()) event.accept() def addFile(self, index): file = QFileDialog.getOpenFileName( self, 'Load image', directory=self.settings.value('directories/dir_open', QDir.currentPath()), filter='Bitmap graphics (*.tif *.bmp);;All (*)') if not file: return self.settings.setValue('directories/dir_open', QFileInfo(file).path()) self.settings.sync() self.addImageToTable(file, index) def addImageToTable(self, file, index): image = QImage(file) if image.format() == QImage.Format_Mono: self.table.insertRow(index) self.table.setItem(index, 0, QTableWidgetItem(QFileInfo(file).fileName())) self.table.item( index, 0).setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable) self.table.item(index, 0).setData(Qt.UserRole, image) self.table.item(index, 0).setToolTip(file) self.table.setCellWidget(index, 1, self.createColorComboBox(index)) self.table.setCellWidget(index, 2, self.createLevelComboBox(index)) self.table.setCurrentCell(index, 0) self.table.setItem( index, 3, QTableWidgetItem("{}x{}".format(image.width(), image.height()))) self.table.item(index, 3).setFlags(Qt.ItemIsSelectable) else: self.statusBar.showMessage("Tiff file not monochrome ({})".format( image.format())) def removeFile(self, index): self.table.removeRow(index) self.table.setCurrentCell(index - 1, 0) try: del self.colorWidgets[index] del self.levelWidgets[index] except (KeyError, IndexError) as err: pass def fillCmbGSLevel(self, index): """ Фунция для заполнения списка уровней значениями. Вызывается при выборе уровня GS """ self.gsLevel = self.levelGS[self.cmbGS.currentText()] for widget in self.levelWidgets: if self.levelWidgets[widget] is not None: self.levelWidgets[widget].clear() for level in range(1, 2**self.gsLevel): self.levelWidgets[widget].addItem("Level {}".format(level), level) def savePrnFile(self): width = 0 height = 0 images = {} for index in range(self.table.rowCount()): image = self.table.item(index, 0).data(Qt.UserRole) color = self.colors[self.table.cellWidget(index, 1).currentText()] if color not in images: images[color] = {} levelCmb = self.table.cellWidget(index, 2) level = levelCmb.itemData(levelCmb.currentIndex()) if level in images[color]: QMessageBox.warning(self, "Error!", "Duplicated GS Level for color!") return else: images[color][level] = image if width != 0: if width != image.width(): QMessageBox.warning(self, "Error!", "Width of images does not match!") return else: width = image.width() if height != 0: if height != image.height(): QMessageBox.warning(self, "Error!", "Height of images does not match!") return else: height = image.height() fileName = QFileDialog.getSaveFileName( self, "Save .prn file", self.settings.value('directories/dir_save', QDir.currentPath()), "PRN Files (*.prn);;BIN Files (*.bin)") if not fileName: return file = QFile(fileName) if not file.open(QFile.WriteOnly): QMessageBox.warning( self, "Prn Creator", "Unable to write file {}:\n{}.".format(self.fileName, file.errorString())) return self.settings.setValue('directories/dir_save', QFileInfo(file).path()) self.testName, status = QInputDialog.getText( self, "Test name", "Enter name of the test to write into file:", text="Test") if not status: QMessageBox.warning(self, "Prn Creator", "Name changed to 'Test'") self.testName = "Test" self.fileName = QFileInfo(file).fileName() self.out = QDataStream(file) self.out.setByteOrder(QDataStream.LittleEndian) colors = '' for color in images: colors += color self.imgwidth = width self.imgheight = height self.bytesPerLine = int((self.gsLevel * self.imgwidth + 31) / 32) * 4 self.writeNewHeader(colors) pd = QProgressDialog('Writing file ...', 'Cancel', 0, self.imgheight - 1, self) pd.setWindowTitle('Creating file...') pd.open() tmp = 0 # Записывать данные будем построчно for row in range(self.imgheight): # обходим по порядку цветов, как расположены в файле for color in colors: # Добиваем строку до длины, кратной 32м байтам for column in range(int(self.bytesPerLine / self.gsLevel * 8)): shift = 7 - column + int(column / 8) * 8 pixel = 0 # Упорядочиваем уровни (на всякий) levels = sorted(list(images[color].keys())) # Если изображение меньше длины строки, то if column < self.imgwidth: for level in levels: # Выбираем максимальный уровень из тех, что указаны в данном пикселе на всех слоях if images[color][level].pixel(column, row) == self.black: pixel = level tmp |= (pixel << shift * self.gsLevel) # Как только сдвиг обнулится, то записываем в файл if not shift: self.out.writeRawData(tmp.to_bytes( self.gsLevel, 'big')) tmp = 0 pd.setValue(row) if pd.wasCanceled(): pd.close() file.close() return pd.close() file.close() self.status.showMessage("File created successful", 7000) def writeNewHeader(self, colors): xdpi = int(self.xdpiCmbBox.currentText()) ydpi = int(self.ydpiCmbBox.currentText()) self.paperWidth = 0 colorOrder = colors.encode() while len(colorOrder) < 16: colorOrder += bytes.fromhex('00') self.out.writeInt32(self.NEW_RIP_FILE) self.out.writeInt32(xdpi) self.out.writeInt32(ydpi) self.out.writeInt32(self.bytesPerLine) self.out.writeInt32(self.imgheight) self.out.writeInt32(self.imgwidth) self.out.writeInt32(self.paperWidth) self.out.writeInt32(len(colors)) self.out.writeInt32(self.gsLevel) self.out.writeRawData(colorOrder) name = self.testName.encode(encoding='utf_16')[ 2:514] # Удаляем первые два байта сигнатуры UTF-16 while len(name) < 256 * 2: # Дополняем до 256 символов WCHAR name += bytes.fromhex('00') self.out.writeRawData(name) self.out.writeInt32(0) # Зарезервировано def unpackPrnFile(self): fileName = QFileDialog.getOpenFileName( self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open', QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadOnly): QMessageBox.warning( self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) file_name = QFileInfo(file).fileName() headerVersion = int.from_bytes(data.readRawData(4), 'little', signed=False) self.status.showMessage("Header Type: {:#X}".format(headerVersion)) if headerVersion == self.NEW_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) name = b'\xff\xfe' + data.readRawData(512) name = name.decode('utf-16').replace(chr(0), '') zero = data.readInt32() elif headerVersion == self.STD_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() if not bitsperdrop: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) zero = data.readInt32() name = 'Not used in this format' elif headerVersion == self.CALDERA_RIP_FILE: xdpi = data.readInt32() ydpi = data.readInt32() bpl = data.readInt32() imgh = data.readInt32() imgw = data.readInt32() ppw = data.readInt32() colnum = data.readInt32() bitsperdrop = data.readInt32() if not bitsperdrop: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colorOrder = data.readRawData(16).decode().replace(chr(0), '') colorList = list(colorOrder) zero = data.readInt32() name = 'Not used in this format' else: QMessageBox.warning(self, "Unpacker .prn", "File format not supported") return colors = {} for color in colorList: colors[color] = {} for level in range(1, 2**bitsperdrop): colors[color][level] = QImage(imgw, imgh, QImage.Format_Mono) colors[color][level].setColor(0, qRgb(255, 255, 255)) colors[color][level].setColor(1, qRgb(0, 0, 0)) colors[color][level].fill(0) pd = QProgressDialog('Analyze file ...', 'Cancel', 0, imgh - 1, self) pd.setWindowTitle('Analyze ...') pd.open() mask = 0xFF >> ( 8 - bitsperdrop ) # Получаем маску для текущего количества бит на каплю for row in range(imgh): for color in colorList: for bytenum in range( 0, bpl, bitsperdrop ): # Получаем номер байта, с которого будем читать byte = int.from_bytes(data.readRawData(bitsperdrop), 'big') for pix in range(8): shift = (7 - pix) * bitsperdrop pixel = (byte >> shift) & mask if pixel > 0: numofpix = 8 * bytenum / bitsperdrop + pix if numofpix < imgw: colors[color][pixel].setPixel(numofpix, row, 1) pd.setValue(row) if pd.wasCanceled(): pd.close() file.close() return pd.close() file.close() catalog = QFileDialog.getExistingDirectory( self, directory=self.settings.value('unpacker/dir_save', QDir.currentPath())) if catalog is None: return self.settings.setValue('unpacker/dir_save', catalog) file = QFile("{}\{}_{}.txt".format(catalog, file_name, colorOrder)) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( self, "Prn creator", "Unable create file {}:\n{}.".format(name, file.errorString())) return text = QTextStream(file) text << "Filename: {}\n".format(file_name) text << "Test Name: {}\n\n".format(name) text << "X Resolution: {} dpi\n".format(xdpi) text << "Y Resolution: {} dpi\n".format(ydpi) text << "Image Width: {} pix\n".format(imgw) text << "Image Height: {} pix\n\n".format(imgh) text << "Bits Per Drop: {}\n".format(bitsperdrop) text << "Bytes Per Line: {}\n\n".format(bpl) text << "Number Of Colors: {}\n".format(colnum) text << "Order Of Colors: {}\n\n".format(colorOrder) text << "Paper Width: {}\n".format(ppw) for color in colorList: for level in range(1, 2**bitsperdrop): colors[color][level].save("{}\{}.{}.gs{}.tif".format( catalog, file_name, "{}".format(color) if color.isupper() else "_{}".format(color), level)) self.status.showMessage("Unpacking finished", 7000) def changeResolution(self): fileName = QFileDialog.getOpenFileName( self, 'Load .prn file', directory=self.settings.value('unpacker/dir_open', QDir.currentPath()), filter='PRN files (*.prn *.bin);;All (*)') if not fileName: return file = QFile(fileName) if not file.open(QFile.ReadWrite): QMessageBox.warning( self, "Unpacker .prn", "Unable load file {}:\n{}.".format(fileName, file.errorString())) return self.settings.setValue('unpacker/dir_open', QFileInfo(file).path()) data = QDataStream(file) data.setByteOrder(QDataStream.LittleEndian) headerVersion = data.readInt32() xdpi = data.readInt32() ydpi = data.readInt32() dialog = ChangeResolutionDialog(xdpi, ydpi, self) if dialog.exec_(): file.seek(4) data.writeInt32(dialog.sbXdpi.value()) data.writeInt32(dialog.sbYdpi.value()) self.status.showMessage("Resolution changed successful", 7000) file.close() def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal='triggered()'): action = QAction(text, self) if icon is not None: action.setIcon(QIcon('icons/{}.png'.format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action