图片旋转详谈(Java)

最近做的项目涉及到通过后台对图片进行旋转处理的需求。经过多方查阅资料及测试,最终选定了方案。现对实验中用到实现方式做如下总结:

一、直接旋转

直接对图片进行旋转处理,但这里需注意到图片宽高像素值必须为基数,如果为偶数,图片旋转后会出现一个像素的黑边。具体实现如下:

public Map<String, Object> rotateImgGraphics2D(HttpServletRequest request) {
		String src = request.getParameter("src");
		String angleStr = request.getParameter("angle");
		Map<String, Object> ret = new HashMap<String, Object>();
		if (Tools.isEmpty(src) || Tools.isEmpty(angleStr)) {
			ret.put("success", false);
			ret.put("msg", "参数有误");
			return ret;
		}
		int angle = Integer.parseInt(angleStr);
		BufferedImage bufferedimage = null;
		File file = null;
		try {// 从服务器读取照片
			int h = 0;
			int w = 0;
			String userDir = System.getProperty("user.dir");
			file = new File(userDir + src);
			bufferedimage = ImageIO.read(file);
			if (angle != 0) {
				if (angle / 90 % 2 == 1) {// 旋转角度为90或270...时,图像的长宽对换
					h = bufferedimage.getWidth();
					w = bufferedimage.getHeight();
				} else {
					w = bufferedimage.getWidth();
					h = bufferedimage.getHeight();
				}
			} else {// 旋转角度为0时,返回
				ret.put("success", true);
				ret.put("msg", "旋转角度为0");
				return ret;
			}
			// 将像素值转换为颜色分量和 alpha 分量的方法,返回此 ColorModel 的转换类型。
			int type = bufferedimage.getColorModel().getTransparency();
			BufferedImage img;
			img = new BufferedImage(w, h, type);
			// 创建一个 Graphics2D,可以将它绘制到此 BufferedImage 中。
			Graphics2D graphics2d = img.createGraphics();
			// 将当前 Graphics2D Transform 与平移转换连接。后续呈现相对于前一位置平移指定的距离。
			graphics2d.translate((w - bufferedimage.getWidth()) / 2, (h - bufferedimage.getHeight()) / 2);
			graphics2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, // 插值提示键
					RenderingHints.VALUE_INTERPOLATION_BILINEAR);// 插值提示值——图像中最接近整数坐标样本的 4 种颜色样本被线性地插入,以生成一个颜色样本
			graphics2d.rotate(Math.toRadians(angle), bufferedimage.getWidth() / 2, bufferedimage.getHeight() / 2);// 注意此处是原图片的宽和长,不是计算后的,用计算后的宽和长,保存后又黑边
			graphics2d.drawImage(bufferedimage, null, null);

			// 把旋转后图片存入服务器
			ImageIO.write(img, src.substring(src.lastIndexOf(".") + 1), file);
			graphics2d.dispose();
			ret.put("success", true);
			ret.put("msg", "旋转成功");
		} catch (IOException e) {
			e.printStackTrace();
			ret.put("success", false);
			ret.put("msg", "旋转失败");
		}
		return ret;
	}

二、通过Thumbnails进行图像旋转

Thumbnails工具类能帮助我们对图片进行很好的处理,Thumbnails对图片的操作进行了很好的封装,往往很复杂的步骤能用一行代码就完成。 而且支持多种语言开发。但是不知道为什么旋转后图片质量降低了,而且有些失真。具体实现如下:

public Map<String, Object> rotateImgThumbnails(HttpServletRequest request) {
		String src = request.getParameter("src");
		String angleStr = request.getParameter("angle");
		Map<String, Object> ret = new HashMap<String, Object>();
		if (Tools.isEmpty(src) || Tools.isEmpty(angleStr)) {
			ret.put("success", false);
			ret.put("msg", "参数有误");
			return ret;
		}
		int angle = Integer.parseInt(angleStr);
		if (angle == 0) {
			ret.put("success", true);
			ret.put("msg", "旋转角度为0");
			return ret;
		}
		BufferedImage bufferedimage = null;
		File file = null;
		try {
			// 从服务器中读取图片,用new URL(),读取本地磁盘中照片用new File()
			String userDir = System.getProperty("user.dir");
			file = new File(userDir + src);
			bufferedimage = ImageIO.read(file);
			int w = bufferedimage.getWidth();
			int h = bufferedimage.getHeight();
			int max = w > h ? w : h;
			Thumbnails.of(bufferedimage).size(max, max).rotate(angle)
					.outputFormat(src.substring(src.lastIndexOf(".") + 1)).toFile(userDir + src);
			ret.put("success", true);
			ret.put("msg", "旋转成功");
		} catch (IOException e) {
			e.printStackTrace();
			ret.put("success", false);
			ret.put("msg", "旋转失败");
		}
		return ret;
	}

 三、自己封装

自己封装的方法,运用旋转矩阵算法实现图像旋转。通过这种方式,不仅保证的图片的高保真,而且不用考虑因图片宽高像素值奇偶问题导致的黑边现象。部分实现如下:

public class RotateImgUtil {
	/***
	 * 顺时针旋转90度(通过交换图像的整数像素RGB 值)
	 * @param bi
	 * @return
	 */
	public static BufferedImage rotateClockwise90(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(height, width, bi.getType());
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				if(width>=height) {
					bufferedImage.setRGB(j, i, bi.getRGB(i, j));
				}else {
					bufferedImage.setRGB(height - 1 - j, width - 1 - i, bi.getRGB(i, j));
				}
			}
		}
		if(width>=height) {
			bufferedImage=rotateHorizon(bufferedImage);
		}else {
			bufferedImage=rotateVertical(bufferedImage);
		}
		return bufferedImage;
	}

	/***
	 * 逆时针旋转90度/顺时针针旋转270度(通过交换图像的整数像素RGB 值)
	 * @param bi
	 * @return
	 */
	public static BufferedImage rotateCounterclockwise90(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(height, width, bi.getType());
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				if(width>height) {
					bufferedImage.setRGB(height - 1 - j, width - 1 - i, bi.getRGB(i, j));
				}else {
					bufferedImage.setRGB(j, i, bi.getRGB(i, j));
				}
			}
		}	
		if(width>height) {
			bufferedImage=rotateHorizon(bufferedImage);
		}else {
			bufferedImage=rotateVertical(bufferedImage);
		}
		return bufferedImage;
	}

	/***
	 * 旋转180度(通过交换图像的整数像素RGB 值)
	 * @param bi
	 * @return
	 */
	public static BufferedImage rotate180(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(width, height, bi.getType());
		for (int i = 0; i < width; i++)
			for (int j = 0; j < height; j++)
				bufferedImage.setRGB(width - i - 1, height - j - 1, bi.getRGB(i, j));
		return bufferedImage;
	}

	/***
	 * 水平翻转
	 * @param bi
	 * @return
	 */
	public static BufferedImage rotateHorizon(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(width, height, bi.getType());
		for (int i = 0; i < width; i++)
			for (int j = 0; j < height; j++)
				bufferedImage.setRGB(width - i - 1, j, bi.getRGB(i, j));
		return bufferedImage;
	}

	/***
	 * 垂直翻转
	 * @param bi
	 * @return
	 */
	public static BufferedImage rotateVertical(BufferedImage bi) {
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(width, height, bi.getType());
		for (int i = 0; i < width; i++)
			for (int j = 0; j < height; j++)
				bufferedImage.setRGB(i, height - 1 - j, bi.getRGB(i, j));
		return bufferedImage;
	}
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值