百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

实战PyQt5: 121-使用QImage实现一个看图应用

liuian 2025-01-20 14:46 46 浏览

QImage简介

QImage类提供了独立于硬件的图像表示形式,该图像表示形式可以直接访问像素数据,并且可以用作绘制设备。QImage是QPaintDevice子类,因此可以使用QPainter直接在图像上绘制。在QImage上使用QPainter时,可以在当前GUI线程以外的其他线程中执行绘制。

QImage提供了多种方式来读取图像文件,在创建QImage对象时可以加载图像文件,也可以在创建对象之后,使用load()或者loadFrameData()函数来加载图像。加载图像时,文件名可以是磁盘上的实际文件,也可以是嵌入到应用程序的资源。

QImage类支持包括单色,8位,32位和alpha混合图像。QImage提供了一组函数用于获取有关图像的各种信息和实现图像转换。

  • 几何尺寸信息: 函数size(), width(), height(), dotsPerMeterX()和dotsPerMeterY()提供了图像的尺寸和纵横比信息。rect()函数返回图像的包围矩形,vaild()函数用于判断一组坐标是否位于这个包围矩形内。
  • 色彩信息: 使用pixel()函数可以获得指定像素的颜色,该颜色是一个独立于文件格式的QRgb值。对于单色或者8位图像,colorCount()和colorTable() 函数提供了有关用于存储图数据的颜色分量的信息。hasAlphaChannel()返回函数是否有alpha通道的信息。
  • 文本信息: text() 函数返回给定文本关键值的图像文本信息。函数textKeys()返回图像的文本关键值信息。
  • 底层信息: depth()函数返回图像的位深度信息。图像支持的深度信息把包括1(单色),8、16、24和32位。bitPlaneCount()返回图像的位平面数。

像素操作

QImage的像素操作功能取决于图像格式而有所不同,原因是单色和8位图像的颜色是基于索引值,使用颜色查找表来获得,而32位图像则直接存储ARGB值。

如果是32位图像,则可以使用setPixel()函数为给定的像素设置一个ARGB颜色值。例如:

image = QImage(3, 3, QImage.Format_RGB32)
 
value = qRgb(180, 149, 39)  # 0xffbd9527
image.setPixel(1, 1, value)
 
value = qRgb(122, 163, 39)  # 0xff7aa327
image.setPixel(0, 1, value)
image.setPixel(1, 0, value)
 
value = qRgb(237, 187, 51)  # 0xffedba31
image.setPixel(2, 1, value)

用一个方格表示一个像素,上面代码生成的图像可以用下图来描述:

对于8位和单色图像,像素值为图像颜色表中的索引值,因此setPixel()函数只能用于将给定位置的像素颜色设置为图像颜色表中的预定义的颜色值,即是说,它只能改变像素的索引值。若需要更改颜色或者将颜色添加到图像的颜色表中,可以使用setColor()函数来完成。颜色表中的一项为一个ARGB颜色值,使用qRgb()和qRgba()函数可以为setColor()提供需要的QRgb值。例如:

image = QImage(3, 3, QImage.Format_Indexed8)
 
value = qRgb(122, 163, 39)  # 0xff7aa327
image.setColor(0, value)
 
value = qRgb(237, 187, 51)  # 0xffedba31
image.setColor(1, value)
 
value = qRgb(180, 149, 39)  # 0xffbd9527
image.setColor(2, value)
 
image.setPixel(0, 1, 0)
image.setPixel(1, 0,0)
image.setPixel(1,1,2)
image.setPixel(2,1,1)

用一个方格表示一个像素,上面代码生成的图像可以用下图来描述:

图像格式

QImage中存储的每个像素都由整数表示。整数的大小取决于格式。QImage支持QImage.Format枚举描述的图像格式。Qt提供以下图像格式:

  • QImage.Format_Invalid (0): 无效图片。
  • QImage.Format_Mono (1): 每像素使用1位存储图像。字节首先用高位(MSB方式打包)。
  • QImage.Format_MonoLSB (2): 每像素使用1位存储图像。字节首先用低位(LSB方式打包)。
  • QImage.Format_Indexed8 (3): 使用8位索引将图像存储到颜色表中。
  • QImage.Format_RGB32 (4): 图像使用32位RGB格式(0xffRRGGBB)存储。
  • QImage.Format_ARGB32 (5): 图像使用32位ARGB格式(0xAARRGGBB)存储。
  • QImage.Format_ARGB32_Premultiplied (6): 使用预乘的32位ARGB格式(0xAARRGGBB)存储图像,即红色,绿色和蓝色通道乘以除以255的alpha分量。(如果RR,GG或BB的值大于alpha使用预乘ARGB32的某些操作(例如使用alpha混合的图像合成)要比使用普通ARGB32更快。
  • QImage.Format_RGB16 (7): 图像以16位RGB格式(5-6-5)存储。
  • QImage.Format_ARGB8565_Premultiplied (8): 使用预乘的24位ARGB格式(8-5-6-5)存储图像。
  • QImage.Format_RGB666 (9): 图像以24位RGB格式(6-6-6)存储。未使用的最高有效位始终为零。
  • QImage.Format_ARGB6666_Premultiplied (10): 使用预乘的24位ARGB格式(6-6-6-6)存储图像。
  • QImage.Format_RGB555 (11): 图像以16位RGB格式(5-5-5)存储。未使用的最高有效位始终为零。
  • QImage.Format_ARGB8555_Premultiplied (12): 使用预乘的24位ARGB格式(8-5-5-5)存储图像。
  • QImage.Format_RGB888 (13): 图像以24位RGB格式(8-8-8)存储。
  • QImage.Format_RGB444 (14): 图像以16位RGB格式(4-4-4)存储。未使用的位始终为零。
  • QImage.Format_ARGB4444_Premultiplied (15): 使用预乘的16位ARGB格式(4-4-4-4)存储图像。
  • QImage.Format_RGBX8888 (16): 图像使用32位字节排序的RGB(x)格式(8-8-8-8)存储。这与Format_RGBA8888相同,除了alpha必须始终为255。(在Qt 5.2中添加)
  • QImage.Format_RGBA8888 (17): 图像使用32位字节顺序RGBA格式(8-8-8-8)存储。与ARGB32不同,这是一种字节排序格式,这意味着32位编码在大字节序和小字节序架构之间有所不同,分别为(0xRRGGBBAA)和(0xAABBGGRR)。如果读取为字节0xRR,0xGG,0xBB,0xAA,则颜色顺序在任何体系结构上都是相同的。(在Qt 5.2中添加)。
  • QImage.Format_RGBA8888_Premultiplied (18): 使用预乘的32位字节排序RGBA格式(8-8-8-8)存储图像。(在Qt 5.2中添加)。
  • QImage.Format_BGR30 (19): 图像使用32位BGR格式(x-10-10-10)存储。(在Qt 5.4中添加)。
  • QImage.Format_A2BGR30_Premultiplied (20): 图像使用32位预乘ABGR格式(2-10-10-10)存储。(在Qt 5.4中添加)。
  • QImage.Format_RGB30 (21): 图像以32位RGB格式(x-10-10-10)存储。(在Qt 5.4中添加)。
  • QImage.Format_A2RGB30_Premultiplied (22): 图像使用32位预乘ARGB格式(2-10-10-10)存储。(在Qt 5.4中添加)。
  • QImage.Format_Alpha8 (23): 图像使用仅8位alpha格式存储。(在Qt 5.5中添加)。
  • QImage.Format_Grayscale8 (24): 图像使用8位灰度格式存储。(在Qt 5.5中添加)。
  • QImage.Format_Grayscale16 (28): 图像使用16位灰度格式存储。(在Qt 5.13中添加)。
  • QImage.Format_RGBX64 (25): 使用64位半字排序的RGB(x)格式(16-16-16-16)存储图像。这与Format_RGBA64相同,除了alpha必须始终为65535。(在Qt 5.12中添加)。
  • QImage.Format_RGBA64 (26): 图像使用64位半字排序RGBA格式(16-16-16-16)存储。(在Qt 5.12中添加)。
  • QImage.Format_RGBA64_Premultiplied (27): 使用预乘的64位半字排序RGBA格式(16-16-16-16)存储图像。(在Qt 5.12中添加)。
  • QImage.Format_BGR888 (29): 图像使用24位BGR格式存储。(在Qt 5.14中添加)。

图像变换和图像属性修改

QImage支持许多用于创建新图像的功能:

  • createAlphaMask(): 从该图像的alpha缓冲区生成并返回一个1-bpp的蒙版
  • mirrored(): 生成一个径向图像
  • scaled(): 生成一个缩放图像
  • rgbSwapped(): 从RGB图像构造一个BGR图像
  • scaledToWidth(): 返回缩放到指定宽度的图像
  • caledToHeight(): 返回缩放到指定高度的图像
  • transformed():返回使用给定的转换矩阵和转换模式转换的图像

一些用于就地图像属性的函数:

  • setDotsPerMeterX(): 设置物理单位的水平像素数来定义纵横比。
  • setDotsPerMeterY(): 设置物理单位的垂直像素数来定义纵横比。
  • fill(): 用给定的像素值填充整个图像。
  • invertPixels(): 使用给定的InvertMode值反转图像中的所有像素值。
  • setColorTable(): 设置用于转换颜色索引的颜色表。仅单色和8位格式。
  • setColorCount(): 调整颜色表的大小。仅单色和8位格式。

创建一个看图应用

参考pyqt5-examples样例文件imageviewer.py, 实现一个简单的看图程序,完整代码如下:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QDir
from PyQt5.QtGui import QImage, QPainter, QPixmap, QPalette
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction,
                             QFileDialog, QMessageBox, QLabel, QScrollArea, QSizePolicy)
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter
 
class ImageViewer(QMainWindow):
    def __init__(self, parent=None):
        super(ImageViewer, self).__init__(parent)   
        
         # 设置窗口标题
        self.setWindowTitle('实战Qt for Python: QImage实现一个看图应用')      
        # 设置窗口大小
        self.resize(500, 400)
      
        self.initUi()
        
    def initUi(self):
        #打印
        self.printer = QPrinter()
        #缩放因子
        self.scaleFactor = 0.0
       
        #创建显示图片的窗口 
        self.imgLabel = QLabel()
        self.imgLabel.setBackgroundRole(QPalette.Base)
        self.imgLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imgLabel.setScaledContents(True)
        
        self.scrollArea = QScrollArea()
        self.scrollArea.setBackgroundRole(QPalette.Dark)
        self.scrollArea.setWidget(self.imgLabel)
        
        self.setCentralWidget(self.scrollArea)
        
        self.initMenuBar()
    
    def initMenuBar(self):
        menuBar = self.menuBar() 
        menuFile = menuBar.addMenu('文件(&F)')
        menuView = menuBar.addMenu('视图(&V)')
        
        actionOpen = QAction('打开(&O)...', self, shortcut='Ctrl+O', triggered=self.onFileOpen)
        self.actionPrint = QAction('打印(&P)...', self, shortcut='Ctrl+P', enabled=False, triggered=self.onFilePrint)  
        actionExit = QAction('退出(&X)', self, shortcut='Ctrl+Q', triggered=QApplication.instance().quit)
        
        self.actionZoomIn = QAction('放大(25%)(&I)', self, shortcut='Ctrl++', enabled=False, triggered=self.onViewZoomIn)
        self.actionZoomOut = QAction('缩小(25%)(&O)', self, shortcut='Ctrl++', enabled=False, triggered=self.onViewZoomOut)
        self.actionNormalSize = QAction('原始尺寸(&N)', self, shortcut='Ctrl+S', enabled=False, triggered=self.onViewNormalSize)
        self.actionFitToWindow = QAction('适应窗口(&F)', self, shortcut='Ctrl+F', enabled=False, checkable=True, triggered=self.onViewFitToWindow)
        
        menuFile.addAction(actionOpen)
        menuFile.addAction(self.actionPrint)
        menuFile.addSeparator()
        menuFile.addAction(actionExit)  
        
        menuView.addAction(self.actionZoomIn)
        menuView.addAction(self.actionZoomOut)
        menuView.addAction(self.actionNormalSize)
        menuView.addSeparator()
        menuView.addAction(self.actionFitToWindow)
    
    #打开文件
    def onFileOpen(self):
        filename,_ = QFileDialog.getOpenFileName(self, '打开文件', QDir.currentPath()) 
        if filename:
            image = QImage(filename)
            if image.isNull():
                QMessageBox.information(self, '图像浏览器', '不能加载文件%s.' % filename)
                return
            
            self.imgLabel.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0
            
            self.actionPrint.setEnabled(True)
            self.actionFitToWindow.setEnabled(True)
            self.updateActions()
            
            if not self.actionFitToWindow.isChecked():
                self.imgLabel.adjustSize()
    
    #打印
    def onFilePrint(self):
        dlg = QPrintDialog(self.printer, self)
        if dlg.exec():
            painter = QPainter(self.printer)
            rect = painter.viewport()
            size = self.imgLabel.pixmap().size()
            size.scale(rect.size(), Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
            painter.setWindow(self.imgLabel.pixmap().rect())
            painter.drawPixmap(0, 0, self.imgLabel.pixmap())
    
    #放大图像
    def onViewZoomIn(self):
        self.scaleIamge(1.25)   
    
    def onViewZoomOut(self):
        self.scaleIamge(0.8)   
    
    def onViewNormalSize(self):
        self.imgLabel.adjustSize()
        self.scaleFactor = 1.0
    
    def onViewFitToWindow(self):
        fitToWindow = self.actionFitToWindow.isChecked()
        self.scrollArea.setWidgetResizable(fitToWindow)
        if not fitToWindow:
            self.onViewNormalSize()
            
        self.updateActions()
    
    def updateActions(self):
        checked = not self.actionFitToWindow.isChecked()
        self.actionZoomIn.setEnabled(checked)
        self.actionZoomOut.setEnabled(checked)
        self.actionNormalSize.setEnabled(checked)
        
    def scaleIamge(self, factor):
        self.scaleFactor *= factor
        self.imgLabel.resize(self.scaleFactor * self.imgLabel.pixmap().size())
        
        self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor)
        self.adjustScrollBar(self.scrollArea.verticalScrollBar(), factor)
        
        self.actionZoomIn.setEnabled(self.scaleFactor < 4.0)
        self.actionZoomOut.setEnabled(self.scaleFactor > 0.25)
        
    def adjustScrollBar(self, scrollBar, factor):
        scrollBar.setValue(int(factor * scrollBar.value() + ((factor - 1) * scrollBar.pageStep()/2)))
        
   
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ImageViewer()
    window.show()
    sys.exit(app.exec())   

