haskellexternalhaskell-diagrams

Load external image in Haskell Diagrams


So I have this doubt. I already have code that works with local (embedded) image files, but now I need to load an external image instead. Dumb replacing with loadImageExt didn't help:

productImageIO :: IO (Diagram B)
productImageIO = do
  res <- loadImageExt "https://s7d2.scene7.com/is/image/dkscdn/16JDNMJRDNCLPSBLKJRD_Black_Black_White_is/"
  return $
    case res of
      Left err -> mempty
      Right product -> image product



• No instance for (Renderable (DImage Double External) B)
        arising from a use of ‘image’
    • In the expression: image product
      In a case alternative: Right product -> image product
      In the second argument of ‘($)’, namely
        ‘case res of
           Left err -> mempty
           Right product -> image product’
   |
26 |       Right product -> image product
   |                        ^^^^^^^^^^^^^

Looking at the source of loadImageExt and readImage I cannot see where it actually performs http stuff to get the image.

And the docs say, loadImageExt, Check that a file exists, and use JuicyPixels to figure out the right size, but save a reference to the image instead of the raster data

So please excuse my ignorance, but does this mean that I need to add http loading logic in this case? Or I'm just missing some point to make this work?

UPD: I might be wrong and there's some fast and easy way to load external images by just putting the link, but what worked for me was using http-conduit, getting the response in ByteString and parsing it:

productImageIO :: String -> IO (Diagram B)
productImageIO path = do
   response <- fmap getResponseBody $ parseRequest path >>= httpBS
   return $
     case loadImageEmbBS response of
        Left error -> mempty
        Right decodedImage -> image decodedImage

It could load even https image, like this https://sneakernews.com/wp-content/uploads/2018/01/jordan-russell-westbrook-signature-shoe-creamsicle-3.jpg?w=1140


Solution

  • loadImageExt appears to expect a FilePath, not a URL, but that's not what the compiler is complaining about. It is complaining that the particular image returned, a DImage Double External, is not Renderable. This could be because the renderer in use doesn't understand external images; for instance, Diagrams.Backend.SVG appears to support Embedded but not External. In contrast, Diagrams.Backend.Html5 supports External but not Embedded. At a guess, it's expected that your diagram refers using local filenames to images, not cross-site URLs. It could be that you can inject URLs with uncheckedImageRef, but still only if the backend supports External. The Diagrams manual section on images claims only the Cairo backend does, but that could be inaccurate.