除了使用ImageIO.read获取图像高度和宽度之外还有其他方法吗?
因为我遇到了锁定线程的问题.
at com.sun.medialib.codec.jpeg.Decoder.njpeg_decode(Native Method) at com.sun.medialib.codec.jpeg.Decoder.decode(Decoder.java:87) at com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader.decode(CLibJPEGImageReader.java:73) - locked <0xd96fb668> (a com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader) at com.sun.media.imageioimpl.plugins.clib.CLibImageReader.getImage(CLibImageReader.java:320) - locked <0xd96fb668> (a com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader) at com.sun.media.imageioimpl.plugins.clib.CLibImageReader.read(CLibImageReader.java:384) - locked <0xd96fb668> (a com.sun.media.imageioimpl.plugins.jpeg.CLibJPEGImageReader) at javax.imageio.ImageIO.read(ImageIO.java:1400) at javax.imageio.ImageIO.read(ImageIO.java:1322)
此错误仅发生在Sun应用服务器上,因此我怀疑它是Sun错误.
这是非常简单和方便的东西.
BufferedImage bimg = ImageIO.read(new File(filename)); int width = bimg.getWidth(); int height = bimg.getHeight();
这是@Kay改写了一篇伟大的帖子,它会抛出IOException并提供早期退出:
/** * Gets image dimensions for given file * @param imgFile image file * @return dimensions of image * @throws IOException if the file is not a known image */ public static Dimension getImageDimension(File imgFile) throws IOException { int pos = imgFile.getName().lastIndexOf("."); if (pos == -1) throw new IOException("No extension for file: " + imgFile.getAbsolutePath()); String suffix = imgFile.getName().substring(pos + 1); Iteratoriter = ImageIO.getImageReadersBySuffix(suffix); while(iter.hasNext()) { ImageReader reader = iter.next(); try { ImageInputStream stream = new FileImageInputStream(imgFile); reader.setInput(stream); int width = reader.getWidth(reader.getMinIndex()); int height = reader.getHeight(reader.getMinIndex()); return new Dimension(width, height); } catch (IOException e) { log.warn("Error reading: " + imgFile.getAbsolutePath(), e); } finally { reader.dispose(); } } throw new IOException("Not a known image file: " + imgFile.getAbsolutePath()); }
我想我的代表不够高,我的输入被认为是值得回复的.
我找到了另一种读取图像大小的方法(更通用).您可以与ImageReader一起使用ImageIO类.以下是示例代码:
private Dimension getImageDim(final String path) { Dimension result = null; String suffix = this.getFileSuffix(path); Iteratoriter = ImageIO.getImageReadersBySuffix(suffix); if (iter.hasNext()) { ImageReader reader = iter.next(); try { ImageInputStream stream = new FileImageInputStream(new File(path)); reader.setInput(stream); int width = reader.getWidth(reader.getMinIndex()); int height = reader.getHeight(reader.getMinIndex()); result = new Dimension(width, height); } catch (IOException e) { log(e.getMessage()); } finally { reader.dispose(); } } else { log("No reader found for given format: " + suffix)); } return result; }
请注意,getFileSuffix是返回路径扩展而没有"."的方法.例如:png,jpg等.示例实现是:
private String getFileSuffix(final String path) { String result = null; if (path != null) { result = ""; if (path.lastIndexOf('.') != -1) { result = path.substring(path.lastIndexOf('.')); if (result.startsWith(".")) { result = result.substring(1); } } } return result; }
此解决方案非常快,因为只从文件中读取图像大小而不是整个图像.我测试了它,并没有与ImageIO.read性能进行比较.我希望有人会觉得这很有用.
我尝试使用列出的各种方法测试性能.由于许多因素会影响结果,因此很难进行严格的测试.我准备了两个文件夹,一个包含330个jpg文件,另一个包含330个png文件.两种情况下的平均文件大小为4Mb.然后我为每个文件调用了getDimension.getDimension方法的每个实现和每个图像类型分别进行了测试(单独运行).这是我得到的执行时间(jpg的第一个数字,png的第二个数字):
1(Apurv) - 101454ms, 84611ms 2(joinJpegs) - 471ms, N/A 3(Andrew Taylor) - 707ms, 68ms 4(Karussell, ImageIcon) - 106655ms, 100898ms 5(user350756) - 2649ms, 68ms
很明显,有些方法会加载整个文件以获取尺寸,而其他方法只需从图像中读取一些标题信息即可.我认为当应用程序性能至关重要时,这些数字可能很有用.
谢谢大家对这个主题的贡献 - 非常有帮助.
您可以将jpeg二进制数据作为文件加载并自己解析jpeg头文件.您要查找的是0xFFC0或帧起始标头:
Start of frame marker (FFC0) * the first two bytes, the length, after the marker indicate the number of bytes, including the two length bytes, that this header contains * P -- one byte: sample precision in bits (usually 8, for baseline JPEG) * Y -- two bytes * X -- two bytes * Nf -- one byte: the number of components in the image o 3 for color baseline JPEG images o 1 for grayscale baseline JPEG images * Nf times: o Component ID -- one byte o H and V sampling factors -- one byte: H is first four bits and V is second four bits o Quantization table number-- one byte The H and V sampling factors dictate the final size of the component they are associated with. For instance, the color space defaults to YCbCr and the H and V sampling factors for each component, Y, Cb, and Cr, default to 2, 1, and 1, respectively (2 for both H and V of the Y component, etc.) in the Jpeg-6a library by the Independent Jpeg Group. While this does mean that the Y component will be twice the size of the other two components--giving it a higher resolution, the lower resolution components are quartered in size during compression in order to achieve this difference. Thus, the Cb and Cr components must be quadrupled in size during decompression.
有关标题的更多信息,请查看维基百科的jpeg条目,或者我在此处获得了上述信息.
我使用了类似于下面代码的方法,我在sun论坛上从这篇文章中得到了这个方法:
import java.awt.Dimension; import java.io.*; public class JPEGDim { public static Dimension getJPEGDimension(File f) throws IOException { FileInputStream fis = new FileInputStream(f); // check for SOI marker if (fis.read() != 255 || fis.read() != 216) throw new RuntimeException("SOI (Start Of Image) marker 0xff 0xd8 missing"); Dimension d = null; while (fis.read() == 255) { int marker = fis.read(); int len = fis.read() << 8 | fis.read(); if (marker == 192) { fis.skip(1); int height = fis.read() << 8 | fis.read(); int width = fis.read() << 8 | fis.read(); d = new Dimension(width, height); break; } fis.skip(len - 2); } fis.close(); return d; } public static void main(String[] args) throws IOException { System.out.println(getJPEGDimension(new File(args[0]))); }
}
简单方法:
BufferedImage readImage = null; try { readImage = ImageIO.read(new File(your path); int h = readImage.getHeight(); int w = readImage.getWidth(); } catch (Exception e) { readImage = null; }