以文本形状裁剪图像

46

我需要将一张图片剪切成文字形状,以下图像最能清楚地表达:

这是一张猫的照片:

一只可爱的猫

这是我想要剪切出来的文字:

猫照片中要剪切出的文字

最终生成的图片应该是这样的:

剪切后得到的猫的图片

文字图像始终为黑色,具有透明背景,得到的剪贴图也应具有透明背景。输入图像的大小也将相同。


21
无论如何。猫?立即+1! - musiKk
11
你填满了内部的"a"孔,这是有意为之吗? - Dr. belisarius
1
@belisarius 很敏锐 - 不,那不是故意的 ;) - Matt
1
你觉得如果有一张图片和文字会不会更好?(仅仅是问问) - OscarRyz
6个回答

39

猫咪图片

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);
    }
}

仅使用JDK的解决方案 - Stephan

21
创建一个新的BufferedImage对象,并循环遍历单词“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;
}

2
你如何迭代遍历单词“cat”的所有像素?如果单词是“dog”呢?从 OP - 文本始终为黑色,因此只需用其他图像的相应像素替换所有黑色像素即可。 - Praveen Lobo
@Lobo 是的,那就是他所建议的。 - Sled
2
一个小建议:在计算newAlpha时,不要将其转换为double,而是将除法移到乘法之后。 - Mark Ransom
@Mark:谢谢,确实更整洁。 - Martijn Courteaux

15

使用GlyphVector类,使用Font类。

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

通过公共抽象形状 getOutline(),您可以从字形向量中获取轮廓形状 Shape

将轮廓形状 Shape 分配为裁剪剪辑到您的 Graphics 实例。

在图形上绘制图像。

只有被裁剪的形状才会填充。


8
没有Java,但需要的图像操作很容易理解。在Mathematica中:enter image description here

可能原帖作者想要首先创建一个像这样的方法。 - OscarRyz

3
您可以使用几行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");
    }
}

-1

首先,将“猫”图像的黑色部分变为透明。请参考此处获取帮助。然后,合成该图像到您最喜欢的猫的图片上(我的最爱是Sheeba)。

这样做的好处是,您可以制作一次透明文本图像,保存它,然后将其应用于Sheeba的所有家人和朋友!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接