Как получить высоту и ширину изображения с помощью Java? - PullRequest
91 голосов
/ 23 марта 2009

Есть ли другой способ, кроме использования 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.

Ответы [ 12 ]

257 голосов
/ 31 января 2012

Вот что-то очень простое и удобное.

BufferedImage bimg = ImageIO.read(new File(filename));
int width          = bimg.getWidth();
int height         = bimg.getHeight();
56 голосов
/ 28 августа 2012

Это переписывание великого поста @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());
}

Полагаю, мой представитель недостаточно высок, чтобы мой вклад считался достойным ответа.

41 голосов
/ 26 мая 2010

Я нашел другой способ прочитать размер изображения (более общий). Вы можете использовать класс 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. Я надеюсь, что кто-то найдет это полезным.

39 голосов
/ 15 февраля 2013

Я пытался протестировать производительность, используя некоторые из перечисленных подходов. Трудно провести строгий тест, так как на результат влияет множество факторов. Я подготовил две папки, одну с 330 файлами JPG, а другую с 330 файлами PNG. Средний размер файла в обоих случаях составлял 4 МБ. Затем я вызвал 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

Очевидно, что некоторые методы загружают весь файл, чтобы получить размеры, в то время как другие получают, просто читая некоторую информацию заголовка из изображения. Я думаю, что эти цифры могут быть полезны, когда производительность приложения критична.

Спасибо всем за вклад в эту тему - очень полезно.

12 голосов
/ 28 марта 2009

Вы можете загрузить двоичные данные jpeg в виде файла и самостоятельно проанализировать заголовки jpeg. Вы ищете заголовок 0xFFC0 или Start of Frame:

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

}

9 голосов
/ 17 февраля 2012

Простой способ:

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}
4 голосов
/ 20 июня 2018

Проблема с ImageIO.read в том, что он действительно медленный. Все, что вам нужно сделать, это прочитать заголовок изображения, чтобы получить размер. ImageIO.getImageReader идеальный кандидат.

Вот пример Groovy, но то же самое относится и к Java

def stream = ImageIO.createImageInputStream(newByteArrayInputStream(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)"

Производительность была такой же, как при использовании Java-библиотеки SimpleImageInfo.

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

4 голосов
/ 23 марта 2009

Попробуйте использовать свободно доступный класс ImageInfo, я использовал его для той же цели:

http://linux.softpedia.com/get/Multimedia/Graphics/ImageInfo-19792.shtml

3 голосов
/ 05 февраля 2013

Вы можете использовать инструментарий, нет необходимости в 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();
1 голос
/ 27 апреля 2017

Вы можете получить ширину и высоту изображения с помощью объекта BufferedImage, используя 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();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...