Android – Skalieren und komprimieren Sie eine Bitmap

Ich arbeite an einer Android-App, die Kamera-Capture und Foto-Upload-Funktion hat. Wenn das Gerät eine hochauflösende Kamera hat, wird die aufgenommene Bildgröße wirklich groß (1 ~ 3MB oder mehr).
Da die App dieses Bild auf den Server hochladen muss, muss ich das Bild vor dem Hochladen komprimieren. Wenn die Kamera zum Beispiel ein 1920×1080 Full-Res-Foto aufgenommen hat, ist die ideale Ausgabe, um ein 16: 9-Verhältnis des Bildes zu behalten, es zu einem Bild von 640×360 zu komprimieren, um eine Bildqualität zu reduzieren und es in Bytes kleiner zu machen.

Hier ist mein Code (referenziert von Google):

  • Garbage Collector in Android
  • Align Center Menü Item Text in Android
  • Was ist mit TransactionTooLargeException zu tun?
  • Was ist AttributeSet und wie kann ich es verwenden?
  • Android-Logcat-Fehler: ZipFileCache: init fehlgeschlagen, wenn offene Zip-Datei - gerätespezifisch?
  • Alarm Manager Ausgabe in Android 6.0 Doze-Modus
  • /** * this class provide methods that can help compress the image size. * */ public class ImageCompressHelper { /** * Calcuate how much to compress the image * @param options * @param reqWidth * @param reqHeight * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } /** * resize image to 480x800 * @param filePath * @return */ public static Bitmap getSmallBitmap(String filePath) { File file = new File(filePath); long originalSize = file.length(); MyLogger.Verbose("Original image size is: " + originalSize + " bytes."); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(filePath, options); // Calculate inSampleSize based on a preset ratio options.inSampleSize = calculateInSampleSize(options, 480, 800); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; Bitmap compressedImage = BitmapFactory.decodeFile(filePath, options); MyLogger.Verbose("Compressed image size is " + sizeOf(compressedImage) + " bytes"); return compressedImage; } 

    Das Problem mit dem oben genannten Code ist:

    1. Es kann das Verhältnis nicht beibehalten, der Code zwingt das Bild auf 480×800. Wenn der Benutzer ein Bild in einem anderen Verhältnis aufgenommen hat, sieht das Bild nach dem Komprimieren nicht gut aus.
    2. Es funktioniert nicht gut. Der Code wird immer die Bildgröße auf 7990272byte ändern, egal was die ursprüngliche Dateigröße ist. Wenn die ursprüngliche Bildgröße schon ziemlich klein ist, wird es es groß machen (mein Testergebnis, um ein Bild von meiner Wand zu machen, das ist so ziemlich einfarbig):

      Original image size is: 990092 bytes.
      Compressed image size is 7990272 bytes

    Ich frage, ob es einen Vorschlag für einen besseren Weg, um Foto zu komprimieren, so dass es problemlos hochgeladen werden kann?

  • Geolocation, Service und lokale Benachrichtigungen
  • Java.lang.NoClassDefFoundError: com.google.ads.AdView
  • Speichern Sie die Orientierung auf ein Array - und vergleichen Sie es
  • TargetSdkVersion Einstellung
  • Tracing der Speicher / Fenster Lecks in Android?
  • Lineare Algebra-Bibliothek für Android
  • 2 Solutions collect form web for “Android – Skalieren und komprimieren Sie eine Bitmap”

    1. Sie müssen entscheiden, auf eine Grenze für Ihre Breite oder Höhe (nicht beide, offensichtlich). Dann ersetzen Sie diese festen Bildgrößen mit berechneten, sagen:

       int targetWidth = 640; // your arbitrary fixed limit int targetHeight = (int) (originalHeight * targetWidth / (double) originalWidth); // casts to avoid truncating 

      (Hinzufügen von Prüfungen und Berechnungsalternativen für Landschafts- / Hochformatausrichtung nach Bedarf).

    2. Als @harism auch kommentiert: die große Größe, die Sie erwähnt wird, ist die rohe Größe dieser 480×800 Bitmap, nicht die Dateigröße, die ein JPEG in Ihrem Fall sein sollte. Wie gehst du damit, diese Bitmap zu speichern, BTW? Dein Code scheint nicht das Sparteil zu enthalten.

      Sehen Sie diese Frage hier für Hilfe, dass mit dem Schlüssel etwas wie:

       OutputStream imagefile = new FileOutputStream("/your/file/name.jpg"); // Write 'bitmap' to file using JPEG and 80% quality hint for JPEG: bitmap.compress(CompressFormat.JPEG, 80, imagefile); 

    Zuerst überprüfe ich die Größe des Bildes dann komprimiere ich das Bild nach Größe und bekomme komprimierte Bitmap dann sende diese Bitmap zum Server Für Compressed Bitmap Aufruf unter funtion müssen wir Bildpfad in unterhalb funtion passieren

     public Bitmap get_Picture_bitmap(String imagePath) { long size_file = getFileSize(new File(imagePath)); size_file = (size_file) / 1000;// in Kb now int ample_size = 1; if (size_file <= 250) { System.out.println("SSSSS1111= " + size_file); ample_size = 2; } else if (size_file > 251 && size_file < 1500) { System.out.println("SSSSS2222= " + size_file); ample_size = 4; } else if (size_file >= 1500 && size_file < 3000) { System.out.println("SSSSS3333= " + size_file); ample_size = 8; } else if (size_file >= 3000 && size_file <= 4500) { System.out.println("SSSSS4444= " + size_file); ample_size = 12; } else if (size_file >= 4500) { System.out.println("SSSSS4444= " + size_file); ample_size = 16; } Bitmap bitmap = null; BitmapFactory.Options bitoption = new BitmapFactory.Options(); bitoption.inSampleSize = ample_size; Bitmap bitmapPhoto = BitmapFactory.decodeFile(imagePath, bitoption); ExifInterface exif = null; try { exif = new ExifInterface(imagePath); } catch (IOException e) { // Auto-generated catch block e.printStackTrace(); } int orientation = exif .getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); Matrix matrix = new Matrix(); if ((orientation == 3)) { matrix.postRotate(180); bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, true); } else if (orientation == 6) { matrix.postRotate(90); bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, true); } else if (orientation == 8) { matrix.postRotate(270); bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, true); } else { matrix.postRotate(0); bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, true); } return bitmap; } 

    GetFileSize funtion für das Erhalten der Größe des Bildes

      public long getFileSize(final File file) { if (file == null || !file.exists()) return 0; if (!file.isDirectory()) return file.length(); final List<File> dirs = new LinkedList<File>(); dirs.add(file); long result = 0; while (!dirs.isEmpty()) { final File dir = dirs.remove(0); if (!dir.exists()) continue; final File[] listFiles = dir.listFiles(); if (listFiles == null || listFiles.length == 0) continue; for (final File child : listFiles) { result += child.length(); if (child.isDirectory()) dirs.add(child); } } return result; } 
    Das Android ist ein Google Android Fan-Website, Alles ├╝ber Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.