Skip to main content

Fast DNG parser for numpy datasets (DJI Pocket 4 + Apple ProRAW)

Project description

dngparser

Fast DNG (Digital Negative) parser for machine learning datasets. Written in C++ with pybind11 bindings, returns numpy arrays with zero torch dependency.

Supports multiple DNG vendors:

  • DJI Pocket 4 — little-endian, uncompressed CFA Bayer (1ch uint16, strip-based)
  • Apple ProRAW — big-endian, LJPEG-compressed LinearRaw (3ch uint16, tile-based)

Features

  • C++ TIFF/DNG parser - reads TIFF container structure, IFD chains, SubIFDs, and all DNG-specific tags directly (no libtiff dependency)
  • LJPEG decoder - built-in lossless JPEG (SOF3) decoder with 16-bit Huffman lookup tables for fast Apple ProRAW tile decompression
  • Multi-format RAW read - uncompressed CFA Bayer (DJI) and LJPEG-compressed tiled LinearRaw (Apple), returned as numpy uint16 arrays
  • Big-endian & little-endian - handles both TIFF byte orders with automatic conversion
  • Full metadata extraction - ColorMatrix (SRATIONAL-aware), BlackLevel, WhiteLevel, AsShotNeutral, NoiseProfile, ActiveArea, LinearizationTable, exposure info, opcodes
  • Numpy-first - load_dng() returns plain numpy arrays and Python primitives
  • Type stubs - ships .pyi files generated by pybind11-stubgen for IDE autocomplete

Installation

pip install dngparser

Only depends on numpy. Install torch separately if you need it for dataset loading.

Quick Start

import dngparser

d = dngparser.load_dng("photo.dng")

# DJI Pocket 4 — CFA Bayer, 1 channel
raw = d["raw"]              # numpy.ndarray (H, W) uint16
print(d["cfa_pattern"])     # [0, 1, 1, 2] = RGGB
print(d["black_level"])     # [1024.0, 1024.0, 1024.0, 1024.0]
print(d["white_level"])     # 62400
print(d["compression"])     # 1 (uncompressed)

# Apple ProRAW — LinearRaw, 3 channels, LJPEG-compressed
d = dngparser.load_dng("IMG_5070.DNG")
raw = d["raw"]              # numpy.ndarray (H, W, 3) uint16
print(d["compression"])     # 7 (LJPEG)
print(d["bits_per_sample"]) # 12
print(d["is_tiled"])        # True
print(d["tile_width"])      # 504
print(d["linearization_table"])  # [0, 1, 2, ..., 4095]

# Shared metadata
print(d["color_matrix_1"])  # 3x3 float32, camera -> XYZ
print(d["as_shot_neutral"]) # [0.382, 1.0, 0.655]
print(d["noise_profile"])   # {"slope": 0.000258, "offset": 3.04e-08}

PyTorch Dataset Example

import random
import numpy as np
import torch
from torch.utils.data import Dataset
from dngparser import load_dng


class DngDataset(Dataset):
    """Paired RAW + JPG dataset for ISP training.

    Parameters
    ----------
    raw_dir : str or Path
        Directory containing .dng files.
    jpg_dir : str or Path, optional
        Directory containing corresponding .jpg files (same stem).
    crop_size : int, optional
        Random crop size for training. None = full resolution.
    normalize : bool
        If True, subtract black level and divide by white level.
    pack_bayer : bool
        If True, pack Bayer pattern into 4 channels (4, H/2, W/2).
    """

    def __init__(
        self,
        raw_dir,
        jpg_dir=None,
        crop_size=512,
        normalize=True,
        pack_bayer=True,
    ):
        from pathlib import Path

        self.raw_dir = Path(raw_dir)
        self.jpg_dir = Path(jpg_dir) if jpg_dir else None
        self.crop_size = crop_size
        self.normalize = normalize
        self.pack_bayer = pack_bayer
        self.raw_files = sorted(self.raw_dir.glob("*.dng"))

    def __len__(self):
        return len(self.raw_files)

    def __getitem__(self, idx):
        dng = load_dng(self.raw_files[idx])
        raw = torch.from_numpy(dng["raw"].copy())  # (H, W) uint16

        if self.normalize:
            raw = raw.to(torch.float32)
            black = torch.tensor(dng["black_level"], dtype=torch.float32)
            white = float(dng["white_level"])
            # Expand 2x2 black level to full image
            rows, cols = dng["cfa_repeat_rows"], dng["cfa_repeat_cols"]
            bl = black.view(rows, cols).repeat(
                raw.shape[0] // rows, raw.shape[1] // cols
            )[: raw.shape[0], : raw.shape[1]]
            raw = (raw - bl) / (white - bl.min().item())
            raw = raw.clamp(0.0, 1.0)
        else:
            raw = raw.to(torch.float32)

        if self.pack_bayer:
            # RGGB -> (4, H/2, W/2): [R, Gr, Gb, B]
            raw = torch.stack(
                [raw[0::2, 0::2], raw[0::2, 1::2],
                 raw[1::2, 0::2], raw[1::2, 1::2]],
                dim=0,
            )

        # Load JPG target if available
        if self.jpg_dir is not None:
            from PIL import Image

            jpg_path = self.jpg_dir / (self.raw_files[idx].stem + ".jpg")
            if jpg_path.exists():
                img = Image.open(jpg_path).convert("RGB")
                jpg = torch.from_numpy(np.array(img)).permute(2, 0, 1).float() / 255.0
            else:
                jpg = None
        else:
            jpg = None

        # Random crop
        if self.crop_size is not None and jpg is not None:
            h = raw.shape[-2]
            w = raw.shape[-1]
            y0 = random.randint(0, max(0, h - self.crop_size))
            x0 = random.randint(0, max(0, w - self.crop_size))
            raw = raw[..., y0:y0 + self.crop_size, x0:x0 + self.crop_size]
            jpg = jpg[..., y0:y0 + self.crop_size, x0:x0 + self.crop_size]

        result = {"raw": raw}
        if jpg is not None:
            result["jpg"] = jpg
        return result


