Pixel sorting ASDF

Processing users! i’m trying to translate this code to OF i’m not much familiar with processing but i’m has some advance any help would be awesome!
Processing:


OF:

can you include the image in the repo ?

1 Like

Sure.
Done in the data folder.

Is this not straight forward? I don’t think there is anything too complex about the code being translated

int getNextWhiteY(int _x, int _y) {
  int x = _x;
  int y = _y+1;
  color c; //just use ofColor 
  if(y < height) {
    //here you can convert the pixel color to a hsb value and use saturation to test with
    //http://openframeworks.cc/documentation/types/ofColor.html#!show_getHsb
    while((c = img.pixels[x + y * img.width]) < whiteValue) { 
      y++;
      if(y >= height) return height-1;
    }
  }
  return y-1;
}

just make sure the white value, black value, brightness value etc are between 0-255 since OF uses 8-bit color depth

anytime you see color just replace it with the openframeworks equivalent ofColor

as for the sort function it just sorts numbers, there is an c++ function for that too though I don’t know that it will handle ofColor the same way processing does so you may have to write your own sort function.

1 Like

Hi @jorgeav, I ported and made PR. But when I compare with a Processing output, column sorting seems wrong…

Processing color is simply an integer of a hex RGB code, but it’s padded by FF, so you can do ofColor::getHex() | 0xff000000 to reproduce color in oF.

1 Like

Hi there!

I will gladly give you some tips. But, instead of just a link to some code, it’s always best to also ask specific questions.

Instead of working with ofImage or screenGrabs, It’s best to work with a ofPixels object. So, in the setup, you can do:

img.loadImage("test");
pixelsObject = img.getPixelsRef();

With you want to draw it to the screen, you can set it to a ofTexture or ofImage again. Like this:

    textureObject.allocate(pixelsObject);
    textureObject.draw(0, 0);

Or:

imageObejct.setFromPixels(pixelsObject);
imageObject.draw(0,0);

I see you want to see the changes in realtime. So, don’t use a while statement, but a if. Something like:

if(column < img.width-1) {
        sortColumn();
        column++;
    }

if(row < img.height-1) {
    sortRow();
    row++;
}

textureObject.allocate(pixelsObject);
textureObject.draw(0, 0);

Like @micuat wrote, you need to remap the HEX values in OF, to equal Processing’s. By doing so, instead of using an array of color ( color[] unsorted = new color[sortLength]; ), you can use a vector of ints, and take advantage of c++ sort(). Like so:

vector<int> colors;

* the rest of the code *

sort(colors.begin(), colors.end());

Finally, to get/set the colors, you’ll have to mind to issues.

First, you are working with HEX values.
Second, Processing deals with the number of channels for you, OF doesn’t. (In your case, is RGB, so 3.)

So… The pixels[] function:

img.pixels[x + i + y * img.width]

Gets replaced with something like:

pixelObject.getColor((x + i + y * img.width) * 3).getHex()

I think this is more than enough to get you going and come back with more questions. :slight_smile: Good work!

1 Like

@hubris this:

img.loadImage("test");
pixelsObject = img.getPixelsRef();
...
textureObject.allocate(pixelsObject);
textureObject.draw(0, 0);

is making a copy of the pixels and then allocating a texture every frame which would be relatively slow. passing it again to the image would also make another copy. the best is to just work with the pixels the image has internally, by accessing them through getPixelsRef() whenever you need like:

img.getPixelsRef().getColor(....);
img.getPixelsRef().setColor(...);
img.update();

or if you want to avoid calling getPixelsRef() every time create a local reference in the method:

ofPixels & pixels = img.getPixelsRef();
pixels.getColor(...)
pixels.setColor(...)
img.update();

which will modify the pixels inside the image. finally calling update updates the internal texture in the ofImage whenever we modify the pixels externally

1 Like

Thanks @arturo!

I didn’t make it clear though, the copy of the pixels was only executed in the setup. Either way, it’s just smarter to pass the reference.

Regarding the colors in hex and the channel, is there a better approach? Thanks.

Thanks guys! this is amazing!

Small fix to give the same result:

if(column < img.width-1) {
    sortColumn();
    column++;
}

else if(row < img.height-1) {
    sortRow();
    row++;
}

and I noticed l96 and l142 I pushed has to be

if(sortLength < 0) break;

Anyways, I’m converting it to an addon which hopefully I’ll finish soon: https://github.com/micuat/ofxAsdfPixelSort