简体   繁体   English

在不损失图像质量的情况下缩放图像无效

[英]Scale image without losing image quality did not work

Does anyone know how to scale the bitmap image without losing the image quality ? 有谁知道如何在不损失图像质量的情况下缩放位图图像? Currently I facing this problem , where the size of selected image maybe too big caused the app return to another activity. 目前,我遇到了这个问题 ,所选图片的大小可能太大,导致应用返回到其他活动。

So now I tried using this method to scale the selected image without losing its quality. 因此,现在我尝试使用此方法缩放所选图像,而不会损失其质量。 I get the code from here . 我从这里得到代码。

 protected void onActivityResult(int requestCode, int resultCode,
                                    Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case RESULT_LOAD_IMAGE:
                if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK & null != data) {
                    Uri selectedImage = data.getData();
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};
                    Cursor cursor = getContentResolver()
                            .query(selectedImage, filePathColumn, null, null,
                                    null);
                    cursor.moveToFirst();
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                    String picturePath = cursor.getString(columnIndex);
                    cursor.close();
                    Bitmap a = (BitmapFactory.decodeFile(picturePath));
                    photo = scaleBitmap(a, 200, 200);
                    imageView.setImageBitmap(photo);
                }
                break;
}

  public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
        Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

        float scaleX = newWidth / (float) bitmap.getWidth();
        float scaleY = newHeight / (float) bitmap.getHeight();
        float pivotX = 0;
        float pivotY = 0;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);

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

        return scaledBitmap;
    }

The answer seems helpful for most of the people, but why it doesn't work for me ? 答案对于大多数人来说似乎很有帮助,但是为什么它对我不起作用? Have I missed anything? 我错过了什么吗?

original image 原始图像

selected image display on imageView 选定的图像显示在imageView上

Please try this 请尝试这个

public Bitmap scaleBitmap(Bitmap bitmap,int newWidth,int newHeight) {    
    Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Config.ARGB_8888);

    float ratioX = newWidth / (float) bitmap.getWidth();
    float ratioY = newHeight / (float) bitmap.getHeight();
    float middleX = newWidth / 2.0f;
    float middleY = newHeight / 2.0f;

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

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

    return scaledBitmap;

    }

Try this for scaling bitmap 试试这个缩放位图

public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
    float scaleX = ((float)newWidth) /  bitmap.getWidth();
    float scaleY = ((float)newHeight) / bitmap.getHeight(); 
    Matrix scaleMatrix = new Matrix();
    scaleMatrix.postScale(scaleX, scaleY);
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight() , scaleMatrix, true);
    return scaledBitmap;
}
Use this it will definitely help you to reduce the size without loosing quality.
public Bitmap compressImage(String imageUri) {

        String filePath = imageUri;
        // String filePath = getRealPathFromURI(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);

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

        // max Height and width values of the compressed image is taken as
        // 816x612

        /*
         * float maxHeight = 816.0f; float maxWidth = 612.0f;
         */
        float maxHeight = 1080.0f;
        float maxWidth = 800.0f;

        float imgRatio = actualWidth / (float) actualHeight;
        float maxRatio = maxWidth / (float) 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);
        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(filePath);

            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
            displayLogs("EXIF", "Exif: " + orientation);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
                displayLogs("EXIF", "Exif: " + orientation);
            } else if (orientation == 3) {
                matrix.postRotate(180);
                displayLogs("EXIF", "Exif: " + orientation);
            } else if (orientation == 8) {
                matrix.postRotate(270);
                displayLogs("EXIF", "Exif: " + orientation);
            }

            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }

        FileOutputStream out = null;
        String filename = getFilename(filePath);
        // File image = new File(getFilename(), System.currentTimeMillis() +
        // ".jpg");
        try {
            out = new FileOutputStream(filename);

            // write the compressed bitmap at the destination specified by
            // filename.
            boolean didWrite = scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

            out.close();

            System.out.println(didWrite);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }

        return scaledBitmap;

    }

    private String getRealPathFromURI(String contentURI) {
        Uri contentUri = Uri.parse(contentURI);
        Cursor cursor = 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 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;
    }

    public String getFilename(String originalname) {

        ImageCache imageCache = new ImageCache(this);
        File file = new File("Your folder path");

        // return file;
        String uriSting = (file.getAbsolutePath() + "/" + "F_" + System.currentTimeMillis() + ".png");
        return uriSting;

    }

Your problem is that you are not keeping the aspect ratio of the original image. 您的问题是您没有保持原始图像的宽高比。 in your code if you need the width to be 200, then the height should be calculated like this: 在您的代码中,如果您需要宽度为200,则高度的计算应如下所示:

newHeight = ((float) originalHeight/(float) originalWidth) * (float) newWidth;

So in your case: 因此,在您的情况下:

float newHeight = ((float) a.getHeight()/(float) a.getWidth()) * (float) 200;

And then call your scaling function with width:200 and height calculated from original value. 然后使用从原始值计算出的width:200和height调用缩放函数。

After that if the quality is still low, then experiment with increasing the width and stop when you get the needed quality. 之后,如果质量仍然很低,请尝试增加宽度并在获得所需质量时停止。

While you have too much large image at that time you must Required to manage Bitmap cache policy.Bitmap cache management is too much Complex.So in Android we have one superb library Picasso .this library is provide inbuilt cache management. 虽然那时您的映像太大,但是必须管理位图缓​​存策略。位图缓存管理太复杂。因此,在Android中,我们有一个一流的Picasso库。此库提供内置的缓存管理。 this will be manage your bitmap in background and it's also provide image cache feature.once your image is load and again you load this same Image this will be get in cache.it's inbuilt functionality no need to change in code. 这将在后台管理您的位图,并且还提供图像缓存功能。一旦加载了图像,然后再次加载了相同的图像,它将进入缓存。它的内置功能无需更改代码。

I hope you are clear with my solution. 希望您对我的解决方案有所了解。 Best of Luck 祝你好运

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM