-- | 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 (ExifTag -> ExifTag -> Bool
(ExifTag -> ExifTag -> Bool)
-> (ExifTag -> ExifTag -> Bool) -> Eq ExifTag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ExifTag -> ExifTag -> Bool
$c/= :: ExifTag -> ExifTag -> Bool
== :: ExifTag -> ExifTag -> Bool
$c== :: ExifTag -> ExifTag -> Bool
Eq, Eq ExifTag
Eq ExifTag
-> (ExifTag -> ExifTag -> Ordering)
-> (ExifTag -> ExifTag -> Bool)
-> (ExifTag -> ExifTag -> Bool)
-> (ExifTag -> ExifTag -> Bool)
-> (ExifTag -> ExifTag -> Bool)
-> (ExifTag -> ExifTag -> ExifTag)
-> (ExifTag -> ExifTag -> ExifTag)
-> Ord ExifTag
ExifTag -> ExifTag -> Bool
ExifTag -> ExifTag -> Ordering
ExifTag -> ExifTag -> ExifTag
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ExifTag -> ExifTag -> ExifTag
$cmin :: ExifTag -> ExifTag -> ExifTag
max :: ExifTag -> ExifTag -> ExifTag
$cmax :: ExifTag -> ExifTag -> ExifTag
>= :: ExifTag -> ExifTag -> Bool
$c>= :: ExifTag -> ExifTag -> Bool
> :: ExifTag -> ExifTag -> Bool
$c> :: ExifTag -> ExifTag -> Bool
<= :: ExifTag -> ExifTag -> Bool
$c<= :: ExifTag -> ExifTag -> Bool
< :: ExifTag -> ExifTag -> Bool
$c< :: ExifTag -> ExifTag -> Bool
compare :: ExifTag -> ExifTag -> Ordering
$ccompare :: ExifTag -> ExifTag -> Ordering
$cp1Ord :: Eq ExifTag
Ord, Int -> ExifTag -> ShowS
[ExifTag] -> ShowS
ExifTag -> String
(Int -> ExifTag -> ShowS)
-> (ExifTag -> String) -> ([ExifTag] -> ShowS) -> Show ExifTag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExifTag] -> ShowS
$cshowList :: [ExifTag] -> ShowS
show :: ExifTag -> String
$cshow :: ExifTag -> String
showsPrec :: Int -> ExifTag -> ShowS
$cshowsPrec :: Int -> ExifTag -> ShowS
Show)

-- | Convert a value to it's corresponding Exif tag.

-- Will often be written as 'TagUnknown'

tagOfWord16 :: Word16 -> ExifTag
tagOfWord16 :: Word16 -> ExifTag
tagOfWord16 Word16
v = case Word16
v of
  Word16
255 -> ExifTag
TagSubfileType
  Word16
256 -> ExifTag
TagImageWidth
  Word16
257 -> ExifTag
TagImageLength
  Word16
258 -> ExifTag
TagBitsPerSample
  Word16
259 -> ExifTag
TagCompression
  Word16
262 -> ExifTag
TagPhotometricInterpretation
  Word16
266 -> ExifTag
TagFillOrder
  Word16
269 -> ExifTag
TagDocumentName
  Word16
270 -> ExifTag
TagImageDescription
  Word16
271 -> ExifTag
TagMake
  Word16
272 -> ExifTag
TagModel
  Word16
273 -> ExifTag
TagStripOffsets
  Word16
274 -> ExifTag
TagOrientation
  Word16
277 -> ExifTag
TagSamplesPerPixel
  Word16
278 -> ExifTag
TagRowPerStrip
  Word16
279 -> ExifTag
TagStripByteCounts
  Word16
282 -> ExifTag
TagXResolution
  Word16
283 -> ExifTag
TagYResolution
  Word16
284 -> ExifTag
TagPlanarConfiguration
  Word16
286 -> ExifTag
TagXPosition
  Word16
287 -> ExifTag
TagYPosition
  Word16
