Avatar billede fbisen Nybegynder
30. maj 2005 - 20:32 Der er 5 kommentarer og
1 løsning

Billedbehandling - Resolution (DPI)

Hej Eksperter!

Jeg har et problem. Jeg vil gerne kunne lave en masse billeder mindre ved en funktion, og har fundet noget kode på nettet (se længere nede). Men hvis jeg har nogle billeder med en opløsning på 300 DPI, så laver funktionen dem mindre, til 96 DPI.
Jeg vil gerne bibeholde de 300 DPI. Billedet skal bare blive mindre, og ikke andet...


Min nuværende kode ser således ud:
------------------------------

    public static void doResize(String inputFile, String outputFile, int thumbWidth, int thumbHeight, int quality) throws Exception {

        // load image from INFILE
        Image image = Toolkit.getDefaultToolkit().getImage(inputFile);
        MediaTracker mediaTracker = new MediaTracker(new Container());
        mediaTracker.addImage(image, 0);
        mediaTracker.waitForID(0);
        // determine thumbnail size from WIDTH and HEIGHT

        double thumbRatio = (double) thumbWidth / (double) thumbHeight;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        double imageRatio = (double) imageWidth / (double) imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int) (thumbWidth / imageRatio);
        } else {
            thumbWidth = (int) (thumbHeight * imageRatio);
        }
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        BufferedImage thumbImage = new BufferedImage(thumbWidth,
                thumbHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = thumbImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, 300, 300, 300, 300, null);
        // save thumbnail image to OUTFILE
        BufferedOutputStream out = new BufferedOutputStream(new
                FileOutputStream(outputFile));
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param = encoder.
                getDefaultJPEGEncodeParam(thumbImage);

        quality = Math.max(0, Math.min(quality, 100));
        param.setQuality((float) quality / 100.0f, false);
        encoder.setJPEGEncodeParam(param);
        encoder.encode(thumbImage);
        out.close();

        if (outputFile.lastIndexOf("\\") != -1) {
            int index = outputFile.lastIndexOf("\\");
            String imageDone = outputFile;//.substring(index + 1);
            setMessage("Done thumbnailing image: " + imageDone);
            System.out.println("Done thumbnailing image: " + imageDone);
        } else {
            System.out.println("Done thumbnailing image");
        }
    }

--------------------------

Måske findes der bedre måder at gøre det på?
Avatar billede simonvalter Praktikant
31. maj 2005 - 01:12 #1
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import java.awt.image.*;
import java.awt.*;
import java.io.*;
import java.util.Iterator;


