Skip to content

Instantly share code, notes, and snippets.

@alex-luxonis
Last active December 23, 2022 23:07
Show Gist options
  • Save alex-luxonis/a60d2d29692b74491838e72b69bdddc2 to your computer and use it in GitHub Desktop.
Save alex-luxonis/a60d2d29692b74491838e72b69bdddc2 to your computer and use it in GitHub Desktop.
RAW headerless image to DNG format converter
# Note: install requirement: python3 -m pip install pidng
# If you get: SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats
# for now you may need to use python older than 3.10, so for example:
# python3.9 -m pip install pidng
# python3.9 to_dng.py capture_raw_1920x1080_93_10bit.bw -rot
from pidng.core import RAW2DNG, DNGTags, Tag
from pidng.defs import *
import numpy as np
import argparse
import struct
import sys
parser = argparse.ArgumentParser()
parser.add_argument('file_name_or_path')
parser.add_argument('-rot', '--rotated', action='store_true',
help='To be set if the image was captured with `ROTATE_180_DEG`, '
'or it originates from an OAK-1 with default orientation')
args = parser.parse_args()
rawFile = args.file_name_or_path
print('Input file name:', rawFile)
if 1:
# Try to take image specs from file name, expecting:
# capture_raw_WWWWxHHHH_xxxxx_xxxxx_10bit.bw
name = rawFile.split('/')[-1]
try:
# capture_raw_WWWWxHHHH_...
width, height = [int(i) for i in name.split('_')[2].split('x')]
except ValueError:
# raw_WWWWxHHHH_...
width, height = [int(i) for i in name.split('_')[1].split('x')]
bpp = int(name.split('_')[-1].split('bit')[0])
else:
width = 4056
height = 3040
bpp= 10
print(f'>>> width: {width}, height: {height}, bpp: {bpp}')
# load raw data into 16-bit numpy array.
numPixels = width*height
rf = open(rawFile, mode='rb')
rawData = struct.unpack("H"*numPixels,rf.read(2*numPixels))
rawFlatImage = np.zeros(numPixels, dtype=np.uint16)
rawFlatImage[:] = rawData[:]
rawImage = np.reshape(rawFlatImage,(height,width))
# Next line commented out, as our image is already LSbit-justified
#rawImage = rawImage >> (16 - bpp)
# uncalibrated color matrix, just for demo. TODO
ccm1 = [[1000, 1000], [ 0, 1000], [ 0, 1000],
[ 0, 1000], [1000, 1000], [ 0, 1000],
[ 0, 1000], [ 0, 1000], [1000, 1000]]
# set DNG tags.
t = DNGTags()
t.set(Tag.ImageWidth, width)
t.set(Tag.ImageLength, height)
t.set(Tag.TileWidth, width)
t.set(Tag.TileLength, height)
t.set(Tag.Orientation, Orientation.Horizontal)
t.set(Tag.PhotometricInterpretation, PhotometricInterpretation.Color_Filter_Array)
t.set(Tag.SamplesPerPixel, 1)
t.set(Tag.BitsPerSample, bpp)
t.set(Tag.CFARepeatPatternDim, [2,2])
t.set(Tag.CFAPattern, CFAPattern.BGGR if args.rotated else CFAPattern.RGGB)
# TODO should this be 1024 for 10-bit?
t.set(Tag.BlackLevel, (4096 >> (16 - bpp)))
t.set(Tag.WhiteLevel, ((1 << bpp) -1) )
t.set(Tag.ColorMatrix1, ccm1)
t.set(Tag.CalibrationIlluminant1, CalibrationIlluminant.D65)
t.set(Tag.AsShotNeutral, [[1,1],[1,1],[1,1]])
t.set(Tag.BaselineExposure, [[-150,100]])
t.set(Tag.Make, "Camera Brand")
t.set(Tag.Model, "Camera Model")
t.set(Tag.DNGVersion, DNGVersion.V1_4)
t.set(Tag.DNGBackwardVersion, DNGVersion.V1_2)
t.set(Tag.PreviewColorSpace, PreviewColorSpace.sRGB)
# save to dng file.
r = RAW2DNG()
r.options(t, path="", compress=True)
r.convert(rawImage, filename="output")
print('Created: output.dng')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment