Skip to main content

A parser library and command-line tool for NITF files.

Project description

nitful: The Useful NITF Library

CI Status PyPI - Version PyPI - Python Version License: MIT

nitful is a zero-dependency Python library and command-line utility for reading, writing, and manipulating National Imagery Transmission Format (NITF / JBF) files.

[!IMPORTANT] nitful is alpha software. It is fully functional for reading, writing, and stripping NITF files, but expect minor API adjustments before a stable release.

Features

  • Command-Line Tool: Inspect, dump, filter, or strip NITF metadata directly from the command line.
  • Rich Data Structures: Headers and extensions are parsed into native, nested Python Dataclasses, enabling type-checking and IDE autocompletion.
  • Lazy Loading: Image data is skipped and can be loaded later, so that parsing even massive NITF files has low memory overhead.
  • Read-Modify-Write: Read an image, modify fields, add TREs/DESs, and seamlessly write a new image.
  • Zero Dependencies: Written in pure Python.

Table of Contents


Installation

nitful is available on PyPI and can be installed with standard package managers.

For library use within a Python project:

pip install nitful

If you strictly want to use nitful as a command-line tool, you can install it with pipx:

pipx install nitful

Development Installation If you want to run the latest unreleased code or contribute to the project, you can install directly from the repository:

git clone https://github.com/swarn/nitful.git
cd nitful
pip install -e .

Command-Line Usage

nitful provides a convenient CLI for inspecting and manipulating NITF files.

(Note: If your environment didn't expose the nitful command to your PATH, you can always execute the tool via python -m nitful).

Dump metadata to text

Print the entire file structure to standard output:

nitful dump image.ntf

Filter the output to target specific image segments, Tagged Record Extensions (TREs), or Data Extension Segments (DESs):

nitful dump image.ntf --header --image 1 --tre RPC00B --des CSEPHB

This is an inclusive filter. The command above will print the file header with all its TREs, image 1 with all its TREs, any other RPC00B TREs, and all CSEPHB DESs.

Strip image payloads

Create a metadata-only copy of a NITF by stripping out the image payloads. This is useful for sharing files for debugging or metadata analysis:

nitful strip image.ntf stripped_metadata.ntf

Python API: Reading Data

nitful parses the binary headers into type-annotated Python dataclasses. Image data is not eagerly loaded, so reading large NITF files has low memory overhead.

import nitful

# Load the file
nitf = nitful.load("tests/data/mock.ntf")

# Access standard file header fields
print(f"File Security: {nitf.security.SCLAS}")
print(f"Number of images: {len(nitf.image_segments)}")


# Assuming there is an ICHIPB TRE in the first image segment.
from nitful.extensions.ichipb import ICHIPB
img = nitf.image_segments[0]
ichipb = next(tre for tre in img.IXSHD if type(tre) is ICHIPB)
print(f"Image scale factor: {ichipb.SCALE_FACTOR}")

You can also dig into complex Data Extension Segments (DES):

# In addition to switching on type, you can simply check tags.
csephb = next(des for des in nitf.data_segments if des.DESID == "CSEPHB")

# Type casting isn't necessary, but will provide your IDE or LSP with useful
# information.
from nitful.extensions.csephb import CSEPHB
from typing import cast
csephb = cast(CSEPHB, csephb)

print(f"Ephemeris date: {csephb.DATE_EPHEM}")
print(f"First ephemeris Vector: {csephb.ephemerides[0]}")

Python API: Manipulating Data

Read-modify-write workflows are easy:

import nitful
from nitful.core.common import SecurityClass
from nitful.extensions.csephb import CSEPHB

nitf = nitful.load("tests/data/mock.ntf")

# Modify a basic header field.
nitf.security.SCLAS = SecurityClass.TOPSECRET

# Change the X coordinate of the first ephemeris point in CSEPHB.
csephb = next(des for des in nitf.data_segments if type(des) is CSEPHB)
csephb.ephemerides[0][0] += 10.5

# Save the new file. This will efficiently stream the pixel data from the
# original to the new image.
nitful.save(nitf, "modified.ntf")

Working with Image Data

nitful avoids dependencies like numpy or pyvips, but can work with them.

By default, nitful skips reading pixel data, but makes it available via the DeferredImageData class. You can read the pixels as raw bytes, but it's usually more useful to use a library.

All examples below assume you've loaded a NITF file with at least one image segment.

import nitful
from nitful.core import DeferredImageData
from typing import cast

nitf = nitful.load('image.ntf')
segment = nitf.image_segments[0]

# Casting is not strictly necessary here, but prevents warnings from your
# type checker. nitful always assigns DeferredImageData on read, but allows
# you to assign raw bytes.
data = cast(DeferredImageData, segment.data)

Pixels in Numpy

If the image is uncompressed, you can use numpy.memmap to map the disk bytes directly into an array.

import numpy as np

pixels = np.memmap(
    'image.ntf',        # or data.path
    dtype=np.uint8,     # adjust based on segment.ABPP
    mode='r',
    offset=data.offset,
    shape=(segment.NROWS, segment.NCOLS)
)

# Numpy only reads the data necessary, not the whole image.
print(np.mean(pixels[:100, :100]))

Pixels in pyvips

pyvips is a good library for handling large and/or compressed images:

import pyvips

with open('image.ntf', 'rb') as f:
    f.seek(data.offset)

    source = pyvips.SourceCustom(f)
    image = pyvips.Image.new_from_source(source, "", access="sequential")

    # Create a thumbnail image. Pyvips intelligently streams the pixel data,
    # so the memory overhead is typically much smaller than the full image.
    image.thumbnail_image(512).write_to_file("preview.jpg")

Pixels as bytes

You can also get the pixel data as raw bytes. Note that this reads the entire image into memory!

raw_bytes = data.read()

You can set pixels to raw bytes, as well:

pixels = b'1234'
nitf.image_segments[0].data = pixels
nitful.save(nitf, 'new_file.ntf')

[!IMPORTANT] It is up to you to correctly configure the image segment metadata (NROWS, ABPP, etc.) when modifying pixel data.

Supported Extensions

The list of explicitly supported SDEs is small but growing; see the nitful/extensions directory.

Crucially, an extension does not need to be supported by nitful for you to read or modify the rest of the file. Unknown extensions are safely preserved as raw bytes and written back out identically.

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

nitful-0.2.0.tar.gz (166.5 kB view details)

Uploaded Source

Built Distribution

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

nitful-0.2.0-py3-none-any.whl (74.5 kB view details)

Uploaded Python 3

File details

Details for the file nitful-0.2.0.tar.gz.

File metadata

  • Download URL: nitful-0.2.0.tar.gz
  • Upload date:
  • Size: 166.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nitful-0.2.0.tar.gz
Algorithm Hash digest
SHA256 3fea2f1a8ace3de31560cda37351244bc96b5908cbaf502864c55926724a8eae
MD5 63a6374c96fd826d860875dee21f1f9a
BLAKE2b-256 4f47f994696fc5498b232bd591df48aa7691979ec2d0e6d5010823c464666bb2

See more details on using hashes here.

File details

Details for the file nitful-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: nitful-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 74.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for nitful-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d7d0de072507809390766ebdeae2558915d39a343307a884f76ab9f29dc36a40
MD5 99b2c9e842bd8f9a8df25cc03906ee02
BLAKE2b-256 e2f96fc18c43232c99875b68e1541770cd8451b90083da5d46cc96605ca3bb4c

See more details on using hashes here.

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