Bilddarstellung in Java

guitarflow

Mitglied
Hallo liebe Community,

bin momentan grad richtig genervt, dass es in Java so schwierig ist, ein Bild zu skalieren!!
Bin es von C gewohnt, dass ich zwar jedes Pixel anfassen muss, aber dass es wenigstens problemlos funktioniert...

Das Bild von der HD zu laden und anzuzeigen funktioniert einwandfrei, bloss komm ich einfach ums Verrecken nicht auf Höhe und Breite des Bildes!! Habs auch schon mit MediaTrackern probiert, da es scheinbar ein Problem ist, dass ich erst an die Daten komm, wenn das Bild komplett geladen ist.

Geht aber trotzdem nicht... Hoffe ihr könnt mir helfen. Danke schon mal

Hier mal mein bisheriger Code :

Java:
try {
        
       // MyCanvas Definition folgt unten
       canvas = new MyCanvas(picpath);

        } catch (InterruptedException ex) {
            Logger.getLogger(PicTestJFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        this.add(canvas);
        canvas.setSize(600, 600);
        canvas.setLocation(100, 10);

        this.repaint();

Die eigentliche Skalierung passiert in MyCanvas :

Java:
public class MyCanvas extends JPanel {

    public static int instanceCnt =0;
    String filepath;
    Image image=null;

    public MyCanvas (String _filepath) throws InterruptedException{
        this.filepath = _filepath;

        float ratio;
        try {
            image = ImageIO.read(new File(filepath));
        } catch (IOException ex) {
            Logger.getLogger(MyCanvas.class.getName()).log(Level.SEVERE, null, ex);
        }
        MediaTracker mTracker = new MediaTracker(this);
        mTracker.addImage(image,1);
        mTracker.waitForID(1);

        if(mTracker.checkAll()){
        // Speicher die Proportionalitätskonstante
            ratio = image.getHeight(null)/image.getWidth(null);

       // Querformat oder Quadratisch
            if(ratio <=1.00){
                int newHeight = Math.round(image.getWidth(null)/ratio);
                image = image.getScaledInstance(600, newHeight, 0);
            }else{
                int newWidth = Math.round(image.getHeight(null)/ratio);
                image = image.getScaledInstance(newWidth, 600, 0);
            }
        }else{
            System.out.println("Fehler");
        }
    }


    @Override
    public void paintComponent(Graphics g){

        g.drawImage(image, 0, 0,this);
        instanceCnt++;
    }
}

Wo is da der Fehler?? Hab auch schon von ein paar Programmierern gelesen, die mit dem Toolkit arbeiten. Was ist da der Unterschied ?? Was wäre zu bevorzugen?

Danke schon mal,

beste Grüße,

Flo
 
Na da ist Java doch toll, wenn du hier nicht jeden Pixel einzeln anfassen musst 🙂 . Den MediaTracker kannst du dir bei der Verwendung von ImageIO sparen. Dein Fehler liegt darin, dass du zwei Ganzzahlen (getHeight(null)/getWidth(null)) durch einander teilst. Das Ergebnis ist natürlich auch wieder eine Ganzzahl. Du müsstest eine der beiden Zahlen vorher in eine Fließkommazahl casten.
 
Naja, das mit dem Casten is wie bei C.

Is aber in diesem Fall nicht das Problem, da meine Ratio immer 0.0 ist, weil ich beim Debuggen in meinem Bild immer Höhe und Breite -1 hab.

Auch manchmal 0 ;( , ich verstehs einfach nicht ....

Also am Typecast liegts zumindest nicht
 
Natürlich musst du trotzdem richtig casten. Wie debuggst du denn? Geb dir doch einfach mal über sysout die Höhe und die Breite des Bildes aus. Und aktualisierten Code hier rein stellen nicht vergessen. Ansonsten wäre auch mal das Bild interessant, bei dem das Problem auftritt.
 
Also das Bild wird gefunden, wenn ichs mir nur anzeigen will is alles super!

Bloss beim Skalieren bekomm ich Probleme, weil "ratio = 0.0" und ich somit durch 0 teile.
Hier mal der aktuelle Code :

Java:
public MyCanvas (String _filepath){
        this.filepath = _filepath;
        
        try {
            image = ImageIO.read(new File(filepath));
        } catch (IOException ex) {
            Logger.getLogger(MyCanvas.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Speicher die Proportionalitätskonstante
        float height = (float)image.getHeight(this);
        float width = (float)image.getWidth(this);
        
        ratio = (float)image.getHeight(this)/(float)image.getWidth(this);

       // Querformat oder Quadratisch
            if(ratio <=1.00){
                int newHeight = Math.round(image.getWidth(null)/ratio);
                image = image.getScaledInstance(600, newHeight, 0);
            }else{
                int newWidth = Math.round(image.getHeight(null)/ratio);
                image = image.getScaledInstance(newWidth, 600, 0);
            }
    }


    @Override
    public void paintComponent(Graphics g){

        g.drawImage(image, 0, 0,this);
        instanceCnt++;
    }

Ich debugge mit Netbeans...
 
Code:
BufferedImage testImage = ImageIO.read(new File(filepath));
System.out.println("Read "+testImage);
System.out.println("Width "+testImage.getWidth());
System.out.println("Height "+testImage.getHeight());
Was gibt er denn da aus?
 
OK, Leute, versteh jetz nicht wieso.

Hab da gestern echt den ganzen Tag rumprobiert... und plötzlich gehts.
Versteh echt die Welt nicht mehr .... aber trotzdem danke für eure Bemühungen.

Da hätt ich bloss mal noch ne Frage :

Was hats denn mit diesem ImageObserver auf sich?? Beim Normalen Image brauch ich den ja immer, also image.getHeight(ImageObserver ob), beim Buffered Image hingegen brauch ich ihn nicht.

Was macht denn der ImageObserver eigentlich??

Dann hab ich noch festgestellt, dass Java anscheinend Probleme mit großen Bildern hat.
Hab hier mal testweise noch ein Panoramabild mit 11,8 MB und 23.000 * 2.000 Px.

Bekomm hier einen OutOfMemory Error : Java Heap Space.
Wie kann denn das sein? Also Arbeitsspeicher is definitiv noch genug vorhanden ...

mfg,

Flo
 
Arbeitsspeicher ja, aber die JVM hat am Anfang einen bestimmten Speicher (standardmäßig 64MB), wenn der voll ist, kommt es zu dem OOME. Kann man aber erhöhen.

Ein BufferedImage ist Pixelgenau. Heißt bei 23000x2000 Pixeln und 3 Farbkanälen je 8 Bit hast du auf jeden Fall schon einmal 132MB.
 
Ah ok,

das is ja interessant.
Kannst du mir sagen, wie ich den Speicher erhöhe??
Wäre ja vielleicht auch für zukünftige Projekte mal ganz nett zu wissen.

Muss ich das in NetBeans machen oder im Code??
Wenn ichs nur in NetBeans mache, dann würds zwar bei mir gehen, aber bei jedem anderen ne Exception werfen, oder?

danke vorab,:toll:

Flo
 

Zurück
Oben