文档章节

在其他大牛那看到的java手机图片上传旋转问题的解决方法

M
 Mr_Han1024
发布于 2016/06/27 11:41
字数 675
阅读 47
收藏 2
// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
//Base64所用包:org.apache.commons.codec.binary.Base64
public static String encodeImgageToBase64(File imageFile) {
		 byte[] data = null;
       // 读取图片字节数组
       try {
           InputStream in = new FileInputStream(imageFile);
           data = new byte[in.available()];
           in.read(data);
           in.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
       // 对字节数组Base64编码
       return Base64.encodeBase64String(data);// 返回Base64编码过的字节数组字符串
}

判断是否旋转:

/**
	 * 
	 * @功能:解析base64图片编码,判断是否有旋转
	 * @param imgStr base64图片编码
	 * @param format 图片格式
	 * @param fileName 图片名称
	 */
	public static Map<String, Object> stringToImage(String imgStr, String format, String fileName){
		//解码base64图片
		byte[] bts = Base64.decodeBase64(imgStr);
		InputStream is = new ByteArrayInputStream(bts);
		try {
			//获取照片的Exif信息
			Metadata metadata = JpegMetadataReader.readMetadata(is); 
			Directory exif = metadata.getFirstDirectoryOfType(ExifDirectoryBase.class);
			/*
           //输出从图片获取到的相关信息
           Iterable<Directory> ites =  metadata.getDirectories();
			for (Directory directory : ites) {
				Iterator<Tag> tags = directory.getTags().iterator();
				while(tags.hasNext()){
					Tag tag = (Tag) tags.next();
					System.out.println(tag);
				}
			}
			*/
			//获取照片拍摄方向
			String type = exif.getString(ExifDirectoryBase.TAG_ORIENTATION);
            //图片正常情况下,type=1,测试正常图片旋转,请修改case 条件为 1
			if(StringUtil.notBlank(type)){//判断拍摄方向是否为空
				switch (Integer.parseInt(type)) {
				case 3://要进行180度旋转
					byte[] bytes = rotateImg(bts , 180.0 , format);
					return uploadToAliYunOSS(fileName, bytes);
				case 6://要进行90度旋转
					byte[] bytes1 = rotateImg(bts , 90.0 , format);
					return uploadToAliYunOSS(fileName, bytes1);
				case 8://要进行-90度旋转
					byte[] bytes2 = rotateImg(bts , -90.0 , format);
					return uploadToAliYunOSS(fileName, bytes2);
				default :	
					return uploadToAliYunOSSBybase64(fileName, bts);
				}
			}else{
				return uploadToAliYunOSSBybase64(fileName, bts);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return Tool.getError(1, "请求错误!", "");
	}

矫正图片旋转

/**
	 * 
	 * @功能:矫正图片旋转,返回byte[]
	 * @param input
	 * @param angle
	 * @param format
	 * @param fileName
	 * @throws IOException void
	 */
	public static byte[] rotateImg(byte[] bytes , double angle , String format) throws IOException{
		InputStream input = new ByteArrayInputStream(bytes);
		BufferedImage old_img = ImageIO.read(input);  
		int width = old_img.getWidth();
		int height = old_img.getHeight();
		double[][] newPositions = new double[4][];
		newPositions[0] = calculatePosition(0, 0, angle);
		newPositions[1] = calculatePosition(width, 0, angle);
		newPositions[2] = calculatePosition(0, height, angle);
		newPositions[3] = calculatePosition(width, height, angle);
		double minX = Math.min(
				Math.min(newPositions[0][0], newPositions[1][0]),
				Math.min(newPositions[2][0], newPositions[3][0])
		);
		double maxX = Math.max(
				Math.max(newPositions[0][0], newPositions[1][0]),
				Math.max(newPositions[2][0], newPositions[3][0])
		);
		double minY = Math.min(
				Math.min(newPositions[0][1], newPositions[1][1]),
				Math.min(newPositions[2][1], newPositions[3][1])
		);
		double maxY = Math.max(
				Math.max(newPositions[0][1], newPositions[1][1]),
				Math.max(newPositions[2][1], newPositions[3][1])
		);
		int newWidth = (int)Math.round(maxX - minX);
		int newHeight = (int)Math.round(maxY - minY);
		BufferedImage new_img = new BufferedImageBuilder(newWidth, newHeight , BufferedImage.TYPE_INT_BGR).build();  
        
		Graphics2D g = new_img.createGraphics();
		
		g.setRenderingHint(
				RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR
		);
		g.setRenderingHint(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON
		);
		double w = newWidth / 2.0;
		double h = newHeight / 2.0;
		
		g.rotate(Math.toRadians(angle), w, h);
		int centerX = (int)Math.round((newWidth - width) / 2.0);
		int centerY = (int)Math.round((newHeight - height) / 2.0);
		
		g.drawImage(old_img, centerX, centerY, null);
		g.dispose();
		//新建流。
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		//利用ImageIO类的write方法,将BufferedImage以png图片的数据模式写入流。
		ImageIO.write(new_img, format, baos);
		return baos.toByteArray();
	}

 rotateImg() 中的calculatePosition()方法

private static double[] calculatePosition(double x, double y, double angle){
		angle = Math.toRadians(angle);
		double nx = (Math.cos(angle) * x) - (Math.sin(angle) * y);
		double ny = (Math.sin(angle) * x) + (Math.cos(angle) * y);
		return new double[] {nx, ny};
	}

本文中的方法出处:http://my.oschina.net/u/2344340/blog/699435

© 著作权归作者所有

共有 人打赏支持
M
粉丝 0
博文 1
码字总数 675
作品 0
渝中
私信 提问
Java base64图片编码上传,判断图片是否有旋转,修正并保存

最近遇到一个问题,手机端上传的图片为base64编码格式的,服务器需要通过解码字符串然后判断图片是否有旋转角度,在保存为图片。手上有一个.net的例子,但需要转为Java语言的,由于对Java的类...

OSC-原谅帽派送员
2016/06/20
1K
2
Java编程语言:学JAVA没有基础,给你4个方向少走弯路。

Java java常常跟"企业"联系在一起, 因为具备一些很好的语言特性, 以及丰富的框架, 在企业应用中最被青睐, 你总可以听到关于J2EE, JSP, Hibernate之类的东西的讨论. 同时, java在手机领域也有...

启示录是真的
2018/05/24
0
0
被标记为事务的方法互相调用的坑(上)

相信大家一定用过Spring中的注解型事务,配合上Spring Boot,只需要在方法上打一个@Transactional 就可以完成,真香。 但是如果大家对其中的机制一知半解的话,可能一不小心就会掉进坑,然后...

编程SHA
02/21
0
0
java程序员基础进阶篇,万丈高楼平地起

一.final,finally,finalize 三者区别 Final是一个修饰符: 当final修饰一个变量的时候,变量变成一个常量,它不能被二次赋值 当final修饰的变量为静态变量(即由static修饰)时,必须在声明这...

启示录是真的
2018/05/26
0
0
工作5年的Java程序员,才学会阅读源码,可悲吗?

最近一位5年开发经验的群友与我聊天 他说:最近慢慢的尝试去看spring的源码,学习spring,以前都只是会用就行了,但是越是到后面,发现只懂怎么用还不够,在面试的时候经常被问到一些开源框架...

Java架构
02/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

再谈使用开源软件搭建数据分析平台

三年前,我写了这篇博客使用开源软件快速搭建数据分析平台, 当时收到了许多的反馈,有50个点赞和300+的收藏。到现在我还能收到一些关于dataplay2的问题。在过去的三年,开源社区和新技术的发...

naughty
今天
3
0
C++网络编程(一)gRPC的编译

Google是真滴烦,整个编译链全是自家产品,在编译之前先来安装一堆东西 安装环境依赖 chocolatey Windows下的包管理系统,没有他就慢慢去下载下面的一堆乱七八糟的东西吧。CMD下执行下面这句...

Pulsar-V
今天
3
0
Python3的日期和时间

python 中处理日期时间数据通常使用datetime和time库 因为这两个库中的一些功能有些重复,所以,首先我们来比较一下这两个库的区别,这可以帮助我们在适当的情况下时候合适的库。 在Python文...

编程老陆
今天
2
0
分布式面试整理

并发和并行 并行是两个任务同时进行,而并发呢,则是一会做一个任务一会又切换做另一个任务。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用,但是每一次,只能有...

群星纪元
今天
3
0
手机通过wifi遥控arduino

手机下载Blinker 从Blinker官网下载手机App,安装到手机。 手机连接WiFi。 点击我的设备右上角的"+"添加设备,选择Arduino -> wifi接入,复制密钥以备后续使用。 点击新建的设备,可以在新界...

davidwbnu
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部