Java 8 and Mac OS (High Sierra) here. I have the following class TextOverlayer that reads an image off the file system and needs to overlay some red text onto the image, and then save that "overlayed" image as a different file on the file system:
public class TextOverlayer implements ImageObserver {
public static void main(String[] args) throws IOException {
// Instantiate a TextOverlayer and read a source/input image from disk
TextOverlayer textOverlayer = new TextOverlayer();
BufferedImage bufferedImage = ImageIO.read(Paths.get("/User/myuser/pix/sourceImage.jpg").toFile());
// Lay some text over the image at specific coordinates
BufferedImage drawn = textOverlayer.drawText(bufferedImage, "Some text");
// Write the overlayed image to disk
File outputfile = new File("/User/myuser/pix/targetImage.jpg");
ImageIO.write(drawn, "jpg", outputfile);
}
private BufferedImage drawText(BufferedImage old, String text) {
int w = old.getWidth() / 3;
int h = old.getHeight() / 3;
BufferedImage img = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, this);
g2d.setPaint(Color.red);
g2d.setFont(new Font("Serif", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
int x = img.getWidth() - fm.stringWidth(text) - 5;
int y = fm.getHeight();
g2d.drawString(text, x, y);
g2d.dispose();
return img;
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
return false;
}
}
When this runs, no errors are thrown and the targetImage.jpg is successfully written to disk, except its just an image of a small black box. I would have expected targetImage.jpg to be the exact same as sourceImage.jpg, just with some extra text added to it at the desired coordinates (within the image).
Any ideas where I'm going awry?
You don't need the ImageObserver and you likely can't write an image with an alpha channel to a JPEG file with the included writers.
This works:
public class TextOverlayer {
public static void main(String[] args) throws IOException {
// Instantiate a TextOverlayer and read a source/input image from disk
TextOverlayer textOverlayer = new TextOverlayer();
BufferedImage bufferedImage = ImageIO.read(Paths.get("/User/myuser/pix/sourceImage.jpg").toFile());
// Lay some text over the image at specific coordinates
BufferedImage drawn = textOverlayer.drawText(bufferedImage, "Some text");
// Write the overlayed image to disk
File outputfile = new File("/User/myuser/pix/targetImage.jpg");
boolean result = ImageIO.write(drawn, "jpg", outputfile);
if (!result) {
System.out.println("FAILED");
}
}
private BufferedImage drawText(BufferedImage old, String text) {
int w = old.getWidth();
int h = old.getHeight();
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.drawImage(old, 0, 0, w, h, null);
g2d.setPaint(Color.red);
g2d.setFont(new Font("Serif", Font.BOLD, 20));
FontMetrics fm = g2d.getFontMetrics();
int x = img.getWidth() - fm.stringWidth(text) - 5;
int y = fm.getHeight();
g2d.drawString(text, x, y);
g2d.dispose();
return img;
}
}
Related
I need to write a program that shrinks an image in half without using any libraries other than Java Graphics and Java Color. I wrote one earlier with Graphics2D that looked like this --
public static void shrink(String orig, String convert) throws Exception { //Ahh damn we needed one from the red group
BufferedImage bufferedimg = null;
File f = new File(orig);
bufferedimg = ImageIO.read(f);
int width = bufferedimg.getWidth();
int height = bufferedimg.getHeight();
int finalWidth = width/2;
int finalHeight = height/2;
BufferedImage resizedImage = new BufferedImage(finalWidth, finalHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bufferedimg, 0, 0, finalWidth, finalHeight, null);
g.dispose();
f = new File(convert);
ImageIO.write(resizedImage, "png", f);
}
Can anyone please help?
I have two images with different sizes. I want to merge these two images so that the front images overlays correctly the background image.
background (width:144 height:147):
front: (width:227 height:238)
Currently my result looks like this, but i need it to overlay perfectly
My approach is.
I am resizing the smaller image to the bigger one. For that I am using the a external lib named imgscalr (https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib/4.2).
As you can see result image is not correct, so I tried to scale the front image so that it overlay the background, also I changed the root of the x / y when I draw the front image on the background but i still have a difference. Any idea how I can merge the two images, so that the strokes image (front) overlays the background.
public static byte[] mergeBackgroundWithStrokes(byte[] backgroundImage, byte[] frontImage)
throws IOException, PDProcessingException {
Path backgroundfile = readAllBytes(backgroundImage, "background");
Path outputFile = Files.createTempFile("output", ".png");
BufferedImage backgroundBuffImg = ImageIO.read(backgroundfile.toFile());
BufferedImage frontBuffImg = makeColorTransparent(frontImage, Color.WHITE);
int width = Math.max(backgroundBuffImg.getWidth(), frontBuffImg.getWidth());
int height = Math.max(backgroundBuffImg.getHeight(), frontBuffImg.getHeight());
backgroundBuffImg = resize(backgroundBuffImg, width, height);
//scaling front image
int scaledWidth = (int) ((width));
int scaledHeight = (int) ((height) * 1.02);
frontBuffImg = resize(frontBuffImg, scaledWidth, scaledHeight);
BufferedImage newImage = mergeImages(backgroundBuffImg, frontBuffImg);
ImageIO.write(newImage, "PNG", outputFile.toFile());
return Files.readAllBytes(outputFile);
}
public static BufferedImage resize(BufferedImage img, int width, int height)
{
if (img.getWidth() == width && img.getHeight() == height) {
return img;
} else {
return Scalr.resize(img, width, height);
}
}
public static BufferedImage mergeImages(BufferedImage background, BufferedImage front) {
int width = background.getWidth();
int height = background.getHeight();
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = newImage.getGraphics();
g.drawImage(background, 0, 0, null);
g.drawImage(front, 15, -10, background.getWidth(), background.getHeight(), 0, 0, width, height, null);
return newImage;
}
Here you can see the complete class: https://pastebin.com/F4VrBwRv
I created a java web application. In which i created program to resize and upload photos. This stored in a specific folder. When I changes the Photo it doesn't change and remains the old photo. But after restarting the TomCat I can change the photo. Why would this happen? Here is the code to resize and store image
public static int createThumbnailNew(String original,
String resized, int maxSize) {
try
{
File originalFile = new File(original);
ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());
Image i = ii.getImage();
int iWidth = i.getWidth(null);
int iHeight = i.getHeight(null);
BufferedImage originalImage = new BufferedImage(
i.getWidth(null), i.getHeight(null),
BufferedImage.TYPE_INT_RGB);
// Copy image to buffered image.
Graphics g = originalImage.createGraphics();
// Clear background and paint the image.
g.setColor(Color.white);
g.fillRect(0, 0, i.getWidth(null), i.getHeight(null));
g.drawImage(i, 0, 0, null);
g.dispose();
BufferedImage bufferedImage = null;
if (iWidth > iHeight) {
bufferedImage = resizeImage(originalImage, BufferedImage.TYPE_INT_RGB,(maxSize * iHeight)/iWidth,maxSize);
} else {
bufferedImage = resizeImage(originalImage, BufferedImage.TYPE_INT_RGB,maxSize,(maxSize * iWidth) / iHeight);
}
//BufferedImage croppedImage=cropImage(bufferedImage,crX,crY,crH,crW);
File file = new File(resized);
FileOutputStream out = new FileOutputStream(file);
/* encodes image as a JPEG data stream */
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
com.sun.image.codec.jpeg.JPEGEncodeParam param = encoder
.getDefaultJPEGEncodeParam(bufferedImage);
// writeParam = new JPEGImageWriteParam(null);
// writeParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
// writeParam.setProgressiveMode(JPEGImageWriteParam.MODE_DEFAULT);
param.setQuality(1.0f, true);
encoder.setJPEGEncodeParam(param);
encoder.encode(bufferedImage);
}
catch(Exception e)
{
return -1;
}
return 0;
}
private static BufferedImage resizeImage(BufferedImage originalImage, int type,int h,int w){
BufferedImage resizedImage = new BufferedImage(w, h, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, w, h, null);
g.dispose();
return resizedImage;
}
Please Help.. Thanks..
You haven't closed your opened files. That is one possible problem here.
I imported:
import javax.swing.ImageIcon;
and I used this code to import the PNG file. (i know i can create a black square easily, but it is the importing any image to my game that i want).
Image player1 = Toolkit.getDefaultToolkit().createImage("Users/Documents/JavaGameImages/Tag/BlackSquare.png");
I tried to call this image later down, but the image did not appear in the window. (assume myX = 100 and myY = 100)
public void paint(Graphics g) {
g.setColor(BackgroundColor);
g.fillRect(WindowWidth, WindowHeight, 1000, 1000);
/////////////////////// The code below is where i am having trouble:
g.drawImage(player1, myX, myY, null);
When you are building that code for distribution, you'll probably want to put the image into the jar file with the class files. What I do is put it into the same directory as the class that's accessing it, and then I access it with getClass().getResource(fileName), as in this snippet of code from a textured background border:
final Toolkit toolKit = Toolkit.getDefaultToolkit();
URL imgURL = getClass().getResource(textureFileName);
if (imgURL != null)
{
Image tmpImage = toolKit.createImage(imgURL);
toolKit.prepareImage(tmpImage, -1, -1,
new ImageObserver() {
public boolean imageUpdate(Image updatedImage, int infoFlags, int x,
int y, int width, int height)
{
if ((infoFlags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS)
{
int w = updatedImage.getWidth(null);
int h = updatedImage.getHeight(null);
BufferedImage backgroundImage = new BufferedImage(w, h,
BufferedImage.TYPE_INT_ARGB_PRE);
Graphics2D g = backgroundImage.createGraphics();
g.drawImage(updatedImage, 0, 0, null);
g.dispose();
Rectangle rect = new Rectangle(0, 0, w, h);
texture = new TexturePaint(backgroundImage, rect);
return false;
}
return true;
}
});
}
I am trying to rotate an instance of a BufferImage named pic when I try this it resizes and skews and crops the image, any advice to get it to work properly
public void rotate(double rads){
AffineTransform tx = new AffineTransform();
tx.rotate(rads,pic.getWidth()/2,pic.getHeight()/2);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
pic = op.filter(pic, null);
}
When I have it rotate 90˚ it works fine so I'm wondering if the problem is that it is the shape of the image?
For use with AffineTransform, you can square an image using something like this:
private BufferedImage getImage(String name) {
BufferedImage image;
try {
image = ImageIO.read(new File(name));
} catch (IOException ioe) {
return errorImage;
}
int w = image.getWidth();
int h = image.getHeight();
int max = Math.max(w, h);
max = (int) Math.sqrt(2 * max * max);
BufferedImage square = new BufferedImage(
max, max, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = square.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(image, (max - w) / 2, (max - h) / 2, null);
g2d.dispose();
return square;
}