Add basic thumbnail extraction to Rawkit (#2659)
* Add `CompressionValue` * Rename `Transform` to `OrientationValue` * Add basic thumbnail extraction * Add `ThumbnailFormat` * fmt + clippy fixes
This commit is contained in:
parent
d441a02e72
commit
c21ccf5284
|
|
@ -1,7 +1,7 @@
|
|||
use crate::tiff::Ifd;
|
||||
use crate::tiff::file::TiffRead;
|
||||
use crate::tiff::tags::SonyDataOffset;
|
||||
use crate::{RawImage, SubtractBlack, Transform};
|
||||
use crate::{OrientationValue, RawImage, SubtractBlack};
|
||||
use bitstream_io::{BE, BitRead, BitReader, Endianness};
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ pub fn decode_a100<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage
|
|||
#[allow(unreachable_code)]
|
||||
maximum: (1 << 12) - 1,
|
||||
black: SubtractBlack::None,
|
||||
transform: Transform::Horizontal,
|
||||
orientation: OrientationValue::Horizontal,
|
||||
camera_model: None,
|
||||
camera_white_balance: None,
|
||||
white_balance: None,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::tiff::file::{Endian, TiffRead};
|
||||
use crate::tiff::tags::{BitsPerSample, CfaPattern, CfaPatternDim, Compression, ImageLength, ImageWidth, SonyToneCurve, StripByteCounts, StripOffsets, Tag, WhiteBalanceRggbLevels};
|
||||
use crate::tiff::values::CurveLookupTable;
|
||||
use crate::tiff::values::{CompressionValue, CurveLookupTable};
|
||||
use crate::tiff::{Ifd, TiffError};
|
||||
use crate::{RawImage, SubtractBlack, Transform};
|
||||
use crate::{OrientationValue, RawImage, SubtractBlack};
|
||||
use rawkit_proc_macros::Tag;
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
|
|||
|
||||
assert!(ifd.strip_offsets.len() == ifd.strip_byte_counts.len());
|
||||
assert!(ifd.strip_offsets.len() == 1);
|
||||
assert!(ifd.compression == 32767);
|
||||
assert!(ifd.compression == CompressionValue::Sony_ARW_Compressed);
|
||||
|
||||
let image_width: usize = ifd.image_width.try_into().unwrap();
|
||||
let image_height: usize = ifd.image_height.try_into().unwrap();
|
||||
|
|
@ -49,7 +49,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
|
|||
cfa_pattern: ifd.cfa_pattern.try_into().unwrap(),
|
||||
maximum: (1 << 14) - 1,
|
||||
black: SubtractBlack::CfaGrid([512, 512, 512, 512]), // TODO: Find the correct way to do this
|
||||
transform: Transform::Horizontal,
|
||||
orientation: OrientationValue::Horizontal,
|
||||
camera_model: None,
|
||||
camera_white_balance: ifd.white_balance_levels.map(|arr| arr.map(|x| x as f64)),
|
||||
white_balance: None,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::tiff::file::TiffRead;
|
||||
use crate::tiff::tags::{BitsPerSample, BlackLevel, CfaPattern, CfaPatternDim, Compression, ImageLength, ImageWidth, RowsPerStrip, StripByteCounts, StripOffsets, Tag, WhiteBalanceRggbLevels};
|
||||
use crate::tiff::values::CompressionValue;
|
||||
use crate::tiff::{Ifd, TiffError};
|
||||
use crate::{RawImage, SubtractBlack, Transform};
|
||||
use crate::{OrientationValue, RawImage, SubtractBlack};
|
||||
use rawkit_proc_macros::Tag;
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
|
|
@ -26,7 +27,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
|
|||
|
||||
assert!(ifd.strip_offsets.len() == ifd.strip_byte_counts.len());
|
||||
assert!(ifd.strip_offsets.len() == 1);
|
||||
assert!(ifd.compression == 1); // 1 is the value for uncompressed format
|
||||
assert!(ifd.compression == CompressionValue::Uncompressed);
|
||||
|
||||
let image_width: usize = ifd.image_width.try_into().unwrap();
|
||||
let image_height: usize = ifd.image_height.try_into().unwrap();
|
||||
|
|
@ -57,7 +58,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
|
|||
cfa_pattern: ifd.cfa_pattern.try_into().unwrap(),
|
||||
maximum: if bits_per_sample == 16 { u16::MAX } else { (1 << bits_per_sample) - 1 },
|
||||
black: SubtractBlack::CfaGrid(ifd.black_level),
|
||||
transform: Transform::Horizontal,
|
||||
orientation: OrientationValue::Horizontal,
|
||||
camera_model: None,
|
||||
camera_white_balance: ifd.white_balance_levels.map(|arr| arr.map(|x| x as f64)),
|
||||
white_balance: None,
|
||||
|
|
|
|||
|
|
@ -12,13 +12,24 @@ use rawkit_proc_macros::Tag;
|
|||
use std::io::{Read, Seek};
|
||||
use thiserror::Error;
|
||||
use tiff::file::TiffRead;
|
||||
use tiff::tags::{Compression, ImageLength, ImageWidth, Orientation, StripByteCounts, SubIfd, Tag};
|
||||
use tiff::values::Transform;
|
||||
use tiff::tags::{Compression, ImageLength, ImageWidth, Orientation, StripByteCounts, SubIfd, Tag, ThumbnailLength, ThumbnailOffset};
|
||||
use tiff::values::{CompressionValue, OrientationValue};
|
||||
use tiff::{Ifd, TiffError};
|
||||
|
||||
pub(crate) const CHANNELS_IN_RGB: usize = 3;
|
||||
pub(crate) type Histogram = [[usize; 0x2000]; CHANNELS_IN_RGB];
|
||||
|
||||
pub enum ThumbnailFormat {
|
||||
Jpeg,
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
/// A thumbnail image extracted from the raw file. This is usually a JPEG image.
|
||||
pub struct ThumbnailImage {
|
||||
pub data: Vec<u8>,
|
||||
pub format: ThumbnailFormat,
|
||||
}
|
||||
|
||||
/// The amount of black level to be subtracted from Raw Image.
|
||||
pub enum SubtractBlack {
|
||||
/// Don't subtract any value.
|
||||
|
|
@ -48,7 +59,7 @@ pub struct RawImage {
|
|||
pub cfa_pattern: [u8; 4],
|
||||
|
||||
/// Transformation to be applied to negate the orientation of camera.
|
||||
pub transform: Transform,
|
||||
pub orientation: OrientationValue,
|
||||
|
||||
/// The maximum possible value of pixel that the camera sensor could give.
|
||||
pub maximum: u16,
|
||||
|
|
@ -97,8 +108,8 @@ pub struct Image<T> {
|
|||
|
||||
/// The transformation required to orient the image correctly.
|
||||
///
|
||||
/// This will be [`Transform::Horizontal`] after the transform step is applied.
|
||||
pub transform: Transform,
|
||||
/// This will be [`OrientationValue::Horizontal`] after the orientation step is applied.
|
||||
pub orientation: OrientationValue,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -119,7 +130,7 @@ impl RawImage {
|
|||
let ifd = Ifd::new_first_ifd(&mut file)?;
|
||||
|
||||
let camera_model = metadata::identify::identify_camera_model(&ifd, &mut file).unwrap();
|
||||
let transform = ifd.get_value::<Orientation, _>(&mut file)?;
|
||||
let orientation = ifd.get_value::<Orientation, _>(&mut file)?;
|
||||
|
||||
let mut raw_image = if camera_model.model == "DSLR-A100" {
|
||||
decoder::arw1::decode_a100(ifd, &mut file)
|
||||
|
|
@ -127,7 +138,7 @@ impl RawImage {
|
|||
let sub_ifd = ifd.get_value::<SubIfd, _>(&mut file)?;
|
||||
let arw_ifd = sub_ifd.get_value::<ArwIfd, _>(&mut file)?;
|
||||
|
||||
if arw_ifd.compression == 1 {
|
||||
if arw_ifd.compression == CompressionValue::Uncompressed {
|
||||
decoder::uncompressed::decode(sub_ifd, &mut file)
|
||||
} else if arw_ifd.strip_byte_counts[0] == arw_ifd.image_width * arw_ifd.image_height {
|
||||
decoder::arw2::decode(sub_ifd, &mut file)
|
||||
|
|
@ -138,13 +149,38 @@ impl RawImage {
|
|||
};
|
||||
|
||||
raw_image.camera_model = Some(camera_model);
|
||||
raw_image.transform = transform;
|
||||
raw_image.orientation = orientation;
|
||||
|
||||
raw_image.calculate_conversion_matrices();
|
||||
|
||||
Ok(raw_image)
|
||||
}
|
||||
|
||||
/// Extracts the thumbnail image from the raw file.
|
||||
pub fn extract_thumbnail<R: Read + Seek>(reader: &mut R) -> Result<ThumbnailImage, DecoderError> {
|
||||
let mut file = TiffRead::new(reader)?;
|
||||
let ifd = Ifd::new_first_ifd(&mut file)?;
|
||||
|
||||
// TODO: ARW files Store the thumbnail offset and length in the first IFD. Add support for other file types in the future.
|
||||
let thumbnail_offset = ifd.get_value::<ThumbnailOffset, _>(&mut file)?;
|
||||
let thumbnail_length = ifd.get_value::<ThumbnailLength, _>(&mut file)?;
|
||||
file.seek_from_start(thumbnail_offset)?;
|
||||
|
||||
let mut thumbnail_data = vec![0; thumbnail_length as usize];
|
||||
file.read_exact(&mut thumbnail_data)?;
|
||||
|
||||
// Check the first two bytes to determine the format of the thumbnail.
|
||||
// JPEG format starts with 0xFF, 0xD8.
|
||||
if thumbnail_data[0..2] == [0xFF, 0xD8] {
|
||||
Ok(ThumbnailImage {
|
||||
data: thumbnail_data,
|
||||
format: ThumbnailFormat::Jpeg,
|
||||
})
|
||||
} else {
|
||||
Err(DecoderError::UnsupportedThumbnailFormat)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the [`RawImage`] to an [`Image`] with 8 bit resolution for each channel.
|
||||
///
|
||||
/// Applies all the processing steps to finally get RGB pixel data.
|
||||
|
|
@ -156,7 +192,7 @@ impl RawImage {
|
|||
data: image.data.iter().map(|x| (x >> 8) as u8).collect(),
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
transform: image.transform,
|
||||
orientation: image.orientation,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +210,7 @@ impl RawImage {
|
|||
let image = raw_image.demosaic_and_apply((convert_to_rgb, &mut record_histogram));
|
||||
|
||||
let gamma_correction = image.gamma_correction_fn(&record_histogram.histogram);
|
||||
if image.transform == Transform::Horizontal {
|
||||
if image.orientation == OrientationValue::Horizontal {
|
||||
image.apply(gamma_correction)
|
||||
} else {
|
||||
image.transform_and_apply(gamma_correction)
|
||||
|
|
@ -211,7 +247,7 @@ impl RawImage {
|
|||
data: image,
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
transform: self.transform,
|
||||
orientation: self.orientation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -232,7 +268,7 @@ impl Image<u16> {
|
|||
|
||||
pub fn transform_and_apply(self, mut transform: impl PixelTransform) -> Image<u16> {
|
||||
let mut image = vec![0; self.width * self.height * 3];
|
||||
let (width, height, iter) = self.transform_iter();
|
||||
let (width, height, iter) = self.orientation_iter();
|
||||
for Pixel { values, row, column } in iter.map(|mut pixel| {
|
||||
pixel.values = transform.apply(pixel);
|
||||
pixel
|
||||
|
|
@ -246,7 +282,7 @@ impl Image<u16> {
|
|||
data: image,
|
||||
width,
|
||||
height,
|
||||
transform: Transform::Horizontal,
|
||||
orientation: OrientationValue::Horizontal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -259,4 +295,6 @@ pub enum DecoderError {
|
|||
ConversionError(#[from] std::num::TryFromIntError),
|
||||
#[error("An IO Error ocurred")]
|
||||
IoError(#[from] std::io::Error),
|
||||
#[error("The thumbnail format is unsupported")]
|
||||
UnsupportedThumbnailFormat,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
use crate::{Image, Pixel, Transform};
|
||||
use crate::{Image, OrientationValue, Pixel};
|
||||
|
||||
impl Image<u16> {
|
||||
pub fn transform_iter(&self) -> (usize, usize, impl Iterator<Item = Pixel> + use<'_>) {
|
||||
let (final_width, final_height) = if self.transform.will_swap_coordinates() {
|
||||
pub fn orientation_iter(&self) -> (usize, usize, impl Iterator<Item = Pixel> + use<'_>) {
|
||||
let (final_width, final_height) = if self.orientation.will_swap_coordinates() {
|
||||
(self.height, self.width)
|
||||
} else {
|
||||
(self.width, self.height)
|
||||
};
|
||||
|
||||
let index_0_0 = inverse_transform_index(self.transform, 0, 0, self.width, self.height);
|
||||
let index_0_1 = inverse_transform_index(self.transform, 0, 1, self.width, self.height);
|
||||
let index_1_0 = inverse_transform_index(self.transform, 1, 0, self.width, self.height);
|
||||
let index_0_0 = inverse_orientation_index(self.orientation, 0, 0, self.width, self.height);
|
||||
let index_0_1 = inverse_orientation_index(self.orientation, 0, 1, self.width, self.height);
|
||||
let index_1_0 = inverse_orientation_index(self.orientation, 1, 0, self.width, self.height);
|
||||
|
||||
let column_step = (index_0_1.0 - index_0_0.0, index_0_1.1 - index_0_0.1);
|
||||
let row_step = (index_1_0.0 - index_0_0.0, index_1_0.1 - index_0_0.1);
|
||||
|
|
@ -42,16 +42,16 @@ impl Image<u16> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn inverse_transform_index(transform: Transform, mut row: usize, mut column: usize, width: usize, height: usize) -> (i64, i64) {
|
||||
let value = match transform {
|
||||
Transform::Horizontal => 0,
|
||||
Transform::MirrorHorizontal => 1,
|
||||
Transform::Rotate180 => 3,
|
||||
Transform::MirrorVertical => 2,
|
||||
Transform::MirrorHorizontalRotate270 => 4,
|
||||
Transform::Rotate90 => 6,
|
||||
Transform::MirrorHorizontalRotate90 => 7,
|
||||
Transform::Rotate270 => 5,
|
||||
pub fn inverse_orientation_index(orientation: OrientationValue, mut row: usize, mut column: usize, width: usize, height: usize) -> (i64, i64) {
|
||||
let value = match orientation {
|
||||
OrientationValue::Horizontal => 0,
|
||||
OrientationValue::MirrorHorizontal => 1,
|
||||
OrientationValue::Rotate180 => 3,
|
||||
OrientationValue::MirrorVertical => 2,
|
||||
OrientationValue::MirrorHorizontalRotate270 => 4,
|
||||
OrientationValue::Rotate90 => 6,
|
||||
OrientationValue::MirrorHorizontalRotate90 => 7,
|
||||
OrientationValue::Rotate270 => 5,
|
||||
};
|
||||
|
||||
if value & 4 != 0 {
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ pub enum TagId {
|
|||
RowsPerStrip = 0x116,
|
||||
StripByteCounts = 0x117,
|
||||
SubIfd = 0x14a,
|
||||
JpegOffset = 0x201,
|
||||
JpegLength = 0x202,
|
||||
ThumbnailOffset = 0x201,
|
||||
ThumbnailLength = 0x202,
|
||||
SonyToneCurve = 0x7010,
|
||||
BlackLevel = 0x7310,
|
||||
WhiteBalanceRggbLevels = 0x7313,
|
||||
|
|
@ -88,10 +88,10 @@ impl Ifd {
|
|||
}
|
||||
|
||||
file.seek_from_start(offset)?;
|
||||
let num = file.read_u16()?;
|
||||
let num_entries = file.read_u16()?;
|
||||
|
||||
let mut ifd_entries = Vec::with_capacity(num.into());
|
||||
for _ in 0..num {
|
||||
let mut ifd_entries = Vec::with_capacity(num_entries.into());
|
||||
for _ in 0..num_entries {
|
||||
let tag = file.read_u16()?.into();
|
||||
let the_type = file.read_u16()?.into();
|
||||
let count = file.read_u32()?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use super::types::{Array, ConstArray, TagType, TypeByte, TypeIfd, TypeLong, TypeNumber, TypeOrientation, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
|
||||
use super::types::{Array, ConstArray, TagType, TypeByte, TypeCompression, TypeIfd, TypeLong, TypeNumber, TypeOrientation, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
|
||||
use super::{Ifd, TagId, TiffError, TiffRead};
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
|
|
@ -22,8 +22,8 @@ pub struct SamplesPerPixel;
|
|||
pub struct RowsPerStrip;
|
||||
pub struct StripByteCounts;
|
||||
pub struct SubIfd;
|
||||
pub struct JpegOffset;
|
||||
pub struct JpegLength;
|
||||
pub struct ThumbnailOffset;
|
||||
pub struct ThumbnailLength;
|
||||
pub struct SonyDataOffset;
|
||||
pub struct SonyToneCurve;
|
||||
pub struct BlackLevel;
|
||||
|
|
@ -55,7 +55,7 @@ impl SimpleTag for BitsPerSample {
|
|||
}
|
||||
|
||||
impl SimpleTag for Compression {
|
||||
type Type = TypeShort;
|
||||
type Type = TypeCompression;
|
||||
|
||||
const ID: TagId = TagId::Compression;
|
||||
const NAME: &'static str = "Compression";
|
||||
|
|
@ -124,17 +124,17 @@ impl SimpleTag for SubIfd {
|
|||
const NAME: &'static str = "SubIFD";
|
||||
}
|
||||
|
||||
impl SimpleTag for JpegOffset {
|
||||
impl SimpleTag for ThumbnailOffset {
|
||||
type Type = TypeLong;
|
||||
|
||||
const ID: TagId = TagId::JpegOffset;
|
||||
const ID: TagId = TagId::ThumbnailOffset;
|
||||
const NAME: &'static str = "Jpeg Offset";
|
||||
}
|
||||
|
||||
impl SimpleTag for JpegLength {
|
||||
impl SimpleTag for ThumbnailLength {
|
||||
type Type = TypeLong;
|
||||
|
||||
const ID: TagId = TagId::JpegLength;
|
||||
const ID: TagId = TagId::ThumbnailLength;
|
||||
const NAME: &'static str = "Jpeg Length";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use super::file::TiffRead;
|
||||
use super::values::{CurveLookupTable, Rational, Transform};
|
||||
use super::values::{CompressionValue, CurveLookupTable, OrientationValue, Rational};
|
||||
use super::{Ifd, IfdTagType, TiffError};
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
|
|
@ -350,6 +350,7 @@ impl<T: PrimitiveType, const N: usize> TagType for ConstArray<T, N> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TypeCompression;
|
||||
pub struct TypeString;
|
||||
pub struct TypeSonyToneCurve;
|
||||
pub struct TypeOrientation;
|
||||
|
|
@ -376,19 +377,17 @@ impl TagType for TypeSonyToneCurve {
|
|||
}
|
||||
|
||||
impl TagType for TypeOrientation {
|
||||
type Output = Transform;
|
||||
type Output = OrientationValue;
|
||||
|
||||
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
|
||||
Ok(match TypeShort::read(file)? {
|
||||
1 => Transform::Horizontal,
|
||||
2 => Transform::MirrorHorizontal,
|
||||
3 => Transform::Rotate180,
|
||||
4 => Transform::MirrorVertical,
|
||||
5 => Transform::MirrorHorizontalRotate270,
|
||||
6 => Transform::Rotate90,
|
||||
7 => Transform::MirrorHorizontalRotate90,
|
||||
8 => Transform::Rotate270,
|
||||
_ => return Err(TiffError::InvalidValue),
|
||||
})
|
||||
OrientationValue::try_from(TypeShort::read(file)?).map_err(|_| TiffError::InvalidValue)
|
||||
}
|
||||
}
|
||||
|
||||
impl TagType for TypeCompression {
|
||||
type Output = CompressionValue;
|
||||
|
||||
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
|
||||
CompressionValue::try_from(TypeShort::read(file)?).map_err(|_| TiffError::InvalidValue)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
|
||||
pub trait ToFloat {
|
||||
fn to_float(&self) -> f64;
|
||||
}
|
||||
|
|
@ -51,29 +53,80 @@ impl CurveLookupTable {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Transform {
|
||||
Horizontal,
|
||||
MirrorHorizontal,
|
||||
Rotate180,
|
||||
MirrorVertical,
|
||||
MirrorHorizontalRotate270,
|
||||
Rotate90,
|
||||
MirrorHorizontalRotate90,
|
||||
Rotate270,
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, IntoPrimitive, TryFromPrimitive)]
|
||||
#[repr(u16)]
|
||||
pub enum OrientationValue {
|
||||
Horizontal = 1,
|
||||
MirrorHorizontal = 2,
|
||||
Rotate180 = 3,
|
||||
MirrorVertical = 4,
|
||||
MirrorHorizontalRotate270 = 5,
|
||||
Rotate90 = 6,
|
||||
MirrorHorizontalRotate90 = 7,
|
||||
Rotate270 = 8,
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
impl OrientationValue {
|
||||
pub fn is_identity(&self) -> bool {
|
||||
*self == Transform::Horizontal
|
||||
*self == Self::Horizontal
|
||||
}
|
||||
|
||||
pub fn will_swap_coordinates(&self) -> bool {
|
||||
use Transform as Tr;
|
||||
|
||||
match *self {
|
||||
Tr::Horizontal | Tr::MirrorHorizontal | Tr::Rotate180 | Tr::MirrorVertical => false,
|
||||
Tr::MirrorHorizontalRotate270 | Tr::Rotate90 | Tr::MirrorHorizontalRotate90 | Tr::Rotate270 => true,
|
||||
Self::Horizontal | Self::MirrorHorizontal | Self::Rotate180 | Self::MirrorVertical => false,
|
||||
Self::MirrorHorizontalRotate270 | Self::Rotate90 | Self::MirrorHorizontalRotate90 | Self::Rotate270 => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
#[repr(u16)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum CompressionValue {
|
||||
Uncompressed = 1,
|
||||
CCITT_1D = 2,
|
||||
T4 = 3,
|
||||
T6 = 4,
|
||||
LZW = 5,
|
||||
JPEG_Old = 6,
|
||||
JPEG = 7,
|
||||
AdobeDeflate = 8,
|
||||
JBIG_BW = 9,
|
||||
JBIG_Color = 10,
|
||||
KODAK_626 = 262,
|
||||
Next = 32766,
|
||||
Sony_ARW_Compressed = 32767,
|
||||
Packed_Raw = 32769,
|
||||
Samsung_SRW_Compressed = 32770,
|
||||
CCIRLEW = 32771,
|
||||
Samsung_SRW_Compressed_2 = 32772,
|
||||
PackedBits = 32773,
|
||||
Thunderscan = 32809,
|
||||
Kodak_KDC_Compressed = 32867,
|
||||
IT8CTPAD = 32895,
|
||||
IT8LW = 32896,
|
||||
IT8MP = 32897,
|
||||
IT8BL = 32898,
|
||||
PixarFilm = 32908,
|
||||
PixarLog = 32909,
|
||||
Deflate = 32946,
|
||||
DCS = 32947,
|
||||
AperioJPEG2K_YCbCr = 33003,
|
||||
AperioJPEG2K_RGB = 33005,
|
||||
JBIG = 34661,
|
||||
SGILog = 34676,
|
||||
SGILog24 = 34677,
|
||||
JPEG2K = 34712,
|
||||
NikonNEFCompressed = 34713,
|
||||
JBIG2_TIFF_FX = 34715,
|
||||
ESRI_Lerc = 34887,
|
||||
LossyJPEG = 34892,
|
||||
LZMA2 = 34925,
|
||||
PNG = 34933,
|
||||
JPEG_XR = 34934,
|
||||
Zstd = 50000,
|
||||
WebP = 50001,
|
||||
JPEG_XL = 52546,
|
||||
Kodak_DCR_Compressed = 65000,
|
||||
Pentax_PEF_Compressed = 65535,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue