如何在java中获取图像的原始大小

时间:2017-09-22 06:17:12

标签: java image size

我试图在java中通过.length获取图像的大小。

然而,图像的原始大小比其高几个字节。

这是什么原因?是否有任何代码可以获得原始大小?

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.imageio.ImageIO;

public class Array {
    public static void main(String argv[]) throws IOException {
        String imageFile1 = "C:/Users/Desktop/4.jpg";

        File file = new File(imageFile1);
        BufferedImage originalImage = ImageIO.read(file);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(originalImage, "jpg", baos);
        byte[] imageInByte = baos.toByteArray();

        System.out.println("The length in bytes " + imageInByte.length);
    }
}

1 个答案:

答案 0 :(得分:0)

我认为这是关于jpeg文件头大小的。

如果要在复制图像文件时获得原始尺寸。 您只能使用文件复制而不是图像文件复制。

或者,如果你真的想要,你可以制作自己的jpeg库。

仅举一个例子, 这是使用java的NIO的旧式代码之一。

private static void fileCopy(String from, String to) {
    FileChannel fromCh = null;
    FileChannel toCh = null;
    FileInputStream fin = null;
    FileOutputStream fout = null;

    try {
        fin = new FileInputStream(new File(from));
        fromCh = fin.getChannel();
        fout = new FileOutputStream(new File(to));
        toCh = fout.getChannel();

        fromCh.transferTo(0, fin.available(), toCh);

    } catch (IOException e) {

        e.printStackTrace();
    } finally {
        if (fin != null)
            try {
                fin.close();
            } catch (IOException e) {

            }
        if (fout != null)
            try {
                fout.close();
            } catch (IOException e) {

            }

    }
}

您可以从原始文件中获取相同大小的文件。

enter image description here

检查以下参考站点:

https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format

我测试了它两个文件之间的区别,一个是原来的另一个是副本。我从谷歌搜索得到了一个jpeg图像。

我修改了一些代码形式here以分析jpeg头文件。 这是方法:

final public static ImageProperties getJpegProperties(File file) throws FileNotFoundException, IOException {
    BufferedInputStream in = null;
    try {
        in = new BufferedInputStream(new FileInputStream(file));

        // check for "magic" header
        byte[] buf = new byte[2];
        int count = in.read(buf, 0, 2);
        if (count < 2) {
            throw new RuntimeException("Not a valid Jpeg file!");
        }
        if ((buf[0]) != (byte) 0xFF || (buf[1]) != (byte) 0xD8) {
            throw new RuntimeException("Not a valid Jpeg file!");
        }

        int width = 0;
        int height = 0;
        char[] comment = null;

        boolean hasDims = false;
        boolean hasComment = false;
        int ch = 0;
        int totalHeaderLen = 0;

        while (ch != 0xDA && !(hasDims && hasComment)) {
            /* Find next marker (JPEG markers begin with 0xFF) */
            while (ch != 0xFF) {
                ch = in.read();
            }
            /* JPEG markers can be padded with unlimited 0xFF's */
            while (ch == 0xFF) {
                ch = in.read();
            }
            /* Now, ch contains the value of the marker. */

            int length = 256 * in.read();
            length += in.read();

            totalHeaderLen += length;

            if (length < 2) {
                throw new RuntimeException("Not a valid Jpeg file!");
            }
            /* Now, length contains the length of the marker. */

            if (ch >= 0xC0 && ch <= 0xC3) {
                in.read();
                height = 256 * in.read();
                height += in.read();
                width = 256 * in.read();
                width += in.read();
                for (int foo = 0; foo < length - 2 - 5; foo++) {
                    in.read();
                }
                hasDims = true;
            } else if (ch == 0xFE) {
                // that's the comment marker
                comment = new char[length - 2];
                for (int foo = 0; foo < length - 2; foo++)
                    comment[foo] = (char) in.read();
                hasComment = true;
            } else {
                // just skip marker
                for (int foo = 0; foo < length - 2; foo++) {
                    in.read();
                }
            }
        }

        if(comment == null) comment = "no comment".toCharArray();

        return (new ImageProperties(width, height, new String(comment), totalHeaderLen, "jpeg"));

    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
            }
        }
    }
}

主要方法是:

public static void main(String argv[]) throws IOException {
    String imageFile1 = "resource/4.jpg";
    String imageFile2 = "resource/4_jpg.jpg";

    //copyImage(imageFile1);

    ImageProperties origin = getJpegProperties(new File(imageFile1));
    ImageProperties copyed = getJpegProperties(new File(imageFile2));

    System.out.println("============ Original one ===========");
    System.out.println("comments(origin) : " + origin.getComments());
    System.out.println("Height(origin) : " + origin.getHeight());
    System.out.println("Width(origin) : " + origin.getWidth());
    System.out.println("Header Length(origin) : " + origin.getHeaderLen());
    //System.out.println("suffix(origin) : " + origin.getSuffix());
    System.out.println();
    System.out.println("============ Copy one ===========");
    System.out.println("comments(copy) : " + copyed.getComments());
    System.out.println("Height(copy) : " + copyed.getHeight());
    System.out.println("Width(copy) : " + copyed.getWidth());
    System.out.println("Header Length(copy) : " + copyed.getHeaderLen());
    //System.out.println("suffix(copy) : " + copyed.getSuffix());

}

我首先使用copyImage方法复制原始图像。

static BufferedImage copyImage(BufferedImage source) {
    BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
    Graphics g = b.getGraphics();
    g.drawImage(source, 0, 0, null);
    g.dispose();
    return b;
}

