# -*- coding: utf-8 -*-
"""
Adobe DNG SDK Conversion Process
================================
Defines various objects implementing raw conversion based on *Adobe DNG SDK*
and *dcraw*:
- :func:`colour_hdri.convert_raw_files_to_dng_files`
- :func:`colour_hdri.convert_dng_files_to_intermediate_files`
- :func:`colour_hdri.read_dng_files_exif_tags`
"""
from __future__ import division, unicode_literals
import logging
import numpy as np
import os
import platform
import re
import shlex
import subprocess
from copy import deepcopy
from colour.utilities import CaseInsensitiveMapping, warning
from colour.utilities.documentation import DocstringText
from colour_hdri.utilities import (ExifTag, parse_exif_array,
parse_exif_numeric, parse_exif_string,
path_exists, read_exif_tags)
__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015-2018 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'
__all__ = [
'RAW_CONVERTER', 'RAW_CONVERSION_ARGUMENTS', 'RAW_D_CONVERSION_ARGUMENTS',
'DNG_CONVERTER', 'DNG_CONVERSION_ARGUMENTS', 'DNG_EXIF_TAGS_BINDING',
'convert_raw_files_to_dng_files',
'convert_dng_files_to_intermediate_files', 'read_dng_files_exif_tags'
]
LOGGER = logging.getLogger(__name__)
RAW_CONVERTER = DocstringText('dcraw')
RAW_CONVERTER.__doc__ = """
Command line raw conversion application, usually Dave Coffin's *dcraw*.
RAW_CONVERTER : unicode
"""
RAW_CONVERSION_ARGUMENTS = DocstringText('-t 0 -D -W -4 -T "{0}"')
if platform.system() in ('Windows', 'Microsoft'):
RAW_CONVERSION_ARGUMENTS = RAW_CONVERSION_ARGUMENTS.replace('"', '')
RAW_CONVERSION_ARGUMENTS.__doc__ = """
Arguments for the command line raw conversion application for non demosaiced
linear *tiff* file format output.
RAW_CONVERSION_ARGUMENTS : unicode
"""
RAW_D_CONVERSION_ARGUMENTS = DocstringText(
'-t 0 -H 1 -r 1 1 1 1 -4 -q 3 -o 0 -T "{0}"')
if platform.system() in ('Windows', 'Microsoft'):
RAW_D_CONVERSION_ARGUMENTS = RAW_D_CONVERSION_ARGUMENTS.replace('"', '')
RAW_D_CONVERSION_ARGUMENTS.__doc__ = """
Arguments for the command line raw conversion application for demosaiced
linear *tiff* file format output.
RAW_D_CONVERSION_ARGUMENTS : unicode
"""
if platform.system() == 'Darwin':
DNG_CONVERTER = DocstringText(
'/Applications/Adobe DNG Converter.app/Contents/'
'MacOS/Adobe DNG Converter')
elif platform.system() in ('Windows', 'Microsoft'):
DNG_CONVERTER = DocstringText(
'C:\\Program Files (x86)\\Adobe\\Adobe DNG Converter.exe')
else:
DNG_CONVERTER = None
warning('"Adobe DNG Converter" is not available on your platform!')
if DNG_CONVERTER is not None:
DNG_CONVERTER.__doc__ = """
Command line *DNG* conversion application, usually *Adobe DNG Converter*.
DNG_CONVERTER : unicode
"""
DNG_CONVERSION_ARGUMENTS = DocstringText('-l -d "{0}" "{1}"')
if platform.system() in ('Windows', 'Microsoft'):
DNG_CONVERSION_ARGUMENTS = DNG_CONVERSION_ARGUMENTS.replace('"', '')
DNG_CONVERSION_ARGUMENTS.__doc__ = """
Arguments for the command line *dng* conversion application.
DNG_CONVERSION_ARGUMENTS : unicode
"""
DNG_EXIF_TAGS_BINDING = CaseInsensitiveMapping({
'EXIF':
CaseInsensitiveMapping({
'Make': (parse_exif_string, None),
'Camera Model Name': (parse_exif_string, None),
'Camera Serial Number': (parse_exif_string, None),
'Lens Model': (parse_exif_string, None),
'DNG Lens Info': (parse_exif_string, None),
'Focal Length': (parse_exif_numeric, None),
'Exposure Time': (parse_exif_numeric, None),
'F Number': (parse_exif_numeric, None),
'ISO': (parse_exif_numeric, None),
'CFA Pattern 2': (lambda x: parse_exif_array(x, np.int_), None),
'CFA Plane Color': (lambda x: parse_exif_array(x, np.int_), None),
'Black Level Repeat Dim': (lambda x: parse_exif_array(x, np.int_),
None),
'Black Level': (lambda x: parse_exif_array(x, np.int_), None),
'White Level': (lambda x: parse_exif_array(x, np.int_), None),
'Samples Per Pixel': (lambda x: parse_exif_numeric(x, np.int_),
None),
'Active Area': (lambda x: parse_exif_array(x, np.int_), None),
'Orientation': (lambda x: parse_exif_numeric(x, np.int_), None),
'Camera Calibration Sig': (parse_exif_string, None),
'Profile Calibration Sig': (parse_exif_string, None),
'Calibration Illuminant 1': (
lambda x: parse_exif_numeric(x, np.int_), 17),
'Calibration Illuminant 2': (
lambda x: parse_exif_numeric(x, np.int_), 21),
'Color Matrix 1': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Color Matrix 2': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Camera Calibration 1': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Camera Calibration 2': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Analog Balance': (lambda x: parse_exif_array(x, np.float_),
'1 1 1'),
'Reduction Matrix 1': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Reduction Matrix 2': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Forward Matrix 1': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'Forward Matrix 2': (
lambda x: parse_exif_array(x, np.float_, (3, 3)),
'1 0 0 0 1 0 0 0 1'),
'As Shot Neutral': (lambda x: parse_exif_array(x, np.float_),
'1 1 1'),
'Baseline Exposure': (lambda x: parse_exif_numeric(x, np.float_),
None),
'Baseline Noise': (lambda x: parse_exif_numeric(x, np.float_),
None)
})
})
DNG_EXIF_TAGS_BINDING.__doc__ = """
Exif tags binding for a *dng* file.
DNG_EXIF_TAGS_BINDING : CaseInsensitiveMapping
"""
[docs]def convert_raw_files_to_dng_files(raw_files, output_directory):
"""
Converts given raw files to *dng* files using given output directory.
Parameters
----------
raw_files : array_like
Raw files to convert to *dng* files.
output_directory : unicode
Output directory.
Returns
-------
list
*dng* files.
"""
dng_files = []
for raw_file in raw_files:
raw_file_extension = os.path.splitext(raw_file)[1]
dng_file = os.path.join(
output_directory,
os.path.basename(
re.sub('{0}$'.format(raw_file_extension), '.dng', raw_file)))
if path_exists(dng_file):
os.remove(dng_file)
LOGGER.info(
'Converting "{0}" file to "{1}" file.'.format(raw_file, dng_file))
command = [DNG_CONVERTER] + shlex.split(
DNG_CONVERSION_ARGUMENTS.format(output_directory, raw_file),
posix=(False
if platform.system() in ('Windows', 'Microsoft') else True))
subprocess.call(command)
dng_files.append(dng_file)
return dng_files