做了五、六年电子商务开发,电商的商品图片非常的庞大,比如商品的预览图片,最少起码有三种格式,40x40,160x160,250x250,所以很多时候需要对商品图片进行处理,总结下电子商务的图片的储存。
项目需要安装 imagemagick,地址:http://www.imagemagick.org/ 有着非常强大的图片处理,动态生成图片,压缩图片,等比压缩
JAVA开发需要 用maven依赖
<dependency>
<groupId>org.im4java</groupId>
<artifactId>im4java</artifactId>
<version>1.2.0</version>
</dependency>
1、如果有足够的服务器空间,可以使用预生成需要的图片格式,这种方案就是需要比较大的硬盘存储,一般实现可以用java+imagemagic。
创建一个接口类
/** * <p> * 对上传的图片进行处理,业务规则是:<br> * 1、对上传的图片进行正方形处理,也就是说所有的图片上传后以正方形存储;<Br> * 2、正方形处理的规则就是以800的长宽为标准,如果没有到达800的图片则按照最大的一边做为标准<br> * 如果最大边到达或者超过800那么就按800标准 * * </p> * * @param srcImage */ void handleImage(String srcImage); /** * <p> * 主要是打水印,业务规则 <code>handleImage(..)</code>一样,只不过该方法默认打水印 * </p> * * @param srcImage * @param maxWidth * @param watermark */ void watermarkImage(String srcImage, boolean watermark); /** * <p> * 对图片进行压缩,主要使用场景是上传商品详细页面 * </p> * * @param srcImage */ void compressionImage(String srcImage, int width);
实现类:
private static final Logger LOG = LoggerFactory.getLogger(DefaultImageAO.class); @Override public void handleImage(String srcImage) { this.watermarkImage(srcImage, false); } @Override public void watermarkImage(String srcImage, boolean watermark) { this.orgImage(srcImage, watermark); this.adaptImage(srcImage, IConstant.VIEW_SIZE); this.adaptImage(srcImage, IConstant.LIST_SIZE); this.adaptImage(srcImage, IConstant.SMALL_SIZE); this.adaptImage(srcImage, IConstant.ROL_SIZE); } @Override public void compressionImage(String srcImage, int width) { IMOperation op = new IMOperation(); op.addRawArgs("-quality", IConstant.COMPRE); if (width > IConstant.MAX_DETAIL) { op.addImage("-sample", getScaling(width)); } op.addImage(srcImage); op.addImage(srcImage); ConvertCmd convert = new ConvertCmd(); try { convert.run(op); } catch (Exception e) { LOG.error(e.getMessage(), e); } } /** * 按照边框的尺寸生成预览图片 * * @param srcImage * @param adaptSize */ private void adaptImage(String srcImage, int adaptSize) { IMOperation op = new IMOperation(); op.background("white"); op.addRawArgs("-thumbnail", this.getImageAreaSize(adaptSize)); op.addRawArgs("-gravity", "center"); op.addRawArgs("-extent", this.getImageAreaSize(adaptSize)); op.addRawArgs("-quality", IConstant.ADAPT); op.addImage(srcImage); op.addImage(this.getAdaptImageName(srcImage, adaptSize)); ConvertCmd convert = new ConvertCmd(); try { convert.run(op); } catch (Exception e) { LOG.error(e.getMessage(), e); } } /** * <p> * 对很大的图片进行压缩, * </p> * * @param width * @param height * @return */ private String getScaling(int width) { double percent = (IConstant.MAX_DETAIL / width) * 100; return percent + "%x" + percent + "%"; } /** * 生成默认的图片格式 * * @param srcImage * @param watermark */ private void orgImage(String srcImage, boolean watermark) { IMOperation op = new IMOperation(); if (watermark) { op.font("宋体").gravity("southeast").pointsize(24).fill("#BCBFC8").draw("text 5,5 xx.com"); } op.background("white"); op.addRawArgs("-thumbnail", this.getImageAreaSize(srcImage)); op.addRawArgs("-gravity", "center"); op.addRawArgs("-extent", this.getImageAreaSize(srcImage)); op.addRawArgs("-quality", IConstant.QUALITY_ORG); op.addImage(srcImage); op.addImage(srcImage); ConvertCmd convert = new ConvertCmd(); try { convert.run(op); } catch (Exception e) { LOG.error(e.getMessage(), e); } } /** * <p> * 获取最大的图片边框,业务规则是 :<Br> * 1、如果长比宽大,并少于预设边框800的时候则选择长为压缩的边框做标准;如果大于预设边框的时候则选择800做为标准<br> * 2、如果宽比长大,并少于预设边框800的时候则选择宽为压缩的边框做标准;如果大于预设边框的时候则选择800做为标准<br> * </p> * * @param srcImage * @return * @throws IOException */ private String getImageAreaSize(String srcImage) { try { BufferedImage bufferedImage = ImageIO.read(new File(srcImage)); int height = bufferedImage.getHeight(); int width = bufferedImage.getWidth(); int tempMaxSelectSize = (height > width ? height : width); int tempMaxSize = (tempMaxSelectSize > IConstant.MAX_SIZE ? IConstant.MAX_SIZE : tempMaxSelectSize); return tempMaxSize + "x" + tempMaxSize; } catch (IOException e) { LOG.error(e.getMessage(), e); } return "1x1"; } /** * 获取最后的自适应图片地址,不建议这么做,毕竟这样会影响到.gif的图片。 * * @param srcImage * @param adaptSize * @return */ private String getAdaptImageName(String srcImage, int adaptSize) { return new StringBuffer(srcImage).append("_").append(adaptSize).append("x").append(adaptSize).append(".jpg") .toString(); } /** * 获取自适应图片的规格 * * @param adaptSize * @return */ private String getImageAreaSize(int adaptSize) { return adaptSize + "x" + adaptSize; }
2、就是访问生成的方式,实现的方式跟1类似,只是先后而已,这里是访问的时候去根据参数生成,不过这种方式消耗性能比较大,储存空间稍微小。