我可以在资源管理器中看到两个图像的区别。

enter image description here

运行程序时我得到了不同的标题大小。

输出:

============ Original one ===========
comments(origin) : no comment
Height(origin) : 534
Width(origin) : 800
Header Length(origin) : 21269

============ Copy one ===========
comments(copy) : no comment
Height(copy) : 534
Width(copy) : 800
Header Length(copy) : 603

标题长度不同,因为您可以看到结果。

这是完整的测试代码。

package stackoverflow;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;


public class Misc {
    public static void main(String argv[]) throws IOException {
        String imageFile1 = "resource/4.jpg";
        String imageFile2 = "resource/4_jpg.jpg";
        String imageFile3 = "resource/4_org.jpg";

        fileCopy(imageFile1, imageFile3);
        //copyImage(imageFile1);

        ImageProperties origin = getJpegProperties(new File(imageFile1));
        ImageProperties copyed = getJpegProperties(new File(imageFile2));

        System.out.println("============ Original one ===========");
        System.out.println("comments(origin) : " + origin.getComments());
        System.out.println("Height(origin) : " + origin.getHeight());
        System.out.println("Width(origin) : " + origin.getWidth());
        System.out.println("Header Length(origin) : " + origin.getHeaderLen());
        //System.out.println("suffix(origin) : " + origin.getSuffix());
        System.out.println();
        System.out.println("============ Copy one ===========");
        System.out.println("comments(copy) : " + copyed.getComments());
        System.out.println("Height(copy) : " + copyed.getHeight());
        System.out.println("Width(copy) : " + copyed.getWidth());
        System.out.println("Header Length(copy) : " + copyed.getHeaderLen());
        //System.out.println("suffix(copy) : " + copyed.getSuffix());

    }

    static class ImageProperties {
        private final int width;
        private final int height;
        private final String comments;
        private final int headerLen;
        private final String suffix;

        public ImageProperties(
            final int width, final int height, final String comments, final int headerLen,
            final String suffix) 
        {
            this.width = width;
            this.height = height;
            this.comments = comments;
            this.suffix = suffix;
            this.headerLen = headerLen;
        }

        public int getWidth() {
            return width;
        }

        public int getHeight() {
            return height;
        }

        public String getComments() {
            return comments;
        }

        public String getSuffix() {
            return suffix;
        }

        public int getHeaderLen() {
            return headerLen;
        }

    }

    final public static ImageProperties getJpegProperties(File file) throws FileNotFoundException, IOException {
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));

            // check for "magic" header
            byte[] buf = new byte[2];
            int count = in.read(buf, 0, 2);
            if (count < 2) {
                throw new RuntimeException("Not a valid Jpeg file!");
            }
            if ((buf[0]) != (byte) 0xFF || (buf[1]) != (byte) 0xD8) {
                throw new RuntimeException("Not a valid Jpeg file!");
            }

            int width = 0;
            int height = 0;
            char[] comment = null;

            boolean hasDims = false;
            boolean hasComment = false;
            int ch = 0;
            int totalHeaderLen = 0;

            while (ch != 0xDA && !(hasDims && hasComment)) {
                /* Find next marker (JPEG markers begin with 0xFF) */
                while (ch != 0xFF) {
                    ch = in.read();
                }
                /* JPEG markers can be padded with unlimited 0xFF's */
                while (ch == 0xFF) {
                    ch = in.read();
                }
                /* Now, ch contains the value of the marker. */

                int length = 256 * in.read();
                length += in.read();

                totalHeaderLen += length;

                if (length < 2) {
                    throw new RuntimeException("Not a valid Jpeg file!");
                }
                /* Now, length contains the length of the marker. */

                if (ch >= 0xC0 && ch <= 0xC3) {
                    in.read();
                    height = 256 * in.read();
                    height += in.read();
                    width = 256 * in.read();
                    width += in.read();
                    for (int foo = 0; foo < length - 2 - 5; foo++) {
                        in.read();
                    }
                    hasDims = true;
                } else if (ch == 0xFE) {
                    // that's the comment marker
                    comment = new char[length - 2];
                    for (int foo = 0; foo < length - 2; foo++)
                        comment[foo] = (char) in.read();
                    hasComment = true;
                } else {
                    // just skip marker
                    for (int foo = 0; foo < length - 2; foo++) {
                        in.read();
                    }
                }
            }

            if(comment == null) comment = "no comment".toCharArray();

            return (new ImageProperties(width, height, new String(comment), totalHeaderLen, "jpeg"));

        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }
        }
    }

    static BufferedImage copyImage(BufferedImage source) {
        BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
        Graphics g = b.getGraphics();
        g.drawImage(source, 0, 0, null);
        g.dispose();
        return b;
    }


    private static void fileCopy(String from, String to) {
        FileChannel fromCh = null;
        FileChannel toCh = null;
        FileInputStream fin = null;
        FileOutputStream fout = null;

        try {
            fin = new FileInputStream(new File(from));
            fromCh = fin.getChannel();
            fout = new FileOutputStream(new File(to));
            toCh = fout.getChannel();

            fromCh.transferTo(0, fin.available(), toCh);

        } catch (IOException e) {

            e.printStackTrace();
        } finally {
            if (fin != null)
                try {
                    fin.close();
                } catch (IOException e) {

                }
            if (fout != null)
                try {
                    fout.close();
                } catch (IOException e) {

                }

        }
    }

}

所以,我认为java中的图像io库跳过了jpeg图像的额外信息。