BufferedImage colour change - java

I have working on an application which captures screen shots and create video from captured images. But the problem is that when video is generated, colours in generated video is very pinkish. I think this is because I am manipulating captured images to show cursor using BufferedImage.TYPE_3BYTE_BGR type. Could someone tell me how to resolve this issue, I want to have the colour of video same as actual colour of screen.
For capturing screen image I am doing as follows:
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(screenBounds);
return robot.createScreenCapture(captureSize);
For manipulating images I am doing as follows:
image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
if (true) {
int x = MouseInfo.getPointerInfo().getLocation().x - 25;
int y = MouseInfo.getPointerInfo().getLocation().y - 37;
Graphics2D graphics2D = sourceImage.createGraphics();`enter code here`
graphics2D.drawImage(SimpleWebBrowserExample.m_MouseIcon, x, y, 48, 48, null);
}
image.getGraphics().drawImage(sourceImage, 0, 0, null);
return image;
please tell me how to get the images with colour same as actual colour on screen.
Thanks.

Use BufferedImage.TYPE_INT_ARGB or BufferedImage.TYPE_INT_RGB, as shown in this example. If you need to change the colors, you can use a LookupOp with a four-component LookupTable that adjusts the alpha component as required for BufferedImage.TYPE_3BYTE_BGR: "When data with non-opaque alpha is stored in an image of this type, the color data must be adjusted to a non-premultiplied form and the alpha discarded." Examples may be found in Using the Java 2D LookupOp Filter Class to Process Images and Image processing with Java 2D.

See the the "pinkish" explanation here
Basically the image is saved as a ARGB and most viewers interpret it as a CMYK. Alpha is preserved when opening it back in Java, though.

Related

How can I set pixels in Java BufferedImages using non-ARGB color spaces?

I'm writing an application that needs to work with 16-bit "5-5-5" RGB colors (that is, 5 bits for each color and one bit of padding). In order to handle these images, I am using the BufferedImage class provided by AWT. The BufferedImage class specifically allows for the usage of non-RGB color spaces by taking either a ColorModel object or a predefined image type constant - one of which is the 5-5-5 pixel format that I need.
My problem is this: the BufferedImage "setRGB()" method states in its description that color values provided are "assumed to be in the default RGB color model, TYPE_INT_ARGB, and default sRGB color space" (per the BufferedImage documentation page). No other method seems to accept values designed for different color spaces, either.
Is there a way to use my non-standard color space directly with BufferedImage, or would I have to rely on the class's internal color conversion mechanisms to handle all of my colors? (Or am I just misreading/misunderstanding something about how the class works?)
BufferedImage.TYPE_USHORT_555_RGB still uses a completely standard RGB color space (in fact, it uses sRGB), so I don't think a different color space is what you are looking for.
If you want to perform painting or other operations in Java, just use the normal methods like setRGB/getRGB() and createGraphics()/Grapics2D. Everything will be properly converted to and from the packed USHORT_555_RGB format for you.
For example:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Do some custom painting
Graphics2D g = image.createGraphics();
g.drawImage(otherImage, 0, 0, null); // image type here does not matter
g.setColor(Color.ORANGE); // Color in sRGB, but does not matter
g.fillOval(0, 0, w, h);
g.dispose();
image.setRGB(0, h/2, w, 1, new int[w]); // Silly way to create a horizontal black line at the center of the image... Don't do this, use fillRect(0, h/2, 1, w)! ;-)
// image will still be USHORT_555_RGB *internally*
However, if you have pixel data in the USHORT_555_RGB format (ie. from an external library/api/service), it may be faster and more accurate to set these values directly to the raster/databuffer. Or if you need to pass the pixel values back to the same library/api/service.
For example, using the Raster:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
WritableRaster raster = image.getRaster();
// Set short values to image
raster.setDataElements(0, 0, w, h, apiPixels);
// Get short values from image
short[] pixels = (short[]) raster.getDataElements(0, 0, w, h, null); // TYPE_USHORT_555_RGB -> always short[]
api.setPixels(pixels, w, h); // Another fictional API
Or, alternatively, use the DataBuffer:
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_555_RGB);
// Some fictional API. It's assumed that data.length == w * h
short[] apiPixels = api.getPixelsUSHORT_555_RGB(w, h);
DataBufferUShort buffer = (DataBufferUShort) image.getRaster().getDataBuffer(); // TYPE_USHORT_555_RGB -> always DataBufferUShort
// Set short values to image
System.arraycopy(apiPixels, 0, buffer.getData(), 0, apiPixels.length);
// Get short values from image
api.setPixels(buffer.getData(), w, h);
In most cases it does not matter which method you use, but the first approach (using Raster only) may keep the image managed, which will make images display faster on screen from your Java process.
PS: If a different color space is really what you need (ie. the pixel array from the external library/api/service uses a different color space, and you need to view the pixels in this color space), you can create a BufferedImage in USHORT_555_RGB style with a custom color space like this:
// Either use one of the built-in color spaces, or load one from disk
ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
ColorSpace colorSpaceToo = new ICC_ColorSpace(ICC_Profile.getInstance(Files.newInputStream(new File("/path/to/custom_rgb_profile.icc").toPath())));
// Create a color model using your color space, TYPE_USHORT and 5/5/5 mask, no transparency
ColorModel colorModel = new DirectColorModel(colorSpace, 15, 0x7C00, 0x03E0, 0x001F, 0, false, DataBuffer.TYPE_USHORT);
// And finally, create an image from the color model and a compatible raster
BufferedImage imageToo = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(w, h), colorModel.isAlphaPremultiplied(), null);
Just remember that as the Java2D graphics operations and setRGB/getRGB are still using sRGB, now all operations on your image will be converted back and forth between your color space and sRGB. Performance will not be as good.

