3

i have a class that draws a shape from a png image, so that i can use the shape to draw the border of custom buttons that i need for my project. here's the code for the class to draw the shape of an image:

public class CreateShapeClass {
    public static Area createArea(BufferedImage image, int maxTransparency) {
        Area area = new Area();
        Rectangle rectangle = new Rectangle();
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                int rgb = image.getRGB(x, y);
                rgb = rgb >>> 24;
                if (rgb >= maxTransparency) {
                    rectangle.setBounds(x, y, 1, 1);
                    area.add(new Area(rectangle));
                }
            }
        }
        return area;
    }
}

however, this takes a very long time to process, and I thought that by pre-drawing the shapes in my main application and then storing them into an array and passing to other classes, it will reduce the rendering time. however, the time taken for the paintBorder() method to draw out the border of the button takes a pretty long time too (although shorter than the time required to draw the shape), because the shape generated by the class above is filled and not empty. I've tried to draw shapes using java2d, for example, Ellipse2D, and the rendering of the button only takes a very short time. anyone experienced in this field can teach me how do i generate a shape that is the border of a BufferedImage? i use the class above to create the shape from PNG image with a transparent background.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
csharpnewbie
  • 421
  • 1
  • 9
  • 18
  • sorry, can you help me see, which parts are used for getting the outline? i'm not very familiar with shapes and such :/ please guide me. – csharpnewbie Jun 01 '12 at 10:30
  • ah, ok i got that thanks! anyway, this method is really really fast as compared to the class i used above.. the result comes out in less than a second! unlike the above method, which takes around +-13 secs to process. thanks again! – csharpnewbie Jun 01 '12 at 10:56

1 Answers1

5

For tips, look at Smoothing a jagged path. The algorithm to obtain the (crude) outline was relatively quick in the final versions. Creating a GeneralPath is astonishingly faster than appending Area objects.

The important part is this method:

public Area getOutline(Color target, BufferedImage bi) {
    // construct the GeneralPath
    GeneralPath gp = new GeneralPath();

    boolean cont = false;
    int targetRGB = target.getRGB();
    for (int xx=0; xx<bi.getWidth(); xx++) {
        for (int yy=0; yy<bi.getHeight(); yy++) {
            if (bi.getRGB(xx,yy)==targetRGB) {
                if (cont) {
                    gp.lineTo(xx,yy);
                    gp.lineTo(xx,yy+1);
                    gp.lineTo(xx+1,yy+1);
                    gp.lineTo(xx+1,yy);
                    gp.lineTo(xx,yy);
                } else {
                    gp.moveTo(xx,yy);
                }
                cont = true;
            } else {
                cont = false;
            }
        }
        cont = false;
    }
    gp.closePath();

    // construct the Area from the GP & return it
    return new Area(gp);
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 1
    You're welcome. Glad that my playing around with that code helped someone. :) – Andrew Thompson Jun 01 '12 at 12:10
  • @AndrewThompson I know this is kind of a necro but when I run your code I get the error that a initial `moveTo` is missing... I tried to implement something like this `if(first) { gp.moveTo(xx,yy); first = false; } else { gp.lineTo(xx,yy); }` to the code but it did not help... Thanks in advance. – nyxaria Feb 21 '15 at 23:35
  • @AndrewThompson I'm working on linux with jdk 6 arm-7 if that helps. – nyxaria Feb 22 '15 at 00:11
  • *"I tried to implement something like this.."* The code already correctly implements it using the `cont` attribute. If you cannot get it working, I suggest you 1) Start a new question. 2) Post an ***[MCVE](http://stackoverflow.com/help/mcve)*** of your attempt. – Andrew Thompson Feb 22 '15 at 00:41