This discussion is archived
12 Replies Latest reply: Jan 15, 2011 6:28 AM by 831465 RSS

Image resizing using JAI

843802 Newbie
Currently Being Moderated
Image resizing using JAI

We have next algorithm of resizing:
        RenderedOp image;
        try {
            SeekableStream s = SeekableStream.wrapInputStream(is, true);
            image = JAI.create("stream", s);
            ((OpImage) image.getRendering()).setTileCache(null);

            double resizeFactor = getResizeFactor(width, height, image
                    .getWidth(), image.getHeight());
            if (resizeFactor < 1) {
                image = JAI.create("SubsampleAverage", image, resizeFactor,
                        resizeFactor, QUALITY_HINTS);
            } else if (resizeFactor > 1) {
                image = ScaleDescriptor.create(image, (float) resizeFactor,
                        (float) resizeFactor, 0.0f, 0.0f, Interpolation
                                .getInstance(Interpolation.INTERP_BICUBIC),
                        null);
            }

            try {
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                try {
                    ImageIO.write(image, "png", os);
                    return os.toByteArray();
                } finally {
                    os.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } finally {
            is.close();
        }
Source without resizing: http://www.servit.ch/sites/all/themes/servit_oss/logo.png
Resize example #1: http://208.109.126.120:7080/gdesk-web/thumbnail/1123_148x148.png (you may see cutted bottom edge)
Resize example #2: http://208.109.126.120:7080/gdesk-web/thumbnail/1123_30x30.png (you may see cutted bottom and right edges and artifacts at left and top)

This resizing algorithm works perfect, BUT he cuts 1-2 pixels from bottom edge and 1-2 pixels from right edge AND adds artifacts to the left and top edges. What I can do with artefacts and cutted pixels, how I can take them back???
  • 1. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Wrong urls in first post. New URLs

    http://208.109.126.120:7080/gdesk-web/thumbnail/1126_148x148.png
    http://208.109.126.120:7080/gdesk-web/thumbnail/1126_30x30.png
  • 2. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Hm... I cant reproduce that behavior. What are your QUALITY_HINTS?
  • 3. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Thanks for answer!
    RenderingHints QUALITY_HINTS = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  • 4. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Did you tried my image??
  • 5. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    I really can't reproduce it. When I run the code below, I get a 148x148 image.
    import javax.swing.*;
    import javax.media.jai.*;
    import java.awt.RenderingHints;
    import java.net.URL;
    public class SSCCE {
        public static void main(String[] args) throws Exception{
            RenderedOp image = JAI.create("url",
                    new URL("http://www.servit.ch/sites/all/themes/servit_oss/logo.png"),
                    null,null);
    
            RenderingHints QUALITY_HINTS = new RenderingHints(
                    RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            image = JAI.create("SubsampleAverage",image,.78,.78,QUALITY_HINTS);
            System.out.println(image.getWidth() + "x" + image.getWidth());
            
            JFrame frame = new JFrame();
            frame.setLayout(new java.awt.GridBagLayout());
            frame.add(new com.sun.media.jai.widget.DisplayJAI(image));
            frame.setSize(300,300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
        }
    }
    In fact, when I run this I get a somewhat blury image. I don't get the crisp image you're getting. This is kind a suprising since I know SubsampleAverage to be of decent quality. Maybe there are some bugs.
  • 6. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    I tested your class and I found that you are right :)

    And I think that problem in
    ImageIO.write(image, "png", os);
    I used another method:
            RenderedOp image;
            try {
                // 1) Read image into memory
                SeekableStream s = SeekableStream.wrapInputStream(is, true);
                image = JAI.create("stream", s);
                ((OpImage) image.getRendering()).setTileCache(null);
    
                // 2) Resize image
                double resizeFactor = getResizeFactor(width, height, image
                        .getWidth(), image.getHeight());
                if (true) {
                    image = JAI.create("SubsampleAverage", image, resizeFactor,
                            resizeFactor, QUALITY_HINTS);
                    PNGEncodeParam.RGB pngEncodeParam = new PNGEncodeParam.RGB();
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    ImageEncoder encoder = ImageCodec.createImageEncoder("PNG",
                            outputStream, pngEncodeParam);
                    PlanarImage planarImage = image.getRendering();
                    encoder.encode(planarImage);
                    return outputStream.toByteArray();
                } else if (resizeFactor > 1) {
                    image = ScaleDescriptor.create(image, (float) resizeFactor,
                            (float) resizeFactor, 0.0f, 0.0f, Interpolation
                                    .getInstance(Interpolation.INTERP_BICUBIC),
                            null);
                }
    
                // 3) Convert image to PNG
                return convertImage(image);
            } finally {
                is.close();
            }
    I changed
    ImageIO.write(image, "png", os);
    to
                    PNGEncodeParam.RGB pngEncodeParam = new PNGEncodeParam.RGB();
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    ImageEncoder encoder = ImageCodec.createImageEncoder("PNG",
                            outputStream, pngEncodeParam);
                    PlanarImage planarImage = image.getRendering();
                    encoder.encode(planarImage);
                    return outputStream.toByteArray();
    And seems it helps, BUT now I have another problem - black bottom border.
  • 7. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Dear Maxideon,

    I changed resize factor at your sample and I get black edge at the bottom of the image.
    import javax.swing.*;
    import javax.media.jai.*;
    
    import java.awt.RenderingHints;
    import java.net.URL;
    
    public class SSCCE {
        public static void main(String[] args) throws Exception {
            RenderedOp image = JAI.create("url", new URL(
                    "http://208.109.126.120:7080/gdesk-web/resource/1126"), null,
                    null);
    
                RenderingHints QUALITY_HINTS = new RenderingHints(
                        RenderingHints.KEY_RENDERING,
                        RenderingHints.VALUE_RENDER_QUALITY);
                double rf = 110d / 360d;
                RenderedOp simage = JAI
                        .create("SubsampleAverage", image, rf, rf, QUALITY_HINTS);
                System.out.println(image.getWidth() + "x" + image.getWidth());
    
                JFrame frame = new JFrame();
                frame.setLayout(new java.awt.GridBagLayout());
                frame.add(new com.sun.media.jai.widget.DisplayJAI(simage));
                frame.setSize(300, 300);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
        }
    }
    If you know how to remove this black line or make it white or other solution, please say me.
  • 8. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    I have had problems with resizing with ImageIO. Have you tried the "Scale" operator? I think thats meant for resizing ops.

    Edited by: rpandit24 on Feb 5, 2010 8:00 AM
  • 9. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    Yes we tried to use "Scale", but "SubsampleAverage" gives more better results.
  • 10. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    I have changed my code which makes image convertation and now I have other problem.
    I have black line at bottom of the image after resizing. Did anyone knows how to fix it.
    You find image with black edge here http://208.109.126.120:7080/gdesk-web/thumbnail/1126_148x148.png

    I need any help.

    Converting to PNG:
                PNGEncodeParam.RGB pngEncodeParam = new PNGEncodeParam.RGB();
                pngEncodeParam.setBackgroundRGB(new int[] { 255, 255, 255 });
                pngEncodeParam.setTransparentRGB(new int[] { 255, 255, 255 });
     
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ImageEncoder encoder = ImageCodec.createImageEncoder("PNG",
                        outputStream, pngEncodeParam);
                PlanarImage planarImage = scaledImage.getNewRendering();
                encoder.encode(planarImage);
  • 11. Re: Image resizing using JAI
    843802 Newbie
    Currently Being Moderated
    I'm having the same issue right now with a black line at the bottom of a resized image. I have concluded that this line is created becuase the resizing of the image is slightly off, probably by just 1 pixel. Maybe from a rounding error.

    The image is also slightly blurry, as if the resizing is off.

    I am trying to find out more about setting specific resizing amounts instead of using a percentage.
  • 12. Re: Image resizing using JAI
    831465 Newbie
    Currently Being Moderated
    only use this for final scale factory

    double width = source.getWidth() * xScale;
    xScale = xScale * Math.round(width) / width;
    double height = source.getHeight() * yScale;
    yScale = yScale * Math.round(height) / height;