C
Ich versuchte mich mal etwas in Java und habe nun ein Problem; ich möchte ein Bild drehen (Image-Klasse), dazu muss ich es erst in ein BufferedImage kopieren (anscheinend). Habe ienen Ausschnitt gefunden zum drehen und nun passiert folgendes:
Das Bild wird gedreht aber das Image/BufferedImage-Objekt behält seie Höhe/Breite, so dass einen Teil des Bildes abgeschnitten wird und schwarze Ränder entstehen. Ich habe beim Anlegen des BufferedImage-Objekts, in welches die Funktion
private static BufferedImage rotateImage(BufferedImage src, double degrees)
das gedrehte Bild zurückgibt aber absichtlich die Höhe/Breite vertauscht! Versuchte es natürlich auch umgekehrt aber immer mit dem Ergebnis.
Hier etwas mehr Code:
if(Label.equals("drehen")){
turnImage();
m_bildanzeige.repaint();
}
....
public void turnImage() {
BufferedImage outImg = new BufferedImage(m_aktBild.getWidth(m_bildanzeige), m_aktBild.getHeight(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(m_aktBild, 0, 0, null);
g.dispose();
BufferedImage turnedImg = new BufferedImage(m_aktBild.getHeight(m_bildanzeige), m_aktBild.getWidth(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
turnedImg=rotateImage(outImg, 90);
/*Graphics g2=m_aktBild.getGraphics();
g2.drawImage(turnedImg, 0, 0, null);
g2.dispose();*/
m_aktBild=turnedImg;
m_tempAnzeigeBild=m_aktBild;
}
private static BufferedImage rotateImage(BufferedImage src, double degrees) {
AffineTransform affineTransform = AffineTransform.getRotateInstance(
Math.toRadians(degrees),
src.getWidth() / 2,
src.getHeight() / 2);
BufferedImage rotatedImage = new BufferedImage(src.getWidth(), src
.getHeight(), src.getType());
Graphics2D g = (Graphics2D) rotatedImage.getGraphics();
g.setTransform(affineTransform);
g.drawImage(src, 0, 0, null);
return rotatedImage;
}
und das ganze Projekt:
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import sun.java2d.loops.ScaledBlit;
import java.awt.print.*;
import javax.print.attribute.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.awt.geom.AffineTransform;
public class JBildbearbeitung extends JFrame {
static JBildbearbeitung m_fenster;
String m_dateiname; // Name der Datei
Image m_aktBild; // Referenz auf das aktuelle Bild
Image m_tempAnzeigeBild;
CBildLeinwand m_bildanzeige; // JPanel zum Anzeigen des Bildes
int m_Xpos,m_Ypos; // neue Position, an der die
// linke obere Ecke des Bildes
// angezeigt wird
int m_bild_x1,m_bild_y1; // die aktuelle Begrenzung
int m_bild_x2,m_bild_y2; // des Bildes
int m_bildHoehe,m_bildBreite; // Höhe und Breite in Pixeln
String fileformat="jpg";
JPanel panel;
JTextField m_width;
JTextField m_height;
JButton bresize;
JButton bresize2;
JButton bturn;
JLabel heightlabel;
JLabel widthlabel;
// Ereignisbehandlung
class CMeinActionLauscher implements ActionListener {
public void actionPerformed(ActionEvent e) {
String Label;
Label = e.getActionCommand();
if(Label.equals("Programm beenden"))
System.exit(0);
if(Label.equals("Bild laden"))
bildLaden();
if (Label.equals("einzoomen")) {
m_tempAnzeigeBild=m_aktBild.getScaledInstance((m_tempAnzeigeBild.getWidth(m_bildanzeige)*2), (m_tempAnzeigeBild.getHeight(m_bildanzeige)*2), Image.SCALE_FAST);
m_bildanzeige.repaint();
}
if (Label.equals("auszoomen")) {
m_tempAnzeigeBild=m_aktBild.getScaledInstance((m_tempAnzeigeBild.getWidth(m_bildanzeige)/2), (m_tempAnzeigeBild.getHeight(m_bildanzeige)/2), Image.SCALE_FAST);
m_bildanzeige.repaint();
}
if (Label.equals("+"))
{
int breite=Integer.parseInt(m_width.getText());
int hoehe=Integer.parseInt(m_height.getText());
breite=breite*2; hoehe=hoehe*2;
m_width.setText(String.valueOf(breite));
m_height.setText(String.valueOf(hoehe));
ResizeImage(breite, hoehe);
m_bildanzeige.repaint();
}
if(Label.equals("-")) {
int breite=Integer.parseInt(m_width.getText());
int hoehe=Integer.parseInt(m_height.getText());
breite=breite/2; hoehe=hoehe/2;
m_width.setText(String.valueOf(breite));
m_height.setText(String.valueOf(hoehe));
ResizeImage(breite, hoehe);
m_bildanzeige.repaint();
}
if(Label.equals("drehen")){
turnImage();
m_bildanzeige.repaint();
}
if(Label.equals("info...")) {
JOptionPane.showMessageDialog(null, "JBildbearbeitung (c) 2009, C. M. Obrecht; Reben Studio, Aufnahmemedien +Informatik.\nhttp://homepage.hispeed.ch/reben \n \nÖffnet Bilder in den Formaten gif, jpg und png \n(eventuell abhängig von Ihrem Betriebssystem) und speichert in jpg und png. \n\nWird ein Bildformat nicht unterstützt welches Sie zu öffnen versuchten wird in der Grössenanzeige -1 angezeigt.\n\nDateiendungen müssen beim Öffnen/Speichern NICHT mit angegeben werden.", "Info über...", JOptionPane.OK_CANCEL_OPTION);
}
if(Label.equals("Bild speichern (JPEG .jpg)")){
saveImage(m_aktBild);
}
if (Label.equals("Bild drucken")){
printImage();
}
if (Label.equals("Bild speichern (PNG .png)")) {
SaveImgAsPng(m_aktBild);
}
}
}
// Im Konstruktor werden ein Panel (als Zeichenfläche)
// und eine Menüleiste angelegt
JBildbearbeitung(String titel) {
super(titel);
m_Xpos = m_Ypos = 0; // Startposition : links oben
m_bild_x1 = m_bild_x2 = m_bild_y1 = m_bild_y2 = 0;
// Zu Beginn ist kein Bild geladen
m_dateiname = null;
m_aktBild = null;
// Einen Layout-Manager anlegen
setLayout(new FlowLayout());
panel=new JPanel();
widthlabel=new JLabel("Breite:");
m_width=new JTextField(4);
heightlabel=new JLabel("Höhe:");
m_height=new JTextField(4);
bresize=new JButton("+");
bresize2=new JButton("-");
bturn=new JButton("drehen");
panel.add(bresize2);
panel.add(widthlabel);
panel.add(m_width);
panel.add(heightlabel);
panel.add(m_height);
panel.add(bresize);
panel.add(bturn);
bresize.addActionListener(new CMeinActionLauscher());
bresize2.addActionListener(new CMeinActionLauscher());
bturn.addActionListener(new CMeinActionLauscher());
add(panel);
// Eine Leinwand anlegen (von JPanel abgeleitet)
m_bildanzeige = new CBildLeinwand();
add(m_bildanzeige);
// Das Fenster mit einer Menüleiste versehen
JMenuBar menueleiste = new JMenuBar();
setJMenuBar(menueleiste);
// Die PopupMenüs der Menüleiste erstellen
JMenu menu1 = new JMenu("Datei");
JMenu menu2= new JMenu("Zoom");
JMenu menu3=new JMenu("Info");
JMenuItem item1 = new JMenuItem("Bild laden");
JMenuItem item3=new JMenuItem("Bild speichern (JPEG .jpg)");
JMenuItem itemPNG=new JMenuItem("Bild speichern (PNG .png)");
JMenuItem item4=new JMenuItem("Bild drucken");
JMenuItem zoomitem1=new JMenuItem("einzoomen");
JMenuItem zoomitem2=new JMenuItem("auszoomen");
JMenuItem infoitem=new JMenuItem("info...");
item1.addActionListener(new CMeinActionLauscher());
zoomitem1.addActionListener(new CMeinActionLauscher());
zoomitem2.addActionListener(new CMeinActionLauscher());
item3.addActionListener(new CMeinActionLauscher());
item4.addActionListener(new CMeinActionLauscher());
itemPNG.addActionListener(new CMeinActionLauscher());
JMenuItem item2 = new JMenuItem("Programm beenden");
item2.addActionListener(new CMeinActionLauscher());
infoitem.addActionListener(new CMeinActionLauscher());
menu1.add(item1);
menu1.add(item3);
menu1.add(itemPNG);
menu1.add(item4);
menu1.add(item2);
menu2.add(zoomitem1);
menu2.add(zoomitem2);
menu3.add(infoitem);
menueleiste.add(menu1);
menueleiste.add(menu2);
menueleiste.add(menu3);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void ResizeImage(int width, int height){
m_tempAnzeigeBild=m_aktBild.getScaledInstance(width, height, Image.SCALE_SMOOTH);
m_aktBild=m_tempAnzeigeBild;
}
public void saveImage(Image Bild) {
FileDialog d = new FileDialog(this,"Bilddatei speichern...",
FileDialog.SAVE);
d.setVisible(true);
if(d.getFile() == null)
return;
String filename;
if (!d.getFile().endsWith(".jpg")){
filename = d.getDirectory()+"/"+ d.getFile()+".jpg";
fileformat="jpg";
}
else {
filename = d.getDirectory()+"/"+ d.getFile();
fileformat="jpg";
}
// Falls der Benutzer keine Datei ausgewählt hat, wird null
// zurückgegeben
// Dann nichts weiter tun
if (Bild!=null) {
try{ File f=new File(filename);
BufferedImage outImg = new BufferedImage(Bild.getWidth(m_bildanzeige), Bild.getHeight(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(Bild, 0, 0, null);
g.dispose();
ImageIO.write(outImg, fileformat, f);
}
catch(IOException e) {JOptionPane.showMessageDialog(null, "Fehler! "+e.getMessage(), "Fehler beim Speichern!", JOptionPane.OK_CANCEL_OPTION); }
}
}
public void SaveImgAsPng(Image Bild){
FileDialog d = new FileDialog(this,"Bilddatei speichern...",
FileDialog.SAVE);
d.setVisible(true);
if(d.getFile() == null)
return;
String filename;
if (!d.getFile().endsWith(".png")){
filename = d.getDirectory()+"/"+ d.getFile()+".png";
fileformat="png";
}
else {
filename = d.getDirectory()+"/"+ d.getFile();
fileformat="png";
}
// Falls der Benutzer keine Datei ausgewählt hat, wird null
// zurückgegeben
// Dann nichts weiter tun
if (Bild!=null) {
try{ File f=new File(filename);
BufferedImage outImg = new BufferedImage(Bild.getWidth(m_bildanzeige), Bild.getHeight(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(Bild, 0, 0, null);
g.dispose();
ImageIO.write(outImg, fileformat, f);
}
catch(IOException e) { JOptionPane.showMessageDialog(null, "Fehler! "+e.getMessage(), "Fehler beim Speichern!", JOptionPane.OK_CANCEL_OPTION);}
}
}
public void turnImage() {
BufferedImage outImg = new BufferedImage(m_aktBild.getWidth(m_bildanzeige), m_aktBild.getHeight(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
Graphics g = outImg.getGraphics();
g.drawImage(m_aktBild, 0, 0, null);
g.dispose();
BufferedImage turnedImg = new BufferedImage(m_aktBild.getHeight(m_bildanzeige), m_aktBild.getWidth(m_bildanzeige), BufferedImage.TYPE_INT_RGB);
turnedImg=rotateImage(outImg, 90);
/*Graphics g2=m_aktBild.getGraphics();
g2.drawImage(turnedImg, 0, 0, null);
g2.dispose();*/
m_aktBild=turnedImg;
m_tempAnzeigeBild=m_aktBild;
}
private static BufferedImage rotateImage(BufferedImage src, double degrees) {
AffineTransform affineTransform = AffineTransform.getRotateInstance(
Math.toRadians(degrees),
src.getWidth() / 2,
src.getHeight() / 2);
BufferedImage rotatedImage = new BufferedImage(src.getWidth(), src
.getHeight(), src.getType());
Graphics2D g = (Graphics2D) rotatedImage.getGraphics();
g.setTransform(affineTransform);
g.drawImage(src, 0, 0, null);
return rotatedImage;
}
public void printImage(){
PrintDialogExample pe=new PrintDialogExample();
pe.SetImage(m_aktBild);
PrinterJob job = PrinterJob.getPrinterJob();
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
PageFormat pf = job.pageDialog(aset);
job.setPrintable(pe, pf);
boolean ok = job.printDialog(aset);
if (ok) {
try {
job.print(aset);
} catch (PrinterException ex) {JOptionPane.showMessageDialog(null, "Fehler! "+ex.getMessage(), "Fehler beim Drucken!", JOptionPane.OK_CANCEL_OPTION);}
}
}
// Eine Bilddatei laden
public void bildLaden(){
FileDialog d = new FileDialog(this,"Bilddatei laden...",
FileDialog.LOAD);
d.setVisible(true);
m_dateiname = d.getDirectory()+"/"+ d.getFile();
// Falls der Benutzer keine Datei ausgewählt hat, wird null
// zurückgegeben
// Dann nichts weiter tun
if(m_dateiname == null)
return;
// Bild laden
ImageIcon tmp = new ImageIcon(m_dateiname);
m_aktBild = tmp.getImage();
m_tempAnzeigeBild=m_aktBild;
// Die Begrenzungskoordinaten des Bildes ermitteln
m_bildBreite = m_tempAnzeigeBild.getWidth(m_bildanzeige);
m_bildHoehe = m_tempAnzeigeBild.getHeight(m_bildanzeige);
m_width.setText(Integer.toString(m_bildBreite)); m_height.setText(Integer.toString(m_bildHoehe));
m_bild_x1 = m_Xpos;
m_bild_y1 = m_Ypos;
m_bild_x2 = m_bild_x1 + m_bildBreite;
m_bild_y2 = m_bild_y1 + m_bildHoehe;
m_fenster.setTitle(m_fenster.getTitle()+" - "+d.getFile());
m_bildanzeige.repaint();
}
public static void main(String[] args) {
m_fenster = new JBildbearbeitung("JBildbearbeitung");
m_fenster.setSize(600,400);
m_fenster.pack();
m_fenster.setVisible(true);
}
// Diese Klasse dient zum Anzeigen und Manipulieren des Bildes
class CBildLeinwand extends JPanel {
// Panel neu zeichnen
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Falls ein Bild geladen ist, das Bild anzeigen
if(m_tempAnzeigeBild != null)
g.drawImage(m_tempAnzeigeBild,m_Xpos,m_Ypos,this);
}
public Dimension getMinimumSize() {
return m_fenster.getSize();
}
public Dimension getPreferredSize() {
return getMinimumSize();
}
}
}