电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

高效获取jpeg图片的尺寸


发布日期:2018/5/12
 

获取图片的尺寸有三种方法

将整个图片文件加载成 BufferedImage 后获取其尺寸

用 ImageReader 快捷获取

即下文所陈述的方式

做过简陋的测试效率自 逐步递增

ImageInfojava

/**

* @author kodeyang

*/

public class ImageInfo {

private int height;

private int width;

public ImageInfo(int height int width) {

super();

thisheight = height;

thiswidth = width;

}

public int getWidth() {

return width;

}

public int getHeight() {

return height;

}

@Override

public String toString() {

return height: + height + width: + width;

}

}

import javaioIOException;

import javaioInputStream;

/**

* @author yangwei

*

*/

public class JpegInfoReader {

private static final byte TAG_START = (byte) xff;

private static final byte START_OF_IMAGE = (byte) xd;

private static final byte END_OF_IMAGE = (byte) xd;

private static final byte START_OF_FRAME = (byte) xc;

private static final byte RESTART_MODULO_START = (byte) xd;

private static final byte RESTART_MODULO_END = (byte) xd;

private static final byte START_OF_SCAN = (byte) xda;

public static ImageInfo getImageInfo(InputStream in) throws IOException {

// : store JPEG tag

// : store JPEG tag length

// : store JPEG image height

// : store JPEG image width

byte[] seg = new byte[];

// read JPEG START_OF_IMAGE tag

if (inread(seg ) == ) {

return null;

}

// if the first two bytes is not xff xd

// that is the image format is not JPEG

if (seg[] != TAG_START || seg[] != START_OF_IMAGE) {

return null;

}

while (true) {

// read JPEG data tag offset must be xff

if (inread(seg ) == ) {

return null;

}

// if tag does not start with xff

// the image format is not JPEG

if (seg[] != TAG_START) {

return null;

}

// Ignore JPEG RESTART_MODULO tag

if (seg[] >= RESTART_MODULO_START && seg[] <= RESTART_MODULO_END) {

continue;

}

// find JPEG format START_OF_SCAN part

// data that starts with poisition is JPEG compression image data

// that never contains image meta information

if (seg[] == START_OF_SCAN) {

return null;

}

// find JPEG format END_OF_IMAGE tag finish scan

if (seg[] == END_OF_IMAGE) {

return null;

}

// read JPEG data tag length

if (inread(seg ) == ) {

return null;

}

// find START_OF_FRAME tag

if (seg[] == START_OF_FRAME) {

break;

}

// skip JPEG data segement

byte[] skip = new byte[toInt(seg ) ];

if (inread(skip) == ) {

return null;

}

}

// ignore JPEG image precision byte

if (inread() == ) {

return null;

}

// read JPEG image height and width bytes

if (inread(seg ) == ) {

return null;

}

return new ImageInfo(toInt(seg ) toInt(seg ));

}

private static int toInt(byte[] bys int start) {

return ((bys[start] & xff) << ) | (bys[start + ] & xff);

}

}

import javaioFileInputStream;

import javaioIOException;

import javaioInputStream;

/**

* @author yangwei

*

*/

public class JpegInfoReaderUsage {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

InputStream in = null;

try {

in = new FileInputStream(d:/imagesjpg);

ImageInfo info = JpegInfoReadergetImageInfo(in);

Systemoutprintln(info);

} finally {

if (in != null) {

inclose();

}

}

}

}

提问

class 前面带 static 是什么用法呢

另外宽高都拿到了为什么还要将 宽高丢到一个 ImageInfo 对象里面呢直接使用整形数组的结果不是更快捷?

回答

内部类使用 static 的话一般说明这个内部类不需要使用到外部类中的任何成员变量或者成员方法也就是说这个内部类相对于较为独立

如果有需要使用到外部类中数据的话则需要把 static 去掉不对外部类数据进行引用时内部类应使用 static 类

对于这个问题举个很简单的例子如果我还想获取图像长宽的 DPI 信息以及颜色深度信息或者是 JPEG 中 Exif 信息的话那使用 int[] 就没办法表示了

在面向对象程序设计中返回值应尽量少使用 int[] String[] Map<String Object> 之类的返回值因为这样的返回值不是自描述的

为什么 int[] 是表示长度呢?int[] 就不能表示宽度么?

我很能理解你认为返回 int[] 的理由是什么可能是因为 new 一个对象比较耗时和占用内存空间吧?

实际上并不是这样的new 一个对象而且这个类的构造中没有任何复杂耗时的操作对于系统消耗来说可以忽略不计而对于 HotSpot 的 JVM 而言其内存分配的速度是大于 C 语言中 malloc 的内存分配速度

在 HotSpot 的 JVM 中一个 new 操作只占用了十几个 CPU 指令的时间new 一个对象和 new 一个 int 数据的效率是等价的

另外new 一个对象所分配的内存更是可以忽略不计了只是在 JVM 的 PermGen 方法区中多存放一些类的信息以及方法的信息

上一篇:JTree用法及JTree使用经验总结

下一篇:在String中==和equals的区别