How to use pointers with two dimensional arrays

Our third party video graphic board API returns us a pointer to a memory block of incoming RGB data. Is there a way to assign this pointer to a two dimensional array in Swift and also to get the address of the array to send image date back to the C interface.


I implemented a test output in playground. When I use a one dimensional array and use this variable as a reference in CGImageCreate then the result image is black as expected.


var image = [UInt8](count: 1920 * 1080, repeatedValue:UInt8(0))
let providerRef = CGDataProviderCreateWithCFData(NSData(bytes: &image, length: 1920 * 1080))
let cgImage = CGImageCreate(1920, 1080, 8, 8, 1920, CGColorSpaceCreateDeviceGray(), bitmapInfo, providerRef, nil, false, CGColorRenderingIntent.RenderingIntentDefault)
if cgImage != nil {
    var uiImage = UIImage(CGImage: cgImage!)
}


But when I change the code to a two dimensional Swift array and pass the reference to CGImageCreate then it seems that it does not point to the correct image bytes (you see a lot of pixel artifacts in the upper area of the image). Maybe because I am using a variable and not a constan heret. But for image processing it is necessary that the pixels in the array can be modified.


var image = [[UInt8]](count: 1920, repeatedValue:[UInt8](count: 540, repeatedValue:UInt8(0)))

In C and C++ it is quite easy. You define two dimensional arrays and their variables are pointers to the memory bytes. Is there a way to assign memory blocks to two dimensional arrays in Swift as well. We could write a x/y coordinate conversion routine and also transfer the incoming video frames pixel by pixel to our Swift array but because of performance reasons we want to avoid this workaround.

C actually handles two-dimensional arrays in two different ways:

  • If the bounds are fixed, the two-dimensionality is just syntactic sugar. The values are laid out in memory contiguously and the compiled does the arithmetic required to access an element using its dimensions.

    I’ve pasted an example of this in below.

  • OTOH, the array bounds aren’t known, C treats a two-dimensional array as an array of pointers to rows. A classic example of this is

    argv
    .

Here’s an example of the first point:

static void test(void) {
    uint8_t a[3][2] = { {0, 0}, {0, 0}, {0, 0} };
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 2; j++) {
            printf("%p\n", &a[i][j]);
        }
    }
}

which prints:

0x7fff5fbffa3a
0x7fff5fbffa3b
0x7fff5fbffa3c
0x7fff5fbffa3d
0x7fff5fbffa3e
0x7fff5fbffa3f

showing that the array is laid out contiguously in memory, in row-major order.

So, to interoperate with C you have to specify which mechanism your C code is using. My guess is that you’re using fixed-bound arrays, in which case a good option would be to:

  1. put the data in a row-major contiguous array

  2. put that array in a struct

  3. implement your own two-dimension subscript functions on that struct

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
How to use pointers with two dimensional arrays
 
 
Q