java解析图片GPS等信息

文章目录

  • java解析图片GPS等信息
    • 1.元数据(Metadata)
      • 1.1Metadata概念解释
      • 1.2 图片元数据
    • 2.代码展示
      • 2.1解析图片信息代码实例(有详细注解)
      • 2.1springboot后端代码设计
        • controller层设计
        • service接口
        • serviceImpl实现类
        • Result设计
        • MultipartFile转File
        • pom依赖
        • postman测试
    • 3.参考文献

前言:我在学习的获取图片信息过程中,发现网上的已有的文章要么需要VIP才能查看,要么就是讲的只言片语,注解太少,对于我这种新手很不友好,特此写这篇文章以便他人参考。

本文代码有详细注解,并且在文章末尾附上我所参考的文章,以及一些知识点的补充。

1.元数据(Metadata)

图片的GPS信息存储在图片的元数据中,所以解析图片GPS就是获取图片元数据

1.1Metadata概念解释

​ 元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息。用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。

元数据是关于数据的组织、数据域及其关系的信息,简言之,元数据就是关于数据的数据。

举个例子:

下面是契诃夫的小说《套中人》中的一段,描写一个叫做瓦莲卡的女子:

(她)年纪已经不轻,三十岁上下,个子高挑,身材匀称,黑黑的眉毛,红红的脸蛋--一句话,不是姑娘,而是果冻,她那样活跃,吵吵嚷嚷,不停地哼着小俄罗斯的抒情歌曲,高声大笑,动不动就发出一连串响亮的笑声:哈,哈,哈!

这段话里提供了这样几个信息:年龄(三十岁上下)、身高(个子高挑)、相貌(身材匀称,黑黑的眉毛,红红的脸蛋)、性格(活跃,吵吵嚷嚷,不停地哼着小俄罗斯的抒情歌曲,高声大笑)。有了这些信息,我们就可以大致想像出瓦莲卡是个什么样的人。推而广之,只要提供这几类的信息,我们也可以推测出其他人的样子。

这个例子中的"年龄"、“身高”、“相貌”、“性格”,就是元数据,因为它们是用来描述具体数据/信息的数据/信息。

当然,这几个元数据用来刻画个人状况还不够精确。我们每个人从小到大,都填过《个人情况登记表》之类的东西吧,其中包括姓名、性别、民族、政治面貌、一寸照片、学历、职称等等…这一套元数据才算比较完备。

1.2 图片元数据

图片元数据(Metadata) 是嵌入到图片文件中的一些标签。比较像文件属性,但是种类繁多。对于数码图像,目前常见的研数据有EXIF, IPTC和XMP三种:

  • EXIF:通常被数码相机在拍摄照片时自动添加,比如相机型号、镜头、曝光、图片尺寸,地理位置等信息
  • IPTF:比如图片标题、关键字、说明、作者、版权等信息。主要是由人工在后期通过软件写入的数据。
  • XMPXMP实际上是一种元数据存储和管理的标准,可以将Exif,IPTC或其他的数据都按XMP统一的格式存放在图像文件中。

元数据的嵌入方式因图像格式而异,不同格式的图像文件(如JPG, TIF, DNS等)有不同的嵌入方式。

2.代码展示

2.1解析图片信息代码实例(有详细注解)

方法封装在自定义的Exif类中,前端获取图片传给后端,后端在service层调用该方法

