首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将JPG图像压缩到以KB为单位的给定大小?

将JPG图像压缩到以KB为单位的给定大小?
EN

Stack Overflow用户
提问于 2017-12-08 15:25:06
回答 6查看 2.7K关注 0票数 0

我在输入中有一个由照相机返回的字节数组。

我需要缩小我的图像,使其大小等于500 my。我正在尝试使用位图来实现这一点,但我找不到如何获得适当的compression值。

代码语言:javascript
运行
复制
public static byte[] compressCapture(byte[] capture) {

    // How to get the right compression value ?
    int compression = 50;

    Bitmap bitmap  = BitmapFactory.decodeByteArray(capture, 0, capture.length);
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, compression, outputStream);
    return outputStream.toByteArray();
}

问题是压缩与图像大小不成比例,这意味着compression = 50不会将图像大小除以2。

有没有一种方法可以在输出中获得不依赖于焦点或智能手机模型的固定图像大小?

编辑:

我不想使用文件(我使用机密数据)。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2017-12-12 13:34:26

更新01/16/2018

最简单的方法是使用BitmapFactory.Options.inSampleSize解码字节数组并同时压缩它。这是医生

代码语言:javascript
运行
复制
 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inSampleSize = 4; // If you want an image four times smaller than the original
 Bitmap decoded = BitmapFactory.decodeByteArray(data, 0, data.length, options);

旧答案,请不要使用这个

由于显然没有办法一次做到这一点,所以我实现了一个迭代过程,以达到给定的KB大小。

我从一个等于80的压缩系数开始,如果这还不够的话,我会降低这个系数,然后再试一次,直到我得到一个低于阈值的大小。

代码语言:javascript
运行
复制
static COMPRESSION_PERCENTAGE_START = 80;
static IMAGE_COMPRESSION_EXPECTED_MAX_ITERATIONS = 3;
static IMAGE_COMPRESSION_STEP_PERCENT = 5;

// For logging
static IMAGE_COMPRESSION_EXPECTED_MAX_ITERATIONS = 5;

static byte[] compressCapture(byte[] capture, int maxSizeKB) {
    long maxSizeByte = ((long) maxSizeKB) * 1_000;

    if (capture.length <= maxSizeByte) return capture;

    byte[] compressed = capture;

    // Chosen arbitrarily so that we can compress multiple times to reach the expected size.
    int compression = COMPRESSION_PERCENTAGE_START;

    Bitmap bitmap = BitmapFactory.decodeByteArray(capture, 0, capture.length);
    ByteArrayOutputStream outputStream;
    int iterations = 0;
    while (compressed.length > maxSizeByte) {
        // Just a counter
        iterations++;

        compression -= IMAGE_COMPRESSION_STEP_PERCENT;

        outputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, compression, outputStream);
        compressed = outputStream.toByteArray();
    }

    if (iterations > IMAGE_COMPRESSION_EXPECTED_MAX_ITERATIONS) {
        Timber.w("Compression process has iterated more than expected, with " + iterations + " iterations.");
    }

    return compressed;
}

以下是1_871_058字节的原始大小的输出大小

  • 迭代#1 (压缩等于80):528_593字节
  • 迭代#2 (压缩等于75):456_591字节

它为我做的工作,但请小心,如果你使用,它当然需要一些微调,我刚刚测试了它的一个给定的智能手机型号。

票数 2
EN

Stack Overflow用户

发布于 2017-12-08 17:24:47

您面临的问题是压缩取决于图像的性质。我的猜测是,有学术研究,观察图像和选择参数,以达到一个给定的大小。

在JPEG中,有几个要缩小大小的设置:

  1. 包括或排除COM和APPn标记。
  2. 无论是优化还是现成的哈夫曼表都被使用。
  3. 量化表的选择。
  4. Cb和Cr组分的再采样。
  5. 渐进式或顺序式编码(如果是前者,则有大量扫描设置可供您使用)。

不过,这主要是试错。

票数 1
EN

Stack Overflow用户

发布于 2017-12-08 15:54:42

很难压缩到给定的大小,我建议使用ImageMagick,并调整选项,直到您达到一个您觉得舒服使用的大小。

我总是使用ImageMagick。请考虑以下命令

代码语言:javascript
运行
复制
convert -strip -interlace Plane -gaussian-blur 0.05 -quality 85% source.jpg result.jpg

该命令使用以下选项:

  • 质量在85
  • 累进(共测压缩)
  • 一个非常微小的高斯模糊来优化尺寸(半径的0.05或0.5 )取决于图片的质量和大小,这明显地优化了jpeg的大小。
  • 去掉任何注释或exif标签

来源

尝试调整质量参数。如果您减少了它,它会增加压缩和减少文件大小。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47717299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档