<!DOCTYPE html>
    <html lang="vi" xmlns="http://www.w3.org/1999/xhtml" prefix="og: http://ogp.me/ns#">
    <head>
<title>Cách tạo ảnh ghép bằng Python</title>
<meta name="description" content="Cách tạo ảnh ghép bằng Python - Savefile - Tin Tức - https&#x3A;&#x002F;&#x002F;www.nguoicodonvn2008.info&#x002F;vi&#x002F;news&#x002F;savefile&#x002F;kien-thuc-may-tinh&#x002F;cach-tao-anh-ghep-bang-python-7506.html">
<meta name="author" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :.">
<meta name="copyright" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :. [admin@nguoicodonvn2008.info]">
<meta name="robots" content="index, archive, follow, noodp">
<meta name="googlebot" content="index,archive,follow,noodp">
<meta name="msnbot" content="all,index,follow">
<meta name="generator" content="NukeViet v4.5">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta property="og:title" content="Cách tạo ảnh ghép bằng Python">
<meta property="og:type" content="website">
<meta property="og:description" content="Savefile - Tin Tức - https&#x3A;&#x002F;&#x002F;www.nguoicodonvn2008.info&#x002F;vi&#x002F;news&#x002F;savefile&#x002F;kien-thuc-may-tinh&#x002F;cach-tao-anh-ghep-bang-python-7506.html">
<meta property="og:site_name" content=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.">
<meta property="og:url" content="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-tao-anh-ghep-bang-python-7506.html">
<link rel="shortcut icon" href="https://nguoicodonvn2008.info/favicon.ico">
<link rel="canonical" href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-tao-anh-ghep-bang-python-7506.html">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/" title="Tin Tức" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/karaoke-dual/" title="Tin Tức - Karaoke Dual" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/nhac-tre/" title="Tin Tức - Nhạc trẻ" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tru-tinh/" title="Tin Tức - Trữ tình" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/nuoc-ngoai/" title="Tin Tức - Nước ngoài" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/remix/" title="Tin Tức - Remix" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tam-su-tinh-yeu/" title="Tin Tức - Tâm sự tình yêu" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tho-suu-tam/" title="Tin Tức - Thơ sưu tầm" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/cuoc-song/" title="Tin Tức - Cuộc sống" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/phan-mem/" title="Tin Tức - Phần mềm" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/kien-thuc-may-tinh/" title="Tin Tức - Kiến thức máy tính" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/hoc-tap/" title="Tin Tức - Học tập" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tai-lieu/" title="Tin Tức - Tài liệu" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/de-thi/" title="Tin Tức - Đề thi" type="application/rss+xml">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/assets/css/font-awesome.min.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/style.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/style.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/news.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/custom.css" type="text/css">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/jquery/jquery.min.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/language/vi.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/global.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/site.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/news.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/main.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/custom.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/bootstrap.min.js" type="text/javascript">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/assets/css/font-awesome.min.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/style.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/style.non-responsive.css">
<link rel="StyleSheet" href="https://nguoicodonvn2008.info/themes/default/css/news.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/custom.css">
<style type="text/css">
	body{background: #fff;}
</style>
    </head>
    <body>
<div id="print">
	<div id="hd_print">
		<h2 class="pull-left">.&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.</h2>
		<p class="pull-right"><a title=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;." href="https://nguoicodonvn2008.info/">https://nguoicodonvn2008.info</a></p>
	</div>
	<div class="clear"></div>
	<hr />
	<div id="content">
		<h1>Cách tạo ảnh ghép bằng Python</h1>
		<ul class="list-inline">
			<li>Thứ sáu - 08/09/2023 10:31</li>
			<li class="hidden-print txtrequired"><em class="fa fa-print">&nbsp;</em><a title="In ra" href="javascript:;" onclick="window.print()">In ra</a></li>
			<li class="hidden-print txtrequired"><em class="fa fa-power-off">&nbsp;</em><a title="Đóng cửa sổ này" href="javascript:;" onclick="window.close()">Đóng cửa sổ này</a></li>
		</ul>
		<div class="clear"></div>
		<div id="hometext">
		</div>
				<div class="imghome">
			<img alt="Cách tạo ảnh ghép bằng Python" src="https://st.quantrimang.com/photos/image/2023/09/08/Python-ghep-anh-7.jpg" width="460" class="img-thumbnail" />
		</div>
		<div class="clear"></div>
		<div id="bodytext" class="clearfix">
			<p style="text-align: justify;">Ảnh ghép là cách tuyệt vời để lưu giữ kỷ niệm theo một nhóm ảnh liên quan. Tuy nhiên, những app ghép ảnh online thường có tiềm ẩn rủi ro bảo mật, còn ứng dụng offline thì lại tốn tiền và thiếu tính năng bạn cần.</p>

<p style="text-align: justify;"><img alt="Tạo app ghép ảnh" data-i="0" data-src="https://st.quantrimang.com/photos/image/2023/09/08/Python-ghep-anh-7.jpg" data-was-processed="true" height="340" src="https://st.quantrimang.com/photos/image/2023/09/08/Python-ghep-anh-7.jpg" width="650" /></p>

<p style="text-align: justify;">Bằng cách tự tay xây dựng công cụ ghép ảnh, bạn không cần phải quan tâm tới những điều đó. Sau đây là<strong>&nbsp;cách tạo app ghép ảnh bằng Python</strong>.</p>

<h2 style="text-align: justify;">Mô đun Tkinter và PIL</h2>

<p style="text-align: justify;">Để xây dựng ứng dụng ghép ảnh bạn cần tới mô đun Tkinter và PIL. Tkinter cho phép bạn tạo ứng dụng desktop. Nó cung cấp một loạt widget khiến việc phát triển GUI dễ dàng hơn.</p>

<p style="text-align: justify;">Thư viện Pillow - một nhánh của Python Imaging Library (PIL) - cung cấp các tính năng xử lý ảnh, giúp chỉnh sửa, tạo, chuyển đổi định dạng file và lưu ảnh.</p>

<p style="text-align: justify;">Để cài đặt Tkinter và Pillow, mở terminal và chạy:</p>

<pre id="pre0" style="text-align: justify;">
pip install tk pillow</pre>

<h2 style="text-align: justify;">Thiết lập GUI và chỉnh sửa ảnh</h2>

<p style="text-align: justify;">Bắt đầu bằng cách nhập các mô đun được yêu cầu. Tạo class,<strong>&nbsp;ImageCollageApp</strong>&nbsp;và đặt tên cùng kích thước của cửa sổ. Xác định một canvas bằng<strong>&nbsp;tk.Canvas()</strong>, rồi đặt phần tử cha, chiều rộng, cao và màu background.</p>

<pre id="pre1" style="text-align: justify;">
import tkinter as tk
from tkinter import filedialog, simpledialog, messagebox
from PIL import Image, ImageTk

class ImageCollageApp:
    def __init__(self, root):
        self.root = root
        self.root.title(&quot;Image Collage Maker&quot;)
        self.images = &#91;&#93;
        self.image_refs = &#91;&#93;
        self.collage_size = (600, 500)

        self.collage_canvas = tk.Canvas(
            self.root,
            width=self.collage_size&#91;0&#93;,
            height=self.collage_size&#91;1&#93;,
            bg=&quot;white&quot;,
        )

        self.collage_canvas.pack()</pre>

<p style="text-align: justify;">Tạo hai nút bấm:&nbsp;<strong>Add Image</strong>&nbsp;và&nbsp;<strong>Create Collage</strong>. Xác định phần tử cha, nội dung hiển thị, lệnh để chạy và kiểu font. Sắp xếp các nút bấm bằng cách thêm padding phù hợp. Khởi tạo&nbsp;<strong>drag_data</strong>&nbsp;để lưu thông tin về thao tác kéo.</p>

<p style="text-align: justify;">Khởi tạo&nbsp;<strong>image_positions</strong>&nbsp;để lưu vị trí của ảnh trên canvas. Xác định 3 trình xử lý sự kiện để phản hồi với lựa chọn, kéo và thả hình.</p>

<pre id="pre2" style="text-align: justify;">
        self.btn_add_image = tk.Button(
            self.root,
            text=&quot;Add Image&quot;,
            command=self.add_images,
            font=(&quot;Arial&quot;, 12, &quot;bold&quot;),
        )

        self.btn_add_image.pack(pady=10)

        self.btn_create_collage = tk.Button(
            self.root,
            text=&quot;Create Collage&quot;,
            command=self.create_collage,
            font=(&quot;Arial&quot;, 12, &quot;bold&quot;),
        )

        self.btn_create_collage.pack(pady=5)
        self.drag_data = {&quot;x&quot;: 0, &quot;y&quot;: 0, &quot;item&quot;: None}
        self.image_positions = &#91;&#93;
        self.collage_canvas.bind(&quot;&lt;ButtonPress-1&gt;&quot;, self.on_press)
        self.collage_canvas.bind(&quot;&lt;B1-Motion&gt;&quot;, self.on_drag)
        self.collage_canvas.bind(&quot;&lt;ButtonRelease-1&gt;&quot;, self.on_release)</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>on_press</strong>. Truy xuất mục canvas gần nhất từ vị trí người dùng click chuột và lưu nó dưới khóa item của từ điển&nbsp;<strong>drag_data</strong>. Lưu trữ tọa độ<strong>&nbsp;x</strong>&nbsp;và&nbsp;<strong>y</strong>&nbsp;của click chuột. Bạn sẽ dùng nó để tính khoảng cách người dùng di chuyển chuột trong khi kéo.</p>

<pre id="pre3" style="text-align: justify;">
    def on_press(self, event):
        self.drag_data&#91;&quot;item&quot;&#93; = self.collage_canvas.find_closest(event.x, event.y)&#91;0&#93;
        self.drag_data&#91;&quot;x&quot;&#93; = event.x
        self.drag_data&#91;&quot;y&quot;&#93; = event.y</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>on_drag</strong>. Tính khoảng cách theo chiều ngang và dọc mà người dùng đã di chuột trong khi kéo và&nbsp;<strong>update&nbsp;</strong>vị trí hình ảnh phù hợp. Lưu tọa độ ảnh đã update bằng các khóa&nbsp;<strong>x&nbsp;</strong>và&nbsp;<strong>y</strong>&nbsp;của từ điển&nbsp;<strong>drag_data</strong>.</p>

<pre id="pre4" style="text-align: justify;">
    def on_drag(self, event):
        delta_x = event.x - self.drag_data&#91;&quot;x&quot;&#93;
        delta_y = event.y - self.drag_data&#91;&quot;y&quot;&#93;
        self.collage_canvas.move(self.drag_data&#91;&quot;item&quot;&#93;, delta_x, delta_y)
        self.drag_data&#91;&quot;x&quot;&#93; = event.x
        self.drag_data&#91;&quot;y&quot;&#93; = event.y</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>on_release</strong>. Xóa tham chiếu tới ảnh mà người dùng đang kéo cùng với tọa độ của nó. Gọi&nbsp;<strong>update_image_positions</strong>&nbsp;để cập nhật vị trí của mọi hình trên canvas sau khi người dùng kéo và thả nó.</p>

<pre id="pre5" style="text-align: justify;">
    def on_release(self, event):
        self.drag_data&#91;&quot;item&quot;&#93; = None
        self.drag_data&#91;&quot;x&quot;&#93; = 0
        self.drag_data&#91;&quot;y&quot;&#93; = 0
        self.update_image_positions()</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>update_image_positions</strong>. Xóa danh sách<strong>&nbsp;image_positions</strong>&nbsp;và lặp nó trên toàn bộ các mục canvas. Đối với mỗi mục, tìm tọa độ và thêm chúng vào danh sách.</p>

<pre id="pre6" style="text-align: justify;">
    def update_image_positions(self):
        self.image_positions.clear()

        for item in self.collage_canvas.find_all():
            x, y = self.collage_canvas.coords(item)
            self.image_positions.append((x, y))</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>add_images</strong>. Tạo hộp thoại nhắc người dùng nhập số ảnh muốn ghép. Nếu người dùng đã cung cấp một số hợp lệ, mở một hộp thoại file, chỉ cho phép người dùng chọn file ảnh. Sau khi người dùng đã chọn một hoặc nhiều ảnh hơn, mở từng ảnh bằng phương thức&nbsp;<strong>Image.open()&nbsp;</strong>của Pillow.</p>

<p style="text-align: justify;">Gọi&nbsp;<strong>resize_image</strong>&nbsp;và tạo&nbsp;<strong>PhotoImage</strong>&nbsp;tương thích<strong>&nbsp;Tkinter</strong>. Thêm nó vào danh sách&nbsp;<strong>image_refs</strong>&nbsp;và gọi<strong>&nbsp;update_canvas</strong>.</p>

<pre id="pre7" style="text-align: justify;">
    def add_images(self):
        num_images = simpledialog.askinteger(
            &quot;Number of Images&quot;, &quot;Enter the number of images:&quot;
        )

        if num_images is not None:
            file_paths = filedialog.askopenfilenames(
                filetypes=&#91;(&quot;Image files&quot;, &quot;*.png;*.jpg;*.jpeg;*.gif&quot;)&#93;
            )

            if file_paths:
                for i in range(min(num_images, len(file_paths))):
                    file_path = file_paths&#91;i&#93;
                    image = Image.open(file_path)
                    resized_image = self.resize_image(image)
                    self.images.append(resized_image)
                    self.image_refs.append(ImageTk.PhotoImage(resized_image))

                self.update_canvas()</pre>

<p style="text-align: justify;">Xác định phương thức,<strong>&nbsp;resize_image</strong>. Lấy chiều rộng và cao của ảnh và tính tỷ lệ khía cạnh của nó. Nếu nhiều hơn một, đặt chiều rộng mới bằng một nửa chiều rộng của ảnh ghép. Tính chiều cao mới tương ứng trong khi vẫn duy trì tỷ lệ khung hình.</p>

<p style="text-align: justify;">Nếu tỷ lệ cạnh nhỏ hơn 1, đặt chiều cao mới bằng nửa của ảnh ghép. Tương tự, tính chiều rộng tương ứng. Dùng phương thức<strong>&nbsp;resize&nbsp;</strong>của&nbsp;<strong>Pillow</strong>&nbsp;để trả về ảnh đã được chỉnh lại kích thước bằng các tham số đã được tính.</p>

<pre id="pre8" style="text-align: justify;">
    def resize_image(self, image):
        img_width, img_height = image.size
        aspect_ratio = img_width / img_height

        if aspect_ratio &gt; 1:
            new_width = self.collage_size&#91;0&#93; // 2
            new_height = int(new_width / aspect_ratio)
        else:
            new_height = self.collage_size&#91;1&#93; // 2
            new_width = int(new_height * aspect_ratio)

        return image.resize((new_width, new_height))</pre>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>update_canvas</strong>. Xóa toàn bộ mục và hỏi người dùng số hàng và cột mong muốn qua hộp thoại file. Đặt chiều rộng và cao bằng 1/2 kích thước ảnh ghép được chỉ định. Xóa danh sách các vị trí ảnh. Đặt offset&nbsp;<strong>x</strong>&nbsp;và&nbsp;<strong>y</strong>&nbsp;sang 0, nhờ đó, bạn có thể liên tục theo dõi các&nbsp;<strong>offset</strong>&nbsp;vị trí để sắp xếp ảnh theo hàng và cột.</p>

<pre id="pre9" style="text-align: justify;">
    def update_canvas(self):
        self.collage_canvas.delete(&quot;all&quot;)
        rows = simpledialog.askinteger(&quot;Number of Rows&quot;, &quot;Enter the number of rows:&quot;)

        cols = simpledialog.askinteger(
            &quot;Number of Columns&quot;, &quot;Enter the number of columns:&quot;
        )

        collage_width = self.collage_size&#91;0&#93; * cols // 2
        collage_height = self.collage_size&#91;1&#93; * rows // 2
        self.collage_canvas.config(width=collage_width, height=collage_height)
        self.image_positions.clear()
        x_offset, y_offset = 0, 0</pre>

<p style="text-align: justify;">Lặp trên danh sách&nbsp;<strong>image_refs&nbsp;</strong>và tạo ảnh trên canvas bằng offset cụ thể. Đặt anchor sang Northwest để bạn định vị góc trên bên trái ở tọa độ cụ thể. Nối các tọa độ vào danh sách&nbsp;<strong>image_positions</strong>.</p>

<p style="text-align: justify;">Update&nbsp;<strong>x_offset&nbsp;</strong>để thêm một nửa chiều rộng của ảnh ghép, để chuẩn bị đặt ảnh tiếp theo. Nếu số ảnh được đặt trong hàng hiện tại là bội số của số cột cụ thể, đặt<strong>&nbsp;x_offset</strong>&nbsp;sang<strong>&nbsp;0</strong>. Điều này chỉ điểm bắt đầu của một hàng mới. Thêm một nửa chiều cao của ảnh ghép để đặt tọa độ y cho hàng tiếp theo.</p>

<pre id="pre10" style="text-align: justify;">
        for i, image_ref in enumerate(self.image_refs):
            self.collage_canvas.create_image(
                x_offset, y_offset, anchor=tk.NW, image=image_ref
            )

            self.image_positions.append((x_offset, y_offset))
            x_offset += self.collage_size&#91;0&#93; // 2

            if (i + 1) % cols == 0:
                x_offset = 0
                y_offset += self.collage_size&#91;1&#93; // 2</pre>

<h2 style="text-align: justify;">Tạo ảnh ghép và lưu nó</h2>

<p style="text-align: justify;">Xác định một phương thức,&nbsp;<strong>create_collage</strong>. Nếu chưa có ảnh trên ảnh ghép, hiện một cảnh báo. Thu thập chiều rộng và cao của ảnh ghép. Tạo một Image Pillow bằng background màu trắng. Lặp qua danh sách images và dán từng ảnh vào background ở vị trí được xác định.</p>

<p style="text-align: justify;">Lưu ảnh ghép và hiện nó bằng trình xem ảnh mặc định.</p>

<pre id="pre11" style="text-align: justify;">
    def create_collage(self):
        if len(self.images) == 0:
            messagebox.showwarning(&quot;Warning&quot;, &quot;Please add images first!&quot;)
            return

        collage_width = self.collage_canvas.winfo_width()
        collage_height = self.collage_canvas.winfo_height()
        background = Image.new(&quot;RGB&quot;, (collage_width, collage_height), &quot;white&quot;)

        for idx, image in enumerate(self.images):
            x_offset, y_offset = self.image_positions&#91;idx&#93;
            x_offset, y_offset = int(x_offset), int(y_offset)

            paste_box = (
                x_offset,
                y_offset,
                x_offset + image.width,
                y_offset + image.height,
            )

            background.paste(image, paste_box)

        background.save(&quot;collage_with_white_background.jpg&quot;)
        background.show()</pre>

<p style="text-align: justify;">Tạo một phiên bản của Tkinter và class&nbsp;<strong>ImageCollageApp</strong>. Hàm&nbsp;<strong>mainloop()&nbsp;</strong>cho Python biết cần chạy lặp sự kiện Tkinter và lắng nghe các sự kiện cho tới khi bạn đóng cửa sổ này.</p>

<pre id="pre12" style="text-align: justify;">
if __name__ == &quot;__main__&quot;:
    root = tk.Tk()
    app = ImageCollageApp(root)
    root.mainloop()</pre>

<h2 style="text-align: justify;">Kiểm thử các tính năng khác nhau của app ghép ảnh</h2>

<p style="text-align: justify;">Khi chạy chương trình này, một cửa sổ sẽ hiện với hai nút bấm,&nbsp;<strong>Add Image&nbsp;</strong>và&nbsp;<strong>Create Collage</strong>. Khi click nút&nbsp;<strong>Add Image</strong>, một hộp thoại sẽ hiện hỏi số ảnh cần ghép. Khi nhập số ảnh là 5 và chọn chúng, hộp thoại khác sẽ hiện ra. Nó hỏi số hàng và theo sau là số cột.</p>

<p style="text-align: justify;"><img alt="Thêm ảnh " data-i="1" data-src="https://st.quantrimang.com/photos/image/2023/09/08/python-them-anh.jpg" data-was-processed="true" height="785" src="https://st.quantrimang.com/photos/image/2023/09/08/python-them-anh.jpg" width="650" /></p>

<p style="text-align: justify;">Khi nhập hai hàng và 3 cột, cửa sổ này sắp xếp ảnh theo cấu trúc lưới.</p>

<p style="text-align: justify;"><img alt="App ghép ảnh bằng Python" data-i="2" data-src="https://st.quantrimang.com/photos/image/2023/09/08/python-app-ghep-anh.jpg" data-was-processed="true" height="525" src="https://st.quantrimang.com/photos/image/2023/09/08/python-app-ghep-anh.jpg" width="650" /></p>

<p style="text-align: justify;">Cửa sổ xem trước cho tính năng kéo ảnh như ý muốn. Khi click nút&nbsp;<strong>Create Collage</strong>, chương trình này sẽ lưu ảnh.</p>

<p style="text-align: justify;">Khi xem ảnh này, bạn có thể xác nhận chương trình đã ghép ảnh thành công.</p>

<p style="text-align: justify;"><img alt="Ghép ảnh bằng Python" data-i="3" data-src="https://st.quantrimang.com/photos/image/2023/09/08/ghep-anh-python.jpg" data-was-processed="true" height="348" src="https://st.quantrimang.com/photos/image/2023/09/08/ghep-anh-python.jpg" width="650" /></p>

<p style="text-align: justify;">Trên đây là<strong>&nbsp;cách tạo app ghép ảnh bằng&nbsp;Python</strong>. Hi vọng bài viết hữu ích với các bạn.</p>
		</div>
				<div id="author">
						<p>
				<strong>Nguồn tin:</strong>
				Quantrimang.com
			</p>
		</div>
	</div>
	<div id="footer" class="clearfix">
		<div id="url">
			<strong>URL của bản tin này: </strong><a href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-tao-anh-ghep-bang-python-7506.html" title="Cách tạo ảnh ghép bằng Python">https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-tao-anh-ghep-bang-python-7506.html</a>

		</div>
		<div class="clear"></div>
		<div class="copyright">
			&copy; .&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.
		</div>
		<div id="contact">
			<a href="mailto:admin@nguoicodonvn2008.info">admin@nguoicodonvn2008.info</a>
		</div>
	</div>
</div>
        <div id="timeoutsess" class="chromeframe">
            Bạn đã không sử dụng Site, <a onclick="timeoutsesscancel();" href="https://nguoicodonvn2008.info/#">Bấm vào đây để duy trì trạng thái đăng nhập</a>. Thời gian chờ: <span id="secField"> 60 </span> giây
        </div>
        <div id="openidResult" class="nv-alert" style="display:none"></div>
        <div id="openidBt" data-result="" data-redirect=""></div>
		</script>
		<div class="car-top">
  <span><img src="https://nguoicodonvn2008.info/themes/default/images/car.png" alt=""></span>
</div>
<div id="run_cronjobs" style="visibility:hidden;display:none;"><img alt="cron" src="/index.php?second=cronjobs&amp;p=s470i8tD" width="1" height="1" /></div>
<script src="https://nguoicodonvn2008.info/assets/js/jquery/jquery.min.js"></script>
<script>var nv_base_siteurl="/",nv_lang_data="vi",nv_lang_interface="vi",nv_name_variable="nv",nv_fc_variable="op",nv_lang_variable="language",nv_module_name="news",nv_func_name="savefile",nv_is_user=0, nv_my_ofs=-4,nv_my_abbr="EDT",nv_cookie_prefix="nv4c_e856T",nv_check_pass_mstime=1738000,nv_area_admin=0,nv_safemode=0,theme_responsive=0,nv_recaptcha_ver=2,nv_recaptcha_sitekey="",nv_recaptcha_type="image",XSSsanitize=1;</script>
<script src="https://nguoicodonvn2008.info/assets/js/language/vi.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/global.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/site.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/news.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/main.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/custom.js"></script>
<script type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "Organization",
            "url": "https://nguoicodonvn2008.info",
            "logo": "https://nguoicodonvn2008.info/uploads/angel.gif"
        }
        </script>
<script src="https://nguoicodonvn2008.info/themes/default/js/bootstrap.min.js"></script>
<script type="text/javascript">
var $scrolltop = $('.car-top');
$scrolltop.on('click', function () {
    $('html,body').animate({
        scrollTop: 0
    }, 800);
    $(this).addClass("car-run");
    setTimeout(function(){ $scrolltop.removeClass('car-run');}, 1000);
    return false;
});
$(window).on('scroll', function ()
{ 
    if($(window).scrollTop() >= 200)
    {
        $scrolltop.addClass("show");
        $scrolltop.addClass("car-down");
    }
    else
    {
       $scrolltop.removeClass("show");
       setTimeout(function(){ $scrolltop.removeClass('car-down');}, 300);
    }
});
</script>
</body>
</html>