BMP mit ImageIO schreiben

Status
Nicht offen für weitere Antworten.

inflamer

Bekanntes Mitglied
Abend!

Ich möchte BMPs mit ImageIO schreiben. Soweit kein Problem. Allerdings kommt es mir darauf an, die Auflösung festlegen zu können (dpi). Bei JPEG-Grafiken klappt das bereits auch ohne Probleme:


Code:
    // erstelle BufferedImage und zeichne in seinen grafikkontext
    BufferedImage bi = new BufferedImage(pxlWidth, pxlHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = bi.createGraphics();
    // ...
    // ... zeichne in den g2d-kontext
    // ...
    g2d.dispose();
    ImageTypeSpecifier its = new ImageTypeSpecifier(bi.getColorModel(), bi.getSampleModel());
    Iterator iterator = ImageIO.getImageWritersByFormatName("jpg");
    ImageWriter imageWriter = (ImageWriter)iterator.next();
    ImageWriteParam param = imageWriter.getDefaultWriteParam();
    IIOMetadata iomd = imageWriter.getDefaultImageMetadata(its, param);
    initJPGImageMetadata(iomd, resolution);  // <<<--------- aufruf der methode s. unten
    IIOImage iioImage = new IIOImage(bi, null, iomd);

    // schreibe datei
    FileImageOutputStream fios = null;
    try {
      fios = new FileImageOutputStream(file);
      imageWriter.setOutput(fios);
      imageWriter.write(iioImage);
    } catch (Exception e) {
      // ...
    } finally {
      if (fios != null) try { fios.close(); } catch (Exception e) {}
    }

Code:
  //----
  private static void initJPGImageMetadata(IIOMetadata iiomd, int resolution) {
    final String resStr = String.valueOf(resolution);
    final String formatName = "javax_imageio_jpeg_image_1.0";
    final Node node = iiomd.getAsTree(formatName);
    final NodeList nodeList = node.getChildNodes();
    for (int i=nodeList.getLength()-1; i>=0; i--) {
      Node n = nodeList.item(i);

      if (n.getNodeName().equals("JPEGvariety")) {
        NodeList childNodes = n.getChildNodes();
        for (int j=childNodes.getLength()-1; j>=0; j--) {
          Node cn = childNodes.item(j);
          if (cn.getNodeName().equals("app0JFIF")) {
            getAttributeByName(cn, "resUnits").setNodeValue("1"); // "dpi"
            getAttributeByName(cn, "Xdensity").setNodeValue(resStr);
            getAttributeByName(cn, "Ydensity").setNodeValue(resStr);
          }
        }
        break;
      }

    }

    try { iiomd.setFromTree(formatName, node);
    } catch (IIOInvalidTreeException e) { /* kann sich nicht ereignen */ }
  }
Code:
  //---- hilfsmethode
  private static Node getAttributeByName(Node node, String attributeName) {
    NamedNodeMap nnm = node.getAttributes();
    for (int i=nnm.getLength()-1; i>=0; i--) {
      Node n = nnm.item(i);
      if (n.getNodeName().equals(attributeName))
        return n;
    }
    return null; // no such attribute was found
  }


Eine entscheidende Rolle spielt dabei die Klasse IIOMetadata, die quasi alle für ein Grafikformat relevanten Informationen zu einer Grafik enthält - im Fall von BMP und JPEG also auch die Auflösung. Für jedes Grafikformat ist desweiteren eine separate von IIOMetadata abgeleitete Klasse zuständig: bei JPEG-Grafiken ist es z.b. com.sun.imageio.plugins.jpeg.JPEGMetadata. Der Hacken bei der entsprechenden BMP-Klasse com.sun.imageio.plugins.bmp.BMPMetadata ist nun, dass sich die Attribute darin nicht überschreiben lassen. So werfen die Implementierungen der Schnittstellen-Setter z.B. gleich eine Exception ohne wenn und aber.

Kennt also jemand vielleicht einen anderen Weg?
 

inflamer

Bekanntes Mitglied
eine Lösung:


Code:
  public void writeBMP(OutputStream out, BufferedImage bi, int resolution) throws IOException {
    ImageTypeSpecifier its = new ImageTypeSpecifier(bi.getColorModel(), bi.getSampleModel());
    Iterator iterator = ImageIO.getImageWritersByFormatName("bmp");
    ImageWriter imageWriter = (ImageWriter)iterator.next();
    ImageWriteParam param = imageWriter.getDefaultWriteParam();
    IIOMetadata iiomd = imageWriter.getDefaultImageMetadata(its, param);

    // im header einer bmp-datei steht die auflösung als 32bit-integers in dots per meter,
    // wobei die bytes rückwärts angeordnet sind
    final int dotsPerMeter = Integer.reverseBytes(Math.round((float)(resolution / 0.0254)));

    // outputstream, der die auflösung der bmp-datei korrigiert
    class CorrectingOutputStream extends DataOutputStream {
      private ByteArrayOutputStream baos = new ByteArrayOutputStream(50);
      public CorrectingOutputStream(OutputStream out) {
        super(out);
      }
      public void write(byte b[], int off, int len) throws IOException {
        if (baos != null) {
          baos.write(b, off, len);
          if (baos.size() >= 38) {
            b = baos.toByteArray();
            super.write(b, 0, 38);
            super.writeInt(dotsPerMeter);
            super.writeInt(dotsPerMeter);
            if (b.length > 46)
              super.write(b, 46, b.length - 46);
            baos = null;
          }
        } else { // if baos == null
          super.write(b, off, len);
        }
      }
    }

    // schreibe datei
    imageWriter.setOutput(new MemoryCacheImageOutputStream(new CorrectingOutputStream(out)));
    imageWriter.write(new IIOImage(bi, null, iiomd));
  }
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Bild Beschreibung mit ImageIO speichern AWT, Swing, JavaFX & SWT 1
M "ImageIO.read()" liest Bild nicht richtig ein AWT, Swing, JavaFX & SWT 3
B Probleme bei ImageIO.read (?!) AWT, Swing, JavaFX & SWT 9
B Problem mit ImageIO.write() AWT, Swing, JavaFX & SWT 7
B ImageIO und animerte gifs? AWT, Swing, JavaFX & SWT 4
N ImageIO Endung mitgeben AWT, Swing, JavaFX & SWT 4
M ImageIO, Bilderordner durchblättern AWT, Swing, JavaFX & SWT 4
B ImageIO gif Dateien laden AWT, Swing, JavaFX & SWT 7
S toolkit vs. imageIO AWT, Swing, JavaFX & SWT 4
T Swing ImageIO - nicht abfangbare IOException AWT, Swing, JavaFX & SWT 5
B ImageIO.read() zweimal hintereinander aus ObjectInputStream funktioniert nicht AWT, Swing, JavaFX & SWT 4
B Problem mit imageIO und ImageIcon AWT, Swing, JavaFX & SWT 5
U ImageIO.read verursacht heap space AWT, Swing, JavaFX & SWT 15
G Problem mit BufferedImage und imageIO AWT, Swing, JavaFX & SWT 2
H ImageIO.write-Probleme, Speicherüberlauf und Absturz AWT, Swing, JavaFX & SWT 12
izoards JTable in CSV File schreiben... AWT, Swing, JavaFX & SWT 23
A JavaFX Daten in eine HTML-Table mit JS schreiben AWT, Swing, JavaFX & SWT 3
M Eigene Klasse mit Grafikobjekten schreiben AWT, Swing, JavaFX & SWT 4
P Variable einer Eingabe in anderes Textfeld schreiben AWT, Swing, JavaFX & SWT 7
M JavaFX berechneten Wert in TableView schreiben AWT, Swing, JavaFX & SWT 1
W Kodierung (CharSet) beim Schreiben ändern AWT, Swing, JavaFX & SWT 1
P JavaFX Mit Stream-API (1.8) in Textdatei schreiben AWT, Swing, JavaFX & SWT 3
3 Swing JList-Inhalt als verschlüsselte Datei schreiben und lesen AWT, Swing, JavaFX & SWT 1
A Swing KeyEvent mit KeyListener und KeyAdapter kürzer schreiben AWT, Swing, JavaFX & SWT 7
S Swing Verzeichnis/Datei-Pfad in JTextField schreiben AWT, Swing, JavaFX & SWT 2
S Swing Eigenen Button schreiben AWT, Swing, JavaFX & SWT 6
B Daten in eine JTable schreiben AWT, Swing, JavaFX & SWT 3
1 Eigenes Layout schreiben AWT, Swing, JavaFX & SWT 4
J Swing Bild laden, Kreise drin malen, Schreiben AWT, Swing, JavaFX & SWT 2
C Integer in ein Textfield schreiben. AWT, Swing, JavaFX & SWT 4
M Swing In GUI-Builder-JFrame mit Menü Schreiben und Zeichnen AWT, Swing, JavaFX & SWT 4
W Vergleich zweier Strings und schreiben in Textarea AWT, Swing, JavaFX & SWT 12
A Swing Text auf eine Seite an beliebigen Orten schreiben AWT, Swing, JavaFX & SWT 6
M JFreeChart in ein File schreiben (bzw. JFrame in ein File Schreiben) AWT, Swing, JavaFX & SWT 2
P Swing Alle Zeilen einer Spalte (jTable) zusammen zählen und in eine eigene Zeile das Ergebnis schreiben. AWT, Swing, JavaFX & SWT 7
E werte zurück in GUI schreiben AWT, Swing, JavaFX & SWT 4
S 3D-Creator schreiben? AWT, Swing, JavaFX & SWT 5
L Zeilenumbrüche aus JTextArea MIT in Textdatei schreiben AWT, Swing, JavaFX & SWT 4
J Eigenen Parser schreiben AWT, Swing, JavaFX & SWT 8
T JTree Daten in DB schreiben am besten SQL AWT, Swing, JavaFX & SWT 21
G Text in JTable schreiben AWT, Swing, JavaFX & SWT 3
S Wie kann man eine XSLT-Parser schreiben? AWT, Swing, JavaFX & SWT 2
L Swing Farbige JComboBox schreiben AWT, Swing, JavaFX & SWT 5
R Direkt in Puffer schreiben AWT, Swing, JavaFX & SWT 7
I 2D-Grafik Problem mit schreiben von Text auf eine Grafik AWT, Swing, JavaFX & SWT 7
M Text in txt-Datei in letzte Zeile schreiben? AWT, Swing, JavaFX & SWT 14
U Beste Möglichkeit JTable-Änderungen in DB zu schreiben? AWT, Swing, JavaFX & SWT 14
D Suche Framework um Grafikprogramm zu schreiben. AWT, Swing, JavaFX & SWT 36
J In JTextfield bei event schreiben AWT, Swing, JavaFX & SWT 4
F png-Datei erstellen und einzelne Pixel schreiben AWT, Swing, JavaFX & SWT 2
G eigenen Observer schreiben AWT, Swing, JavaFX & SWT 6
G JIntegerField selber schreiben AWT, Swing, JavaFX & SWT 2
S Vorhandene Datei in anderes Verzeichnis schreiben! AWT, Swing, JavaFX & SWT 8
T JTable in *.dat schreiben und auslesen AWT, Swing, JavaFX & SWT 7
G Textfeld Auslesen und in Array schreiben (bei newline) AWT, Swing, JavaFX & SWT 2
I Event, Eventquelle und Listener selber schreiben AWT, Swing, JavaFX & SWT 9
W Vollbild Frames neu schreiben AWT, Swing, JavaFX & SWT 2
M .txt unter Verwendung von JSpinner in Textfeld schreiben AWT, Swing, JavaFX & SWT 4
S Menuausgabe in Tabelle schreiben AWT, Swing, JavaFX & SWT 7
S In Instanz von JTextArea schreiben AWT, Swing, JavaFX & SWT 4
H Yes No Dialog eleganter schreiben AWT, Swing, JavaFX & SWT 2
S Text eines JButtons vertikal schreiben AWT, Swing, JavaFX & SWT 5
V Listener selber schreiben? AWT, Swing, JavaFX & SWT 2
M Daten in JTable aus DB schreiben ? AWT, Swing, JavaFX & SWT 16
P Eigenes Look&Feel schreiben (Tutorials?) AWT, Swing, JavaFX & SWT 6
G Vertikal schreiben AWT, Swing, JavaFX & SWT 5
G TableModel auswerten und in Datei schreiben AWT, Swing, JavaFX & SWT 3
R JPanel als Screenshot in eine Datei schreiben AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben