Donnerstag, 6. Oktober 2011

Custom Shape in Java based on an Image

First Blog entry in years, quick one that I think some people could use. A quick code snippet on how to create a custom Shape based on a Black/White Bitmap. This code is based on a Class from Andrew Thompson:
http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape-in-java/7059497#7059497

I changed it, and created an enhanced "Hack", that creates the custom Shape somewhat fast, depending on the complexity of the Shape.
(Use RGB(0,0,0) for the Pixels that should be visible, everything else will be invisible).

The best way would be to implement an own Shape or extend an existing Implementation, but I don't know anything about Bézier curves and such.

(I'm still a student and german, so please excuse the sloppy coding and language ...)
import java.awt.*;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;


/**
* CustomShape
* based on a Class from Andrew Thompson *
* Source: http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape-in-java/7059497#7059497
* @author Samuel Schneider, Andrew Thompson
*
*
*/
class CustomShape {
private BufferedImage image=null;
/**
* Creates an Area with PixelPerfect precision
* @param color The color that is draws the Custom Shape
* @param tolerance The color tolerance
* @return Area
*/
public Area getArea(Color color, int tolerance) {
if(image==null) return null;
Area area = new Area();
for (int x=0; x
for (int y=0; y
Color pixel = new Color(image.getRGB(x,y));
if (isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x,y,1,1);
area.add(new Area(r));
}
}
}
return area;
}
public Area getArea_FastHack() {
//Assumes Black as Shape Color
if(image==null) return null;
Area area = new Area();
Rectangle r;
int y1,y2;
for (int x=0; x
y1=99;
y2=-1;
for (int y=0; y
Color pixel = new Color(image.getRGB(x,y));
//-16777216 entspricht RGB(0,0,0)
if (pixel.getRGB()==-16777216) {
if(y1==99) {y1=y;y2=y;}
if(y>(y2+1)) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
y1=y;y2=y;
}
y2=y;
}
}
if((y2-y1)>=0) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
}
}
return area;
}

public static boolean isIncluded(Color target, Color pixel, int tolerance) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return(
(rP-tolerance<=rT) && (rT<=rP+tolerance) &&
(gP-tolerance<=gT) && (gT<=gP+tolerance) &&
(bP-tolerance<=bT) && (bT<=bP+tolerance) );
}
public CustomShape(String path) {
try {
BufferedImage image = ImageIO.read(new File(path));
this.image = image;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}