簡體   English   中英

為 3 色電子墨水顯示器轉換圖像時出現問題

[英]Problem converting an image for a 3-color e-ink display

我正在嘗試將圖像文件處理成可以在黑白/紅色電子墨水顯示器上顯示的內容,但我遇到了 output 分辨率的問題。

根據顯示的示例代碼,它需要兩個 arrays 字節(一個用於黑色/白色,一個用於紅色),每個 15,000 字節。 電子墨水顯示屏的分辨率為 400x300。

我正在使用以下 Python 腳本生成兩個 BMP 文件:一個用於黑色/白色,一個用於紅色。 這一切正常,但每個文件大小為 360,000 字節,不適合 ESP32 memory。輸入圖像(PNG 文件)為 195,316 字節。

我正在使用的庫有一個名為EPD_4IN2B_V2_Display(BLACKWHITEBUFFER, REDBUFFER); ,它希望完整圖像(一個通道用於 BW,一個通道用於紅色)在 memory 中。但是,對於這些圖像尺寸,它不適合 ESP32。 而且,該示例為每個顏色通道(BW、R)使用 15KB,所以我覺得我在圖像處理中遺漏了一些必要的東西來完成這項工作。

誰能闡明我所缺少的東西? 我將如何更新 Python 圖像處理腳本來解決這個問題?

我用的是微雪4.2寸電子墨水屏和微雪ESP32驅動板 很多 Python 代碼都是基於這篇 StackOverflow 帖子,但我似乎找不到問題所在。

輸入圖像 體重 紅色的

import io
import traceback
from wand.image import Image as WandImage
from PIL import Image

# This function takes as input a filename for an image
# It resizes the image into the dimensions supported by the ePaper Display
# It then remaps the image into a tri-color scheme using a palette (affinity)
# for remapping, and the Floyd Steinberg algorithm for dithering
# It then splits the image into two component parts:
# a white and black image (with the red pixels removed)
# a white and red image (with the black pixels removed)
# It then converts these into PIL Images and returns them
# The PIL Images can be used by the ePaper library to display
def getImagesToDisplay(filename):
    print(filename)
    red_image = None
    black_image = None
    try:
        with WandImage(filename=filename) as img:
            img.resize(400, 300)
            with WandImage() as palette:
                with WandImage(width = 1, height = 1, pseudo ="xc:red") as red:
                    palette.sequence.append(red)
                with WandImage(width = 1, height = 1, pseudo ="xc:black") as black:
                    palette.sequence.append(black)
                with WandImage(width = 1, height = 1, pseudo ="xc:white") as white:
                    palette.sequence.append(white)
                palette.concat()
                img.remap(affinity=palette, method='floyd_steinberg')
                
                red = img.clone()
                black = img.clone()

                red.opaque_paint(target='black', fill='white')
                black.opaque_paint(target='red', fill='white')
                
                red_image = Image.open(io.BytesIO(red.make_blob("bmp")))
                black_image = Image.open(io.BytesIO(black.make_blob("bmp")))

                red_bytes = io.BytesIO(red.make_blob("bmp"))
                black_bytes = io.BytesIO(black.make_blob("bmp"))

    except Exception as ex:
        print ('traceback.format_exc():\n%s',traceback.format_exc())

    return (red_image, black_image, red_bytes, black_bytes)


if __name__ == "__main__":
    print("Running...")

    file_path = "testimage-tree.png"
    with open(file_path, "rb") as f:
            image_data = f.read()

    red_image, black_image, red_bytes, black_bytes = getImagesToDisplay(file_path)

    print("bw: ", red_bytes)
    print("red: ", black_bytes)

    black_image.save("output/bw.bmp")
    red_image.save("output/red.bmp")

    print("BW file size:", len(black_image.tobytes()))
    print("Red file size:", len(red_image.tobytes()))

根據要求,如果它可能對未來的讀者有用,我會更廣泛地寫下我在評論中所說的內容(並被證實確實是問題的原因)。

電子墨水顯示器通常需要黑白圖像。 即每個像素圖像 1 位。 不是灰度(每個像素 1 個通道字節),更不用說 RGB(每個像素 3 個通道/字節)。

我不熟悉雙色紅/黑顯示器。 但它的行為就像 2 個二進制顯示(一個黑白顯示,一個黑白紅顯示)似乎很合乎邏輯。 共享同一個位置。

您的代碼似乎所做的是從 RGB 圖像中刪除所有黑色像素,並將其用作紅色圖像,並從同一 RDB 圖像中刪除所有紅色像素,並將其用作黑色圖像。 但是由於這些圖像是通過clone獲得的,因此它們仍然是 RGB 圖像。 RGB 圖像恰好只包含黑色和白色像素,或者紅色和白色像素,但仍然是 RGB 圖像。

使用 PIL,它是控制圖像在 memory 中的表示方式的模式,因此也控制它們如何保存到文件中。 相關模式是RGBL (灰度又名每像素 1 個線性字節/通道)和1 (二進制又名每像素 1 位)。

所以你需要的是轉換為模式1 在兩張圖片上使用.convert('1')方法。

請注意,400x300×3(圖像的未壓縮 rgb 數據)是 360000,這就是您得到的。 400×300(同一圖像的 L 模式)是 120000,400×300/8(1 模式,1 位/像素)是 15000,這正是你提到的預期大小。 所以這是另一個確認,確實需要 1 位/像素圖像。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM