2017-01-31 1 views
0

Ich habe ein Stück einen Code, wo ich eine Bitmap komprimieren und skalieren, wenn es scheint, dass ihre Breite zu breit ist. Der Code funktioniert, aber ich weiß, dass Bitmap, Größenanpassung und Komprimierung teure Aufgaben sind, und ich befürchte, dass mein Code es in Bezug auf die Leistung nicht richtig macht.Bitmap Größe und Komprimierung optimieren

Könnten Sie bitte einen Blick darauf werfen und bessere Wege vorschlagen, um es zu erreichen?

Danke,

Andy

Hier ist der Code:

// Max Width size 
     final int destWidth = 2300; 


     // Compress the Image 
     ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
     Bitmap bitmap = null; 
     Bitmap resizedBitmap = null; 
     String path = null; 

     try { 
      bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), imageUri); 
      bitmap.compress(Bitmap.CompressFormat.JPEG, 20, bytes); 
      path = MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), bitmap, imageUri.getEncodedQuery(), null); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     if (bitmap != null) { 
      if (bitmap.getWidth() > destWidth) { 
       final int desHeight = bitmap.getHeight()/(bitmap.getWidth()/destWidth); 
       resizedBitmap = Bitmap.createScaledBitmap(bitmap, destWidth, desHeight,false); 
       resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 20, bytes); 
       path = MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), resizedBitmap, imageUri.getEncodedQuery(), null); 
      } 
     } 

     final Uri uri = Uri.parse(path); 


     // Clean up 
     try { 
      bitmap.recycle(); 
      bytes.close(); 

      if (resizedBitmap != null) { 
       resizedBitmap.recycle(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

Antwort

0

Sie können die folgenden Java-Klassen für Ihre Zwecke verwenden. Dies ist vollständig optimiert.

ERINNERN Sie sich Import in Ihrem Projekt.

FileUtil.java

import android.content.Context; 
import android.database.Cursor; 
import android.net.Uri; 
import android.provider.MediaStore; 
import android.provider.OpenableColumns; 
import android.util.Log; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

/** 
* Created by aupadhyay on 1/31/17. 
*/ 

public class FileUtil { 
    static final String FILES_PATH = "CompressImage"; 
    private static final int EOF = -1; 
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; 

    private FileUtil() { 

    } 

    public static File from(Context context, Uri uri) throws IOException { 
     InputStream inputStream = context.getContentResolver().openInputStream(uri); 
     String fileName = getFileName(context, uri); 
     String[] splitName = splitFileName(fileName); 
     File tempFile = File.createTempFile(splitName[0], splitName[1]); 
     tempFile = rename(tempFile, fileName); 
     tempFile.deleteOnExit(); 
     FileOutputStream out = null; 
     try { 
      out = new FileOutputStream(tempFile); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     if (inputStream != null) { 
      copy(inputStream, out); 
      inputStream.close(); 
     } 

     if (out != null) { 
      out.close(); 
     } 
     return tempFile; 
    } 

    static String[] splitFileName(String fileName) { 
     String name = fileName; 
     String extension = ""; 
     int i = fileName.lastIndexOf("."); 
     if (i != -1) { 
      name = fileName.substring(0, i); 
      extension = fileName.substring(i); 
     } 

     return new String[]{name, extension}; 
    } 

    static String getFileName(Context context, Uri uri) { 
     String result = null; 
     if (uri.getScheme().equals("content")) { 
      Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); 
      try { 
       if (cursor != null && cursor.moveToFirst()) { 
        result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } finally { 
       if (cursor != null) { 
        cursor.close(); 
       } 
      } 
     } 
     if (result == null) { 
      result = uri.getPath(); 
      int cut = result.lastIndexOf(File.separator); 
      if (cut != -1) { 
       result = result.substring(cut + 1); 
      } 
     } 
     return result; 
    } 

    static String getRealPathFromURI(Context context, Uri contentUri) { 
     Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null); 
     if (cursor == null) { 
      return contentUri.getPath(); 
     } else { 
      cursor.moveToFirst(); 
      int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
      String realPath = cursor.getString(index); 
      cursor.close(); 
      return realPath; 
     } 
    } 

    static File rename(File file, String newName) { 
     File newFile = new File(file.getParent(), newName); 
     if (!newFile.equals(file)) { 
      if (newFile.exists()) { 
       if (newFile.delete()) { 
        Log.d("FileUtil", "Delete old " + newName + " file"); 
       } 
      } 
      if (file.renameTo(newFile)) { 
       Log.d("FileUtil", "Rename file to " + newName); 
      } 
     } 
     return newFile; 
    } 

    static int copy(InputStream input, OutputStream output) throws IOException { 
     long count = copyLarge(input, output); 
     if (count > Integer.MAX_VALUE) { 
      return -1; 
     } 
     return (int) count; 
    } 

    static long copyLarge(InputStream input, OutputStream output) 
      throws IOException { 
     return copyLarge(input, output, new byte[DEFAULT_BUFFER_SIZE]); 
    } 

    static long copyLarge(InputStream input, OutputStream output, byte[] buffer) 
      throws IOException { 
     long count = 0; 
     int n; 
     while (EOF != (n = input.read(buffer))) { 
      output.write(buffer, 0, n); 
      count += n; 
     } 
     return count; 
    } 
} 

ImageUtil.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.Paint; 
import android.media.ExifInterface; 
import android.net.Uri; 
import android.text.TextUtils; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 

/** 
* Created by aupadhyay on 1/31/17. 
*/ 

class ImageUtil { 

    private ImageUtil() { 

    } 

    static Bitmap getScaledBitmap(Context context, Uri imageUri, float maxWidth, float maxHeight, Bitmap.Config bitmapConfig) { 
     String filePath = FileUtil.getRealPathFromURI(context, imageUri); 
     Bitmap scaledBitmap = null; 

     BitmapFactory.Options options = new BitmapFactory.Options(); 

     //by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If 
     //you try the use the bitmap here, you will get null. 
     options.inJustDecodeBounds = true; 
     Bitmap bmp = BitmapFactory.decodeFile(filePath, options); 
     if (bmp == null) { 

      InputStream inputStream = null; 
      try { 
       inputStream = new FileInputStream(filePath); 
       BitmapFactory.decodeStream(inputStream, null, options); 
       inputStream.close(); 
      } catch (FileNotFoundException exception) { 
       exception.printStackTrace(); 
      } catch (IOException exception) { 
       exception.printStackTrace(); 
      } 
     } 

     int actualHeight = options.outHeight; 
     int actualWidth = options.outWidth; 

     if (actualWidth < 0 || actualHeight < 0) { 
      Bitmap bitmap2 = BitmapFactory.decodeFile(filePath); 
      actualWidth = bitmap2.getWidth(); 
      actualHeight = bitmap2.getHeight(); 
     } 

     float imgRatio = (float) actualWidth/actualHeight; 
     float maxRatio = maxWidth/maxHeight; 

     //width and height values are set maintaining the aspect ratio of the image 
     if (actualHeight > maxHeight || actualWidth > maxWidth) { 
      if (imgRatio < maxRatio) { 
       imgRatio = maxHeight/actualHeight; 
       actualWidth = (int) (imgRatio * actualWidth); 
       actualHeight = (int) maxHeight; 
      } else if (imgRatio > maxRatio) { 
       imgRatio = maxWidth/actualWidth; 
       actualHeight = (int) (imgRatio * actualHeight); 
       actualWidth = (int) maxWidth; 
      } else { 
       actualHeight = (int) maxHeight; 
       actualWidth = (int) maxWidth; 
      } 
     } 

     //setting inSampleSize value allows to load a scaled down version of the original image 
     options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight); 

     //inJustDecodeBounds set to false to load the actual bitmap 
     options.inJustDecodeBounds = false; 

     //this options allow android to claim the bitmap memory if it runs low on memory 
     options.inPurgeable = true; 
     options.inInputShareable = true; 
     options.inTempStorage = new byte[16 * 1024]; 

     try { 
      //load the bitmap from its path 
      bmp = BitmapFactory.decodeFile(filePath, options); 
      if (bmp == null) { 

       InputStream inputStream = null; 
       try { 
        inputStream = new FileInputStream(filePath); 
        BitmapFactory.decodeStream(inputStream, null, options); 
        inputStream.close(); 
       } catch (FileNotFoundException exception) { 
        exception.printStackTrace(); 
       } catch (IOException exception) { 
        exception.printStackTrace(); 
       } 
      } 
     } catch (OutOfMemoryError exception) { 
      exception.printStackTrace(); 
     } 
     try { 
      scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, bitmapConfig); 
     } catch (OutOfMemoryError exception) { 
      exception.printStackTrace(); 
     } 

     float ratioX = actualWidth/(float) options.outWidth; 
     float ratioY = actualHeight/(float) options.outHeight; 

     Matrix scaleMatrix = new Matrix(); 
     scaleMatrix.setScale(ratioX, ratioY, 0, 0); 

     Canvas canvas = new Canvas(scaledBitmap); 
     canvas.setMatrix(scaleMatrix); 
     canvas.drawBitmap(bmp, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG)); 

     //check the rotation of the image and display it properly 
     ExifInterface exif; 
     try { 
      exif = new ExifInterface(filePath); 
      int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0); 
      Matrix matrix = new Matrix(); 
      if (orientation == 6) { 
       matrix.postRotate(90); 
      } else if (orientation == 3) { 
       matrix.postRotate(180); 
      } else if (orientation == 8) { 
       matrix.postRotate(270); 
      } 
      scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, 
        scaledBitmap.getWidth(), scaledBitmap.getHeight(), 
        matrix, true); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return scaledBitmap; 
    } 

    static File compressImage(Context context, Uri imageUri, float maxWidth, float maxHeight, 
           Bitmap.CompressFormat compressFormat, Bitmap.Config bitmapConfig, 
           int quality, String parentPath, String prefix, String fileName) { 
     FileOutputStream out = null; 
     String filename = generateFilePath(context, parentPath, imageUri, compressFormat.name().toLowerCase(), prefix, fileName); 
     try { 
      out = new FileOutputStream(filename); 

      //write the compressed bitmap at the destination specified by filename. 
      ImageUtil.getScaledBitmap(context, imageUri, maxWidth, maxHeight, bitmapConfig).compress(compressFormat, quality, out); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       if (out != null) { 
        out.close(); 
       } 
      } catch (IOException ignored) { 
      } 
     } 

     return new File(filename); 
    } 

    private static String generateFilePath(Context context, String parentPath, Uri uri, 
              String extension, String prefix, String fileName) { 
     File file = new File(parentPath); 
     if (!file.exists()) { 
      file.mkdirs(); 
     } 
     /** if prefix is null, set prefix "" */ 
     prefix = TextUtils.isEmpty(prefix) ? "" : prefix; 
     /** reset fileName by prefix and custom file name */ 
     fileName = TextUtils.isEmpty(fileName) ? prefix + FileUtil.splitFileName(FileUtil.getFileName(context, uri))[0] : fileName; 
     return file.getAbsolutePath() + File.separator + fileName + "." + extension; 
    } 

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
     final int height = options.outHeight; 
     final int width = options.outWidth; 
     int inSampleSize = 1; 

     if (height > reqHeight || width > reqWidth) { 
      final int heightRatio = Math.round((float) height/(float) reqHeight); 
      final int widthRatio = Math.round((float) width/(float) reqWidth); 
      inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
     } 

     final float totalPixels = width * height; 
     final float totalReqPixelsCap = reqWidth * reqHeight * 2; 

     while (totalPixels/(inSampleSize * inSampleSize) > totalReqPixelsCap) { 
      inSampleSize++; 
     } 

     return inSampleSize; 
    } 
} 

CompressImage.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.net.Uri; 

import java.io.File; 

import rx.Observable; 
import rx.functions.Func0; 

/** 
* Created by aupadhyay on 1/31/17. 
*/ 

public class CompressImage { 
    private static volatile CompressImage INSTANCE; 
    private Context context; 
    //max width and height values of the compressed image is taken as 612x816 
    private float maxWidth = 612.0f; 
    private float maxHeight = 816.0f; 
    private Bitmap.CompressFormat compressFormat = Bitmap.CompressFormat.JPEG; 
    private Bitmap.Config bitmapConfig = Bitmap.Config.ARGB_8888; 
    private int quality = 80; 
    private String destinationDirectoryPath; 
    private String fileNamePrefix; 
    private String fileName; 


    private CompressImage(Context context) { 
     this.context = context; 
     destinationDirectoryPath = context.getCacheDir().getPath() + File.pathSeparator + FileUtil.FILES_PATH; 
    } 

    public static CompressImage getDefault(Context context) { 
     if (INSTANCE == null) { 
      synchronized (CompressImage.class) { 
       if (INSTANCE == null) { 
        INSTANCE = new CompressImage(context); 
       } 
      } 
     } 
     return INSTANCE; 
    } 

    public File compressToFile(File file) { 
     return ImageUtil.compressImage(context, Uri.fromFile(file), maxWidth, maxHeight, 
       compressFormat, bitmapConfig, quality, destinationDirectoryPath, 
       fileNamePrefix, fileName); 
    } 

