Aufgenommene Bilder verkleinern

  • Antworten:7
  • Bentwortet
Dom Santiago
  • Forum-Beiträge: 30

20.11.2012, 09:13:41 via Website

Hallo Zusammen!

Ich benötige eure Hilfe in meinem kleinen App Beispiel. Ich rufe per Intent die Action "android.provider.MediaStore.ACTION_IMAGE_CAPTURE" auf, greife damit auf die Kamera zu, mache von dort ein Bild und speichere dieses per "intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);" in dem mitgegebenen Pfad. Soweit so gut.
Die Größe der Bilder liegt momentan bei 1,5 MB und diese würde ich gerne verkleinern. Meine Frage ist also,
über welche Methode oder Befehl kann ich dies ermöglichen?

Danke und gruß

Dom

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

20.11.2012, 09:30:09 via Website

http://stackoverflow.com/questions/3331527/android-resize-a-large-bitmap-file-to-scaled-output-file

Nachteil hierbei:
Beim einlesen des Bitmap gibt man einen Skalierungsfaktor X mit und liest es also mit einer Auflösung ORGINAL geteilt durch X ein.
Dadurch kommen halt teilweise ungrade neue Auflösungen raus, wie 426 oder so.

Vorteil dieser Methode:
Es wird nur das verkleinerte Bitmap in den Speicher geladen. Würde man ein 8MP Bild in voller Auflösung laden, würde das den Heap unter Android sprengen.

Will man auf eine genaue Auflösung skalieren, kann man dann dieses kleinere, bereits skalierte Bitmap laden und mit Matrix skalieren.
Siehe hier: http://thinkandroid.wordpress.com/2009/12/25/resizing-a-bitmap/

Einen besseren Weg hab ich unter Android bisher nicht gefunden. Eine Skalierung auf eine genaue Wunschauflösung läuft also immer in 2 Schritten.

Antworten
Dom Santiago
  • Forum-Beiträge: 30

20.11.2012, 11:03:59 via Website

Super, danke für die schnelle Hilfe.

Ich habe meinem Quellcode folgendes hinzugefügt:

//verändere die Größe vom geholten Bitmap und speicher die Änderung in bitmap1
Bitmap bitmap1 = Bitmap.createScaledBitmap(bitmap, 500, 375, true);


Dann wollte ich bitmap1 auf meiner SD-Karte mit neuen Pfad speichern,

FileOutputStream out = new FileOutputStream(path2);
bitmap1.compress(Bitmap.CompressFormat.JPEG, 80, out);

doch leider schreibt er mir das Bild nicht zurück, was mache ich falsch?

Antworten
Dom Santiago
  • Forum-Beiträge: 30

20.11.2012, 16:51:20 via Website

Kann ich so nicht sagen, da bei Kamerafunktionen der Emulator nicht mitspielt und ich von Handy aus teste.

Antworten
Dom Santiago
  • Forum-Beiträge: 30

20.11.2012, 17:31:00 via Website

So habe mein Mobile mit angeschlossen und kann jetzt auch darüber debuggen.

Hier kommt der Eintrag aus dem LogCat, sind allerdings auch nur "Warnungen"

W/IInputConnectionWrapper(7266): showStatusIcon on inactive InputConnection
W/System.err(7266): java.io.FileNotFoundException: /mnt/sdcard/images/make_machine_example_size.jpg: open failed: EACCES (Permission denied)
W/System.err(7266): at libcore.io.IoBridge.open(IoBridge.java:406)
W/System.err(7266): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err(7266): at java.io.FileOutputStream.<init>(FileOutputStream.java:128)
W/System.err(7266): at java.io.FileOutputStream.<init>(FileOutputStream.java:117)
W/System.err(7266): at com.example.emobilitycam.EMobilityCam$ButtonClickHandler1.onClick(EMobilityCam.java:99)
W/System.err(7266): at android.view.View.performClick(View.java:3644)
W/System.err(7266): at android.view.View$PerformClick.run(View.java:14313)
W/System.err(7266): at android.os.Handler.handleCallback(Handler.java:605)
W/System.err(7266): at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err(7266): at android.os.Looper.loop(Looper.java:137)
W/System.err(7266): at android.app.ActivityThread.main(ActivityThread.java:4517)
W/System.err(7266): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err(7266): at java.lang.reflect.Method.invoke(Method.java:511)
W/System.err(7266): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
W/System.err(7266): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
W/System.err(7266): at dalvik.system.NativeStart.main(Native Method)
W/System.err(7266): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
W/System.err(7266): at libcore.io.Posix.open(Native Method)
W/System.err(7266): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err(7266): at libcore.io.IoBridge.open(IoBridge.java:390)
W/System.err(7266): ... 15 more
W/IInputConnectionWrapper(7266): showStatusIcon on inactive InputConnection

Antworten
Dom Santiago
  • Forum-Beiträge: 30

20.11.2012, 21:20:04 via Website

So, kann das Bild jetzt verkleinern und wieder abspeichern. Es lag wohl daran, dass ich den OutputStream nicht über write ausgeführt habe.
Hier mal der ausführliche Code zum Nachlesen:
1//Hole Bild von der SD-Card und speicher es als Bitmap
2 Bitmap bitmap = BitmapFactory.decodeFile(path);
3
4 //Verkleinere das Bitmap
5 bitmap = Bitmap.createScaledBitmap(bitmap, 500, 375, true);
6
7 //Verändere die Qualität des Bitmaps geringfügig
8 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
9 bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bytes);
10
11 //Speichere das Bitmap zurück auf die SD-Card
12 //Erstelle ein File und übergebe den Pfad
13 File f = new File(path2);
14 f.createNewFile();
15
16 //Schreibe die bytes in das File
17 FileOutputStream fo = new FileOutputStream(f);
18 fo.write(bytes.toByteArray());
19
20 //FileOutput wieder schließen
21 fo.close();


Damit habe ich es geschafft ein 1,5 MB großes Image auf 36 KB zu verkleinern. Die Qualität ist weiterhin recht gut.

Danke für eure Hilfe, bis dahin.

Dom

Antworten