package com.haoshang.until;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;/*** @author 浩殇* @create 2022/12/7--22:56--周三* Exif*/
public class Exif {//主方法体,封装在Exif类中,通过service层调用public static JSONObject analysis(File file)throws Exception{//将图片传入自定义方法中return printImageTags( file);}private static JSONObject printImageTags(File file) throws ImageProcessingException, IOException {String lat = "";String log = "";
//      读取元数据Metadata metadata = ImageMetadataReader.readMetadata(file);for (Directory directory : metadata.getDirectories()) {//            打印元数据内容for (Tag tag : directory.getTags()) {String tagName = tag.getTagName();  //标签名String desc = tag.getDescription(); //标签信息
//            System.out.println("["+tagName +"]"+ " : " + desc);//照片信息switch (tagName) {//                    经度case "GPS Longitude":lat = pointToLatlong(desc);
//                  System.out.println("***********"+lat+"*************");break;//                        纬度case "GPS Latitude":log = pointToLatlong(desc);
//                  System.out.println("***********"+log+"*************");break;default:break;}}}System.out.println("###########################################################################");String add = getAdd(log, lat);JSONObject jsonObject = JSON.parseObject(add);//controller层设计为传输JSONObject类,读者也可设计为传输地址字符串return jsonObject;/*输出地址String add = getAdd(log, lat);JSONObject jsonObject = JSON.parseObject(add);JSONObject object=jsonObject.getJSONObject("result");String adds = object.getString("formatted_address");*/}/*** 经纬度格式  转换** @param point 坐标点** @return*/public static String pointToLatlong(String point) {Double du = Double.parseDouble(point.substring(0, point.indexOf("°")).trim());Double fen = Double.parseDouble(point.substring(point.indexOf("°") + 1, point.indexOf("'")).trim());Double miao = Double.parseDouble(point.substring(point.indexOf("'") + 1, point.indexOf("\"")).trim());Double duStr = du + fen / 60 + miao / 60 / 60;return duStr.toString();}/*** @param log 经度** @param lat 纬度** @return*/public static String getAdd(String log, String lat) {//采用百度地图的接口:String urlString = "http://api.map.baidu.com/geocoder?location="+log+","+lat+"&output=json";System.out.println(urlString);String res = "";try {/*URL定义:统一资源标识符(Uniform Resource Identifier ,URL)是采用一种特定语法标识一个资源的字符串。所标识的资源可能是服务器上的一个文件。Java的URL网络类可以让你通过URL去练级网络服务器并获取资源。*/
//            创建新的urlURL url = new URL(urlString);
//             调用URL对象的openConnection( )来获取HttpURLConnection对象实例:HttpURLConnection conn = (HttpURLConnection) url.openConnection();//            可以使用conn.getOutputStream().write()conn.setDoOutput(true);//            设置HTTP请求使用的方法:GET(不安全) 或者POST,PUT等,HttpURLConnection默认是进行Get请求的:conn.setRequestMethod("GET");
//              调用getInputStream()方法获得服务器返回的输入流,然后输入流进行读取BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));String line;
//            解析获得的数据while ((line = in.readLine()) != null) {res += line + "\n";}in.close();} catch (Exception e) {System.out.println("error in wapaction,and e is " + e.getMessage());}return res;}
}

2.1springboot后端代码设计

springboot上传文件类型为MultipartFile,而解析图片需要上传File文件,所以代码涉及到MultipartFile转为File的类

代码中的MassageMapper, PhotoMassage分别为设计的mapper和实体类pojo,但并未对数据库进行操作,所以并未展示

controller层设计

package com.haoshang.apppro.analysis.controller;import com.alibaba.fastjson.JSONObject;
import com.haoshang.apppro.analysis.service.MassageService;
import com.haoshang.until.Result;
import com.haoshang.until.Status;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/*** @author 浩殇* @create 2022/12/6--19:59--周二* AnalysisController*/
@RestController
@RequestMapping("/analysis")
public class AnalysisController {@Autowiredprivate MassageService massageService;@PostMapping("/photo")private Result<JSONObject> analysisPhoto(@RequestParam("file") MultipartFile file){try {return massageService.analysis(file);} catch (Exception e) {e.printStackTrace();return new Result<>(Status.SYSTEM_ERROR.getCode(), Status.SYSTEM_ERROR.getMessage(),null);}}}

service接口

package com.haoshang.apppro.analysis.service;import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import com.haoshang.apppro.analysis.entity.PhotoMassage;
import com.haoshang.until.Result;
import org.springframework.web.multipart.MultipartFile;
/*** @author 浩殇* @create 2022/12/6--20:19--周二* MassageService*/
public interface MassageService extends IService<PhotoMassage> {Result<JSONObject> analysis(MultipartFile f) throws Exception;
}

serviceImpl实现类

package com.haoshang.apppro.analysis.service.impl;import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haoshang.apppro.analysis.entity.PhotoMassage;
import com.haoshang.apppro.analysis.mapper.MassageMapper;
import com.haoshang.apppro.analysis.service.MassageService;
import com.haoshang.until.Exif;
import com.haoshang.until.Result;
import com.haoshang.until.Shift;
import com.haoshang.until.Status;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/*** @author 浩殇* @create 2022/12/6--20:37--周二* MassageServiceImpl*/
@Service
public class MassageServiceImpl extends ServiceImpl<MassageMapper, PhotoMassage> implements MassageService {@Overridepublic Result<JSONObject> analysis( MultipartFile file)  {try {File f=Shift.multipartFileToFile(file);JSONObject jsonObject=Exif.analysis(f);Shift.deleteTempFile(f);//清除缓存return new Result<>(Status.OK.getCode(), "读取图片信息成功",jsonObject);} catch (Exception e) {e.printStackTrace();return new Result<>(Status.SYSTEM_ERROR.getCode(), Status.SYSTEM_ERROR.getMessage(),null);// Status.SYSTEM_ERROR.getCode()是自定义的code,读者采用自己设计的code即可}}
}

Result设计

package com.haoshang.until;import lombok.Data;
/*** @author 浩殇* @create 2022/11/23--20:02--周三* Result*/
@Data
public class Result<T> {//    状态码private int code;//    返回信息private  String msg;//     数据private T data;public Result() {}public Result(int code, String msg) {this.code = code;this.msg = msg;}public Result(int code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}public Result(T data) {this.data = data;}}

MultipartFile转File

package com.haoshang.until;import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/*** @author 浩殇* @create 2022/12/8--0:00--周四* shift*/
public class Shift {/*** MultipartFile 转 File** @param file* @throws Exception*/public static File multipartFileToFile(MultipartFile file) throws Exception {File toFile = null;if (file.equals("") || file.getSize() <= 0) {file = null;} else {InputStream ins = null;ins = file.getInputStream();//读入到内存toFile = new File(file.getOriginalFilename());//给File文件实体化inputStreamToFile(ins, toFile);ins.close();}return toFile;}//获取流文件private static void inputStreamToFile(InputStream ins, File file) {try {OutputStream os = new FileOutputStream(file);//以输出流打开file,实现outputStream.write向file中输出内容int bytesRead = 0;byte[] buffer = new byte[8192];while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {os.write(buffer, 0, bytesRead);//文件写入}os.close();ins.close();} catch (Exception e) {e.printStackTrace();}}/*** 删除本地临时文件* @param file*/public static void deleteTempFile(File file) {if (file != null) {File del = new File(file.toURI());del.delete();}}
}

pom依赖

仅展示解析元数据类的依赖

<!--获取元数据依赖--><dependency><groupId>com.drewnoakes</groupId><artifactId>metadata-extractor</artifactId><version>2.7.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.71</version></dependency>

postman测试

3.参考文献

参考文献:

  1. Java Metadata.getDirectories方法代码示例 - 纯净天空 (vimsky.com)
  2. 图像元数据(Metadata) 及 Exif信息分析 - 掘金 (juejin.cn)
  3. http://t.csdn.cn/XOJJD(元数据理解)
  4. JSONArray与JSONObject的区别 - 清华大咖 - 博客园 (cnblogs.com)
  5. 通过经纬度获取具体省市区位置地址的Api | 程序员磊哥 (examplecode.cn)

java解析图片GPS等信息,springboot项目获得图片GPS相关推荐

  1. SpringBoot项目中图片加载失败

    SpringBoot项目中图片加载失败 这个原因有很多,比如你的拦截器,过滤了静态资源. 如果你感觉自己的前端代码没有问题,配置也没有问题,可能是由于你后期导入的图片还没有被加载到target文件夹中 ...

  2. SpringBoot项目静态图片加载浏览器不显示问题解决方案

