Skip to content

jbig/jbg support in Python, using old 2014 C library

License

Notifications You must be signed in to change notification settings

DealerShelf/jbigkitpy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A simple, fast Python wrapper for Markus Kuhn's jbig-kit C library, providing functions for encoding and decoding JBIG1 image data (supported file types include .jbg, .jbig).

This library compiles the necessary C source files into a Python C extension, enabling direct, high-performance interaction without needing to have a pre-compiled .dll or .so file on your system. It is designed to be cross-platform, working on both Windows and Linux/macOS.

The primary goal of this wrapper is to convert between raw JBIG1 bytestreams and raw bitmap data, making it easy to integrate with other libraries like Pillow.

Features

  • Decode JBIG1 image data into a raw bitmap, width, and height.
  • Encode a raw bitmap, width, and height into a JBIG1 bytestream.
  • No external library dependencies are needed at runtime (the C code is compiled into the extension).
  • Cross-platform build process for Windows, macOS, and Linux.

Installation & Build

You will need a C compiler set up on your system.

  • On Windows: You'll need the "C++ build tools" from the Visual Studio Installer.
  • On Linux: You'll need gcc and the Python development headers (e.g., sudo apt install build-essential python3-dev).
  • On macOS: You'll need Xcode Command Line Tools.

You can install the package directly from GitHub using pip:

pip install git+https://github.com/ReedGraff/jbigkitpy.git

Usage

The library provides two main functions: decode and encode.

  • jbigkitpy.decode(jbig_data: bytes) -> tuple[bytes, int, int]
  • jbigkitpy.encode(bitmap_data: bytes, width: int, height: int) -> bytes

Important Note on Pixel Format: The jbig-kit library uses the PBM (Portable Bitmap) convention where a 1 bit represents black and a 0 bit represents white. However, libraries like Pillow use the opposite convention for their '1' mode images.

  • When encoding data from Pillow, you must invert the bits first.
  • When decoding data to be used in Pillow, you must invert the bits after decoding.

Example Script

The following script (example.py) demonstrates a full round-trip conversion. It takes a standard image (e.g., a PNG), encodes it to JBIG, saves it, then decodes it back and saves the result.

You will need Pillow to run this example:

pip install Pillow
# example.py
from PIL import Image, ImageOps
import jbigkitpy as jbig

def run_example():
    """
    Demonstrates a full encode -> decode cycle.
    """
    input_image_path = 'input.png'  # Your source image (PNG, JPEG, etc.)
    jbig_output_path = 'output.jbg'
    final_image_path = 'decoded_output.png'

    # --- 1. ENCODING ---
    print(f"Encoding '{input_image_path}' to '{jbig_output_path}'...")
    try:
        # Open with Pillow and convert to 1-bit black and white
        with Image.open(input_image_path) as img:
            img_bw = img.convert('1')
            width, height = img_bw.size
            
            # Get the raw bitmap data from Pillow. Pillow uses 1 for white, 0 for black.
            pillow_bitmap = img_bw.tobytes()

        # Invert the bitmap data for jbig-kit, which expects 1 for black, 0 for white.
        jbig_bitmap = bytes(b ^ 0xFF for b in pillow_bitmap)

        # Call our C extension to encode the data
        jbig_data = jbig.encode(jbig_bitmap, width, height)

        # Write the resulting JBIG file
        with open(jbig_output_path, 'wb') as f:
            f.write(jbig_data)

        print(f"Successfully encoded and saved to '{jbig_output_path}'.")

    except Exception as e:
        print(f"An error occurred during encoding: {e}")
        return

    # --- 2. DECODING ---
    print(f"\nDecoding '{jbig_output_path}' to '{final_image_path}'...")
    try:
        # Read the JBIG file we just created
        with open(jbig_output_path, 'rb') as f:
            jbig_file_data = f.read()

        # Call our C extension to decode the data
        bitmap_data, width, height = jbig.decode(jbig_file_data)
        
        # Load the raw bitmap into a Pillow Image object.
        # Since the raw data is in the PBM format (1=black), we create the
        # image and then invert it to display correctly.
        img_from_raw = Image.frombytes('1', (width, height), bitmap_data)
        img_final = ImageOps.invert(img_from_raw)
        
        # Save the final decoded image
        img_final.save(final_image_path)
            
        print(f"Successfully decoded and saved to '{final_image_path}'.")

    except Exception as e:
        print(f"An error occurred during decoding: {e}")

if __name__ == '__main__':
    # You will need to create a sample 'input.png' file for this script to work.
    try:
        run_example()
    except FileNotFoundError:
        print("\nError: 'input.png' not found.")
        print("Please create a sample image named 'input.png' in this directory to run the example.")

License

This wrapper is available under the GNU General Public License (GPLv2), the same license as the underlying jbig-kit library. See the COPYING file for more details.

Acknowledgments

This package is a wrapper around the jbig-kit C library, created and maintained by Markus Kuhn. All credit for the compression and decompression logic belongs to him.

About

jbig/jbg support in Python, using old 2014 C library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published