Last Updated on 2020-11-30 by Clay
Introduction
Recently, because I have been studying the interface of the program, I got many strange problems.
I want to record today is how to merge two pictures. I found that if I simply use the composite()
function in PIL, the second picture will be overwritten by the first picture. So, I started to try convert the background of the second picture to transparent.
After converting the image to a transparent background, the result of the merging is quite natural to me.
I will start to introduce how to merge two pictures in below.
Preparation
If you use pillow in the first time, you need to use the following command:
pip3 install pillow
Merge pictures
I have a dog picture to be example.
And then I have a canvas program. (You can use any QLabel to replace it.)
I saved the code as PaintLabel.py to rewrite the QLabel program in PyQt5.
# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class PLabel(QLabel):
def __init__(self, centralwidget):
super(PLabel, self).__init__(centralwidget)
self.tracing_xy = []
self.lineHistory = []
self.pen = QPen(Qt.black, 10, Qt.SolidLine)
def paintEvent(self, QPaintEvent):
self.painter = QPainter()
self.painter.begin(self)
self.painter.setPen(self.pen)
start_x_temp = 0
start_y_temp = 0
if self.lineHistory:
for line_n in range(len(self.lineHistory)):
for point_n in range(1, len(self.lineHistory[line_n])):
start_x, start_y = self.lineHistory[line_n][point_n-1][0], self.lineHistory[line_n][point_n-1][1]
end_x, end_y = self.lineHistory[line_n][point_n][0], self.lineHistory[line_n][point_n][1]
self.painter.drawLine(start_x, start_y, end_x, end_y)
for x, y in self.tracing_xy:
if start_x_temp == 0 and start_y_temp == 0:
self.painter.drawLine(self.start_xy[0][0], self.start_xy[0][1], x, y)
else:
self.painter.drawLine(start_x_temp, start_y_temp, x, y)
start_x_temp = x
start_y_temp = y
self.painter.end()
def mousePressEvent(self, QMouseEvent):
self.start_xy = [(QMouseEvent.pos().x(), QMouseEvent.pos().y())]
def mouseMoveEvent(self, QMouseEvent):
self.tracing_xy.append((QMouseEvent.pos().x(), QMouseEvent.pos().y()))
self.update()
def mouseReleaseEvent(self, QMouseEvent):
self.lineHistory.append(self.start_xy+self.tracing_xy)
self.tracing_xy = []
Then I stacked the two pictures together (the drawing board above):
I can paint whatever I want.
Then, we write a program to store the two pictures, the code is not long, plus the program that rewrites QLabel just now is only about 100 lines.
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from label_test import Ui_MainWindow
from PIL import ImageQt, Image
from PaintLabel import PLabel
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.statusbar.setVisible(False)
self.paintBoard = PLabel(self.ui.centralwidget)
self.paintBoard.setGeometry(QRect(self.ui.label.pos(), self.ui.label.size()))
self.add = QShortcut(QKeySequence("Ctrl+S"), self)
self.add.activated.connect(self.compositeEvent)
def compositeEvent(self):
image1 = ImageQt.fromqpixmap(self.ui.label.pixmap())
image2 = ImageQt.fromqimage(self.paintBoard.grab())
image1 = image1.convert('RGBA')
image2 = image2.resize(image1.size)
# Transparency
newImage2 = []
for item in image2.getdata():
if item[:3] == (240, 240, 240):
newImage2.append((240, 240, 240, 0))
else:
newImage2.append(item)
image2.putdata(newImage2)
print(image1.mode, image1.size)
print(image2.mode, image2.size)
newImage = Image.alpha_composite(image1, image2)
newImage.save('test.png')
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
sys.exit(app.exec_())
The most important thing is actually this line:
newImage = Image.alpha_composite(image1, image2)
Use the alpha_composite()
function to merge my two pictures together. The saved file is the picture of the dog pirate at the top of me.