运行结果如下图:

本文知识点

  • QImage支持的图像格式
  • 使用QImage进行图像变换
  • 创建一个简单的图像浏览应用

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


请多多关注,评论,收藏,点赞,和转发。

相关推荐

自己可以重装电脑系统么(可以自己重装系统吗)

电脑自身也可以重装系统。1.电脑是一个可编程的设备,通过特定的步骤和操作,用户可以自行进行系统重装。2.重装系统的过程包括备份重要数据、获取系统安装介质、重新启动电脑进入安装界面、按照指引选择系统...

win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
  • win11免费下载(win11正式版下载)
qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
  • qq邮箱在哪里找账号(qq邮箱账号在qq里怎么找)
苹果处理器性能排行(苹果处理器性能排行榜平板)

1、截止至最新的iPhoneXS上搭载的A12,从iPhone4首次搭载A4处理器开始,目前已经有9代的苹果A系列处理器;2、A4是一颗45nm制程的ARMCortex-A8的单核心处理器,GP...

苹果手机怎么录屏(苹果手机怎么录屏在哪里打开)

iPhone手机的屏幕录制功能需要在设置里面进行添加,添加成功之后,就可以使用录屏功能了。点击控制中心进入iPhone手机的设置,来到设置之后,找到控制中心选项并点击。点击加号添加录屏功能来到控制中心...

