Java-图片格式

Java

图片格式

这两天在处理网络图片数据时,需要对不同格式的图片采用不用的处理办法,这就需要掌握图片的格式识别。结合这两天的学习内容,对其进行总结,以备将来不时之需。

通过 url

常见的图片格式有jpg(jpeg),png,gif这三种,可以分别通过字符创的contains(“jpg”);contains(“png”); contains(“gif”) 来获取对应格式的图片,这种方法我认为是简单粗暴的,识别率一般情况下也会很高,但是,有的url中包含的 jpg 这个字符,却是一个 gif 格式的图片,比如说下面这个链接(http://img4.imgtn.bdimg.com/it/u=14736324,2917249387&fm=214&gp=0.jpg),他实质上是一个 gif 文件,可是如两种显示它是一个 jpg 文件。这种情况下直接通过 url 去识别就不正确了,所以就需要下面的解决方法。

通过二进制流

通过二进制流我总结有两种解决方法。

  • 代码示例
package com.myapp.image;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;

/**
 * Created by lionel on 16/12/2.
 */
public class ImageFormat {
    //第一种方法,只适用于判断 gif 格式和 png 格式
    public static String getImageFormat(String url) {
        String imageFormat = "";
        HttpURLConnection conn;
        InputStream inputStream = null;
        byte[] buffer = new byte[4];
        int len;
        try {
            URL url1 = new URL(url);
            conn = (HttpURLConnection) url1.openConnection();
            inputStream = conn.getInputStream();
            len = inputStream.read(buffer);
            if (len == 4 && buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F') {
                imageFormat = "gif";
            } else if (len == 4 && buffer[1] == 'P' && buffer[2] == 'N' && buffer[3] == 'G') {
                imageFormat = "png";
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return imageFormat;
    }

    //第二种方法:使用 javax.ImageIo类
    public static String getImageFormat2(String url) {
        String picFormat = "";
        try {
            File file = File.createTempFile("tmp", "jpg");
            URL url1 = new URL(url);
            URLConnection connection = url1.openConnection();
            InputStream inputStream = connection.getInputStream();
            byte[] bytes = new byte[1024];
            int len;
            OutputStream outputStream = new FileOutputStream(file);
            while ((len = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
            }
            outputStream.close();
            inputStream.close();
            ImageInputStream imageInputStream = ImageIO.createImageInputStream(file);
            Iterator iterator = ImageIO.getImageReaders(imageInputStream);
            if (!iterator.hasNext()) {
                throw new RuntimeException("No readers found!");
            }
            ImageReader reader = iterator.next();
            picFormat = reader.getFormatName();


        } catch (IOException e) {
            e.printStackTrace();
        }
        return picFormat;
    }

    //第三种方法:使用metadata-extractor工具包
    public static String getImageFormat3(String url) {
        HttpURLConnection conn = null;
        InputStream is = null;
        try {
            URL uri = new URL(url);
            conn = (HttpURLConnection) uri.openConnection();
            is = conn.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            FileType fileType = com.drew.imaging.FileTypeDetector.detectFileType(bis);
            return fileType.name();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 测试代码:
@Test
public void test() {
        System.out.println(ImageFormat.getImageFormat("http://heilongjiang.sinaimg.cn/2016/0713/U11780P1274DT20160713151843.gif"));//gif
        System.out.println(ImageFormat.getImageFormat("http://img01.lianzhong.com/upload/newbbs/2013/03/06/562/128564577804426.png"));//png
}

@Test
public void test2() {
        System.out.println(ImageFormat.getImageFormat2("http://mmbiz.qpic.cn/mmbiz_gif/bTTVNfzmRM8Xmc0YsntZGSlBZCnPYLOBLTqXAoac53kRUJU3wUic0qQhJRCxYpf6F4g8MYfIXaY2SOwcwQnxXSw/0?wx_fmt=gif"));//gif
        System.out.println(ImageFormat.getImageFormat2("http://mmbiz.qpic.cn/mmbiz_jpg/bTTVNfzmRM8Xmc0YsntZGSlBZCnPYLOB2msB91o8lzwVK5kAtibh93FE9YqwsTaTU6SZUgRUwfdgD3Bxqib3v9hw/0?wx_fmt=jpeg"));//JPEG
        System.out.println(ImageFormat.getImageFormat2("http://www.pooban.com/forum/attachments/month_0803/20080312_efbadda4f99208eddd17Wvc0F7LaegE2.png"));//png
}

@Test
public void test3(){
        System.out.println(ImageFormat.getImageFormat3("http://img01.lianzhong.com/upload/newbbs/2013/03/06/562/128564577804426.png"));
        System.out.println(ImageFormat.getImageFormat3("http://heilongjiang.sinaimg.cn/2016/0713/U11780P1274DT20160713151843.gif"));
        System.out.println(ImageFormat.getImageFormat3("http://mmbiz.qpic.cn/mmbiz_jpg/bTTVNfzmRM8Xmc0YsntZGSlBZCnPYLOB2msB91o8lzwVK5kAtibh93FE9YqwsTaTU6SZUgRUwfdgD3Bxqib3v9hw/0?wx_fmt=jpeg"));
}

第一种方法中,如果图片的格式是 gif 的,则对应的二进制流的buffer[0],buffer[1],buffer[2]分别返回的是’G’,’I’,’F’的 Ascii 码;如果图片的格式是 png 的,则对应的二进制流的buffer[1],buffer[2],buffer[3]分别返回的是’P’,’N’,’G’的 Ascii 码,有兴趣的同学可以自己测试下,但是如果是 jpeg 或者 jpg 的,则对应的流,就我自己而言,无法找出规律。第二种方法是把文件暂时写到本地文件中,然后通过ImageIO类中的方法来获取文件对应的格式。第三种方法:使用metadata-extractor工具包。其实质和第一种方法一样,通过阅读文件的前几个字节流来判断图片格式。要想了解具体过程可以去github进行阅读。

webp 图片

最后,我想讲一下 google 最近出的一种图片格式-webp,这种格式的图片有些浏览器不支持查看,如 safari 和 firefox ,以下的 url 就不能查看:
http://mmbiz.qpic.cn/mmbiz/HZIIEPB0r1zh8HuU1Ytk9NaYhEJkXticqicCu4zTvEABpvINyI1FfcHEfEic7sGK4JLaZ9bOGJ6jmWuZmKTYH63HQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5

http://mmbiz.qpic.cn/mmbiz/SRbibgDh1zOswibjegzOHnwyGOuXexaK4ggpHFejhdiaN2eQz6pGvZhFgPEicziaTDEQBmaEk1bdGVeyONe2YC0qoSQ/640?wxfrom=5&wx_fmt=jpeg&tp=webp

http://mmbiz.qpic.cn/mmbiz/SRbibgDh1zOswibjegzOHnwyGOuXexaK4gZ4WMa8hdg2iacZic3SaYA2NEcjjjeGZShd3FSbzVgM3ejXVnOWXTIvPQ/640?wxfrom=5&wx_fmt=jpeg&tp=webp

有什么办法可以查看了?
告诉一个小窍门,就是把 url 中 &tp=webp 这一块去掉就可以了
上面的三个 url 修改后如下所示:

http://mmbiz.qpic.cn/mmbiz/HZIIEPB0r1zh8HuU1Ytk9NaYhEJkXticqicCu4zTvEABpvINyI1FfcHEfEic7sGK4JLaZ9bOGJ6jmWuZmKTYH63HQ/640?wx_fmt=jpeg&wxfrom=5

http://mmbiz.qpic.cn/mmbiz/SRbibgDh1zOswibjegzOHnwyGOuXexaK4ggpHFejhdiaN2eQz6pGvZhFgPEicziaTDEQBmaEk1bdGVeyONe2YC0qoSQ/640?wxfrom=5&wx_fmt=jpeg

http://mmbiz.qpic.cn/mmbiz/SRbibgDh1zOswibjegzOHnwyGOuXexaK4gZ4WMa8hdg2iacZic3SaYA2NEcjjjeGZShd3FSbzVgM3ejXVnOWXTIvPQ/640?wxfrom=5&wx_fmt=jpeg

这样就可以去 safari 和 firefox 下查看了。

还有另外一种方法,就是使用 webp-imageIo 对图片进行处理,具体内容可以去官网进行学习,下面附上我测试的代码:

public void test() {

    File file1 = new File("/usr/local/a.webp");
    File file = new File("/usr/local/b.jpg");
    try {
        BufferedImage image = ImageIO.read(file1);

        if (image != null) {
            ImageIO.write(image, "jpg", file);
        }
        System.out.println(image == null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意在官网中有这样一段介绍:

Ensure libwebp-imageio.so, libwebp-imageio.dylib or webp-imageio.dll is accessible on the Java native library path (java.library.path system property)

就是在执行代码前需要把根据你用的操作系统来选择其中的包,比如,mac 就选libwebp-imageio.dylib 放在你的java.library.path 路径下,要是不知道路径在哪的话,可以执行 System.out.println(System.getProperty(“java.library.path”))打印出来看看,然后把文件拷贝到其中一个路径下面就可以了。

你可能感兴趣的:(Java)