如何在Python中将8bpp位图转换为1bpp位图

huangapple go评论83阅读模式
英文:

How to convert an 8bpp bitmap to 1bpp bitmap in Python

问题

以下是您提供的代码的翻译部分:

我有一些代码用于创建灰度8bpp图像但我需要创建1bpp二进制图像以供打印机使用我在这里看到了两篇帖子但不理解它们是如何解决问题的
https://stackoverflow.com/questions/21067028/cant-format-bmp-image-data-to-1-bit-per-pixel-in-pil
我已经安装了Pillow但按照我所阅读的所有教程都要从PIL中导入Image

我有一个名为conv_to_1bpp的方法将所有值为255的像素设置为1但这仍然生成8bpp图像

**代码**

```python
from PIL import Image
import numpy as np
import os
import sys
import struct

class BmpMaker:

    def __init__(self):
        self.ffp = None
        self.img_width = None
        self.img_height = None
        self.ws_activation = None
        self.bpp = None

    def make_image(self, img_width, img_height, ws_activation):
        """创建位图。"""

        self.ffp = None
        self.img_width = img_width
        self.img_height = img_height
        self.ws_activation = ws_activation

        # 创建新的黑色图像 - L模式用于黑白
        img = Image.new('L', (img_width, img_height))
        # 转换为Numpy数组以便于处理
        na = np.array(img)
        # 设置白色空白激活的行数
        white_rows = ws_activation
        # 创建白色线条
        na[0:white_rows, 0:999] = 255
        # 从Numpy数组中恢复为PIL图像并保存
        self.ffp = self.make_img_title(img_width, img_height, ws_activation)
        Image.fromarray(na).save(self.ffp)
        self.bpp = self.get_bitdepth()
        return self.ffp

    def make_img_title(self, img_width, img_height, ws_activation):
        if ws_activation == 0:
            mystr = f"{img_height}x{img_width}"
        elif ws_activation is not None:
            mystr = f"{ws_activation}_{img_height}x{img_width}"
        self.ffp = os.path.join(os.getcwd(), mystr + ".bmp")
        print("img_ffp : ", self.ffp)
        return self.ffp

    def get_bitdepth(self):
        # 读取前100个字节
        with open(self.ffp, 'rb') as f:
            BMP = f.read(100)

        if BMP[0:2] != b'BM':
            sys.exit('错误:不正确的BMP签名')

        # 获取BITMAPINFOHEADER大小 - https://en.wikipedia.org/wiki/BMP_file_format
        BITMAPINFOHEADERSIZE = struct.unpack('<i', BMP[14:18])[0]
        okSizes = [40, 52, 56, 108, 124]
        if BITMAPINFOHEADERSIZE not in okSizes:
            sys.exit(f'错误:BITMAPINFOHEADER大小为{BITMAPINFOHEADERSIZE},期望其中之一{okSizes}')

        # 获取每像素位数
        self.bpp = struct.unpack('<H', BMP[28:30])[0]
        print(f'bpp:{self.bpp}')
        return self.bpp

    def get_img_bitdepth(self, img):
        # 读取前100个字节
        with open(img, 'rb') as f:
            BMP = f.read(100)

        if BMP[0:2] != b'BM':
            sys.exit('错误:不正确的BMP签名')

        # 获取BITMAPINFOHEADER大小 - https://en.wikipedia.org/wiki/BMP_file_format
        BITMAPINFOHEADERSIZE = struct.unpack('<i', BMP[14:18])[0]
        okSizes = [40, 52, 56, 108, 124]
        if BITMAPINFOHEADERSIZE not in okSizes:
            sys.exit(f'错误:BITMAPINFOHEADER大小为{BITMAPINFOHEADERSIZE},期望其中之一{okSizes}')

        # 获取每像素位数
        img_bpp = struct.unpack('<H', BMP[28:30])[0]
        print(f'bpp:{img_bpp}')
        return img_bpp

    def conv_to_1bpp(self):
        img = Image.open(self.ffp)
        arr = np.array(img)
        # 将所有值等于255的索引处的像素设置为1。
        arr[arr == 255] = 1
        print('\n' * 3, arr)
        Image.fromarray(arr).save("my_img.bmp")
        print(self.get_img_bitdepth("my_img.bmp"))


if __name__ == "__main__":
    import PIL
    print('Pillow版本:', PIL.__version__)
    bm = BmpMaker()
    base_image = bm.make_image(1000, 8, 5)

    print("位图ffp:", bm.ffp)
    print("位图位深度:", bm.bpp)
    bm.conv_to_1bpp()

希望这能帮助您理解代码。如果您需要进一步的帮助,请随时告诉我。

英文:

I have some code which is fine for creating greyscale (8bpp) images but I need to create 1bpp (binary) also for a printer. I have seen 2 posts here but cannot understand how they fix the issue.
https://stackoverflow.com/questions/21067028/cant-format-bmp-image-data-to-1-bit-per-pixel-in-pil
I have pillow installed but call it using PIL as all the tutorials I have read seem to say to import Image from PIL.

I have a method called conv_to_1bpp which sets anything at 255 equal to 1, this is still making 8bpp images though.

Code

from PIL import Image
import numpy as np
import os
import sys
import struct
class BmpMaker:
def __init__(self):
self.ffp = None
self.img_width = None
self.img_height = None
self.ws_activation = None
self.bpp = None
def make_image(self, img_width, img_height, ws_activation):
&quot;&quot;&quot;Creates a bitmap.&quot;&quot;&quot;
self.ffp = None
self.img_width = img_width
self.img_height = img_height
self.ws_activation = ws_activation
# Create new black image - L mode for b/w
img = Image.new(&#39;L&#39;, (img_width, img_height))
# Convert to Numpy array for easy processing
na = np.array(img)
# set the amount of white space activation
white_rows = ws_activation
# make white lines
na[0:white_rows, 0:999] = 255
# Revert to PIL Image from Numpy array and save
self.ffp = self.make_img_title(img_width, img_height, ws_activation)
Image.fromarray(na).save(self.ffp)
self.bpp = self.get_bitdepth()
return self.ffp
def make_img_title(self, img_width, img_height, ws_activation):
if ws_activation == 0:
mystr = f&quot;{img_height}x{img_width}&quot;
elif ws_activation is not None:
mystr = f&quot;{ws_activation}_{img_height}x{img_width}&quot;
self.ffp = os.path.join(os.getcwd(), mystr + &quot;.bmp&quot;)
print(&quot;img_ffp : &quot;, self.ffp)
return self.ffp
def get_bitdepth(self):
# Read first 100 bytes
with open(self.ffp, &#39;rb&#39;) as f:
BMP = f.read(100)
if BMP[0:2] != b&#39;BM&#39;:
sys.exit(&#39;ERROR: Incorrect BMP signature&#39;)
# Get BITMAPINFOHEADER size - https://en.wikipedia.org/wiki/BMP_file_format
BITMAPINFOHEADERSIZE = struct.unpack(&#39;&lt;i&#39;, BMP[14:18])[0]
okSizes = [40, 52, 56, 108, 124]
if BITMAPINFOHEADERSIZE not in okSizes:
sys.exit(f&#39;ERROR: BITMAPINFOHEADER size was {BITMAPINFOHEADERSIZE},&#39;
f&#39; expected one of {okSizes}&#39;)
# Get bits per pixel
self.bpp = struct.unpack(&#39;&lt;H&#39;, BMP[28:30])[0]
print(f&#39;bbp: {self.bpp}&#39;)
return self.bpp
def get_img_bitdepth(self, img):
# Read first 100 bytes
with open(img, &#39;rb&#39;) as f:
BMP = f.read(100)
if BMP[0:2] != b&#39;BM&#39;:
sys.exit(&#39;ERROR: Incorrect BMP signature&#39;)
# Get BITMAPINFOHEADER size - https://en.wikipedia.org/wiki/BMP_file_format
BITMAPINFOHEADERSIZE = struct.unpack(&#39;&lt;i&#39;, BMP[14:18])[0]
okSizes = [40, 52, 56, 108, 124]
if BITMAPINFOHEADERSIZE not in okSizes:
sys.exit(f&#39;ERROR: BITMAPINFOHEADER size was {BITMAPINFOHEADERSIZE},&#39;
f&#39; expected one of {okSizes}&#39;)
# Get bits per pixel
img_bpp = struct.unpack(&#39;&lt;H&#39;, BMP[28:30])[0]
print(f&#39;bbp: {img_bpp}&#39;)
return img_bpp
def conv_to_1bpp(self):
img = Image.open(self.ffp)
arr = np.array(img)
#print(arr)
# Set all values at indices where the array equals 255 to 1.
arr[arr==255] = 1
print(&#39;\n&#39;*3, arr)
Image.fromarray(arr).save(&quot;my_img.bmp&quot;)
print(self.get_img_bitdepth(&quot;my_img.bmp&quot;))
if __name__ == &quot;__main__&quot;:
import PIL
print(&#39;Pillow Version:&#39;, PIL.__version__)
bm = BmpMaker()
base_image = bm.make_image(1000, 8, 5)
print(&quot;bitmap ffp: &quot;, bm.ffp)
print(&quot;bitmap bitdepth : &quot;, bm.bpp)
bm.conv_to_1bpp()

答案1

得分: 1

当创建初始图像时,使用模式 '1' 而不是 'L'。

# 创建新的黑白图像 - 使用 '1' 模式进行二值化
img = Image.new('1', (img_width, img_height))
英文:

when creating the initial image use mode '1' instead of 'L'

    # Create new black image - L mode for b/w, &#39;1&#39; for binary
img = Image.new(&#39;1&#39;, (img_width, img_height))

huangapple
  • 本文由 发表于 2023年4月6日 19:10:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75948844.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定