2016-03-10 11 views
3

Для того, чтобы получить высоту изображения, мы можем использовать ImageIO.read(new URL("…")).getHeight().Есть ли какой-либо способ в Java для получения ширины и высоты изображения без переноса или загрузки?

Мои вопросы:

  1. Правильно ли я понимаю, что этот метод загружает изображение для расчета локального компьютера предварительного размера?
  2. Если да, то где именно загружается изображение - в какой-то кеш-накопитель JVM на жесткий диск или непосредственно в ОЗУ?
  3. Есть ли способ сделать высоту изображения без переноса или скачивания? Но с каким-то запросом на сервер?
+0

Нет метода 'ImageIO.read()' – wero

+0

@wero, конечно, я имею в виду что-то вроде 'ImageIO.read (новый URL-адрес («% IMG_URL% »)). GetHeight();' –

+0

ответ находится в ' ImageIO.read (URL) 'Javadoc и реализация. JDK поставляется с исходным кодом. – wero

ответ

4

Во-первых, ваши вопросы:

  1. Вид. Прежде всего, методы ImageIO.read(...) являются удобными методами, которые будут декодировать первое изображение в файле, используя все параметры по умолчанию для декодирования. Поскольку все операции ImageIO.read(...) делегированы для форматирования определенных плагинов или ImageReader экземпляров (например, JPEGImageReader), это может быть конкретным плагином. Но общий случай заключается в том, что данные изображения передаются и декодируются «на лету». Обратите внимание, что здесь нет «расчета размера», скорее всего, полное изображение декодируется на BufferedImage в этом случае. Так много данных, необходимых для декодирования первого изображения в файле, должно быть переведено, но необязательно хранится в любом месте на компьютере, кроме значений декодированного пикселя.

  2. От этого зависит. Существует настройка ImageIO.setUseCache(boolean), которая контролирует, кэшируются ли данные на диске или в ОЗУ.

    • Если параметр true, данные временно хранятся на диске, обычно в директории темпа по умолчанию (см java.io.tempdir свойства системы).
    • Если настройка false, данные временно сохраняются в памяти при декодировании изображения.
  3. Нет, если у вашего сервера нет специального API, чтобы предоставить вам эти данные, и вы выполняете определенные запросы к этому API. Однако API ImageIO имеет намного более гранулированные методы, которые позволяют намного быстрее получать размеры изображения, без загрузки/декодирования всего изображения спереди.

Чем быстрее способ получения размеров изображения является:

try (InputStream stream = url.openStream()) { 
    // The "useCache" setting will decide whether "input" below 
    // will be disk or memory cached 
    try (ImageInputStream input = ImageIO.createImageInputStream(stream)) { 
     ImageReader reader = ImageIO.getImageReaders(input).next(); // TODO: Handle no reader 
     try { 
      reader.setInput(input); 

      // Get dimensions of first image in the stream, without decoding pixel values 
      int width = reader.getWidth(0); 
      int height = reader.getHeight(0); 
     } 
     finally { 
      reader.dispose(); 
     } 
    } 
} 

Опять же, в зависимости от формата изображения, приведенный выше код должен читать только как большая часть заголовка/мета-данных, как это необходимо, чтобы определить, размеры изображения. Большинство реализаций ImageReader будут читать все данные заголовка для этого, но все же это намного быстрее и требует намного меньше данных (и памяти), чем декодирования всего изображения.

Это трудно сделать какие-либо предположения относительно того, сколько данных или должен быть загружен, потому что различные форматы имеют заголовки разного размера, основного транспорта (то есть. HTTP) может передавать данные в «куски» и т.д.

+1

относительно 1), я не вижу никакого способа узнать высоту изображения, не загружая сначала изображение (а затем изучая его) даже в теории. Можете ли вы объяснить, как это произойдет? – eis

+1

Терминология, возможно, но вам не нужно полностью загружать файл, * затем * начать декодировать его. «ImageReader» может начать декодирование изображения, как только некоторые из байтов будут переданы, и продолжить декодирование во время передачи данных. Вам нужно всего лишь передать достаточно данных для декодирования * первого * изображения (если вы считаете формат файла с несколькими изображениями, например, TIFF или изображения с большим количеством метаданных). Наконец, чтобы просто получить ширину/высоту, большинство форматов сохраняют их в заголовке, и вам нужно только передать/декодировать несколько байтов в начале файла (как в моем примере кода). – haraldK

+0

@haraldK, есть ли способ передать * просто * заголовки изображений с метаданными ширины/высоты без загрузки всего изображения? –

0

Ответ на этот вопрос заключается в том, что метод read() должен заполнить и вернуть значение для метода getHeight().

Это даже не вопрос ImageIO, это просто базовый синтаксис и семантика Java.

+4

Базовый синтаксис Java не отвечает на этот вопрос, например. когда ['Toolkit.createImage (URL)'] (https://docs.oracle.com/javase/8/docs/api/java/awt/Toolkit.html#createImage-java.net.URL-) возвращает, изображение не обязательно загружается. Вот почему ['Image.getHeight (...)'] (https://docs.oracle.com/javase/8/docs/api/java/awt/Image.html#getHeight-java.awt.image.ImageObserver-) может возвращать '-1' и асинхронно уведомлять предоставленный« ImageObserver ». Это 'BufferedImage', возвращенный' ImageIO', что делает разницу. – Holger

+0

Мой вопрос не о «базовом синтаксисе и семантике Java», а о реализации 'read()', как и где именно «BufferedImage» хранит изображение? –

+0

@Holger Это задокументированное исключение, и оно применяется только при использовании перегрузки с помощью ImageObserver. – EJP