0

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

Robert Longson
  • 118,664
  • 26
  • 252
  • 242
Vinc
  • 695
  • 2
  • 10
  • 26

1 Answers1

1

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

jarnbjo
  • 33,923
  • 7
  • 70
  • 94
  • Tried drawing the source image onto new bufferedimage,didnt work.Tried anti-aliasing with both types of interpolation,didnt work.Also tried both suggestions at the same time,still no luck. – Vinc Dec 05 '13 at 11:22
  • In which case you probably must be clearer about what you are actually doing. Post a complete example to reproduce your behaviour and clearly state what you actually expect. – jarnbjo Dec 05 '13 at 13:04
  • I unfortunately I cannot post a complete code example as my company does not allow it,but if you replace g.drawImage in the 3 lines that I posted with g.drawOval you will see the same pixelation.All I want is for the circle to be a lot smoother. – Vinc Dec 06 '13 at 06:37
  • Since I don't have the PNG file you are reading, it is of course not possible for me to run the code you've posted, even if I replace the last line. Drawing a circle in a BufferedImage using the suggestions I posted results in the image, which I added to my answer and a lot better result cannot be achieved with the available resolution. – jarnbjo Dec 06 '13 at 07:22
  • Thanks for all your help,turns out I was just being an idiot.The circle was being drawn onto a buffered image of its own,and I was not setting anti aliasing and interpolation on that graphics object.Done and its working now.Thanks alot. – Vinc Dec 06 '13 at 07:39