-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathExif.hs
More file actions
224 lines (212 loc) · 5.82 KB
/
Exif.hs
File metadata and controls
224 lines (212 loc) · 5.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
-- | This module provide a totally partial and incomplete maping
-- of Exif values. Used for Tiff parsing and reused for Exif extraction.
module Codec.Picture.Metadata.Exif ( ExifTag( .. )
, ExifData( .. )
, tagOfWord16
, word16OfTag
, isInIFD0
) where
import Control.DeepSeq( NFData( .. ) )
import Data.Int( Int32 )
import Data.Word( Word16, Word32 )
import qualified Data.Vector as V
import qualified Data.ByteString as B
-- | Tag values used for exif fields. Completly incomplete
data ExifTag
= TagPhotometricInterpretation
| TagCompression -- ^ Short type
| TagImageWidth -- ^ Short or long type
| TagImageLength -- ^ Short or long type
| TagXResolution -- ^ Rational type
| TagYResolution -- ^ Rational type
| TagResolutionUnit -- ^ Short type
| TagRowPerStrip -- ^ Short or long type
| TagStripByteCounts -- ^ Short or long
| TagStripOffsets -- ^ Short or long
| TagBitsPerSample -- ^ Short
| TagColorMap -- ^ Short
| TagTileWidth
| TagTileLength
| TagTileOffset
| TagTileByteCount
| TagSamplesPerPixel -- ^ Short
| TagArtist
| TagDocumentName
| TagSoftware
| TagPlanarConfiguration -- ^ Short
| TagOrientation
| TagSampleFormat -- ^ Short
| TagInkSet
| TagSubfileType
| TagFillOrder
| TagYCbCrCoeff
| TagYCbCrSubsampling
| TagYCbCrPositioning
| TagReferenceBlackWhite
| TagXPosition
| TagYPosition
| TagExtraSample
| TagImageDescription
| TagPredictor
| TagCopyright
| TagMake
| TagModel
| TagDateTime
| TagGPSInfo
| TagLightSource -- ^ Short
| TagFlash -- ^ Short
| TagJpegProc
| TagJPEGInterchangeFormat
| TagJPEGInterchangeFormatLength
| TagJPEGRestartInterval
| TagJPEGLosslessPredictors
| TagJPEGPointTransforms
| TagJPEGQTables
| TagJPEGDCTables
| TagJPEGACTables
| TagExifOffset
| TagUnknown !Word16
deriving (Eq, Ord, Show)
-- | Convert a value to it's corresponding Exif tag.
-- Will often be written as 'TagUnknown'
tagOfWord16 :: Word16 -> ExifTag
tagOfWord16 v = case v of
255 -> TagSubfileType
256 -> TagImageWidth
257 -> TagImageLength
258 -> TagBitsPerSample
259 -> TagCompression
262 -> TagPhotometricInterpretation
266 -> TagFillOrder
269 -> TagDocumentName
270 -> TagImageDescription
271 -> TagMake
272 -> TagModel
273 -> TagStripOffsets
274 -> TagOrientation
277 -> TagSamplesPerPixel
278 -> TagRowPerStrip
279 -> TagStripByteCounts
282 -> TagXResolution
283 -> TagYResolution
284 -> TagPlanarConfiguration
286 -> TagXPosition
287 -> TagYPosition
296 -> TagResolutionUnit
305 -> TagSoftware
306 -> TagDateTime
315 -> TagArtist
317 -> TagPredictor
320 -> TagColorMap
322 -> TagTileWidth
323 -> TagTileLength
324 -> TagTileOffset
325 -> TagTileByteCount
332 -> TagInkSet
338 -> TagExtraSample
339 -> TagSampleFormat
529 -> TagYCbCrCoeff
512 -> TagJpegProc
513 -> TagJPEGInterchangeFormat
514 -> TagJPEGInterchangeFormatLength
515 -> TagJPEGRestartInterval
517 -> TagJPEGLosslessPredictors
518 -> TagJPEGPointTransforms
519 -> TagJPEGQTables
520 -> TagJPEGDCTables
521 -> TagJPEGACTables
530 -> TagYCbCrSubsampling
531 -> TagYCbCrPositioning
532 -> TagReferenceBlackWhite
33432 -> TagCopyright
34665 -> TagExifOffset
34853 -> TagGPSInfo
37384 -> TagLightSource
37385 -> TagFlash
vv -> TagUnknown vv
-- | Convert a tag to it's corresponding value.
word16OfTag :: ExifTag -> Word16
word16OfTag t = case t of
TagSubfileType -> 255
TagImageWidth -> 256
TagImageLength -> 257
TagBitsPerSample -> 258
TagCompression -> 259
TagPhotometricInterpretation -> 262
TagFillOrder -> 266
TagDocumentName -> 269
TagImageDescription -> 270
TagMake -> 271
TagModel -> 272
TagStripOffsets -> 273
TagOrientation -> 274
TagSamplesPerPixel -> 277
TagRowPerStrip -> 278
TagStripByteCounts -> 279
TagXResolution -> 282
TagYResolution -> 283
TagPlanarConfiguration -> 284
TagXPosition -> 286
TagYPosition -> 287
TagResolutionUnit -> 296
TagSoftware -> 305
TagDateTime -> 306
TagArtist -> 315
TagPredictor -> 317
TagColorMap -> 320
TagTileWidth -> 322
TagTileLength -> 323
TagTileOffset -> 324
TagTileByteCount -> 325
TagInkSet -> 332
TagExtraSample -> 338
TagSampleFormat -> 339
TagYCbCrCoeff -> 529
TagJpegProc -> 512
TagJPEGInterchangeFormat -> 513
TagJPEGInterchangeFormatLength -> 514
TagJPEGRestartInterval -> 515
TagJPEGLosslessPredictors -> 517
TagJPEGPointTransforms -> 518
TagJPEGQTables -> 519
TagJPEGDCTables -> 520
TagJPEGACTables -> 521
TagYCbCrSubsampling -> 530
TagYCbCrPositioning -> 531
TagReferenceBlackWhite -> 532
TagCopyright -> 33432
TagExifOffset -> 34665
TagGPSInfo -> 34853
TagLightSource -> 37384
TagFlash -> 37385
(TagUnknown v) -> v
isInIFD0 :: ExifTag -> Bool
isInIFD0 t = word16OfTag t <= lastTag || isRedirectTag where
lastTag = word16OfTag TagCopyright
isRedirectTag = t `elem` [TagExifOffset, TagGPSInfo]
-- | Possible data held by an Exif tag
data ExifData
= ExifNone
| ExifLong !Word32
| ExifShort !Word16
| ExifFloat !Float
| ExifDouble !Double
| ExifString !B.ByteString
| ExifUndefined !B.ByteString
| ExifShorts !(V.Vector Word16)
| ExifLongs !(V.Vector Word32)
| ExifFloats !(V.Vector Double)
| ExifDoubles !(V.Vector Double)
| ExifRational !Word32 !Word32
| ExifSignedRational !Int32 !Int32
| ExifIFD ![(ExifTag, ExifData)]
deriving Show
instance NFData ExifTag where
rnf a = a `seq` ()
instance NFData ExifData where
rnf (ExifIFD ifds) = rnf ifds `seq` ()
rnf (ExifLongs l) = rnf l `seq` ()
rnf (ExifShorts l) = rnf l `seq` ()
rnf (ExifFloats l) = rnf l `seq` ()
rnf (ExifDoubles l) = rnf l `seq` ()
rnf a = a `seq` ()