{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module Codec.Picture.Tiff.Internal.Types
    ( BinaryParam( .. )
    , Endianness( .. )
    , TiffHeader( .. )
    , TiffPlanarConfiguration( .. )
    , TiffCompression( .. )
    , IfdType( .. )
    , TiffColorspace( .. )
    , TiffSampleFormat( .. )
    , ImageFileDirectory( .. )
    , ExtraSample( .. )
    , Predictor( .. )

    , planarConfgOfConstant
    , constantToPlaneConfiguration
    , unpackSampleFormat
    , packSampleFormat
    , word16OfTag
    , unpackPhotometricInterpretation
    , packPhotometricInterpretation
    , codeOfExtraSample
    , unPackCompression
    , packCompression 
    , predictorOfConstant
    ) where

#if !MIN_VERSION_base(4,8,0)
import Control.Applicative( (<$>), (<*>), pure )
#endif

import Control.Monad( forM_, when, replicateM, )
import Data.Bits( (.&.), unsafeShiftR )
import Data.Binary( Binary( .. ) )
import Data.Binary.Get( Get
                      , getWord16le, getWord16be
                      , getWord32le, getWord32be
                      , bytesRead
                      , skip
                      , getByteString
                      )
import Data.Binary.Put( Put
                      , putWord16le, putWord16be
                      , putWord32le, putWord32be
                      , putByteString
                      )
import Data.Function( on )
import Data.List( sortBy, mapAccumL )
import qualified Data.Vector as V
import qualified Data.ByteString as B
import Data.Int( Int32 )
import Data.Word( Word8, Word16, Word32 )

import Codec.Picture.Metadata.Exif
{-import Debug.Trace-}

data Endianness
  = EndianLittle
  | EndianBig
  deriving (Endianness -> Endianness -> Bool
(Endianness -> Endianness -> Bool)
-> (Endianness -> Endianness -> Bool) -> Eq Endianness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Endianness -> Endianness -> Bool
$c/= :: Endianness -> Endianness -> Bool
== :: Endianness -> Endianness -> Bool
$c== :: Endianness -> Endianness -> Bool
Eq, Int -> Endianness -> ShowS
[Endianness] -> ShowS
Endianness -> String
(Int -> Endianness -> ShowS)
-> (Endianness -> String)
-> ([Endianness] -> ShowS)
-> Show Endianness
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Endianness] -> ShowS
$cshowList :: [Endianness] -> ShowS
show :: Endianness -> String
$cshow :: Endianness -> String
showsPrec :: Int -> Endianness -> ShowS
$cshowsPrec :: Int -> Endianness -> ShowS
Show)

instance Binary Endianness where
  put :: Endianness -> Put
put Endianness
EndianLittle = Word16 -> Put
putWord16le Word16
0x4949
  put Endianness
EndianBig = Word16 -> Put
putWord16le Word16
0x4D4D

  get :: Get Endianness
get = do
    Word16
tag <- Get Word16
getWord16le
    case Word16
tag of
      Word16
0x4949 -> Endianness -> Get Endianness
forall (m :: * -> *) a. Monad m => a -> m a
return Endianness
EndianLittle
      Word16
0x4D4D -> Endianness -> Get Endianness
forall (m :: * -> *) a. Monad m => a -> m a
return Endianness
EndianBig
      Word16
_ -> String -> Get Endianness
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid endian tag value"

-- | Because having a polymorphic get with endianness is to nice

-- to pass on, introducing this helper type class, which is just

-- a superset of Binary, but formalising a parameter passing

-- into it.

class BinaryParam a b where
  getP :: a -> Get b
  putP :: a -> b -> Put

data TiffHeader = TiffHeader
  { TiffHeader -> Endianness
hdrEndianness :: !Endianness
  , TiffHeader -> Word32
hdrOffset     :: {-# UNPACK #-} !Word32
  }
  deriving (TiffHeader -> TiffHeader -> Bool
(TiffHeader -> TiffHeader -> Bool)
-> (TiffHeader -> TiffHeader -> Bool) -> Eq TiffHeader
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TiffHeader -> TiffHeader -> Bool
$c/= :: TiffHeader -> TiffHeader -> Bool
== :: TiffHeader -> TiffHeader -> Bool
$c== :: TiffHeader -> TiffHeader -> Bool
Eq, Int -> TiffHeader -> ShowS
[TiffHeader] -> ShowS
TiffHeader -> String
(Int -> TiffHeader -> ShowS)
-> (TiffHeader -> String)
-> ([TiffHeader] -> ShowS)
-> Show TiffHeader
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TiffHeader] -> ShowS
$cshowList :: [TiffHeader] -> ShowS
show :: TiffHeader -> String
$cshow :: TiffHeader -> String
showsPrec :: Int -> TiffHeader -> ShowS
$cshowsPrec :: Int -> TiffHeader -> ShowS
Show)

instance BinaryParam Endianness Word16 where
  putP :: Endianness -> Word16 -> Put
putP Endianness
EndianLittle = Word16 -> Put
putWord16le
  putP Endianness
EndianBig = Word16 -> Put
putWord16be

  getP :: Endianness -> Get Word16
getP Endianness
EndianLittle = Get Word16
getWord16le
  getP Endianness
EndianBig = Get Word16
getWord16be

instance BinaryParam Endianness Int32 where
  putP :: Endianness -> Int32 -> Put
putP Endianness
en Int32
v = Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
en (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ (Int32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
v :: Word32)
  getP :: Endianness -> Get Int32
getP Endianness
en = Word32 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int32) -> Get Word32 -> Get Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Endianness -> Get Word32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
en :: Get Word32) 

instance BinaryParam Endianness Word32 where
  putP :: Endianness -> Word32 -> Put
putP Endianness
EndianLittle = Word32 -> Put
putWord32le
  putP Endianness
EndianBig = Word32 -> Put
putWord32be

  getP :: Endianness -> Get Word32
getP Endianness
EndianLittle = Get Word32
getWord32le
  getP Endianness
EndianBig = Get Word32
getWord32be

instance Binary TiffHeader where
  put :: TiffHeader -> Put
put TiffHeader
hdr = do
    let endian :: Endianness
