image processing - java

I want to change the value of the pixels in an image, for which i need to store the image as a matrix. How can i perform this job? Please guide.

BufferedImage image = ImageIO.read(..);
image.setRGB(x, y, rgb);
Check the documentation of BufferedImage

Using image.setRGB is extremely slow.
You can use Catalano Framework
Example:
FastBitmap fb = new FastBitmap(bufferedImage);
int x = fb.getRed(0,0);
//If you prefer to retrieve the matrix you can do too.
int[][][] image = new int[fb.getHeight][fb.getWidth][3];
fb.toArrayRGB(image);

Firstly read the image into a BufferedImage.
BufferedImage image = ImageIO.read(new File("..."));
Then create matrix like structure in the 2D array like this and set RGB:
for(int i = 0; i < image.getWidth(); i++){
for(int j = 0; j < image.getHeight(); j++){
image.setRGB(i, j, rgb);
}
}

Image is 2d representation of data (pixel info)
2D means x&y directions. In case of image, these directions are generally treated as rows & columns
To change the pixel value, we have to get its location in these rows and columns
Getting pixel location is like that class teacher addressing the unknown student with his sitting position (ex:2nd bench 3rd person)
Like this we have to address the pixel by its rows and column location

Related

Pixel relocation, showing side-by-side

I want to read individual pixels from one image and "relocate" them to another image. I basically want to simulate how it would be if I grabbed pixel by pixel from one image and "move" them to a blank canvas. Turning the pixels I grab from the original image white.
This is what I have right now, I'm able to read the pixels from the image and create a copy (which comes out saturated for some reason) of it.
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageTest
{
public static void main(String args[])throws IOException
{
//create buffered image object img
File oldImgFile = new File("/path/to/image/shrek4life.jpg");
BufferedImage oldImg = null;
BufferedImage newImg = null;
try{
oldImg = ImageIO.read(oldImgFile);
}catch(IOException e){}
newImg = new BufferedImage(oldImg.getWidth(), oldImg.getHeight(), BufferedImage.TYPE_INT_ARGB);
File f = null;
try
{
for(int i = 0; i < oldImg.getWidth(); i++){
for(int j = 0; j < oldImg.getHeight(); j++){
//get the rgb color of the old image and store it the new
Color c = new Color(oldImg.getRGB(i, j));
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
int col = (r<<16) | (g<<8) | b;
newImg.setRGB(i, j, col);
}
}
//write image
f = new File("newImg.jpg");
ImageIO.write(newImg, "jpg", f);
}catch(IOException e){
System.out.println("Error: " + e);
}
}//main() ends here
}//class ends here
And I would like to basically slow the process down and display it happening. But I'm not sure how to do that. Would I need to use to accomplish this ? I'm somewhat new to threading but I think I would need multiple threads to handle the painting of both pictures.
First of all, I would like to mention you are working in a very inefficient way. You are creating a Color, decomposing a pixel in its channels, and moving to the new image by a bit-shift. It is easier if you work directly with the integer the whole time (and more efficient).
I will assume the image "/path/to/image/shrek4life.jpg" has ARGB color space. I recommend ensure this, because if the old image does not have this color space you should make a conversion.
When you create the new image, you create it as ARGB color space, so each channel is expressed in a byte of the int, first byte for Alpha, second byte for red, third byte for green and the last one for blue.
I think you forgot the alpha channel when you manipulated the old image pixel to move it into the new image.
With this explanation in mind, I think you can change your code to increase the efficiency, like this:
for(int i = 0; i < oldImg.getWidth(); i++){
for(int j = 0; j < oldImg.getHeight(); j++){
int pixel = oldImg.getRGB(i,j);
newImg.setRGB(i, j, pixel );
//If you like to get more control over the pixels and print
//you can decompose the pixel using Color as you already do
//But when you understand fully the process I recommend erase it
Color c = new Color(pixel);
//Print the color or do whatever you like
}
}
About how to display the process of pixel relocation:
In process:
You can print the changed pixel as a number with its position in image (discouraged). System.out.println("pixel"+pixel+" X:"+i+" Y:"+j);
Use this tutorial in baeldung to print an image. I suggest draw a rectangle with the color of the image and wait for a key press (enter, for example) using Scanner. After the key was press, you can load the next pixel, an so on.
If a single rectangle with just one pixel has little information, I suggest add an array of rectangles to draw several pixels in a time. Even you can print an image, and see the process pixel by pixel, using Scanner to mark each step.
As #haraldK suggest, you can use Swing to display de relocation image. Through swing timer and invokes update()
Post process:
Save the image in a file. To improve the speed of process, I suggest save a few pixels (10 - 100).

How to create a grayscale image using java

can anyone help me and tell me how to create a gray scale image where one pixel of the image is shown as a square with the size 2 x 2?
I already searched for help and found this how to create a gray scale image from pixel values using java but i don't know how to create a gray scale with the information that one pixel is shown as a square with the size 2 x 2.
thanks!
to create a picture where each pixel has the size 2x2 you must either scale the image (factor 2) for display only... or if you want to create a image you have to do it manually and create an image and draw with scale factor 2 on it
int[] pixels = ... //we already have our gray scale pixels here
int widthOriginal = ... //size of original image
int heightOriginal = ...
//let's create an buffered Image twice the size
BufferedImage img =
new BufferedImage(2*widthOriginal, 2*heightOriginal, BufferedImage.TYPE_4BYTE_ABGR);
//we paint on the buffered image's graphic...
Graphics gr = img.getGraphics();
//we draw all pixels on the graphic
for(int y = 0; y < heightOriginal; y ++){
for(int x = 0; x < widthOriginal; x ++){
int index = y*widthOriginal + x;
int gray = pixels[index];
//to draw we first set the color
gr.setColor(new Color(gray));
//then draw the pixel
gr.drawRect(2*x, 2*y,2,2); //draw a 2x2 pixel instead of a 1x1 pixel
}
}
uhm - honestly i've written that code entirely out of my head, so there may be some minor compilation problems... but the technique is explained properly...

