# DPI von einem Bild definieren



## unknown (10. Nov 2015)

Hallo zusammen, 

Ich möchte meine BufferedImages nicht mit 72 sondern 300 DPI speichern.
Im Netz habe ich den folgenden Code gefunden. Der funktioniert allerdings nur für PNG. Andere Formate ausser Bitmap (BMP) werden zwar gespeichert, sie haben allerdings immer noch 72 DPI.

Weiss jemand wo ich den Code anpassen sollte, damit er für alle anderen Formate auch funktioniert?


```
BufferedImage image = ImageIO.read(url);

            File output = new File("C:\\test\\out.JPG");

            final String formatName = "JPG";

            for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) {
                ImageWriter writer = iw.next();
                ImageWriteParam writeParam = writer.getDefaultWriteParam();
                ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
                IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
                if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
                    continue;
                }

                setDPI(metadata);

                final ImageOutputStream stream = ImageIO.createImageOutputStream(output);
                try {
                    writer.setOutput(stream);
                    writer.write(metadata, new IIOImage(image, null, metadata), writeParam);
                } finally {
                    stream.close();
                }
                break;
            }
```


```
private static void setDPI(IIOMetadata metadata) throws IIOInvalidTreeException {

       // for PNG, it's dots per millimeter
       double dotsPerMilli = 1.0 * 300 / 10 / 2.54;

       IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
       horiz.setAttribute("value", Double.toString(dotsPerMilli));

       IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
       vert.setAttribute("value", Double.toString(dotsPerMilli));

       IIOMetadataNode dim = new IIOMetadataNode("Dimension");
       dim.appendChild(horiz);
       dim.appendChild(vert);

       IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
       root.appendChild(dim);

       metadata.mergeTree("javax_imageio_1.0", root);
    }
```


----------



## Thallius (10. Nov 2015)

BMP und JPEG haben keine DPI Angabe in ihrem Format. Wozu willst du das denn machen?


----------



## unknown (10. Nov 2015)

Dies ist eine Anforderung in diesem Projekt. Es muss doch eine Lösung dafür geben. Was ist mit den restlichen Formaten GIF, TIF etc.?


----------



## nvidia (10. Nov 2015)

Bei dir liegt ein Missverständnis vor was DPI/PPI bedeutet. Die Anzahl der Pixel deines Bildes wird allein durch die Auflösung bestimmt in der es gemacht wurde, sei es ein Screenshot oder ein Bild durch eine Digitalkamera. DPI/PPI drückt an dieser Stelle noch überhaupt nichts aus.

Das DPI/PPI Geraffel ist für die Ausgabe auf z.B. einem Monitor oder Drucker, da ist es mehr oder minder ein Faktor um zu bestimmen wie viele Pixel der Drucker denn so pro Zoll auf das Papier bringt und je nachdem auch dein Ausdruck aussieht. Es gibt aber Bildbearbeitungsprogramme wenn du da z.B. 72 DPI stehen hast und 300 einträgst die dir das von der Größe her (durch resampling) vervierfachen, da du aber nur eine bestimmte Anzahl an Pixeln hast werden die auch aufgeblasen was dann eine schlechtere Qualität zur Folge hat (in der 100% Ansicht).

Falls du nicht überzeugt bist, such einfach mal im Netz nach z.B. photography dots per inch, etc. Es gibt nämlich genug Hobbydigitalkameraphotographen denen der Zusammenhang auch nicht ganz klar ist. Und aus der Ecke Fotografie kommen die Bezeichnungen IMHO.


----------



## nvidia (10. Nov 2015)

Thallius hat gesagt.:


> BMP und JPEG haben keine DPI Angabe in ihrem Format. Wozu willst du das denn machen?



Das ist nicht richtig diese Angabe existiert bei BMP und JPEG, bei BMP wird sie im Header unter dem Offset 26h und 2Ah angegeben und zwar in Pixeln pro Meter, man muss das also noch umrechnen auf DPI/PPI. Das Äquivalent in JPEG sind die werte für die "pixel density" in x,y-Richtung. Die Anzeige dieses Wertes für den Nutzer ist dann abhängig von dem Programm was er verwendet. Schreibt man beim Bitmap z.B. 0 an die Stellen gibt Windows irgendeinen Defaultwert aus, IMHO 96 dpi wenn man über die Rechtsklick-Eigenschaften geht.


----------



## unknown (10. Nov 2015)

nvidia hat gesagt.:


> Das ist nicht richtig diese Angabe existiert bei BMP und JPEG, bei BMP wird sie im Header unter dem Offset 26h und 2Ah angegeben und zwar in Pixeln pro Meter, man muss das also noch umrechnen auf DPI/PPI. Das Äquivalent in JPEG sind die werte für die "pixel density" in x,y-Richtung. Die Anzeige dieses Wertes für den Nutzer ist dann abhängig von dem Programm was er verwendet. Schreibt man beim Bitmap z.B. 0 an die Stellen gibt Windows irgendeinen Defaultwert aus, IMHO 96 dpi wenn man über die Rechtsklick-Eigenschaften geht.


Danke für deine Antwort.
Könnte man das was du erklärt hast, direkt in meinem Code einbinden? Zurzeit werden BMP mit meinem Code erst gar nicht gespeichert.
Wo kann ich mir solche Infos für jedes einzelne Format holen? Muss eben das gleiche auch mit  GIF, TIF machen.


----------

