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