Skip to main content

Python binding for TinyDNG

Project description

Tiny DNG Loader and Writer library

Header-only simple&limited DNG(Digital NeGative, TIFF format + extension) loader and writer in C++11.

Currently TinyDNG only supports lossless RAW DNG and limited lossless JPEG DNG(no lossy compression support).

TinyDNG can also be used as an TIFF RGB image loader(8bit, 16bit and 32bit are supported).

TinyDNG loader module is being fuzz tested using LLVMFuzzer, and is enoughly secure(and no C++ exception and assert/abort code exists).

(NOTE: TinyDNG just loads DNG data as is, thus you'll need your own RAW processing code(e.g. debayer) to get a developed image as shown the above)

Features

Loading

  • RAW DNG data
  • Lossless JPEG
  • ZIP-compressed DNG
    • Use miniz or zlib
  • JPEG
    • Support JPEG image(e.g. thumbnail) through stb_image.h.
  • TIFF
    • 8bit uncompressed
    • 8bit LZW compressed(no preditor, horizontal diff predictor)
  • Experimental
    • Apple ProRAW(Lossless JPEG 12bit)
      • Lossless JPEG 12bit
      • Semantic map(8bit Standard JPEG)
    • Decode Canon RAW(CR2)
      • RAW
      • mRAW
      • sRAW
    • Decode Nikon RAW(NEF)
      • TODO
    • Reading custom TIFF tags.
  • Read DNG data from memory.

Writing

  • DNG and TIFF
    • LosslessJPEG compression

Supported DNG files

Here is the list of supported DNG files.

  • Sigma sd Quattro H
    • Uncompressed RGB 12bit image.
  • iPhone DNG
  • Apple ProRAW
    • Lossless JPEG 12bit
    • Semantic map
  • Black magic DNG
    • CinemaDNG(lossy compression) is not supported.
  • Canon CR2(experimental)
  • Magic lantern DNG
  • 8-bit TIFF image
    • LZW compressed 8-bit image.
  • 16-bit uncompressed TIFF image
  • 32-bit uncompressed TIFF image
  • OpCodeList
    • GainMap

Usage

Loading DNG

#include <cstdio>
#include <cstdlib>
#include <iostream>

// Define TINY_DNG_LOADER_IMPLEMENTATION and STB_IMAGE_IMPLEMENTATION in only one *.cc
#define TINY_DNG_LOADER_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION

// Enable ZIP compression(through miniz library)
// Please don't forget copying&adding `miniz.c` and `miniz.h` to your project.
// #define TINY_DNG_LOADER_ENABLE_ZIP

// Uncomment these two lines if you want to use system provided zlib library, not miniz
// #define TINY_DNG_LOADER_USE_SYSTEM_ZLIB
// #include <zlib.h>
#include "tiny_dng_loader.h"

int main(int argc, char **argv) {
  std::string input_filename = "colorchart.dng";

  if (argc > 1) {
    input_filename = std::string(argv[1]);
  }

  std::string warn, err;
  std::vector<tinydng::DNGImage> images;

  // List of custom field infos. This is optional and can be empty.
  std::vector<tinydng::FieldInfo> custom_field_lists;

  // Loads all images(IFD) in the DNG file to `images` array.
  // You can use `LoadDNGFromMemory` API to load DNG image from a memory.
  bool ret = tinydng::LoadDNG(input_filename.c_str(), custom_field_lists, &images, &warn, &err);


  if (!warn.empty()) {
    std::cout << "Warn: " << warn << std::endl;
  }

  if (!err.empty()) {
    std::cerr << "Err: " << err << std::endl;
  }

  if (ret) {
    for (size_t i = 0; i < images.size(); i++) {
      const tinydng::DNGImage &image = images[i];
;
      std::cout << "width = " << image.width << std::endl;
      std::cout << "height = " << image.height << std::endl;
      std::cout << "bits per piexl = " << image.bits_per_sample << std::endl;
      std::cout << "bits per piexl(original) = " << image.bits_per_sample_original << std::endl;
      std::cout << "samples per pixel = " << image.samples_per_pixel << std::endl;

    }
  }

  return EXIT_SUCCESS;
}

Writing DNG(and TIFF)

See examples/dngwriter and https://github.com/storyboardcreativity/zraw-decoder for more details.

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <iostream>

#define TINY_DNG_WRITER_IMPLEMENTATION
#include "tiny_dng_writer.h"

static void CreateRGBImage(tinydngwriter::DNGImage *dng_image,
                        const unsigned short basecol) {
  unsigned int image_width = 512;
  unsigned int image_height = 512;
  dng_image->SetSubfileType(false, false, false);
  dng_image->SetImageWidth(image_width);
  dng_image->SetImageLength(image_height);
  dng_image->SetRowsPerStrip(image_height);

  // SetSamplesPerPixel must be called before SetBitsPerSample()
  dng_image->SetSamplesPerPixel(3);
  uint16_t bps[3] = {16, 16, 16};
  dng_image->SetBitsPerSample(3, bps);
  dng_image->SetPlanarConfig(tinydngwriter::PLANARCONFIG_CONTIG);
  dng_image->SetCompression(tinydngwriter::COMPRESSION_NONE);
  dng_image->SetPhotometric(tinydngwriter::PHOTOMETRIC_RGB);
  dng_image->SetXResolution(1.0);
  dng_image->SetYResolution(1.2); // fractioal test
  dng_image->SetResolutionUnit(tinydngwriter::RESUNIT_NONE);
  dng_image->SetImageDescription("bora");

  std::vector<unsigned short> buf;
  buf.resize(image_width * image_height * 3);

  for (size_t y = 0; y < image_height; y++) {
    for (size_t x = 0; x < image_width; x++) {
      buf[3 * (y * image_width + x) + 0] = static_cast<unsigned short>(x % 512);
      buf[3 * (y * image_width + x) + 1] = static_cast<unsigned short>(y % 512);
      buf[3 * (y * image_width + x) + 2] = basecol;
    }
  }

  dng_image->SetImageData(reinterpret_cast<unsigned char *>(buf.data()),
                          buf.size() * sizeof(unsigned short));
}

int main(int argc, char **argv) {
  std::string output_filename = "output.dng";

  if (argc < 1) {
    std::cout << argv[0] << " <output.dng>" << std::endl;
  }

  if (argc > 1) {
    output_filename = std::string(argv[1]);
  }

  // TinyDNGWriter supports both BigEndian and LittleEndian TIFF.
  // Default = BigEndian.
  bool big_endian = false;

  if (argc > 2) {
    big_endian = bool(atoi(argv[2]));
  }

  {
    // DNGWriter supports multiple DNG images.
    // First create DNG image data, then pass it to DNGWriter with AddImage API.
    tinydngwriter::DNGImage dng_image0;
    dng_image0.SetBigEndian(big_endian);
    tinydngwriter::DNGImage dng_image1;
    dng_image1.SetBigEndian(big_endian);

    CreateRGBImage(&dng_image0, 12000);
    CreateRGBImage(&dng_image1, 42000);

    tinydngwriter::DNGWriter dng_writer(big_endian);
    bool ret = dng_writer.AddImage(&dng_image0);
    assert(ret);

    ret = dng_writer.AddImage(&dng_image1);
    assert(ret);

    std::string err;
    ret = dng_writer.WriteToFile(output_filename.c_str(), &err);

    if (!err.empty()) {
      std::cerr << err;
    }

    if (!ret) {
      return EXIT_FAILURE;
    }

    std::cout << "Wrote : " << output_filename << std::endl;
  }

  return EXIT_SUCCESS;
}

Customizations

  • TINY_DNG_LOADER_USE_THREAD : Enable threaded loading(requires C++11)
  • TINY_DNG_LOADER_ENABLE_ZIP : Enable decoding AdobeDeflate image(Currently, tiled RGB image only).
    • TINY_DNG_LOADER_USE_SYSTEM_ZLIB : Use system's zlib library instead of miniz.
  • TINY_DNG_LOADER_DEBUG : Enable debug printf(developer only!)
  • TINY_DNG_LOADER_NO_STB_IMAGE_INCLUDE : Do not include stb_image.h inside of tiny_dng_loader.h.
  • TINY_DNG_LOADER_NO_STDIO : Disable printf, cout/cerr.

Examples

Python binding(Experimental)

Build native module.

Install pybind11.

$ python -m pip install pybind11

Then,

$ python setup.py build

or

$ python -m pip install build
$ python -m build .

Currently no PyPI package is available.

See experimental/python for sample python code.

Fuzzing test

Resource

Here is the list of great articles on how to decode RAW file and how to develop RAW image.

TODO

  • Move to C++11.
    • Drop C++03 support.
  • Parse semantic map tags in Apple ProRAW.
  • Add DNG header load only mode
  • Parse more DNG headers
  • Parse more custom DNG(TIFF) tags
  • lossy DNG
  • Improve DNG writer
    • Support compression(LJPEG)
  • Support Big TIFF(4GB+)
  • Decode Nikon RAW(NEF)
  • Improve Canon RAW decoding
  • Optimimze lossless JPEG decoding
  • Delayed load of tiled image.

License

TinyDNG is licensed under MIT license.

TinyDNG uses the following third party libraries.

  • liblj92(Lossless JPEG library) : (c) Andrew Baldwin 2014. MIT license. https://bitbucket.org/baldand/mlrawviewer.git
  • stb_image : Public domain image loader.
  • lzw.hpp : Author: Guilherme R. Lampert. Public domain LZW decoder.
  • miniz : Copyright 2013-2014 RAD Game Tools and Valve Software. Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC MIT license. See miniz.LICENSE

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

tinydng-0.0.0.tar.gz (204.2 kB view details)

Uploaded Source

File details

Details for the file tinydng-0.0.0.tar.gz.

File metadata

  • Download URL: tinydng-0.0.0.tar.gz
  • Upload date:
  • Size: 204.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.10.12

File hashes

Hashes for tinydng-0.0.0.tar.gz
Algorithm Hash digest
SHA256 e536ff0ebaf4f287df36ca3157f1814dd4a1339f569e865dbeed3036571e8d67
MD5 2587f38cf59c814bbd6fdfd1e99f7bf9
BLAKE2b-256 058dbcb29c3b88563f9bae6d62cea70151f139a4fcbb7ceb0045efbde601abf8

See more details on using hashes here.

Supported by

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