Convert 2D binary matrix to black/white image in java - java

I am new for java. I have 2D binary matrix with only 1s and 0s now. I want to save it as jpg image(black and white) with same width and height. How could I realize that? I tried the code below but failed, saying "java.lang.IllegalArgumentException: image == null!" Please help me with that or give me your better solution. Thank you very much.
public static void main(String[] args) throws IOException {
//result is double[25][33] binary matrix with only 1s and 0s;
int height=result.length;
int width=result[0].length;;
byte[] data = new byte[height*width];
int k=0;
for(int i = 0;i < height;i++){
for(int j = 0; j < width; j++){
data[k]=(byte)result[i][j];
k++;
}
System.out.print("\n");
}
InputStream input = new ByteArrayInputStream(data);
BufferedImage output = ImageIO.read(input);
ImageIO.write(ouput, "jpg", new File("c:/result.jpg"));
}

This is a simple example that creates a 30x30 checkered box:
public static void main(String... args) throws IOException {
int w = 30, h = 30;
// create the binary mapping
byte BLACK = (byte)0, WHITE = (byte)255;
byte[] map = {BLACK, WHITE};
IndexColorModel icm = new IndexColorModel(1, map.length, map, map, map);
// create checkered data
int[] data = new int[w*h];
for(int i=0; i<w; i++)
for(int j=0; j<h; j++)
data[i*h + j] = i%4<2 && j%4<2 || i%4>=2 && j%4>=2 ? BLACK:WHITE;
// create image from color model and data
WritableRaster raster = icm.createCompatibleWritableRaster(w, h);
raster.setPixels(0, 0, w, h, data);
BufferedImage bi = new BufferedImage(icm, raster, false, null);
// output to a file
ImageIO.write(bi, "jpg", new File("C:\\Users\\user\\Desktop\\test.jpg"));
}
EDIT:
For what you are doing you actually don't need to create your own ImageColorModel, you can use a built in type: BufferedImage.TYPE_BYTE_GRAY or TYPE_BYTE_BINARY. Here is a better example and shows how to use grayscale to get a checkered box:
public static void main(String... args) throws IOException {
int w = 40, h = 40, divs = 5;
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = bi.getRaster();
for(int i=0; i<w; i++)
for(int j=0; j<h; j++)
raster.setSample(i,j,0,128+(int)(127*Math.sin(Math.PI*i/w*divs)*Math.sin(Math.PI*j/h*divs)));
ImageIO.write(bi, "jpg", new File("C:\\Users\\user\\Desktop\\test.jpg"));
}

