zoukankan      html  css  js  c++  java
  • 解析图片内隐含的信息并将其打印在图片上做水印

    周五收到说要做一个给照片加水印的功能,大概就是说将一张含有坐标点的图片,将它的坐标点以及拍摄时间给打印在照片上,于是乎就在网上找了些相关文章,一开始不太顺利,图片根本解析不出来东西还报了一堆的错,开始还以为是代码的问题,就在那找啊找测啊测的,后来才发现是依赖的jar没导全,以及开发工具设置的一些问题。

    其实这个功能分两步,

    一、将图片(必须是带有位置信息的照片)里含有的信息解析出来:

       

    package photo;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileOutputStream;
    
    import javax.swing.ImageIcon;
    
    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 com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGEncodeParam;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    
    /**
     * java读取照片信息
     */
    public class SampleUsage {
        public static void main(String[] args) throws Exception, Exception {
            File file = new File("D:\test\aa.jpg");
            printImageTags(file);
        }
    
        /**
         * 读取照片里面的信息
         */
        private static void printImageTags(File file) throws ImageProcessingException, Exception {
            Metadata metadata = ImageMetadataReader.readMetadata(file);
            for (Directory directory : metadata.getDirectories()) {
                for (Tag tag : directory.getTags()) {
                    String tagName = tag.getTagName(); // 标签名
                    String desc = tag.getDescription(); // 标签信息
                    if (tagName.equals("Image Height")) {
                        System.out.println("图片高度: " + desc);
                    } else if (tagName.equals("Image Width")) {
                        System.out.println("图片宽度: " + desc);
                    } else if (tagName.equals("Date/Time Original")) {
                        System.out.println("拍摄时间1: " + desc);
                    }else if (tagName.equals("Date/Time Digitized")) {
                        System.out.println("拍摄时间2: " + desc);
                    } else if (tagName.equals("GPS Latitude")) {
                        System.err.println("纬度 : " + desc);
                        System.err.println("纬度(度分秒格式) : " + pointToLatlong(desc));
                    } else if (tagName.equals("GPS Longitude")) {
                        System.err.println("经度: " + desc);
                        System.err.println("经度(度分秒格式): " + pointToLatlong(desc));
                    }
                    System.err.println("tagName: " + tagName+"----->desc"+desc);
                }
            }
        }
    
    
        /**
         * 经纬度格式 转换为 度分秒格式 ,如果需要的话可以调用该方法进行转换
         * 
         * @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();
        }
    }

    运行结果就如下:

        

    ps:需要注意得是查看一张图片是否含有位置信息,找到图片鼠标右键点击“属性”-->“详细信息” 如下:

            

     二、就是将第一步解析到的信息拿到你想要的,并将它打印在照片上:

    package photo;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.FileOutputStream;
    import javax.swing.ImageIcon;
    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGEncodeParam;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
     
    public class ImageEdit {
        
        public static void main(String[] a) {
     
     
            ImageEdit.createStringMark("D:\test\photo\IMG_954.jpg", "*****测试文字*****","D:\test\B.jpg");
            }
     
     
           /**
             * @param filePath 源图片路径
             * @param markContent 图片中添加内容
             * @param outPath  输出图片路径
             * 字体颜色等在函数内部实现的
           */
            //给jpg添加文字
            public static boolean createStringMark(String filePath,String markContent,String outPath) 
            { 
            ImageIcon imgIcon=new ImageIcon(filePath); 
            Image theImg =imgIcon.getImage(); 
            int width=theImg.getWidth(null)==-1?200:theImg.getWidth(null); 
            int height= theImg.getHeight(null)==-1?200:theImg.getHeight(null); 
            System.out.println(width);
            System.out.println(height);
            System.out.println(theImg.toString());
            BufferedImage bimage = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB); 
            Graphics2D g=bimage.createGraphics(); 
            
            Color mycolor = Color.red; 
            g.setColor(mycolor); 
            g.setBackground(Color.red); 
            g.drawImage(theImg, 0, 0, null ); 
            g.setFont(new Font("宋体",Font.PLAIN,80)); //字体、字型、字号 
            g.drawString(markContent,width/80,height-height/100); //画文字 
            g.dispose(); 
            try 
            { 
            FileOutputStream out=new FileOutputStream(outPath); //先用一个特定的输出文件名 
            JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(out); 
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage); 
            param.setQuality(100, true);  //
            encoder.encode(bimage, param); 
            out.close(); 
            } 
            catch(Exception e) 
            { return false; } 
            return true; 
            } 
     
    }

    测试结果:

      因为我的需求是将解析的信息加在照片的下方(关于字体、颜色、位置都可以设置),所以:

      

     看起来是大功告成了呢,哈哈。再顺便排个雷,以下我再将用到的jjar包和eclipse设置告诉一下,话不多数上截图

        

    这两个jar缺一不可的,jar包的话可以去

       https://mvnrepository.com/artifact/com.drewnoakes/metadata-extractor/2.6.2

       https://mvnrepository.com/artifact/com.adobe.xmp/xmpcore/5.1.2 

     里下载这两个,在文件类型里选择jar还是pom

      

    如果eclipse(MyEclipse同理)在打印照片时,引入的

    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    报错的话:
    Access restriction: The type JPEGImageEncoder is not accessible due to restriction on required library C:Javajre1.6.0_07lib t.jar


    此时解决办法:
    Eclipse默认把这些受访问限制的API设成了ERROR。只要把Windows-Preferences-Java-Complicer-Errors/Warnings里面的Deprecated and restricted API中的Forbidden references(access rules)选为Warning就可以编译通过。

    最后的最后,将这两个合二为一,我需要的是拍摄时间以及经纬度,那么以下:

      

    
    
    /**
     * @author yc  
     * @date 2019年3月8日 
     */
    package photo;
    
    import com.drew.imaging.ImageMetadataReader;
    import com.drew.imaging.ImageProcessingException;
    import com.drew.imaging.jpeg.JpegMetadataReader;
    import com.drew.metadata.Directory;
    import com.drew.metadata.Metadata;
    import com.drew.metadata.Tag;
    import com.sun.image.codec.jpeg.JPEGCodec;
    import com.sun.image.codec.jpeg.JPEGEncodeParam;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileOutputStream;
    
    import javax.swing.ImageIcon;
    
    public class ExifTester {
    
        public static void main(String[] args) throws ImageProcessingException, Exception {
            File file = new File("D:\test\photo\IMG_954.jpg");
            if(file.exists()){
                String imageMsg = printImageTags(file);
                boolean result = ImageEdit.createStringMark(file.getPath(), imageMsg,"D:\test\B.jpg");
                System.out.println("iamgeMsg:----->" + imageMsg+"打印到照片上:"+result);
            }else{
                System.out.println("图片不存在或错误,请核实!");
            }
        }
    
        /**
         * 读取照片里面的信息
         */
        private static String printImageTags(File jpegFile) throws ImageProcessingException, Exception {
            //File jpegFile = new File(filePath);
            Metadata metadata = JpegMetadataReader.readMetadata(jpegFile);
            String imageToString = "";
            imagesEntity image = new imagesEntity();
            for (Directory directory : metadata.getDirectories()) {
                for (Tag tag : directory.getTags()) {
                    // System.out.print("name : " + tag.getTagName() + "  -->");
                    // System.out.println("desc : " + tag.getDescription());
    
                    String tagName = tag.getTagName();
                    String desc = tag.getDescription();
    
                    if (tagName.equals("Image Height")) {
                        System.out.println("图片高度: " + desc);
                    } else if (tagName.equals("Image Width")) {
                        System.out.println("图片宽度: " + desc);
                    } else if (tagName.equals("Date/Time Original")) {
                        image.setDateOriginal(desc);
                        System.out.println("拍摄时间1: " + desc);
                    } else if (tagName.equals("Date/Time Digitized")) {
                        image.setDateDigitized(desc);
                        System.out.println("拍摄时间2: " + desc);
                    } else if (tagName.equals("GPS Latitude")) {
                        System.err.println("纬度 : " + desc);
                        image.setLatitude(pointToLatlong(desc));
                        System.err.println("纬度(度分秒格式) : " + pointToLatlong(desc));
                    } else if (tagName.equals("GPS Longitude")) {
                        System.err.println("经度: " + desc);
                        image.setLongitude(pointToLatlong(desc));
                        System.err.println("经度(度分秒格式): " + pointToLatlong(desc));
                    }
                }
            }
            imageToString = image.getLongitude() + "," + image.getLatitude() + "  " + image.getDateOriginal();
            System.err.println("照片内获取信息为" + imageToString);
            return imageToString;
        }
    
        /**
         * 经纬度格式 转换为 度分秒格式 ,如果需要的话可以调用该方法进行转换
         * 
         * @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 filePath 源图片路径
         * @param markContent 图片中添加内容
         * @param outPath  输出图片路径
         * 字体颜色等在函数内部实现的
       */
        //给jpg添加文字
        public static boolean createStringMark(String filePath,String markContent,String outPath) 
        { 
        ImageIcon imgIcon=new ImageIcon(filePath); 
        Image theImg =imgIcon.getImage(); 
        int width=theImg.getWidth(null)==-1?200:theImg.getWidth(null); 
        int height= theImg.getHeight(null)==-1?200:theImg.getHeight(null); 
        System.out.println(width);
        System.out.println(height);
        System.out.println(theImg.toString());
        BufferedImage bimage = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB); 
        Graphics2D g=bimage.createGraphics(); 
        
        Color mycolor = Color.red; 
        g.setColor(mycolor); 
        g.setBackground(Color.red); 
        g.drawImage(theImg, 0, 0, null ); 
        g.setFont(new Font("宋体",Font.PLAIN,80)); //字体、字型、字号 
        g.drawString(markContent,width/80,height-height/100); //画文字位置 
        g.dispose(); 
        try 
        { 
        FileOutputStream out=new FileOutputStream(outPath); //先用一个特定的输出文件名 
        JPEGImageEncoder encoder =JPEGCodec.createJPEGEncoder(out); 
        JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage); 
        param.setQuality(100, true);  //
        encoder.encode(bimage, param); 
        out.close(); 
        } 
        catch(Exception e) 
        { return false; } 
        return true; 
        } 
    }

    信息实体:

      

    /**
     * @author yc  
     * @date 2019年3月8日 
     */
    package photo;
    
    /**
     * @author yang.cheng  
     * @date 2019年3月8日 
     */
    public class imagesEntity {
        private String DateOriginal;
        private String DateDigitized;
        private String Latitude;
        private String Longitude;
        public String getDateOriginal() {
            return DateOriginal;
        }
        public void setDateOriginal(String dateOriginal) {
            DateOriginal = dateOriginal;
        }
        public String getDateDigitized() {
            return DateDigitized;
        }
        public void setDateDigitized(String dateDigitized) {
            DateDigitized = dateDigitized;
        }
        public String getLatitude() {
            return Latitude;
        }
        public void setLatitude(String latitude) {
            Latitude = latitude;
        }
        public String getLongitude() {
            return Longitude;
        }
        public void setLongitude(String longitude) {
            Longitude = longitude;
        }
        @Override
        public String toString() {
            return "imagesEntity [DateOriginal=" + DateOriginal + ", DateDigitized=" + DateDigitized + ", Latitude=" + Latitude + ", Longitude="
                    + Longitude + "]";
        }
        
    
    }
  • 相关阅读:
    [HNOI2006]鬼谷子的钱袋
    一日游与两道题
    [HNOI2009]梦幻布丁
    [Ahoi2009]self 同类分布
    50 days before NOI2017
    Topcoder SRM 606 div1题解
    Topcoder SRM 605 div1 题解
    Topcoder SRM 604 div1题解
    Topcoder SRM 603 div1题解
    Topcoder SRM 602 div1题解
  • 原文地址:https://www.cnblogs.com/yangchengdebokeyuan/p/10510323.html
Copyright © 2011-2022 走看看