I am new to image processing in java and I am trying to convert an image to stencil (I think stencil is name given for it!).
The input image is this:-
After processing the image would be like this:-
I searched google. But could find a solution. (maybe because I don't know what is the actual name of this process.)
Is this possible with java?
Yes I found the solution. if we Binarize an image it will work.
Input image:-
Output Image:-
Code:-
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Main {
public static void main(String[] args) throws IOException {
BufferedImage bi = ImageIO.read(new File("D:\\IMG_20211029_124954.jpg"));
ImageIO.write(binarizeImage(bi), "png", new File("D:\\1.png"));
}
public static BufferedImage binarizeImage(BufferedImage img_param)
{
BufferedImage image = new BufferedImage(
img_param.getWidth(),
img_param.getHeight(),
BufferedImage.TYPE_BYTE_BINARY
);
Graphics g = image.getGraphics();
g.drawImage(img_param, 0, 0, null);
g.dispose();
return image;
}
}
To make the image transparent , You can do something like this:-
for(int i=0;i<img.width;i++){
for(int j=0;j<img.height;j++){
Color c = new Color(255,255,255,0);
if(img.getRGB==Color.white.getRGB){
img.setRGB(i,j,c.getRGB)
}
}
}
Related
What is the shortest code one can write in java to break an image (say 200x1000) into 10 images of a tenth height but same width (200x 100)?
Mine is a pretty long code; the main part , I am just giving:
for (int i_=0;i_<10;i_++)
{
for(int k=i_*100;k<i_*100+h/10;k++)
{
for(int j_=0;j_<w;j_++)
{
int pixv=img.getRGB(j_,k);
r=(pixv>>16)&0xff;
g=(pixv>>8)&0xff;
b=(pixv)&0xff;
int rgb=new Color(r,g,b).getRGB();
img.setRGB(j_,k-i_*200,rgb);
}
}
// Here I am writing the img to a new .bmp file thus creating 10 seperate files
}
Here img is a BufferedImage
w,h the width and height of large image
you can get a sub image from BufferedImage using getSubimage(int x,int y,int w,int h). Try this:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class NewClass9 {
public static void main(String[] args) throws IOException{
BufferedImage img = null;
img = ImageIO.read(new File("C:\\users\\uzochi\\desktop\\Penguins.jpg"));
for(int i = 0;i<10;i++){
BufferedImage sub = img.getSubimage(0, i*(img.getHeight()/10), img.getWidth(), img.getHeight()/10);
File f = new File("C:\\users\\uzochi\\desktop\\SubImage"+i+".png");
ImageIO.write(sub, "png", f);
}
}
}
I've got a method that's supposed to add some text to screenshots. The screenshot is fed into this method as a File object like this:
private void modifyScreenshot(File file) throws Exception {
String textToAdd = "Something something";
BufferedImage image = ImageIO.read(file);
Graphics g = image.getGraphics();
At this point, adding the text via g.drawString is easy to do. However, I want the text to not cover any of the actual screenshot, but be in a white area "above" the screenshot.
What I mean is, at this point, this is what the Graphics object looks like when it gets saved to file:
However, I want it to look like this instead, with the "Some text some text" being the string I specify in the code.
So, how would I be able to add white rectangle above the image where the text can be written?
EDIT: Note, this is not simply adding a string to an image. This involves "enlarging" the canvas to have white space for the string, so that the string is not over the actual image.
Here's the rough idea:
BufferedImage image = ImageIO.read(file);
int whiteSpaceHeight = 20;
BufferedImage result = new BufferedImage(image.getWidth(),
image.getHeight()+whiteSpaceHeight, image.getType());
Graphics graphics = result.getGraphics();
graphics.drawImage(image, 0, whiteSpaceHeight, null);
graphics.drawString(textToAdd, 0, whiteSpaceHeight/2);
(Edit: Answer was rewritten - see history for details)
The task that is indicated in the example image may in fact be a bit tricky: Namely, having multi-line text. But one simple solution here is to use a JLabel and a CellRendererPane for rendering the text, because it also supports HTML. So for a title like
String title =
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
with line breaks and colors and a dedicated font size, one can obtain the appropriate image:
Here is an example showing how this may be achieved:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import javax.swing.CellRendererPane;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class TitleAdder
{
public static void main(String[] args)
{
addTitle("yS2aQ.png", "output.png",
"<html><font size=4>This <font color=#FF0000><b>Text</b></font><br>" +
"with line breaks<br>" +
"will be the title</font></html>");
}
private static void addTitle(
String inputFileName, String outputFileName, String title)
{
try (InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName))
{
BufferedImage sourceImage = ImageIO.read(in);
BufferedImage targetImage =
addTitle(sourceImage, title);
ImageIO.write(targetImage, "png", out);
// Show the image, for testing
show(targetImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
private static BufferedImage addTitle(
BufferedImage sourceImage, String title)
{
JLabel label = new JLabel(title);
label.setBackground(Color.WHITE);
label.setForeground(Color.BLACK);
label.setOpaque(true);
int titleHeight = label.getPreferredSize().height;
int height = sourceImage.getHeight() + titleHeight;
BufferedImage targetImage = new BufferedImage(
sourceImage.getWidth(), height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = targetImage.createGraphics();
SwingUtilities.paintComponent(g, label, new CellRendererPane(),
0, 0, sourceImage.getWidth(), titleHeight);
g.drawImage(sourceImage, 0, titleHeight, null);
g.dispose();
return targetImage;
}
private static void show(final BufferedImage image)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
JFrame f = new JFrame();
f.getContentPane().add(new JLabel(new ImageIcon(image)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
This question already has answers here:
decrease image resolution in java
(4 answers)
Closed 8 years ago.
can any one help me..?
I have some .jpg's created from JPanel. Unfortunately its DPI is 72. Is there a programmatic way to change the DPI of these .jpg's ?
Now i use following code for change DPI. But it have some issues when i try to build project.
`JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(new FileOutputStream(outfile));
JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);
jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
jpegEncodeParam.setXDensity(300);
jpegEncodeParam.setYDensity(300);
jpegEncoder.encode(image, jpegEncodeParam);`
Thanks in advance :)
You can scale an image using Graphics2D methods (from java.awt). This tutorial at http://www.mkyong.com/java/how-to-resize-an-image-in-java explains it in depth.
here is an example
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import javax.imageio.*;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.io.File;
import java.io.FileOutputStream;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.swing.ImageIcon;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageManipulation {
public static void main(String[] args) throws Exception {
File infile = new File("/your image.jpg");
File outfile = new File("/your image.jpg");
ImageReader reader = ImageIO.getImageReadersByFormatName("jpeg").next();
reader.setInput(new FileImageInputStream(infile), true, false);
IIOMetadata data = reader.getImageMetadata(0);
BufferedImage image = reader.read(0);
int w = 600, h = -1;
Image rescaled = image.getScaledInstance(w, h, Image.SCALE_AREA_AVERAGING);
BufferedImage output = toBufferedImage(rescaled, BufferedImage.TYPE_INT_RGB);
Element tree = (Element) data.getAsTree("javax_imageio_jpeg_image_1.0");
Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
for (int i = 0; i < jfif.getAttributes().getLength(); i++) {
Node attribute = jfif.getAttributes().item(i);
System.out.println(attribute.getNodeName() + "="
+ attribute.getNodeValue());
}
FileOutputStream fos = new FileOutputStream(outfile);
JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(fos);
JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(output);
jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
jpegEncodeParam.setXDensity(300);
jpegEncodeParam.setYDensity(300);
jpegEncoder.encode(output, jpegEncodeParam);
fos.close();
}
public static BufferedImage toBufferedImage(Image image, int type) {
int w = image.getWidth(null);
int h = image.getHeight(null);
BufferedImage result = new BufferedImage(w, h, type);
Graphics2D g = result.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return result;
}
}
There is a similar question about resolution, answered in the following SO question here.
In general, you may be interested in learning image processing algorithms, which are described here:
The basic concept in decreasing resolution is that you are selectively
deleting data from the image.
I am working on a project related to colored image manipulation using JAVA.
I got to know the conversion of the colored image into a matrix using a getSample method of Raster class,
pixels[x][y]=raster.getSample(x,y,0);
I got the matrix in pixels[][] (only the values in red band).
Then i converted the matrix back to image using WritableRaster as,
raster.setSample(i,j,0,pixels[i][j]);
I converted it to image using,
*BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
image.setData(raster);*
But the problem is,
1) I want the colored image to be displayed as it is whereas i am getting only a particular band(like only red, only blue . . ) because I have to specify a band as per the prototype of the method setSample and getenter code hereSample.
2) How can i get a 2d matrix representing a colored image(of all 3 bands represented in 3 different matrices)
Here is the code that i wrote with the help of snippets of code online...
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
class TestImage {
ImageIcon icon;
SampleModel sampleModel;
public static void main(String args[]){
TestImage mamu = new TestImage();
File file = new File("photo.jpg");
mamu.compute(file);
}
public void compute(File file){
try{
BufferedImage img= ImageIO.read(file);
Raster raster=img.getData();
sampleModel = raster.getSampleModel();
int w=raster.getWidth(),h=raster.getHeight();
int pixels[][]=new int[w][h];
for (int x=0;x<w;x++){
for(int y=0;y<h;y++){
pixels[x][y]=raster.getSample(x,y,0);
}
}
Image image = getImage(pixels);
JFrame frame = new JFrame("uff");
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel(icon);
frame.setContentPane(label);
frame.setVisible(true);
frame.setSize(200,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}catch (Exception e){
e.printStackTrace();
}
}
public java.awt.Image getImage(int pixels[][]){
int w=pixels.length;
int h=pixels[0].length;
WritableRaster raster= Raster.createWritableRaster(sampleModel, new Point(0,0));
for(int i=0;i<w;i++){
for(int j=0;j<h;j++){
raster.setSample(i,j,0,pixels[i][j]);
}
}
BufferedImage image=new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
image.setData(raster);
File output=new File("check.jpg");
try {
ImageIO.write(image,"jpg",output);
}catch (Exception e){
e.printStackTrace();
}
return image;
}
}
You may be looking or java.awt.image.LookupOp, which uses a java.awt.image.LookupTable to modify bands en bloc. Several examples are cited here. The image below illustrates inversion:
short[] invert = new short[256];
for (int i = 0; i < 256; i++) {
invert[i] = (short) (255 - i);
}
BufferedImageOp invertOp = new LookupOp(new ShortLookupTable(0, invert), null));
invertOp.filter(src, dst);
My issue: Every time I create graphics from a buffered image and then draw another buffered image to the graphics I get an image that is blank.
My code is as follows.
Graphics2D g2d = atlas.createGraphics();
// images[i] is a buffered image read the fileio
g2d.drawImage(images[i], null, x, y); // Image is not blank, been tested
g2d.dispose();
// then save image
Ironically after trying to create a self contained example which is as follows... it worked. I am not quite sure what I am doing wrong in my code and I am wondering if it is because maybe an image is not static, could an image or another variable not being static affect my drawing?
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class Main {
public static void main(String[] args) {
String FOLDER_LOCATION = "./Images/";
BufferedImage atlas = new BufferedImage(2048, 2048, BufferedImage.TYPE_INT_ARGB);
BufferedImage redSquare = readImage(FOLDER_LOCATION + "red.png");
Graphics2D g2d = atlas.createGraphics();
g2d.drawImage(redSquare, null, 0, 0);
g2d.dispose();
writeImage(atlas, FOLDER_LOCATION + "atlas.png");
}
public static BufferedImage readImage(String location) {
BufferedImage img = null;
InputStream is = null;
try {
is = new FileInputStream(location);
img = ImageIO.read(is);
} catch(Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch(Exception e) {
e.printStackTrace();
}
}
return img;
}
public static void writeImage(BufferedImage bi, String location) {
try {
File file = new File(location);
ImageIO.write(bi, "png", file);
} catch(Exception e) {
e.printStackTrace();
}
}
}
After I save the image I see just a blank 2048 by 2048 image. I printed the entire image out and I get (0, 0, 0), but if I print out any of the image I am drawing to the atlas I get something like (72, 32, 283).
I am not quite sure what I am doing wrong, but my entire source code for this project is here: https://github.com/gemurdock/jTextureAtlas and the branch I am working on is here: https://github.com/gemurdock/jTextureAtlas/tree/alpha.
You have to look at the alpha branch to see my code