Is there a function that converts any image into a circle of 150x150 pixels-java?

I need a function/method that can mold(crop and resize) an imported (.png format) image into a circle of exact 150x150 pixels and it should keep transparency. I have searched all over internet, also I have my own code but I think its completely useless. I need this function for a code I am using to make GUI of a social-media app database.
private ImageIcon logo = new ImageIcon(getClass().getResource("/test/test200x200.png"));
toCircle(logo);
I need the code for the following function:
public ImageIcon toCircle(ImageIcon icon)
{
//code
return icon;
}
This function should convert this picture:
To this:
Create a new transparent image
Get a Graphics object from the image.
Set a clip for the graphics object.
Paint the PNG format image.
See also this answer that uses a clipped region.
An alternative approach, that might be more straight-forward to implement for this use case, is:
Create a transparent BufferedImage the size of your icon
Create Graphics2D from image, set hints for antialias
Fill a circle the size of your background circle
Draw the image on top of your circle, using AlphaComposite.SrcIn
Something like:
public Icon toCircle(ImageIcon logo) {
BufferedImage image = new BufferedImage(150, 150); // Assuming logo 150x150
Graphics2D g = image.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.fillOval(1, 1, 148, 148); // Leaving some room for antialiasing if needed
g.setComposite(AlphaComposite.SrcIn);
g.drawImage(logo.getImage(), 0, 0, null);
g.dispose();
return new ImageIcon(image);
}

Java GUI image size

So I have an assignment where I need to create a catalog.
The catalog needs to have a list, an image and a description.
My entire code works, so I have no issue with the coding as such.
I do have an issue with the image size.
How do I take care of images on a java gui program to make them all into one size when it is running.
Please let me know :D
When you read in an image, create a new BufferedImage that is the exact size that you desire, get it's Graphics object via getGraphics(), draw the original image into the new image using Graphics#drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) where x and y are 0 and width and height are from the dimensions of the new image, dispose() of the Graphics object, and then display the new Image as an ImageIcon in a JLabel. Make sure though that the original image is the same size or larger than the new one, else your images will look gawd-awful.
For example, and note that this code may not be exactly correct since I don't have my IDE up:
BufferedImage originalImage = ImageIO.read(something); // read in original image
// create new empty image of desired size
BufferedImage newImage = new BufferedImage(desiredWidth, desiredHeight, BufferedImage.TYPE_INT_ARGB);
Graphics g = newImage.getGraphics(); // get its graphics object
// draw old image into new image
g.drawImage(originalImage, 0, 0, desiredWidth, desiredHeight, null);
g.dispose(); // get rid of Graphics object
// create ImageIcon and put in JLabel to display
Icon newIcon = new ImageIcon(newImage);
myJLabel.setIcon(newIcon);
I would propably create a JPanel to draw on one Image, and then work with the method:
myPanel.setSize(new Dimension(x,y))
or
myPanel.setPreferredSize(new Dimension....)
There is a method (image = imgobj.getScaledInstance(width, height, hints)) in awt.Image class which provides re-sizing capabilities very nicely, I always use this to re-size my images when I need. Please see here some examples :-), I hope it will work for you, it is the most convenient way to scale images I have ever seen. create a method pass the image to the method and size of the image you want and return the image back in return to reuse the code ;)

