如何在Python中保存1 bit深度的PNG二进制图像?
Hey there! I totally get the frustration of trying to save a 1-bit PNG and hitting walls with PIL/Pillow or OpenCV. Let's break down exactly how to make this work for both libraries—you probably just missed a key step or parameter.
Using Pillow (PIL) to Save 1-bit PNGs
This is the most straightforward method once you know the right conversion step. The key is ensuring your image is explicitly converted to the 1-bit mode before saving.
Step-by-Step Code:
from PIL import Image # Let's assume you already have your binary image—either loaded via Pillow or converted from a numpy array # Example if starting from a numpy array: # import numpy as np # binary_np = np.array([[0, 255], [255, 0]], dtype=np.uint8) # Sample binary image # img = Image.fromarray(binary_np) # Convert the image to 1-bit mode (critical step!) # Use dither=Image.NONE if you want no dithering (strict black/white, no intermediate shades) img_1bit = img.convert('1', dither=Image.NONE) # Save as PNG—Pillow will handle the 1-bit encoding automatically img_1bit.save('output_1bit_pillow.png', format='PNG')
Why this works:
- The
convert('1')method transforms your image into a 1-bit bilevel (black/white) mode. Without this, even if your image looks binary, it's likely stored as 8-bit grayscale ('L' mode), which is what you were probably saving before. - Checking the mode afterward: Load the saved image back with
Image.open('output_1bit_pillow.png')and printimg.mode—it should return'1'.
Using OpenCV (With a Workaround)
OpenCV doesn't natively support saving 1-bit PNGs directly, but we can either convert to a Pillow Image first (using the method above) or use the pypng library to write the 1-bit data directly.
Option 1: Convert to Pillow Image
import cv2 from PIL import Image # Load your binary image with OpenCV (grayscale mode) cv_img = cv2.imread('input_binary.png', cv2.IMREAD_GRAYSCALE) # Convert OpenCV image (grayscale) to Pillow Image pillow_img = Image.fromarray(cv_img) # Follow the Pillow steps above img_1bit = pillow_img.convert('1', dither=Image.NONE) img_1bit.save('output_1bit_cv2_pillow.png', format='PNG')
Option 2: Use the pypng Library
If you prefer to stick with OpenCV without Pillow, install pypng first with pip install pypng, then use this code:
import cv2 import png # Load binary grayscale image cv_img = cv2.imread('input_binary.png', cv2.IMREAD_GRAYSCALE) # Convert 0/255 values to 0/1 (1-bit PNG uses 0 for black, 1 for white) binary_data = (cv_img // 255).tolist() # Write the 1-bit PNG with open('output_1bit_pypng.png', 'wb') as f: writer = png.Writer( width=cv_img.shape[1], height=cv_img.shape[0], bitdepth=1, greyscale=True ) writer.write(f, binary_data)
Quick Checks to Verify
After saving, you can confirm the bit depth:
- On Windows: Right-click the image → Properties → Details → Bit depth
- On macOS: Right-click → Get Info → More Info → Bits per sample
- Using Pillow:
Image.open('output.png').modereturns'1'for 1-bit images.
内容的提问来源于stack exchange,提问作者Jimbo

