3
\$\begingroup\$

This code is intended to be used with an image manipulation library that I'm working on, and the goal is to take the raw byte[] data from an image, and transform it into a 2D array where each position on the array has a value corresponding to the pixel coordinates of the image.

Comments concerning how to do this faster or more aligned with F# standards, or concerning style and formatting, are very much appreciated. I'm still learning F# so I need all the help I can get.

let Transform2D (pArrayWidth:int) (pArray:byte[]) = 
 let tHeight = pArray.Length / pArrayWidth
 let tImageArray = Array.zeroCreate<byte[]> tHeight
 let mutable tStart = 0
 let mutable tFinish = tStart + pArrayWidth - 1 // 0 indexed array
 for tRowIndex in [ 0 .. tHeight ] do
 tImageArray.[tRowIndex] <- pArray.[tStart .. tFinish]
 tStart <- tStart + pArrayWidth
 tFinish <- tFinish + pArrayWidth
 tImageArray
RubberDuck
31.1k6 gold badges73 silver badges176 bronze badges
asked Jul 17, 2014 at 23:31
\$\endgroup\$
3
  • \$\begingroup\$ So, the image is a greyscale 8-bit bitmap? (Otherwise, one byte per pixel wouldn't make sense.) \$\endgroup\$ Commented Jul 18, 2014 at 2:37
  • \$\begingroup\$ Ummmmm, actually now that you mentioned that I think I might need to go review that bit of information. \$\endgroup\$ Commented Jul 18, 2014 at 2:38
  • \$\begingroup\$ Does the transformation part seem ok though, even if I need to increase the width that I'm slicing? \$\endgroup\$ Commented Jul 18, 2014 at 16:26

1 Answer 1

1
\$\begingroup\$

You should consider whether byte[][] is really the best type to represent a bitmap in F#.

On one hand, arrays are inherently mutable and don't work well with pattern matching, so you might want to consider using list<list<byte>>, especially if performance is not critical.

On the other hand, a rectangular array of bytes is more accurately modeled as byte[,] (2D array), not byte[][] (array of arrays, a.k.a. jagged array). Though again, this is going to be slower than the original option.


for tRowIndex in [ 0 .. tHeight ] do

This has to be tHeight - 1, otherwise your code will fail with an exception.


let mutable tStart = 0
let mutable tFinish = tStart + pArrayWidth - 1 // 0 indexed array
for tRowIndex in [ 0 .. tHeight ] do
 tImageArray.[tRowIndex] <- pArray.[tStart .. tFinish]
 tStart <- tStart + pArrayWidth
 tFinish <- tFinish + pArrayWidth
tImageArray

You can use sequence expressions to create arrays in a functional way. Here, that would look something like:

[|
 for tRowIndex in [ 0 .. tHeight - 1 ] do
 let tStart = tRowIndex * pArrayWidth
 let tFinish = tStart + pArrayWidth - 1
 yield pArray.[tStart .. tFinish]
|]

In both cases, a very similar syntax (for .. in) is used, but my version doesn't use any mutable variables and is very similar to list comprehensions in other functional languages.

answered Jul 19, 2014 at 20:40
\$\endgroup\$
3
  • \$\begingroup\$ I'm actually accustomed to using list comprehensions in python, but I'm trying to adjust to F# from a C# mindset, so it's taking a bit of effort to see problems in a new way. I have a bit of confusion understanding what you mean concerning performance issues with the 2D array vs an array of arrays, are you saying that the byte[][] is fastest, byte[,] is fastest, or the list<list<byte>> is fastest? \$\endgroup\$ Commented Jul 20, 2014 at 0:14
  • 1
    \$\begingroup\$ @KortPleco If you know C#, then you should know LINQ, which is also quite similar to list comprehensions (using yet another syntax). And I meant that byte[][] is going to be fastest. \$\endgroup\$ Commented Jul 20, 2014 at 9:05
  • \$\begingroup\$ great, thanks for the clarification. This is going to be very speed sensitive, so that's important for me to know. =) \$\endgroup\$ Commented Jul 20, 2014 at 18:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.