电脑怎么打开系统还原(电脑怎么开启系统还原的功能)

右键此电脑,属性,系统保护,配置,勾选启用系统保护,确定,创建,输入还原点描述,点击创建,系统提示已成功创建还原点,点击关闭,当需要还原的时候,点击上面的系统还原,选择需要还原的节点,点击完成,即可开...

ghost系统下载xp(非ghostxp下载)

蒲公英系统网站能下载。下载后缀为gho的xp系统,使用体验非常棒效果非常好。以上信息根据美国华盛顿操作系统邮报最新消息显示。不能装钉钉的。在WindowsXP系统上是不能安装钉钉来上网课的。要使用钉...

电脑安全模式怎么用(电脑安全模式怎么按出来)

1.进入运行输入指令确定键盘上按下win+r组合键,打开运行,输入msconfig,点击确定。2.进引导系统选安全引导进入页面后,点击引导,选中系统,勾选安全引导,点击确定。3.重启进入安全模式弹出...

win10可选更新(win10可选更新和必要更新)

首先确保系统是激活状态。如果不是,可以用小马激活或KMS激活软件等工具激活。1.打开开始菜单,选择“设置”,选择“更新和安全”,设置自动检测安装更新,接受win10推送。电脑接受win10推送后...

讯飞语音输入法(讯飞语音输入法电脑版)

手机中讯飞语音输入法操作起来非常的简便。我们可以先打开讯飞语音。输入法在输入法键盘上的上端有一个麦克风的标识,我们只要点开麦克风的标识,就可以说话了,上面就会出现相应的文字了。文字可以自动帮我们识别修...

电脑品牌型号在哪里看(电脑选什么牌子的好)

查看自己电脑品牌型号和具体配置的具体方法:1.右键点击桌面上的“这台电脑”图标,弹出的菜单中选择“属性”。2.在此界面即可看到你的电脑的CPU品牌(AMD)、型号(A6-5200)、频率(2.0GHz...

网卡驱动装不上怎么回事(网卡驱动装不了怎么办)

可能原因如下1、这种情况是因为系统中没有集成电脑网卡所对应的驱动程序。2、这种情况可以利用鲁大师查询网卡的具体型号,然后去官网或者网络上下载对应的驱动重新安装就可以正常上网了。可能原因如下:1,估计是...

手机输入法怎么打繁体字(手机怎样输入繁体)

步骤如下:1.在手机设置页面找到输入法设置,如果能搜索,会帮助找到输入法设置页面。2.在系统的输入法设置页面,找到输入法自身的设置页面入口。3.在输入法自设难度设置页面,找到简繁切换的设置页面。4.勾...

photoshop 下载(photoshop下载需要花钱吗)

怎样下载photoshop的步骤方法如下面所示:1.首先第一步的步骤是在我们的电脑桌面上找到电脑管家并紧接着点击它(如果没有电脑管家需要提前安装)。2.然后一步的方法是点击屏幕右下方的工具箱。3.最后...

联想官方网站驱动下载官网(联想官方网站驱动下载官网安装)

拯救者官网下驱动的方法:打开联想服务官网(support.lenovo.com.cn),页面滚动下拉找到“帮助与支持”板块,点击“驱动和软件下载”。下载联想拯救者的驱动很简单。简单联想官网提供详细的驱...