简体   繁体   中英

efficient cropping calculation in processing

I am loading a png in processing. This png has a lot of unused pixels around the actual image. Luckily all those pixels are completely transparent. My goal is to crop the png to only show the image and get rid of the unused pixels. The first step would be to calculate the bounds of the image. Initially i wanted to check every pixel for alpha value and see if that pixel is the highest or lowest coordinate for bounds. like this:

------
------
--->oo
oooooo
oooooo

Then i realized i only needed to do this until the first non-alpha pixel and repeat it backwards for highest coordinate bound. Like this:

------
-->ooo
oooooo
ooo<--
------

This would mean less calculating for the same result. However the code i got out of it still seems to be very complex. Here it is:

class Rect {  //class for storing the boundries
  int xMin, xMax, yMin, yMax;
  Rect() {

  }
}

PImage gfx;

void setup() {
  size(800, 600);
  gfx = loadImage("resources/test.png");
  Rect _bounds = calcBounds();  //first calculate the boundries
  cropImage(_bounds);  //then crop the image using those boundries
}

void draw() {

}

Rect calcBounds() {
  Rect _bounds = new Rect();
  boolean _coordFound = false;
  gfx.loadPixels();

  //x min bounds
  for (int i = 0; i < gfx.width; i++) {  //rows
    for (int i2 = 0; i2 < gfx.height; i2++) {  //columns
      if (alpha(gfx.pixels[(gfx.width * i2) + i]) != 0) {
        _bounds.xMin = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //x max bounds
  _coordFound = false;
  for (int i = gfx.width - 1; i >= 0; i--) {  //rows
    for (int i2 = gfx.height - 1; i2 >= 0; i2--) {  //columns
      if (alpha(gfx.pixels[(gfx.width * i2) + i]) != 0) {
        _bounds.xMax = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //y min bounds
  _coordFound = false;
  for (int i = 0; i < gfx.height; i++) {  //columns
    for (int i2 = 0; i2 < gfx.width; i2++) {  //rows
      if (alpha(gfx.pixels[(gfx.width * i) + i2]) != 0) {
        _bounds.yMin = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //y max bounds
  _coordFound = false;
  for (int i = gfx.height - 1; i >= 0; i--) {  //columns
    for (int i2 = gfx.width -1; i2 >= 0; i2--) {  //rows
      if (alpha(gfx.pixels[(gfx.width * i) + i2]) != 0) {
        _bounds.yMax = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  return _bounds;
}

void cropImage(Rect _bounds) {
  PImage _temp = createImage((_bounds.xMax - _bounds.xMin) + 1, (_bounds.yMax - _bounds.yMin) + 1, ARGB);
  _temp.copy(gfx, _bounds.xMin, _bounds.yMin, (_bounds.xMax - _bounds.xMin) + 1, (_bounds.yMax - _bounds.yMin)+ 1, 0, 0, _temp.width, _temp.height);
  gfx = _temp;  //now the image is cropped
}

Isnt there a more efficient/faster way to calculate the bounds of the image? And i do still want the boundries coordinates afterward instead of just cutting away at the image during calculation.

If you store the last completely empty line found for eg the horizontal minimum and maximum scan in a variable, you can use that to constrain your vertical scanning to only the area that has not yet been checked for being empty, instead of having to scan full columns. Depending on the amount and shape of the croppable area that can save you quite a bit - See the schematic for a visual explanation of the modified algorithm:

优化原理图


By the way, in your //x min bounds scan you seem to be iterating over the width in both for loops, should be height in one though? (unless your images are all square of course :))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM