通过Java代码获取图片拍摄详细地址和其他相关信息

时间:2024-11-15 12:12:14

1 准备工作

1.1 导入依赖

        <!-- 地址定位 -->
        <dependency>
            <groupId></groupId>
            <artifactId>metadata-extractor</artifactId>
            <version>2.16.0</version>
        </dependency>

1.2 照片图片

图片名和地址如上所述

2 具体实现

2.1 图片工具类

package ;

import .slf4j.Slf4j;
import ;
import .*;
import ;
import ;
import ;
import ;
import ;

/**
 * 图片工具类
 * @author wuKeFan
 * @date 2022-08-30 15:16:07
 */
@Slf4j
public class ImageUtils {

    public static void main(String[] args) throws Exception {
        ArrayList<String> list = new ArrayList<>();
        ("C:\\Users\\1\\Desktop\\");
        ("C:\\Users\\1\\Desktop\\");
        String path="D://1";
        String resultPath = doVImageMerging2(list, path);
        (resultPath);
    }

    //2张图片水平合并
    public static String doVImageMerging2(ArrayList<String> list, String pathFile) {
        // 读取待合并的文件
        BufferedImage bi1 = null;
        BufferedImage bi2 = null;
        // 调用mergeImage方法获得合并后的图像
        BufferedImage destImg = null;
        try {
            bi2 = getBufferedImage((0));
            bi1 = getBufferedImage((1));
        } catch (IOException e) {
            ();
        }
        // 调用mergeImage方法获得合并后的图像
        try {
            if (bi1 != null && bi2 != null) {
                destImg = mergeImage(bi1, bi2, false);//true为水平,false为垂直
            }
        } catch (IOException e) {
            ();
        }
        // 保存图像
        String savePath = pathFile + "/";//文件存放路径
        String fileName = createImageName() + ".jpg";//文件名称
        String fileType = "jpg";//文件格式
        boolean result = saveImage(destImg, savePath, fileName, fileType);
        ("图片保存结果:{}", result ? "成功" : "失败");
        return savePath + fileName;
    }
    public static BufferedImage getBufferedImage(String fileUrl) throws IOException {
        File f = new File(fileUrl);
        return (f);
    }
    /**
     * 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
     * mergeImage方法不做判断,自己判断。
     *
     * @param img1
     * 待合并的第一张图
     * @param img2
     * 带合并的第二张图
     * @param isHorizontal
     * 为true时表示水平方向合并,为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     */
    public static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2, boolean isHorizontal) throws IOException {
        int w1 = ();
        int h1 = ();
        int w2 = ();
        int h2 = ();
        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = (0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = (0, 0, w2, h2, ImageArrayTwo, 0, w2);
        // 生成新图片
        BufferedImage DestImage;
        // 水平方向合并
        if (isHorizontal) {
        // DestImage = new BufferedImage(w1+w2, h1, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d;
            if (h1 >= h2) {
                DestImage = new BufferedImage(w1 + w2, h1, BufferedImage.TYPE_INT_RGB);
            } else {
                DestImage = new BufferedImage(w2, h1, BufferedImage.TYPE_INT_RGB);//TYPE_INT_RGB
            }
            g2d = ();
            ();
            (0, 0, w1 + w2, h1);
            ();
            (0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            (w1, 0, w2, h2, ImageArrayTwo, 0, w2);
        } else { // 垂直方向合并
            Graphics2D g2d;
            if (w1 >= w2) {
                DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);//TYPE_INT_RGB
            } else {
                DestImage = new BufferedImage(w2, h1 + h2, BufferedImage.TYPE_INT_RGB);//TYPE_INT_RGB
            }
            g2d = ();
            ();
            (0, 0, w1 + w2, h1 + h2);
            ();
            (0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            (0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }
        return DestImage;
    }
    //随机生成图片名称
    public static String createImageName() {
        // 创建 GUID 对象
        UUID uuid = ();
        // 得到对象产生的ID
        String a = ();
        // 转换为大写
        a = ();
        // 替换 -
        a = ("-", "");
        return a;
    }
    public static boolean saveImage(BufferedImage savedImg, String saveDir, String fileName, String format) {
        boolean flag = false;
        // 先检查保存的图片格式是否正确
        String[] legalFormats = { "jpg", "JPG", "png", "PNG", "bmp", "BMP" };
        int i;
        for (i = 0; i < ; i++) {
            if ((legalFormats[i])) {
                break;
            }
        }
        if (i == ) { // 图片格式不支持
            ("不是保存所支持的图片格式!");
            return false;
        }
        // 再检查文件后缀和保存的格式是否一致
        String postfix = (('.') + 1);
        if (!(format)) {
            ("待保存文件后缀和保存的格式不一致!");
            return false;
        }
        String fileUrl = saveDir + fileName;
        File file = new File(fileUrl);
        try {
            flag = (savedImg, format, file);
        } catch (IOException e) {
            ();
        }
        return flag;
    }

    /**
     * 经纬度格式  转换为  度分秒格式 ,如果需要的话可以调用该方法进行转换
     *
     * @param point 坐标点
     * @return 返回时分秒格式
     */
    public static String pointToLatLong(String point) {
        double du = ((0, ("°")).trim());
        double fen = ((("°") + 1, ("'")).trim());
        double miao = ((("'") + 1, ("\"")).trim());
        double duStr = du + fen / 60 + miao / 60 / 60;
        return (duStr);
    }

    /***
     * 经纬度坐标格式转换(* °转十进制格式)
     * @param gps gps坐标
     */
    public static double latLng2Decimal(String gps) {
        String a = ("°")[0].replace(" ", "");
        String b = ("°")[1].split("'")[0].replace(" ", "");
        String c = ("°")[1].split("'")[1].replace(" ", "").replace("\"", "");
        return (a) + (b) / 60 + (c) / 60 / 60;
    }

}

2.2 地址处理工具类(主要逻辑代码都在这个类)

package ;

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import .slf4j.Slf4j;
import ;
import ;

import ;
import ;
import ;
import ;
import ;

/**
 * 图片地址工具类
 * @author wuKeFan
 * @date 2023-02-24 15:44:31
 */
@Slf4j
@Component
public class ImageAddressUtils {

    @Resource
    private RestTemplate restTemplate;

    public String getPhotoAddress(String fileName) throws ImageProcessingException, IOException {
        File file = new File(fileName);
        Metadata metadata = (file);
        //图片的所有目录信息
        Iterable<Directory> directories = ();
        for (Directory directory : directories) {
            for (Tag tag : ()) {
                ("[{}] - {} = {}",
                        (), (), ());
            }
            if (()) {
                for (String error : ()) {
                    ("ERROR: {}", error);
                }
            }
        }
        Double lat = null;
        Double lng = null;
        for (Directory directory : directories) {
            for (Tag tag : ()) {
                String tagName = ();  //标签名
                String desc = (); //标签信息
                switch (tagName) {
                    case "Image Height":
                        ("图片高度: " + desc);
                        break;
                    case "Image Width":
                        ("图片宽度: " + desc);
                        break;
                    case "Date/Time Original":
                        ("拍摄时间: " + desc);
                        break;
                    case "GPS Latitude":
                        ("纬度 : " + desc);
                        ("纬度(度分秒格式) : " + (desc));
                        lat = ImageUtils.latLng2Decimal(desc);
                        break;
                    case "GPS Longitude":
                        ("经度: " + desc);
                        ("经度(度分秒格式): " + (desc));
                        lng = ImageUtils.latLng2Decimal(desc);
                        break;
                }
            }
        }
        //经纬度转地主使用百度api
        if (lat != null && lng != null) {
            ReverseGeocodingRequest request = ()
                    .token(BaiduMapConstants.BAIDU_MAP_TOKEN).output(BaiduMapConstants.OUTPUT_TYPE_JSON)
                    .coordinateType(BaiduMapConstants.COORDINATE_TYPE_GPS).lat(lat).lng(lng)
                    .build();
            Map<String, Object> map = (request);
            String result = (BaiduMapConstants.REVERSE_GEOCODING_URL, , map);
            JSONObject resultObj = ((result));
            if (resultObj != null && (("status"), 0)) {
                AddressComponentResponse response = ("result").getObject("addressComponent", );
                return "拍摄地点:" + () + " " + () + " " + () + " " + () + " "
                        + () + " " + ("result").get("formattedAddress") + " " + ("result").get("business");
            }
        }
        return null;
    }

}

2.3 实体类和

package ;

import ;

/**
 * 地址构成实体类
 * @author wuKeFan
 * @date 2022-08-18 14:48:28
 */
@Data
public class AddressComponentResponse {

    /**
     * 国家
     */
    private String country;

    /**
     * 国家编码
     */
    private int countryCode;

    /**
     * 国家英文缩写(三位)
     */
    private String countryCodeIso;

    /**
     * 国家英文缩写(两位)
     */
    private String countryCodeIso2;

    /**
     * 省名
     */
    private String province;

    /**
     * 城市名
     */
    private String city;

    /**
     * 城市所在级别(仅国外有参考意义。
     * 国外行政区划与中国有差异,城市对应的层级不一定为『city』。
     * country、province、city、district、town分别对应0-4级,
     * 若city_level=3,则district层级为该国家的city层级)
     */
    private int cityLevel;

    /**
     * 区县名
     */
    private String district;

    /**
     * 乡镇名,需设置extensions_town=true时才会返回
     */
    private String town;

    /**
     * 乡镇id
     */
    private String townCode;

    /**
     * 相对当前坐标点的距离,
     * 当有门牌号的时候返回数据
     */
    private String distance;

    /**
     * 和当前坐标点的方向
     */
    private String direction;

    /**
     * 行政区划代码
     */
    private String adcode;

    /**
     * 街道名(行政区划中的街道层级)
     */
    private String street;

    /**
     * 街道门牌号
     */
    private String streetNumber;

}
package ;

import ;
import ;
import ;
import ;

/**
 * 逆地理编码参数请求实体类
 * @author wuKeFan
 * @date 2022-08-18 14:29:15
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ReverseGeocodingRequest {

    /**
     * 用户申请注册的key,即ak
     */
    private String token;

    /**
     * 输出格式为json或者xml
     */
    private String output;

    /**
     * 坐标的类型,
     * 目前支持的坐标类型包括:bd09ll(百度经纬度坐标)、
     * bd09mc(百度米制坐标)、gcj02ll(国测局经纬度坐标,仅限中国)、wgs84ll( GPS经纬度)
     */
    private String coordinateType;

    /**
     * 纬度
     */
    private Double lat;

    /**
     * 经度
     */
    private Double lng;

}

2.4 测试代码

package ;

import ;
import ;
import .slf4j.Slf4j;
import ;
import ;
import ;
import ;
import ;

/**
 * 公共测试类
 * @author wuKeFan
 * @date 2023-02-20 09:53:14
 */
@Slf4j
@SpringBootTest
public class PublicTest {

    @Resource
    private ImageAddressUtils imageAddressUtils;

    @Test
    public void photoAddressTest() throws ImageProcessingException, IOException {
        (("C:\\Users\\1\\Desktop\\2023_02_18_20_21_IMG_0057.JPG"));
    }

}

运行结果如图: