1use super::types::{Array, ConstArray, TagType, TypeByte, TypeIfd, TypeLong, TypeNumber, TypeOrientation, TypeSRational, TypeSShort, TypeShort, TypeSonyToneCurve, TypeString};
2use super::{Ifd, TagId, TiffError, TiffRead};
3
4use std::io::{Read, Seek};
5
6pub trait SimpleTag {
7 type Type: TagType;
8
9 const ID: TagId;
10 const NAME: &'static str;
11}
12
13pub struct ImageWidth;
14pub struct ImageLength;
15pub struct BitsPerSample;
16pub struct Compression;
17pub struct PhotometricInterpretation;
18pub struct Make;
19pub struct Model;
20pub struct StripOffsets;
21pub struct Orientation;
22pub struct SamplesPerPixel;
23pub struct RowsPerStrip;
24pub struct StripByteCounts;
25pub struct SubIfd;
26pub struct JpegOffset;
27pub struct JpegLength;
28pub struct SonyDataOffset;
29pub struct SonyToneCurve;
30pub struct BlackLevel;
31pub struct WhiteBalanceRggbLevels;
32pub struct CfaPatternDim;
33pub struct CfaPattern;
34pub struct ColorMatrix1;
35pub struct ColorMatrix2;
36
37impl SimpleTag for ImageWidth {
38 type Type = TypeNumber;
39
40 const ID: TagId = TagId::ImageWidth;
41 const NAME: &'static str = "Image Width";
42}
43
44impl SimpleTag for ImageLength {
45 type Type = TypeNumber;
46
47 const ID: TagId = TagId::ImageLength;
48 const NAME: &'static str = "Image Length";
49}
50
51impl SimpleTag for BitsPerSample {
52 type Type = TypeShort;
53
54 const ID: TagId = TagId::BitsPerSample;
55 const NAME: &'static str = "Bits per Sample";
56}
57
58impl SimpleTag for Compression {
59 type Type = TypeShort;
60
61 const ID: TagId = TagId::Compression;
62 const NAME: &'static str = "Compression";
63}
64
65impl SimpleTag for PhotometricInterpretation {
66 type Type = TypeShort;
67
68 const ID: TagId = TagId::PhotometricInterpretation;
69 const NAME: &'static str = "Photometric Interpretation";
70}
71
72impl SimpleTag for Make {
73 type Type = TypeString;
74
75 const ID: TagId = TagId::Make;
76 const NAME: &'static str = "Make";
77}
78
79impl SimpleTag for Model {
80 type Type = TypeString;
81
82 const ID: TagId = TagId::Model;
83 const NAME: &'static str = "Model";
84}
85
86impl SimpleTag for StripOffsets {
87 type Type = Array<TypeNumber>;
88
89 const ID: TagId = TagId::StripOffsets;
90 const NAME: &'static str = "Strip Offsets";
91}
92
93impl SimpleTag for Orientation {
94 type Type = TypeOrientation;
95
96 const ID: TagId = TagId::Orientation;
97 const NAME: &'static str = "Orientation";
98}
99
100impl SimpleTag for SamplesPerPixel {
101 type Type = TypeShort;
102
103 const ID: TagId = TagId::SamplesPerPixel;
104 const NAME: &'static str = "Samples per Pixel";
105}
106
107impl SimpleTag for RowsPerStrip {
108 type Type = TypeNumber;
109
110 const ID: TagId = TagId::RowsPerStrip;
111 const NAME: &'static str = "Rows per Strip";
112}
113
114impl SimpleTag for StripByteCounts {
115 type Type = Array<TypeNumber>;
116
117 const ID: TagId = TagId::StripByteCounts;
118 const NAME: &'static str = "Strip Byte Counts";
119}
120
121impl SimpleTag for SubIfd {
122 type Type = TypeIfd;
123
124 const ID: TagId = TagId::SubIfd;
125 const NAME: &'static str = "SubIFD";
126}
127
128impl SimpleTag for JpegOffset {
129 type Type = TypeLong;
130
131 const ID: TagId = TagId::JpegOffset;
132 const NAME: &'static str = "Jpeg Offset";
133}
134
135impl SimpleTag for JpegLength {
136 type Type = TypeLong;
137
138 const ID: TagId = TagId::JpegLength;
139 const NAME: &'static str = "Jpeg Length";
140}
141
142impl SimpleTag for CfaPatternDim {
143 type Type = ConstArray<TypeShort, 2>;
144
145 const ID: TagId = TagId::CfaPatternDim;
146 const NAME: &'static str = "CFA Pattern Dimension";
147}
148
149impl SimpleTag for CfaPattern {
150 type Type = Array<TypeByte>;
151
152 const ID: TagId = TagId::CfaPattern;
153 const NAME: &'static str = "CFA Pattern";
154}
155
156impl SimpleTag for ColorMatrix1 {
157 type Type = Array<TypeSRational>;
158
159 const ID: TagId = TagId::ColorMatrix1;
160 const NAME: &'static str = "Color Matrix 1";
161}
162
163impl SimpleTag for ColorMatrix2 {
164 type Type = Array<TypeSRational>;
165
166 const ID: TagId = TagId::ColorMatrix2;
167 const NAME: &'static str = "Color Matrix 2";
168}
169
170impl SimpleTag for SonyDataOffset {
171 type Type = TypeLong;
172
173 const ID: TagId = TagId::SubIfd;
174 const NAME: &'static str = "Sony Data Offset";
175}
176
177impl SimpleTag for SonyToneCurve {
178 type Type = TypeSonyToneCurve;
179
180 const ID: TagId = TagId::SonyToneCurve;
181 const NAME: &'static str = "Sony Tone Curve";
182}
183
184impl SimpleTag for BlackLevel {
185 type Type = ConstArray<TypeShort, 4>;
186
187 const ID: TagId = TagId::BlackLevel;
188 const NAME: &'static str = "Black Level";
189}
190
191impl SimpleTag for WhiteBalanceRggbLevels {
192 type Type = ConstArray<TypeSShort, 4>;
193
194 const ID: TagId = TagId::WhiteBalanceRggbLevels;
195 const NAME: &'static str = "White Balance Levels (RGGB)";
196}
197
198pub trait Tag {
199 type Output;
200
201 fn get<R: Read + Seek>(ifd: &Ifd, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError>;
202}
203
204impl<T: SimpleTag> Tag for T {
205 type Output = <T::Type as TagType>::Output;
206
207 fn get<R: Read + Seek>(ifd: &Ifd, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
208 let tag_id = T::ID;
209 let index: u32 = ifd.iter().position(|x| x.tag == tag_id).ok_or(TiffError::MissingTag)?.try_into()?;
210
211 file.seek_from_start(ifd.current_ifd_offset + 2 + 12 * index + 2)?;
212 T::Type::read(file)
213 }
214}
215
216impl<T: Tag> Tag for Option<T> {
217 type Output = Option<T::Output>;
218
219 fn get<R: Read + Seek>(ifd: &Ifd, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
220 let result = T::get(ifd, file);
221
222 match result {
223 Err(TiffError::MissingTag) => Ok(None),
224 Ok(x) => Ok(Some(x)),
225 Err(x) => Err(x),
226 }
227 }
228}