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

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

word16OfTag :: ExifTag -> Word16
word16OfTag :: ExifTag -> Word16
word16OfTag t :: ExifTag
t = case ExifTag
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 :: Word16
v) -> Word16
v

isInIFD0 :: ExifTag -> Bool
isInIFD0 :: ExifTag -> Bool
isInIFD0 t :: 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 a :: ExifTag
a = ExifTag
a ExifTag -> () -> ()
forall a b. a -> b -> b
`seq` ()

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