IOS拍摄图片上传自动旋转问题

IOS拍摄图片上传自动旋转问题

java后端处理

项目中使用了图片上传至腾讯云,图片都可以正常上传,可是发现iOS拍摄的照片会被自动旋转.

出现这种情况的原因:
iPhone对拍摄的照片附加了EXIF信息(如镜头、光圈、快门、焦距、相机拍摄角度等),图片被上传
后自动根据相机拍摄角度做了旋转。
那么解决方案就是根据图像EXIF信息中的相机拍摄角度(Orientation),再旋转回来就OK了。

orientation的几种类型:
Orientation = 1(不翻转)
Orientation = 2 (左右翻转)
Orientation = 3 (180度翻转)
Orientation = 4 (上下翻转)
Orientation = 5 (顺时针翻转90度后,左右翻转)
Orientation = 6 (顺时针翻转90度)
Orientation = 7 (逆时针翻转90度后,左右翻转)
Orientation = 8 (逆时针翻转90度)

PS:一般常用的也就是1,3,6,8,另外几种应该是那种有特效功能的相机拍出的吧。

直接上解决细节吧!
腾讯云图片上传工具类:

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import java.io.File;
import java.net.URL;
import java.util.Date;
import java.util.Random;
public class TencentCOS {
// 此处填写的存储桶名称
private static final String bucketName = “bucketName “;
// secretId 可在腾讯云后台中的API密钥管理中查看
private static final String secretId = “secretId”
// secretKey 可在腾讯云后台中的API密钥管理中查看
private static final String secretKey = “secretKey”;
//时区
private static final String region = “ap-shanghai-fsi”;
//上传至腾讯云的路径
private static final String prefix = “headUrl/”;
// 1 初始化用户身份信息(secretId, secretKey)
private static COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
// 2 设置bucket的区域, COS地域的简称请参照
// https://cloud.tencent.com/document/product/436/6224,根据自己创建的存储桶选择地区
private static ClientConfig clientConfig = new ClientConfig(new Region(region));
/**
* 简单文件上传, 最大支持 5 GB, 适用于小文件上传, 建议 20 M 以下的文件使用该接口 大文件上传请参照 API 文档高级 API 上传
*
* @param localFile
*/
public static String uploadfile(File localFile) throws CosClientException {
// 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
String fileName = localFile.getName();
String url = null;
try {
String substring = fileName.substring(fileName.lastIndexOf(”.”));
Random random = new Random();
// 指定要上传到 COS 上的路径
fileName = prefix + random.nextInt(10000) + System.currentTimeMillis() + substring;
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, localFile);
cosclient.putObject(putObjectRequest);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭客户端(关闭后台线程)
cosclient.shutdown();
Date expiration = new Date(new Date().getTime() + 3600 * 10000 * 24 * 365L);
URL oldUrl = cosclient.generatePresignedUrl(bucketName, fileName, expiration);
url = oldUrl.toString();
url = url.substring(0, url.indexOf("?"));
}
return url;
}
}

图片旋转工具类

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import lombok.extern.slf4j.Slf4j;
//import com.sun.image.codec.jpeg.ImageFormatException;
//import com.sun.image.codec.jpeg.JPEGCodec;
//import com.sun.image.codec.jpeg.JPEGEncodeParam;
//import com.sun.image.codec.jpeg.JPEGImageEncoder;
import javax.imageio.ImageIO;
import java.awt.;
import java.awt.image.BufferedImage;
import java.io.
;
import java.util.Iterator;
@Slf4j
public class PictureRotateUtil {
/**

  • 旋转图片为指定角度
  • @param file 目标图像
  • @param angel 旋转角度
  • @return
    */
    public static File rotateImage(File file, final int angel) {
    BufferedImage src = null;
    try {
    src = ImageIO.read(file);
    } catch (IOException e) {
    e.printStackTrace();
    }
    int src_width = src.getWidth(null);
    int src_height = src.getHeight(null);
    Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
    BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = bi.createGraphics();
    g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
    g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
    g2.drawImage(src, null, null);
    try {
    ImageIO.write(bi, “jpg”, file);
    } catch (IOException e) {
    e.printStackTrace();
    }
    // 调用方法输出图片文件
    // outImage(file.getPath(), bi, (float) 0.5);
    return file;
    }

读取图片orientation信息工具类

import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.MetadataException;
import com.drew.metadata.exif.ExifDirectoryBase;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
@Slf4j
public class ReadFileProperties {
public static File getRotate(File file) {
Metadata metadata = null;
try {
metadata = ImageMetadataReader.readMetadata(file);
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (metadata == null) {
return null;
}
int orientation = 0;
try {
orientation = getOrientation(metadata);
} catch (Exception e) {
e.printStackTrace();
}
switch (orientation) {
case 1:
log.info(“0度”);
break;
case 3:
file = PictureRotateUtil.rotateImage(file, 180);
log.info(“180度”);
break;
case 6:
file = PictureRotateUtil.rotateImage(file, 90);
log.info(“90度”);
break;
case 8:
file = PictureRotateUtil.rotateImage(file, 270);
log.info(“270度”);
break;
}
return file;
}
public static int getOrientation(Metadata metadata) {
Iterable directories = metadata.getDirectories();
int orientation = 0;
for (Directory directory : directories) {
//有很多组orientation信息,只有Exif IFD0对应的orientation才是需要的
if (directory.getName().equals(“Exif IFD0”)) {
try {
orientation = directory.getInt(ExifDirectoryBase.TAG_ORIENTATION);
} catch (MetadataException e) {
e.printStackTrace();
}
log.info(“orientation:” + orientation);
}
}
return orientation;
}

代码实现

public SysResponse updateUrl(@RequestParam(“file”) MultipartFile file ) {
SysResponse sysResp = new SysResponse();
// 获取文件名
String fileName = file.getOriginalFilename();
log.info(“fileName:” + fileName);
获取文件后缀
String prefix = fileName.substring(fileName.lastIndexOf("."));
log.info(“prefix:” + prefix);
// 用uuid作为文件名,防止生成的临时文件重复
File excelFile = File.createTempFile(“imagesFile-” + System.currentTimeMillis(), prefix);
// 将MultipartFile转为File
file.transferTo(excelFile);
log.info(“旋转…开启”);
excelFile = ReadFileProperties.getRotate(excelFile);
log.info(“旋转…完成”);
//调用腾讯云工具上传文件
String headPortrait = null;
try {
headPortrait = TencentCOS.uploadfile(excelFile);
} catch (CosClientException e) {
e.printStackTrace();
}
icpAgentUser.setHeadPortrait(headPortrait);
int i = user.updateUrl(icpAgentUser);
if (i > 0) {
responseData.getpData().put(“photoUrl”, qrCode);
sysResp.setrCode(StatusCode.UPDATE_SUCCESS.code());
sysResp.setrMsg(StatusCode.UPDATE_SUCCESS.message());
sysResp.setrData(responseData);
} else {
sysResp.setrCode(StatusCode.UPDATE_FAIL.code());
sysResp.setrMsg(StatusCode.UPDATE_FAIL.message());
}
return sysResp;
}

第一次写博客,纯属个人理解,如有不对之处请多多指教~

猜你喜欢

转载自blog.csdn.net/star919402/article/details/107820340