def _add(c1: QColor, c2: QColor) -> QColor: return QColor( _clampcolor(c1.red() + c2.red()), _clampcolor(c1.green() + c2.green()), _clampcolor(c1.blue() + c2.blue()), _clampcolor(c1.alpha() + c2.alpha()), )
def set_colors(data: bin, fg: QColor, bg: QColor, trans: QColor, swap_fg_bg=False) -> bin: # pylint: disable=too-many-locals """ Burns foreground and background colors into a raster image, and returns the results as a PNG binary """ image = QImage() image.loadFromData(data) if image.isNull(): raise UnreadablePictureException( 'Could not read embedded picture data') image = image.convertToFormat(QImage.Format_ARGB32) ucharptr = image.bits() ucharptr.setsize(image.byteCount() * image.height()) fg_rgba = qRgba(fg.red(), fg.green(), fg.blue(), fg.alpha()) if fg and fg.isValid() else None bg_rgba = qRgba(bg.red(), bg.green(), bg.blue(), bg.alpha()) if bg and bg.isValid() else None COLOR_TOLERANCE = 40 fg_comp = 0 bg_comp = 255 for y in range(image.height()): start = y * image.width() * 4 for x in range(image.width()): x_start = x * 4 + start rgba = struct.unpack('I', ucharptr[x_start:x_start + 4])[0] if trans and abs(qRed(rgba) - trans.red( )) < COLOR_TOLERANCE and abs(qGreen(rgba) - trans.green( )) < COLOR_TOLERANCE and abs(qBlue(rgba) - trans.blue()) < COLOR_TOLERANCE: ucharptr[x_start:x_start + 4] = struct.pack( 'I', qRgba(0, 0, 0, 0)) elif fg_rgba is not None and abs( qRed(rgba) - fg_comp) < COLOR_TOLERANCE and abs( qGreen(rgba) - fg_comp) < COLOR_TOLERANCE and abs( qBlue(rgba) - fg_comp) < COLOR_TOLERANCE: ucharptr[x_start:x_start + 4] = struct.pack('I', fg_rgba) elif bg_rgba is not None and abs( qRed(rgba) - bg_comp) < COLOR_TOLERANCE and abs( qGreen(rgba) - bg_comp) < COLOR_TOLERANCE and abs( qBlue(rgba) - bg_comp) < COLOR_TOLERANCE: ucharptr[x_start:x_start + 4] = struct.pack('I', bg_rgba) # convert to PNG png_data = QBuffer() image.save(png_data, "png") return png_data.data()
def QColorLerp(a: QColor, b: QColor, t: float): """ Blends two QColors. t=0 returns a. t=1 returns b. t=0.5 returns evenly mixed. """ t = max(min(t, 1.0), 0.0) i_t = 1.0 - t return QColor( int((a.red() * i_t) + (b.red() * t)), int((a.green() * i_t) + (b.green() * t)), int((a.blue() * i_t) + (b.blue() * t)), int((a.alpha() * i_t) + (b.alpha() * t)), )
def overlay_colors(bottom: QColor, top: QColor) -> QColor: bottom_multiplier = (1 - (top.alpha() / 255)) * (bottom.alpha() / 255) top_multiplier = top.alpha() / 255 alpha_multiplier = bottom_multiplier + top_multiplier return QColor( (bottom.red() * bottom_multiplier + top.red() * top_multiplier) / alpha_multiplier, (bottom.green() * bottom_multiplier + top.green() * top_multiplier) / alpha_multiplier, (bottom.blue() * bottom_multiplier + top.blue() * top_multiplier) / alpha_multiplier, alpha_multiplier * 255, )
def onHexChanged(self, code): if len(code) != 7: return color = QColor(code) if color.isValid(): self.blockRgbaSignals(True) self.editHex.blockSignals(True) self.editRed.setValue(color.red()) self.editGreen.setValue(color.green()) self.editBlue.setValue(color.blue()) self.editAlpha.setValue(color.alpha()) self.colorChanged.emit(color, color.alpha()) self.editHex.blockSignals(False) self.blockRgbaSignals(False)
def convertColor(value: QColor): return ( value.red() / 255, value.green() / 255, value.blue() / 255, value.alpha() / 255 )
class ColorButton(QPushButton): colorChanged = pyqtSignal(QColor) def __init__(self, parent=None, color: Optional[QColor] = None): super().__init__(parent) self.setFixedWidth(35) self.clicked.connect(self.click) self.color = QColor(0, 0, 0, 255) if color is None else color @property def color(self): return QColor(self._color) @color.setter def color(self, color: QColor): self._color = QColor(color) self._updateUI() def _updateUI(self): self.setStyleSheet( "QPushButton {{ background-color: rgba({}, {}, {}, {}) }}".format( self._color.red(), self._color.green(), self._color.blue(), self._color.alpha())) @pyqtSlot() def click(self): col = QColorDialog.getColor(self._color, self, "", QColorDialog.ShowAlphaChannel) if col.isValid(): self.color = col self.colorChanged.emit(self._color)
def get_task_bgcolor(task: TaskOccurrence, isSelected=False) -> QColor: bgColor = get_task_base_bgcolor(task) if isSelected: red = min(255, bgColor.red() + 40) green = min(255, bgColor.green() + 40) blue = min(255, bgColor.blue() + 40) bgColor = QColor(red, green, blue, bgColor.alpha()) return bgColor
def q_color_to_color(q_color: QColor) -> Color: """Create a `Color` from a `QColor` Args: q_color (QColor): The source `QColor` Returns: Color """ return Color(q_color.red(), q_color.green(), q_color.blue(), q_color.alpha())
def setPenColor(self, col): q_col = QColor(col) r, g, b, a = q_col.red(), q_col.green(), q_col.blue(), q_col.alpha() self.red.setValue( int(r / 255 * (self.red.maximum() - self.red.minimum()))) self.grn.setValue( int(g / 255 * (self.grn.maximum() - self.grn.minimum()))) self.blu.setValue( int(b / 255 * (self.blu.maximum() - self.blu.minimum()))) self.alp.setValue( int(a / 255 * (self.alp.maximum() - self.alp.minimum())))
def changeHue(self): for row_pixel in range(self.image.width()): for col_pixel in range(self.image.height()): current_val = QColor(self.image.pixel(row_pixel, col_pixel)) hue = current_val.hue() current_val.setHsv(hue, current_val.saturation(), current_val.value(), current_val.alpha()) self.image.setPixelColor(row_pixel, col_pixel, current_val) self.setPixmap(QPixmap().fromImage(self.image))
def adjustBright(image: QImage, value) -> QImage: width, height = image.width(), image.height() newImage = QImage(width, height, QImage.Format_RGBA8888) for h in range(height): for w in range(width): pixel = QColor(image.pixel(h, w)) red = (pixel.red() + value) red = bound(0, 255, red) green = (pixel.green() + value) green = bound(0, 255, green) blue = (pixel.blue() + value) blue = bound(0, 255, blue) newImage.setPixel(h, w, qRgba(red, green, blue, pixel.alpha())) return newImage
def adjustSaturation(image: QImage, value) -> QImage: width, height = image.width(), image.height() newImage = QImage(width, height, QImage.Format_RGBA8888) for h in range(height): for w in range(width): pixel = QColor(image.pixel(h, w)).toHsl() H = pixel.hue() S = pixel.saturation() + value L = pixel.lightness() S = bound(0, 255, S) pixel.setHsl(H, S, L) newImage.setPixel( h, w, qRgba(pixel.red(), pixel.green(), pixel.blue(), pixel.alpha())) return newImage
def set_colors(data: bin, fg: QColor, bg: QColor, trans: QColor) -> bin: # pylint: disable=too-many-locals """ Burns foreground and background colors into a raster image, and returns the results as a PNG binary """ image = QImage() image.loadFromData(data) image = image.convertToFormat(QImage.Format_ARGB32) ucharptr = image.bits() ucharptr.setsize(image.byteCount() * image.height()) fg_rgba = qRgba(fg.red(), fg.green(), fg.blue(), fg.alpha()) if fg and fg.isValid() else None bg_rgba = qRgba(bg.red(), bg.green(), bg.blue(), bg.alpha()) if bg and bg.isValid() else None # TODO: what's this even for? _ = qRgba(trans.red(), trans.green(), trans.blue(), trans.alpha()) if trans else None for y in range(image.height()): start = y * image.width() * 4 for x in range(image.width()): x_start = x * 4 + start rgba = struct.unpack('I', ucharptr[x_start:x_start + 4])[0] if fg_rgba is not None and rgba == 0xff000000: ucharptr[x_start:x_start + 4] = struct.pack('I', fg_rgba) elif bg_rgba is not None and rgba == 0xffffffff: ucharptr[x_start:x_start + 4] = struct.pack('I', bg_rgba) # convert to PNG png_data = QBuffer() image.save(png_data, "png") return png_data.data()
def adjustContrast(image: QImage, value) -> QImage: width, height = image.width(), image.height() newImage = QImage(width, height, QImage.Format_RGBA8888) if value >= 0: value = 1 / (1 - value / 100.0) - 1 else: value /= 100.0 for h in range(height): for w in range(width): pixel = QColor(image.pixel(h, w)) color = [ bound(0, 255, (c - 127) * value + c) for c in [pixel.red( ), pixel.green(), pixel.blue()] ] newImage.setPixel(h, w, qRgba(*color, pixel.alpha())) return newImage
def adjustWarm(image: QImage, value) -> QImage: width, height = image.width(), image.height() newImage = QImage(width, height, QImage.Format_RGBA8888) for h in range(height): for w in range(width): pixel = QColor(image.pixel(h, w)) red, green, blue = pixel.red(), pixel.green(), pixel.blue() if value >= 0: red += value red = bound(0, 255, red) green += value green = bound(0, 255, green) else: blue += abs(value) blue = bound(0, 255, blue) newImage.setPixel(h, w, qRgba(red, green, blue, pixel.alpha())) return newImage
def paintEvent(self, event): painter = QPainter(self) if self.isEnabled() and not self.isDown() and not self.isChecked(): painter.save() hover_color = QColor("#424242") faded_hover_color = QColor(hover_color) faded_hover_color.setAlpha(int(self._fader * hover_color.alpha())) painter.fillRect(event.rect(), faded_hover_color) painter.restore() elif self.isDown() or self.isChecked(): painter.save() selected_color = QColor("#161719") painter.fillRect(event.rect(), selected_color) painter.restore() is_titled = bool(self.defaultAction().property("titled")) icon_rect = QRect(0, 0, 32, 32) icon_rect.moveCenter(event.rect().center()) if is_titled: font = painter.font() center_rect = event.rect() font.setPointSizeF(6) fm = QFontMetrics(font) line_height = fm.height() text_flags = Qt.AlignHCenter | Qt.AlignTop project_name = self.defaultAction().property("heading") if project_name is not None: center_rect.adjust(0, line_height, 0, 0) icon_rect.moveTop(center_rect.top()) else: icon_rect.moveCenter(center_rect.center()) self.icon().paint(painter, icon_rect, Qt.AlignCenter) painter.setFont(font) r = QRect(0, 5, self.rect().width(), line_height) painter.setPen(Qt.white) margin = 5 available_width = r.width() - margin ellided_project_name = fm.elidedText( project_name, Qt.ElideMiddle, available_width) painter.drawText(r, text_flags, ellided_project_name) else: self.icon().paint(painter, icon_rect, Qt.AlignCenter)
def paintEvent(self, event): painter = QPainter(self) if self.isEnabled() and not self.isDown() and not self.isChecked(): painter.save() hover_color = QColor("#424242") faded_hover_color = QColor(hover_color) faded_hover_color.setAlpha(int(self._fader * hover_color.alpha())) painter.fillRect(event.rect(), faded_hover_color) painter.restore() elif self.isDown() or self.isChecked(): painter.save() selected_color = QColor("#090909") painter.fillRect(event.rect(), selected_color) painter.restore() fm = QFontMetrics(painter.font()) rect = QRect(-3, 0, self.rect().width(), fm.height()) icon_rect = QRect(0, 0, 22, 22) self.icon().paint(painter, icon_rect, Qt.AlignVCenter) painter.drawText(rect, Qt.AlignRight | Qt.AlignVCenter, self.text())
def paintEvent(self, event): painter = QPainter(self) if self.isEnabled() and not self.isDown() and not self.isChecked(): painter.save() hover_color = QColor("#424242") faded_hover_color = QColor(hover_color) faded_hover_color.setAlpha(int(self._fader * hover_color.alpha())) painter.fillRect(event.rect(), faded_hover_color) painter.restore() elif self.isDown() or self.isChecked(): painter.save() selected_color = QColor("#161719") painter.fillRect(event.rect(), selected_color) painter.restore() is_titled = bool(self.defaultAction().property("titled")) icon_rect = QRect(0, 0, 32, 32) icon_rect.moveCenter(event.rect().center()) if is_titled: font = painter.font() center_rect = event.rect() font.setPointSizeF(6) fm = QFontMetrics(font) line_height = fm.height() text_flags = Qt.AlignHCenter | Qt.AlignTop project_name = self.defaultAction().property("heading") if project_name is not None: center_rect.adjust(0, line_height, 0, 0) icon_rect.moveTop(center_rect.top()) else: icon_rect.moveCenter(center_rect.center()) self.icon().paint(painter, icon_rect, Qt.AlignCenter) painter.setFont(font) r = QRect(0, 5, self.rect().width(), line_height) painter.setPen(Qt.white) margin = 5 available_width = r.width() - margin ellided_project_name = fm.elidedText(project_name, Qt.ElideMiddle, available_width) painter.drawText(r, text_flags, ellided_project_name) else: self.icon().paint(painter, icon_rect, Qt.AlignCenter)
def on_color_changed(self, color: QColor): """ Set the project selection color from the color button """ try: QgsProject.instance().setSelectionColor(color) # Mark the project dirty to make it "saveable" QgsProject.instance().setDirty() except AttributeError: # QGIS < 3.10 iface.mapCanvas().setSelectionColor(color) QgsProject.instance().writeEntry("Gui", "SelectionColorRedPart", color.red()) QgsProject.instance().writeEntry("Gui", "SelectionColorBluePart", color.blue()) QgsProject.instance().writeEntry("Gui", "SelectionColorGreenPart", color.green()) QgsProject.instance().writeEntry("Gui", "SelectionColorAlphaPart", color.alpha()) # Will trigger the icon color change self.colorChanged.emit()
def paintEvent(self, event): painter = QPainter(self) if self.isEnabled() and not self.isDown() and not self.isChecked(): painter.save() hover_color = QColor("#424242") faded_hover_color = QColor(hover_color) faded_hover_color.setAlpha(int(self._fader * hover_color.alpha())) painter.fillRect(event.rect(), faded_hover_color) painter.restore() elif self.isDown() or self.isChecked(): painter.save() selected_color = QColor("#090909") painter.fillRect(event.rect(), selected_color) painter.restore() # fm = QFontMetrics(painter.font()) # rect = QRect(-3, 2, self.rect().width(), fm.height()) rect = event.rect() icon_rect = QRect(0, 0, 22, 22) self.icon().paint(painter, icon_rect, Qt.AlignVCenter) painter.drawText( rect.adjusted(0, 0, -3, 0), Qt.AlignRight | Qt.AlignVCenter, self.text())
class SidebarItem(QWidget): on_pressed = pyqtSignal(bool) def __init__(self, text, pixmap=None, parent=None): super().__init__(parent) rgb_value = 255 if options.theme == 'dark' else 0 self.theme = options.theme # You are supposed to set size policy like this, and not to override sizePolicy() # If vertical policy was preferred, then you would have to implement minimumSizeHint and # maximumSize to limit how much the item can shrink and grow. self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) self.text = text self.pixmap = pixmap self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200)) self.spacing = 12 self.font = QApplication.font() self.font.setBold(True) self.fm = QFontMetrics(self.font) self.mouse_over = False self.checked = False self.active = False self.setMouseTracking(True) self.background_color = QColor(rgb_value, rgb_value, rgb_value, 0) self.background_animation = QPropertyAnimation(self, b'opacity') self.background_animation.setStartValue(0) self.background_animation.setEndValue(40) self.background_animation.setDuration(300) self.indicator_pos = 5 self.indicator_position_anim = QPropertyAnimation( self, b'indicator_position') self.indicator_position_anim.setStartValue(5) self.indicator_position_anim.setEndValue(-5) self.indicator_position_anim.setDuration(300) self.indicator_background = QColor(rgb_value, rgb_value, rgb_value, 0) self.indicator_opacity_anim = QPropertyAnimation( self, b'indicator_opacity') self.indicator_opacity_anim.setStartValue(0) self.indicator_opacity_anim.setEndValue(140) self.indicator_opacity_anim.setDuration(300) self.all_animations = QParallelAnimationGroup() self.all_animations.addAnimation(self.background_animation) self.all_animations.addAnimation(self.indicator_position_anim) self.all_animations.addAnimation(self.indicator_opacity_anim) OptionEventChannel.subscribe('theme', self.handle_theme_change) def mousePressEvent(self, event): super().mousePressEvent(event) self.on_pressed.emit(True) def set_checked(self, checked): self.checked = checked self.check_active() def check_active(self): old_active = self.active if self.checked: self.active = True else: self.active = self.mouse_over if old_active == self.active: return if self.active is True: self.all_animations.setDirection(QParallelAnimationGroup.Forward) self.all_animations.start() else: self.all_animations.setDirection(QParallelAnimationGroup.Backward) self.all_animations.start() # Calling update 10 times will result in only one update. # So it's fine to do this even after starting the animations. self.update() def enterEvent(self, event): self.mouse_over = True self.check_active() def leaveEvent(self, event): self.mouse_over = False self.check_active() def sizeHint(self): # sizeHint is used by layouts to get the recommended size of the widget. return QSize(100, 40) # def minimumSizeHint(self): # # minimumSizeHint is used by layouts to get the minimum size of the widget. # # It's ignored if minimumSize is also implemented # return self.sizeHint() def paintEvent(self, paint_event): super().paintEvent(paint_event) widget_rect = self.rect() painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.fillRect(widget_rect, self.background_color) if self.mouse_over: indicator_rect = QRect( widget_rect.width() + self.indicator_pos - 6, (widget_rect.height() - 6) // 2, 6, 9) triangle_path = QPainterPath(indicator_rect.topRight()) triangle_path.lineTo(indicator_rect.bottomRight()) mid_left = indicator_rect.bottomLeft() mid_left.setY(mid_left.y() - indicator_rect.height() // 2) triangle_path.lineTo(mid_left) triangle_path.lineTo(indicator_rect.topRight()) painter.fillPath(triangle_path, self.indicator_background) if self.pixmap: pixmap_rect = QRect(self.spacing, (widget_rect.height() - 20) // 2, 20, 20) painter.drawPixmap(pixmap_rect, self.pixmap, self.pixmap.rect()) # painter.drawRect(pixmap_rect) else: pixmap_rect = QRect(0, 0, 0, 0) text_rect = QRect(pixmap_rect.right() + self.spacing, 0, 0, widget_rect.height()) text_rect.setWidth(widget_rect.width() - text_rect.left()) # painter.drawRect(text_rect) text = self.fm.elidedText(self.text, Qt.ElideRight, text_rect.width()) painter.setFont(self.font) painter.drawText(text_rect, Qt.AlignVCenter | Qt.AlignLeft, text) def _prepare_pixmap(self, qcolor): if self.pixmap is None: return painter = QPainter(self.pixmap) painter.setCompositionMode(QPainter.CompositionMode_SourceAtop) painter.fillRect(self.pixmap.rect(), qcolor) painter.end() def _get_opacity(self): return self.background_color.alpha() def _set_opacity(self, new_value): self.background_color.setAlpha(new_value) self.update() opacity = pyqtProperty('int', _get_opacity, _set_opacity) def _get_indicator_position(self): return self.indicator_pos def _set_indicator_position(self, new_value): self.indicator_pos = new_value self.update() indicator_position = pyqtProperty('int', _get_indicator_position, _set_indicator_position) def _get_indicator_opacity(self): return self.indicator_background.alpha() def _set_indicator_opacity(self, new_value): self.indicator_background.setAlpha(new_value) self.update() indicator_opacity = pyqtProperty('int', _get_indicator_opacity, _set_indicator_opacity) def handle_theme_change(self, theme): if theme == self.theme: return self.theme = theme if theme == 'dark': rgb_value = 255 else: rgb_value = 0 self.background_color.setRgb(rgb_value, rgb_value, rgb_value, self.background_color.alpha()) self.indicator_background.setRgb(rgb_value, rgb_value, rgb_value, self.indicator_background.alpha()) self._prepare_pixmap(QColor(rgb_value, rgb_value, rgb_value, 200)) self.update()
def qcolor_to_qsscolor(c: QColor) -> str: """Convert a QColor to a string that can be used in a QStyleSheet.""" ensure_valid(c) return "rgba({}, {}, {}, {})".format( c.red(), c.green(), c.blue(), c.alpha())
class ColorPicker(QWidget): primaryColorChanged = pyqtSignal(QColor) secondaryColorChanged = pyqtSignal(QColor) def __init__(self, parent=None): super(ColorPicker, self).__init__(parent) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self._primarySelectedColor = QColor() self._secondarySelectedColor = QColor() self._activeColorIndex = ColorIndex.Primary self._controlPressed = False self._altPressed = False self._palette = ColorPalette() # Initialize Sliders self._hueSlider = ColorSlider(0, 359) self._hueSlider.set_color_at(0.0, QColor(255, 0, 0)) self._hueSlider.set_color_at(0.16, QColor(255, 255, 0)) self._hueSlider.set_color_at(0.33, QColor(0, 255, 0)) self._hueSlider.set_color_at(0.5, QColor(0, 255, 255)) self._hueSlider.set_color_at(0.76, QColor(0, 0, 255)) self._hueSlider.set_color_at(0.85, QColor(255, 0, 255)) self._hueSlider.set_color_at(1.0, QColor(255, 0, 0)) self._hueSlider.label = 'Hue' self._satSlider = ColorSlider(0, 255) self._satSlider.label = 'Saturation' self._valSlider = ColorSlider(0, 255) self._valSlider.label = 'Value' self._valSlider.start_color = QColor("black") self._redSlider = ColorSlider(0, 255) self._redSlider.label = 'Red' self._redSlider.start_color = QColor("black") self._redSlider.end_color = QColor("red") self._greenSlider = ColorSlider(0, 255) self._greenSlider.label = 'Green' self._greenSlider.start_color = QColor("black") self._greenSlider.end_color = QColor("green") self._blueSlider = ColorSlider(0, 255) self._blueSlider.label = 'Blue' self._blueSlider.start_color = QColor("black") self._blueSlider.end_color = QColor("blue") self._alphaSlider = ColorSlider(0, 255) self._alphaSlider.label = 'Alpha' self._alphaSlider.start_color = QColor("black") self._alphaSlider.end_color = QColor("black") self._alphaSlider.value = 255 # Initialize Color Box self._colorBox = ColorBox(self._primarySelectedColor, self._secondarySelectedColor) # Set Initial Colors self.primary_color = QColor('black') self.secondary_color = QColor('white') # Initialize Layout self._layout = QVBoxLayout() self._layout.setAlignment(Qt.AlignTop) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.addWidget(self._palette) self._layout.addWidget(self._colorBox) self._layout.addWidget(self._hueSlider) self._layout.addWidget(self._satSlider) self._layout.addWidget(self._valSlider) self._layout.addWidget(self._redSlider) self._layout.addWidget(self._greenSlider) self._layout.addWidget(self._blueSlider) self._layout.addWidget(self._alphaSlider) self.setLayout(self._layout) # Initialize Events self._init_events() # Set Style self.setStyleSheet("background-color: #333") # ========== PUBLIC API ======================================================================= @property def primary_color(self): return self._primarySelectedColor @primary_color.setter def primary_color(self, value): if self._primarySelectedColor is None: self._primarySelectedColor = QColor() self._primarySelectedColor.setRgba(value.rgba()) self._on_primary_color_changed(update_alpha_value=True) self._primarySelectedColor = value @property def secondary_color(self): return self._secondarySelectedColor @secondary_color.setter def secondary_color(self, value): if self._secondarySelectedColor is None: self._secondarySelectedColor = QColor() self._secondarySelectedColor.setRgba(value.rgba()) self._on_secondary_color_changed(update_alpha_value=True) self._secondarySelectedColor = value def set_color_hue(self, h, color_index=None): color_index = color_index or ColorIndex.Primary store_alpha = self._primarySelectedColor.alpha() if color_index == ColorIndex.Primary: self._primarySelectedColor.setHsv(h, self._primarySelectedColor.saturation(), self._primarySelectedColor.value()) self._primarySelectedColor.setAlpha(store_alpha) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setHsv(h, self._secondarySelectedColor.saturation(), self._secondarySelectedColor.value()) self._secondarySelectedColor.setAlpha(store_alpha) self._on_secondary_color_changed() def set_color_saturation(self, s, color_index=None): color_index = color_index or ColorIndex.Primary store_alpha = self._primarySelectedColor.alpha() if color_index == ColorIndex.Primary: self._primarySelectedColor.setHsv(self._primarySelectedColor.hue(), s, self._primarySelectedColor.value()) self._primarySelectedColor.setAlpha(store_alpha) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setHsv(self._secondarySelectedColor.hue(), s, self._secondarySelectedColor.value()) self._secondarySelectedColor.setAlpha(store_alpha) self._on_secondary_color_changed(update_alpha_value=False) def set_color_value(self, v, color_index=None): color_index = color_index or ColorIndex.Primary store_alpha = self._primarySelectedColor.alpha() if color_index == ColorIndex.Primary: self._primarySelectedColor.setHsv(self._primarySelectedColor.hue(), self._primarySelectedColor.saturation(), v) self._primarySelectedColor.setAlpha(store_alpha) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setHsv(self._secondarySelectedColor.hue(), self._secondarySelectedColor.saturation(), v) self._secondarySelectedColor.setAlpha(store_alpha) self._on_secondary_color_changed(update_alpha_value=False) def set_color_red(self, r, color_index=None): color_index = color_index or ColorIndex.Primary if color_index == ColorIndex.Primary: self._primarySelectedColor.setRed(r) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setRed(r) self._on_secondary_color_changed(update_alpha_value=False) def set_color_green(self, g, color_index=None): color_index = color_index or ColorIndex.Primary if color_index == ColorIndex.Primary: self._primarySelectedColor.setGreen(g) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setGreen(g) self._on_secondary_color_changed(update_alpha_value=False) def set_color_blue(self, b, color_index=None): color_index = color_index or ColorIndex.Primary if color_index == ColorIndex.Primary: self._primarySelectedColor.setBlue(b) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setBlue(b) self._on_secondary_color_changed(update_alpha_value=False) def set_color_alpha(self, a, color_index=None): color_index = color_index or ColorIndex.Primary if color_index == ColorIndex.Primary: self._primarySelectedColor.setAlpha(a) self._on_primary_color_changed(update_alpha_value=False) elif color_index == ColorIndex.Secondary: self._secondarySelectedColor.setAlpha(a) self._on_secondary_color_changed(update_alpha_value=False) def select_next_color_on_palette(self): self._palette.move_color_selection(1) def select_previous_color_on_palette(self): self._palette.move_color_selection(-1) def select_next_ramp_on_palette(self): self._palette.move_ramp_selection(1) def select_previous_ramp_on_palette(self): self._palette.move_ramp_selection(-1) def switch_active_color(self): if self._activeColorIndex == ColorIndex.Primary: self._activeColorIndex = ColorIndex.Secondary else: self._activeColorIndex = ColorIndex.Primary self._colorBox.set_active_color_index(self._activeColorIndex) self._palette.switch_slot() self.update() def _init_events(self): self._palette.colorHovered.connect(self._on_palette_color_hovered) self._palette.colorSelected.connect(self._on_palette_color_changed) self._palette.mouseLeave.connect(self.on_palette_mouse_leave) self._hueSlider.valueChanged.connect(self._on_hue_slider_value_changed) self._satSlider.valueChanged.connect(self._on_sat_slider_value_changed) self._valSlider.valueChanged.connect(self._on_val_slider_value_changed) self._redSlider.valueChanged.connect(self._on_red_slider_value_changed) self._greenSlider.valueChanged.connect(self._on_green_slider_value_changed) self._blueSlider.valueChanged.connect(self._on_blue_slider_value_changed) self._alphaSlider.valueChanged.connect(self._on_alpha_slider_value_changed) self._colorBox.mouseClicked.connect(self._on_color_box_clicked) def _update_sliders(self, update_alpha_value=None): color = (self._primarySelectedColor if self._activeColorIndex == ColorIndex.Primary else self._secondarySelectedColor) # HUE self._hueSlider.value = color.hue() # SATURATION self._satSlider.start_color = QColor.fromHsv(color.hue(), 0, color.value()) self._satSlider.end_color = QColor.fromHsv(color.hue(), 255, color.value()) self._satSlider.value = color.saturation() # VALUE self._valSlider.end_color = QColor.fromHsv(color.hue(), color.saturation(), 255) self._valSlider.value = color.value() # RGB self._redSlider.value = color.red() self._greenSlider.value = color.green() self._blueSlider.value = color.blue() # ALPHA alpha_color = QColor(color) alpha_color.setAlpha(0) self._alphaSlider.start_color = alpha_color alpha_color.setAlpha(255) self._alphaSlider.end_color = alpha_color if update_alpha_value: self._alphaSlider.value = color.alpha() def _on_primary_color_changed(self, update_alpha_value=None): self._colorBox.primary_color = self._primarySelectedColor self._update_sliders(update_alpha_value) self.update() self.primaryColorChanged.emit(self._primarySelectedColor) def _on_secondary_color_changed(self, update_alpha_value=None): self._colorBox.secondary_color = self._secondarySelectedColor self._update_sliders(update_alpha_value) self.update() self.secondaryColorChanged.emit(self._secondarySelectedColor) def _on_palette_color_hovered(self, color): self._colorBox.preview_color = color self.update() def on_palette_mouse_leave(self): self._colorBox.preview_color = None self.update() def _on_palette_color_changed(self, color, color_index): if color_index == ColorIndex.Primary: self._activeColorIndex = ColorIndex.Primary self.primary_color = color self._colorBox.set_active_color_index(ColorIndex.Primary) elif color_index == ColorIndex.Secondary: self._activeColorIndex = ColorIndex.Secondary self.secondary_color = color self._colorBox.set_active_color_index(ColorIndex.Secondary) def _on_hue_slider_value_changed(self, value): self.set_color_hue(value, self._activeColorIndex) def _on_sat_slider_value_changed(self, value): self.set_color_saturation(value, self._activeColorIndex) def _on_val_slider_value_changed(self, value): self.set_color_value(value, self._activeColorIndex) def _on_red_slider_value_changed(self, value): self.set_color_red(value, self._activeColorIndex) def _on_green_slider_value_changed(self, value): self.set_color_green(value, self._activeColorIndex) def _on_blue_slider_value_changed(self, value): self.set_color_blue(value, self._activeColorIndex) def _on_alpha_slider_value_changed(self, value): self.set_color_alpha(value, self._activeColorIndex) def _on_color_box_clicked(self, color_box_index): if color_box_index != self._activeColorIndex: if color_box_index == 0: self._activeColorIndex = ColorIndex.Primary elif color_box_index == 1: self._activeColorIndex = ColorIndex.Secondary self._palette.switch_slot()
def outlineColorChanged(self, color: QColor) -> None: self.polygon.outlineColor = (color.red(), color.green(), color.blue(), color.alpha()) self.propertiesChanged.emit(self.polygon, True)
if not 4 <= len(sys.argv) <= 7: sys.stderr.write( "Usage: %s [--background=<color>] [--stitches-only] [--quality=high|low] <dimensions> <JEF file> <PNG file>\n" % sys.argv[0]) sys.exit(1) stitches_only = read_argument("--stitches-only", sys.argv) background = read_argument("--background=", sys.argv) if background is False: background_color = qRgba(0, 0, 0, 0) else: color = QColor(background) background_color = qRgba(color.red(), color.green(), color.blue(), color.alpha()) quality = read_argument("--quality=", sys.argv) if quality is False: quality = "high" elif quality != "high" and quality != "low": sys.stderr.write("Please specify either low or high quality.\n") sys.exit(1) dimensions = sys.argv[1] try: width, height = map(int, dimensions.split("x")) if width <= 0 or height <= 0: raise ValueError except ValueError:
class Canvas(widgets.QWidget): def __init__(self, parent=None): super().__init__(parent) self.background_color = QColor('#000000') self.rubberMode = False self.rubberModeStrokeWidthFctr = 20 self.stroke_width = 1 self.pen_color = QColor('#00FF00') self.col_prev_rct = QRect(0, 0, 20, 20) self.initImage() self.points = list() self.curDragPoints = list() self._initPointsAverager() self.reg = list() # self.setMouseTracking(True) def setPointsData(self, data): self.points = data.points self.img = data.img self.validateImage() self.update() def setPoints(self, points): self.points = points def validateImage(self): if self.img.isNull(): self.initImage() def getPointsData(self): return PointsData(self.points, self.img) @pyqtSlot() def retrieveUpdatedData(self): try: data = self.dataRetriever() self.setPointsData(data) except: pass @pyqtSlot() def updateData(self): try: self.dataUpdater(self.getPointsData()) except: pass def getPoints(self): return self.points def initImage(self): self.img = initImage(self.size(), self.background_color) def drawColorPreview(self): self.painter.setBrush(QBrush(self.pen_color)) self.painter.drawRect(self.col_prev_rct) def rgba(self): return (self.pen_color.red(), self.pen_color.green(), self.pen_color.blue(), self.pen_color.alpha()) @pyqtSlot(int, int, int, int) def rgba_changed(self, r, g, b, a): self.pen_color = QColor(r, g, b, a) self.update() @pyqtSlot('QString') def setPenColor(self, col_hex): self.pen_color = QColor(col_hex) self.update() @pyqtSlot() def saveImage(self): if self.img.isNull(): return img_path = saveFileDialog(self) if img_path: pixmp = QPixmap.fromImage(self.img) pixmp.save(img_path, quality=100) @pyqtSlot(int) def setStrokeWidth(self, sw): self.stroke_width = max(sw, 0.25) def strokeWidth(self): return self.stroke_width def resizeEvent(self, e): if not self.img.isNull(): self.img = resizeImage(self.img, self.size(), self.background_color) def paintEvent(self, event): painter = QPainter(self) self.painter = painter self.paintBackground() if not self.img.isNull(): pixmp = QPixmap.fromImage(self.img) painter.drawPixmap(pixmp.rect(), pixmp, pixmp.rect()) # for p in self.curDragPoints: # col = self.background_color if self.rubberMode else self.pen_color # self.drawDispersePoint(p, self.stroke_width, col=col) self.drawColorPreview() painter.end() del painter def createImagePainter(self): if self.img.isNull(): return painter = QPainter(self.img) self.painter = painter def deletePainter(self): self.painter.end() del self.painter def drawLinesOnImage(self, points): if self.img.isNull(): return self.createImagePainter() self.drawLines(points) self.deletePainter() def drawLatestAveragedPontsOnImage(self, averager=None): if averager is None: averager = self.pntsAvrgr # self.pntsAvrgr.getLatestAveragedPoints() - if no new points are available, None is returned! latestAvrgdPoints = averager.getLatestAveragedPoints() if latestAvrgdPoints is not None: self.drawLinesOnImage(latestAvrgdPoints) self.update() @pyqtSlot() def clearCanvas(self): self._clearPoints() self._clearImg() self.updateData() self.update() def _clearImg(self): if self.img.isNull(): return painter = QPainter(self.img) painter.setBrush(QBrush(self.background_color)) painter.drawRect(self.img.rect()) painter.end() del painter def _clearPoints(self): self.points.clear() self.curDragPoints.clear() def paintBackground(self): self.painter.setBrush(QBrush(self.background_color)) self.painter.drawRect(0, 0, 10000, 10000) def mouseMoveEvent(self, e): self.mouseMovePressed(e) def mousePressEvent(self, e): btns = e.buttons() if btns == Qt.LeftButton or btns == Qt.RightButton: self.rubberMode = btns == Qt.RightButton self._initPointsAverager() self.curDragPoints = list() self.addPoint((e.x(), e.y())) def _onAvrgrFinalized(self, averager): self.points.append(averager.getPoints()) self.updateData() self.update() def mouseReleaseEvent(self, e): #pnts_cnt = len(self.curDragPoints) self.pntsAvrgr.finalize() #self.points.append( self.pntsAvrgr.getPoints() ) #self.drawLatestAveragedPontsOnImage() self.curDragPoints = list() self.rubberMode = False self.update() def _initPointsAverager(self): pntsAvrgr = PointsAverager() pntsAvrgr.rubberMode = self.rubberMode def newAvrgPntsAvlbl(): rmBckup = self.rubberMode self.rubberMode = pntsAvrgr.rubberMode self._newAveragedPointsAvailable(pntsAvrgr) self.rubberMode = rmBckup def onFnlzd(): self._onAvrgrFinalized(pntsAvrgr) pntsAvrgr.onNewAvergedPointsAvailable.connect(newAvrgPntsAvlbl) pntsAvrgr.onFinalized.connect(onFnlzd) self.pntsAvrgr = pntsAvrgr def _newAveragedPointsAvailable(self, averager): self.drawLatestAveragedPontsOnImage(averager) def mouseMovePressed(self, e): curPnt = (e.x(), e.y()) self.addPoint(curPnt) def addPoint(self, p): self.curDragPoints.append(p) self.pntsAvrgr.addPoint(p) #self.drawLatestAveragedPontsOnImage() self.update() def drawLines(self, pnts): pen = QPen() pen.setWidth(1) pen_width = self.stroke_width if self.rubberMode: pen_width *= self.rubberModeStrokeWidthFctr col = self.background_color if self.rubberMode else self.pen_color ld = LineDrawer() ld.addPoints(pnts) ld.drawLines(self.painter, col, pen_width)
def _deserialize_color(color: QtGui.QColor) -> AssColor: return AssColor(color.red(), color.green(), color.blue(), 255 - color.alpha())
def setColor(self, color: QColor): # RGB channels are used for widget color bar display self.color = QColor(color.rgb()) # Alpha channel will be used as the new widget value self.value = color.alpha() self.update()
def color_values(color: QColor) -> t.Tuple[int, int, int, int]: return color.red(), color.green(), color.blue(), color.alpha()
class ColorBox(QWidget): mouseClicked = pyqtSignal(int) def __init__(self, color_a=None, color_b=None): super(ColorBox, self).__init__() self._previewColor = None self._primaryColor = QColor(color_a) self._secondaryColor = QColor(color_b) self._activeColorIndex = ColorIndex.Primary self._background = utils.generate_checkerboard_tile(8, QColor(150, 150, 150), QColor(175, 175, 175)) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) @property def primary_color(self): return self._primaryColor @primary_color.setter def primary_color(self, value): if self._primaryColor is None: self._primaryColor = QColor() self._primaryColor.setRgba(value.rgba()) @property def secondary_color(self): return self._secondaryColor @secondary_color.setter def secondary_color(self, value): if self._secondaryColor is None: self._secondaryColor = QColor() self._secondaryColor.setRgba(value.rgba()) @property def preview_color(self): return self._previewColor @preview_color.setter def preview_color(self, value): if self._previewColor is None: self._previewColor = QColor() if value is not None: self._previewColor.setRgba(value.rgba()) else: self._previewColor = None def set_active_color_index(self, index): self._activeColorIndex = index def mousePressEvent(self, e): clicked_pos = e.pos() if clicked_pos.x() <= self.rect().width() / 2: self._activeColorIndex = 0 self.update() self.mouseClicked.emit(0) else: self._activeColorIndex = 1 self.update() self.mouseClicked.emit(1) def paintEvent(self, e): p = QPainter(self) paint_rect = e.rect() half_width = paint_rect.width() / 2 paint_rect.adjust(0, 0, -half_width, -2) if self._primaryColor: if self._primaryColor.alpha() < 255: p.drawTiledPixmap(paint_rect, self._background) p.fillRect(paint_rect, self._primaryColor) if self._activeColorIndex == ColorIndex.Primary: p.fillRect(paint_rect.adjusted(0, paint_rect.height(), 0, paint_rect.height() + 2), QColor("red")) if self._secondaryColor: second_box_rect = paint_rect.translated(half_width, 0) if self._primaryColor.alpha() < 255: p.drawTiledPixmap(second_box_rect, self._background) p.fillRect(second_box_rect, self._secondaryColor) if self._activeColorIndex == ColorIndex.Secondary: p.fillRect(paint_rect.adjusted(paint_rect.width(), paint_rect.height(), paint_rect.width(), paint_rect.height() + 2), QColor("red")) if self._previewColor: if self._activeColorIndex == ColorIndex.Primary: p.fillRect(paint_rect, self._previewColor) else: p.fillRect(paint_rect.translated(half_width, 0), self._previewColor) def sizeHint(self): return QSize(223, 17)