Ghost white line appears when smoothing polygons in JAVA

I am trying to write a program to draw polygons and fill them with the desired color. This is a simple drawing application, but the problem I am facing is when I draw polygons and draw them, then a thin white line appears between the polygons. But when I do not smooth the polygons, then the white line disappears, but the polygons are not smooth. And the real problem is that I need the polygons to be smooth, and I also need to remove the white thin line.

Class for drawing a polygon:

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 that I get when I run the code, enter image description here

In fact, the code rotates in a chain (from 3 scenarios):

Scenario 1 . If the code is executed as follows

    public void grayScaleSelectedPotion(Graphics2D g, ToolsModel selectedArea){
         g.setClip((Shape) selectedArea);
         g.drawImage(grayScaledImage, 0, 0, null);
         g.setClip(null);
    }

: 1. , (Single layer). 2. . : 1. .

2. , .

   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);
    }

: 1. . 2. . : 1. .

3: , drawImage()

     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);
      }

: 1. . 2. .

: 1. , ( ).

, .

@MadProgrammer :

    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;

}

grayScaledImage , , ScaledImage, .

+4
3

, , . setClip " ", .

, , "". "" , , , .

, ...

...

// The master image or background
master = ImageIO.read(...);
// Generate a gray scaled version of the master image
// This is what we will be cutting out
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
grayScaled = op.filter(master, null);

int width = master.getWidth() / 4;
int height = master.getHeight() / 4;

// This simply what I'm using as the base "selection"
// But for all intents purpose, it can be anything which can
// be painted through Graphics
Shape shape = new Rectangle2D.Double(0, 0, width, height);

// The base mask, not that it transparent
BufferedImage mask = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = mask.createGraphics();
// Offset the location to apply the "selection"
g2d.translate((master.getWidth() - shape.getBounds().width) / 2, (master.getHeight() - shape.getBounds().height) / 2);
// Any color will do, it could even have an alpha applied
g2d.setColor(Color.BLUE);
// Rotate it a bit, because square is boring...
shape = new Path2D.Double(shape, AffineTransform.getRotateInstance(Math.toRadians(45.0), width / 2, height / 2));
// Fill the area
g2d.fill(shape);
// Rotate again, so you can see that we're compounding the selection
shape = new Path2D.Double(shape, AffineTransform.getRotateInstance(Math.toRadians(45.0), width / 2, height / 2));
// Fill the new selection
g2d.fill(shape);        
// Clean up 
g2d.dispose();

// Now, apply the mask to the image to get a "cut out"
masked = applyMask(mask, grayScaled, AlphaComposite.SRC_IN);

. , mask mask, grayScaled masked.

, , masked master -, .

Example

"" , ;)

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage master;
        private BufferedImage grayScaled;
        private BufferedImage masked;

        public TestPane() {
            try {
                master = ImageIO.read(...);
                ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
                grayScaled = op.filter(master, null);

                int width = master.getWidth() / 4;
                int height = master.getHeight() / 4;

                Shape shape = new Rectangle2D.Double(0, 0, width, height);
                shape = new Path2D.Double(shape, AffineTransform.getRotateInstance(Math.toRadians(45.0), width / 2, height / 2));

                BufferedImage mask = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = mask.createGraphics();
                g2d.translate((master.getWidth() - shape.getBounds().width) / 2, (master.getHeight() - shape.getBounds().height) / 2);
                g2d.setColor(Color.BLUE);
                g2d.fill(shape);
                shape = new Path2D.Double(shape, AffineTransform.getRotateInstance(Math.toRadians(45.0), width / 2, height / 2));
                g2d.fill(shape);            
                g2d.dispose();

                masked = applyMask(mask, grayScaled, AlphaComposite.SRC_IN);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return master == null ? getPreferredSize() : new Dimension(master.getWidth(), master.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (master != null && masked != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - master.getWidth()) / 2;
                int y = (getHeight() - master.getHeight()) / 2;

                g2d.drawImage(master, x, y, this);
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
                g2d.drawImage(masked, x, y, this);
                g2d.dispose();
            }
        }

    }

    public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {

        BufferedImage maskedImage = null;
        if (sourceImage != null) {

            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.drawImage(sourceImage, x, y, null);
            mg.setComposite(AlphaComposite.getInstance(method));

            mg.drawImage(maskImage, 0, 0, null);

            mg.dispose();
        }

        return maskedImage;

    }

}

, , , ( ) ;)

+1

, Area, .

0

, , 2D, , 2D, .

-2
source

Source: https://habr.com/ru/post/1669116/


All Articles