JHeatChart does this job as well without you having to create a custom image library.
http://www.javaheatmap.com/
// Create some dummy data.
double[][] data = new double[][]{{3,2,3,4,5,6},
{2,3,4,5,6,7},
{3,4,5,6,7,6},
{4,5,6,7,6,5}};
// Step 1: Create our heat map chart using our data.
HeatChart map = new HeatChart(data);
// Step 2: Customise the chart.
map.setTitle("This is my heat chart title");
map.setXAxisLabel("X Axis");
map.setYAxisLabel("Y Axis");
// Step 3: Output the chart to a file.
map.saveToFile(new File("java-heat-chart.png"));
What you are essentially trying to do is make a heat map. And instead of a range of values ranging from 0 to whatever, you have a range of 0 and 1.
Replace double[][] data = new double[][](//etc); with your boolean array.

Related

Convolution implementation does not work as expected

I spent the whole day trying to implement the "convolution algorithm" in Java, but this last does not seem to work properly with all kernels, it works great with the blur kernel with a factor of 1/9, but not with the other ones.
For example, if I use the {{0.1.0},{0,0,0},{0,0,0}} matrix which is supposed to shift the image up by 1 pixel, surprisingly, it stretches the image all the way down.
Example of what I get:
And here is the code:
public class ConvolutionTest {
static BufferedImage bfimg;
static BufferedImage outputimg;
static File output = new File("/home/bz/Pictures/Selection_003_mod");
static File input = new File("/home/bz/Pictures/Selection_003.png");
static WritableRaster wr;
static int tempColor;
static double [] newColor = {0,0,0};
static double red=0, green=0, blue=0;
static double sumR=0, sumG=0, sumB=0;
public static void main(String[] args) throws IOException {
int tempIcoor;
int tempJcoor;
double[][] matConv = {
{0d, 1d, 0d},
{0d, 0d, 0d},
{0d, 0d, 0d}
};
bfimg = ImageIO.read(input);
outputimg = bfimg;
wr = outputimg.getRaster();
for (int i = 1; i < bfimg.getHeight()-1; i++) {
for (int j = 1; j < bfimg.getWidth()-1; j++) {
tempIcoor = i - 1;
tempJcoor = j - 1;
for (int tempI = 0; tempI < 3; tempI++) {
for (int tempJ = 0; tempJ < 3; tempJ++) {
tempColor = bfimg.getRGB(tempJcoor, tempIcoor);
red = tempColor >> 16 & 0xff;
red = red * matConv[tempI][tempJ];
green = tempColor >> 8 & 0xff;
green = green * matConv[tempI][tempJ];
blue = tempColor & 0xff;
blue = blue * matConv[tempI][tempJ];;
sumR = red + sumR;
sumG = green + sumG;
sumB = blue + sumB;
tempJcoor++;
}
newColor[0] = sumR;
newColor[1] = sumG;
newColor[2] = sumB;
tempIcoor++;
tempJcoor=j-1;
}
wr.setPixel(j, i, newColor);
sumR=0;
sumG=0;
sumB=0;
}
}
ImageIO.write(sortie, "png", output);
}
}
With
outputimg = bfimg;
you are setting the output image to be the same as the input image. When you perform the convolution of the first row, then (as you said) the first row of pixels from the input image will be written into the the second row of the output image. But they are identical - so you end up with all rows of the output image being copies of the first row of the input image.
Just replace this line with
outputimg = new BufferedImage(
bfimg.getWidth(), bfimg.getHeight(),
BufferedImage.TYPE_INT_ARGB);
to create a new output image to write to.
By the way: All this is already available in the standard API. You might want to have a look at the classes related to http://docs.oracle.com/javase/7/docs/api/java/awt/image/ConvolveOp.html

How to display a colour image using a JPanel?

I have a colour image that is been stored in a 3D array and now I want to display this data or the image on to a JPanel. My code read function is as follows :
public void readImage(String filename) throws Exception {
String filenameExtension = filename.substring(filename.lastIndexOf('.')+1);
File fileImage = FileChosen;
Iterator imageReaders = ImageIO.getImageReadersBySuffix(filenameExtension);
ImageReader imageReader;
if(imageReaders.hasNext())
imageReader = (ImageReader)imageReaders.next();
else
throw new IOException("Unsupported image format");
FileImageInputStream imageInputStream = new FileImageInputStream(fileImage);
imageReader.setInput(imageInputStream);
ImgWidth = imageReader.getWidth(0);
ImgHeight = imageReader.getHeight(0);
BufferedImage bufImage = imageReader.read(0);
imageInputStream.close();
WritableRaster wRaster = bufImage.getRaster();
//int numBands = wRaster.getNumBands();
System.out.println(ImgWidth);
System.out.println(ImgHeight);
imageArray = (new double[ImgHeight][ImgWidth][ColourLevels]);
// get the samples and normalize to between 0 and 1
for(int row = 0; row < ImgHeight; row++)
for(int col = 0; col < ImgWidth; col++)
for(int level = 0; level < ColourLevels; level++)
imageArray[row][col][level] = (wRaster.getSample((col), (row), level) / 255.0);
} // end read method`
Now I want to print the data stored in the imageArray[][][] in to a panel, how can I do that?

grayscale bitmap into 2d array

Hi everyone i have problems in converting GrayScale bmp images into integer 2D-array (with values 0-255) in Java.
I have a pmb image that could be seen as an integer(0-255) 2D-array and i want to see that 2D-array in a Java data structure
i tried this way:
Image image = ImageIO.read(new File("my_img.bmp"));
BufferedImage img = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_BYTE_GRAY);
Graphics g = img.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
Then with my BufferedImage i create int[][] this way:
int w = img.getWidth();
int h = img.getHeight();
int[][] array = new int[w][h];
for (int j = 0; j < w; j++) {
for (int k = 0; k < h; k++) {
array[j][k] = img.getRGB(j, k);
}
}
But now all the 2D-array is full of number like "-9211021" or similar.
i think that the problem is in getRGB(j,k) but i don't know if it's possible to solve it.
edit:
i know RGB is not grayscale, so how can i get the grayscale value of a single pixel from a grayscale BufferedImage?
In a grayscale image, BufferedImage.getPixel(x,y) wont give values within the [0-255] range. Instead, it returns the corresponding value of a gray level(intensity) in the RGB colorspace. That's why you are getting values like "-9211021".
The following snippet should solve your problem :
Raster raster = image.getData();
for (int j = 0; j < w; j++) {
for (int k = 0; k < h; k++) {
array[j][k] = raster.getSample(j, k, 0);
}
}
where image is the created BufferedImage. The 0 in the getSample indicates that we are accessing the first byte/band(setting it to a greater value will throw a ArrayOutOfBoundException in grayscale images).
You can use Catalano Framework. Contains several filters for image processing.
http://code.google.com/p/catalano-framework/
Detail: That's it faster than using WritableRaster.
FastBitmap fb = new FastBitmap(bufferedImage);
int[][] image = new int[fb.getHeight()][fb.getWidth];
fb.toArrayGray(image);
//Do manipulations with image
//...
//Place the image into fastBitmap
fb.arrayToImage(image);
//Retrieve in bufferedImage if you desire.
bufferedImage = fb.toBufferedImage();

