2016-04-23 35 views
0

黑色邊框我使用這個壓縮類從以下站點:http://voidcanvas.com/whatsapp-like-image-compression-in-android/安卓:壓縮圖像創建上左,上邊距

這裏是我壓縮類從原來的類很少的修改:

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 java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 

import timber.log.Timber; 

//http://voidcanvas.com/whatsapp-like-image-compression-in-android/ 
public class ImageCompressor { 

    public ImageCompressor() {} 

    public static String compressImage(String imagePath, Context context) { 
     Bitmap scaledBitmap = null; 
     String filename = "compressed_" +imagePath.substring(imagePath.lastIndexOf("/")+1); 

     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; 
     Timber.e("imagePath "+imagePath); 
     Timber.e("filename "+filename); 
     Bitmap bmp = BitmapFactory.decodeFile(imagePath, options); 
     if (options == null) { 
      Timber.e("zero bitmap"); 
     } 
     int actualHeight = options.outHeight; 
     int actualWidth = options.outWidth; 
     float imgRatio = actualWidth/actualHeight; 

     float maxHeight = actualHeight * 10/20; 
     float maxWidth = actualWidth * 10/20; 
     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(imagePath, options); 
     } catch (OutOfMemoryError exception) { 
      exception.printStackTrace(); 

     } 
     try { 
      scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888); 
     } catch (OutOfMemoryError exception) { 
      exception.printStackTrace(); 
     } 

     float ratioX = actualWidth/(float) options.outWidth; 
     float ratioY = actualHeight/(float) options.outHeight; 
     float middleX = actualWidth/2.0f; 
     float middleY = actualHeight/2.0f; 

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

     Canvas canvas = new Canvas(scaledBitmap); 
     canvas.setMatrix(scaleMatrix); 
     canvas.drawBitmap(bmp, middleX - bmp.getWidth()/2, middleY - bmp.getHeight()/2, new Paint(Paint.FILTER_BITMAP_FLAG)); 

//  check the rotation of the image and display it properly 
     ExifInterface exif; 
     try { 
      exif = new ExifInterface(imagePath); 

      int orientation = exif.getAttributeInt(
        ExifInterface.TAG_ORIENTATION, 0); 
      Timber.e("Exif: " + orientation); 
      Matrix matrix = new Matrix(); 
      if (orientation == 6) { 
       matrix.postRotate(90); 
       Timber.e("Exif: " + orientation); 
      } else if (orientation == 3) { 
       matrix.postRotate(180); 
       Timber.e("Exif: " + orientation); 
      } else if (orientation == 8) { 
       matrix.postRotate(270); 
       Timber.e("Exif: " + orientation); 
      } 
      scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, 
        scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, 
        true); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (NullPointerException e) { 
      e.printStackTrace(); 
     } 

     FileOutputStream out = null; 

     try { 

      out = context.openFileOutput(filename, Context.MODE_PRIVATE); 
      scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 

      out.close(); 

     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
      return filename; 
     } 

    public 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; 
    } 

} 
} 

這是我原來的圖像:

enter image description here

這是我compresse d圖片:

enter image description here

我不明白,爲什麼在壓縮後的圖像對圖像的頂部和左側黑色輪廓。它似乎只發生在低分辨率圖像上;如果這是一部手機相機的照片,這將不會發生,因爲這是一個高分辨率的圖像。如果這是一張來自互聯網的低分辨率照片,這將會發生。

有誰知道我該如何解決這個問題?

編輯:

爲了測試這一點,你可以在這裏下載演示項目或創建自己:http://www.voidcanvas.com/projects/1951EfficientImageLoading.zip您需要在您的手機或模擬器瀏覽器導航到谷歌圖片照片,並儘量壓縮它。結果看起來像下面,你可以看到出現在左,右兩側的黑色邊框:

enter image description here

回答

2

我相信問題來源於此行:

canvas.drawBitmap(bmp, middleX - bmp.getWidth()/2, middleY - bmp.getHeight()/2, new Paint(Paint.FILTER_BITMAP_FLAG)); 

你失去由整數除以精度2.

嘗試這樣的事:

canvas.drawBitmap(bmp, middleX - (float)bmp.getWidth()/2.0f, middleY - (float)bmp.getHeight()/2.0f, new Paint(Paint.FILTER_BITMAP_FLAG)); 
+0

謝謝 - 這是正確的答案,並修復了我的錯誤。我將在接下來的17個小時內向您頒發這筆賞金,因爲我現在不能頒獎。 – Simon

+0

太好了,我很高興解決了這個問題,謝謝。 –