Qt/PyQt(/其他?):如何更改像素图中的特定颜色?

发布于 2024-12-22 23:08:56 字数 134 浏览 1 评论 0原文

如何更改像素图中的特定颜色?例如,我有一个包含白色和黑色像素的像素图,我想将所有白色像素更改为蓝色,但保留黑色像素。或者也许将黑色更改为白色,将白色更改为蓝色...[我正在 Qt/PyQt 中寻找解决方案,但也许这是关于如何处理/组合像素图的一般问题。]

How do I change specific colors in a pixmap? For example, I have a pixmap with white and black pixels, and I want to change all white pixels to blue, but leave the black ones alone. Or maybe change the black to white and the white to blue... [I am searching for a solution in Qt/PyQt, but maybe this is a general question as to how pixmaps are handled/composed.]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薄荷→糖丶微凉 2024-12-29 23:08:56

您可以使用createMaskFromColor为白色像素创建位图,然后使用drawPixmap用另一种颜色覆盖它们。

    pix = QPixmap("test.png")
    mask = pix.createMaskFromColor(QColor(255, 255, 255), Qt.MaskOutColor)

    p = QPainter(pix)
    p.setPen(QColor(0, 0, 255))
    p.drawPixmap(pix.rect(), mask, mask.rect())
    p.end()

请注意,createMaskFromColor 会将像素图转换为 QImage,因此如果可能的话,您应该尝试直接使用 QImage

You can use createMaskFromColor to create a bitmap for the white pixels, then use drawPixmap to overwrite them with another color.

    pix = QPixmap("test.png")
    mask = pix.createMaskFromColor(QColor(255, 255, 255), Qt.MaskOutColor)

    p = QPainter(pix)
    p.setPen(QColor(0, 0, 255))
    p.drawPixmap(pix.rect(), mask, mask.rect())
    p.end()

Note that createMaskFromColor is going to convert the pixmap to a QImage, so you should try to use a QImage directly, if possible.

千年*琉璃梦 2024-12-29 23:08:56

有几个人问如何在不使用掩码的情况下完成位级操作(改变颜色)。为此,我们需要知道如何直接读取和设置像素。 QImage 就是为此类像素级操作而设计的,而标签和其他 QWidget 则需要 QPixmap。因此,我们还必须知道如何在 QPixmap 和 QImage 之间进行转换。

这是一个 PyQt6 示例(在 Windows 机器上用 Python 编写),它从头开始创建 QImage,使用 QPainter 绘制一些彩色圆圈,在屏幕上显示“之前”图像,然后检查每个像素,记录每个红色像素的计数,并将每个红色像素更改为白色,同时忽略所有其他颜色。我知道这段代码很丑陋。我按原样提供它是因为没有其他人提出一个例子来回答最初的问题。请将此代码视为启动您更深入研究的地方,并原谅其中的缺点。 -科学_1

import sys
from PyQt6.QtWidgets import QMainWindow, QApplication, QLabel
from PyQt6.QtCore import QSize,QPoint,QRect
from PyQt6.QtGui import QPainter, QPixmap, QPen, QColor, QImage
from random import choice, randint
from time import sleep

class myWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        COLORS = [QColor('red').rgb(),QColor('blue').rgb(),QColor('black').rgb(),QColor('green').rgb(),QColor('red')]

        img_1 = QPixmap(QSize(300,300)).toImage() # Create a 300x300 QPixmap image from scratch and convert it to a QImage.

        self.label = QLabel() # Declare a Qself.label for our widget.       
        self.label.resize(img_1.size())
        self.setCentralWidget(self.label)

        # Create our example image from scratch. A Green square with black outline, and a red diagonal line across it.
        img_1.fill(QColor('lightgreen')) # Fill the QImage with light-green.

        # Declare some colors that we will use with our QPens.
        targetColor = QColor('red') # We could use penColor = QColor(rgb(255,0,0,255)) here.

        # Draw a diagonal line across the QImage using QPainter
        artist = QPainter(img_1) # Higher an artist.

        for cnt in range(0,60): 
            artist.setPen(QPen(choice(COLORS),3)) # Have computer choose a color at random from our COLORS list.
            x = randint(0,300)
            y = randint(0,300)
            r = randint(15,40)
            artist.drawEllipse(x,y,r,r) # For a circle type ellipse, the length and width must be the same.
        artist.end() # Dismiss the artist.

        # You don't actually need QPainter to draw on a QImage, but without it, you must code everything it does yourself.
        # Also, setPixel() can't handle attempts to set pixels that are off screen, like QPainter can,
        # So you must be careful to stay in bounds.
        # Here is an example of setting pixels without using QPainter.
        diagonal_Color = QColor("brown").rgba()
        for a in range(0,298):
            img_1.setPixelColor(a,a,diagonal_Color) # The setPixel() or setPixelColor() commands can 
            img_1.setPixel(a+1,a,diagonal_Color)    # be used to set a pixel in an image.   
            img_1.setPixel(a+2,a,diagonal_Color)    # What's the difference? Beats me. If one gives you fits, try the other.    

        self.label.setPixmap(QPixmap.fromImage(img_1))
        self.show()

        # Here we tease the viewer, then suspend the program for three seconds so the 'before' image can be studied.
        print(' Wait for it...') # Tease
        sleep(3) # <-- A quick & dirty pause. For real code, use a one-off signal emitter, or a user-driven event. 

        # In this section, we progress incrementally through all of the pixels, checking the colors.
        # Any red pixels are over-written with white. This is a slow process. For speed, use a mask with QPainter.
        # But pixel-level manipulation has its place, if speed is not a criteria.

        rcount = 0
        x = self.label.size().width()  
        y = self.label.size().height() 

        for row in range(0,y):
            for column in range(0,x):
                pixel_color = img_1.pixelColor(QPoint(column,row)) # Read the pixel color from the QImage.
                if pixel_color == targetColor: # If the pixel is red..
                    rcount += 1 # Incriment the pixel count.
                    img_1.setPixel(column,row,QColor("white").rgb())    # Change the red pixel to white.

                    '''     
                    # If you want to examine the rgb colors individually, you can use .red(), .green(), .blue(), and .alpha()
                    r = pixel_color.red()
                    g = pixel_color.green()
                    b = pixel_color.blue()
                    a = pixel_color.alpha()                 
                    print('pixel_color RGBA = ('+str(r)+', '+str(g)+', '+str(b)+', '+str(a)+')')
                    ''' 

        self.label.setPixmap(QPixmap.fromImage(img_1))  # Convert the Image to a QPixmap, and put it on the label.
        print('\n Finished.')
        print(" All red pixels have been changed to white.")
        print(" Total number of pixels changed:",rcount)
        print("\n Close Window to Quit")            

        self.setCentralWidget(self.label) # A label, being a widget, and can be directly assigned to a QWindow.
        self.show()                       # But if you need several widgets on the screen, use one of the layouts and assign that.

app = QApplication(sys.argv)
window = myWindow()
window.show()
app.exec()

A couple of people have asked how bit-level manipulation (changing colors) can be done without using a mask. For this, we need to know how to read and set pixels directly. QImage is designed for just such pixel-level manipulation, while QPixmaps are needed for labels and other QWidgets. So we also must know how to convert from QPixmaps to QImages and back again.

Here is a PyQt6 example (written in Python on a Windows machine) that creates a QImage from scratch, uses QPainter to draw some colored circles, shows the 'before' image on the screen, then examines each pixel, keeping count of each red pixel, and changes each red pixel to white while ignoring all other colors. I know this code is ugly. I offer it as-is because no one else has come forward with an example that answers the original question. Please consider this code a place to launch your deeper studies, and forgive the warts. -Science_1

import sys
from PyQt6.QtWidgets import QMainWindow, QApplication, QLabel
from PyQt6.QtCore import QSize,QPoint,QRect
from PyQt6.QtGui import QPainter, QPixmap, QPen, QColor, QImage
from random import choice, randint
from time import sleep

class myWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        COLORS = [QColor('red').rgb(),QColor('blue').rgb(),QColor('black').rgb(),QColor('green').rgb(),QColor('red')]

        img_1 = QPixmap(QSize(300,300)).toImage() # Create a 300x300 QPixmap image from scratch and convert it to a QImage.

        self.label = QLabel() # Declare a Qself.label for our widget.       
        self.label.resize(img_1.size())
        self.setCentralWidget(self.label)

        # Create our example image from scratch. A Green square with black outline, and a red diagonal line across it.
        img_1.fill(QColor('lightgreen')) # Fill the QImage with light-green.

        # Declare some colors that we will use with our QPens.
        targetColor = QColor('red') # We could use penColor = QColor(rgb(255,0,0,255)) here.

        # Draw a diagonal line across the QImage using QPainter
        artist = QPainter(img_1) # Higher an artist.

        for cnt in range(0,60): 
            artist.setPen(QPen(choice(COLORS),3)) # Have computer choose a color at random from our COLORS list.
            x = randint(0,300)
            y = randint(0,300)
            r = randint(15,40)
            artist.drawEllipse(x,y,r,r) # For a circle type ellipse, the length and width must be the same.
        artist.end() # Dismiss the artist.

        # You don't actually need QPainter to draw on a QImage, but without it, you must code everything it does yourself.
        # Also, setPixel() can't handle attempts to set pixels that are off screen, like QPainter can,
        # So you must be careful to stay in bounds.
        # Here is an example of setting pixels without using QPainter.
        diagonal_Color = QColor("brown").rgba()
        for a in range(0,298):
            img_1.setPixelColor(a,a,diagonal_Color) # The setPixel() or setPixelColor() commands can 
            img_1.setPixel(a+1,a,diagonal_Color)    # be used to set a pixel in an image.   
            img_1.setPixel(a+2,a,diagonal_Color)    # What's the difference? Beats me. If one gives you fits, try the other.    

        self.label.setPixmap(QPixmap.fromImage(img_1))
        self.show()

        # Here we tease the viewer, then suspend the program for three seconds so the 'before' image can be studied.
        print(' Wait for it...') # Tease
        sleep(3) # <-- A quick & dirty pause. For real code, use a one-off signal emitter, or a user-driven event. 

        # In this section, we progress incrementally through all of the pixels, checking the colors.
        # Any red pixels are over-written with white. This is a slow process. For speed, use a mask with QPainter.
        # But pixel-level manipulation has its place, if speed is not a criteria.

        rcount = 0
        x = self.label.size().width()  
        y = self.label.size().height() 

        for row in range(0,y):
            for column in range(0,x):
                pixel_color = img_1.pixelColor(QPoint(column,row)) # Read the pixel color from the QImage.
                if pixel_color == targetColor: # If the pixel is red..
                    rcount += 1 # Incriment the pixel count.
                    img_1.setPixel(column,row,QColor("white").rgb())    # Change the red pixel to white.

                    '''     
                    # If you want to examine the rgb colors individually, you can use .red(), .green(), .blue(), and .alpha()
                    r = pixel_color.red()
                    g = pixel_color.green()
                    b = pixel_color.blue()
                    a = pixel_color.alpha()                 
                    print('pixel_color RGBA = ('+str(r)+', '+str(g)+', '+str(b)+', '+str(a)+')')
                    ''' 

        self.label.setPixmap(QPixmap.fromImage(img_1))  # Convert the Image to a QPixmap, and put it on the label.
        print('\n Finished.')
        print(" All red pixels have been changed to white.")
        print(" Total number of pixels changed:",rcount)
        print("\n Close Window to Quit")            

        self.setCentralWidget(self.label) # A label, being a widget, and can be directly assigned to a QWindow.
        self.show()                       # But if you need several widgets on the screen, use one of the layouts and assign that.

app = QApplication(sys.argv)
window = myWindow()
window.show()
app.exec()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文