1

I have a sequence of elements [(12, 34); (56, 78); ...] and I want to turn it into [(XXX, XXX, XXX); (XXX, XXX, XXX); ...] where (XXX, XXX, XXX) is the (R, G, B) of the given tuple/coordinates, e.g., (12, 34). According to .NET documentation, System.Drawing.Bitmap.GetPixel returns System.Drawing.Color and you can just call Color.R, Color.B and Color.G to get the colour value as a byte.

This is what I've got so far:

let neighbourColor (img : System.Drawing.Bitmap) (s : seq<int * int>) =
 s |> Seq.collect(fun e -> s |> img.GetPixel(fst(e), snd(e)) |> Seq.map(fun c -> (c.R, c.G, c.B)))

For every element e in sequence s, get the color of e which is a tuple of coordinates on image img, then pass it to Seq.map to transform it into (Red, Green, Blue) and collect it as a new sequence neighbourColor.

Basically I want to turn seq<int*int> into seq<byte*byte*byte>.

Søren Debois
  • 5,598
  • 26
  • 48
Dakaa
  • 199
  • 9

2 Answers2

2
let neighbourColor (img:Bitmap) coords =
   coords |> Seq.map (fun (x, y) -> let c = img.GetPixel (x, y) in c.R, c.G, c.B)

In general, it is probably better style to only explicitly specify a parameter's type when it cannot be inferred (in this case coords is already implicitly understood to be a seq<int*int>).

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • [Meaning of keyword “in” in F#](http://stackoverflow.com/questions/546287/meaning-of-keyword-in-in-f) – ChaosPandion Apr 04 '14 at 00:21
  • 1
    @ChaosPandion : I only used it here because I was going for a one-liner. :-] – ildjarn Apr 04 '14 at 00:23
  • 1
    Just wanted to make it convenient for people to understand the syntax as it is used rarely. – ChaosPandion Apr 04 '14 at 00:26
  • let neighbourColor (img : System.Drawing.Bitmap) (s : seq) = s |> Seq.map(fun(i, j) -> (img.GetPixel(i, j).R, img.GetPixel(i, j).G, img.GetPixel(i, j).B)) //I figured it out, but yours is cleaner. – Dakaa Apr 04 '14 at 00:37
  • 1
    @user3487239 : And also more efficient - `GetPixel` is a _very_ expensive call, so calling it only once vs. thrice will likely have a noticeable impact. – ildjarn Apr 04 '14 at 00:39
  • Is system.drawing.bitmap.lockbits the faster way to go if I want recolor an entire image without using get/set pixel. – Dakaa Apr 04 '14 at 01:39
  • @user3487239 : Yes, by orders of magnitude. Just hope you don't have more than one type of palette. ;-] – ildjarn Apr 04 '14 at 01:43
1
let (|RGB|) (c:Color)=RGB(c.R,c.G,c.B)
let Test (img:Bitmap)=Seq.map (img.GetPixel>>function RGB(r,g,b)->r,g,b)
Dima_
  • 81
  • 5