Почему бы вам не попробовать использовать захват аргументов, чтобы получить значение ожидаемого списка, когда он был запущен, и затем вы можете сравнить его.
ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);
verify(collaborator).run(listCaptor.capture());
assertEquals(expectedList, argument.getValue());
Простой способ:
BufferedImage readImage = null;
try {
readImage = ImageIO.read(new File(your path);
int h = readImage.getHeight();
int w = readImage.getWidth();
} catch (Exception e) {
readImage = null;
}
Проблема с 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
Это переписывание большого сообщения @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());
}
Я думаю, что мой репутатор недостаточно высок, чтобы мой вклад считался достойным ответ.
javax.imageio.ImageIO.getImageReadersByMIMEType(mimeType)
, если вы хотите быть уверенным в типе файла?
– EdgeCaseBerg
10 November 2015 в 20:14
.close()
в потоке, прежде чем вы вернетесь? в противном случае вы оставите поток открытым
– EdgeCaseBerg
10 November 2015 в 20:31
throws IOException
.
– php_coder_3809625
26 June 2016 в 13:06
org.apache.commons.io.FilenameUtils#getExtension
для обнаружения расширения имени файла.
– Patrick Bergner
29 August 2017 в 14:23
Я нашел этот свободный класс, отлично работает:
http://jaimonmathew.wordpress.com/2011/01/29/simpleimageinfo/
Чтобы получить буферное изображение с ImageIO.read, это очень тяжелый метод, так как он создает полную несжатую копию изображения в памяти. Для png вы также можете использовать pngj и код:
if (png)
PngReader pngr = new PngReader(file);
width = pngr.imgInfo.cols;
height = pngr.imgInfo.rows;
pngr.close();
}
Вы можете загружать двоичные данные 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])));
}
}
==192
он должен проверять номера 192-207, кроме 196, 200 и 204.
– vorrtex
2 October 2014 в 06:38
com.drewnoakes.metadata-extractor
, чтобы легко извлекать эти заголовки
– Victor Petit
3 May 2017 в 12:55
Попробуйте использовать свободно доступный класс ImageInfo, я использовал его для этой же цели:
http://linux.softpedia.com/get/Multimedia/Graphics/ImageInfo-19792 .shtml
Вы можете использовать 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();
Вы можете получить ширину и высоту изображения с помощью объекта 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();
}
Я попытался проверить производительность, используя некоторые из перечисленных подходов. Трудно сделать строгий тест, так как на результат влияет множество факторов. Я подготовил две папки: одну с 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
Очевидно, что некоторые методы загружают весь файл, чтобы получить размеры, а другие получают только чтение некоторая информация заголовка из изображения. Я думаю, что эти цифры могут быть полезны, когда производительность приложения имеет решающее значение.
Спасибо всем за вклад в эту тему - очень полезно.
Я нашел другой способ прочитать размер изображения (более общий). Вы можете использовать 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. Надеюсь, кто-то найдет это полезным.
getFileSuffix()
содержит ненужные ifs и инициализацию с помощью null
, в данном случае это не очень хорошая идея.
– Jimmy T.
13 December 2013 в 00:23
ImageIO.read()
полностью из воды, как с точки зрения времени процессора, так и использования памяти.
– aroth
4 February 2016 в 06:41
Чтобы получить размер файла 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);
}