F# lazy pixels reading

后端 未结 3 1012
终归单人心
终归单人心 2021-01-16 21:11

I want to make a lazy loading of image pixels to the 3 dimensional array of integers. For example in simple way it looks like this:

   for i=0 to Width 
             


        
3条回答
  •  孤街浪徒
    2021-01-16 21:34

    What would be slow is the call to GetPixel. If you want to call it only as needed, you could use something like this:

    open System.Drawing
    
    let lazyPixels (image:Bitmap) =
        let Width = image.Width
        let Height = image.Height
        let pixels : Lazy[,,] = Array3D.zeroCreate 3 Width Height
        for i = 0 to Width-1 do
            for j = 0 to Height-1 do
                let point = lazy image.GetPixel(i,j)
                pixels.[0,i,j] <- lazy point.Value.R
                pixels.[1,i,j] <- lazy point.Value.G
                pixels.[2,i,j] <- lazy point.Value.B
        pixels
    

    GetPixel will be called at most once for every pixel, and then reused for the other components.

    Another way of approaching this problem would be to do a bulk-load of the entire image. This will be a lot quicker than calling GetPixel over and over again.

    open System.Drawing
    open System.Drawing.Imaging
    
    let pixels (image:Bitmap) =
        let Width = image.Width
        let Height = image.Height
        let rect = new Rectangle(0,0,Width,Height)
    
        // Lock the image for access
        let data = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat)
    
        // Copy the data
        let ptr = data.Scan0
        let stride = data.Stride
        let bytes = stride * data.Height
        let values : byte[] = Array.zeroCreate bytes
        System.Runtime.InteropServices.Marshal.Copy(ptr,values,0,bytes)
    
        // Unlock the image
        image.UnlockBits(data)
    
        let pixelSize = 4 // <-- calculate this from the PixelFormat
    
        // Create and return a 3D-array with the copied data
        Array3D.init 3 Width Height (fun i x y ->
            values.[stride * y + x * pixelSize + i])
    

    (adopted from the C# sample on Bitmap.LockBits)

提交回复
热议问题