javasvgsvg-salamander

SVG Circle Resolution in Java


I have a circle represented in SVG by :

    <circle cx="50" cy="50" r="50" stroke="black" stroke-width="1" style="fill:white"/>

I then convert this circle to a BufferedImage in Java with width and height = 100 and imageType = BufferedImage.TYPE_INT_ARGB. I then draw this BufferedImage onto another via the following code :

    BufferedImage source = ImageIO.read(new File("imgToDrawOnto.png"));
    Graphics g = source.getGraphics();
    g.drawImage(circleImg, 100, 100, null);

where circleImg is the BufferedImage of the SVG circle. This works fine and draws onto the image however it comes out very pixelated. Is there any way I can get a smoother circle? I would prefer to keep using SVG, but other ways can also be considered if there is no way in SVG.

Things I have tried:

  1. I have set the radius of the circle to 500 and left the BufferedImage height and width at 100.
  2. I have set the BufferedImage height and width to 1000 and used the draw method which takes height and width as arguments and made them 100.
  3. I have done both 1 and 2 at the same time.
  4. I have also tried making the radius even bigger ie. 2500
  5. I also changed the circleImg argument to circleImg.getScaledInstance(100, 100, 1)

Nothing has worked. Some seem smoother, but not by alot and others look worse. Also something to note is I also observe the pixelation when using g.drawOval(150, 150, 100, 100). This leads me to believe the problem is not with SVG, but I may be wrong.

Java Version:

    java version "1.6.0_30"
    Java SE Runtime Enviroment (build 1.6.0_30-b12)
    Java HotSpot 64-bit Server VM (build 20.5-b03, mixed mode)

For SVG I am using SVG-Salamander v1.0


Solution

  • When you read an image with ImageIO.read, the colour model of the image file is retained. Since you read a PNG file, the problem may be that the source file is using an indexed colour model (palette) with few and perhaps not matching colours. Another problem may be that you have to enable anti-aliasing to avoid what you call pixelation.

    To avoid the colour model issue, you may have to create a new BufferedImage with e.g. an ARGB colour model, on which you first draw the loaded image and then the SVG graphic:

    BufferedImage source = ImageIO.read(new File("imgToDrawOnto.png"));
    BufferedImage newImage = new BufferedImage(
        source.getWidth(), 
        source.getHeight(), 
        BufferedImage.TYPE_INT_ARGB);
    
    Graphics2D g = (Graphics2D)newImage.getGraphics();
    
    g.drawImage(source, 0, 0, null);
    g.drawImage(circleImg, 100, 100, null);
    

    To enable antialiasing, you can set the appropriate rendering hint on the Graphics2D object before drawing the other images:

    g.setRenderingHint(
        RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    

    Optionally, you can also increase the antialiasing quality by enabling bilinear or bicubic interpolation:

    g.setRenderingHint(
        RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    
    g.setRenderingHint(
        RenderingHints.KEY_INTERPOLATION,
        RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    

    Added example image: enter image description here