Как мне заставить imageBuffer java правильно считывать PNG-файл?

#java #image #image-processing #resize #crop

#java #изображение #обработка изображений #изменение размера #обрезка

Вопрос:

По какой-то причине открытие некоторых PNG-файлов с помощью imageBuffer и ImageIO не работает. Вот некоторый код, который я использую, который отлично работает для изменения размера / обрезки файлов JPG:

 BufferedImage image = ImageIO.read(new File(location));

BufferedImage croppedImage = image.getSubimage(
    cropInfo.getX(), cropInfo.getY(), cropInfo.getW(), cropInfo.getH());

BufferedImage resizedImage = new BufferedImage(
    TARGET_WIDTH, TARGET_HEIGHT, croppedImage.getType());
Graphics2D g = resizedImage.createGraphics();
g.drawImage(croppedImage, 0, 0, TARGET_WIDTH, TARGET_HEIGHT, null);
g.dispose();

this.changeContentType("image/png", ".png"); // not really relevant. just a property

ImageIO.write(resizedImage, "png", new File(location));

return resizedImage;
  

Цель этой функции — выбрать любой заданный тип, изменить размер и обрезать изображение, а затем сохранить его в PNG с тем же именем файла.

Это работает в Windows, но если я обрезаю / изменяю размер в Linux (lenny), он полностью вылетает и жалуется на тип файла (он говорит, что тип равен 0).

 java.lang.IllegalArgumentException: Unknown image type 0
    java.awt.image.BufferedImage.<init>(BufferedImage.java:490)
    trainingdividend.domain.file.ServerImage.resizeImage(ServerImage.java:68)
    trainingdividend.domain.file.ServerImage.cropAndResize(ServerImage.java:80)
    trainingdividend.service.user.UserAccountManagerImpl.cropAvatar(UserAccountManagerImpl.java:155)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  

Решения?

Есть ли другая библиотека, которую я могу использовать вообще?

Комментарии:

1. Какую JVM вы используете в Linux? (Редактировать: судя по sun.reflect в трассировке стека, это Sun, но на всякий случай)

2. Да, последняя версия sun jvm. 1.6_24

3. Ну, я это исправил. Я вставил туда хак, где, если image.GetType() == 0, я вручную устанавливаю его равным 5. Это работает.

4. Черт возьми, я только что закончил компиляцию вашего кода в Windows (jvm 1.6.0_20), и он отлично работал со случайным jpg. Интересно, мог ли это быть ваш входной файл.

5. Нет, этот код работает в Windows для всего. Это просто не работало на Debian (lenny) с обновленным jdk. Я просто проверяю, равен ли тип 0, и если это так, я передаю 5. Кажется, это заставляет его работать. Я предполагаю, что это ошибка, и она вообще не имеет ко мне никакого отношения: (

Ответ №1:

При запуске моей функции в Windows croppedImaged.GetType() возвращает значение 5. Итак, простой «взлом» заключается в сохранении типа, проверьте, равен ли он 0… и если это так, установите значение 5 вручную.

 int imageType = croppedImage.getType();
if(imageType == 0) imageType = 5;
  

Затем мы передаем вместо этого ImageType, и это должно работать в Linux.

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

Совершенно очевидно, что версия Java 1.6 для Windows работает отлично, но в версии Linux есть ошибка.

Ответ №2:

эгервари, ты можешь использовать библиотеку, подобную imgscalr (Apache 2), чтобы «правильно» изменять размер за тебя, которая устраняет подобные проблемы с помощью очень простого API — это не поможет с обрезкой, но изменение размера — это то, что он делает лучше всего (разные скорости, качества, даже сглаживание, если хочешь).

Я хотел бы отметить, что код, который вы используете сейчас (преобразование ПОЛЬЗОВАТЕЛЬСКОГО типа в тип 3BYTE_BGR), также должен учитывать входящие изображения с альфа-каналом.

Кроме того, если вы хотите продолжать использовать свой пользовательский код, RGB и ARGB являются двумя из наиболее поддерживаемых типов изображений в Java2D — если вы используете плохо поддерживаемый тип изображения, когда Java2D переходит к выполнению операции с изображением, он возвращается к программному конвейеру рендеринга и не использует специализированные типы с аппаратным ускорением. Это не просто влияет на производительность, поскольку вы увидите, что результат на самом деле выглядит хуже (например, в GIF вы часто это видите).

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

обработка изображений Java … темпераментна 🙂

Ответ №3:

Обходным решением было бы сначала преобразовать файл в jpeg, а затем обработать его. Ошибка типа 0, похоже, в основном влияет на изображения PNG.