Java BufferedImage Grayscale Degradation

I'm creating a simple program which accepts a gray scale image as an input and what I simply want to do is retrieve the color information of each pixel, store it in an array of objects I call PixelClass. The ultimate goal is simply to repaint the image to a new BufferedImage using the said acquired color information.
Code used to create the pixel array from a given image.
public static PixelClass[][] getPixelArray(BufferedImage bi){
int height = bi.getHeight();
int width = bi.getWidth();
PixelClass[][] pixelArray = new PixelClass[height][width];
for(int i = 0 ; i < height ; i++){
for(int j = 0 ; j < width ; j++){
pixelArray [i] [j] = new PixelClass(bi.getRGB(j, i));
}
}
return pixelArray;
}
Code used to attempt to repaint the said image, using the array of PixelClass objects
public void paintToPanel(PixelClass [][] pc, int height, int width){
BufferedImage nbi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
for ( int i = 0 ; i < height ; i++){
for ( int j = 0 ; j < width ; j++){
nbi.setRGB(j, i, pc[i][j].getRGBValue());
}
}
JLabel containerLabel = new JLabel(new ImageIcon(nbi));
containerLabel.setBounds(10,10,nbi.getHeight(), nbi.getWidth());
this.add(containerLabel);
}
Links to original images
http://sphotos.ak.fbcdn.net/hphotos-ak-snc4/hs1364.snc4/163667_172099429501181_100001033756527_413302_3062182_n.jpg
As you can see there is significant degradation on the quality of the image. The resulting image appear to be faded.
I would suggest you use the MemoryImageSource class. Something like :
byte[] pixels = // your pixels
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int bits[] = new int[] {8};
ColorModel cm = new ComponentColorModel(cs, bits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
MemoryImageSource mis = new MemoryImageSource(width, height, cm, pixels, 0, width);
Image im = Toolkit.getDefaultToolkit().createImage(mis);

how to read RGB Data from png in j2me

hey i have using j2me to read an image
i want to do some process on that image like Darkenes , lightens
i already read image as an input stream
InputStream iStrm = getClass().getResourceAsStream("/earth.PNG");
ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1){
bStrm.write(ch);
byte imageData[] = bStrm.toByteArray();
Image im = Image.createImage(imageData, 0, imageData.length);
how can i get RGB values or how can i add some values to the array of pixles
imageData[] so it can more lightens or darkness ,
is there header data including in the input stream i had read , that cause me error when iam adding some values to it ?
I think you should be able to do the following:
int width = im.getWidth();
int height = im.getHeight();
int[] rgbData = new int[width*height]; // since we are working with rgba
im.getRGB(rgbData, 0, width, 0, 0, width, height);
// now, the data is stored in each integer as 0xAARRGGBB,
// so high-order bits are alpha channel for each integer
Now, if you want to put them into three arrays, one for each channel, you could do the following:
int red[][] = new int[width][height];
int green[][] = new int[width][height];
int blue[][] = new int[width][height];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
red[i][j] = rgb[i*width + j] & 0xFF0000;
green[i][j] = rgb[i*width + j] & 0xFF00;
blue[i][j] = rgb[i+width + j] & 0xFF;
}
}

Categories