Write pixel data in a grayscale image in java

I am developing a project on image processing where I have to fill the digitized images of cracked paintings. I have to convert a color image to grayscale, performing some calculations on the 2D Array of the gray image and writing it back as gray image. The code for this is:
BufferedImage colorImage=ImageIO.read(new File(strImagePath));
BufferedImage image = new BufferedImage(colorImage.getWidth(),colorImage.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
Graphics g = image.getGraphics();
g.drawImage(colorImage, 0, 0, null);
g.dispose();
ImageIO.write(image,"PNG",new File("Image.PNG"));
BufferedImage imgOriginal=ImageIO.read(new File("Image.PNG"));
int width=image.getWidth();
int height=image.getHeight();
BufferedImage im=new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
int arrOriginal[][]=new int[height][width];
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
arrOriginal[i][j]=imgOriginal.getRGB(j,i)& 0xFF;
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
im.setRGB(j,i,arrOriginal[i][j]);
ImageIO.write(im,"PNG",new File("Image1.PNG"));
But the output image is very much darker, I am not getting the original image back (I have not done any changes yet).
I think there should be some changes in setRGB() statement but I don't know what.
To write image back, I have also tried:
`
BufferedImage im = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
WritableRaster raster = im.getRaster();
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
raster.setSample(j,i,0,arrOriginal[i][j]);
`
But it also don't give me original image back.
Can anyone provide me the solution of this problem?
Thanks in advance.
I don't know anything about Java-based image processing, but I do know quite a lot about image processing in general, so I will see if I can give you any ideas. Please don't shoot me if I am wrong - I am just suggesting an idea.
In a greyscale image, the red, green and blue values are all the same, i.e. Red=Green=Blue. So, when you call getRGB and do the AND with 0xff, you are probably getting the blue component only, but that is ok as the red and green are the same - because it's greyscale.
I suspect the problem is that when you write it back to create your new output image, you are only setting the blue component and not the red and green - which should still be the same. Try writing back
original pixel + (original pixel << 8 ) + (original pixel <<16)
so that you set not only the Blue, but also the Red and Green components.

Prepending an image to the top of another image

I've been looking for a solution for the last several days.
I've seen an example of composite images with Java Advanced Imaging. But that seems to be restricted by the smallest width and height of either image files. So it outputs a file with the height and width of the header file.
Preferably, I'd like to have the header not covering any part of the body image. But it's not a requirement. Sometimes the body image's width is smaller than the header and that's fine as the main content of the header file will be in the middle.
Using JDK 1.6.0_41, I need to take the first two images:
And have the result be:
Whether it is using Java or Javscript is fine. The entire process is as follows:
I take a canvas object of a map using OpenLayers, then use a POST to send it to a Java Servlet to be processed and stored. Then later retrieved the image if the user desires.
The long blue header needs to be at the top of an image or just above it. The header image will have content from the user that created it, etc. That I can do. But manipulating multiple images is not something I am familiar with.
In Java, you can do this:
public BufferedImage prependImage(BufferedImage image1, BufferedImage image2) {
Dimension d1 = new Dimension(image1.getWidth(null),
image1.getHeight(null));
Dimension d2 = new Dimension(image2.getWidth(null),
image2.getHeight(null));
Dimension dt = new Dimension(d1.width, d1.height + d2.height);
BufferedImage image = new BufferedImage(dt.width, dt.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
int x = 0;
int y = 0;
g.drawImage(image1, x, y, d1.width, d1.height, null);
y += d1.height;
g.drawImage(image2, x, y, d2.width, d2.height, null);
g.dispose();
return image;
}

Categories

Resources