endian = TiffHeader -> Endianness
hdrEndianness TiffHeader
hdr
    Endianness -> Put
forall t. Binary t => t -> Put
put Endianness
endian
    Endianness -> Word16 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endian (Word16
42 :: Word16)
    Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endian (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ TiffHeader -> Word32
hdrOffset TiffHeader
hdr

  get :: Get TiffHeader
get = do
    Endianness
endian <- Get Endianness
forall t. Binary t => Get t
get
    Word16
magic <- Endianness -> Get Word16
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endian
    let magicValue :: Word16
magicValue = Word16
42 :: Word16
    Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word16
magic Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word16
magicValue)
         (String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid TIFF magic number")
    Endianness -> Word32 -> TiffHeader
TiffHeader Endianness
endian (Word32 -> TiffHeader) -> Get Word32 -> Get TiffHeader
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get Word32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endian

data TiffPlanarConfiguration
  = PlanarConfigContig    -- = 1

  | PlanarConfigSeparate  -- = 2


planarConfgOfConstant :: Word32 -> Get TiffPlanarConfiguration
planarConfgOfConstant :: Word32 -> Get TiffPlanarConfiguration
planarConfgOfConstant Word32
0 = TiffPlanarConfiguration -> Get TiffPlanarConfiguration
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffPlanarConfiguration
PlanarConfigContig
planarConfgOfConstant Word32
1 = TiffPlanarConfiguration -> Get TiffPlanarConfiguration
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffPlanarConfiguration
PlanarConfigContig
planarConfgOfConstant Word32
2 = TiffPlanarConfiguration -> Get TiffPlanarConfiguration
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffPlanarConfiguration
PlanarConfigSeparate
planarConfgOfConstant Word32
v = String -> Get TiffPlanarConfiguration
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get TiffPlanarConfiguration)
-> String -> Get TiffPlanarConfiguration
forall a b. (a -> b) -> a -> b
$ String
"Unknown planar constant (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show Word32
v String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

constantToPlaneConfiguration :: TiffPlanarConfiguration -> Word16
constantToPlaneConfiguration :: TiffPlanarConfiguration -> Word16
constantToPlaneConfiguration TiffPlanarConfiguration
PlanarConfigContig = Word16
1
constantToPlaneConfiguration TiffPlanarConfiguration
PlanarConfigSeparate = Word16
2

data TiffCompression
  = CompressionNone           -- 1

  | CompressionModifiedRLE    -- 2

  | CompressionLZW            -- 5

  | CompressionJPEG           -- 6

  | CompressionPackBit        -- 32273


data IfdType
  = TypeByte
  | TypeAscii
  | TypeShort
  | TypeLong
  | TypeRational
  | TypeSByte
  | TypeUndefined
  | TypeSignedShort
  | TypeSignedLong
  | TypeSignedRational
  | TypeFloat
  | TypeDouble
  deriving Int -> IfdType -> ShowS
[IfdType] -> ShowS
IfdType -> String
(Int -> IfdType -> ShowS)
-> (IfdType -> String) -> ([IfdType] -> ShowS) -> Show IfdType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IfdType] -> ShowS
$cshowList :: [IfdType] -> ShowS
show :: IfdType -> String
$cshow :: IfdType -> String
showsPrec :: Int -> IfdType -> ShowS
$cshowsPrec :: Int -> IfdType -> ShowS
Show

instance BinaryParam Endianness IfdType where
    getP :: Endianness -> Get IfdType
getP Endianness
endianness = Endianness -> Get Word16
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness Get Word16 -> (Word16 -> Get IfdType) -> Get IfdType
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Word16 -> Get IfdType
conv where
      conv :: Word16 -> Get IfdType
      conv :: Word16 -> Get IfdType
conv Word16
v = case Word16
v of
        Word16
1  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeByte
        Word16
2  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeAscii
        Word16
3  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeShort
        Word16
4  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeLong
        Word16
5  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeRational
        Word16
6  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeSByte
        Word16
7  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeUndefined
        Word16
8  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeSignedShort
        Word16
9  -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeSignedLong
        Word16
10 -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeSignedRational
        Word16
11 -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeFloat
        Word16
12 -> IfdType -> Get IfdType
forall (m :: * -> *) a. Monad m => a -> m a
return IfdType
TypeDouble
        Word16
_  -> String -> Get IfdType
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid TIF directory type"

    putP :: Endianness -> IfdType -> Put
putP Endianness
endianness = Endianness -> Word16 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness (Word16 -> Put) -> (IfdType -> Word16) -> IfdType -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IfdType -> Word16
conv where
      conv :: IfdType -> Word16
      conv :: IfdType -> Word16
conv IfdType
v = case IfdType
v of
        IfdType
TypeByte -> Word16
1
        IfdType
TypeAscii -> Word16
2
        IfdType
TypeShort -> Word16
3
        IfdType
TypeLong -> Word16
4
        IfdType
TypeRational -> Word16
5
        IfdType
TypeSByte -> Word16
6
        IfdType
TypeUndefined -> Word16
7
        IfdType
TypeSignedShort -> Word16
8
        IfdType
TypeSignedLong -> Word16
9
        IfdType
TypeSignedRational -> Word16
10
        IfdType
TypeFloat -> Word16
11
        IfdType
TypeDouble -> Word16
12

instance BinaryParam Endianness ExifTag where
  getP :: Endianness -> Get ExifTag
getP Endianness
endianness = Word16 -> ExifTag
tagOfWord16 (Word16 -> ExifTag) -> Get Word16 -> Get ExifTag
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get Word16
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness
  putP :: Endianness -> ExifTag -> Put
putP Endianness
endianness = Endianness -> Word16 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness (Word16 -> Put) -> (ExifTag -> Word16) -> ExifTag -> Put
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExifTag -> Word16
word16OfTag

data Predictor
  = PredictorNone                   -- 1

  | PredictorHorizontalDifferencing -- 2

  deriving Predictor -> Predictor -> Bool
(Predictor -> Predictor -> Bool)
-> (Predictor -> Predictor -> Bool) -> Eq Predictor
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Predictor -> Predictor -> Bool
$c/= :: Predictor -> Predictor -> Bool
== :: Predictor -> Predictor -> Bool
$c== :: Predictor -> Predictor -> Bool
Eq

predictorOfConstant :: Word32 -> Get Predictor
predictorOfConstant :: Word32 -> Get Predictor
predictorOfConstant Word32
1 = Predictor -> Get Predictor
forall (f :: * -> *) a. Applicative f => a -> f a
pure Predictor
PredictorNone
predictorOfConstant Word32
2 = Predictor -> Get Predictor
forall (f :: * -> *) a. Applicative f => a -> f a
pure Predictor
PredictorHorizontalDifferencing
predictorOfConstant Word32
v = String -> Get Predictor
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get Predictor) -> String -> Get Predictor
forall a b. (a -> b) -> a -> b
$ String
"Unknown predictor (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show Word32
v String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

paddWrite :: B.ByteString -> Put
paddWrite :: ByteString -> Put
paddWrite ByteString
str = ByteString -> Put
putByteString ByteString
str Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Put
padding where
  zero :: Word8
zero = Word8
0 :: Word8
  padding :: Put
padding = Bool -> Put -> Put
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int -> Bool
forall a. Integral a => a -> Bool
odd (ByteString -> Int
B.length ByteString
str)) (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ Word8 -> Put
forall t. Binary t => t -> Put
put Word8
zero

instance BinaryParam (Endianness, Int, ImageFileDirectory) ExifData where
  putP :: (Endianness, Int, ImageFileDirectory) -> ExifData -> Put
putP (Endianness
endianness, Int
_, ImageFileDirectory
_) = ExifData -> Put
dump
    where
      dump :: ExifData -> Put
dump ExifData
ExifNone = () -> Put
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      dump (ExifLong Word32
_) = () -> Put
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      dump (ExifShort Word16
_) = () -> Put
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      dump (ExifIFD [(ExifTag, ExifData)]
_) = () -> Put
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
      dump (ExifString ByteString
bstr) = ByteString -> Put
paddWrite ByteString
bstr
      dump (ExifUndefined ByteString
bstr) = ByteString -> Put
paddWrite ByteString
bstr
      -- wrong if length == 2

      dump (ExifShorts Vector Word16
shorts) = (Word16 -> Put) -> Vector Word16 -> Put
forall (m :: * -> *) a b. Monad m => (a -> m b) -> Vector a -> m ()
V.mapM_ (Endianness -> Word16 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness) Vector Word16
shorts
      dump (ExifLongs Vector Word32
longs) = (Word32 -> Put) -> Vector Word32 -> Put
forall (m :: * -> *) a b. Monad m => (a -> m b) -> Vector a -> m ()
V.mapM_ (Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness) Vector Word32
longs
      dump (ExifRational Word32
a Word32
b) = Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness Word32
a Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness Word32
b
      dump (ExifSignedRational Int32
a Int32
b) = Endianness -> Int32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness Int32
a Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Endianness -> Int32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness Int32
b

  getP :: (Endianness, Int, ImageFileDirectory) -> Get ExifData
getP (Endianness
endianness, Int
maxi, ImageFileDirectory
ifd) = ImageFileDirectory -> Get ExifData
fetcher ImageFileDirectory
ifd
    where
      align :: ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory { ifdOffset :: ImageFileDirectory -> Word32
ifdOffset = Word32
offset } Get ExifData
act = do
        Int64
readed <- Get Int64
bytesRead
        let delta :: Int64
delta = Word32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
offset Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
readed
        if Word32
offset Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
maxi Bool -> Bool -> Bool
|| Int64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
readed Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
offset then
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure ExifData
ExifNone
        else do
          Int -> Get ()
skip (Int -> Get ()) -> Int -> Get ()
forall a b. (a -> b) -> a -> b
$ Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
delta
          Get ExifData
act

      getE :: (BinaryParam Endianness a) => Get a
      getE :: Get a
getE = Endianness -> Get a
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness

      getVec :: a -> m a -> m (Vector a)
getVec a
count = Int -> m a -> m (Vector a)
forall (m :: * -> *) a. Monad m => Int -> m a -> m (Vector a)
V.replicateM (a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
count)

      immediateBytes :: a -> [a]
immediateBytes a
ofs =
        let bytes :: [a]
bytes = [a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ (a
ofs a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0xFF000000) a -> Int -> a
forall a. Bits a => a -> Int -> a
`unsafeShiftR` (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8)
                    ,a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ (a
ofs a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0x00FF0000) a -> Int -> a
forall a. Bits a => a -> Int -> a
`unsafeShiftR` (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8)
                    ,a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ (a
ofs a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0x0000FF00) a -> Int -> a
forall a. Bits a => a -> Int -> a
`unsafeShiftR` (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8)
                    ,a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$  a
ofs a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0x000000FF
                    ]
        in case Endianness
endianness of
             Endianness
EndianLittle -> [a] -> [a]
forall a. [a] -> [a]
reverse [a]
bytes
             Endianness
EndianBig    -> [a]
bytes

      fetcher :: ImageFileDirectory -> Get ExifData
fetcher ImageFileDirectory { ifdIdentifier :: ImageFileDirectory -> ExifTag
ifdIdentifier = ExifTag
TagExifOffset
                                 , ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeLong
                                 , ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 } = do
         ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ do
            let byOffset :: [ImageFileDirectory] -> [ImageFileDirectory]
byOffset = (ImageFileDirectory -> ImageFileDirectory -> Ordering)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Word32 -> Word32 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word32 -> Word32 -> Ordering)
-> (ImageFileDirectory -> Word32)
-> ImageFileDirectory
-> ImageFileDirectory
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ImageFileDirectory -> Word32
ifdOffset)
                cleansIfds :: [ImageFileDirectory] -> [ImageFileDirectory]
cleansIfds = (ImageFileDirectory -> ImageFileDirectory)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Endianness -> ImageFileDirectory -> ImageFileDirectory
cleanImageFileDirectory Endianness
endianness)
            [ImageFileDirectory]
