Looping through array: performance problem
in
Programming Questions
•
8 months ago
Hi there,
I have a performance problem with my Processing-code and hours of pondering about it rather drove me crazy instead of making it any better. I have to say that do not have too much experience in _good_ coding with lots of elegance, it just always worked out somehow. Maybe some elegance is needed here.. Thank you for reading!
=== About the project: woody ===
So, this script is about controlling an arduino, who controls two steppers (x and y) and a servo to sort of "write" with a soldering iron pixel per pixel. Cnc-like. Processing first prepares an image and sends coordinates and brightness for a pixel to arduino. When Arduino says: "go on", Processing sends the next pixel and so on. So when Arduino calls, the data need to be ready to send, and here lies the problem.
=== Problem ===
Within setup(), a 2d-array (braunmapB[][]) is created to store all pixels of an image.
Each pixel has a certain brightness that is being translated to miliseconds (for the soldering iron to burn on the workpiece). When the brightness is below a certain threshold, it is 0 in the array (no burning). So far, so good.
Called by setup():
Within draw(), the following function picks the next pixel and sends it to arduino (if > 0). The bold part is crucial: Every second row of the array is read backwards, so that when a full row of pixels has been sent to the arduino, the next pixel sent is at the same (or near) x position but in the next row. That means an improvement of speed, because the soldering iron doesnt always have to revert to the first colum.
I have a performance problem with my Processing-code and hours of pondering about it rather drove me crazy instead of making it any better. I have to say that do not have too much experience in _good_ coding with lots of elegance, it just always worked out somehow. Maybe some elegance is needed here.. Thank you for reading!
=== About the project: woody ===
So, this script is about controlling an arduino, who controls two steppers (x and y) and a servo to sort of "write" with a soldering iron pixel per pixel. Cnc-like. Processing first prepares an image and sends coordinates and brightness for a pixel to arduino. When Arduino says: "go on", Processing sends the next pixel and so on. So when Arduino calls, the data need to be ready to send, and here lies the problem.
=== Problem ===
Within setup(), a 2d-array (braunmapB[][]) is created to store all pixels of an image.
Each pixel has a certain brightness that is being translated to miliseconds (for the soldering iron to burn on the workpiece). When the brightness is below a certain threshold, it is 0 in the array (no burning). So far, so good.
Called by setup():
- void initBild() {
- braunmapB = new int[img.width][img.height]; // ms Braunwerte
- for (int gridY = 0; gridY < img.height; gridY++) {
- for (int gridX = 0; gridX < img.width; gridX++) {
- color farbe = img.get(gridX, gridY);
- float braunwert =red(farbe)*0.222+green(farbe)*0.707+blue(farbe)*0.071;
- float braunwertRGB = braunwert;
- braunwert = map(braunwert, 255, 0, brenndauerHell, brenndauerDunkel);
- if (braunwert < schwellenwert) { // Schwellenwert unterschritten
- braunmapB[gridX][gridY] = 0;
- braunwert = 0;
- }
- else {
- braunmapB[gridX][gridY] = int(braunwert);
- pointsToBurn++;
- noStroke();
- if (firstInit) {
- braunXLast = gridX;
- braunYLast = gridY;
- firstInit = false;
- }
- fill(255-int(braunwertRGB));
- rect (gridX+21+10+img.width, gridY+276, 1, 1);
- }
- }
- }
- }
Within draw(), the following function picks the next pixel and sends it to arduino (if > 0). The bold part is crucial: Every second row of the array is read backwards, so that when a full row of pixels has been sent to the arduino, the next pixel sent is at the same (or near) x position but in the next row. That means an improvement of speed, because the soldering iron doesnt always have to revert to the first colum.
- void brennePunkt() {
- if (burning && !burningFinish) { // burning-button betätigt und nicht fertig gebrannt
- if (braunmapB[braunX][braunY] > 0) { // sende kein weiß an Woody
- // X
- woodyControlFull = woodyControl[2] + (braunX*int(multiX)) + "/";
- myPort.write(woodyControlFull);
- // Y
- woodyControlFull = woodyControl[3] + (braunY*int(multiY)) + "/";
- myPort.write(woodyControlFull);
- // B
- int braunwertOut = braunmapB[braunX][braunY];
- woodyControlFull = woodyControl[4] + braunwertOut +"/";
- myPort.write(woodyControlFull);
- woodyReady = false;
- pointsPosition++;
- }
- if (zeile == 0) { // Zeile 0
- if (braunX + 1 == img.width) { // Zeile 0 (links -> rechts) durch
- zeile = 1;
- if (braunY+1 == img.height) {
- burningFinish = true;
- }
- else {
- braunY++;
- }
- }
- else { // Zeile 0 noch nicht durch
- braunX++;
- }
- }
- else { // Zeile 1
- if (braunX == 0) { // Zeile 1 (rechts -> links) durch
- zeile = 0;
- if (braunY+1 == img.height) {
- burningFinish = true;
- }
- else {
- braunY++;
- }
- }
- else { // Zeile 1 noch nicht durch
- braunX--;
- }
- }
- }
- }
The code works but is just too slow, because I think all the if/else cases to go through the array is not very fast. If the image contains lots of fileds that are just 0 (where the coordniates and brightness are not sent to the arduino), the loop will have to pass all of these, before there is a pixel to send.
I don't really know, how to avoid this, maybe there is another way to flip every second row in the array and have the next valid value at call...?
I'd love to hear your opinions about it, maybe just a basic appoach. And sorry for the german variables and comments, but I think it should be readable though..
Best, Philip
I don't really know, how to avoid this, maybe there is another way to flip every second row in the array and have the next valid value at call...?
I'd love to hear your opinions about it, maybe just a basic appoach. And sorry for the german variables and comments, but I think it should be readable though..
Best, Philip
1