1

I'm very new to Haskell so I apologise if this is too basic, or if it makes very little sense. I'm trying to read an image; I can get it to a list of pixel data with the following code:

data Pixel = Pixel {
    red :: Integer,
    green :: Integer,
    blue :: Integer,
    alpha :: Integer
} deriving (Show)

getImagePixelArray :: FilePath -> IO (Codec.Picture.Repa.Img RGBA)
getImagePixelArray fp = do
    img <- (either error return =<< readImageRGBA fp)
    return img

getImagePixelData :: Codec.Picture.Repa.Img RGBA -> [(Word8,Word8,Word8,Word8)]
getImagePixelData img = R.toList (collapseColorChannel img)

rawPixelToPixel :: (Word8,Word8,Word8,Word8) -> Pixel
rawPixelToPixel (r, g, b, a) = Pixel  {
    red = (toInteger r),
    green = (toInteger g),
    blue = (toInteger b),
    alpha = (toInteger a)
}

main = do
    imageData <- getImagePixelArray "./images/image1.png"
    let imageRawPixels = getImagePixelData imageData
    let asPixels = Prelude.map rawPixelToPixel imageRawPixels 
    mapM print asPixels

I more or less follow what's going on, but my knowledge of Haskell is still limited, so when it comes to making sense of api documentation, I'm struggling a little.

I really want to be able to parse the positions of the pixels; I understand how to do that if I know the width and height of an image, but I can't figure out how to get the width/height of an image.

I'm making my way through a Haskell course, but I'm also trying to put it to some practical use along the way to help the concepts sink in.

OliverRadini
  • 6,238
  • 1
  • 21
  • 46
  • 1
    Unrelated: note that the `Integer` type is meant for arbitrary precision integers -- potentially with thousands of digits. Do you really need that level of precision for the color components? If performance is an issue, that might need to be reconsidered. – chi May 13 '20 at 09:02
  • @chi Ah ok, that makes sense - I don't imagine I'll _need_ to consider performance, as this is just a quick personal project, but I will consider it as it'll help me to figure things out – OliverRadini May 13 '20 at 09:09

1 Answers1

2

Start with the documentation. None of what you're asking for is obviously available on Img, so where else could it be? There's a related Image type, mentioned in convertImage's documentation - I wonder what that is. As it turns out, it has a width and a height. How can we get an Image from our Img, then? imgToImage will give us a DynamicImage, which has several constructors each containing an Image. Figure out what kind of Image you have inside your DynamicImage, and then ask that Image its dimensions.

Perhaps there is something easier with the other lens-y stuff in that module, but it is not obvious to me, and this approach seems simple enough, if a hassle.

amalloy
  • 89,153
  • 8
  • 140
  • 205
  • This is very useful, thanks; I will work my way through the parts that you mention and see what I can throw together – OliverRadini May 13 '20 at 08:56