296 -> ExifTag
TagResolutionUnit
  Word16
305 -> ExifTag
TagSoftware
  Word16
306 -> ExifTag
TagDateTime
  Word16
315 -> ExifTag
TagArtist
  Word16
317 -> ExifTag
TagPredictor
  Word16
320 -> ExifTag
TagColorMap
  Word16
322 -> ExifTag
TagTileWidth
  Word16
323 -> ExifTag
TagTileLength
  Word16
324 -> ExifTag
TagTileOffset
  Word16
325 -> ExifTag
TagTileByteCount
  Word16
332 -> ExifTag
TagInkSet
  Word16
338 -> ExifTag
TagExtraSample
  Word16
339 -> ExifTag
TagSampleFormat
  Word16
529 -> ExifTag
TagYCbCrCoeff
  Word16
512 -> ExifTag
TagJpegProc
  Word16
513 -> ExifTag
TagJPEGInterchangeFormat
  Word16
514 -> ExifTag
TagJPEGInterchangeFormatLength
  Word16
515 -> ExifTag
TagJPEGRestartInterval
  Word16
517 -> ExifTag
TagJPEGLosslessPredictors
  Word16
518 -> ExifTag
TagJPEGPointTransforms
  Word16
519 -> ExifTag
TagJPEGQTables
  Word16
520 -> ExifTag
TagJPEGDCTables
  Word16
521 -> ExifTag
TagJPEGACTables
  Word16
530 -> ExifTag
TagYCbCrSubsampling
  Word16
531 -> ExifTag
TagYCbCrPositioning
  Word16
532 -> ExifTag
TagReferenceBlackWhite
  Word16
33432 -> ExifTag
TagCopyright
  Word16
34665 -> ExifTag
TagExifOffset
  Word16
34853 -> ExifTag
TagGPSInfo
  Word16
37384 -> ExifTag
TagLightSource
  Word16
37385 -> ExifTag
TagFlash
  Word16
vv -> Word16 -> ExifTag
TagUnknown Word16
vv

-- | Convert a tag to it's corresponding value.

word16OfTag :: ExifTag -> Word16
word16OfTag :: ExifTag -> Word16
word16OfTag ExifTag
t = case ExifTag
t of
  ExifTag
TagSubfileType -> Word16
255
  ExifTag
TagImageWidth -> Word16
256
  ExifTag
TagImageLength -> Word16
257
  ExifTag
TagBitsPerSample -> Word16
258
  ExifTag
TagCompression -> Word16
259
  ExifTag
TagPhotometricInterpretation -> Word16
262
  ExifTag
TagFillOrder -> Word16
266
  ExifTag
TagDocumentName -> Word16
269
  ExifTag
TagImageDescription -> Word16
270
  ExifTag
TagMake -> Word16
271
  ExifTag
TagModel -> Word16
272
  ExifTag
TagStripOffsets -> Word16
273
  ExifTag
TagOrientation -> Word16
274
  ExifTag
TagSamplesPerPixel -> Word16
277
  ExifTag
TagRowPerStrip -> Word16
278
  ExifTag
TagStripByteCounts -> Word16
279
  ExifTag
TagXResolution -> Word16
282
  ExifTag
TagYResolution -> Word16
283
  ExifTag
TagPlanarConfiguration -> Word16
284
  ExifTag
TagXPosition -> Word16
286
  ExifTag
TagYPosition -> Word16
287
  ExifTag
TagResolutionUnit -> Word16
296
  ExifTag
TagSoftware -> Word16
305
  ExifTag
TagDateTime -> Word16
306
  ExifTag
TagArtist -> Word16
315
  ExifTag
TagPredictor -> Word16
317
  ExifTag
TagColorMap -> Word16
320
  ExifTag
TagTileWidth -> Word16
322
  ExifTag
TagTileLength -> Word16
323
  ExifTag
TagTileOffset -> Word16
324
  ExifTag
TagTileByteCount -> Word16
325
  ExifTag