import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Thumbnail {
    public static void main(String[] args) throws Exception {

        doResize("bla.JPG", "bla2.jpg", 600, 600);
    }


    public static void doResize(String inputFile,String outPutFile, int thumbWidth, int thumbHeight) throws Exception {
        // load image from INFILE
        Image image = Toolkit.getDefaultToolkit().getImage(inputFile);
        MediaTracker mediaTracker = new MediaTracker(new Container());
        mediaTracker.addImage(image, 0);
        mediaTracker.waitForID(0);
        // determine thumbnail size from WIDTH and HEIGHT

        double thumbRatio = (double) thumbWidth / (double) thumbHeight;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        double imageRatio = (double) imageWidth / (double) imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int) (thumbWidth / imageRatio);
        } else {
            thumbWidth = (int) (thumbHeight * imageRatio);
        }
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        BufferedImage thumbImage = new BufferedImage(thumbWidth,
                thumbHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = thumbImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);

      int dpi[] = getImageDpi(inputFile);
      saveImageToDisk(thumbImage,dpi[0],dpi[1],outPutFile);
    }

    //      Here is a function to save a jpeg using ImageIO:
    private static void saveImageToDisk(BufferedImage bi, int dpix, int dpiy, String fileName) {

        Iterator i = ImageIO.getImageWritersByFormatName("jpeg");
        //are there any jpeg encoders available?

        if (i.hasNext()) //there's at least one ImageWriter, just use the first one
        {
            ImageWriter imageWriter = (ImageWriter) i.next();
            //get the param
            ImageWriteParam param = imageWriter.getDefaultWriteParam();
           
            ImageTypeSpecifier its = new
                    ImageTypeSpecifier(bi.getColorModel(), bi.getSampleModel());

            //get metadata
            IIOMetadata iomd = imageWriter.getDefaultImageMetadata(its,
                    param);

            String formatName = "javax_imageio_jpeg_image_1.0";//this is the DOCTYPE of the metadata we need

            Node node = iomd.getAsTree(formatName);
            //what are child nodes?
            NodeList nl = node.getChildNodes();
            for (int j = 0; j < nl.getLength(); j++) {
                Node n = nl.item(j);

                if (n.getNodeName().equals("JPEGvariety")) {
                    NodeList childNodes = n.getChildNodes();

                    for (int k = 0; k < childNodes.getLength(); k++) {
                        if
                        (childNodes.item(k).getNodeName().equals("app0JFIF")) {

                            //get the resUnits, Xdensity, and Ydensity attribuutes
                            Node resUnitsNode =
                                    getAttributeByName(childNodes.item(k), "resUnits");
                            Node XdensityNode =
                                    getAttributeByName(childNodes.item(k), "Xdensity");
                            Node YdensityNode =
                                    getAttributeByName(childNodes.item(k), "Ydensity");

                            //reset values for nodes
                            resUnitsNode.setNodeValue("1"); //indicate DPI mode
                            XdensityNode.setNodeValue(String.valueOf(dpix));
                            YdensityNode.setNodeValue(String.valueOf(dpiy));


                        }    //end  if (childNodes.item(k).getNodeName().equals("app0JFIF"))
                    } //end if (n.getNodeName().equals("JPEGvariety")
                    break; //we don't care about the rest of the children
                } //end if (n.getNodeName().equals("JPEGvariety"))

            } //end  for (int j = 0; j < nl.getLength(); j++)

            try {
                iomd.setFromTree(formatName, node);
            } catch (IIOInvalidTreeException e) {
                e.printStackTrace();  //To change body of catch statement use Options | File Templates.
            }
            //attach the metadata to an image
            IIOImage iioimage = new IIOImage(bi, null, iomd);
            try {
                imageWriter.setOutput(new FileImageOutputStream(new
                        File(fileName)));
                imageWriter.write(iioimage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }  //end if (i.hasNext()) //there's at least one ImageWriter, justuse the first one
    }  //end public static void saveImageToDisk(BufferedImage bi, int dpi, String fileName)

    /**
    * @param node
    * @param attributeName - name of child node to return
    * @return
    */
    static Node getAttributeByName(Node node, String attributeName) {
        if (node == null) return null;
        NamedNodeMap nnm = node.getAttributes();
        for (int i = 0; i < nnm.getLength(); i++) {
            Node n = nnm.item(i);
            if (n.getNodeName().equals(attributeName)) {
                return n;
            }
        }
        return null; // no such attribute was found
    } //end Node getAttributeByName(Node node, String attributeName)


    private static int[] getImageDpi(String inputFile) {

        ImageInputStream imageInput = null;
        int xDPI = -1;
        int yDPI = -1;
        int dpi[] = new int[2];
        try {
            imageInput = ImageIO.createImageInputStream(new FileInputStream(inputFile));

            Iterator it = ImageIO.getImageReaders(imageInput);
            ImageReader reader = (ImageReader) it.next();
            reader.setInput(imageInput);
            IIOMetadata srcMeta = reader.getImageMetadata(0);
            IIOMetadataNode srcNodes = (IIOMetadataNode) srcMeta.getAsTree("javax_imageio_1.0");
            NodeList nl = srcNodes.getElementsByTagName("HorizontalPixelSize");
            if ((nl != null) && (nl.getLength() > 0))
                xDPI = Math.round(25.4f /
                        Float.parseFloat(nl.item(0).getAttributes().item(0).getNodeValue()));
            nl = srcNodes.getElementsByTagName("VerticalPixelSize");
            if ((nl != null) && (nl.getLength() > 0))
                yDPI = Math.round(25.4f / Float.parseFloat(nl.item(0).getAttributes().item(0).getNodeValue()));
            dpi[0] = xDPI;
            dpi[1] = yDPI;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return dpi;
    }


}
Avatar billede simonvalter Praktikant
31. maj 2005 - 01:15 #2
af en eller anden grund går det meget langsomt hvis jeg ikke indlæser billedet med
Image image = Toolkit.getDefaultToolkit().getImage(inputFile);

hvis jeg indlæser billedet med
imageInput = ImageIO.createImageInputStream(new FileInputStream(inputFile));

og sender det videre til resizeren som et bufferedimage så tager det +1min at resize.

derfor bliver det indlæst både når jeg resizer og når jeg finder ud af DPI for billedet... hvis du ved at det altid vil være 300x300 så kan du droppe getImageDpi()
Avatar billede simonvalter Praktikant
31. maj 2005 - 01:17 #3
det nyttede ikke noget at lave det buffered image indlæst i getImageDpi() om til image igen .. den var stadig langsom til at resize.. jeg vil tror der er lagt en masse nye informationer på billedet der gør det langsomt.
Avatar billede simonvalter Praktikant
31. maj 2005 - 01:42 #4
public static void doResize(String inputFile, String outputFile, int thumbWidth, int thumbHeight, int quality) throws Exception {

        // load image from INFILE
        Image image = Toolkit.getDefaultToolkit().getImage(inputFile);
        MediaTracker mediaTracker = new MediaTracker(new Container());
        mediaTracker.addImage(image, 0);
        mediaTracker.waitForID(0);
        // determine thumbnail size from WIDTH and HEIGHT

        double thumbRatio = (double) thumbWidth / (double) thumbHeight;
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        double imageRatio = (double) imageWidth / (double) imageHeight;
        if (thumbRatio < imageRatio) {
            thumbHeight = (int) (thumbWidth / imageRatio);
        } else {
            thumbWidth = (int) (thumbHeight * imageRatio);
        }
        // draw original image to thumbnail image object and
        // scale it to the new size on-the-fly
        BufferedImage thumbImage = new BufferedImage(thumbWidth,
                thumbHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = thumbImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
        // save thumbnail image to OUTFILE
        BufferedOutputStream out = new BufferedOutputStream(new
                FileOutputStream(outputFile));
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param = encoder.
                getDefaultJPEGEncodeParam(thumbImage);
        quality = Math.max(0, Math.min(quality, 100));
        param.setQuality((float) quality / 100.0f, false);

        param.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
        param.setXDensity(300);
        param.setYDensity(300);
        encoder.setJPEGEncodeParam(param);
        encoder.encode(thumbImage);
        out.close();

        if (outputFile.lastIndexOf("\\") != -1) {
            int index = outputFile.lastIndexOf("\\");
            String imageDone = outputFile;//.substring(index + 1);

            System.out.println("Done thumbnailing image: " + imageDone);
        } else {
            System.out.println("Done thumbnailing image");
        }
    }
Avatar billede fbisen Nybegynder
02. juni 2005 - 09:00 #5
Jeg har kun prøvet den sidste kode du gav mig, den lignede også mest den jeg brugte - du har vidst kun sat param.... ind.

Mange tak - virker perfekt :)

Desuden, ved du hvordan man kan få en "browse" knap til at virke. Altså åbne en boks hvor man kan vælge mappe? - Bare et ekstra spørgsmål :P
Avatar billede simonvalter Praktikant
02. juni 2005 - 10:25 #6
Det var så lidt

hvis du skal vælge filer/mapper skal du nok have fat i jfilechooser.
Se her for mere info:
http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester