如何使用java获取图像的高度和宽度?

发布于 2024-07-16 02:27:36 字数 1095 浏览 12 评论 0原文

除了使用 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 的错误。

Is there any other way besides using ImageIO.read to get image height and width?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

墨落成白 2024-07-23 02:27:36

这是非常简单和方便的东西。

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();

Here is something very simple and handy.

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();
メ斷腸人バ 2024-07-23 02:27:36

这是@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());
}

我想我的代表还不够高,不足以让我的输入被认为值得作为回复。

This is a rewrite of the great post by @Kay, which throws IOException and provides an early exit:

/**
 * 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.

允世 2024-07-23 02:27:36

我尝试使用列出的一些方法来测试性能。 很难进行严格的测试,因为影响结果的因素很多。 我准备了两个文件夹,一个有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

很明显,有些方法会加载整个文件以获得尺寸,而其他方法则通过从图像中读取一些标题信息来获取尺寸。 我认为当应用程序性能至关重要时这些数字可能很有用。

感谢大家对此主题的贡献 - 非常有帮助。

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):

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.

说好的呢 2024-07-23 02:27:36

我找到了另一种读取图像大小的方法(更通用)。
您可以将 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;
}

请注意,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 性能没有可比性。 我希望有人会觉得这很有用。

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:

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:

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.

私野 2024-07-23 02:27:36

您可以将 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 条目,或者我得到了上述信息 此处

我使用了类似于以下代码的方法,该代码是我从 这篇文章 获得的在太阳论坛上:

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])));
}

}

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:

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.

I used a method similar to the code below which I got from this post at the sun forums:

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])));
}

}

你的往事 2024-07-23 02:27:36

简单的方法:

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}

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;
}
深巷少女 2024-07-23 02:27:36

在过去的几年里,我在 ImageIO 上遇到了很多困难,我认为 Andrew Taylor解决方案是迄今为止最好的折衷方案(快速:不使用ImageIO#read,并且用途广泛)。 谢啦!!

但我对被迫使用本地文件(文件/字符串)感到有点沮丧,特别是在您想要检查来自多部分/表单数据请求(通常在其中检索 InputPart)的图像大小的情况下/InputStream 的。 因此,我基于 ImageIO#createImageInputStream 的功能,快速制作了一个接受 FileInputStreamRandomAccessFile 的变体这样做。

当然,这种带有对象输入的方法只能保持私有,您应该根据需要创建尽可能多的多态方法,并调用此方法。 您还可以在传递之前使用 Path#toFile() 接受 Path 和使用 URL#openStream() 接受 URL对于这个方法:

  private static Dimension getImageDimensions(Object input) throws IOException {

    try (ImageInputStream stream = ImageIO.createImageInputStream(input)) { // accepts File, InputStream, RandomAccessFile
      if(stream != null) {
        IIORegistry iioRegistry = IIORegistry.getDefaultInstance();
        Iterator<ImageReaderSpi> iter = iioRegistry.getServiceProviders(ImageReaderSpi.class, true);
        while (iter.hasNext()) {
          ImageReaderSpi readerSpi = iter.next();
          if (readerSpi.canDecodeInput(stream)) {
            ImageReader reader = readerSpi.createReaderInstance();
            try {
              reader.setInput(stream);
              int width = reader.getWidth(reader.getMinIndex());
              int height = reader.getHeight(reader.getMinIndex());
              return new Dimension(width, height);
            } finally {
              reader.dispose();
            }
          }
        }
        throw new IllegalArgumentException("Can't find decoder for this image");
      } else {
        throw new IllegalArgumentException("Can't open stream for this image");
      }
    }
  }

Having struggled with ImageIO a lot in the past years, I think Andrew Taylor's solution is by far the best compromise (fast: not using ImageIO#read, and versatile). Thanks man!!

But I was a little frustrated to be compelled to use a local file (File/String), especially in cases where you want to check image sizes coming from, say, a multipart/form-data request where you usually retrieve InputPart/InputStream's. So I quickly made a variant that accepts File, InputStream and RandomAccessFile, based on the ability of ImageIO#createImageInputStream to do so.

Of course, such a method with Object input, may only remain private and you shall create as many polymorphic methods as needed, calling this one. You can also accept Path with Path#toFile() and URL with URL#openStream() prior to passing to this method:

  private static Dimension getImageDimensions(Object input) throws IOException {

    try (ImageInputStream stream = ImageIO.createImageInputStream(input)) { // accepts File, InputStream, RandomAccessFile
      if(stream != null) {
        IIORegistry iioRegistry = IIORegistry.getDefaultInstance();
        Iterator<ImageReaderSpi> iter = iioRegistry.getServiceProviders(ImageReaderSpi.class, true);
        while (iter.hasNext()) {
          ImageReaderSpi readerSpi = iter.next();
          if (readerSpi.canDecodeInput(stream)) {
            ImageReader reader = readerSpi.createReaderInstance();
            try {
              reader.setInput(stream);
              int width = reader.getWidth(reader.getMinIndex());
              int height = reader.getHeight(reader.getMinIndex());
              return new Dimension(width, height);
            } finally {
              reader.dispose();
            }
          }
        }
        throw new IllegalArgumentException("Can't find decoder for this image");
      } else {
        throw new IllegalArgumentException("Can't open stream for this image");
      }
    }
  }
遇见了你 2024-07-23 02:27:36

您可以使用 Toolkit,不需要 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();

You could use the Toolkit, no need for 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();
祁梦 2024-07-23 02:27:36

ImageIO.read 的问题是它真的很慢。 您所需要做的就是读取图像标题来获取尺寸。 ImageIO.getImageReader 是完美的候选者。

这是 Groovy 示例,但同样的情况也适用于 Java

def stream = ImageIO.createImageInputStream(new ByteArrayInputStream(inputStream))
def formatReader = ImageIO.getImageWritersByFormatName(format).next() 
def reader = ImageIO.getImageReader(formatReader)
reader.setInput(stream, true)

println "width:reader.getWidth(0) -> height: reader.getHeight(0)"

性能与使用 SimpleImageInfo java 库相同。

https://github.com/ cbeust/personal/blob/master/src/main/java/com/beust/SimpleImageInfo.java

Problem with ImageIO.read is that it is really slow. All you need to do is to read image header to get the size. ImageIO.getImageReader is perfect candidate.

Here is the Groovy example, but the same thing applies to Java

def stream = ImageIO.createImageInputStream(new ByteArrayInputStream(inputStream))
def formatReader = ImageIO.getImageWritersByFormatName(format).next() 
def reader = ImageIO.getImageReader(formatReader)
reader.setInput(stream, true)

println "width:reader.getWidth(0) -> height: reader.getHeight(0)"

The performance was the same as using SimpleImageInfo java library.

https://github.com/cbeust/personal/blob/master/src/main/java/com/beust/SimpleImageInfo.java

迷路的信 2024-07-23 02:27:36

您可以使用 java.io.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();
}

You can get width and height of image with BufferedImage object using java.

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();
}
荆棘i 2024-07-23 02:27:36

使用 ImageIO.read 获取缓冲图像是一种非常繁重的方法,因为它在内存中创建图像的完整未压缩副本。 对于 png,您也可以使用 pngj 和代码:

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}

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:

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}
橘味果▽酱 2024-07-23 02:27:36
public static Optional<Dimension> getImageDimensions(Path imageFile) {

    Optional<String> suffixOpt = getExtension(imageFile);
    Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffixOpt.orElse(""));
    while (iter.hasNext()) {
        ImageReader reader = iter.next();
        try (ImageInputStream stream = new FileImageInputStream(imageFile.toFile())) {
            reader.setInput(stream);
            return Optional.of(new Dimension(reader.getWidth(reader.getMinIndex()),
                    reader.getHeight(reader.getMinIndex())));
        } catch (IOException e) {
            log.warn("Error reading: " + imageFile, e); //or however you want to handle the exception
        } finally {
            reader.dispose();
        }
    }
    return Optional.empty();
}

public static Optional<String> getExtension(Path file) {
    int pos = file.getFileName().toString().lastIndexOf(".");
    if (pos == -1) {
        return Optional.empty();
    }
    return Optional.of(file.getFileName().toString().substring(pos + 1));
}

修改了@Andrew Taylor 的方法 使用选项。

还使用 Java 的 NIO Path 使 Java 21 中向 Path.getExt 的转换更加容易(可以删除第二个方法,并将 getExtension(imageFile) 替换为 >imageFile.getExtension())。

还使用 Java 的 try-with-resources 设计。

如果更可取的话,可以使用外部库来代替第二种方法。

使用 Spliterator 可能是另一种方式,尽管最终代码变得更加冗长,因为从 Iterator 进行转换几乎没有什么好处。

public static Optional<Dimension> getImageDimensions(Path imageFile) {

    Optional<String> suffixOpt = getExtension(imageFile);
    Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffixOpt.orElse(""));
    while (iter.hasNext()) {
        ImageReader reader = iter.next();
        try (ImageInputStream stream = new FileImageInputStream(imageFile.toFile())) {
            reader.setInput(stream);
            return Optional.of(new Dimension(reader.getWidth(reader.getMinIndex()),
                    reader.getHeight(reader.getMinIndex())));
        } catch (IOException e) {
            log.warn("Error reading: " + imageFile, e); //or however you want to handle the exception
        } finally {
            reader.dispose();
        }
    }
    return Optional.empty();
}

public static Optional<String> getExtension(Path file) {
    int pos = file.getFileName().toString().lastIndexOf(".");
    if (pos == -1) {
        return Optional.empty();
    }
    return Optional.of(file.getFileName().toString().substring(pos + 1));
}

Revised the method by @Andrew Taylor to use Optionals.

Also uses the Java's NIO Path to make the transition to Path.getExt easier in Java 21 (the second method can be removed and getExtension(imageFile) can be replaced with imageFile.getExtension()).

Also uses the try-with-resources design from Java.

One could instead use an external library in place of the second method if that's preferable.

Using a Spliterator could be another way, though in the end the code became more verbose as little is gained by converting from an Iterator.

岛歌少女 2024-07-23 02:27:36

所以不幸的是,在尝试了上面的所有答案之后,经过不懈的尝试,我没有让它们工作。 所以我决定自己做真正的黑客,我让它为我工作。 我相信它也非常适合您。

我正在使用这个简单的方法来获取应用程序生成的图像的宽度,并稍后上传以进行验证:

请。 请注意:您必须在清单中启用访问存储的权限。

/我将其设置为静态并放入我的 Global 类中,这样我就可以从一个源引用或访问它,如果有任何修改,都必须在一个地方完成。 只是在java中保持了DRY的概念。 (无论如何):)/

public static int getImageWidthOrHeight(String imgFilePath) {

            Log.d("img path : "+imgFilePath);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imgFilePath, o);

            int width_tmp = o.outWidth, height_tmp = o.outHeight;

            Log.d("Image width : ", Integer.toString(width_tmp) );

            //you can decide to rather return height_tmp to get the height.

            return width_tmp;

}

So unfortunately, after trying all the answers from above, I did not get them to work after tireless times of trying. So I decided to do the real hack myself and I go this to work for me. I trust it would work perfectly for you too.

I am using this simple method to get the width of an image generated by the app and yet to be upload later for verification :

Pls. take note : you would have to enable permissions in manifest for access storage.

/I made it static and put in my Global class so I can reference or access it from just one source and if there is any modification, it would all have to be done at just one place. Just maintaining a DRY concept in java. (anyway) :)/

public static int getImageWidthOrHeight(String imgFilePath) {

            Log.d("img path : "+imgFilePath);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imgFilePath, o);

            int width_tmp = o.outWidth, height_tmp = o.outHeight;

            Log.d("Image width : ", Integer.toString(width_tmp) );

            //you can decide to rather return height_tmp to get the height.

            return width_tmp;

}

我很坚强 2024-07-23 02:27:36

要在没有 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);
}

To get size of emf file without EMF Image Reader you can use code:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文