subIfds <- [ImageFileDirectory] -> [ImageFileDirectory]
cleansIfds ([ImageFileDirectory] -> [ImageFileDirectory])
-> ([ImageFileDirectory] -> [ImageFileDirectory])
-> [ImageFileDirectory]
-> [ImageFileDirectory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ImageFileDirectory] -> [ImageFileDirectory]
byOffset ([ImageFileDirectory] -> [ImageFileDirectory])
-> Get [ImageFileDirectory] -> Get [ImageFileDirectory]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get [ImageFileDirectory]
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness
            [ImageFileDirectory]
cleaned <- Endianness
-> Int -> [ImageFileDirectory] -> Get [ImageFileDirectory]
fetchExtended Endianness
endianness Int
maxi ([ImageFileDirectory] -> Get [ImageFileDirectory])
-> [ImageFileDirectory] -> Get [ImageFileDirectory]
forall a b. (a -> b) -> a -> b
$ (ImageFileDirectory -> ImageFileDirectory -> Ordering)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Word32 -> Word32 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word32 -> Word32 -> Ordering)
-> (ImageFileDirectory -> Word32)
-> ImageFileDirectory
-> ImageFileDirectory
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ImageFileDirectory -> Word32
ifdOffset) [ImageFileDirectory]
subIfds
            ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData) -> ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ [(ExifTag, ExifData)] -> ExifData
ExifIFD [(ImageFileDirectory -> ExifTag
ifdIdentifier ImageFileDirectory
fd, ImageFileDirectory -> ExifData
ifdExtended ImageFileDirectory
fd) | ImageFileDirectory
fd <- [ImageFileDirectory]
cleaned]
         {-  
      fetcher ImageFileDirectory { ifdIdentifier = TagGPSInfo
                                 , ifdType = TypeLong
                                 , ifdCount = 1 } = do
         align ifd 
         subIfds <- fmap (cleanImageFileDirectory endianness) <$> getP endianness
         cleaned <- fetchExtended endianness subIfds
         pure $ ExifIFD [(ifdIdentifier fd, ifdExtended fd) | fd <- cleaned]
        -}
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeUndefined, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
count } | Word32
count Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
4 =
         ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ ByteString -> ExifData
ExifUndefined (ByteString -> ExifData) -> Get ByteString -> Get ExifData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Get ByteString
getByteString (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
count)
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeUndefined, ifdOffset :: ImageFileDirectory -> Word32
ifdOffset = Word32
ofs } =
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData)
-> ([Word8] -> ExifData) -> [Word8] -> Get ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ExifData
ExifUndefined (ByteString -> ExifData)
-> ([Word8] -> ByteString) -> [Word8] -> ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
B.pack ([Word8] -> Get ExifData) -> [Word8] -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Int -> [Word8] -> [Word8]
forall a. Int -> [a] -> [a]
take (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdCount ImageFileDirectory
ifd)
              (Word32 -> [Word8]
forall a a. (Integral a, Bits a, Num a) => a -> [a]
immediateBytes Word32
ofs)
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeAscii, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
count } | Word32
count Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
4 =
          ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ ByteString -> ExifData
ExifString (ByteString -> ExifData) -> Get ByteString -> Get ExifData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Get ByteString
getByteString (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
count)
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeAscii, ifdOffset :: ImageFileDirectory -> Word32
ifdOffset = Word32
ofs } =
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData)
-> ([Word8] -> ExifData) -> [Word8] -> Get ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ExifData
ExifString (ByteString -> ExifData)
-> ([Word8] -> ByteString) -> [Word8] -> ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
B.pack ([Word8] -> Get ExifData) -> [Word8] -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Int -> [Word8] -> [Word8]
forall a. Int -> [a] -> [a]
take (Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int) -> Word32 -> Int
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdCount ImageFileDirectory
ifd)
              (Word32 -> [Word8]
forall a a. (Integral a, Bits a, Num a) => a -> [a]
immediateBytes Word32
ofs)
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeShort, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
2, ifdOffset :: ImageFileDirectory -> Word32
ifdOffset = Word32
ofs } =
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData)
-> (Vector Word16 -> ExifData) -> Vector Word16 -> Get ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Word16 -> ExifData
ExifShorts (Vector Word16 -> Get ExifData) -> Vector Word16 -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Int -> [Word16] -> Vector Word16
forall a. Int -> [a] -> Vector a
V.fromListN Int
2 [Word16]
valList
            where high :: Word16
high = Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word16) -> Word32 -> Word16
forall a b. (a -> b) -> a -> b
$ Word32
ofs Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16
                  low :: Word16
low = Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Word16) -> Word32 -> Word16
forall a b. (a -> b) -> a -> b
$ Word32
ofs Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word32
0xFFFF
                  valList :: [Word16]
valList = case Endianness
endianness of
                    Endianness
EndianLittle -> [Word16
low, Word16
high]
                    Endianness
EndianBig -> [Word16
high, Word16
low]
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeRational, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 } = do
          ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Word32 -> Word32 -> ExifData
ExifRational (Word32 -> Word32 -> ExifData)
-> Get Word32 -> Get (Word32 -> ExifData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get Word32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
EndianLittle Get (Word32 -> ExifData) -> Get Word32 -> Get ExifData
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Endianness -> Get Word32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
EndianLittle
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeSignedRational, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 } = do
          ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Int32 -> Int32 -> ExifData
ExifSignedRational (Int32 -> Int32 -> ExifData)
-> Get Int32 -> Get (Int32 -> ExifData)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get Int32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
EndianLittle Get (Int32 -> ExifData) -> Get Int32 -> Get ExifData
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Endianness -> Get Int32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
EndianLittle
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeShort, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 } =
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData)
-> (Word32 -> ExifData) -> Word32 -> Get ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word16 -> ExifData
ExifShort (Word16 -> ExifData) -> (Word32 -> Word16) -> Word32 -> ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Get ExifData) -> Word32 -> Get ExifData
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdOffset ImageFileDirectory
ifd
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeShort, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
count } | Word32
count Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
2 =
          ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Vector Word16 -> ExifData
ExifShorts (Vector Word16 -> ExifData) -> Get (Vector Word16) -> Get ExifData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word32 -> Get Word16 -> Get (Vector Word16)
forall (m :: * -> *) a a.
(Monad m, Integral a) =>
a -> m a -> m (Vector a)
getVec Word32
count Get Word16
forall a. BinaryParam Endianness a => Get a
getE
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeLong, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 } =
          ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ExifData -> Get ExifData)
