What I am trying to achieve is getting a mask of an image
, converting it into an Array
with the dimensions (image.getWidth(), image.getHeight())
, then getting all the pixels and seeing if they have an alpha value of 0
.
IF they do, then:
1
for the x, y
co-ordinate that I am examining at the moment. ELSE:
0
for the x, y
co-ordinate that I am examining at the moment. Up to this point, I know how to program this. If you are interested, this is the code I am using:
private int[] createMask(BufferedImage image) {
final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
final boolean hasAlphaChannel = image.getAlphaRaster() != null;
int[][] result = new int[height][width];
if (hasAlphaChannel) {
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += 4) {
int alpha = pixels[pixel];
if(alpha != 0) {
result[row][col] = 1;
} else {
result[row][col] = 0;
}
if (col == width) {
col = 0;
row++;
}
}
}
return result;
}
After I get this mask, I am attempting to use this Array
to draw a Polygon
via this code, or an alternation of it (obtained from http://docs.oracle.com/javase/tutorial/2d/geometry/arbitrary.html ) :
int x1Points[] = {0, 100, 0, 100};
int y1Points[] = {0, 50, 50, 0};
GeneralPath polygon =
new GeneralPath(GeneralPath.WIND_EVEN_ODD,
x1Points.length);
polygon.moveTo(x1Points[0], y1Points[0]);
for (int index = 1; index < x1Points.length; index++) {
polygon.lineTo(x1Points[index], y1Points[index]);
};
polygon.closePath();
g2.draw(polygon);
However, I need to create a method which gives me all the co-ordinates in an Array
consisting of Point
objects to go around the image to essentially create a "mask".
public Point[] getCords(int[] mask) {
ArrayList<Point> points = new ArrayList<Point>(); //you can change this to whatever you want to use
//get coords to surround the mask
// >> involving `0` (for transparent) and `1` (non transparent)
// >> these are contained in the `mask` Array...
return points.toArray(new Points[0]);
So, to conclude:
int[]
array which contains the values 1
's and 0
's, the former for non-transparent pixel and latter for transparent pixel, respectively. (link to related java code below)
To create the mask border, do the following: for each pair of coordinates (x,y) check if any one of 8 its neighboring points is outside the mask. However, keep in mind that the resulting mask isn't necessarily 1 pixel wide and vectorizing it might be non-trivial, as in this example (white is the masked area, red is the mask border inside the mask, black is unmasked area):
Luckily, even if you get a wider-than-1-pixel border in some places in your mask, you can workaround that by rejecting some pixels of the mask from that mask building a submask that is polygonizable. The following image shows the submask's border in blue:
I implemented such algorithm a while ago. There is the code you can use, but it is quite tightly coupled with my solution, however you could find some insights in it: Thick mask border resolution . Its idea is that from the initial mask you build a submask by flood-filling original mask with a predicate that checks that a cell of submask's border has at most 2 cardinal direction neighbors (ordinal direction neighbors don't matter here).
Once you got the blue submask's border, build a graph where vertices are points of submask's border, and edges are between cardinally neighboring points. Then traverse each component of that graph, and for each component you get a list of points that form your polygons.
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.