    public Bitmap compressToBitmap(File file) { 
     return ImageUtil.getScaledBitmap(context, Uri.fromFile(file), maxWidth, maxHeight, bitmapConfig); 
    } 

    public Observable<File> compressToFileAsObservable(final File file) { 
     return Observable.defer(new Func0<Observable<File>>() { 
      @Override 
      public Observable<File> call() { 
       return Observable.just(compressToFile(file)); 
      } 
     }); 
    } 

    public Observable<Bitmap> compressToBitmapAsObservable(final File file) { 
     return Observable.defer(new Func0<Observable<Bitmap>>() { 
      @Override 
      public Observable<Bitmap> call() { 
       return Observable.just(compressToBitmap(file)); 
      } 
     }); 
    } 

    public static class Builder { 
     private CompressImage compressImage; 

     public Builder(Context context) { 
      compressImage = new CompressImage(context); 
     } 

     public Builder setMaxWidth(float maxWidth) { 
      compressImage.maxWidth = maxWidth; 
      return this; 
     } 

     public Builder setMaxHeight(float maxHeight) { 
      compressImage.maxHeight = maxHeight; 
      return this; 
     } 

     public Builder setCompressFormat(Bitmap.CompressFormat compressFormat) { 
      compressImage.compressFormat = compressFormat; 
      return this; 
     } 

     public Builder setBitmapConfig(Bitmap.Config bitmapConfig) { 
      compressImage.bitmapConfig = bitmapConfig; 
      return this; 
     } 

     public Builder setQuality(int quality) { 
      compressImage.quality = quality; 
      return this; 
     } 

     public Builder setDestinationDirectoryPath(String destinationDirectoryPath) { 
      compressImage.destinationDirectoryPath = destinationDirectoryPath; 
      return this; 
     } 

     public Builder setFileNamePrefix(String prefix) { 
      compressImage.fileNamePrefix = prefix; 
      return this; 
     } 

     public Builder setFileName(String fileName) { 
      compressImage.fileName = fileName; 
      return this; 
     } 

     public CompressImage build() { 
      return compressImage; 
     } 
    } 
} 

Jetzt com Drücken Sie Ihr Bild können Sie diesen Code-Schnipsel verwenden:

 // Compress image using RxJava in background thread 
     CompressImage.getDefault(this) 
       .compressToFileAsObservable(actualImage) 
       .subscribeOn(Schedulers.io()) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(new Action1<File>() { 
        @Override 
        public void call(File file) { 
         compressedImage = file; 
         // use compressedImage or pass in any function. 
        } 
       }, new Action1<Throwable>() { 
        @Override 
        public void call(Throwable throwable) { 
         //throwable.getMessage(); 
        } 
       }); 

Wo wir actualImage und compressedImage als File-Objekt haben.

private File actualImage; 
private File compressedImage; 

** UPDATE

Intent Fotogalerie zu öffnen:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
     intent.setType("image/*"); 
     startActivityForResult(intent, PICK_IMAGE_REQUEST); // private static final int PICK_IMAGE_REQUEST = 1; 

Und Sie können wie Ihre onActivityResult haben:

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK) { 
     if (data == null) { 
      //Failed to open picture! 
      return; 
     } 
     try { 
      actualImage = FileUtil.from(this, data.getData());// conversion to file is important. 

     } catch (IOException e) { 
      //Failed to read picture data! 
      e.printStackTrace(); 
     } 
    } 
} 

Jetzt ziehe ich an‘ Ich denke du solltest e Fehler.

+0

Es sagt der compressedImage ist null: E/BitmapFactory: Nicht imstande, Strom zu entschlüsseln: java.io.FileNotFoundException: /[email protected]832dd: Öffnen fehlgeschlagen: ENOENT (Keine solche Datei oder das Verzeichnis) –

+0

@ AndyStrife: Aktualisiere meine Antwort –

+0

Das ist so ziemlich, wie ich es tat, funktioniert nicht. Ich untersuche immer noch –

Verwandte Themen