Dak*_*kaa 4 f# f#-interactive f#-3.0
我想使用 LockBits 方法替换 GetPixel 和 SetPixel,所以我遇到了这个F# 延迟像素读取
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])
Run Code Online (Sandbox Code Playgroud)
在代码末尾,它返回一个包含复制数据的 3D 数组。
那么3D阵列是复制的图像,如何编辑3D阵列的像素,例如更改颜色?像素大小有什么用?为什么将图像存储在 3D 字节数组而不是 2D 中?
例如,如果我们想使用 2D 数组,并且我想更改指定像素的颜色,我们该怎么做?
我们是在字节数组外部像素函数中对给定的复制图像进行操作,还是在解锁图像之前在像素函数内部进行操作?
如果我们不再使用GetPixel或SetPixel呢?如何从复制的图像字节[]中检索像素的颜色?
如果您不明白我的问题,请解释一下我如何使用上面的代码来执行操作,例如给给定图像的每个像素的 R、G、B“添加 50”,而不使用 getPixel、setPixel
3D 数组的第一个分量是颜色分量。因此,索引 1,78,218 处的值是 78,218 处像素的蓝色分量的值。
像这样:
Array2D.init Width Height (fun x y ->
let color i = values.[stride * y + x * pixelSize + i] |> int
new Color(color 0, color 1, color 2)
Run Code Online (Sandbox Code Playgroud)由于图像是复制的,因此无论您在解锁图像之前还是之后对其进行修改,都不会产生任何影响。锁定是为了确保在您进行实际复制时没有人更改图像。
该values数组是将 2D 数组展平为平面数组。2D 索引.[x,y]位于stride * y + x * pixelSize。RGB 分量各有一个字节。这解释了为什么在 x,y 处找到第 i 个颜色分量:
values.[stride * y + x * pixelSize + i] |> int
Run Code Online (Sandbox Code Playgroud)要为每个像素添加 50,使用原始 3D 数组更容易。假设您有一张图像myImage:
pixels (myImage) |> Array3D.map ((+) 50)
Run Code Online (Sandbox Code Playgroud)
这个类型是Array3D<Color>, not Image。如果您需要 an Image,您需要以某种方式从Array3D您现在拥有的 构建它。
| 归档时间: |
|
| 查看次数: |
1940 次 |
| 最近记录: |