java解析图片GPS等信息,springboot项目获得图片GPS
java解析圖片GPS等信息
文章目錄
- java解析圖片GPS等信息
- 1.元數(shù)據(jù)(Metadata)
- 1.1Metadata概念解釋
- 1.2 圖片元數(shù)據(jù)
- 2.代碼展示
- 2.1解析圖片信息代碼實例(有詳細注解)
- 2.1springboot后端代碼設計
- controller層設計
- service接口
- serviceImpl實現(xiàn)類
- Result設計
- MultipartFile轉File
- pom依賴
- postman測試
- 3.參考文獻
前言:我在學習的獲取圖片信息過程中,發(fā)現(xiàn)網(wǎng)上的已有的文章要么需要VIP才能查看,要么就是講的只言片語,注解太少,對于我這種新手很不友好,特此寫這篇文章以便他人參考。
本文代碼有詳細注解,并且在文章末尾附上我所參考的文章,以及一些知識點的補充。
1.元數(shù)據(jù)(Metadata)
圖片的GPS信息存儲在圖片的元數(shù)據(jù)中,所以解析圖片GPS就是獲取圖片元數(shù)據(jù)
1.1Metadata概念解釋
? 元數(shù)據(jù)(Metadata),又稱中介數(shù)據(jù)、中繼數(shù)據(jù),為描述數(shù)據(jù)的數(shù)據(jù)(data about data),主要是描述數(shù)據(jù)屬性(property)的信息。用來支持如指示存儲位置、歷史數(shù)據(jù)、資源查找、文件記錄等功能。
元數(shù)據(jù)是關于數(shù)據(jù)的組織、數(shù)據(jù)域及其關系的信息,簡言之,元數(shù)據(jù)就是關于數(shù)據(jù)的數(shù)據(jù)。
舉個例子:
下面是契訶夫的小說《套中人》中的一段,描寫一個叫做瓦蓮卡的女子:
(她)年紀已經(jīng)不輕,三十歲上下,個子高挑,身材勻稱,黑黑的眉毛,紅紅的臉蛋--一句話,不是姑娘,而是果凍,她那樣活躍,吵吵嚷嚷,不停地哼著小俄羅斯的抒情歌曲,高聲大笑,動不動就發(fā)出一連串響亮的笑聲:哈,哈,哈!
這段話里提供了這樣幾個信息:年齡(三十歲上下)、身高(個子高挑)、相貌(身材勻稱,黑黑的眉毛,紅紅的臉蛋)、性格(活躍,吵吵嚷嚷,不停地哼著小俄羅斯的抒情歌曲,高聲大笑)。有了這些信息,我們就可以大致想像出瓦蓮卡是個什么樣的人。推而廣之,只要提供這幾類的信息,我們也可以推測出其他人的樣子。
這個例子中的"年齡"、“身高”、“相貌”、“性格”,就是元數(shù)據(jù),因為它們是用來描述具體數(shù)據(jù)/信息的數(shù)據(jù)/信息。
當然,這幾個元數(shù)據(jù)用來刻畫個人狀況還不夠精確。我們每個人從小到大,都填過《個人情況登記表》之類的東西吧,其中包括姓名、性別、民族、政治面貌、一寸照片、學歷、職稱等等…這一套元數(shù)據(jù)才算比較完備。
1.2 圖片元數(shù)據(jù)
圖片元數(shù)據(jù)(Metadata) 是嵌入到圖片文件中的一些標簽。比較像文件屬性,但是種類繁多。對于數(shù)碼圖像,目前常見的研數(shù)據(jù)有EXIF, IPTC和XMP三種:
- EXIF:通常被數(shù)碼相機在拍攝照片時自動添加,比如相機型號、鏡頭、曝光、圖片尺寸,地理位置等信息
- IPTF:比如圖片標題、關鍵字、說明、作者、版權等信息。主要是由人工在后期通過軟件寫入的數(shù)據(jù)。
- XMP:XMP實際上是一種元數(shù)據(jù)存儲和管理的標準,可以將Exif,IPTC或其他的數(shù)據(jù)都按XMP統(tǒng)一的格式存放在圖像文件中。
元數(shù)據(jù)的嵌入方式因圖像格式而異,不同格式的圖像文件(如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 = ""; // 讀取元數(shù)據(jù)Metadata metadata = ImageMetadataReader.readMetadata(file);for (Directory directory : metadata.getDirectories()) { // 打印元數(shù)據(jù)內容for (Tag tag : directory.getTags()) {String tagName = tag.getTagName(); //標簽名String desc = tag.getDescription(); //標簽信息 // System.out.println("["+tagName +"]"+ " : " + desc);//照片信息switch (tagName) {// 經(jīng)度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類,讀者也可設計為傳輸?shù)刂纷址?/span>return jsonObject;/*輸出地址String add = getAdd(log, lat);JSONObject jsonObject = JSON.parseObject(add);JSONObject object=jsonObject.getJSONObject("result");String adds = object.getString("formatted_address");*/}/*** 經(jīng)緯度格式 轉換** @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 經(jīng)度** @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定義:統(tǒng)一資源標識符(Uniform Resource Identifier ,URL)是采用一種特定語法標識一個資源的字符串。所標識的資源可能是服務器上的一個文件。Java的URL網(wǎng)絡類可以讓你通過URL去練級網(wǎng)絡服務器并獲取資源。*/ // 創(chuàng)建新的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; // 解析獲得的數(shù)據(jù)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,但并未對數(shù)據(jù)庫進行操作,所以并未展示
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實現(xiàn)類
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> {// 狀態(tài)碼private int code;// 返回信息private String msg;// 數(shù)據(jù)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,實現(xiàn)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依賴
僅展示解析元數(shù)據(jù)類的依賴
<!--獲取元數(shù)據(jù)依賴--><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.參考文獻
參考文獻:
總結
以上是生活随笔為你收集整理的java解析图片GPS等信息,springboot项目获得图片GPS的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 权限和归属关系解析与新手小白操作教程
- 下一篇: Docker从入门到放弃------do