Это, наверное, очень простой вопрос, но я не могу понять, как собрать все воедино. Этот вопрос и этот вопрос , а также эта страница в документации API все несколько намекают на ответ, но я не смог понять, что Мне нужно от них.
Так что сейчас я пытаюсь реализовать наивную небольшую программу, чтобы открыть изображение, вывести пиксели в массив, обработать их немного, а затем сохранить обновленные пиксели обратно как новое изображение. В данном конкретном случае я хочу взять среднее значение в окне 3х3 вокруг каждого пикселя как простое размытие. Конкретная операция не слишком важна (определенно есть более эффективные способы, я специально пытаюсь написать наивную версию прямо сейчас для последующего сравнения с другими версиями), но я не смог понять, как это сделать. бывает. Прямо сейчас у меня есть:
let accessClampedArrayWithDefault (arr: uint32[][]) width height def x y : uint32[] =
if x < 0 || x > width-1 || y < 0 || y > height-1 then
def
else
arr.[x + width * y]
let extractPixelParts (p: Rgba32) =
let R = uint32 p.R
let G = uint32 p.G
let B = uint32 p.B
let A = uint32 p.A
[|R; G; B; A|]
[<EntryPoint>]
let main argv =
use img = Image.Load(@"D:\Users\sampleimage.jpg")
let mutable out_img = img.Clone()
let pxs = img.GetPixelSpan().ToArray() |> Array.map extractPixelParts
let mutable (nps: uint32[][]) = Array.zeroCreate pxs.Length
let ac = accessClampedArrayWithDefault pxs img.Width img.Height [|0u;0u;0u;0u|]
for x in 0..img.Width-1 do
for y in 0..img.Height-1 do
let p = ac x y
for z in -1..1 do
for w in -1..1 do
let q = ac (x + z) (y + w)
nps.[x + y * img.Width] <- Array.zip p q |> Array.map (fun (a,b) -> a + b)
nps.[x + y * img.Width] <- Array.map (fun i -> float i / 9.0 |> uint32 ) nps.[x + y * img.Width]
let rpx = Array.collect (fun a -> Array.map byte a) nps
let out_img = Image.Load<Rgba32>(img.GetConfiguration(), rpx, Formats.Jpeg.JpegDecoder())
printfn "out_img's width is %d and height is %d" out_img.Width out_img.Height
, но происходит сбой за исключением строки let out_img =
. Если я не включаю часть JpegDecoder, то получаю сообщение об ошибке об отсутствующем декодере, но если я его включаю, я получаю сообщение об ошибке об отсутствующем SOI.
Итак, мой вопрос: как я могу извлечь пиксели и работать с ними / каждым каналом с переменным размером, большим, чем 8 бит (например, 32 бита), чтобы я мог выполнять промежуточные операции, которые не могут быть представлены в 8 бит на канал, перед тем как преобразовать окончательный результат обратно в байты, а затем восстановить его обратно во что-то, что можно сохранить на диск как образ?
Возможно, я забыл упомянуть кое-что важное, поэтому, пожалуйста, не стесняйтесь спрашивать разъяснения :) Спасибо.