Java BufferedImage альтернативы - PullRequest
0 голосов
/ 07 февраля 2012

Я пытаюсь реализовать простой класс, который позволит пользователю обрезать изображение, которое будет использоваться для его изображения профиля.Это веб-приложение на Java.

Я провел некоторый поиск и обнаружил, что java.awt имеет класс BufferedImage, и это (на первый взгляд) кажется идеальным для того, что мне нужно.Тем не менее, кажется, что в этом есть ошибка (или, возможно, Java, как я видел, предположил), что означает, что обрезка не всегда работает правильно.

Вот код, который я использую, чтобы попытаться обрезатьmy image:

    BufferedImage profileImage = getProfileImage(form, modelMap);
    if (profileImage != null) {
        BufferedImage croppedImage = profileImage
                .getSubimage(form.getStartX(), form.getStartY(), form.getWidth(), form.getHeight());
        System.err.println(form.getStartX());
        System.err.println(form.getStartY()); 
        File finalProfileImage = new File(form.getProfileImage());
        try {
            String imageType = getImageType(form.getProfileImage());
            ImageIO.write(croppedImage, imageType, finalProfileImage);
        }
        catch (Exception e) {
            logger.error("Unable to write cropped image", e);
        }
    }
    return modelAndView;
}

protected BufferedImage getProfileImage(CropImageForm form, Map<String, Object> modelMap) {
    String profileImageFileName = form.getProfileImage();
    if (validImage(profileImageFileName) && imageExists(profileImageFileName)) {
        BufferedImage image = null;
        try {
            image = getCroppableImage(form, ImageIO.read(new File(profileImageFileName)), modelMap);
        }
        catch (IOException e) {
            logger.error("Unable to crop image, could not read profile image: [" + profileImageFileName + "]");
            modelMap.put("errorMessage", "Unable to crop image.  Please try again");
            return null;
        }
        return image;
    }

    modelMap.put("errorMessage", "Unable to crop image.  Please try again.");
    return null;
}

private boolean imageExists(String profileImageFileName) {
    return new File(profileImageFileName).exists();
}

private BufferedImage getCroppableImage(CropImageForm form, BufferedImage image, Map<String, Object> modelMap) {
    int cropHeight = form.getHeight();
    int cropWidth = form.getWidth();
    if (cropHeight <= image.getHeight() && cropWidth <= image.getWidth()) {
        return image;
    }
    modelMap.put("errorMessage", "Unable to crop image. Crop size larger than image.");
    return null;
}

private boolean validImage(String profileImageFileName) {
    String extension = getImageType(profileImageFileName);
    return (extension.equals("jpg") || extension.equals("gif") || extension.equals("png"));
}

private String getImageType(String profileImageFileName) {
    int indexOfSeparator = profileImageFileName.lastIndexOf(".");
    return profileImageFileName.substring(indexOfSeparator + 1);
}

Форма, упомянутая в этом фрагменте кода, представляет собой простой POJO, который содержит целочисленные значения левого верхнего угла для начала обрезки (startX и startY), а также ширину и высоту для создания новогоimage.

Однако я получаю обрезанное изображение, которое всегда начинается с 0,0, а не с позиции startX и startY.Я проверил код, чтобы убедиться, что в метод getSubimage передаются правильные значения, и они выглядят так:

Существуют ли простые альтернативы использованию BufferedImage для обрезки изображения.Я кратко посмотрел на JAI.Я предпочел бы добавить jar в свое приложение, чем обновлять jdk, установленный на всех производственных блоках, а также на любых серверах разработки / тестирования и локальных рабочих станциях.

Мои критерии выбора альтернативы: 1) простойиспользовать, чтобы обрезать изображение, так как это все, что я буду использовать для 2) если оно не встроено в java или spring, баночка должна быть небольшой и легко развертываемой в веб-приложении

Есть предложения?

Примечание: комментарий выше о том, что есть проблема с bufferedImage или Java, был тем, что я видел в этой публикации: Руководство по методу BufferedImage.getSubimage (int x, int y, int w, int h) метод?

Ответы [ 3 ]

2 голосов
/ 07 февраля 2012

Я использовал getSubimage () несколько раз без проблем. Вы добавили System.out.println (form.getStartX () + "" + form.getStartY ()) перед этим вызовом, чтобы убедиться, что они не равны 0?

Кроме того, вы по крайней мере получаете изображение, имеющее форму form.getWidth () x form.getHeight ()?

Убедитесь, что вы никоим образом не изменяете / не используете profileImage, поскольку возвращаемый BufferedImage использует тот же массив данных, что и родительский.

Лучший способ - просто нарисовать его, если вы хотите совершенно новый и независимый BufferedImage:

BufferedImage croppedImage = new BufferedImage(form.getWidth(),form.getHeight(),BufferedImage.TYPE_INT_ARGB);

Graphics g = croppedImage.getGraphics();
g.drawImage(profileImage,0,0,form.getWidth(),form.getHeight(),form.getStartX(),form.getStartY(),form.getWidth(),form.getHeight(),null);
g.dispose();
1 голос
/ 07 февраля 2012

Вы также можете сделать это таким же образом (код не проверен на 100%, как я принял, например, из существующего приложения, которое я сделал):

import javax.imageio.*;
import java.awt.image.*;
import java.awt.geom.*;

...

BufferedImage img = ImageIO.read(imageStream);

...

/*
 *  w = image width, h = image height, l = crop left, t = crop top
 */

ColorModel dstCM = img.getColorModel();
BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(w, h), dstCM.isAlphaPremultiplied(), null);

Graphics2D g = dst.createGraphics();
g.drawRenderedImage(img, AffineTransform.getTranslateInstance(-l,-t));
g.dispose();

java.io.File outputfile = new java.io.File(sessionScope.get('absolutePath') + java.io.File.separator + sessionScope.get('lastUpload'));
ImageIO.write(dst, 'png', outputfile);
0 голосов
/ 07 февраля 2012

Спасибо всем, кто ответил.Оказывается, проблема была не в коде обрезки вообще.

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

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

Я изменил отображение, чтобы больше не изменять размер изображения, и теперь обрезка работает прекрасно.

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