Java: создание миниатюр с прозрачностью - PullRequest
4 голосов
/ 28 января 2010

У меня проблемы с генерацией миниатюр изображений с альфа-каналом (прозрачность). Код, который я использую, это:

public void saveThumbnail(File file, String imageType) {
    if (bufferedThumb == null) {
        return;
    }

    if(bufferedImage.getColorModel().hasAlpha()) {
        logger.debug("Original image has Alpha channel");
    }

    BufferedImage bi = new BufferedImage(bufferedThumb.getWidth(null), bufferedThumb.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.getGraphics();
    g.drawImage(bufferedThumb, 0, 0, null);
    try {
        ImageIO.write(bi, imageType, file);
    } catch (IOException ioe) {
        ioe.printStackTrace();
        System.out.println("Error occured saving thumbnail");
    }
}

Однако, если я предоставляю, например, изображение GIF с прозрачным фоном, я всегда получаю черный или цветной фон.

EDIT:

Вот как он вызывается из класса с помощью миниатюры, в последний раз я пропустил двухпараметрическую версию метода getThuimbnail () -

Thumbnail th = new Thumbnail(file.getPath());
th.getThumbnail(100);

Добавлены методы, используемые для получения изображений:

public Thumbnail(String fileName) {
    try {
        this.bufferedImage = ImageIO.read(new File(fileName));
    } catch (IOException ex) {
        logger.error("Failed to read image file: " + ex.getMessage());
    }
}

public Image getThumbnail(int size) {
    int dir = VERTICAL;
    if (bufferedImage.getHeight() < bufferedImage.getWidth()) {
        dir = HORIZONTAL;
    }
    return getThumbnail(size, dir);
}

/**
 * Creates image with specifed max sized to a specified direction.
 * Will use Image.SCALE_SMOOTH for scaling.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir) {
    return getThumbnail(size, dir, Image.SCALE_SMOOTH);
}

/**
 * Creates image with specified size.
 * @param size Maximum size
 * @param dir Direction of maximum size - 0 = vertical, 1 = height.
 * @param scale Image.Scale to use for conversion.
 * @return Resized image.
 */
public Image getThumbnail(int size, int dir, int scale) {
    if (dir == HORIZONTAL) {
        bufferedThumb = bufferedImage.getScaledInstance(size, -1, scale);
    } else {
        bufferedThumb = bufferedImage.getScaledInstance(-1, size, scale);
    }
    return bufferedThumb;
}

Спасибо!

Ответы [ 4 ]

1 голос
/ 28 января 2010

Масштабирование изображений GIF с прозрачным цветом должно работать нормально. Я согласен с jarnbjo, что проблема, скорее всего, в поколении bufferedThumb.

Может быть, помогут следующие подсказки:

1) При создании большого пальца скопируйте тип изображения из источника, например ::100100

BufferedImage thumb = new BufferedImage(fit, fit, image.getType());

2) Использовать 2D-подход:

Graphics2D g = thumb.createGraphics();

Вот пример кода для простого создания большого пальца (проверено и работает; прозрачность GIF, большой палец сохраняет прозрачность):

  public static BufferedImage thumb(BufferedImage image, int fit) {

    //image = blur(image);
    BufferedImage thumb = new BufferedImage(fit, fit, image.getType());
    Graphics2D g = thumb.createGraphics();

    try {
      int width = image.getWidth();
      int height = image.getHeight();
      int sx1;
      int sy1;
      int sx2;
      int sy2;
      int tmp;

      if (height > width) {
        tmp = height - width;
        sx1 = 0;
        sy1 = tmp / 2;
        sx2 = width;
        sy2 = height - sy1;
      } else if (width > height) {
        tmp = width - height;
        sx1 = tmp / 2;
        sy1 = 0;
        sx2 = width - sx1;
        sy2 = height;
      } else {
        sx1 = 0;
        sy1 = 0;
        sx2 = width;
        sy2 = height;
      }

      g.drawImage(
          image,
          0, 0,
          fit, fit,
          sx1, sy1,
          sx2, sy2,
          null
      );

    } finally {
      g.dispose();
    }
    return thumb;
  }//thumb

Примечание: под простым я подразумеваю, что он не даст качественных результатов, если вы пытаетесь слишком сильно масштабировать за один шаг (например, 2048 пикселей на входе, 100 пикселей на выходе). Возможно, вам потребуется многошаговый подход, и, вероятно, вам следует использовать AffineTransformOp с подсказками вместо использования графического устройства.

1 голос
/ 01 февраля 2010

Решено с помощью операции масштабирования AffineTransform:

AffineTransform af = new AffineTransform();
af.scale(scaleFactor, scaleFactor);

AffineTransformOp operation = new AffineTransformOp(af, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedThumb = operation.filter(bufferedImage, null);
return bufferedThumb;

Это, похоже, сохраняет прозрачность изображения.

0 голосов
/ 22 июля 2016

Вы можете попробовать это, используя Image IO Library:

PFB код:

package com.incture.thumbnail;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Thumnail {

    public static void main(String[] args) {

        String source = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/download-button.gif";
        String target = "E:/Incture/APAutomation/NewWorkspace/BarCodeReading/thumb1.jpg";

        saveScaledImage(source, target);

    }

    public static void saveScaledImage(String filePath, String outputFile) {

        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        try {
            Graphics g=img.getGraphics();
            g.setColor(Color.white);
            g.fillRect(0, 0, img.getWidth(), img.getHeight());   
            g.drawImage(ImageIO.read(new File(filePath)), 0 , 0, 20, 20, null);
            ImageIO.write(img, "png", new File(outputFile));
            System.out.println("done");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
0 голосов
/ 28 января 2010

Код, который вы используете для записи файла, верен, по крайней мере, если вы используете формат, который поддерживает прозрачность (например, PNG). Скорее всего, bufferedThumb уже испорчен, поэтому, чтобы помочь вам, было бы более полезно, если бы вы указали, как вы получаете bufferedImage и как вы создаете bufferedThumb.

...