Изменение размера бикубического изображения без головы в Java

Мне нужно выполнить обрезку и изменение размера изображения Java без X-сервера.

Я пробовал несколько методов. первый метод ниже работает, но выводит довольно уродливое изображение с измененным размером (вероятно, с использованием алгоритма ближайшего соседа для изменения размера:

static BufferedImage createResizedCopy(Image originalImage, int scaledWidth, int scaledHeight, boolean preserveAlpha)
{
    int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
    BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
    Graphics2D g = scaledBI.createGraphics();
    if (preserveAlpha)
    {
        g.setComposite(AlphaComposite.Src);
    }
    g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
    g.dispose();
    return scaledBI;
}

Поэтому я решил использовать bicubic изменение размера, которое дает лучшие результаты:

public static BufferedImage createResizedCopy(BufferedImage source, int destWidth, int destHeight, Object interpolation)
{
    if (source == null) throw new NullPointerException("source image is NULL!");
    if (destWidth <= 0 && destHeight <= 0) throw new IllegalArgumentException("destination width & height are both <=0!");
    int sourceWidth = source.getWidth();
    int sourceHeight = source.getHeight();
    double xScale = ((double) destWidth) / (double) sourceWidth;
    double yScale = ((double) destHeight) / (double) sourceHeight;
    if (destWidth <= 0)
    {
        xScale = yScale;
        destWidth = (int) Math.rint(xScale * sourceWidth);
    }
    if (destHeight <= 0)
    {
        yScale = xScale;
        destHeight = (int) Math.rint(yScale * sourceHeight);
    }
    GraphicsConfiguration gc = getDefaultConfiguration();
    BufferedImage result = gc.createCompatibleImage(destWidth, destHeight, source.getColorModel().getTransparency());
    Graphics2D g2d = null;
    try
    {
        g2d = result.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation);
        AffineTransform at = AffineTransform.getScaleInstance(xScale, yScale);
        g2d.drawRenderedImage(source, at);
    }
    finally
    {
        if (g2d != null) g2d.dispose();
    }
    return result;
}

public static GraphicsConfiguration getDefaultConfiguration()
{
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    GraphicsDevice gd = ge.getDefaultScreenDevice();
    return gd.getDefaultConfiguration();
}

Это работало нормально, пока я не попытался установить его на сервер, и в этот момент я столкнулся с java.awt.HeadlessException. мои попытки поиграть с java.awt.headless=true не увенчались успехом.

Итак, вот вопрос: как изменить размер, обрезать и изображение в Java без X-сервера, используя алгоритм бикубической интерполяции?

Ответ: Используя код из комментария Божо, я создал эту функцию, которая делает свое дело (интерполяция должна быть RenderingHints.VALUE_INTERPOLATION_*).

public static BufferedImage createResizedCopy(BufferedImage source, int destWidth, int destHeight, Object interpolation)
{
    BufferedImage bicubic = new BufferedImage(destWidth, destHeight, source.getType());
    Graphics2D bg = bicubic.createGraphics();
    bg.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation);
    float sx = (float)destWidth / source.getWidth();
    float sy = (float)destHeight / source.getHeight();
    bg.scale(sx, sy);
    bg.drawImage(source, 0, 0, null);
    bg.dispose();
    return bicubic;
}

person Omry Yadan    schedule 26.12.2010    source источник


Ответы (1)


Проверьте этот код. Также проверьте, не решает ли проблему Image.getScaledInstance(..) (с «плавным» масштабированием). И, наконец, взгляните на java-image-scaling-library.

person Bozho    schedule 26.12.2010
comment
это работает, спасибо! обновление моего вопроса с окончательной версией функции изменения размера. - person Omry Yadan; 27.12.2010