I am trying to write a program to draw polygons and fill them with desired color.It is a simple painting application but the problem I am facing is when I draw polygons and paint them then a thin white line appears between the polygons. But when I don't antialias the polygons then the white line disappear but the polygons are not smooth. And the real problem is I need to have the polygons smooth as well as the white thin line also needs to be removed.
The class to paint the polygon is a:
public class GrayScaleManager{
private final VisualizerController controller;
private final BufferedImage grayScaledImage;
private final HashMap<ToolsModel, BufferedImage> grayScaleportionList;
public GrayScaleManager(VisualizerController drawingCanvas) {
this.controller = drawingCanvas;
grayScaleportionList = new HashMap<>();
grayScaledImage = toGray(Utility.bufferedImageDeepCopy(Util.getImg()));
}
public void grayScaleSelectedPortion(Graphics2D g, ToolsModel selectedArea) {
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setClip((Shape) selectedArea);
g.drawImage(grayScaledImage, 0, 0, null);
g.setClip(null);
}
private BufferedImage toGray(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
Color c = new Color(image.getRGB(j, i));
int red = (int) (c.getRed() * 0.3);
int green = (int) (c.getGreen() * 0.59);
int blue = (int) (c.getBlue() * 0.11);
int sum = red + green + blue;
Color newColor = new Color(sum, sum, sum);
image.setRGB(j, i, newColor.getRGB());
}
}
return image;
}
public VisualizerController getController() {
return controller;
}
public HashMap<ToolsModel, BufferedImage> getGrayScaleportionList() {
return grayScaleportionList;
}
}
And the image what I get when I run the code are
Actually the code revolves in a traingle (of 3 scenarios):
Scenario 1: If the code is done like this
public void grayScaleSelectedPotion(Graphics2D g, ToolsModel selectedArea){
g.setClip((Shape) selectedArea);
g.drawImage(grayScaledImage, 0, 0, null);
g.setClip(null);
}
Pros: 1. If multiple layers are drawn by coinciding each other with same color, the layers seem as a single one(Single layer). 2. No ghost white lines. Cons: 1. The edges of lines are not smooth.
Scenario 2: If rendering is applied, just applying below code inside above metod.
public void grayScaleSelectedPotion(Graphics2D g, ToolsModel selectedArea){
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setClip((Shape) selectedArea);
g.drawImage(grayScaledImage, 0, 0, null);
g.setClip(null);
}
Pros: 1. Single layer. 2. The edges are smooth. Cons: 1. Ghost white lines appears.
Scenario 3: If rendered but drawImage() removed
public void grayScaleSelectedPotion(Graphics2D g, ToolsModel selectedArea){
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setClip((Shape) selectedArea);
// g.drawImage(grayScaledImage, 0, 0, null);
g.setClip(null);
}
Pros: 1. The edges are smooth. 2. No ghost white lines.
Cons: 1. Multiple layers are distinctively seen even layers have same colors(which is not acceptable).
In conclusion, all the three cons in three scenarios should be cleared out.
After implementing the solution from @MadProgrammer the code looks as:
super.paintComponent(g);
grayImage = grayScaleManager.getGrayImage();
BufferedImage mask = new BufferedImage(img.getWidth(),img.getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
shadeList.forEach((shape)->{
g2d.setColor(shape.getColor());
if (shape.getColor().getAlpha() != NULL_ALPHA) {
//g2d.fill((Shape)shape);
}
g2d.fill((Shape)shape);
if (shape.getColor().getAlpha() == SELECTION_ALPHA) {
g2d.setStroke(new BasicStroke(1));
g2d.setColor(Color.red.brighter().brighter().brighter());
g2d.draw((Shape) shape);
}
});
// g2d.dispose();
masked = applyMask(mask,grayImage,AlphaComposite.SRC_IN);
g.drawImage(img,0,0,null);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 0.0f));
g.drawImage(masked, 0, 0, this);
g2d.dispose();
g.dispose();
}
/*Added methods for the changes applymask method*/
public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
System.out.println("I am in applymask");
BufferedImage maskedImage = null;
if (sourceImage != null) {
System.out.println("I am in applymask in if case");
int width = maskImage.getWidth(null);
int height = maskImage.getHeight(null);
maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D mg = maskedImage.createGraphics();
int x = (width - sourceImage.getWidth(null)) / 2;
int y = (height - sourceImage.getHeight(null)) / 2;
//mg.setColor(Color.RED);
//mg.drawImage(sourceImage, x, y, null);
mg.drawImage(sourceImage, 0, 0, null);
mg.setComposite(AlphaComposite.getInstance(method,0.0f));
mg.dispose();
}
return maskedImage;
}
But now the grayScaledImage is not painted and the polygons are overlapping, and when the grayScaledImage is added then we can't add other colors to the polygon.