做了五、六年电子商务开发,电商的商品图片非常的庞大,比如商品的预览图片,最少起码有三种格式,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类似,只是先后而已,这里是访问的时候去根据参数生成,不过这种方式消耗性能比较大,储存空间稍微小。