JAVA Using ImageIO.read and paintComponents() - java

I programmed a class, which helps me to get 32x32 images from a large one. But I have a problem. My class looks like this:
package tool;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageLoader {
private String file;
private BufferedImage image;
private BufferedImage[][] subImage;
public ImageLoader(String FILE) {
file = FILE;
try {
image = ImageIO.read(new File(file));
} catch (IOException e) {
}
subImage = new BufferedImage[image.getWidth() / 32][image.getHeight() / 32];
for (int i = 0; i < image.getWidth() / 32; i++) {
for (int j = 0; j < image.getHeight() / 32; j++) {
subImage[i][j] = image.getSubimage(i * 32, j * 32, (1 + i) * 32, (1 + j) * 32);
}
}
}
public BufferedImage getSubImage(int X, int Y) {
return subImage[X][Y];
}
}
If I do it that way, it seems the ImageIO.read(new File(String file)) command prevents the use of paintComponent() of that Swing object, where I want to draw the image. I experimented a little bit and found out, that when you load the image in the getSubImage(int X, int Y) method, it works fine. But I think, it's not the smartest idea, because then you always load this image again, if you call the method. I need help, how I can load that image just one time and that the Swing object draw everthing correctly.
Thanks in advance.

Write the thumbnail and load it back in a JLabel instead.
//get the large file and create a new 32x32 thumbnail
BufferedImage sourceImage = ImageIO.read(new FileInputStream("c://filename"));
Image thumbnail = sourceImage.getScaledInstance(32, 32, Image.SCALE_SMOOTH);
BufferedImage bufferedThumbnail = new BufferedImage(thumbnail.getWidth(null),
thumbnail.getHeight(null),
BufferedImage.TYPE_INT_RGB);
bufferedThumbnail.getGraphics().drawImage(thumbnail, 0, 0, null);
//read the file back
ImageIO.write(bufferedThumbnail, "jpeg", outputStream);
//read the file back
image = ImageIO.read(new File(path));
JLabel picLabel = new JLabel(new ImageIcon(image));

Related

ImageIO.write not writing image into folder

I am working on a project in which I am trying to store all the pixels of a jpg image in an array, and then using that array to write a copy of the original image in a different folder. However, I do not seem to be able to write the copy into the folder. I know that the issue has something to do with the copy of the image I created, since the writing works perfectly if I use the original image as the parameter in ImageIO.write, but i'm still not entirely sure what the issue is. Does anyone know what sort of error I may be encountering, and what I could do to fix it? (For additional context, I know that reading/writing can be implemented without using arrays, but I want to use arrays to implement this)
Code for reference:
package com.company;
import java.io.File;
import java.util.Scanner;
import java.util.concurrent.*;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
public class filereader {
public static void main(String[] args) throws IOException {
int width = 1536;
int height = 2048;
BufferedImage image = null;
BufferedImage newimage = null;
int[][] newarray = new int[height][width];
File f = null;
File g = null;
try {
System.out.println("Insert your file");
Scanner scanney = new Scanner(System.in);
String arg1 = scanney.next();
f = new File(arg1);
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
image = ImageIO.read(f);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
newarray[i][j] = image.getRGB(j, i);
}
}
} catch (IOException e) {
System.out.println("Error:" + e);
}
try {
newimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
System.out.println(newimage.getType());
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int newimagestuff = newarray[i][j];
newimage.setRGB(j, i, newimagestuff);
}
}
int i = 0;
g = new File("C:\\Users\\user1\\Documents\\File Reading\\Outputest.jpg");
ImageIO.write(newimage,"jpg", g);
System.out.println(newimage);
System.out.println(image);
} catch (IOException e) {
System.out.println("Error:" + e);
}
}
}
There are several issues with your code:
You create two new BufferedImages - the first one is completely useless as you are overwriting it in the next line with the result of ImageIO.read().
The second BufferedImage you create has the type BufferedImage.TYPE_INT_ARGB which is probably wrong as JPG images don't have an alpha channel (thats the "A" in the type). You rather should use the type of the image read in with ImageIO.
Also why do you copy pixel by pixel when you could read always a complete row - if it has to be a two-dimensional array for intermediate storage - or even the complete image at once - if a single-dimensional image would suffice. You can use public int[] getRGB​(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) and the matching setRGB method for this.
I think escaping the space in your file path might help. Like that:
g = new File("C:\\Users\\user1\\Documents\\File\ Reading\\Outputest.jpg");

generating design with java

