首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java收缩图像文件到目标文件大小

Java收缩图像文件到目标文件大小
EN

Stack Overflow用户
提问于 2019-03-24 19:24:10
回答 2查看 1.1K关注 0票数 0

我正在开发一个android应用程序,用户会用相机拍一张照片。生成的照片大小可以从<1MB到超过3-4 MB不等。我需要确保照片小于1MB,以存储在服务器上。因此,对于大于1MB的图像,我希望将其缩小到小于1MB,但尽可能保持质量。我不担心质量的下降。

我怎样才能做到这一点?据我所知,大多数解决方案都涉及将图像缩小到目标尺寸(宽度X、高度),但在我的情况下,我只关心缩小图像的大小。

而且非常重要的是,结果小于1MB,如果存在任何错误空间,则必须在较低的文件大小上,如果这是合理的话。

是否有一种方法可以计算出达到目标文件大小的宽度和高度?或者更好的是,在不指定宽度和高度的情况下缩小它?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-24 19:34:29

我怎样才能做到这一点?

三大选择是:

  • 降低分辨率(宽度和高度)
  • 降低JPEG质量(将位图压缩为JPEG时使用的0-100值)
  • 缩小比特深度(例如,从ARGB888到RGB565),尽管这主要是PNG的一部分,我怀疑这会破坏您的照片质量。

是否有一种方法可以计算出达到目标文件大小的宽度和高度?

不,因为这在很大程度上取决于图像的内容和它使用JPEG压缩算法的压缩效果。

或者更好的是,在不指定宽度和高度的情况下缩小它?

对于从3-4 MB到不足1MB的数据,几乎可以保证您将需要降低分辨率。

然而,由于只有您知道您认为什么是可接受的输出,您需要自己进行试验,以确定如何最好地应用这三个选项。

票数 1
EN

Stack Overflow用户

发布于 2019-03-24 21:07:35

大约15年前,我使用了Swing和javax.image,唯一可行的解决方案是将不同的质量级别应用于JPG编码器,以找到图像仍然小于所要求的最大大小的最佳质量设置。代码是这样的(这里的代码是从实际代码中合成的,从未在这个版本中测试过):

代码语言:javascript
复制
/** Create JPG version of some image with given JPG quality setting (0..1), helper method */  
private byte[] createResultBytes(BufferedImage losslessimage,float lossyquality) {
  Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("JPG");
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  if (iter.hasNext()) {
    ImageWriter writer = iter.next();
    ImageWriteParam iwp = writer.getDefaultWriteParam();
    iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    iwp.setCompressionQuality(lossyquality);

    MemoryCacheImageOutputStream mcios = new MemoryCacheImageOutputStream(baos);
    writer.setOutput(mcios);

    // workaround for alpha-channel problems with lossy images: Seems to be non-functional for some pictures, anyway.
    BufferedImage img2=new BufferedImage(losslessimage.getWidth(),losslessimage.getHeight(),BufferedImage.TYPE_INT_RGB);
    Graphics g=img2.getGraphics();
    g.drawImage(new ImageIcon(losslessimage).getImage(),0,0,null);
    g.dispose();
    IIOImage iioimg = new IIOImage(img2, null, null);
    try {
      writer.write(null, iioimg, iwp);
      mcios.close();
    }
    catch (IOException ioe) {}
  }
  return baos.toByteArray();
}

/** Create JPG version of some image with best JPG quality where the file size is still not larger than maxsize. */
public byte[] getLossyImage(BufferedImage losslessimage,int maxsize,float maxquality) {
  byte[] resultbytes=createResultBytes(losslessimage,maxquality);
  if (resultbytes.length>size) {
    int minsize=(int)(size*.9f);
    float newq=maxquality/2f;
    resultbytes=createResultBytes(losslessimage,newq);
    float qdiff=newq/2f;
    while ((resultbytes.length<minsize || resultbytes.length>size) &&  diff>.02f) {
      newq+=(resultbytes.length<minsize?qdiff:-qdiff);
      resultbytes=createResultBytes(losslessimage,newq);
      qdiff=qdiff/2f;
    }
  }
  return resultbytes;
}

注意,我只通过JPG质量设置来更改文件大小,而不是通过自动更改图像的大小。如果您想要这样做,您必须首先应用这些大小更改。

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

https://stackoverflow.com/questions/55327626

复制
相关文章

相似问题

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