简体   繁体   English

Android 从相机意图压缩图像,体积小,质量好

[英]Android compress image with small size and good quality from camera intent

In my app user can take picture from camera intent, then I save this image as full size image not thumbnail.在我的应用程序中,用户可以从相机意图中拍照,然后我将此图像保存为全尺寸图像而不是缩略图。 Then what I want to do is use this saved image to compress it and send it over to server.然后我想要做的是使用这个保存的图像来压缩它并将它发送到服务器。

The image size from camera intent is around 7-8 MB and resolution of 5664x4248.来自相机意图的图像大小约为 7-8 MB,分辨率为 5664x4248。

The requirements is to achieve is image of same size and quality of whatsapp which is 40-80KB要求是要实现与whatsapp相同大小和质量的图像,即40-80KB

I tried different solution but I couldn't achieve the same good quality and size.我尝试了不同的解决方案,但无法达到相同的质量和尺寸。

For this I used id.zelory:compressor:2.1.1 library为此,我使用id.zelory:compressor:2.1.1

Any Idea?任何想法?

Here I call this method after saving the image to resize it这里我在保存图像后调用这个方法来调整它的大小

private File customCompressImage (File imgFile) {
    String destinationDirectoryPath=  Environment.getExternalStorageDirectory().getPath() + "/Pictures/";
    try {
        return new CustomCompressor(context)
                 .setMaxWidth(612)
                 .setMaxHeight(816)
                 .setQuality(80)
                 .setCompressFormat(Bitmap.CompressFormat.JPEG)
                 .setDestinationDirectoryPath(destinationDirectoryPath)
                 .compressToFile(imgFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

CompressImage压缩图像

static File compressImage(File imageFile, int reqWidth, int reqHeight, Bitmap.CompressFormat compressFormat, int quality, String destinationPath) throws IOException {
    FileOutputStream fileOutputStream = null;
    File file = new File(destinationPath).getParentFile();
    if (!file.exists()) {
        file.mkdirs();
    }
    try {
        fileOutputStream = new FileOutputStream(destinationPath);
        // write the compressed bitmap at the destination specified by destinationPath.
        decodeSampledBitmapFromFile(imageFile, reqWidth, reqHeight).compress(compressFormat, quality, fileOutputStream);
    } finally {
        if (fileOutputStream != null) {
            fileOutputStream.flush();
            fileOutputStream.close();
        }
    }

    return new File(destinationPath);
}


static Bitmap decodeSampledBitmapFromFile(File imageFile, int reqWidth, int reqHeight) throws IOException {
    // First decode with inJustDecodeBounds=true to check dimensions
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    Bitmap scaledBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);

    //check the rotation of the image and display it properly
    ExifInterface exif;
    exif = new ExifInterface(imageFile.getAbsolutePath());
    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);
    return scaledBitmap;
}


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

I tried passing different max width and height and quality and I never achived both small size and good quality我尝试通过不同的最大宽度和高度和质量,但我从未同时实现小尺寸和高质量

You can try this piece of code.你可以试试这段代码。

public static Bitmap getCompressed( Bitmap imageBitmap) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    return imageBitmap;
}

// 100 is quality, change it according to your need // 100是质量,根据需要更改

@End User shouldn't it be like this instead (that's at least what I get from reading the documentation): @End User 不应该是这样的(这至少是我从阅读文档中得到的):

public static Bitmap getCompressed(Bitmap imageBitmap) {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    if (!imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out))
        throw new IllegalStateException("Unable to compress image");
    ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
    return BitmapFactory.decodeStream(in);
}

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

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