content: {-|
  Module: IHP.FileStorage.Preprocessor.ImageMagick
  Description: Preprocessor for images. Requires that you add @imagemagick@ to the @otherDeps@ inside the project's @default.nix.
  Copyright: (c) digitally induced GmbH, 2021
  -}
  module IHP.FileStorage.Preprocessor.ImageMagick
  ( applyImageMagick
  ) where
  
  import IHP.Prelude
  
  import qualified Network.Wai.Parse as Wai
  import qualified Data.ByteString.Lazy as LBS
  import qualified System.IO.Temp as Temp
  import qualified System.Process as Process
  
  
  -- | Converts the image to the specified output format and applies specified image magick transforms
  --
  -- __Example:__ Transform an uploaded image to a PNG file, resize it to 512x512 and strip meta data
  --
  -- > let uploadLogo = uploadToStorageWithOptions $ def
  -- >         { preprocess = applyImageMagick "png" ["-resize", "512x512^", "-gravity", "north", "-extent" , "512x512", "-quality", "100%", "-strip"] }
  -- >
  -- > company <- fetch companyId
  -- > company
  -- >     |> fill @'["name"]
  -- >     |> uploadLogo #logoUrl
  -- >     >>= ifValid \case
  -- >         Left company -> render EditView { .. }
  -- >         Right company -> do
  -- >             company <- company |> updateRecord
  -- >             redirectTo EditCompanyAction { .. }
  --
  --
  -- __Example:__ Transform an uploaded image to a JPEG file and strip meta data
  --
  -- > let uploadLogo = uploadToStorageWithOptions $ def
  -- >         { preprocess = applyImageMagick "jpg" ["-strip"] }
  -- >
  -- > company <- fetch companyId
  -- > company
  -- >     |> fill @'["name"]
  -- >     |> uploadLogo #logoUrl
  -- >     >>= ifValid \case
  -- >         Left company -> render EditView { .. }
  -- >         Right company -> do
  -- >             company <- company |> updateRecord
  -- >             redirectTo EditCompanyAction { .. }
  --
  applyImageMagick :: Text -> [String] -> Wai.FileInfo LByteString -> IO (Wai.FileInfo LByteString)
  applyImageMagick convertTo otherParams fileInfo = do
      Temp.withTempDirectory "/tmp" "ihp-upload" $ \tempPath -> do
          let tempFilePath = tempPath <> "/image"
          let convertedFilePath = tempPath <> "/converted." <> cs convertTo
  
          fileInfo
              |> (.fileContent)
              |> LBS.writeFile tempFilePath
  
          let params :: [String] = [tempFilePath] <> otherParams <> [convertedFilePath]
          Process.callProcess "magick" params
  
          newContent <- LBS.readFile convertedFilePath
          pure fileInfo { Wai.fileContent = newContent }