TagInkSet -> Word16
332
  ExifTag
TagExtraSample -> Word16
338
  ExifTag
TagSampleFormat -> Word16
339
  ExifTag
TagYCbCrCoeff -> Word16
529
  ExifTag
TagJpegProc -> Word16
512
  ExifTag
TagJPEGInterchangeFormat -> Word16
513
  ExifTag
TagJPEGInterchangeFormatLength -> Word16
514
  ExifTag
TagJPEGRestartInterval -> Word16
515
  ExifTag
TagJPEGLosslessPredictors -> Word16
517
  ExifTag
TagJPEGPointTransforms -> Word16
518
  ExifTag
TagJPEGQTables -> Word16
519
  ExifTag
TagJPEGDCTables -> Word16
520
  ExifTag
TagJPEGACTables -> Word16
521
  ExifTag
TagYCbCrSubsampling -> Word16
530
  ExifTag
TagYCbCrPositioning -> Word16
531
  ExifTag
TagReferenceBlackWhite -> Word16
532
  ExifTag
TagCopyright -> Word16
33432
  ExifTag
TagExifOffset -> Word16
34665
  ExifTag
TagGPSInfo -> Word16
34853
  ExifTag
TagLightSource -> Word16
37384
  ExifTag
TagFlash -> Word16
37385
  (TagUnknown Word16
v) -> Word16
v

isInIFD0 :: ExifTag -> Bool
isInIFD0 :: ExifTag -> Bool
isInIFD0 ExifTag
t = ExifTag -> Word16
word16OfTag ExifTag
t Word16 -> Word16 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word16
lastTag Bool -> Bool -> Bool
|| Bool
isRedirectTag where
  lastTag :: Word16
lastTag = ExifTag -> Word16
word16OfTag ExifTag
TagCopyright
  isRedirectTag :: Bool
isRedirectTag = ExifTag
t ExifTag -> [ExifTag] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ExifTag
TagExifOffset, ExifTag
TagGPSInfo]

-- | Possible data held by an Exif tag

data ExifData
  = ExifNone
  | ExifLong      !Word32
  | ExifShort     !Word16
  | ExifString    !B.ByteString
  | ExifUndefined !B.ByteString
  | ExifShorts    !(V.Vector Word16)
  | ExifLongs     !(V.Vector Word32)
  | ExifRational  !Word32 !Word32
  | ExifSignedRational  !Int32 !Int32
  | ExifIFD       ![(ExifTag, ExifData)]
  deriving Int -> ExifData -> ShowS
[ExifData] -> ShowS
ExifData -> String
(Int -> ExifData -> ShowS)
-> (ExifData -> String) -> ([ExifData] -> ShowS) -> Show ExifData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExifData] -> ShowS
$cshowList :: [ExifData] -> ShowS
show :: ExifData -> String
$cshow :: ExifData -> String
showsPrec :: Int -> ExifData -> ShowS
$cshowsPrec :: Int -> ExifData -> ShowS
Show

instance NFData ExifTag where
  rnf :: ExifTag -> ()
rnf ExifTag
a = ExifTag
a ExifTag -> () -> ()
`seq` ()

instance NFData ExifData where
  rnf :: ExifData -> ()
rnf (ExifIFD [(ExifTag, ExifData)]
ifds) = [(ExifTag, ExifData)] -> ()
forall a. NFData a => a -> ()
rnf [(ExifTag, ExifData)]
ifds () -> () -> ()
`seq` ()
  rnf (ExifLongs Vector Word32
l) = Vector Word32 -> ()
forall a. NFData a => a -> ()
rnf Vector Word32
l () -> () -> ()
`seq` ()
  rnf (ExifShorts Vector Word16
l) = Vector Word16 -> ()
forall a. NFData a => a -> ()
rnf Vector Word16
l () -> () -> ()
`seq` ()
  rnf ExifData
a = ExifData
a ExifData -> () -> ()
`seq` ()