java - how to make an image using setRGB?

i have 2D array to keep color component value :
p[pixel_value][red]
p[pixel_value][green]
p[pixel_value][blue]
i just dont know how to use them to make an image.
i read about setRGB, what i understand is i should mix all of them to become a RGBArray. then how to make it?
is it any better way to make an image without setRGB ? i need some explanation.
The method setRGB() can be used to set the color of a pixel of an already existing image. You can open an already existing image and set all the pixels of it, using the values stored in your 2D array.
You can do it like this:
BufferedImage img = ImageIO.read(new File("image which you want to change the pixels"));
for(int width=0; width < img.getWidth(); width++)
{
for(int height=0; height < img.getHeight(); height++)
{
Color temp = new Color(p[pixel_value][red], p[pixel_value][green], p[pixel_value][blue]);
img.setRGB(width, height, temp.getRGB());
}
}
ImageIO.write(img, "jpg", new File("where you want to store this new image"));
Like this, you can iterate over all the pixels and set their color accordingly.
NOTE: By doing this, you will lose your original image. This is just a way which I know.
What you need is a BufferedImage. Create a BufferedImage of type TYPE_3BYTE_BGR, if RGB is what you want, with a specified width and height.
QuickFact:
The BufferedImage subclass describes an Image with an accessible
buffer of image data.
Then, call the getRaster() method to get a WritableRaster
QuickFact:
This class extends Raster to provide pixel writing capabilities.
Then, use the setPixel(int x, int y, double[] dArray) method to set the pixels.
Update:
If all you want is to read an image, use the ImageIO.read(File f) method. It will allow you to read an image file in just one method call.
Somewhat SSCCE:
BufferedImage img = null;
try {
img = ImageIO.read(new File("strawberry.jpg"));
} catch (IOException e) {
}
You want to manually set RGB values?
You need to know that since an int is 32bit it contains all 4 rgb values (1 for the transparency).
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
^Alpha ^red ^green ^blue
You can accomplish using 4 int values by the use of binary arithmetic:
int rgb = (red << 16) && () (green << 8) & (blue);
bufferedImage.setRGB(x, y, rgb);
IN the above you can add Alpha as well if needed. You just "push" the binary codes into the right places.

What is the fastest way to read a large tiff image in java?

I currently use the JAI library to read the tiff image but it is very very slow large tiff images (I need to work with satellite images of size around 1GB).
I need to read the height of each point from the tiff image and then color it accordingly.
I am reading the image by creating a PlanarImage and iterating through every pixel by using the image.getData().getPixel(x,y,arr) method.
Suggest me a better way of implementing the solution.
Edit:
I found the error.I was creating a new raster of the image for every pixel by calling the image.getData() method in the for loop.Creating a raster just once and then using its getPixel() function in the loop solved my problem.
From the JavaDoc of PlanarImage.getData():
The returned Raster is semantically a copy.
This means that for every pixel of your image, you are creating a copy of the entire image in memory... This cannot give good performance.
Using getTile(x, y) or getTiles() should be faster.
Try:
PlanarImage image;
final int tilesX = image.getNumXTiles();
final int tilesY = image.getNumYTiles();
int[] arr = null;
for (int ty = image.getMinTileY(); ty < tilesY; ty++) {
for (int tx = startX; tx < image.getMinTileX(); tx++) {
Raster tile = image.getTile(tx, ty);
final int w = tile.getWidth();
final int h = tile.getHeight();
for (int y = tile.getMinY(); y < h; y++) {
for (int x = tile.getMinX(); x < w; x++) {
arr = tile.getPixel(x, y, arr);
// do stuff with arr
}
}
}
}
A 1 GB compressed image is likely to be about 20 GB+ when loaded into memory. The only way to handle this in Java is to load it with a very large heap space.
You are dealing with very large images and the simplest way to make this faster is to use a faster PC. I suggest an over clocked i7 3960X which you can get for a reasonable price http://www.cpubenchmark.net/high_end_cpus.html

Get Pixel Color around an image

I have an image, and I figured out how to use robot and getPixelColor() to grab the color of a certain pixel. The image is a character that I'm controlling, and I want robot to scan around the image constantly, and tell me if the pixels around it equal a certain color. Is this at all possible? Thanks!
Myself, I'd use the Robot to extract the image that's just a little larger than the "character", and then analyze the BufferedImage obtained. The details of course will depend on the details of your program. Probably the quickest would be to get the BufferedImage's Raster, then get thats dataBuffer, then get thats data, and analyze the array returned.
For example,
// screenRect is a Rectangle the contains your "character"
// + however many images around your character that you desire
BufferedImage img = robot.createScreenCapture(screenRect);
int[] imgData = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
// now that you've got the image ints, you can analyze them as you wish.
// All I've done below is get rid of the alpha value and display the ints.
for (int i = 0; i < screenRect.height; i++) {
for (int j = 0; j < screenRect.width; j++) {
int index = i * screenRect.width + j;
int imgValue = imgData[index] & 0xffffff;
System.out.printf("%06x ", imgValue );
}
System.out.println();
}

Categories

Resources