-> (Word32 -> ExifData) -> Word32 -> Get ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> ExifData
ExifLong (Word32 -> ExifData) -> (Word32 -> Word32) -> Word32 -> ExifData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Get ExifData) -> Word32 -> Get ExifData
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdOffset ImageFileDirectory
ifd
      fetcher ImageFileDirectory { ifdType :: ImageFileDirectory -> IfdType
ifdType = IfdType
TypeLong, ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
count } | Word32
count Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
> Word32
1 =
          ImageFileDirectory -> Get ExifData -> Get ExifData
align ImageFileDirectory
ifd (Get ExifData -> Get ExifData) -> Get ExifData -> Get ExifData
forall a b. (a -> b) -> a -> b
$ Vector Word32 -> ExifData
ExifLongs (Vector Word32 -> ExifData) -> Get (Vector Word32) -> Get ExifData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word32 -> Get Word32 -> Get (Vector Word32)
forall (m :: * -> *) a a.
(Monad m, Integral a) =>
a -> m a -> m (Vector a)
getVec Word32
count Get Word32
forall a. BinaryParam Endianness a => Get a
getE
      fetcher ImageFileDirectory
_ = ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure ExifData
ExifNone

cleanImageFileDirectory :: Endianness -> ImageFileDirectory -> ImageFileDirectory
cleanImageFileDirectory :: Endianness -> ImageFileDirectory -> ImageFileDirectory
cleanImageFileDirectory Endianness
EndianBig ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdCount :: ImageFileDirectory -> Word32
ifdCount = Word32
1 }) = IfdType -> ImageFileDirectory
aux (IfdType -> ImageFileDirectory) -> IfdType -> ImageFileDirectory
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> IfdType
ifdType ImageFileDirectory
ifd
  where
    aux :: IfdType -> ImageFileDirectory
aux IfdType
TypeShort = ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = ImageFileDirectory -> Word32
ifdOffset ImageFileDirectory
ifd Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16 }
    aux IfdType
_ = ImageFileDirectory
ifd
cleanImageFileDirectory Endianness
_ ImageFileDirectory
ifd = ImageFileDirectory
ifd

fetchExtended :: Endianness -> Int -> [ImageFileDirectory] -> Get [ImageFileDirectory]
fetchExtended :: Endianness
-> Int -> [ImageFileDirectory] -> Get [ImageFileDirectory]
fetchExtended Endianness
endian Int
maxi = (ImageFileDirectory -> Get ImageFileDirectory)
-> [ImageFileDirectory] -> Get [ImageFileDirectory]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((ImageFileDirectory -> Get ImageFileDirectory)
 -> [ImageFileDirectory] -> Get [ImageFileDirectory])
-> (ImageFileDirectory -> Get ImageFileDirectory)
-> [ImageFileDirectory]
-> Get [ImageFileDirectory]
forall a b. (a -> b) -> a -> b
$ \ImageFileDirectory
ifd -> do
  ExifData
v <- (Endianness, Int, ImageFileDirectory) -> Get ExifData
forall a b. BinaryParam a b => a -> Get b
getP (Endianness
endian, Int
maxi, ImageFileDirectory
ifd)
  ImageFileDirectory -> Get ImageFileDirectory
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ImageFileDirectory -> Get ImageFileDirectory)
-> ImageFileDirectory -> Get ImageFileDirectory
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory
ifd { ifdExtended :: ExifData
ifdExtended = ExifData
v }

-- | All the IFD must be written in order according to the tag

-- value of the IFD. To avoid getting to much restriction in the

-- serialization code, just sort it.

orderIfdByTag :: [ImageFileDirectory] -> [ImageFileDirectory]
orderIfdByTag :: [ImageFileDirectory] -> [ImageFileDirectory]
orderIfdByTag = (ImageFileDirectory -> ImageFileDirectory -> Ordering)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ImageFileDirectory -> ImageFileDirectory -> Ordering
comparer where
  comparer :: ImageFileDirectory -> ImageFileDirectory -> Ordering
comparer ImageFileDirectory
a ImageFileDirectory
b = Word16 -> Word16 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word16
t1 Word16
t2 where
    t1 :: Word16
t1 = ExifTag -> Word16
word16OfTag (ExifTag -> Word16) -> ExifTag -> Word16
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> ExifTag
ifdIdentifier ImageFileDirectory
a
    t2 :: Word16
t2 = ExifTag -> Word16
word16OfTag (ExifTag -> Word16) -> ExifTag -> Word16
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> ExifTag
ifdIdentifier ImageFileDirectory
b

-- | Given an official offset and a list of IFD, update the offset information

-- of the IFD with extended data.

setupIfdOffsets :: Word32 -> [ImageFileDirectory] -> (Word32, [ImageFileDirectory])
setupIfdOffsets :: Word32 -> [ImageFileDirectory] -> (Word32, [ImageFileDirectory])
setupIfdOffsets Word32
initialOffset [ImageFileDirectory]
lst = (Word32 -> ImageFileDirectory -> (Word32, ImageFileDirectory))
-> Word32 -> [ImageFileDirectory] -> (Word32, [ImageFileDirectory])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL Word32 -> ImageFileDirectory -> (Word32, ImageFileDirectory)
updater Word32
startExtended [ImageFileDirectory]
lst
  where ifdElementCount :: Word32
ifdElementCount = Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word32) -> Int -> Word32
forall a b. (a -> b) -> a -> b
$ [ImageFileDirectory] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ImageFileDirectory]
lst
        ifdSize :: Word32
ifdSize = Word32
12
        ifdCountSize :: Word32
ifdCountSize = Word32
2
        nextOffsetSize :: Word32
nextOffsetSize = Word32
4
        startExtended :: Word32
startExtended = Word32
initialOffset
                     Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
ifdElementCount Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
* Word32
ifdSize
                     Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
ifdCountSize Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Word32
nextOffsetSize

        paddedSize :: ByteString -> b
paddedSize ByteString
blob = Int -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> b) -> Int -> b
forall a b. (a -> b) -> a -> b
$ Int
blobLength Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
padding where
          blobLength :: Int