i am trying to generate following given sateen design with help of my java code but this code is not creating png file named sateen
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Sateen {
BufferedImage image;
int width;
int height;
int red,green,blue;
public Sateen() {
try {
File input = new File("n.png");
image = ImageIO.read(input);
width = image.getWidth();
height = image.getHeight();
//n is png file with only white pixels
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
Color p = new Color(image.getRGB(j, i));
Color g = new Color(image.getRGB(j+5, i));
//getting (j,i) coordinate pixel value and then comparing it to next 5th pixel
if(p.getRed()==255&&p.getBlue()==255&&p.getGreen()==255&&g.getRed()==255&&
g.getBlue()==255&&g.getGreen()==255)
{ red=0;
blue=0;
green=0; }
//if both pixel value is white then setting 5th pixel value to black
Color newColor = new Color(red,green,blue);
image.setRGB(j+5,i,newColor.getRGB());
j=j+5;
}
}
File ouptut = new File("Sateen.png");
ImageIO.write(image, "png", ouptut);
//creating sateen png file
} catch (Exception e) {}
}
static public void main(String args[]) throws Exception
{
Sateen obj = new Sateen();
}
}
Seems to actually create a .png file (make sure the filepath is correct?). However this code will not generate a sateen pattern, rather draws black pixels at column 6, 12, 18 etc.
The following code fixes some issues in your code. Although it produces an output file but the output file does not look like what you are trying to produce. Perhaps you need to tweak your algorithm?
Anyway the main thing to learn here is that if you are looping over arrays and incrementing the index within the loop then you need to take care of the situation where your index might go out of bounds of the array i.e. your j+5 can be anything outside the image.
Also, make sure that your input file is in the correct location which will depend on where you run the program from. If you run it from the debugger/IDE then it should be inside the project folder next to the src folder. It would be better if you specify full path to your file i.e. C:\SomeFolder\n.png to avoid input file missing error.
Finally, use something like e.printStackTrace(); in your catch block to find out where and why your code is failing.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class Sateen {
BufferedImage image;
int width;
int height;
int red, green, blue;
public Sateen() {
try {
File input = new File("n.png");
image = ImageIO.read(input);
width = image.getWidth();
height = image.getHeight();
// n is png file with only white pixels
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) { // may not need j++ as you are doing j+5?
Color p = new Color(image.getRGB(j, i));
int jPlus5 = j + 5;
if (jPlus5 < width) {
Color g = new Color(image.getRGB(jPlus5, i));
// getting (j,i) coordinate pixel value and then
// comparing
// it to next 5th pixel
if (p.getRed() == 255 && p.getBlue() == 255 && p.getGreen() == 255 && g.getRed() == 255 &&
g.getBlue() == 255 && g.getGreen() == 255)
{
red = 0;
blue = 0;
green = 0;
}
// if both pixel value is white then setting 5th pixel
// value
// to black
Color newColor = new Color(red, green, blue);
image.setRGB(jPlus5, i, newColor.getRGB());
}
j = jPlus5;
}
}
File ouptut = new File("Sateen.png");
ImageIO.write(image, "png", ouptut);
// creating sateen png file
} catch (Exception e) {
e.printStackTrace();
}
}
static public void main(String args[]) throws Exception
{
Sateen obj = new Sateen();
}
}

How to flip and save Image

