Image array rotation

Hello

I have a unsigned char array 1d representing an rgb image with a size of widthheight3 (3202403) and would like to rotate 90 degree clockwise so i end with a (2403203)

I know i can pass that array to a ofImage or a opencv mat and do the rotation but i would like to rotate the array instead… but i can’t wrap my head around as is 3 channel and not 1 that will be easier…

Any clues? Thanks in advance

Hi @pandereto,

So if I understand you correctly you want to transpose the array ?

If so, you won’t be able to do this inplace for a non-square array (as far as I know), but you can create a second one and switch rows to columns and inversely.

Something akin to this (no tested) :

#include <array>

constexpr int kWidth = 320;
constexpr int kHeight = 240;
constexpr int kAttrib = 3;
constexpr int kSize = kWidth * kHeight * kAttrib;

std::array<float, kSize> src;
std::array<float, kSize> dst;

fillSourceArray(src);

// Transpose src to dst.
for (int y=0; y<kHeight; ++y) {
  for (int x=0; x<kWidth; ++x) {
    const int srcIndex = kAttrib * (y * kWidth + x);
    const int dstIndex = kAttrib * (x * kHeight + y);

    dst[dstIndex + 0] = src[srcIndex + 0];
    dst[dstIndex + 1] = src[srcIndex + 1];
    dst[dstIndex + 2] = src[srcIndex + 2];
  }
}
2 Likes

Hi, I will suggest you to use ofPixels or openCv and it will solve your problem, yet I dont understand what you really mean to “rotate the array” since it is a 1D it is not possible. If what you mean is that you want to do it inplace without creating a secondary array it will be a lot harder.
as for having the 3 channels there, you can go like


for(size_t i = 0; i < height; i++){
for(size_t j = 0; j < width; i++){

size_t index = i*width + j;

pixels[index];//channel 1
pixels[index+1];//channel 2
pixels[index+2];//channel 3
}
}

Sorry i did not explained myself ok, i have an image sent to a microcontroller in landscape [WxH] and i want to rotate it to [HxW] portrait, yep i can use ofPixels or OpenCv but was curious on how to do that without.

@DarkSalmon thanks i will try

I see. @DarkSalmon ´s code should do it

Hey I think DarkSalmon’s code will work too. I tested this loop for a 90 deg cloclwise rotation. Also, the ofPixels::rotate90() function does this, so you could look at the class function in ofPixels.cpp, but I had a hard time following it to some degree.

This was my ofApp::setup() function in the code that worked:

void ofApp::setup(){

    ofPixels pixels;
    ofLoadImage(pixels, "image.jpg");
    int num = pixels.getWidth() * pixels.getHeight() * pixels.getNumChannels();
    unsigned char pix[num] = {0};
    int width = pixels.getWidth();
    int height = pixels.getHeight();

    for(size_t j{0}; j < height; j++) // each row
    {
        for(size_t i{0}; i < width; i++)
        {
            // the x,y coordinate in the rotated image (90, clockwise)
            int x = height  -  j;
            int y = i;
            // corresponding index values for each array
            int index = (j * width + i) * 3;
            int indexPix = ((y * height) + x) * 3;
            // set the pixel values for an RGB image
            pix[indexPix] = pixels[index];
            pix[indexPix + 1] = pixels[index + 1];
            pix[indexPix + 2] = pixels[index + 2];
        }
    }

    texture.loadData(pix, height, width, GL_RGB);
}

And this will do it in 1 loop!

    for(size_t i{0}; i < pixels.size(); i+= 3)
    {
        int x = (i / 3) % width;
        int y = (i / 3) / width;
        int indexPix = (x * height + y) * 3;
        pix[indexPix] = pixels[i];
        pix[indexPix + 1] = pixels[i + 1];
        pix[indexPix + 2] = pixels[i + 2];
    }

Edit: DarkSalmon’s code will rotate 90 deg counter clockwise.

I have tested it and indeed DarkSalmon as others commented is right. Thanks