Как найти общее количество пикселей в изображении [дубликат]

Почему бы вам не попробовать использовать захват аргументов, чтобы получить значение ожидаемого списка, когда он был запущен, и затем вы можете сравнить его.

ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);

verify(collaborator).run(listCaptor.capture());

assertEquals(expectedList, argument.getValue());
83
задан silver est 19 June 2016 в 08:57
поделиться

13 ответов

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

BufferedImage readImage = null;

try {
    readImage = ImageIO.read(new File(your path);
    int h = readImage.getHeight();
    int w = readImage.getWidth();
} catch (Exception e) {
    readImage = null;
}
241
ответ дан alex 17 August 2018 в 08:48
поделиться
  • 1
    Это лучший ответ на очень долгий путь, и вас обманули из голосов тем же ответом, опубликованным кем-то еще через 17 дней после вашего сообщения. Это должен быть главный ответ, а не нижний. – Oversteer 25 June 2012 в 12:07
  • 2
    @Vishal Rao: Я помню, что добавлял некоторые дополнительные кусочки в classpath для файлов формата TIFF. Я думаю, что это jai_imageio.jar – Apurv 10 August 2012 в 04:07
  • 3
    Это было немного запутанно, пытаясь найти нужные файлы, есть специфические для дистрибутива, но есть и java-платформа, зависящая от платформы, которая может быть помещена в путь к классам. На момент написания файлы находятся в zip-файле. Jai-1_1_3-lib.zip доступен download.java.net/media/jai/builds/release С инструкциями download.java.net/media/jai/builds/release/1_1_3 /. jai_imageio.jar также необходим, я не мог найти, где это получить, и в конечном итоге загрузить его как зависимость от другого проекта code.google.com/p/mapgrid/downloads/… – Dan675 23 August 2012 в 04:16
  • 4
    Из всего, что я читаю, это считывает все изображение в память. Это экстремально, чтобы получить ширину и высоту. – Marc 17 May 2015 в 20:07
  • 5
    плохой способ: вам нужно загрузить весь растровый растровый файл в память, что вызывает OOM с очень большими изображениями – yetanothercoder 27 October 2015 в 10:41
  • 6
    это необходимо для чтения всего изображения в памяти только для того, чтобы узнать ширину и высоту. Да, это просто, но будет плохо работать для многих изображений или огромных ... – Clint Eastwood 15 September 2016 в 15:43

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

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

def stream = ImageIO.createImageInputStream(new ByteArrayInputStream(inputStream))
def reader = ImageIO.getImageReader(getReaderByFormat(format))
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

1
ответ дан argoden 17 August 2018 в 08:48
поделиться

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

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

46
ответ дан Austin Powers 17 August 2018 в 08:48
поделиться
  • 1
    Спасибо за это! и учитывая сравнение производительности, выполненное пользователем194715, я приму ваше предложение для оценки производительности и png! Спасибо! – ah-shiang han 2 November 2015 в 06:50
  • 2
    Не могли бы вы также использовать probeContentType из пакета nio.Files в сочетании с javax.imageio.ImageIO.getImageReadersByMIMEType(mimeType), если вы хотите быть уверенным в типе файла? – EdgeCaseBerg 10 November 2015 в 20:14
  • 3
    Кроме того, не следует ли вам называть .close() в потоке, прежде чем вы вернетесь? в противном случае вы оставите поток открытым – EdgeCaseBerg 10 November 2015 в 20:31
  • 4
    Полезно, но я не могу окутать голову в код, который ловит IOException, а затем регистрирует это в журнале, когда подпись метода уже имеет throws IOException. – php_coder_3809625 26 June 2016 в 13:06
  • 5
    – Andrew Taylor 27 June 2016 в 18:48
  • 6
    Вы можете использовать org.apache.commons.io.FilenameUtils#getExtension для обнаружения расширения имени файла. – Patrick Bergner 29 August 2017 в 14:23

Я нашел этот свободный класс, отлично работает:

http://jaimonmathew.wordpress.com/2011/01/29/simpleimageinfo/

11
ответ дан Gus 17 August 2018 в 08:48
поделиться
  • 1
    Отличная находка! Спасибо! Это очень быстрый метод и отлично работает. – rustyx 6 June 2014 в 20:48

Чтобы получить буферное изображение с ImageIO.read, это очень тяжелый метод, так как он создает полную несжатую копию изображения в памяти. Для png вы также можете использовать pngj и код:

if (png)
    PngReader pngr = new PngReader(file);
    width = pngr.imgInfo.cols;
    height = pngr.imgInfo.rows;
    pngr.close();
}
1
ответ дан Jessi 17 August 2018 в 08:48
поделиться

Вы можете загружать двоичные данные 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 в wikipedia или я получил здесь информацию здесь .

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

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

}

11
ответ дан joinJpegs 17 August 2018 в 08:48
поделиться
  • 1
    Это помогло мне LOT! благодаря! – Orr Matarasso 22 September 2009 в 15:32
  • 2
    Хорошо. Но я думаю, что вместо ==192 он должен проверять номера 192-207, кроме 196, 200 и 204. – vorrtex 2 October 2014 в 06:38
  • 3
    Или вы можете использовать библиотеку com.drewnoakes.metadata-extractor, чтобы легко извлекать эти заголовки – Victor Petit 3 May 2017 в 12:55

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

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

4
ответ дан karim79 17 August 2018 в 08:48
поделиться

Вы можете использовать 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();
3
ответ дан Karussell 17 August 2018 в 08:48
поделиться

Вы можете получить ширину и высоту изображения с помощью объекта 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();
    }
1
ответ дан KIBOU Hassan 17 August 2018 в 08:48
поделиться

Я попытался проверить производительность, используя некоторые из перечисленных подходов. Трудно сделать строгий тест, так как на результат влияет множество факторов. Я подготовил две папки: одну с 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

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

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

31
ответ дан mp31415 17 August 2018 в 08:48
поделиться
  • 1
    Теперь это ответ. Отличная работа! – ssimm 25 February 2016 в 20:01
  • 2
    Вы также анализировали использование пространства кучи при загрузке изображений? Кроме того, были ли вы получены ошибки OOM при выполнении этих тестов по любому из методов? – saibharath 2 April 2018 в 18:26
  • 3
    – Farkas Csanád 20 August 2018 в 12:59

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

40
ответ дан silver est 17 August 2018 в 08:48
поделиться
  • 1
    getFileSuffix() содержит ненужные ifs и инициализацию с помощью null, в данном случае это не очень хорошая идея. – Jimmy T. 13 December 2013 в 00:23
  • 2
    Черт, да, это «очень быстро». Я думаю, что вы получили награду «Преуменьшение года» с этим. Удаляет ImageIO.read() полностью из воды, как с точки зрения времени процессора, так и использования памяти. – aroth 4 February 2016 в 06:41
  • 3
    public static String getFileSuffix (final String path) {if (path! = null & amp; & amp; path.lastIndexOf ('.')! = -1) {return path.substring (путь.lastIndexOf ('.')). substring (1); } return null; } – Nilanchala Panigrahy 30 March 2016 в 22:47

Чтобы получить размер файла emf без EMF Image Reader, вы можете использовать код:

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);
}
-2
ответ дан Viktor Sirotin 17 August 2018 в 08:48
поделиться
245
ответ дан alex 6 September 2018 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: