实战PyQt5:120-像素图QPixmap和QBitmap


实战PyQt5:120-像素图QPixmap和QBitmap文章插图
Qt提供了四个用于处理图像数据的类:QImage , QPixmap , QBitmap和QPicture 。 QImage是为I/O设计的 , 并且针对直接的像素访问和操作做了优化 , QPixmap是为在屏幕上显示图像而设计和优化的 。 QBitmap为继承自QPixmap的便利类 。 如果QPixmap对象确实是位图 , 在其isQBitmap()函数返回True, 否则返回False 。 QPicture类是一种绘图设备 , 它可以记录并重放QPainter的命令 。
QPixmap简介QPixmap类可以作为绘图设备来输出离屏(off-screen)图像 。 使用QLabel或者QAbstractButton的子类(例如QPushbutton和QToolButton) , 可以在屏幕上轻松地显示QPixmap 。 QPixmap是QPaintDevice的子类 , 因此QPainter可以直接在QPixmap的对象上绘图 。
QPixmap提供了多种方式来读取图像文件 , 在创建QPixmap对象时可以加载图像文件 , 也可以在创建对象之后 , 使用load()或者loadFrameData()函数来加载图像 。 加载图像时 , 文件名可以是磁盘上的实际文件 , 也可以是嵌入到应用程序的资源 。 QPixmap可以读取的文件类型有BMP、GIF、JPG、JPEG、PNG、PBM、PGM、PPM、XBM、XPM等 。
【实战PyQt5:120-像素图QPixmap和QBitmap】QPixmap的常用方法:

  • copy(self, rect): 从QRect对象复制到QPixmap对象 。
  • fromImage(image, flag): 静态函数 ,将QImage对象转换为QPixmap对象 。
  • fill(self, color : QColor): 用给定的color填充 。
  • width(self): 返回图像的宽度 。
  • height(self): 返回图像的高度 。
  • loadFromData(self, data, len, format,flag): 从给定的二进制数据data的前len个字节加载带像素图 。 如果指定了格式format , 则按指定格式加载 , 如果未指定格式 , 那么加载程序将根据相关信息猜测加载格式 。
  • save(self, filename, format, quality): 使用指定的图像格式format和质量因子quality将像素图保存到文件filename中 。 quality必须在范围[0,100]或-1 。 指定0以获取小的压缩文件 , 指定100为大的未压缩文件 , 并指定-1以使用默认设置 。
  • toImage(): 将像素图转换为QImage 。 如果转换失败 , 则返回一个空图像 。
QBitmap简介QBitmap类提供单色(1位深度)像素图 。 它主要用于创建自定义QCursor和QBrush对象 , 构造QRegion对象以及为像素图和部件设置蒙版(mask) 。 QBitmap的位深度为1(空对象为0) , 如果将位深度大于1的像素图分配给位图 , 组位图将自动抖动 。
在QBitmap对象上绘制图像时 , 使用Qt.color0将位图位设置为0 , 使用Qt.color1将位图位设置为1. 对一个位图来说 , 0位表示背景(或者透明像素),1位表示前景(或不透明像素) 。 使用clear()函数将所有位设置为0 。 注意 , 在位图中 , 使用Qt.black 和Qt.white颜色是没有意义的 , 因为QColor.pixel()值对于黑色并不一定是0 , 对于白色并不一定是1 。
QBitmap常用函数:
  • clear(self): 清除位图 , 将其所有位都设置为Qt.color0 。
  • fromData( size:QSize, bits, format): 静态函数 , 创建一个给定size大小的位图 , 并将其内容设置为给定的bits 。
  • fromImage(image, flag): 静态函数 , 从给定的图像image创建一个位图 。