# Usage
dataset = DngDataset(
    raw_dir="/path/to/dng_files",
    jpg_dir="/path/to/jpg_files",
    crop_size=512,
)
sample = dataset[0]
# sample["raw"]  -> (4, 512, 512) float32  (packed Bayer, normalized)
# sample["jpg"]  -> (3, 512, 512) float32  (sRGB target)

Vendor Differences

Feature DJI Pocket 4 Apple ProRAW
Byte order Little-endian (II) Big-endian (MM)
Compression Uncompressed (1) LJPEG (7)
PhotometricInterpretation CFA (32803) LinearRaw (34892)
Channels 1 (Bayer) 3 (interleaved RGB)
Bit depth 16 12
Layout Strips Tiles (504x504)
LinearizationTable absent 4096-entry LUT
NoiseProfile location Main IFD Raw SubIFD
WhiteLevel type LONG SHORT[3]
Raw output shape (H, W) uint16 (H, W, 3) uint16

What It Does NOT Do

The parser only reads and structures data. It does not apply:

  • Black level subtraction
  • Linearization
  • Demosaicing
  • White balance / color correction
  • Tone mapping

These transforms belong to the differentiable ISP pipeline (planned as a separate project).

Build from Source

Requires CMake 3.18+, a C++17 compiler, and Python 3.10+.

python -m venv .venv
.\.venv\Scripts\pip install scikit-build-core build pybind11 numpy

# Build wheel
.\.venv\Scripts\python.exe -m build --wheel

# Install
.\.venv\Scripts\pip install --force-reinstall --no-deps dist\dngparser-0.1.0-*.whl

# Test
.\.venv\Scripts\python.exe tests\test_dng_parse.py

Project Layout

cpp/
  include/dng/       # C++ headers: TIFF reader, LJPEG decoder, DNG parser, data structs
  src/               # C++ sources: tiff_reader.cpp, ljpeg_decoder.cpp, dng_parser.cpp
  binding/           # pybind11 module exposing load_dng()
python/dngparser/    # Python package: dng_loader.py, _dng.pyi
tests/               # End-to-end test with real DNG files (DJI + Apple)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dngparser-0.1.0.tar.gz (28.4 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

dngparser-0.1.0-cp313-cp313-win_amd64.whl (295.9 kB view details)

Uploaded CPython 3.13Windows x86-64

