content: {-# LANGUAGE DeriveGeneric #-}
  
  -- | 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
  import GHC.Generics( Generic )
  
  -- | 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, Generic)
  instance NFData ExifTag
  
  -- | 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
    | ExifString    !B.ByteString
    | ExifUndefined !B.ByteString
    | ExifShorts    !(V.Vector Word16)
    | ExifLongs     !(V.Vector Word32)
    | ExifRational  !Word32 !Word32
    | ExifSignedRational  !Int32 !Int32
    | ExifIFD       ![(ExifTag, ExifData)]
    deriving (Eq, Show, Generic)
  instance NFData ExifData
  