# Skalieren von Image -> java.lang.OutOfMemoryError - WARUM



## HaraldM (13. Jun 2005)

Wie kann ich beim Skalieren eines Bildes einen java.lang.OutOfMemoryError Fehler verhindern?

Es geht um folgendes:

Ich habe ein Imageobjekt 'image' welches auf eine JPEG Datei zeigt. Dieses JPEG Bild ist 3072x2304 Pixel groß (400kb).
Versuche ich nun dieses Bild mit 


```
image = image.getScaledInstance(1300, 1300, Image.SCALE_DEFAULT);
```

auf 1300x1300 zu skalieren, kommt ein java.lang.OutOfMemoryError Fehler. Versuche ich, das Bild auf einen kleineren Wert zu skalieren (z.b. 1000x1000) kommt dieser Fehler nicht. Es ist ebenfalls möglich, ein etwas kleineres Bild (z.b. 2000x2000) auf die Größe 1300x1300 zu skalieren.


Wie kann ich nun diese blöden Fehler verhindern? Es kann doch nicht sein, dass ich mit Java 1.4 und 512 MB RAM ein etwas größeres JPEG nicht skalieren kann.

MfG
Harald


----------



## Wildcard (13. Jun 2005)

Du kannst der VM beim start mehr Speicher reservieren. (-xmx/-xms)


----------



## HaraldM (13. Jun 2005)

super, danke, das funktioniert.

jetzt habe ich aber ein anderes problem. wie kann ich den speicher wieder freigeben?

mein programm ist ein screensaver - solange er minimiert läuft und noch keine bilder anzeigte, benötigt er 2 MB. startet er nun "richtig" und zeigt mehrere bilder an (in einem neuen thread), dann belegt die jvm trotzdem rund 100 mb auch wenn der thread wieder geschlossen ist.

interessant ist, dass wenn ich das eigentliche screensaver programm (für die einstellungen etc) maximiere und dann wieder minimiere, der speicher freigegeben wird.

kann ich das auch irgendwie manuell veranlassen?

mfg!
harald


----------



## Wildcard (13. Jun 2005)

Du kannst es mal mit System.gc() versuchen, aber du hast vermutlich noch Referenzen auf die Bilder gespeichert und bekommst deshalb den Speicher nicht zurück.
100mb kommt mir viel zu viel vor, aber ohne deinen Code zu kennen...

EDIT:
es währe übrigens sehr zu empfehlen ein so großes Bild schon vorher in einem Grafikprog zu skalieren und direkt mit dem kleineren Bild zu arbeiten.


----------



## Guest (13. Jun 2005)

Wildcard hat gesagt.:
			
		

> aber ohne deinen Code zu kennen...
> quote]
> 
> Der Code sieht sinngemäß so aus
> ...


----------



## Wildcard (13. Jun 2005)

Momentmal, du hast 3 Bilder und erzeugst diese ständig neu???
Und dann hast du auch noch jedes Image 3MAL im Speicher!!!
Warum verwendest du nicht die alten weiter?
Kein wunder das du soviel Speicher brauchst...


----------



## HaraldM (13. Jun 2005)

hi,

das war nur beispielhaft. in wirklichkeit sieht's anders aus aber dieses code beispiel demonstriert genau mein problem.

ich skaliere mehrere bilder und mit jedem bild steigt der speicherbedarf um 30 MB obwohl ich immer die gleichen Image und ImageIcon Objekte überschreibe.


----------



## KISS (13. Jun 2005)

rufe doch zwischendurch mal Image.flush() auf, und in der zeit in der du wartest (nimm wait) kannst du ja noch den gc forcen. kann es sein das deine anzeige flackert?


----------



## Wildcard (13. Jun 2005)

bin mir nicht sicher nach welchen Kriterien der gc Image-Objekte beseitigt, aber 30mb pro Bild sollte eigentlich nicht sein


----------



## KISS (13. Jun 2005)

kommt drauf an, wenn genug speicherplatz zur verfuegung steht wird der gc nicht unbedingt aktiv, zumal sich in seinem beispiel alles im selben scope abspielt und 1000*1000*32 (rgba) sind bei mir recht genau 30MB


----------



## Wildcard (13. Jun 2005)

falls du das tatsächlich so ähnlich machst wie oben kann ich dir nur den Tipp geben entweder vorskalieren, oder die Bilder EINMAL erzeugen und dann das Graphics Objekt skalieren.


----------



## HaraldM (13. Jun 2005)

.flush hilft leider auch nicht.
die anzeige flackert sind. außerdem tritt das problem auch auf, wenn ich das bild überhaupt nicht in einer gui anzeige.

30 MB ist schon ok, das hängt von der Bildgröße ab. Die Bilder sind von ner 5 MegaPixel Kamera. Du brauchst also ca. 18 MB pro Original im Speicher und dann nochmal ein paar MB für das skalierte Bild

sonst noch jemand ideen???


----------



## Wildcard (13. Jun 2005)

Ladt alle Bilder auf einmal in ein Array und änder nach 5 sekunden den Index...


----------



## KISS (13. Jun 2005)

ja, nimm mal Xmx wieder auf einen kleineren wert (30MB oder so), in meiner testschleife laesst sich der gc nicht uebereden den speicher aufzuraeumen solange er noch mehr als 1MB free memory hat


----------



## Hansdampf (13. Jun 2005)

> 1000*1000*32 (rgba) sind bei mir recht genau 30MB


hab ich ein Glück, bei mir sinds nur 3.8   
1000*1000*4/(1024*1024)

Bei dir sinds wohl MegaBit?


----------



## Roar (13. Jun 2005)

Hansdampf hat gesagt.:
			
		

> > 1000*1000*32 (rgba) sind bei mir recht genau 30MB
> 
> 
> hab ich ein Glück, bei mir sinds nur 3.8
> ...


muss man das kapieren?


----------



## KISS (13. Jun 2005)

sorry, kam nur bis zur signatur Color(int,int,int,int), das intern nur je das lsbyte genutzt wird ist mir entgangen


----------



## HaraldM (14. Jun 2005)

bisher klappte leider keiner eurer vorschläge. 

was mich erstaunt, ist, dass wenn ich meine anwendung minimiere, der speicher aufgeräumt wird. es muss doch also auch eine möglichkeit geben, das manuell zu machen.

die anwendung mit tofront() in den vordergrund und toback() in den hintergrund zu bringen hilft leider nicht.


----------



## Hansdampf (15. Jun 2005)

> was mich erstaunt, ist, dass wenn ich meine anwendung minimiere, der speicher aufgeräumt wird. es muss doch also auch eine möglichkeit geben, das manuell zu machen.


das Problem hab ich auch bei einer Anwendung, der Speicherverbrauch nimmt dauernd zu. Das Lustige dabei ist: mit Excelsior Jet umgewandelt verschwindet das Problem... (der Speicherzuwachs).



> muss man das kapieren?


ein argb Pixel braucht nur 4 Byte=1 int, nicht 4.


----------

