class Thumbnail(QStyledItemDelegate): '''Styled Item Delegate paints images directly to the List View at the desired resolution''' def __init__(self): super().__init__() self.reader = QImageReader() def sizeHint(self, option, index): item = index.model().data(index, role=Qt.UserRole) with Image.open(item) as img: width, height = img.size dx = option.rect.width() / width height *= dx size = QSize(option.rect.width(), height) self.reader.setScaledSize(size) return size def paint(self, painter, option, index): painter.save() item = index.model().data(index, role=Qt.UserRole) self.reader.setFileName(item) image = QPixmap.fromImageReader(self.reader) painter.translate(option.rect.x(), option.rect.y()) if option.state & (QStyle.State_Selected | QStyle.State_MouseOver): painter.setOpacity(1) else: painter.setOpacity(0.90) painter.drawPixmap(0, 0, image) painter.restore()
def savePascalVocFormat(self, filename, shapes, imagePath, imageData, lineColor=None, fillColor=None, databaseSrc=None): imgFolderPath = os.path.dirname(imagePath) imgFolderName = os.path.split(imgFolderPath)[-1] imgFileName = os.path.basename(imagePath) #imgFileNameWithoutExt = os.path.splitext(imgFileName)[0] # Read from file path because self.imageData might be empty if saving to # Pascal format reader0 = QImageReader(imagePath) reader0.setAutoTransform(True) image = reader0.read() imageShape = [ image.height(), image.width(), 1 if image.isGrayscale() else 3 ] writer = PascalVocWriter(imgFolderName, imgFileName, imageShape, localImgPath=imagePath) writer.verified = self.verified for shape in shapes: points = shape['points'] label = shape['label'] # Add Chris difficult = int(shape['difficult']) direction = shape['direction'] isRotated = shape['isRotated'] extra_text = shape['extra_text'] if not isRotated: bndbox = LabelFile.convertPoints2BndBox(points) writer.addBndBox(bndbox[0], bndbox[1], bndbox[2], bndbox[3], label, difficult, extra_text) else: #if shape is rotated box, save as rotated bounding box robndbox = LabelFile.convertPoints2RotatedBndBox(shape) writer.addRotatedBndBox(robndbox[0], robndbox[1], robndbox[2], robndbox[3], robndbox[4], label, difficult, extra_text) writer.save(targetFile=filename) return
class ImageDocument(Document, name="Image"): extensions = [ "." + f.data().decode("utf-8") for f in QImageReader.supportedImageFormats() ] def __init__(self, path=None): super().__init__(path) self._pixmap = QPixmap(str(path)) if path else QPixmap() def pixmap(self): return self._pixmap def setPixmap(self, pixmap): self._pixmap = pixmap @staticmethod def detectTypeFromName(name: str): return PurePath(name).suffix in ImageDocument.extensions @staticmethod def detectTypeFromSample(sample): return False def reload(self): self._pixmap = QPixmap(str(self.path()))
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.widget = QWidget() self.shortcuts = {} self.shortcuts_labels = {} self.feature = FeatureStyle() self.pal = QPalette() self.text_widget = QLabel() self.labels_widget = QWidget() self.icon_widget = QLabel() self.icon_reader = QImageReader() self.icon_file = None self.icon_size = 60 self.index = None self.start()
def images_load(self, images): """ Take list of images and display in main window """ num = len(images) if num == 0: return width = self.width() maxcol = self.max_columns if num < maxcol: maxcol = num colwidth = width / maxcol # Set proper widget for display of multiple or single images if num > 1: self.setCurrentWidget(self.multiple_image) # Clear the layout while self.multiple_image_layout.count(): self.multiple_image_layout.removeAt(0) # Clear the scene for child in self.panel.childItems(): child.setParent(None) else: self.setCurrentWidget(self.single_image) self.single_image_scene.clear() self.single_image_scene.setSceneRect( self.single_image_scene.itemsBoundingRect()) # Display images or image row = 0 col = -1 for index, image in images.items(): col += 1 if col >= maxcol: col = 0 row += 1 # Used any cached reads if index not in self.cached_images.keys(): image_reader = QImageReader() image_reader.setDecideFormatFromContent(True) image_reader.setFileName(image.getFilename()) self.cached_images[index] = image_reader.read() cached_image = self.cached_images[index] pixmap = QPixmap(cached_image) if num > 1: pixmap = pixmap.scaledToWidth(colwidth - 20) rec = MultiImageWidget(pixmap, basename(image.getFilename()), index) rec.imageClicked.connect(self.emitter) self.multiple_image_layout.addItem(rec, row, col) else: self.single_image_scene.addPixmap(pixmap) adjusted = self.multiple_image_scene.itemsBoundingRect() adjusted.adjust(0, 0, 0, 8 * row) self.multiple_image_scene.setSceneRect(adjusted)
def __init__(self, name, default=False): super().__init__() # Variables self.name = name self.hovered = False self.enabled = default self.padding = 5 # Objects self.image = QImageReader() self.imageSize = QSize(20, 20) # Styling self.font = QFont('Arial', 8) self.font.setWeight(QFont.Bold) self.nameHeight = QFontMetrics(self.font).height() self.nameWidth = QFontMetrics(self.font).width(self.name) self.image.setScaledSize(self.imageSize) self.setFixedSize( self.imageSize.width() + self.padding + self.nameWidth, self.imageSize.height())
def open_folder(self, path=None): self.current_index = 0 self.path = path if path is None: dialog = QFileDialog(self) dialog.setAcceptMode(QFileDialog.AcceptOpen) dialog.setFileMode(QFileDialog.DirectoryOnly) if dialog.exec(): self.path = dialog.selectedFiles()[0] if not self.path: return list_ = os.listdir(self.path) list_ = sorted(list_) self.file_list = OrderedDict() for item in list_: if item.split(".")[-1] in QImageReader.supportedImageFormats(): self.file_list[item] = False self.show_image(self.current_index)
def setup(self): for label, value in self.data: if label is None and value is None: # Separator: (None, None) separator = QFrame() separator.setFrameShape(QFrame.HLine) separator.setFrameShadow(QFrame.Sunken) self.formlayout.addRow(separator) self.widgets.append(None) continue if label is None: if isinstance(value, (list, tuple)): field = PushLayout(value, self) self.formlayout.addRow(field) else: img_fmt = tuple(['.'+str(bytes(ext).decode()) for ext in QImageReader.supportedImageFormats()]) if value.endswith(img_fmt): # Image pixmap = QPixmap(value) lab = QLabel() lab.setPixmap(pixmap) self.formlayout.addRow(lab) else: # Comment self.formlayout.addRow(QLabel(value)) self.widgets.append(None) continue if tuple_to_qfont(value) is not None: field = FontLayout(value, self) elif text_to_qcolor(value).isValid(): field = ColorLayout(QColor(value), self) elif is_text_string(value): if value in ['file', 'dir'] or value.startswith('file:'): field = FileLayout(value, self) elif value == 'slider' or value.startswith('slider:') \ or value.startswith('slider@'): field = SliderLayout(value, self) elif value == 'password': field = QLineEdit(self) field.setEchoMode(QLineEdit.Password) elif value in ['calendar', 'calendarM'] \ or value.startswith(('calendar:', 'calendarM:')) \ or value.startswith(('calendar@', 'calendarM@')): index = value.find('@') if index != -1: value, date = value[:index], value[index+1:] else: date = False field = QCalendarWidget(self) field.setVerticalHeaderFormat(field.NoVerticalHeader) parsed = value.split(':') if parsed[-1] == '': field.setGridVisible(True) parsed.pop(-1) if parsed[0] == 'calendarM': field.setFirstDayOfWeek(Qt.Monday) if len(parsed) == 2: field.setMaximumDate(datetime.date(*eval(parsed[1]))) elif len(parsed) == 3: field.setMinimumDate(datetime.date(*eval(parsed[1]))) field.setMaximumDate(datetime.date(*eval(parsed[2]))) if date: field.setSelectedDate(datetime.date(*eval(date))) elif '\n' in value: if value == '\n': value = '' for linesep in (os.linesep, '\n'): if linesep in value: value = value.replace(linesep, "\u2029") # paragraph separator field = QTextEdit(value, self) else: field = QLineEdit(value, self) elif isinstance(value, (list, tuple)) and is_text_string(value[0])\ and (value[0].startswith('0v') or value[0].startswith('0h') or value[0].startswith('1v') or value[0].startswith('1h')): if value[0][2:]: binary = value[0][2:] else: binary = value[0][0] * len(value[1:]) if value[0][1] == 'v': field = CheckVLayout(value[1:], binary, self) elif value[0][1] == 'h': field = CheckHLayout(value[1:], binary, self) elif isinstance(value, (list, tuple)): save_value = value value = list(value) # always needed to protect self.data selindex = value.pop(0) if isinstance(selindex, int): selindex = selindex - 1 if isinstance(value[0], (list, tuple)): keys = [ key for key, _val in value ] value = [ val for _key, val in value ] else: keys = value if selindex in value: selindex = value.index(selindex) elif selindex in keys: selindex = keys.index(selindex) elif not isinstance(selindex, int): print(f"Warning: '{selindex}' index is invalid (label: {label}, value: {value})" ,file=sys.stderr) selindex = -1 if isinstance(save_value, list): field = QComboBox(self) field.addItems(value) field.setCurrentIndex(selindex) elif isinstance(save_value, tuple): field = RadioLayout(value, selindex, self) elif isinstance(value, bool): field = QCheckBox(self) field.setChecked(value) elif isinstance(value, float): field = QLineEdit(QLocale().toString(value), self) field.setValidator(QDoubleValidator(field)) dialog = self.get_dialog() dialog.register_float_field(field) if SIGNAL is None: field.textChanged.connect(dialog.float_valid) else: self.connect(field, SIGNAL('textChanged(QString)'), dialog.float_valid) elif isinstance(value, int): field = QSpinBox(self) field.setRange(-1e9, 1e9) field.setValue(value) elif isinstance(value, datetime.datetime): field = QDateTimeEdit(self) field.setDateTime(value) elif isinstance(value, datetime.date): field = QDateEdit(self) field.setDate(value) elif isinstance(value, datetime.time): field = QTimeEdit(self) field.setTime(value) else: field = QLineEdit(repr(value), self) # Eventually catching the 'countfield' feature and processing it if label.startswith('n '): label = label[2:] if isinstance(field, QLineEdit) and is_text_string(value) or isinstance(field, QComboBox): field = CountLayout(field) else: print(f"Warning: '{label}' doesn't support 'nfield' feature", file=sys.stderr) # Eventually extracting tooltip from label and processing it index = label.find('::') if index != -1: label, tooltip = label[:index], label[index+2:] field.setToolTip(tooltip) # Eventually catching the 'required' feature and processing it if label.endswith(' *'): label = label[:-1] + '<font color="red">*</font>' if isinstance(field, (QLineEdit, QTextEdit, QComboBox, FileLayout, RadioLayout)): dialog = self.get_dialog() dialog.register_required_field(field) else: print(f"Warning: '{type(field)}' doesn't support 'required' feature", file=sys.stderr) if isinstance(field, QLineEdit): if SIGNAL is None: field.textChanged.connect(dialog.required_valid) else: self.connect(field, SIGNAL('textChanged(QString)'),dialog.required_valid) elif isinstance(field, QTextEdit): if SIGNAL is None: field.textChanged.connect(dialog.required_valid) else: self.connect(field, SIGNAL('textChanged()'),dialog.required_valid) elif isinstance(field, QComboBox): if SIGNAL is None: field.currentIndexChanged.connect(dialog.required_valid) else: self.connect(field,SIGNAL('currentIndexChanged(QString)'),dialog.required_valid) elif isinstance(field, FileLayout): if SIGNAL is None: field.lineedit.textChanged.connect(dialog.required_valid) else: self.connect(field.lineedit,SIGNAL('textChanged(QString)'),dialog.required_valid) elif isinstance(field, RadioLayout): if SIGNAL is None: field.group.buttonClicked.connect(dialog.required_valid) else: self.connect(field.group, SIGNAL('buttonClicked(int)'),dialog.required_valid) # Eventually setting the widget_color if self.widget_color: style = "background-color:" + self.widget_color + ";" field.setStyleSheet(style) if self.type == 'form': self.formlayout.addRow(label, field) elif self.type == 'questions': self.formlayout.addRow(QLabel(label)) self.formlayout.addRow(field) self.widgets.append(field)
class Check(QFrame): def __init__(self, name, default=False): super().__init__() # Variables self.name = name self.hovered = False self.enabled = default self.padding = 5 # Objects self.image = QImageReader() self.imageSize = QSize(20, 20) # Styling self.font = QFont('Arial', 8) self.font.setWeight(QFont.Bold) self.nameHeight = QFontMetrics(self.font).height() self.nameWidth = QFontMetrics(self.font).width(self.name) self.image.setScaledSize(self.imageSize) self.setFixedSize( self.imageSize.width() + self.padding + self.nameWidth, self.imageSize.height()) def getEnabled(self): return self.enabled def setPadding(self, param): self.padding = param self.update() def enterEvent(self, event): super().enterEvent(event) self.hovered = True self.update() def leaveEvent(self, event): super().leaveEvent(event) self.hovered = False self.update() def mouseReleaseEvent(self, event): super().mousePressEvent(event) if event.button() == Qt.LeftButton: self.enabled = not self.enabled self.stateChanged.emit(self.enabled) self.update() def paintEvent(self, event): # Set checked depending on state self.image.setFileName(ThemeManager.CHECKED_PATH if self. enabled else ThemeManager.UNCHECKED_PATH) # Init painter and draw image at correct location painter = QPainter(self) pixmap = QPixmap.fromImageReader(self.image) painter.setRenderHint(QPainter.HighQualityAntialiasing, True) painter.drawPixmap(0, (self.height() - pixmap.height()) / 2, pixmap) # Style font and draw text at correct location painter.setFont(self.font) pen = QPen() pen.setColor(ThemeManager.LABEL_QC if any([self.hovered, self.enabled]) else ThemeManager.LABEL_LOW_OPACITY_QC) painter.setPen(pen) painter.drawText(pixmap.width() + self.padding, self.height() / 2 + self.nameHeight / 4, self.name) stateChanged = Signal(object)
def supported_img_formats(): """Function to check if reading .ico files is supported.""" img_formats = QImageReader().supportedImageFormats() img_formats_str = '\n'.join(str(x) for x in img_formats) logging.debug("Supported Image formats:\n%s", img_formats_str)
def __init__(self): super().__init__() self.reader = QImageReader()
def supported_image_formats() -> List[str]: """ Return list of supported image formats """ supported_formats: List[Any] = QImageReader.supportedImageFormats() return [format_.data().decode() for format_ in supported_formats]
def __init__(self, app, parent=None): super(MainWindow, self).__init__(parent) self.imagesDir = app.dir + '/images/' self.setWindowIcon(QIcon(self.imagesDir + 'icon.png')) self.path = '' self.settings = QSettings() self.lastDir = self.settings.value('lastDir', '') self.setMinimumWidth(540) self.supportedFormats = [] for f in QImageReader.supportedImageFormats(): self.supportedFormats.append(str(f.data(), encoding="utf-8")) self.fileWatcher = QFileSystemWatcher() self.fileWatcher.fileChanged.connect(self.fileChanged) # widgets self.showPixmapWidget = None self.tileWidthSpinBox = QSpinBox() self.tileWidthSpinBox.setValue(16) self.tileWidthSpinBox.setFixedWidth(50) self.tileWidthSpinBox.setMinimum(1) self.tileHeightSpinBox = QSpinBox() self.tileHeightSpinBox.setValue(16) self.tileHeightSpinBox.setFixedWidth(50) self.tileHeightSpinBox.setMinimum(1) self.paddingSpinBox = QSpinBox() self.paddingSpinBox.setFixedWidth(50) self.paddingSpinBox.setMinimum(1) self.transparentCheckbox = QCheckBox("Transparent") self.transparentCheckbox.setChecked(True) self.transparentCheckbox.stateChanged.connect(self.transparentChanged) self.backgroundColorEdit = ColorEdit() self.backgroundColorEdit.setEnabled(False) self.backgroundColorLabel = QLabel("Background color:") self.backgroundColorLabel.setEnabled(False) self.forcePotCheckBox = QCheckBox("Force PoT") self.forcePotCheckBox.setChecked(True) self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged) self.reorderTilesCheckBox = QCheckBox("Reorder tiles") self.generateAndExportButton = QPushButton("Generate and export") self.generateAndExportButton.setFixedHeight(32) self.generateAndExportButton.clicked.connect(self.generateAndExportClicked) self.generateAndExportButton.setEnabled(False) self.pixmapWidget = PixmapWidget() self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.pixmapWidget.setPixmap(self.createDropTextPixmap()) self.pixmapWidget.dropSignal.connect(self.fileDropped) self.pixmapWidget.setMinimumHeight(300) # load settings self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16))) self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16))) self.paddingSpinBox.setValue(int(self.settings.value('padding', 1))) self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False) self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False) self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False) self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF'))) self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry'))) self.restoreState(QByteArray(self.settings.value('MainWindow/windowState'))) # layout hl1 = QHBoxLayout() hl1.setContentsMargins(5, 5, 5, 5) hl1.addWidget(QLabel("Tile width:")) hl1.addSpacing(5) hl1.addWidget(self.tileWidthSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Tile height:")) hl1.addSpacing(5) hl1.addWidget(self.tileHeightSpinBox) hl1.addSpacing(15) hl1.addWidget(QLabel("Padding:")) hl1.addSpacing(5) hl1.addWidget(self.paddingSpinBox) hl1.addSpacing(15) hl1.addWidget(self.forcePotCheckBox) hl1.addSpacing(15) hl1.addWidget(self.reorderTilesCheckBox) hl1.addStretch() hl2 = QHBoxLayout() hl2.setContentsMargins(5, 5, 5, 5) hl2.addWidget(self.transparentCheckbox) hl2.addSpacing(15) hl2.addWidget(self.backgroundColorLabel) hl2.addSpacing(5) hl2.addWidget(self.backgroundColorEdit) hl2.addStretch() hl3 = QHBoxLayout() hl3.setContentsMargins(5, 5, 5, 5) hl3.addWidget(self.generateAndExportButton) vl = QVBoxLayout() vl.setContentsMargins(0, 0, 0, 0) vl.setSpacing(0) vl.addLayout(hl1) vl.addLayout(hl2) vl.addWidget(self.pixmapWidget) vl.addLayout(hl3) w = QWidget() w.setLayout(vl) self.setCentralWidget(w) self.setTitle()
class ImageListItem(QListWidgetItem): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.widget = QWidget() self.shortcuts = {} self.shortcuts_labels = {} self.feature = FeatureStyle() self.pal = QPalette() self.text_widget = QLabel() self.labels_widget = QWidget() self.icon_widget = QLabel() self.icon_reader = QImageReader() self.icon_file = None self.icon_size = 60 self.index = None self.start() def start(self): widgetLayout = QHBoxLayout() widgetLayout.addWidget(self.labels_widget) self.shorcutLayout = QVBoxLayout() self.labels_widget.setLayout(self.shorcutLayout) widgetLayout.addWidget(self.icon_widget) widgetLayout.addWidget(self.text_widget) widgetLayout.addStretch() self.widget.setLayout(widgetLayout) # pixmap=icon.pixmap(100,100) # item.setIcon(icon) # item.setSizeHint(QSize(size,size)) self.update_size() def set_shortcuts_labels(self, shortcuts_labels): self.shortcuts = {} for shortcut in shortcuts_labels.keys(): shortcut_w = QLabel(f'{shortcut}') self.pal.setColor(QPalette.Text, self.feature.unknown) shortcut_w.setPalette(self.pal) self.shortcuts[shortcut] = {'status': '', 'widget': shortcut_w} self.shorcutLayout.addWidget(shortcut_w) self.update_size() def set_shortcuts_status(self, shortcut, status): self.shortcuts[shortcut]['status'] = status has_feature = status if has_feature == 1: self.pal.setColor(QPalette.Text, self.feature.has) if has_feature == 0: self.pal.setColor(QPalette.Text, self.feature.unknown) if has_feature == -1: self.pal.setColor(QPalette.Text, self.feature.hasnt) if has_feature == 10: self.pal.setColor(QPalette.Text, self.feature.unsure) self.shortcuts[shortcut]['widget'].setPalette(self.pal) def update_size(self): self.setSizeHint(self.widget.sizeHint()) def set_index(self, index): self.index = index def set_labels(self, labels): self.set_shortcuts_labels(labels) # self.update_size() def set_text(self, text): self.text_widget.setText(text) self.update_size() def set_icon(self, icon_file): self.icon_file = icon_file self.update_icon() self.update_size() def set_icon_size(self, size): self.icon_size = size self.update_icon() self.update_size() def update_icon(self): self.icon_reader.setDecideFormatFromContent(True) self.icon_reader.setFileName(self.icon_file) self.icon_reader.setScaledSize(QSize(self.icon_size, self.icon_size)) image = self.icon_reader.read() pixmap = QPixmap(image) # pixmap.scaled(QSize(size,size)) # icon=QIcon(pixmap) self.icon_widget.setPixmap(pixmap)
def init_filters(self): formats = QImageReader.supportedImageFormats() for f in formats: self.filters.append('*.' + f.data().decode('utf-8'))
def load_img(): img = QImageReader(IMG_FILE).read() pmap = QPixmap.fromImage(img) return pmap
def supported_image_extensions(): ''' Get the image file extensions that can be read. ''' formats = QImageReader().supportedImageFormats() # Convert the QByteArrays to strings return [str(fmt) for fmt in formats]
def run(self): image = QImageReader(str(self.path)).read() self.remove_runnable_callback() self.signals.processing_completed.emit(image, str(self.path))