Вырежьте изображение в форме текста - PullRequest
43 голосов
/ 09 июня 2011

Мне нужно вырезать изображение в форме текста на другом изображении. Я думаю, что это лучше всего показано на изображениях.

Это фото кота:

Photo of a nice cat

и вот текст, который я хочу вырезать:

Text to cut out of the cat photo

Полученное изображение будет таким:

Resulting cut-out of the cat photo

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

Ответы [ 6 ]

33 голосов
/ 09 июня 2011

Cat text

import java.awt.*;
import java.awt.font.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;
import javax.imageio.ImageIO;
import java.net.URL;
import java.io.File;

class PictureText {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://i.stack.imgur.com/Nqf3H.jpg");
        BufferedImage originalImage = ImageIO.read(url);
        final BufferedImage textImage = new BufferedImage(
            originalImage.getWidth(),
            originalImage.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = textImage.createGraphics();
        FontRenderContext frc = g.getFontRenderContext();
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, 250);
        GlyphVector gv = font.createGlyphVector(frc, "Cat");
        Rectangle2D box = gv.getVisualBounds();
        int xOff = 25+(int)-box.getX();
        int yOff = 80+(int)-box.getY();
        Shape shape = gv.getOutline(xOff,yOff);
        g.setClip(shape);
        g.drawImage(originalImage,0,0,null);
        g.setClip(null);
        g.setStroke(new BasicStroke(2f));
        g.setColor(Color.BLACK);
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g.draw(shape);

        g.dispose();

        File file = new File("cat-text.png");
        ImageIO.write(textImage,"png",file);
        Desktop.getDesktop().open(file);
    }
}
21 голосов
/ 09 июня 2011

Создайте новый BufferedImage и выполните итерацию по всем пикселям слова cat, и, если они черные, скопируйте пиксели изображения cat в новое изображение.

Вот некоторый код: ( Окончательная работакод, поддерживает сглаживание )

public static BufferedImage textEffect(BufferedImage image, BufferedImage text) {
    if (image.getWidth() != text.getWidth() ||
        image.getHeight() != text.getHeight())
    {
        throw new IllegalArgumentException("Dimensions are not the same!");
    }
    BufferedImage img = new BufferedImage(image.getWidth(),
                                          image.getHeight(),
                                          BufferedImage.TYPE_INT_ARGB_PRE);

    for (int y = 0; y < image.getHeight(); ++y) {
        for (int x = 0; x < image.getWidth(); ++x) {
           int textPixel = text.getRGB(x, y);
           int textAlpha = (textPixel & 0xFF000000);
           int sourceRGB = image.getRGB(x, y);
           int newAlpha = (int) (((textAlpha >> 24) * (sourceRGB >> 24)) / 255d);
           int imgPixel = (newAlpha << 24) |  (sourceRGB & 0x00FFFFFF);
           int rgb = imgPixel | textAlpha;
           img.setRGB(x, y, rgb);

        }
    }
    return img;
}
15 голосов
/ 09 июня 2011

Используйте GlyphVector. Используйте Font класс

public GlyphVector layoutGlyphVector(FontRenderContext frc,
                                         char[] text,
                                         int start,
                                         int limit,
                                         int flags) {

Вы можете получить контур Shape из вектора глифа с помощью публичного абстрактного Shape getOutline()

Назначьте контур Shape как клип для вашего Graphics экземпляра.

Нарисуйте изображение на графике.

Будет заполнена только вырезанная форма.

8 голосов
/ 09 июня 2011

Здесь нет java, но необходимые операции с изображениями легко понять. В Mathematica:

enter image description here

2 голосов
/ 10 ноября 2013

Вы можете сделать это на Java с помощью всего лишь нескольких строк исходного кода, используя Marvin Framework

enter image description here

исходный код:

public class CutAndFill {
    public static void main(String[] args) {
        // 1. Load images
        MarvinImage catImage = MarvinImageIO.loadImage("./res/catImage.jpg");
        MarvinImage catText = MarvinImageIO.loadImage("./res/catText.png");

        // 2. Load plug-in, set parameters and process de image
        MarvinImagePlugin combine = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.combine.combineByMask");
        combine.setAttribute("combinationImage", catImage);
        combine.setAttribute("colorMask", Color.black);
        combine.process(catText.clone(), catText);

        // 3. Save the output image.
        MarvinImageIO.saveImage(catText, "./res/catOut.jpg");
    }
}
0 голосов
/ 09 июня 2011

Во-первых, сделайте черную часть изображения "Кошка" прозрачной. См. здесь для помощи с этим. Затем составное это изображение поверх изображения вашей любимой кошки (у меня Шиба).

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

...