def testImage(): width, height = 100, 100 im = QImage(width, height, QImage.Format_ARGB32) for x in range(im.width()): for y in range(im.height()): if x % 2 == 0: im.setPixel(x, y, QColor('white').rgb()) else: im.setPixel(x, y, QColor('black').rgb()) # im.setPixel(x, y, QColor(255, x*2.56, y*2.56, 255).rgb()) im.save('test.png')
class SetPixelFloat(UsesQApplication): '''Test case for calling setPixel with float as argument''' def setUp(self): #Acquire resources super(SetPixelFloat, self).setUp() self.color = qRgb(255, 0, 0) self.image = QImage(200, 200, QImage.Format_RGB32) def tearDown(self): #Release resources del self.color del self.image super(SetPixelFloat, self).tearDown() def testFloat(self): #QImage.setPixel(float, float, color) - Implicit conversion self.image.setPixel(3.14, 4.2, self.color) self.assertEqual(self.image.pixel(3.14, 4.2), self.color)
class SetPixelFloat(UsesQApplication): '''Test case for calling setPixel with float as argument''' def setUp(self): #Acquire resources super(SetPixelFloat, self).setUp() self.color = qRgb(255, 0, 0) self.image = QImage(200, 200, QImage.Format_RGB32) def tearDown(self): #Release resources del self.color del self.image super(SetPixelFloat, self).tearDown() def testFloat(self): #QImage.setPixel(float, float, color) - Implicit conversion self.image.setPixel(3.14, 4.2, self.color) self.assertEqual(self.image.pixel(3.14, 4.2), self.color)
class SpriteView(QWidget): sprite_edited = Signal() def __init__(self, parent): super().__init__(parent) self._scene = QGraphicsScene(self) self._graphics_view = QGraphicsView(self._scene, self) layout = QVBoxLayout(self) layout.addWidget(self._graphics_view) self._pixmap_item = SpriteGraphicsItem(self) self._scene.addItem(self._pixmap_item) self._image = QImage(SPRITE_SIZE, SPRITE_SIZE, QImage.Format_ARGB32) self.sprite = [[0] * SPRITE_SIZE] * SPRITE_SIZE button_layout = QHBoxLayout(self) layout.addLayout(button_layout) self._color_button_group = QButtonGroup(self) for color in COLORS: button = QPushButton(self) button.setCheckable(True) button.setText(f"{color}") self._color_button_group.addButton(button, color) button_layout.addWidget(button) self._selected_color = 0 self._color_button_group.button(self._selected_color).setChecked(True) QObject.connect(self._color_button_group, SIGNAL("buttonClicked(int)"), self._color_selected) self._update_scaling() @property def sprite(self): return self._sprite @sprite.setter def sprite(self, sprite): if len(sprite) != SPRITE_SIZE: raise SpriteFormatException("Invalid Row Count") for row in sprite: if len(row) != SPRITE_SIZE: raise SpriteFormatException("Invalid Column Count") for value in row: if value not in COLORS: raise SpriteFormatException(f"Invalid Color Value {value}") self._sprite = sprite self._update_image() def _update_image(self): for row in range(SPRITE_SIZE): for column in range(SPRITE_SIZE): self._image.setPixel(column, row, COLORS[self._sprite[row][column]]) pixmap = QPixmap.fromImage(self._image) self._pixmap_item.setPixmap(pixmap) def resizeEvent(self, *args, **kwargs): super().resizeEvent(*args, **kwargs) self._update_scaling() def showEvent(self, *args, **kwargs): super().showEvent(*args, **kwargs) self._update_scaling() def _update_scaling(self): self._graphics_view.fitInView(self._pixmap_item, Qt.KeepAspectRatio) def _color_selected(self, id): self._selected_color = id def paint_pixel(self, x, y): if self._sprite[y][x] == self._selected_color: return self._sprite[y][x] = self._selected_color self._update_image() self.sprite_edited.emit()
def run(self): while True: self.mutex.lock() resultSize = self.resultSize scaleFactor = self.scaleFactor centerX = self.centerX centerY = self.centerY self.mutex.unlock() halfWidth = resultSize.width() // 2 halfHeight = resultSize.height() // 2 image = QImage(resultSize, QImage.Format_RGB32) NumPasses = 8 curpass = 0 while curpass < NumPasses: MaxIterations = (1 << (2 * curpass + 6)) + 32 Limit = 4 allBlack = True for y in range(-halfHeight, halfHeight): if self.restart: break if self.abort: return ay = 1j * (centerY + (y * scaleFactor)) for x in range(-halfWidth, halfWidth): c0 = centerX + (x * scaleFactor) + ay c = c0 numIterations = 0 while numIterations < MaxIterations: numIterations += 1 c = c * c + c0 if abs(c) >= Limit: break numIterations += 1 c = c * c + c0 if abs(c) >= Limit: break numIterations += 1 c = c * c + c0 if abs(c) >= Limit: break numIterations += 1 c = c * c + c0 if abs(c) >= Limit: break if numIterations < MaxIterations: image.setPixel( x + halfWidth, y + halfHeight, self.colormap[numIterations % RenderThread.ColormapSize]) allBlack = False else: image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0)) if allBlack and curpass == 0: curpass = 4 else: if not self.restart: self.renderedImage.emit(image, scaleFactor) curpass += 1 self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock()
def run(self): while True: self.mutex.lock() resultSize = self.resultSize scaleFactor = self.scaleFactor centerX = self.centerX centerY = self.centerY self.mutex.unlock() halfWidth = resultSize.width() // 2 halfHeight = resultSize.height() // 2 image = QImage(resultSize, QImage.Format_RGB32) NumPasses = 8 curpass = 0 while curpass < NumPasses: MaxIterations = (1 << (2 * curpass + 6)) + 32 Limit = 4 allBlack = True for y in range(-halfHeight, halfHeight): if self.restart: break if self.abort: return ay = 1j * (centerY + (y * scaleFactor)) for x in range(-halfWidth, halfWidth): c0 = centerX + (x * scaleFactor) + ay c = c0 numIterations = 0 while numIterations < MaxIterations: numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break numIterations += 1 c = c*c + c0 if abs(c) >= Limit: break if numIterations < MaxIterations: image.setPixel(x + halfWidth, y + halfHeight, self.colormap[numIterations % RenderThread.ColormapSize]) allBlack = False else: image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0)) if allBlack and curpass == 0: curpass = 4 else: if not self.restart: self.renderedImage.emit(image, scaleFactor) curpass += 1 self.mutex.lock() if not self.restart: self.condition.wait(self.mutex) self.restart = False self.mutex.unlock()
class Canvas(QWidget): content_changed = Signal() _background_color = QColor.fromRgb(0, 0, 0) _foreground_color = QColor.fromRgb(255, 255, 255) def __init__(self, parent, w, h, pen_width, scale): super().__init__(parent) self.w = w self.h = h self.scaled_w = scale * w self.scaled_h = scale * h self.scale = scale # Set size self.setFixedSize(self.scaled_w, self.scaled_h) # Create image self.small_image = QImage(self.w, self.h, QImage.Format_RGB32) self.small_image.fill(self._background_color) self.large_image = QImage(self.scaled_w, self.scaled_h, QImage.Format_RGB32) self.large_image.fill(self._background_color) # Create pen self.pen = QPen() self.pen.setColor(self._foreground_color) self.pen.setJoinStyle(Qt.RoundJoin) self.pen.setCapStyle(Qt.RoundCap) self.pen.setWidthF(scale * pen_width) # There is currently no path self.currentPath = None self.content_changed.connect(self.repaint) def _get_painter(self, paintee): painter = QPainter(paintee) painter.setPen(self.pen) painter.setRenderHint(QPainter.Antialiasing, True) return painter def _derive_small_image(self, large_image=None): if large_image is None: large_image = self.large_image # Downsample image self.small_image = large_image.scaled(self.w, self.h, mode=Qt.SmoothTransformation) self.content_changed.emit() def _current_path_updated(self, terminate_path=False): # Determine whether to draw on the large image directly or whether to make a temporary copy paintee = self.large_image if terminate_path else self.large_image.copy( ) # Draw path on the large image of choice painter = self._get_painter(paintee) if self.currentPath.elementCount() != 1: painter.drawPath(self.currentPath) else: painter.drawPoint(self.currentPath.elementAt(0)) painter.end() # Optionally terminate the path if terminate_path: self.currentPath = None # Downsample image self._derive_small_image(paintee) def _clear_image(self): self.large_image.fill(self._background_color) self._derive_small_image() def get_content(self): return np.asarray(self.small_image.constBits()).reshape( (self.h, self.w, -1)) def set_content(self, image_rgb): for row in range(image_rgb.shape[0]): for col in range(image_rgb.shape[1]): self.small_image.setPixel(col, row, image_rgb[row, col]) self.large_image = self.small_image.scaled( self.scaled_w, self.scaled_h, mode=Qt.SmoothTransformation) self._derive_small_image() self.content_changed.emit() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: # Create new path self.currentPath = QPainterPath() self.currentPath.moveTo(event.pos()) self._current_path_updated() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) and self.currentPath is not None: # Add point to current path self.currentPath.lineTo(event.pos()) self._current_path_updated() def mouseReleaseEvent(self, event): if (event.button() == Qt.LeftButton) and self.currentPath is not None: # Add terminal point to current path self.currentPath.lineTo(event.pos()) self._current_path_updated(terminate_path=True) elif event.button() == Qt.RightButton: self._clear_image() def paintEvent(self, event): paint_rect = event.rect() # Only paint the surface that needs painting painter = self._get_painter(self) # Draw image painter.scale(self.scale, self.scale) painter.drawImage(paint_rect, self.small_image, paint_rect) painter.end() painter = self._get_painter(self) #if self.currentPath is not None: # painter.drawPath(self.currentPath) @Slot() def repaint(self): super().repaint()
class IconEditor(QWidget): def __init__(self): super(IconEditor, self).__init__() self.setAttribute(Qt.WA_StaticContents) self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum) self.curColor = Qt.black self.zoom = 8 * 1 self.image = QImage(16, 16, QImage.Format_ARGB32) self.image.fill(qRgba(0, 0, 0, 0)) def penColor(self): return self.curColor def setPenColor(self, newColor): self.curColor = newColor def zoomFactor(self): return self.zoom def setZoomFactor(self, newZoom): if newZoom < 1: newZoom = 1 if newZoom != self.zoom: self.zoom = newZoom self.update() self.updateGeometry() def iconImage(self): return self.image def setIconImage(self, newImage): if newImage != self.image: print('updating image') self.image = newImage.convertToFormat(QImage.Format_ARGB32) self.update() self.updateGeometry() def sizeHint(self): size = self.zoom * self.image.size() if self.zoom >= 3: size += QSize(1, 1) return size def pixelRect(self, i, j): if self.zoom >= 3: return QRect(self.zoom * i + 1, self.zoom * j + 1, self.zoom - 1, self.zoom - 1) else: return QRect(self.zoom * i, self.zoom * j, self.zoom, self.zoom) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.setImagePixel(event.pos(), True) print('mouse left press') elif event.button() == Qt.RightButton: self.setImagePixel(event.pos(), False) print('mouse right press') def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.setImagePixel(event.pos(), True) elif event.buttons() & Qt.RightButton: self.setImagePixel(event.pos(), False) def setImagePixel(self, pos, opaque): i = pos.x() // self.zoom j = pos.y() // self.zoom print(f'setting pixel ({i}, {j})') if self.image.rect().contains(i, j): if opaque: penC = QColor('black') self.image.setPixel(i, j, penC.rgba()) # self.image.setPixel(i, j, QColor(255, i*2.56, j*2.56, 255).rgb()) else: print('#' * 10) self.image.setPixel(QPoint(i, j), qRgba(0, 0, 0, 0)) print(f'Pixel Rect: {self.pixelRect(i,j)}') self.update(self.pixelRect(i, j)) def paintEvent(self, event): painter = QPainter(self) if self.zoom >= 3: painter.setPen(self.palette().foreground().color()) # painter.setPen(QPen('red')) for i in range(0, self.image.width()): painter.drawLine(self.zoom * i, 0, self.zoom * i, self.zoom * self.image.height()) for j in range(0, self.image.height()): painter.drawLine(0, self.zoom * j, self.zoom * self.image.width(), self.zoom * j) for i in range(0, self.image.width()): for j in range(0, self.image.height()): rect = self.pixelRect(i, j) if event.region().intersected(rect): color = QColor.fromRgba(self.image.pixel(i, j)) if color.alpha() < 255: painter.fillRect(rect, Qt.white) painter.fillRect(rect, color) penColorProperty = property(QColor, penColor, setPenColor) iconImageProperty = property(QImage, iconImage, setIconImage) zoomFactorProperty = property(int, zoomFactor, setZoomFactor)