如何使用java获取图像的高度和宽度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/672916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get image height and width using java?
提问by
Is there any other way besides using ImageIO.readto get image height and width?
除了使用ImageIO.read获取图像高度和宽度之外,还有其他方法吗?
Because I encounter an issue that locks up the thread.
因为我遇到了锁线程的问题。
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)
This error only occurs on a Sun app server and therefore I suspect that it is a Sun bug.
此错误仅发生在 Sun 应用服务器上,因此我怀疑它是 Sun 错误。
回答by joinJpegs
You can load jpeg binary data as a file and parse the jpeg headers yourself. The one you are looking for is the 0xFFC0 or Start of Frame header:
您可以将 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.
For more info about the headers check out wikipedia's jpeg entry or I got the above info here.
有关标题的更多信息,请查看维基百科的 jpeg 条目,或者我在此处获得了上述信息。
I used a method similar to the code below which I got from this postat the sun forums:
我使用了一种类似于以下代码的方法,该代码是从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])));
}
}
}
回答by user350756
I have found another way to read an image size (more generic). You can use ImageIO class in cooperation with ImageReaders. Here is the sample code:
我找到了另一种读取图像大小的方法(更通用)。您可以将 ImageIO 类与 ImageReaders 配合使用。这是示例代码:
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;
}
Note that getFileSuffix is method that returns extension of path without "." so e.g.: png, jpg etc. Example implementation is:
请注意,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;
}
This solution is very quick as only image size is read from the file and not the whole image. I tested it and there is no comparison to ImageIO.read performance. I hope someone will find this useful.
此解决方案非常快,因为仅从文件中读取图像大小而不是整个图像。我对其进行了测试,与 ImageIO.read 的性能没有可比性。我希望有人会发现这很有用。
回答by Apurv
Here is something very simple and handy.
这里有一些非常简单和方便的东西。
BufferedImage bimg = ImageIO.read(new File(filename));
int width = bimg.getWidth();
int height = bimg.getHeight();
回答by user1215499
Simple way:
简单的方法:
BufferedImage readImage = null;
try {
readImage = ImageIO.read(new File(your path);
int h = readImage.getHeight();
int w = readImage.getWidth();
} catch (Exception e) {
readImage = null;
}
回答by Andrew Taylor
This is a rewrite of the great post by @Kay, which throws IOException and provides an early exit:
这是对@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);
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());
}
I guess my rep is not high enough for my input to be considered worthy as a reply.
我想我的代表不够高,不足以让我的意见被认为值得作为回复。
回答by Karussell
You could use the Toolkit, no need for ImageIO
你可以使用 Toolkit,不需要 ImageIO
Image image = Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath());
int width = image.getWidth(null);
int height = image.getHeight(null);
If you don't want to handle the loading of the image do
如果您不想处理图像的加载,请执行
ImageIcon imageIcon = new ImageIcon(file.getAbsolutePath());
int height = imageIcon.getIconHeight();
int width = imageIcon.getIconWidth();
回答by mp31415
I tried to test performance using some of the various approaches listed. It's hard to make a rigorous test as many factors affect the result. I prepared two folders, one with 330 jpg files and another one with 330 png files. The average file size was 4Mb in both cases. Then I called getDimension for each file. Each implementation of getDimension method and each image type was tested separately (separate run). Here is the execution times that I got (first number for jpg, second number for png):
我尝试使用列出的各种方法来测试性能。由于影响结果的因素很多,因此很难进行严格的测试。我准备了两个文件夹,一个包含 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
It's obvious that some methods load the whole file in order to get dimensions while others get by just reading some header information from the image. I think these numbers may be useful when application performance is critical.
很明显,有些方法加载整个文件以获取尺寸,而其他方法仅通过从图像中读取一些标题信息来获取。我认为当应用程序性能至关重要时,这些数字可能很有用。
Thank you everyone for the contribution to this thread - very helpful.
感谢大家对这个线程的贡献 - 非常有帮助。
回答by Jessi
To get a Buffered Image with ImageIO.read is a very heavy method, as it's creating a complete uncompressed copy of the image in memory. For png's you may also use pngj and the code:
使用 ImageIO.read 获取缓冲图像是一种非常繁重的方法,因为它正在内存中创建图像的完整未压缩副本。对于 png,您也可以使用 pngj 和代码:
if (png)
PngReader pngr = new PngReader(file);
width = pngr.imgInfo.cols;
height = pngr.imgInfo.rows;
pngr.close();
}
回答by Viktor Sirotin
To get size of emf file without EMF Image Reader you can use code:
要在没有 EMF Image Reader 的情况下获取 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);
}
回答by KIBOU Hassan
You can get width and height of image with BufferedImage object using java.
您可以使用 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();
}