#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.