如何获得图像的高度和宽度使用java?
除了使用ImageIO.read获取图像的高度和宽度,还有其他的方法吗?
因为我遇到了locking线程的问题。
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重写的好post,它会抛出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); Iterator<ImageReader> iter = 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()); }
我想我的代表不够高,我认为值得回复。
我发现了另一种读取图像大小(更通用)的方法。 您可以与ImageReaders配合使用ImageIO类。 这里是示例代码:
private Dimension getImageDim(final String path) { Dimension result = null; String suffix = this.getFileSuffix(path); Iterator<ImageReader> iter = 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是返回没有“。”的path扩展的方法。 所以例如: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; }
这个解决scheme非常快,因为只从图像中读取图像大小,而不是整个图像。 我testing了它,并没有比较ImageIO.read性能。 我希望有人会觉得这有用。
我尝试使用列出的各种方法来testing性能。 很多因素会影响结果,因此很难做出严格的testing。 我准备了两个文件夹,一个用330 jpg文件,另一个用330 png文件。 两种情况下的平均文件大小都是4Mb。 然后我为每个文件调用getDimension。 getDimension方法和每个图像types的每个实现都单独testing(单独运行)。 这是我得到的执行时间(第一个数字为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二进制数据作为文件加载,并自己parsingjpeg头文件。 你正在寻找的是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.
有关标题的更多信息,请查看wikipedia的jpeg条目或者我在这里获得了上述信息。
我使用了一个类似于下面的代码的方法,我从这个post在太阳论坛上得到了:
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]))); }
}
我发现这个免费的课,完美的工作:
http://jaimonmathew.wordpress.com/2011/01/29/simpleimageinfo/
简单的方法:
BufferedImage readImage = null; try { readImage = ImageIO.read(new File(your path); int h = readImage.getHeight(); int w = readImage.getWidth(); } catch (Exception e) { readImage = null; }
尝试使用ImageInfo免费提供的类,我用它来达到同样的目的:
http://linux.softpedia.com/get/Multimedia/Graphics/ImageInfo-19792.shtml
你可以使用工具包,不需要ImageIO
Image image = Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath()); int width = image.getWidth(null); int height = image.getHeight(null);
如果你不想处理图像的加载的话
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath()); int height = imageIcon.getIconHeight(); int width = imageIcon.getIconWidth();
使用ImageIO.read获取缓冲图像是一个非常繁重的方法,因为它会在内存中创build一个完整的未压缩的图像副本。 对于PNG的你也可以使用pngj和代码:
if (png) PngReader pngr = new PngReader(file); width = pngr.imgInfo.cols; height = pngr.imgInfo.rows; pngr.close(); }
您可以使用java获取BufferedImage对象的图像宽度和高度。
public void setWidthAndHeightImage(FileUploadEvent event){ byte[] imageTest = event.getFile().getContents(); baiStream = new ByteArrayInputStream(imageTest ); BufferedImage bi = ImageIO.read(baiStream); //get width and height of image int imageWidth = bi.getWidth(); int imageHeight = bi.getHeight(); }
要获得emf文件的大小,而不使用EMF图像阅读器,您可以使用代码:
Dimension getImageDimForEmf(final String path) throws IOException { ImageInputStream inputStream = new FileImageInputStream(new File(path)); inputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN); // Skip magic number and file size inputStream.skipBytes(6*4); int left = inputStream.readInt(); int top = inputStream.readInt(); int right = inputStream.readInt(); int bottom = inputStream.readInt(); // Skip other headers inputStream.skipBytes(30); int deviceSizeInPixelX = inputStream.readInt(); int deviceSizeInPixelY = inputStream.readInt(); int deviceSizeInMlmX = inputStream.readInt(); int deviceSizeInMlmY = inputStream.readInt(); int widthInPixel = (int) Math.round(0.5 + ((right - left + 1.0) * deviceSizeInPixelX / deviceSizeInMlmX) / 100.0); int heightInPixel = (int) Math.round(0.5 + ((bottom-top + 1.0) * deviceSizeInPixelY / deviceSizeInMlmY) / 100.0); inputStream.close(); return new Dimension(widthInPixel, heightInPixel); }