blobLength = ByteString -> Int
B.length ByteString
blob
          padding :: Int
padding = if Int -> Bool
forall a. Integral a => a -> Bool
odd Int
blobLength then Int
1 else Int
0

        updater :: Word32 -> ImageFileDirectory -> (Word32, ImageFileDirectory)
updater Word32
ix ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdIdentifier :: ImageFileDirectory -> ExifTag
ifdIdentifier = ExifTag
TagExifOffset }) =
            (Word32
ix, ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = Word32
ix } )
        updater Word32
ix ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdExtended :: ImageFileDirectory -> ExifData
ifdExtended = ExifUndefined ByteString
b }) =
            (Word32
ix Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ ByteString -> Word32
forall b. Num b => ByteString -> b
paddedSize ByteString
b, ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = Word32
ix } )
        updater Word32
ix ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdExtended :: ImageFileDirectory -> ExifData
ifdExtended = ExifString ByteString
b }) =
            (Word32
ix Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ ByteString -> Word32
forall b. Num b => ByteString -> b
paddedSize ByteString
b, ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = Word32
ix } )
        updater Word32
ix ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdExtended :: ImageFileDirectory -> ExifData
ifdExtended = ExifLongs Vector Word32
v })
            | Vector Word32 -> Int
forall a. Vector a -> Int
V.length Vector Word32
v Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1 = ( Word32
ix Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector Word32 -> Int
forall a. Vector a -> Int
V.length Vector Word32
v Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
4)
                               , ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = Word32
ix } )
        updater Word32
ix ifd :: ImageFileDirectory
ifd@(ImageFileDirectory { ifdExtended :: ImageFileDirectory -> ExifData
ifdExtended = ExifShorts Vector Word16
v })
            | Vector Word16 -> Int
forall a. Vector a -> Int
V.length Vector Word16
v Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2 = ( Word32
ix Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
+ Int -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Vector Word16 -> Int
forall a. Vector a -> Int
V.length Vector Word16
v Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
2)
                             , ImageFileDirectory
ifd { ifdOffset :: Word32
ifdOffset = Word32
ix })
        updater Word32
ix ImageFileDirectory
ifd = (Word32
ix, ImageFileDirectory
ifd)

instance BinaryParam B.ByteString (TiffHeader, [[ImageFileDirectory]]) where
  putP :: ByteString -> (TiffHeader, [[ImageFileDirectory]]) -> Put
putP ByteString
rawData (TiffHeader
hdr, [[ImageFileDirectory]]
ifds) = do
    TiffHeader -> Put
forall t. Binary t => t -> Put
put TiffHeader
hdr
    ByteString -> Put
putByteString ByteString
rawData
    let endianness :: Endianness
endianness = TiffHeader -> Endianness
hdrEndianness TiffHeader
hdr
        (Word32
_, [[ImageFileDirectory]]
offseted) = (Word32 -> [ImageFileDirectory] -> (Word32, [ImageFileDirectory]))
-> Word32
-> [[ImageFileDirectory]]
-> (Word32, [[ImageFileDirectory]])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL
            (\Word32
ix [ImageFileDirectory]
ifd -> Word32 -> [ImageFileDirectory] -> (Word32, [ImageFileDirectory])
setupIfdOffsets Word32
ix ([ImageFileDirectory] -> (Word32, [ImageFileDirectory]))
-> [ImageFileDirectory] -> (Word32, [ImageFileDirectory])
forall a b. (a -> b) -> a -> b
$ [ImageFileDirectory] -> [ImageFileDirectory]
orderIfdByTag [ImageFileDirectory]
ifd)
            (TiffHeader -> Word32
hdrOffset TiffHeader
hdr)
            [[ImageFileDirectory]]
ifds
    [[ImageFileDirectory]] -> ([ImageFileDirectory] -> Put) -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[ImageFileDirectory]]
offseted (([ImageFileDirectory] -> Put) -> Put)
-> ([ImageFileDirectory] -> Put) -> Put
forall a b. (a -> b) -> a -> b
$ \[ImageFileDirectory]
list -> do
        Endianness -> [ImageFileDirectory] -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness [ImageFileDirectory]
list
        (ImageFileDirectory -> Put) -> [ImageFileDirectory] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\ImageFileDirectory
field -> (Endianness, Int, ImageFileDirectory) -> ExifData -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP (Endianness
endianness, (Int
0::Int), ImageFileDirectory
field) (ExifData -> Put) -> ExifData -> Put
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> ExifData
ifdExtended ImageFileDirectory
field) [ImageFileDirectory]
list

  getP :: ByteString -> Get (TiffHeader, [[ImageFileDirectory]])
getP ByteString
raw = do
    TiffHeader
hdr <- Get TiffHeader
forall t. Binary t => Get t
get
    Int64
readed <- Get Int64
bytesRead
    Int -> Get ()
skip (Int -> Get ()) -> (Int64 -> Int) -> Int64 -> Get ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Get ()) -> Int64 -> Get ()
forall a b. (a -> b) -> a -> b
$ Word32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (TiffHeader -> Word32
hdrOffset TiffHeader
hdr) Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
- Int64
readed
    let endian :: Endianness
endian = TiffHeader -> Endianness
hdrEndianness TiffHeader
hdr
        byOffset :: [ImageFileDirectory] -> [ImageFileDirectory]
byOffset = (ImageFileDirectory -> ImageFileDirectory -> Ordering)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (Word32 -> Word32 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word32 -> Word32 -> Ordering)
-> (ImageFileDirectory -> Word32)
-> ImageFileDirectory
-> ImageFileDirectory
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ImageFileDirectory -> Word32
ifdOffset)
        cleanIfds :: [ImageFileDirectory] -> [ImageFileDirectory]
cleanIfds = (ImageFileDirectory -> ImageFileDirectory)
-> [ImageFileDirectory] -> [ImageFileDirectory]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Endianness -> ImageFileDirectory -> ImageFileDirectory
cleanImageFileDirectory Endianness
endian)

    [ImageFileDirectory]
