Cut out image in shape of 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);
}
}
Create a new BufferedImage and iterate over all the pixels of word cat and if they are black, copy the cat-image pixels to the new image.
Here is some code: (Final working code, supports anti-alias)
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;
}
Use GlyphVector
. Use Font
class
public GlyphVector layoutGlyphVector(FontRenderContext frc,
char[] text,
int start,
int limit,
int flags) {
You can get outline Shape
from glyph vector by public abstract Shape getOutline()
Assign the outline Shape
as a clip to your Graphics
instance.
Draw the image on the graphics.
Only clipped shape will be filled.
No java here, but the needed image operations are easy to understand. In Mathematica:
You can do it in Java with just a few lines of source code, using Marvin Framework
source code:
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");
}
}