测试演示程序使用QPixmap加载一个图像文件 , 结合QPainter变换操作 , 演示缩放 , 旋转和扭曲图像效果 。完整代码如下:
import sys,osfrom PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtCore import Qtfrom PyQt5.QtGui import QPainter,QPixmapfrom PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,QMenuBar, QMenu, QAction, QGridLayout,QSizePolicy) class MyPixmapWidget(QWidget):def __init__(self, type, parent = None):super(MyPixmapWidget, self).__init__(parent)self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)self.type = typeself.image_filename = os.path.dirname(__file__) + '/panda.jpg'def paintEvent(self, event):painter = QPainter(self)painter.setRenderHint(QPainter.Antialiasing, True)#绘制边框线painter.drawRect(self.rect())self.setFixedSize(256, 256)if self.type == '原图':self.drawOrignal(painter)elif self.type == '缩小':self.drawZoomOut(painter)elif self.type == '放大':self.drawZoomIn(painter)elif self.type == '旋转':self.drawRotate(painter)elif self.type == '横向扭曲':self.drawShearHor(painter)elif self.type == '纵向扭曲':self.drawShearVer(painter)else:print('not supported')def drawOrignal(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '原图')pix = QPixmap(self.image_filename)rect = self.rect()painter.translate((rect.width() - pix.width()) / 2, (rect.height() - pix.height()) / 2)painter.drawPixmap(0, 0, pix)def drawZoomOut(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '缩小')pix = QPixmap(self.image_filename)rect = self.rect()new_w = pix.width() * 0.5new_h = pix.height() * 0.5pix = pix.scaled(new_w, new_h, Qt.KeepAspectRatio)painter.translate((rect.width() - new_w) / 2, (rect.height() - new_h) / 2)painter.drawPixmap(0, 0, pix)def drawZoomIn(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '放大')pix = QPixmap(self.image_filename)rect = self.rect()new_w = pix.width() * 1.5new_h = pix.height() * 1.5pix = pix.scaled(new_w, new_h, Qt.KeepAspectRatio)painter.translate((rect.width() - new_w) / 2, (rect.height() - new_h) / 2)painter.drawPixmap(0, 0, pix)def drawRotate(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '旋转')pix = QPixmap(self.image_filename)rect = self.rect()img_w = pix.width()img_h = pix.height()painter.rotate(60)painter.translate(100, -100)painter.drawPixmap(0, 0, pix)def drawShearHor(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '横向扭曲')pix = QPixmap(self.image_filename)rect = self.rect()painter.translate(20, (rect.height() - pix.height()) / 2)painter.shear(0.5,0); #横向扭曲painter.drawPixmap(0, 0, pix)def drawShearVer(self, painter):painter.drawText(self.rect(),Qt.AlignBottom|Qt.AlignCenter, '纵向扭曲 ')pix = QPixmap(self.image_filename)rect = self.rect()painter.translate((rect.width() - pix.width()) / 2, 20)painter.shear(0,0.5); #纵向扭曲painter.drawPixmap(0, 0, pix)class DemoPixmap(QMainWindow):def __init__(self, parent=None):super(DemoPixmap, self).__init__(parent)# 设置窗口标题self.setWindowTitle('实战 Qt for Python: QPixmap 演示')self.initUi()def initUi(self):self.initMenuBar()mainWidget = QWidget()layout = QGridLayout()lhGrad = MyPixmapWidget('原图')lvGrad = MyPixmapWidget('缩小')ldGrad = MyPixmapWidget('放大')qGradA = MyPixmapWidget('旋转')qGradB = MyPixmapWidget('横向扭曲')cGrad =MyPixmapWidget('纵向扭曲')layout.addWidget(lhGrad, 0, 0)layout.addWidget(lvGrad, 0, 1)layout.addWidget(ldGrad, 0, 2)layout.addWidget(qGradA, 1, 0)layout.addWidget(qGradB, 1, 1)layout.addWidget(cGrad, 1, 2)mainWidget.setLayout(layout)self.setCentralWidget(mainWidget)def initMenuBar(self):menuBar = self.menuBar()menuFile = menuBar.addMenu('文件(&F)')actionExit = QAction('退出(&X)', self)actionExit.triggered.connect(QApplication.instance().quit)menuFile.addAction(actionExit)if __name__ == '__main__':app = QApplication(sys.argv)window = DemoPixmap()window.show()sys.exit(app.exec())