Android:图像压缩中出现黑色背景而不会降低质量

时间:2023-02-08 21:47:10

Following is the class file I'm using for Image compression and it's working very well but the problem is when I use low resolution images the output Image drawn with black background. Can anybody tell me where I need to make changes?

以下是我用于图像压缩的类文件,它工作得非常好,但问题是当我使用低分辨率图像输出用黑色背景绘制的图像时。谁能告诉我需要做哪些改变?

public class CompressImage {

public static Context context;

/**
 * @function returnCompressImage() - will return the compressed Image Path
 * @param mContext
 * @param imageUri
 * @return
 */
public static String returnCompressImage(Context mContext, String imageUri, int imageId, int optionId) {
    context = mContext;

    String filePath = getRealPathFromURI(context, imageUri);
    String compressImageFilePath = "";

    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);// actual bitmap

    // File mFile = new File(filePath);
    // long fileSize = mFile.length() / 1024;

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

    // max Height and width values of the compressed image is taken as 800x480

    float maxHeight = 816.0f;
    float maxWidth = 612.0f;

    float imgRatio = 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);
    } 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);

    // Fill with white
    // canvas.drawColor(Color.WHITE);
    Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);

    float tempLeft = middleX - bmp.getWidth() / 2;
    float tempRight = middleY - bmp.getHeight() / 2;
    canvas.drawBitmap(bmp, tempLeft, tempRight, mPaint);

    // 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);
        Log.d("EXIF", "Exif: " + orientation);
        Matrix matrix = new Matrix();
        if (orientation == 6) {
            matrix.postRotate(90);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 3) {
            matrix.postRotate(180);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 8) {
            matrix.postRotate(270);
            Log.d("EXIF", "Exif: " + orientation);
        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
    } catch (IOException e) {
        e.printStackTrace();
    }
    FileOutputStream out = null;
    compressImageFilePath = getFilename(imageId, optionId);
    try {
        out = new FileOutputStream(compressImageFilePath);
        // write the compressed bitmap at the destination specified by filename.
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 45, out);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    Log.d("compressedFileName", compressImageFilePath);

    return compressImageFilePath;
}

public static String getFilename(int imageId, int optionId) {
    ContextWrapper cw = new ContextWrapper(context);
    // path to /data/data/yourapp/app_data/imageDir
    File directory = cw.getDir("MyPictures", Context.MODE_PRIVATE);
    File file = new File(directory, imageId + "_opt" + optionId + ".jpg");
    String uriSting = (file.getAbsolutePath());
    return uriSting;
}

public static File getFile(int imageId, int optionId) {
    ContextWrapper cw = new ContextWrapper(context);
    // path to /data/data/yourapp/app_data/imageDir
    File directory = cw.getDir("MyPicture", Context.MODE_PRIVATE);
    File file = new File(directory, imageId + "_opt" + optionId + ".jpg");
    // String uriSting = (file.getAbsolutePath());
    return file;
}

@SuppressLint("NewApi")
public static int sizeOf(Bitmap data) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
        return data.getRowBytes() * data.getHeight();
    } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return data.getByteCount();
    } else {
        return data.getAllocationByteCount();
    }
}

private static String getRealPathFromURI(Context context, String contentURI) {
    Uri contentUri = Uri.parse(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);
        return cursor.getString(index);
    }
}

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;
    Log.d("totalPixels :", "" + totalPixels);
    final float totalReqPixelsCap = reqWidth * reqHeight * 2;
    Log.d("totalReqPixelsCap :", "" + totalReqPixelsCap);
    while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
        inSampleSize++;
    }

    return inSampleSize;

}}

1 个解决方案

#1


0  

Try out this class I am using. To comress use this line,

试试这个我正在使用的课程。要使用这条线,

imageView.setImageBitmap(BitmapUtility.decodeSampledBitmapFromResource(picturePath,400,400));

and the class BitmapUtility class,

和BitmapUtility类,

public class BitmapUtility {

public static Bitmap decodeSampledBitmapFromResource(String path,int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path,options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(path, options);
}
private 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;
}
}

#1


0  

Try out this class I am using. To comress use this line,

试试这个我正在使用的课程。要使用这条线,

imageView.setImageBitmap(BitmapUtility.decodeSampledBitmapFromResource(picturePath,400,400));

and the class BitmapUtility class,

和BitmapUtility类,

public class BitmapUtility {

public static Bitmap decodeSampledBitmapFromResource(String path,int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path,options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(path, options);
}
private 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;
}
}