ifd <-  [ImageFileDirectory] -> [ImageFileDirectory]
cleanIfds ([ImageFileDirectory] -> [ImageFileDirectory])
-> ([ImageFileDirectory] -> [ImageFileDirectory])
-> [ImageFileDirectory]
-> [ImageFileDirectory]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ImageFileDirectory] -> [ImageFileDirectory]
byOffset ([ImageFileDirectory] -> [ImageFileDirectory])
-> Get [ImageFileDirectory] -> Get [ImageFileDirectory]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Endianness -> Get [ImageFileDirectory]
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endian
    [ImageFileDirectory]
cleaned <- Endianness
-> Int -> [ImageFileDirectory] -> Get [ImageFileDirectory]
fetchExtended Endianness
endian (ByteString -> Int
B.length ByteString
raw) [ImageFileDirectory]
ifd
    (TiffHeader, [[ImageFileDirectory]])
-> Get (TiffHeader, [[ImageFileDirectory]])
forall (m :: * -> *) a. Monad m => a -> m a
return (TiffHeader
hdr, [[ImageFileDirectory]
cleaned])

data TiffSampleFormat
  = TiffSampleUint
  | TiffSampleInt
  | TiffSampleFloat
  | TiffSampleUnknown
  deriving TiffSampleFormat -> TiffSampleFormat -> Bool
(TiffSampleFormat -> TiffSampleFormat -> Bool)
-> (TiffSampleFormat -> TiffSampleFormat -> Bool)
-> Eq TiffSampleFormat
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TiffSampleFormat -> TiffSampleFormat -> Bool
$c/= :: TiffSampleFormat -> TiffSampleFormat -> Bool
== :: TiffSampleFormat -> TiffSampleFormat -> Bool
$c== :: TiffSampleFormat -> TiffSampleFormat -> Bool
Eq

unpackSampleFormat :: Word32 -> Get TiffSampleFormat
unpackSampleFormat :: Word32 -> Get TiffSampleFormat
unpackSampleFormat Word32
v = case Word32
v of
  Word32
1 -> TiffSampleFormat -> Get TiffSampleFormat
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffSampleFormat
TiffSampleUint
  Word32
2 -> TiffSampleFormat -> Get TiffSampleFormat
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffSampleFormat
TiffSampleInt
  Word32
3 -> TiffSampleFormat -> Get TiffSampleFormat
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffSampleFormat
TiffSampleFloat
  Word32
4 -> TiffSampleFormat -> Get TiffSampleFormat
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffSampleFormat
TiffSampleUnknown
  Word32
vv -> String -> Get TiffSampleFormat
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get TiffSampleFormat) -> String -> Get TiffSampleFormat
forall a b. (a -> b) -> a -> b
$ String
"Undefined data format (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show Word32
vv String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"

packSampleFormat :: TiffSampleFormat -> Word32
packSampleFormat :: TiffSampleFormat -> Word32
packSampleFormat TiffSampleFormat
TiffSampleUint    = Word32
1
packSampleFormat TiffSampleFormat
TiffSampleInt     = Word32
2
packSampleFormat TiffSampleFormat
TiffSampleFloat   = Word32
3
packSampleFormat TiffSampleFormat
TiffSampleUnknown = Word32
4

data ImageFileDirectory = ImageFileDirectory
  { ImageFileDirectory -> ExifTag
ifdIdentifier :: !ExifTag -- Word16

  , ImageFileDirectory -> IfdType
ifdType       :: !IfdType -- Word16

  , ImageFileDirectory -> Word32
ifdCount      :: !Word32
  , ImageFileDirectory -> Word32
ifdOffset     :: !Word32
  , ImageFileDirectory -> ExifData
ifdExtended   :: !ExifData
  }
  deriving Int -> ImageFileDirectory -> ShowS
[ImageFileDirectory] -> ShowS
ImageFileDirectory -> String
(Int -> ImageFileDirectory -> ShowS)
-> (ImageFileDirectory -> String)
-> ([ImageFileDirectory] -> ShowS)
-> Show ImageFileDirectory
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ImageFileDirectory] -> ShowS
$cshowList :: [ImageFileDirectory] -> ShowS
show :: ImageFileDirectory -> String
$cshow :: ImageFileDirectory -> String
showsPrec :: Int -> ImageFileDirectory -> ShowS
$cshowsPrec :: Int -> ImageFileDirectory -> ShowS
Show

instance BinaryParam Endianness ImageFileDirectory where
  getP :: Endianness -> Get ImageFileDirectory
getP Endianness
endianness =
    ExifTag
-> IfdType -> Word32 -> Word32 -> ExifData -> ImageFileDirectory
ImageFileDirectory (ExifTag
 -> IfdType -> Word32 -> Word32 -> ExifData -> ImageFileDirectory)
-> Get ExifTag
-> Get
     (IfdType -> Word32 -> Word32 -> ExifData -> ImageFileDirectory)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get ExifTag
forall a. BinaryParam Endianness a => Get a
getE Get (IfdType -> Word32 -> Word32 -> ExifData -> ImageFileDirectory)
-> Get IfdType
-> Get (Word32 -> Word32 -> ExifData -> ImageFileDirectory)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get IfdType
forall a. BinaryParam Endianness a => Get a
getE Get (Word32 -> Word32 -> ExifData -> ImageFileDirectory)
-> Get Word32 -> Get (Word32 -> ExifData -> ImageFileDirectory)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word32
forall a. BinaryParam Endianness a => Get a
getE Get (Word32 -> ExifData -> ImageFileDirectory)
-> Get Word32 -> Get (ExifData -> ImageFileDirectory)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word32
forall a. BinaryParam Endianness a => Get a
getE
                       Get (ExifData -> ImageFileDirectory)
-> Get ExifData -> Get ImageFileDirectory
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ExifData -> Get ExifData
forall (f :: * -> *) a. Applicative f => a -> f a
pure ExifData
ExifNone
        where getE :: (BinaryParam Endianness a) => Get a
              getE :: Get a
getE = Endianness -> Get a
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness

  putP :: Endianness -> ImageFileDirectory -> Put
putP Endianness
endianness ImageFileDirectory
ifd = do
    let putE :: (BinaryParam Endianness a) => a -> Put
        putE :: a -> Put
putE = Endianness -> a -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness
    ExifTag -> Put