dngparser-0.1.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (109.7 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

dngparser-0.1.0-cp313-cp313-macosx_11_0_arm64.whl (88.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

dngparser-0.1.0-cp312-cp312-win_amd64.whl (295.9 kB view details)

Uploaded CPython 3.12Windows x86-64

dngparser-0.1.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (109.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

dngparser-0.1.0-cp312-cp312-macosx_11_0_arm64.whl (88.7 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

dngparser-0.1.0-cp311-cp311-win_amd64.whl (293.6 kB view details)

Uploaded CPython 3.11Windows x86-64

dngparser-0.1.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (109.6 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

dngparser-0.1.0-cp311-cp311-macosx_11_0_arm64.whl (87.1 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

dngparser-0.1.0-cp310-cp310-win_amd64.whl (293.2 kB view details)

Uploaded CPython 3.10Windows x86-64

dngparser-0.1.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (108.2 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

dngparser-0.1.0-cp310-cp310-macosx_11_0_arm64.whl (86.1 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file dngparser-0.1.0.tar.gz.

File metadata

  • Download URL: dngparser-0.1.0.tar.gz
  • Upload date:
  • Size: 28.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dngparser-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4bcd91a70c83d647fa6be40d1a302429012ec202b32df0702a9b07690d527de7
MD5 71030cc63d55d1a40d77a371db865707
BLAKE2b-256 024ae26137caf97cea615a4a09f81909239f7dbeabfc22489cc18ffb4bd6250a

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0.tar.gz:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: dngparser-0.1.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 295.9 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dngparser-0.1.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8ce263be1bd5bc6b6ac47e7d7546c0df123fca7e8042f69796895123008a4ce8
MD5 b2784d7ff8d2c88d908db3f906641c71
BLAKE2b-256 aa6bbaa7ee8c73c817fcc33b931846beb9859faeb2cbe884543d224462ca8f85

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp313-cp313-win_amd64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b2ba7ad8cfd2304723994a089f7a9f487d299c65f1542a043686a587429d0629
MD5 fa41eb2dc4e48bf235835ae8cb20b208
BLAKE2b-256 b40a6310b541f9ad4aee1032f7d38f400005c4f6d536bad1d2fd9e37613ec15b

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 83334dce44fe4ecc6e241c28160742a9350402132763c193a272426c5950e882
MD5 740f9292f07f28605c31e0f85781d12f
BLAKE2b-256 fd39c984716a260cef2bae5bbcb3d154a5c8207a13135f4e5487b63bff99272f

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: dngparser-0.1.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 295.9 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dngparser-0.1.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c1aa0987a5fc6649a41294371a37d7bdc732854aab5df70f1053db137d3532f4
MD5 30d7667e156dc5dbe2f0ddf96219f9a0
BLAKE2b-256 820c5cbb9b10859644072d97c5741d6defe261203ce320216aec8c4da2a5d927

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp312-cp312-win_amd64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d7ad359fee24cbf158cd0620a016b2dd650abcc44184502b3bd9ca9a1b0a5583
MD5 6d38391180d769d6f5fb74bb216bdb91
BLAKE2b-256 4efcc75587395145b26f7100fc3c543a9b90fdfa3b11cf302d660973fdbb585c

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 122ac66b1636a27c1c3c17e723b1f2316a25be9ca236b3009a361da055606874
MD5 065ef542a21d0f2d85d54375e1cfc6e3
BLAKE2b-256 3799cf00e28e8e18901d13cba3688ae73757dfe518b6bdbd652d685375d2e887

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: dngparser-0.1.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 293.6 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dngparser-0.1.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 3015cab1217bf987ecb3b0c15141be6c79baeb2b80f479ed2fd67c494ad7f478
MD5 e9bb740a635c46546f5d8dc370bf2a3e
BLAKE2b-256 9f1b17b1e1cf906e737bcd6b53b014f0df2ebfe686959902ab9ccf249a0bf08c

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp311-cp311-win_amd64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0dd685c7c9d7835fb727d3da2443be2f01a4c1595e81c1a9675a43bea93fa87f
MD5 b595fa1fb91fdce0fded0816fcbddcaa
BLAKE2b-256 eac2fe7113ad6b867deea2cc0aedd08c14b1ae8d94aab5932399057ceff1d3af

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a375df36124374ecd408d19fcfb2ca79c03fc7ea8684117b22f3450dc9c9e178
MD5 d584464abc084770e6dced63ddedf39e
BLAKE2b-256 f50fc99e2f170aa4609f35745adda443f15703d028740ab1388f907e341ba3af

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: dngparser-0.1.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 293.2 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dngparser-0.1.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 835edba5a0d164f7a880eceb8e47e4dc9582c76a4497913080e0702dd64426b2
MD5 8e25f1b6c7953e61b32113d97d6a9500
BLAKE2b-256 e0d50cf9c0ac844704d25c19c1f55077e52fcbcf858dffcd765ce3b2b3c34e31

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp310-cp310-win_amd64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5d15dd63946601d0e53575139365d63e3e09cfc82094f4984912577f15ea706a
MD5 2c026ecc57e2ebf1852af6d3c8aaadbf
BLAKE2b-256 245f6006c499e117b64e244d308fbf117f36b415defb6bdc448f20601c1c5885

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dngparser-0.1.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for dngparser-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fa5dd2c06f46d3258be8689d2665ca9f0e665f3b6306acedf7b04fc704c19b62
MD5 76f71f07e290105c3de4a6df016c596b
BLAKE2b-256 37473a3d0cb42e739a802138f155145e1eb3bb5daa0ec204312e6dc11639b3e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for dngparser-0.1.0-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: release.yml on JonahZeng/dngparser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page