diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.analyze.yaml new file mode 100644 index 000000000..0b2476e7b --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 12630528 + fileName: SIGMA_FP_647_20240229_000001_4k_12bit.DNG + digest: 2d77060fa07d37393576e1837f64c9d8 +data: + metadata: + rawParams: + rawWidth: 3856 + rawHeight: 2170 + bitDepth: 12 + cropArea: + p: + x: 8 + y: 5 + d: + w: 3832 + h: 2155 + activeArea: + p: + x: 0 + y: 0 + d: + w: 3856 + h: 2170 + blacklevels: + levels: + - 262007/1024 + - 262007/1024 + - 262007/1024 + - 262007/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 4095 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:08:33" + create_date: "2024:02:29 19:08:33" + modify_date: "2024:02:29 19:08:33" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.digest.txt new file mode 100644 index 000000000..adac6fd8e --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG.digest.txt @@ -0,0 +1 @@ +04be71fe1169c290f283b35e47f73c35 diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.analyze.yaml new file mode 100644 index 000000000..d45aee5fe --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 10538496 + fileName: SIGMA_FP_648_20240229_000001_4k_10bit.DNG + digest: 77095aa4828573317eda9cb0e5fef0f3 +data: + metadata: + rawParams: + rawWidth: 3856 + rawHeight: 2170 + bitDepth: 10 + cropArea: + p: + x: 8 + y: 5 + d: + w: 3832 + h: 2155 + activeArea: + p: + x: 0 + y: 0 + d: + w: 3856 + h: 2170 + blacklevels: + levels: + - 65527/1024 + - 65527/1024 + - 65527/1024 + - 65527/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 1023 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:09:07" + create_date: "2024:02:29 19:09:07" + modify_date: "2024:02:29 19:09:07" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.digest.txt new file mode 100644 index 000000000..307752c7a --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG.digest.txt @@ -0,0 +1 @@ +6d1e45fe37210b8444d34fe4ccc3f3d2 diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.analyze.yaml new file mode 100644 index 000000000..01b634844 --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 8447488 + fileName: SIGMA_FP_650_20240229_000001_4k_8bit.DNG + digest: 4ca46f410a807e2448b5aa3fb48a0ba7 +data: + metadata: + rawParams: + rawWidth: 3856 + rawHeight: 2170 + bitDepth: 16 + cropArea: + p: + x: 8 + y: 5 + d: + w: 3832 + h: 2155 + activeArea: + p: + x: 0 + y: 0 + d: + w: 3856 + h: 2170 + blacklevels: + levels: + - 262147/1024 + - 262147/1024 + - 262147/1024 + - 262147/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 4095 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:09:29" + create_date: "2024:02:29 19:09:29" + modify_date: "2024:02:29 19:09:29" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.digest.txt new file mode 100644 index 000000000..83c90ee92 --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG.digest.txt @@ -0,0 +1 @@ +8cd2388050fcadfa03af3b569d88df20 diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.analyze.yaml new file mode 100644 index 000000000..7151ff459 --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 3244544 + fileName: SIGMA_FP_651_20240229_000001_2k_12bit.DNG + digest: 66a26765d76976252d1e6d81a0741761 +data: + metadata: + rawParams: + rawWidth: 1936 + rawHeight: 1090 + bitDepth: 12 + cropArea: + p: + x: 8 + y: 5 + d: + w: 1912 + h: 1075 + activeArea: + p: + x: 0 + y: 0 + d: + w: 1936 + h: 1090 + blacklevels: + levels: + - 262002/1024 + - 262002/1024 + - 262002/1024 + - 262002/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 4095 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:09:57" + create_date: "2024:02:29 19:09:57" + modify_date: "2024:02:29 19:09:57" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.digest.txt new file mode 100644 index 000000000..34009b9d8 --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG.digest.txt @@ -0,0 +1 @@ +7e551610db51ac0a664f0504a021b833 diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.analyze.yaml new file mode 100644 index 000000000..66f1caa2f --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 2716672 + fileName: SIGMA_FP_652_20240229_000001_2k_10bit.DNG + digest: 1e39cd2daeedadf3110d040ab2920533 +data: + metadata: + rawParams: + rawWidth: 1936 + rawHeight: 1090 + bitDepth: 10 + cropArea: + p: + x: 8 + y: 5 + d: + w: 1912 + h: 1075 + activeArea: + p: + x: 0 + y: 0 + d: + w: 1936 + h: 1090 + blacklevels: + levels: + - 65516/1024 + - 65516/1024 + - 65516/1024 + - 65516/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 1023 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:10:08" + create_date: "2024:02:29 19:10:08" + modify_date: "2024:02:29 19:10:08" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.digest.txt new file mode 100644 index 000000000..8751a540c --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG.digest.txt @@ -0,0 +1 @@ +8c0533cc938467a648638bdc36379faa diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.analyze.yaml new file mode 100644 index 000000000..7fabc22ca --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 2190336 + fileName: SIGMA_FP_653_20240229_000001_2k_8bit.DNG + digest: b87d31fca1d42315b5705e09ec27d261 +data: + metadata: + rawParams: + rawWidth: 1936 + rawHeight: 1090 + bitDepth: 16 + cropArea: + p: + x: 8 + y: 5 + d: + w: 1912 + h: 1075 + activeArea: + p: + x: 0 + y: 0 + d: + w: 1936 + h: 1090 + blacklevels: + levels: + - 262184/1024 + - 262184/1024 + - 262184/1024 + - 262184/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 4095 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:10:21" + create_date: "2024:02:29 19:10:21" + modify_date: "2024:02:29 19:10:21" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 365946/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.digest.txt new file mode 100644 index 000000000..11bb46f6d --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG.digest.txt @@ -0,0 +1 @@ +1bbf78933cab2573847e3ad2df8e954d diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.analyze.yaml b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.analyze.yaml new file mode 100644 index 000000000..b5a47bd20 --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.analyze.yaml @@ -0,0 +1,93 @@ +--- +file: + fileSize: 34676310 + fileName: SIGMA_FP_6k_14bit.DNG + digest: 6aa22d4676d449f05af8809ade4147dd +data: + metadata: + rawParams: + rawWidth: 6064 + rawHeight: 4042 + bitDepth: 14 + cropArea: + p: + x: 32 + y: 21 + d: + w: 5968 + h: 3979 + activeArea: + p: + x: 0 + y: 0 + d: + w: 6064 + h: 4042 + blacklevels: + levels: + - 1048576/1024 + - 1048576/1024 + - 1048576/1024 + - 1048576/1024 + cpp: 1 + width: 2 + height: 2 + whitelevels: + - 16383 + wbCoeffs: + - 1.9726561 + - 1.0 + - 1.671875 + - ~ + rawMetadata: + exif: + orientation: 1 + copyright: "" + artist: "" + lens_spec: ~ + exposure_time: 1/50 + fnumber: 0/10 + aperture_value: 0/65534 + brightness_value: ~ + iso_speed_ratings: 3200 + iso_speed: ~ + recommended_exposure_index: 3200 + sensitivity_type: 2 + exposure_bias: 0/10 + date_time_original: "2024:02:29 19:07:48" + create_date: "2024:02:29 19:07:48" + modify_date: "2024:02:29 19:07:48" + exposure_program: 1 + timezone_offset: ~ + offset_time: "-04:00" + offset_time_original: "-04:00" + offset_time_digitized: "-04:00" + sub_sec_time: ~ + sub_sec_time_original: ~ + sub_sec_time_digitized: ~ + shutter_speed_value: 369914/65535 + max_aperture_value: 0/65534 + subject_distance: 0/10 + metering_mode: 5 + light_source: 0 + flash: 48 + focal_length: 0/10 + image_number: ~ + color_space: 1 + flash_energy: ~ + exposure_mode: 1 + white_balance: 1 + scene_capture_type: 0 + subject_distance_range: ~ + owner_name: ~ + serial_number: "91415977" + lens_serial_number: ~ + lens_make: ~ + lens_model: ~ + gps: ~ + model: SIGMA fp + make: SIGMA + lens: ~ + unique_image_id: ~ + rating: ~ + diff --git a/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.digest.txt b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.digest.txt new file mode 100644 index 000000000..c117dc6ef --- /dev/null +++ b/rawler/data/testdata/cameras/Sigma/SIGMA fp/cinemadng/SIGMA_FP_6k_14bit.DNG.digest.txt @@ -0,0 +1 @@ +a75614d62c5c5cd3c1a62747476b7a3a diff --git a/rawler/src/bits.rs b/rawler/src/bits.rs index 98bd343be..2cddd52c1 100644 --- a/rawler/src/bits.rs +++ b/rawler/src/bits.rs @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LGPL-2.1 // Copyright 2021 Daniel Vogelbacher +use std::iter::repeat; + use byteorder::{BigEndian, ByteOrder, LittleEndian}; use serde::{Deserialize, Serialize}; @@ -177,6 +179,17 @@ impl LookupTable { LookupTable { table: tbl } } + pub fn new_with_bits(table: &[u16], bits: u32) -> LookupTable { + if table.len() >= 1 << bits { + Self::new(table) + } else { + let mut expanded = Vec::with_capacity(1 << bits); + expanded.extend_from_slice(table); + expanded.extend(repeat(table.last().expect("Need one element")).take((1 << bits) - table.len())); + Self::new(&expanded) + } + } + // pub fn lookup(&self, value: u16) -> u16 { // let (val, _, _) = self.table[value as usize]; // val diff --git a/rawler/src/decoders/dng.rs b/rawler/src/decoders/dng.rs index eeb1fc4ba..a1cfc88ba 100644 --- a/rawler/src/decoders/dng.rs +++ b/rawler/src/decoders/dng.rs @@ -1,12 +1,14 @@ use std::cmp; use std::f32::NAN; +use image::EncodableLayout; use image::ImageBuffer; use image::Rgb; use crate::alloc_image_ok; use crate::alloc_image_plain; use crate::bits::Endian; +use crate::bits::LEu32; use crate::bits::LookupTable; use crate::cfa::*; use crate::decoders::*; @@ -50,12 +52,19 @@ impl<'a> Decoder for DngDecoder<'a> { let cpp = fetch_tiff_tag!(raw, TiffCommonTag::SamplesPerPixel).force_usize(0); let bits = fetch_tiff_tag!(raw, TiffCommonTag::BitsPerSample).force_u32(0); - let image = match fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_u32(0) { + let mut image = match fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_u32(0) { 1 => self.decode_uncompressed(file, raw, width * cpp, height, dummy)?, 7 => self.decode_compressed(file, raw, width * cpp, height, cpp, dummy)?, c => return Err(RawlerError::DecoderFailed(format!("Don't know how to read DNGs with compression {}", c))), }; + if let Some(lintable) = raw.get_entry(TiffCommonTag::Linearization) { + if bits != 8 && fetch_tiff_tag!(raw, TiffCommonTag::Compression).force_u32(0) != 1 { + // 8 bit uncompressed data is already read delinearized + apply_linearization(&mut image, &lintable.value, bits); + } + } + let orientation = Orientation::from_tiff(self.tiff.root_ifd()); let mut cam = self.make_camera(raw, width, height)?; @@ -205,7 +214,12 @@ impl<'a> DngDecoder<'a> { let linear = fetch_tiff_tag!(raw, TiffCommonTag::PhotometricInt).force_usize(0) == 34892; let cfa = if linear { CFA::default() } else { self.get_cfa(raw)? }; let color_matrix = self.get_color_matrix()?; - let real_bps = raw.get_entry(TiffCommonTag::BitsPerSample).map(|v| v.force_usize(0)).unwrap_or(16); + let real_bps = if raw.has_entry(TiffCommonTag::Linearization) { + // If DNG contains linearization table, output is always 16 bits + 16 + } else { + raw.get_entry(TiffCommonTag::BitsPerSample).map(|v| v.force_usize(0)).unwrap_or(16) + }; Ok(Camera { clean_make: make.clone(), @@ -347,8 +361,8 @@ impl<'a> DngDecoder<'a> { (Endian::Little, 16) => Ok(decode_16le(&src, width, height, dummy)), // 12 Bits, DNG spec says it must be always encoded as big-endian (_, 12) => Ok(decode_12be(&src, width, height, dummy)), - // TODO: implement 10 bit BE, but no real world samples so far - //(_, 10) => Ok(decode_10be(&src, width, height, dummy)), + // 10 Bits, DNG spec says it must be always encoded as big-endian + (_, 10) => Ok(decode_10be(&src, width, height, dummy)), // 8 bits with linearization table (_, 8) if raw.has_entry(TiffCommonTag::Linearization) => { let linearization = fetch_tiff_tag!(self.tiff, TiffCommonTag::Linearization); @@ -361,8 +375,12 @@ impl<'a> DngDecoder<'a> { }; Ok(decode_8bit_wtable(&src, &curve, width, height, dummy)) } + // 8 bits (_, 8) => Ok(decode_8bit(&src, width, height, dummy)), - (_, bps) => Err(format_args!("DNG: Don't know about {} bps images", bps).into()), + // Generic MSB decoder for exotic packed bit sizes + (_, bps) if bps > 0 && bps < 16 => Ok(decode_generic_msb(&src, width, height, bps, dummy)), + // Unhandled bits + (_, bps) => Err(format_args!("DNG: Don't know how to handle DNG with {} bps", bps).into()), } } @@ -443,3 +461,20 @@ impl<'a> DngDecoder<'a> { } } } + +fn apply_linearization(image: &mut PixU16, tbl: &Value, bits: u32) { + match tbl { + Value::Short(points) => { + let table = LookupTable::new_with_bits(points, bits); + image.pixel_rows_mut().for_each(|row| { + let mut random = LEu32(row.as_bytes(), 0); + row.iter_mut().for_each(|p| { + *p = table.dither(*p, &mut random); + }) + }); + } + _ => { + panic!("Unsupported linear table"); + } + } +} diff --git a/rawler/src/decoders/unwrapped.rs b/rawler/src/decoders/unwrapped.rs index 78c19d601..17fee6bc6 100644 --- a/rawler/src/decoders/unwrapped.rs +++ b/rawler/src/decoders/unwrapped.rs @@ -31,7 +31,7 @@ pub fn decode_unwrapped(file: &mut RawFile) -> Result { Ok(RawImageData::Integer(decode_8bit_wtable(data, &table, width, height, false).into_inner())) } 1 => Ok(RawImageData::Integer(decode_10le_lsb16(data, width, height, false).into_inner())), - 2 => Ok(RawImageData::Integer(decode_10le(data, width, height, false).into_inner())), + 2 => Ok(RawImageData::Integer(decode_10be(data, width, height, false).into_inner())), 3 => Ok(RawImageData::Integer(decode_12be(data, width, height, false).into_inner())), 4 => Ok(RawImageData::Integer(decode_12be_msb16(data, width, height, false).into_inner())), 5 => Ok(RawImageData::Integer(decode_12le_16bitaligned(data, width, height, false).into_inner())), diff --git a/rawler/src/packed.rs b/rawler/src/packed.rs index 428f6b436..bf5ef022a 100644 --- a/rawler/src/packed.rs +++ b/rawler/src/packed.rs @@ -1,4 +1,10 @@ -use crate::{alloc_image, bits::*, decoders::decode_threaded, pixarray::PixU16}; +use crate::{ + alloc_image, + bits::*, + decoders::decode_threaded, + pixarray::PixU16, + pumps::{BitPump, BitPumpLSB, BitPumpMSB}, +}; pub fn decode_8bit_wtable(buf: &[u8], tbl: &LookupTable, width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( @@ -63,7 +69,7 @@ pub fn decode_10le_lsb16(buf: &[u8], width: usize, height: usize, dummy: bool) - ) } -pub fn decode_10le(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { +pub fn decode_10be(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU16 { decode_threaded( width, height, @@ -80,7 +86,7 @@ pub fn decode_10le(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU o[0] = g1 << 2 | g2 >> 6; o[1] = (g2 & 0x3f) << 4 | g3 >> 4; - o[2] = (g3 & 0x0f) << 6 | g3 >> 2; + o[2] = (g3 & 0x0f) << 6 | g4 >> 2; o[3] = (g4 & 0x03) << 8 | g5; } }), @@ -561,3 +567,25 @@ pub fn decode_16be(buf: &[u8], width: usize, height: usize, dummy: bool) -> PixU }), ) } + +pub fn decode_generic_msb(buf: &[u8], width: usize, height: usize, bits: u32, dummy: bool) -> PixU16 { + assert!(bits <= 16); + let mut pix: PixU16 = alloc_image!(width, height, dummy); + assert!(8 * buf.len() >= width * height * bits as usize, "buf has not enough bits"); + let mut pump = BitPumpMSB::new(buf); + for p in pix.pixels_mut() { + *p = pump.get_bits(bits) as u16; + } + pix +} + +pub fn decode_generic_lsb(buf: &[u8], width: usize, height: usize, bits: u32, dummy: bool) -> PixU16 { + assert!(bits <= 16); + let mut pix: PixU16 = alloc_image!(width, height, dummy); + assert!(8 * buf.len() >= width * height * bits as usize, "buf has not enough bits"); + let mut pump = BitPumpLSB::new(buf); + for p in pix.pixels_mut() { + *p = pump.get_bits(bits) as u16; + } + pix +} diff --git a/rawler/tests/cameras/mod.rs b/rawler/tests/cameras/mod.rs index 5192c298f..ad14afd19 100644 --- a/rawler/tests/cameras/mod.rs +++ b/rawler/tests/cameras/mod.rs @@ -2410,6 +2410,15 @@ mod camera_dmc_zs40_raw_modes { mod camera_dmc_zs60_raw_modes { super::camera_file_check!("Panasonic", "DMC-ZS60", cam_dmc_zs60_iso_400_panasonic_raw_1_4896x3672_rw2, "raw_modes/DMC-ZS60_ISO_400_Panasonic RAW 1_4896x3672.RW2"); } +mod camera_sigma_fp_cinemadng { + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_6k_14bit_dng, "cinemadng/SIGMA_FP_6k_14bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_653_20240229_000001_2k_8bit_dng, "cinemadng/SIGMA_FP_653_20240229_000001_2k_8bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_648_20240229_000001_4k_10bit_dng, "cinemadng/SIGMA_FP_648_20240229_000001_4k_10bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_647_20240229_000001_4k_12bit_dng, "cinemadng/SIGMA_FP_647_20240229_000001_4k_12bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_652_20240229_000001_2k_10bit_dng, "cinemadng/SIGMA_FP_652_20240229_000001_2k_10bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_650_20240229_000001_4k_8bit_dng, "cinemadng/SIGMA_FP_650_20240229_000001_4k_8bit.DNG"); + super::camera_file_check!("Sigma", "SIGMA fp", cam_sigma_fp_651_20240229_000001_2k_12bit_dng, "cinemadng/SIGMA_FP_651_20240229_000001_2k_12bit.DNG"); +} mod camera_c_lux_raw_modes { super::camera_file_check!("Leica", "C-Lux", cam_c_lux_iso_125_4fmt_5472x3648_rwl, "raw_modes/C-Lux_ISO_125_4fmt_5472x3648.RWL"); } diff --git a/rawler/tests/issues/mod.rs b/rawler/tests/issues/mod.rs index 5242f57b5..d496bafb8 100644 --- a/rawler/tests/issues/mod.rs +++ b/rawler/tests/issues/mod.rs @@ -14,7 +14,7 @@ use rawler::{analyze::raw_pixels_digest, decoders::RawDecodeParams}; fn dnglab_354_dng_mismatch_tile_dim_vs_ljpeg_sof_dim() -> std::result::Result<(), Box> { let path = rawdb_file("issues/dnglab_354/dnglab_354.dng"); let digest = raw_pixels_digest(path, RawDecodeParams::default())?; - check_md5_equal(digest, "44e5e63b152719c0ff9eae9e25cdc275"); + check_md5_equal(digest, "e5fcd3fd81a3f8e2d9709b92f3b8f546"); Ok(()) } diff --git a/rawler/tests/supported_rawdb_sets.txt b/rawler/tests/supported_rawdb_sets.txt index 342ae0324..16e9fb7c0 100644 --- a/rawler/tests/supported_rawdb_sets.txt +++ b/rawler/tests/supported_rawdb_sets.txt @@ -617,6 +617,7 @@ cameras/Panasonic/DMC-TZ81/raw_modes cameras/Panasonic/DMC-ZS100/raw_modes cameras/Panasonic/DMC-ZS40/raw_modes cameras/Panasonic/DMC-ZS60/raw_modes +cameras/Sigma/SIGMA fp/cinemadng cameras/Leica/C-Lux/raw_modes cameras/Leica/C Typ 112/raw_modes cameras/Leica/Digilux 2/raw_modes