forall a. BinaryParam Endianness a => a -> Put
putE (ExifTag -> Put) -> ExifTag -> Put
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> ExifTag
ifdIdentifier ImageFileDirectory
ifd
    IfdType -> Put
forall a. BinaryParam Endianness a => a -> Put
putE (IfdType -> Put) -> IfdType -> Put
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> IfdType
ifdType ImageFileDirectory
ifd
    Word32 -> Put
forall a. BinaryParam Endianness a => a -> Put
putE (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdCount ImageFileDirectory
ifd
    Word32 -> Put
forall a. BinaryParam Endianness a => a -> Put
putE (Word32 -> Put) -> Word32 -> Put
forall a b. (a -> b) -> a -> b
$ ImageFileDirectory -> Word32
ifdOffset ImageFileDirectory
ifd

instance BinaryParam Endianness [ImageFileDirectory] where
  getP :: Endianness -> Get [ImageFileDirectory]
getP Endianness
endianness = do
    Word16
count <- Endianness -> Get Word16
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness :: Get Word16
    [ImageFileDirectory]
rez <- Int -> Get ImageFileDirectory -> Get [ImageFileDirectory]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Word16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
count) (Get ImageFileDirectory -> Get [ImageFileDirectory])
-> Get ImageFileDirectory -> Get [ImageFileDirectory]
forall a b. (a -> b) -> a -> b
$ Endianness -> Get ImageFileDirectory
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness
    Word32
_ <- Endianness -> Get Word32
forall a b. BinaryParam a b => a -> Get b
getP Endianness
endianness :: Get Word32
    [ImageFileDirectory] -> Get [ImageFileDirectory]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ImageFileDirectory]
rez


  putP :: Endianness -> [ImageFileDirectory] -> Put
putP Endianness
endianness [ImageFileDirectory]
lst = do
    let count :: Word16
count = Int -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word16) -> Int -> Word16
forall a b. (a -> b) -> a -> b
$ [ImageFileDirectory] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ImageFileDirectory]
lst :: Word16
    Endianness -> Word16 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness Word16
count
    (ImageFileDirectory -> Put) -> [ImageFileDirectory] -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Endianness -> ImageFileDirectory -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness) [ImageFileDirectory]
lst
    Endianness -> Word32 -> Put
forall a b. BinaryParam a b => a -> b -> Put
putP Endianness
endianness (Word32
0 :: Word32)

data TiffColorspace
  = TiffMonochromeWhite0 -- ^ 0

  | TiffMonochrome       -- ^ 1

  | TiffRGB              -- ^ 2

  | TiffPaleted          -- ^ 3

  | TiffTransparencyMask -- ^ 4

  | TiffCMYK             -- ^ 5

  | TiffYCbCr            -- ^ 6

  | TiffCIELab           -- ^ 8



packPhotometricInterpretation :: TiffColorspace -> Word16
packPhotometricInterpretation :: TiffColorspace -> Word16
packPhotometricInterpretation TiffColorspace
v = case TiffColorspace
v of
  TiffColorspace
TiffMonochromeWhite0 -> Word16
0
  TiffColorspace
TiffMonochrome       -> Word16
1
  TiffColorspace
TiffRGB              -> Word16
2
  TiffColorspace
TiffPaleted          -> Word16
3
  TiffColorspace
TiffTransparencyMask -> Word16
4
  TiffColorspace
TiffCMYK             -> Word16
5
  TiffColorspace
TiffYCbCr            -> Word16
6
  TiffColorspace
TiffCIELab           -> Word16
8

unpackPhotometricInterpretation :: Word32 -> Get TiffColorspace
unpackPhotometricInterpretation :: Word32 -> Get TiffColorspace
unpackPhotometricInterpretation Word32
v = case Word32
v of
  Word32
0 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffMonochromeWhite0
  Word32
1 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffMonochrome
  Word32
2 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffRGB
  Word32
3 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffPaleted
  Word32
4 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffTransparencyMask
  Word32
5 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffCMYK
  Word32
6 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffYCbCr
  Word32
8 -> TiffColorspace -> Get TiffColorspace
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffColorspace
TiffCIELab
  Word32
vv -> String -> Get TiffColorspace
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get TiffColorspace) -> String -> Get TiffColorspace
forall a b. (a -> b) -> a -> b
$ String
"Unrecognized color space " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show Word32
vv

data ExtraSample
  = ExtraSampleUnspecified       -- ^ 0

  | ExtraSampleAssociatedAlpha   -- ^ 1

  | ExtraSampleUnassociatedAlpha -- ^ 2


codeOfExtraSample :: ExtraSample -> Word16
codeOfExtraSample :: ExtraSample -> Word16
codeOfExtraSample ExtraSample
v = case ExtraSample
v of
  ExtraSample
ExtraSampleUnspecified -> Word16
0
  ExtraSample
ExtraSampleAssociatedAlpha -> Word16
1
  ExtraSample
ExtraSampleUnassociatedAlpha -> Word16
2

unPackCompression :: Word32 -> Get TiffCompression
unPackCompression :: Word32 -> Get TiffCompression
unPackCompression Word32
v = case Word32
v of
  Word32
0 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionNone
  Word32
1 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionNone
  Word32
2 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionModifiedRLE
  Word32
5 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionLZW
  Word32
6 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionJPEG
  Word32
32773 -> TiffCompression -> Get TiffCompression
forall (f :: * -> *) a. Applicative f => a -> f a
pure TiffCompression
CompressionPackBit
  Word32
vv -> String -> Get TiffCompression
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get TiffCompression) -> String -> Get TiffCompression
forall a b. (a -> b) -> a -> b
$ String
"Unknown compression scheme " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word32 -> String
forall a. Show a => a -> String
show Word32
vv

packCompression :: TiffCompression -> Word16
packCompression :: TiffCompression -> Word16
packCompression TiffCompression
v = case TiffCompression
v of
  TiffCompression
CompressionNone        -> Word16
1
  TiffCompression
CompressionModifiedRLE -> Word16
2
  TiffCompression
CompressionLZW         -> Word16
5
  TiffCompression
CompressionJPEG        -> Word16
6
  TiffCompression
CompressionPackBit     -> Word16
32773