    SpringBoot项目静态图片加载浏览器不显示问题解决方案 项目结构如下: 我是通过Maven创建的以Thymeleaf为模板引擎创建的SpringBoot Web项目,发现加载的图片在浏览器不显示 ...

  3. springboot项目引入图片_SpringBoot实现上传图片功能

    1:首先在项目的pom文件中添加两个依赖 commons-fileupload commons-fileupload 1.3.1 net.coobird thumbnailator 0.4.8 2:r ...

  4. springboot项目引入图片_项目经验不重样!3个基于 SpringBoot 的图片识别处理系统送给你!...

    我是 Guide 哥,一 Java 后端开发,会一点前端,自由的少年. 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步! 最近看了太多读者小伙伴的简历,发现各种商城/秒杀系统/在线教育 ...

  5. springboot项目引入图片_项目经验不重样!3个基于SpringBoot 的图片识别处理系统送给你...

    转载:https://mp.weixin.qq.com/s/WDMyIfOi2ogw0mKl3XxQdQ 最近看了太多读者小伙伴的简历,发现各种商城/秒杀系统/在线教育系统真的是挺多的.推荐一下昨晚找 ...

  6. docker 挂载目录_完美解决:Docker部署SpringBoot项目后图片无法访问和上传,3招搞定!...

    以前使用FTP在Linux中使用java -jar xxx.jar部署SpringBoot项目时,由于在项目中指定了主机文件存放路径映射,可以直接访问服务器的文件. 但是最近入坑Docker,将Spr ...

  7. Java毕业设计:养老院管理系统(Springboot项目)

    [辰兮要努力]:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端.后台.数据 ...

  8. SpringBoot项目中图片的引用

    问题描述:在SpringBoot项目中需要在CSS样式文件中引入图片给某个元素设置样式 解决办法: body{background-image: url("../image/580.jpg& ...

  9. java web图片旋转_修正web项目中图片旋转方向

    # 使用 imagemagick 旋转 查看照片 EXIF 信息,Exif 中的图片旋转信息储存在``Orientation``中. ``` identify -verbose xxx.jpg ``` ...

最新文章

  1. 输入两个整数a和b,计算a+b的和
  2. pytorch checkpoint_pytorch的两种部署方式 web部署与c++部署
  3. 原生Java高仿抖音短视频APP双端源码
  4. java debug try catch 打印发生错误的代码的详细信息 代码行数
  5. 【Linux运维】centOS7 中安装可视化图形界面
  6. linux 安装触摸版驱动程序,在ubuntu和linux上配置触摸屏驱动程序启用触摸屏
  7. NAND FLASH简介
  8. 徐思201771010132《面向对象程序设计(java)》第十四周学习总结
  9. 用python做自我介绍_使用Python实现自我介绍
  10. 起点:如何成为一名黑客?
  11. log4j日志文件默认存放路径
  12. linux下 scp 和 ssh 命令
  13. iphone手机视频和照片永久删除还能恢复吗?
  14. python 多线程卡死跳出_解决python线程卡死的问题
  15. 用cadence进行原理图设计时,如何更改图纸大小?
  16. XY的模式识别学习笔记-最小平方误差准则分类 MSE
  17. 《神经网络与深度学习》-注意力机制与外部记忆
  18. 遥感IDL二次开发(辐射定标)
  19. 接触式IC卡 - STM32(Smart Card)
  20. 【架构】电商微服务架构图 -来源网络(非原创)

热门文章

  1. 《Cracking the Coding Interview程序员面试金典》----猫狗收容所
  2. ITK入门教程(13)点集之得到点中的存储数据
  3. c/c++ 求解数独
  4. uniapp-商品详情配置
  5. 面对对象之差异化的网络数据交互方式--单机游戏开发之无缝切换到C/S模式
  6. 2022年化工自动化控制仪表考试资料及化工自动化控制仪表免费试题
  7. GNS3 2.1.21详细安装教程
  8. python画五角星代码_Python使用turtule画五角星的方法
  9. 计算机方向的综述投稿哪个期刊,人工智能方向论文投稿期刊
  10. Jquery如何去掉复选框的勾