CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pypng

Pure Python library for saving and loading PNG images without external dependencies

Pending
Overview
Eval results
Files

writing.mddocs/

PNG Writing Operations

Comprehensive PNG encoding capabilities with full format control, metadata support, and optimization options. The Writer class handles all PNG color types, bit depths, and optional chunks for professional-quality PNG creation.

Capabilities

PNG File Writing

The Writer class provides complete control over PNG creation with extensive format and metadata options.

class Writer:
    def __init__(self, width=None, height=None, size=None, greyscale=Default, 
                 alpha=False, bitdepth=8, palette=None, transparent=None, 
                 background=None, gamma=None, compression=None, interlace=False, 
                 planes=None, colormap=None, maxval=None, chunk_limit=2**20, 
                 x_pixels_per_unit=None, y_pixels_per_unit=None, unit_is_meter=False):
        """
        Initialize PNG writer with format and metadata options.
        
        Parameters:
        - width, height: int, image dimensions in pixels
        - size: tuple, alternative way to specify (width, height)
        - greyscale: bool or Default, whether to create greyscale image
        - alpha: bool, whether to include alpha channel
        - bitdepth: int, bits per sample (1, 2, 4, 8, 16)
        - palette: list, RGB or RGBA tuples for palette images
        - transparent: color value or index for transparency
        - background: color value for default background
        - gamma: float, gamma correction value
        - compression: int, zlib compression level (0-9)
        - interlace: bool, whether to use Adam7 interlacing
        - planes: int, deprecated, use greyscale and alpha instead
        - colormap: dict, deprecated, use palette instead
        - maxval: int, maximum pixel value for scaling
        - chunk_limit: int, maximum chunk size in bytes
        - x_pixels_per_unit, y_pixels_per_unit: int, resolution information
        - unit_is_meter: bool, whether resolution units are meters (vs. unknown)
        """

Writing Methods

Multiple methods for writing PNG data from different Python data structures.

def write(self, outfile, rows):
    """
    Write PNG from row iterator.
    
    Parameters:
    - outfile: file-like object opened in binary write mode
    - rows: iterable of pixel rows, each row is sequence of pixel values
    """
    
def write_array(self, outfile, pixels):
    """
    Write PNG from 2D array or nested sequences.
    
    Parameters:
    - outfile: file-like object opened in binary write mode  
    - pixels: 2D array-like structure of pixel data
    """
    
def write_packed(self, outfile, rows):
    """
    Write PNG from pre-packed byte rows.
    
    Parameters:
    - outfile: file-like object opened in binary write mode
    - rows: iterable of byte strings representing packed pixel rows
    """
    
def write_passes(self, outfile, rows):
    """
    Write PNG with interlacing support.
    
    Parameters:
    - outfile: file-like object opened in binary write mode
    - rows: iterable of pixel rows for interlaced writing
    """

Usage Examples

Basic PNG Writing

import png

# Create a simple RGB image
width, height = 256, 256
pixels = []

# Generate gradient pattern
for y in range(height):
    row = []
    for x in range(width):
        # RGB gradient
        r = (x * 255) // width
        g = (y * 255) // height  
        b = 128
        row.extend([r, g, b])
    pixels.append(row)

# Write PNG
writer = png.Writer(width=width, height=height, greyscale=False)
with open('gradient.png', 'wb') as f:
    writer.write_array(f, pixels)

Greyscale Image Writing

import png

# Create greyscale image
width, height = 100, 100
pixels = []

for y in range(height):
    row = []
    for x in range(width):
        # Simple checkerboard pattern
        if (x // 10 + y // 10) % 2:
            grey = 255  # White
        else:
            grey = 0    # Black
        row.append(grey)
    pixels.append(row)

# Write greyscale PNG
writer = png.Writer(width=width, height=height, greyscale=True, bitdepth=8)
with open('checkerboard.png', 'wb') as f:
    writer.write_array(f, pixels)

RGBA Image with Transparency

import png

# Create RGBA image with transparency
width, height = 64, 64
pixels = []

for y in range(height):
    row = []
    for x in range(width):
        # Create a circle with alpha blending
        center_x, center_y = width // 2, height // 2
        distance = ((x - center_x) ** 2 + (y - center_y) ** 2) ** 0.5
        
        if distance < width // 3:
            # Inside circle - solid color
            r, g, b, a = 255, 100, 50, 255
        elif distance < width // 2:
            # Edge of circle - fade out
            alpha = int(255 * (1 - (distance - width//3) / (width//2 - width//3)))
            r, g, b, a = 255, 100, 50, alpha
        else:
            # Outside circle - transparent
            r, g, b, a = 0, 0, 0, 0
            
        row.extend([r, g, b, a])
    pixels.append(row)

# Write RGBA PNG
writer = png.Writer(width=width, height=height, greyscale=False, alpha=True)
with open('circle_alpha.png', 'wb') as f:
    writer.write_array(f, pixels)

Palette-Based Image

import png

# Define color palette
palette = [
    (255, 0, 0),    # Red
    (0, 255, 0),    # Green  
    (0, 0, 255),    # Blue
    (255, 255, 0),  # Yellow
    (255, 0, 255),  # Magenta
    (0, 255, 255),  # Cyan
    (255, 255, 255), # White
    (0, 0, 0)       # Black
]

# Create image using palette indices
width, height = 32, 32
pixels = []

for y in range(height):
    row = []
    for x in range(width):
        # Use palette index based on position
        palette_index = (x // 4 + y // 4) % len(palette)
        row.append(palette_index)
    pixels.append(row)

# Write palette PNG
writer = png.Writer(width=width, height=height, palette=palette, bitdepth=8)
with open('palette_image.png', 'wb') as f:
    writer.write_array(f, pixels)

High Bit Depth Images

import png

# Create 16-bit per channel image
width, height = 64, 64
pixels = []

for y in range(height):
    row = []
    for x in range(width):
        # Use full 16-bit range (0-65535)
        r = (x * 65535) // width
        g = (y * 65535) // height
        b = 32768  # Mid-range value
        row.extend([r, g, b])
    pixels.append(row)

# Write 16-bit RGB PNG
writer = png.Writer(width=width, height=height, greyscale=False, bitdepth=16)
with open('high_bit_depth.png', 'wb') as f:
    writer.write_array(f, pixels)

PNG with Metadata

import png

# Create simple image
width, height = 32, 32
pixels = [[y * 8 for x in range(width)] for y in range(height)]

# Write PNG with gamma correction and resolution metadata
writer = png.Writer(
    width=width, 
    height=height, 
    greyscale=True,
    gamma=2.2,                    # Gamma correction
    x_pixels_per_unit=2835,       # 72 DPI in pixels per meter
    y_pixels_per_unit=2835,
    unit_is_meter=True
)

with open('metadata_image.png', 'wb') as f:
    writer.write_array(f, pixels)

Row-by-Row Writing

import png

def generate_rows(width, height):
    """Generator function that yields rows on demand"""
    for y in range(height):
        row = []
        for x in range(width):
            # Generate pixel data on-the-fly
            value = (x + y) % 256
            row.append(value)
        yield row

# Write PNG using row generator (memory efficient for large images)
width, height = 1000, 1000
writer = png.Writer(width=width, height=height, greyscale=True)

with open('large_generated.png', 'wb') as f:
    writer.write(f, generate_rows(width, height))

Install with Tessl CLI

npx tessl i tessl/pypi-pypng

docs

convenience.md

image-container.md

index.md

reading.md

writing.md

tile.json