python - 使用 QPainter 覆盖两个具有 alpha 值的像素图
问题描述
我正在尝试覆盖 2 个像素图并将它们转换为 QGraphics 场景中的单个像素图。两个像素图在某些位置都是透明的。我想使用此处列出的“SourceOver”混合类型来组合地图:我在下面有一个简单的玩具示例来说明我的问题,其中我创建了两个虚拟透明像素图,一个绿色和一个蓝色。实际上,这些地图是从图像中加载并绘制出来的,但是这个例子重现了这个问题。基于此如何在另一个图像的顶部添加图像?,我尝试的方法(注释掉 4 行)是使用其中一个像素图创建一个 QPainter,然后在其上绘制另一个像素图,但是这会使程序崩溃。有想法该怎么解决这个吗?我最终希望能够保存组合的像素图。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QPixmap, QPainter, QPen, QBrush, QPainterPath
from PyQt5.QtCore import (QLineF, QPointF, QRectF, Qt)
class Viewer(QtWidgets.QGraphicsView):
def __init__(self, parent):
super(Viewer, self).__init__(parent)
self._scene = QtWidgets.QGraphicsScene(self)
self.photo = QtWidgets.QGraphicsPixmapItem()
self.label = QtWidgets.QGraphicsPixmapItem()
self._scene.addItem(self.photo)
self._scene.addItem(self.label)
self.setScene(self._scene)
def overlayMaps(self):
blue = QtGui.QPixmap(600, 600)
blue.fill(QtGui.QColor(0,0,255,0))
p = QPainter(blue)
self.pen = QPen()
self.pen.setColor(QtGui.QColor(0,0,255,255))
self.pen.setWidth(10)
p.setPen(self.pen)
p.drawLine(0,0,600,600)
green = QtGui.QPixmap(600, 600)
green.fill(QtGui.QColor(0,255,0,0))
p = QPainter(green)
self.pen = QPen()
self.pen.setColor(QtGui.QColor(0,255,0,255))
self.pen.setWidth(10)
p.setPen(self.pen)
p.drawLine(600,0,0,600)
self.photo.setPixmap(blue)
self.label.setPixmap(green)
resultPixmap = QtGui.QPixmap(self.photo.pixmap().width(), self.photo.pixmap().height())
# resultPainter = QtGui.QPainter(resultPixmap)
# resultPainter.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
# resultPainter.drawPixmap(300,300, self.photo.pixmap())
# resultPainter.drawPixmap(300,300, self.label.pixmap())
def saveOverlayMap(self):
pass
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.viewer = Viewer(self)
self.viewer.overlayMaps()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 600, 600)
window.show()
sys.exit(app.exec_())
解决方案
我已经实现了一个根据模式执行加入操作的功能,为了更好地欣赏我已经移动了这些项目。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
def join_pixmap(p1, p2, mode=QtGui.QPainter.CompositionMode_SourceOver):
s = p1.size().expandedTo(p2.size())
result = QtGui.QPixmap(s)
result.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(result)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.drawPixmap(QtCore.QPoint(), p1)
painter.setCompositionMode(mode)
painter.drawPixmap(result.rect(), p2, p2.rect())
painter.end()
return result
class Viewer(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Viewer, self).__init__(parent)
self._scene = QtWidgets.QGraphicsScene(self)
self.setScene(self._scene)
blue = QtGui.QPixmap(100, 100)
blue.fill(QtCore.Qt.transparent)
p = QtGui.QPainter(blue)
pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0,0,255)), 10)
p.setPen(pen)
p.drawLine(0, 0, 100, 100)
p.end()
self.photo = self._scene.addPixmap(blue)
green = QtGui.QPixmap(100, 100)
green.fill(QtCore.Qt.transparent)
p = QtGui.QPainter(green)
pen = QtGui.QPen(QtGui.QBrush(QtGui.QColor(0, 255, 0, 255)), 10)
p.setPen(pen)
p.drawLine(100, 0, 0, 100)
p.end()
self.label = self._scene.addPixmap(green)
self.label.setPos(200, 0)
self.overlayMaps()
def overlayMaps(self):
p1 = QtGui.QPixmap(self.photo.pixmap())
p2 = QtGui.QPixmap(self.label.pixmap())
result_pixmap = join_pixmap(self.photo.pixmap(), self.label.pixmap())
self.result_item = self._scene.addPixmap(result_pixmap)
self.result_item.setPos(100, 200)
result_pixmap.save("result_pixmap.png")
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Viewer()
window.resize(640, 480)
window.show()
sys.exit(app.exec_())
result_pixmap.png
推荐阅读
- iframe - Youtube 视频 iframe 无法加载
- javascript - Promises.all 在循环多个 ajax 请求后未触发
- c# - 为什么我不能反序列化 Json 数组 C#?
- json - 错误无法加载 Json 文件:{"headers":{"normalizedNames":{},"lazyUpdate":null} in angular
- mysql - 在 SQL 中将两列值相除并将结果插入新列
- python - 无法安装 Tensorflow,tensorflow-base-1.12 错误
- java - 从 Android Studio 中的自定义应用程序发送电子邮件 + 附件,为什么 URI 为空?
- d3.js - D3.JS 根据输入变化重新计算 datum() 值
- excel - 将多个excel文件中的数据合并到一个主文件中
- mqtt - 对 Mosquitto MQTT 服务器进行分区