实战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等。

 

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,os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter,QPixmap
from 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 = type
        
        self.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.5
        new_h = pix.height() * 0.5
        pix = 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.5
        new_h = pix.height() * 1.5
        pix = 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())

运行结果如下图:

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

QPixmap演示

本文知识点

  • Qt提供了四个用于处理图像数据的类。
  • 使用QPixmap来加载和显示图像。
  • 使用QPixmap来绘制离屏图像。
  • 保存QPixmap。
  • QBitmap位图。

前一篇: 实战PyQt5: 119-图标处理类QIcon

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值