My Image declaration:
ImageIcon imageIcon1 = new ImageIcon(main.class.getResource("image1.png"));
Image image1 = imageIcon1.getImage();
How do I take image1, flip it along it's vertical axis and save it as another image?
I have googled and every solution I have found has come with some type of casting error.
Also, if there is a more efficient way to declare my image please let me know.
You state:
I have googled and every solution I have found has come with some type of casting error.
Which only tells us that you're doing something wrong but doesn't tell us what, limiting how we can help you. I can only tell you some steps that have worked for me:
Create another BufferedImage the same size as the first,
get its Graphics2D context via createGraphics(),
flip the graphics via an AffineTransform.getScaleInstance(-1, 1) for a horizontal flip
Don't forget to then translate the transform to bring the flipped image to where you want it.
draw the old image into the new image,
dispose the Graphics2D object.
If you need more help, then please show us what you've tried and include any and all error messages.
For instance, I played with this when playing with mirror sprite images a while back. Compile and run this to see what I mean:
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class FlipViaTransform {
private static final String SPRITE_SHEET_SPEC = "http://www.funorb.com/img/images/game/"
+ "central/dev_diary/sprite_sheet_full.gif";
private static final int TIMER_DELAY = 200;
private static final int SPRITE_ROWS = 8; // an 8 x 8 sprite sheet
public static void main(String[] args) {
try {
URL spriteSheetUrl = new URL(SPRITE_SHEET_SPEC);
BufferedImage spriteSheet = ImageIO.read(spriteSheetUrl);
final ImageIcon[] iconsA = new ImageIcon[64];
final ImageIcon[] iconsB = new ImageIcon[64];
double wD = (double) spriteSheet.getWidth() / SPRITE_ROWS;
double hD = (double) spriteSheet.getHeight() / SPRITE_ROWS;
int w = (int) wD;
int h = (int) hD;
// *** here's what I used to flip
AffineTransform at = AffineTransform.getScaleInstance(-1, 1); // *** flip
at.translate(-wD, 0); // *** translate so that flipped image is visible
for (int i = 0; i < SPRITE_ROWS; i++) {
for (int j = 0; j < SPRITE_ROWS; j++) {
int x = (int) (i * wD);
int y = (int) (j * hD);
BufferedImage imgA = spriteSheet.getSubimage(x, y, w, h);
BufferedImage imgB = new BufferedImage(imgA.getWidth(),
imgA.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = imgB.createGraphics();
g2.setTransform(at); // *** transform
g2.drawImage(imgA, 0, 0, null); // *** draw old image into new
g2.dispose(); // *** get rid of graphics2d object
iconsA[j * SPRITE_ROWS + i] = new ImageIcon(imgA);
iconsB[j * SPRITE_ROWS + i] = new ImageIcon(imgB);
}
}
final JLabel labelA = new JLabel("Image");
final JLabel labelB = new JLabel("Mirror Image");
labelA.setVerticalTextPosition(JLabel.BOTTOM);
labelB.setVerticalTextPosition(JLabel.BOTTOM);
labelA.setHorizontalTextPosition(JLabel.CENTER);
labelB.setHorizontalTextPosition(JLabel.CENTER);
labelA.setIcon(iconsA[0]);
labelB.setIcon(iconsB[0]);
final JPanel panel = new JPanel(new GridLayout(1, 0));
panel.add(labelA);
panel.add(labelB);
Timer spriteTimer = new Timer(TIMER_DELAY, new ActionListener() {
int spriteIndex = 0;
#Override
public void actionPerformed(ActionEvent arg0) {
labelA.setIcon(iconsA[spriteIndex]);
labelB.setIcon(iconsB[spriteIndex]);
spriteIndex++;
spriteIndex %= iconsA.length;
}
});
spriteTimer.start();
JOptionPane.showMessageDialog(null, panel, "AffineTransform Example", JOptionPane.PLAIN_MESSAGE);
spriteTimer.stop();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
which displays as:
I have never done this, but you can try to research if you can use a 3d party library such as ImageMagick or GraphicsMagic with Java. Those libraries can read PNG images and perform graphics operation on them.

Wider/Taller Images Get Distorted

I'm loading an image using C++ and feeding the pixels to JNI via a ByteBuffer. I know the pixels are being fed just fine because if the images are square, they render perfectly fine. If they are rectangular, they get distorted. I've also saved the Image back successfully in the DLL and it works. Java unfortunately gave up on me (unless it's square-like). I cannot figure out why! What am I doing wrong?
package library;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Frame extends JFrame {
public Frame(int Width, int Height, String FrameName, BufferedImage Buffer) {
setName(FrameName);
setSize(Width, Height);
getContentPane().add(new JLabel(new ImageIcon(Buffer)));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setVisible(true);
}
}
All the loading:
package library;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.nio.ByteBuffer;
class SharedLibrary {
static{System.loadLibrary("TestDLL");}
private static native void GetGLBuffer(ByteBuffer Buffer);
private ByteBuffer Buffer = null;
private int ByteSize = 0, Width = 0, Height = 0, BitsPerPixel = 32;
public SharedLibrary(int ImageWidth, int ImageHeight) throws IOException {
Width = ImageWidth;
Height = ImageHeight;
ByteSize = ((Width * BitsPerPixel + 31) / 32) * 4 * Height; //Compute Image Size in Bytes.
Buffer = ByteBuffer.allocateDirect(ByteSize); //Allocate Space for the image data.
GetGLBuffer(Buffer); //Fill the buffer with Image data from the DLL.
byte[] Bytes = new byte[ByteSize];
Buffer.get(Bytes);
BufferedImage Image = new BufferedImage(Width, Height, BufferedImage.TYPE_3BYTE_BGR);
WritableRaster raster = (WritableRaster) Image.getData();
raster.setPixels(0, 0, Width, Height, ByteBufferToIntBuffer(Bytes));
Image.setData(raster);
Frame F = new Frame(Width, Height, "", Image);
}
private int[] ByteBufferToIntBuffer(byte[] Data) {
int IntBuffer[] = new int[Data.length];
for (int I = 0; I < Data.length; I++) {
IntBuffer[I] = (int)Data[I] & 0xFF;
}
return IntBuffer;
}
}
The above Image Gets drawn perfectly because it is almost square. If I resize it to a rectangle, it gets distorted. Example:
Gets distorted and looks like:

Java Combine multiple images into a single bigger image without overlapping

I'm trying to combine several images into a larger image using Java. The images that are passed in are all height 127 x width 293. The idea is that a number of images are passed to the method and the method takes the images and builds them into another larger image. There is going to be a layout for the larger image where a total of 12 possible images can be input to the larger image, spaced out evenly (2 rows of 6 images, none overlapping). If there are fewer than 12 images passed in, then only the first however many spaces will be filled, the rest of the image will be white because the background is to going to be white. When I run the program it prints the larger image, but it will only fill the first space showing the first image in the upper left, regardless of how many images are passed in. Also the background is a pinkish color instead of the intended white background. I'm only a beginner with Java so I'm trying to work through some of these learning pains. Any advice on how I might be able to solve my problem? (Code is copied below for reference) Thanks!
public class ImagesCombine {
public String BuildImgs (File[] imgs)throws IOException {
int arsize = imgs.length;
File path = new File("Z:/JAVAFiles/Images/");
BufferedImage page = new BufferedImage(620,900,BufferedImage.TYPE_INT_ARGB);
Graphics2D paint;
paint = page.createGraphics();
paint.setPaint(Color.WHITE);
paint.fillRect ( 0, 0, page.getWidth(), page.getHeight() );
paint.setBackground(Color.WHITE);
String tmpname = "";
for (int i=0;i<imgs.length;i++){
if(i==0){
Image img0 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img0,0,0,null);
paint.dispose();
}
if(i==1){
Image img1 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img1,323,0,null);
paint.dispose();
}
if(i==2){
Image img2 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img2,0,142,null);
paint.dispose();
}
if(i==3){
BufferedImage img3 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img3,323,142,null);
paint.dispose();
}
if(i==4){
BufferedImage img4 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img4,0,284,null);
paint.dispose();
}
if(i==5){
BufferedImage img5 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img5,323,284,null);
paint.dispose();
}
if(i==6){
BufferedImage img6 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img6,0,426,null);
paint.dispose();
}
if(i==7){
BufferedImage img7 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img7,323,426,null);
paint.dispose();
}
if(i==8){
BufferedImage img8 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img8,0,568,null);
paint.dispose();
}
if(i==9){
BufferedImage img9 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img9,323,568,null);
paint.dispose();
}
if(i==10){
BufferedImage img10 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img10,0,710,null);
paint.dispose();
}
if(i==11){
BufferedImage img11 = ImageIO.read(new File(path, imgs[i].getName()));
paint.drawImage(img11,323,710,null);
paint.dispose();
}
}
String outpath = "Z:\\JAVAFiles\\" + imgs[0].getName().substring(0,16) + ".jpg";
OutputStream outfile = new FileOutputStream(outpath);
JPEGImageEncoder encoder2 = JPEGCodec.createJPEGEncoder(outfile);
encoder2.encode(page);
outfile.close();
return("Success");
}
}
The first thing I notice is that you're calling dispose() on the Graphics2D after each image draw. This is probably why you're only seeing one image being drawn in the larger image. Take out that call and place it after the loop and you should start seeing more images.
As a side note, you can simplify your for-loop a lot:
int width = 293;
int height = 127;
for (int i=0; i < Math.min(imgs.length, 12); i++){
Image image = ImageIO.read(new File(path, imgs[i].getName()));
int row = i / 6; // This will truncate to 0 or 1.
int column = i % 6; // Mod will produce the remainder of i / 6 in the range 0-5
paint.drawImage(image, column * width, row * height, null);
}
You are calling the dispose method inside a for loop so when the program completes the first run of the code inside the loop it then gets rid of the paint object. When it's time to browse the loop for a second time, the program can't find the paint object so it can neither draw the next image nor fill the room with white.
Try using the dispose method right after you close your for loop.
You can also try adding some println methods to see what length does the imgs item return. You should generally check the numbers inside the variables you use in your loop to see if you are getting what you want.
Create a panel that uses a GridLayout? Then you can add 12 JLabels to the panel with each label containing an ImageIcon. This way the layout manager does all the hard work of positioning and painting the images.
This can be done in java, below is the sample program.
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class CombineImages {
public static void main(String[] args) throws IOException {
int imagesCount = 4;
BufferedImage images[] = new BufferedImage[imagesCount];
for(int j = 0; j < images.length; j++) {
images[j] = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = images[j].createGraphics();
g2d.drawRect(10, 10, 80, 80);
g2d.dispose();
}
int heightTotal = 0;
for(int j = 0; j < images.length; j++) {
heightTotal += images[j].getHeight();
}
int heightCurr = 0;
BufferedImage concatImage = new BufferedImage(100, heightTotal, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = concatImage.createGraphics();
for(int j = 0; j < images.length; j++) {
g2d.drawImage(images[j], 0, heightCurr, null);
heightCurr += images[j].getHeight();
}
g2d.dispose();
ImageIO.write(concatImage, "png", new File("/Users/kumarabhishek/Downloads/downloadedFiles/concat.png")); // export concat image
ImageIO.write(images[0], "png", new File("/Users/kumarabhishek/Downloads/downloadedFiles/single.png"));
}
}

Categories