i have 2D array( it's only 1 -0 values) but its type is int[][].
Now i want to convert that array into image ( binary image black and white). But i couldn't find suitable answer for my question. I have searched google and this website. Can anyone help me??
I have tried this following code, but it
String path = "C:\\Users\\Cyrus\\Desktop\\test.jpg";
BufferedImage image = new BufferedImage(b.length, b[0].length, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < b.length; x++) { // b is my 2D array
for (int y = 0; y < b[x].length; y++) {
image.setRGB(x, y, b[x][y]);
}
}
File ImageFile = new File(path);
try {
ImageIO.write(image, "jpg", ImageFile);
} catch (IOException e) {
e.printStackTrace();
}
// after i modify my code
String path = "C:\\Users\\Cyrus\\Desktop\\test.jpg";
BufferedImage image = new BufferedImage(a.length, a[0].length, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < a.length; x++) {
for (int y = 0; y < a[x].length; y++) {
int value ;
if(a[x][y]==1) value = new Color(255,255,255).getRGB();
else value = new Color(0,0,0).getRGB();
image.setRGB(x, y, value);
}
}
File ImageFile = new File(path);
try {
ImageIO.write(image, "jpg", ImageFile);
} catch (IOException e) {
e.printStackTrace();
}
But it return wrong image
Can you be more specific on the result you get? Did it throw some exceptions? or the program finished normally but didn't produce the result you want?
You should notice that here you want to work with binary image, then is there any specific reason to choose JPG? As I know, JPG is not a native representation of color triplet RGB (as bmp for example). a jpeg file is a "container" of data sequence, in which there are a lot of information in its header (EXIF, QT,...), marked by markers. To deal with pixel value "directly" as in your array, the data sequence in jpg file must be "decoded", then after you play it the image, the main image data will be "encoded" again to be jpg stream.
To play directly with pixel value, I suggest you work with other formats (such as TGA, png,...)
Related
What I need to do is I have a input image file and I need to change it as user's parameters. For example if user wants to make it %30 darker, first I get all pixels with their RGB values and store them in an 2D array. Sample array given below.
114 121 140 //Pixel 1
114 121 140 //Pixel 2
114 121 140 //Pixel 3
.
.
.
50 57 83 //Pixel 2073601
After that I overwrite that RGB values (in our case if RGB values are 10:10:10, new values will be 7:7:7). Everything from that point is ok. But now I'm facing some difficulties about creating my output.jpg file using my new array of information. When I run my function, it does not creates any output.jpg file. Here is my function.
public static void createFinalImage(int height, int width, String[][] rgbArray, String outputFile) {
BufferedImage img;
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
File f;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
String[] data = rgbArray[y][x].split(" ");
int red = Integer.parseInt(data[0]);
int green = Integer.parseInt(data[1]);
int blue = Integer.parseInt(data[2]);
int rgb = new Color(red,green,blue).getRGB();
img.setRGB(x,y,rgb);
}
}
try
{
f = new File(outputFile);
ImageIO.write(img, "jpg", f);
}
catch(IOException e)
{
System.out.println("Error: " + e);
}
}
I cant understand what is the problem and why I cant get darker image using this function. (I know there is always easier and basic ways to do it but this is an multithreading assignment and I must do it like I explained.) If anyone help me, I would be appreciated.
The ImageIO.write(...) methods return a boolean indicating whether or not there is a plugin installed that can write the image in the given format. It's good practice to check this value. While there is always a JPEG plugin installed, in recent versions of Java the JPEG plugin no longer supports images with alpha channel. Most other software don't support 4 channel RGBA JPEGs anyway, so it's not a big loss...
All you need is to change BufferedImage.TYPE_INT_ARGB to a type without alpha, like BufferedImage.TYPE_INT_RGB or TYPE_3BYTE_BGR, and things will work. You don't seem to use the alpha channel anyway.
The important changes:
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Manipulate pixels
}
}
try {
File f = new File(outputFile);
if (!ImageIO.write(img, "JPEG", f)) {
System.err.println("No plugin to write " + img + " in JPEG format to " + f);
}
}
catch (IOException e) {
System.out.println("Error: " + e);
}
As #HaraldK said, in my function I was using BufferedImage.TYPE_INT_ARGB as parameter. But since I have no alpha value, I just changed it as BufferedImage.TYPE_INT_RGB. Modified function given below and it works as normal.
public static void createFinalImage(int height, int width, String[][] rgbArray, String outputFile) {
BufferedImage img;
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
File f;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
String[] data = rgbArray[y][x].split(" ");
int red = Integer.parseInt(data[0]);
int green = Integer.parseInt(data[1]);
int blue = Integer.parseInt(data[2]);
int rgb = new Color(red,green,blue).getRGB();
img.setRGB(x,y,rgb);
}
}
try
{
f = new File(outputFile);
ImageIO.write(img, "jpg", f);
}
catch(IOException e)
{
System.out.println("Error: " + e);
}
}
This question already has answers here:
reading black/white image in java with TYPE_USHORT_GRAY
(2 answers)
Closed 2 years ago.
I have tried to grayscale a already black-white-gray picture and it become black.
When I try to grayscale a picture with Java, I do like this:
// This turns the image data to grayscale and return the data
private static RealMatrix imageData(File picture) {
try {
BufferedImage image = ImageIO.read(picture);
int width = image.getWidth();
int height = image.getHeight();
RealMatrix data = MatrixUtils.createRealMatrix(height * width, 1);
// Convert to grayscale
int countRows = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Turn image to grayscale
int p = image.getRGB(x, y);
int r = (p >> 16) & 0xff;
int g = (p >> 8) & 0xff;
int b = p & 0xff;
// calculate average and save
int avg = (r + g + b) / 3;
data.setEntry(countRows, 0, avg);
countRows++;
}
}
return data;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
The problem what I see is that p is an 32-bit value and I only want 8-bit value. Even if the picture is already grayscaled, the p value is already a 32-bit value. That cause trouble for me.
So if I grayscale a gray picture, it will become black. Or at least darker.
And I want 0..255 values of p, which is a 32-bit integer value.
Do you have any suggestions how to read pictures as they where 8-bit?
It's for image classification.
Summarize:
I need help to get each pixels from a picture in 0..255 format.
One way is to gray scale it, but how can I verify if the picture is already gray scaled?
Update:
I have tried to read a picture as it was 8-bit values. It works. Then I try to save the picture with the same values. The picture becomes very dark.
I have a matlab example I want to show.
First I read my picture:
image = imread("subject01.normal");
And then I save the picture.
imwrite(uint8(image), "theSameImage.gif")
If I try with a minimal Java code snipped for reading an image.
private static void imageData(File picture) {
try {
BufferedImage image = ImageIO.read(picture);
int width = image.getWidth();
int height = image.getHeight();
DataBuffer buffer = image.getRaster().getDataBuffer();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int p = buffer.getElem(x + y * width);
image.setRGB(x, y, p);
}
}
File output = new File(picture.getName());
ImageIO.write(image, "gif", output);
return data;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I will get this picture:
So even if there is a marked answer in this question, it's still not going to help you.
You mentioned that the image you're reading is a grayscale image, and that getRGB returns values like 23241 and 23551.
That means your image uses a CS_GRAY ColorSpace, not an RGB color space. You can confirm this by calling getType(), which would return TYPE_USHORT_GRAY.
That means that your p value is a gray-level in range 0 - 65535. Since you want the result to be a double in range 0 - 255, you need to calculate:
double avg = p * 255.0 / 65535.0;
Unless you're 100% sure the input image will always be grayscale, you should check the type in the code and handle the p value accordingly.
I have a problem with getting gray scale of a .jpg file. I am trying to create a new .jpg file as gray scaled but I am just copying the image nothing more. Here is my code:
package training01;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
public class GrayScale {
BufferedImage image;
int width;
int height;
public GrayScale() {
try {
File input = new File("digital_image_processing.jpg");
image = ImageIO.read(input);
width = image.getWidth();
height = image.getHeight();
for(int i = width;i < width;i++) {
for(int j = height;j < height;j++) {
Color c = new Color(image.getRGB(i, j));
int red = c.getRed();
int green = c.getGreen();
int blue = c.getBlue();
int val = (red+green+blue)/3;
Color temp = new Color(val,val,val);
image.setRGB(i, j, temp.getRGB());
}
}
File output = new File("digital_image_processing1.jpg");
ImageIO.write(image, "jpg", output);
}catch(Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
GrayScale gs = new GrayScale();
}
}
You need to change the following. Start your i and j at 0.
for(int i = width;i < width;i++) {
for(int j = height;j < height;j++) {
However, here is a faster way to do it. Write it to a new BufferedImage object that is set for gray scale.
image = ImageIO.read(input);
width = image.getWidth();
height = image.getHeight();
bwImage = new BufferedImage(width,
height, BufferedImage.TYPE_BYTE_GRAY);
Graphics g = bwImage.getGraphics();
g.drawImage(image,0,0,null);
Then save the bwImage.
The main problem with your code, is that it won't loop, because you initialize i, j to width, height which is already greater than the exit condition of the for loops (i < width, j < height). Start iterating at 0 by initializing i and j to 0, and your code will work as intended.
For better performance, you also want to change the order of the loops. As BufferedImages are stored as a continuous array, row by row, you will utilize the CPU cache much better if you loop over the x axis (row) in the inner loop.
Side note: I also suggest renaming i and j to x and y for better readability.
Finally, your method of converting RGB to gray by averaging the colors will work, but is not the most common way to convert to gray scale, as the human eye does not perceive the intensities of the colors as the same. See Wikipedia on gray scale conversion for a better understanding of correct conversion and the theory behind it.
However, all of this said, for JPEG images stored as YCbCr (the most common way to store JPEGs), there is a much faster, memory efficient and simpler way of converting the image to gray scale, and that is simply reading the Y (luminance) channel of the JPEG and use that as gray scale directly.
Using Java and ImageIO, you can do it like this:
public class GrayJPEG {
public static void main(String[] args) throws IOException {
try (ImageInputStream stream = ImageIO.createImageInputStream(new File(args[0]))) {
ImageReader reader = ImageIO.getImageReaders(stream).next(); // Will throw exception if no reader available
try {
reader.setInput(stream);
ImageReadParam param = reader.getDefaultReadParam();
// The QnD way, just specify the gray type directly
//param.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));
// The very correct way, query the reader if it supports gray, and use that
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
while (types.hasNext()) {
ImageTypeSpecifier type = types.next();
if (type.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_GRAY) {
param.setDestinationType(type);
break;
}
}
BufferedImage image = reader.read(0, param);
ImageIO.write(image, "JPEG", new File(args[0] + "_gray.jpg"));
}
finally {
reader.dispose();
}
}
}
}
I have a .bin file that has been created in a MATLAB code as uint16 and i need to read it in Java.
With the code below, I get a blurry image with a very bad grayscale and the length of the file seems to be the double of the amount of pixels. There seems to be some loss of information when reading the file this way. Is there a way to read .bin files other than inputstreams?
This is how I try to read the .bin file:
is = new FileInputStream(filename);
dis = new DataInputStream(is);
int[] buf = new int[length];
int[][] real = new int[x][y];
while (dis.available() > 0) {
buf[i] = dis.readShort();
}
int counter = 0;
for (int j = 0; j < x; j++) {
for (int k = 0; k < y; k++) {
real[j][k] = buf[counter];
counter++;
}
}
return real;
And this is from the part from the main class where the first class is called:
BinaryFile2 binary = new BinaryFile2();
int[][] image = binary.read("data001.bin", 1024, 2048);
BufferedImage theImage = new BufferedImage(1024, 2048,
BufferedImage.TYPE_BYTE_GRAY);
for (int y = 0; y < 2048; y++) {
for (int x = 0; x < 1024; x++) {
int value = image[x][y];
theImage.setRGB(x, y, value);
}
}
File outputfile = new File("saved.png");
ImageIO.write(theImage, "png", outputfile);
You are storing uint16 data in an int array, this may lead to loss/corruption of data.
Following post discusses similar issue:
Java read unsigned int, store, and write it back
To correctly read and display an image originally stored as uint16, it's best to use the BufferedImage.TYPE_USHORT_GRAY type. A Java short is 16 bit, and the DataBufferUShort is made for storing unsigned 16 bit values.
Try this:
InputStream is = ...;
DataInputStream data = new DataInputStream(is);
BufferedImage theImage = new BufferedImage(1024, 2048, BufferedImage.TYPE_USHORT_GRAY);
short[] pixels = ((DataBufferUShort) theImage.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
pixels[i] = data.readShort(); // short value is signed, but DataBufferUShort will take care of the "unsigning"
}
// TODO: close() streams in a finally block
To convert the image further to an 8 bit image, you can create a new image and draw the original onto that:
BufferedImage otherImage = new BufferedImage(1024, 2048, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = otherImage.createGraphics();
try {
g.drawImage(theImage, 0, 0, null);
}
finally {
g.dispose();
}
Now you can store otherImage as an eight bit grayscale PNG.
I am getting the int array from png image how I will convert this to bufferdimage or creating new PNG file ?
int[] pixel = new int[w1*h1];
int i = 0;
for (int xx = 0; xx < h1; xx++) {
for (int yy = 0; yy < w1; yy++) {
pixel[i] = img.getRGB(yy, xx);
i++;
}
}
If you have an array of integers which are packed RGB values, this is the java code to save it to a file:
int width = 100;
int height = 100;
int[] rgbs = buildRaster(width, height);
DataBuffer rgbData = new DataBufferInt(rgbs, rgbs.length);
WritableRaster raster = Raster.createPackedRaster(rgbData, width, height, width,
new int[]{0xff0000, 0xff00, 0xff},
null);
ColorModel colorModel = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
BufferedImage img = new BufferedImage(colorModel, raster, false, null);
String fname = "/tmp/whatI.png";
ImageIO.write(img, "png", new File(fname));
System.out.println("wrote to "+fname);
The reason for the arrays 0xff0000, 0xff00, 0xff is that the RGB bytes are packed with blue in the least significant byte. If you pack your ints different, alter that array.
You can rebuild the image manually, this is however a pretty expensive operation.
BufferedImage image = new BufferedImage(64, 64, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
for(int i = 0; i < pixels.size(); i++)
{
g.setColor(new java.awt.Color(pixels.get(i).getRed(), pixels.get(i).getGreen(), pixels.get(i).getBlue()));
g.fillRect(pixels.get(i).getxPos(), pixels.get(i).getyPos(), 1, 1);
}
try
{
ImageIO.write(image, "PNG", new File("imageName.png"))
}
catch(IOException error)
{
error.printStackTrace();
}
I formatted your image array into an object, this is personal preference tho (of course you could us an int array with this model as well). Keep in mind that you can always add the alpha to there as well.
Try the ImageIO class, which can take a byte array representing pixel data to build an image object and then writing it out in a particular format.
try {
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(yourBytes));
ImageIO.write(bufferedImage, "png", new File("out.png"));
} catch (IOException e) {
e.printStackTrace();
}