I need to merge/combine two SWT images in Java.
Unfortunately I am having issue with the result image coloring, and the result image does not have transparency like the original two images.
I am not an image expert, but I think the PaletteData of the result ImageData somehow affects the coloring for copied pixels of copied second image and the transparency.
ImageData targetData = new ImageData(sourceData1.width + sourceData2.width,
sourceData1.height, sourceData1.depth, sourceData1.palette);
Changing SourceData1.palette to SourceData2.palette would affects coloring for the copied pixels of first image.
The full code can be found in : https://bugs.eclipse.org/bugs/show_bug.cgi?id=153863
I tried to change the PaletteData for the targetData before coping the pixels of the
second image, but that did not work also.
merge(sourceData1, targetData, sourceData1.x, sourceData1.x, 1);
targetData.palette = sourceData2.palette;
merge(sourceData2, targetData, startX, startY, 1);
Tried also to copy the Alpha for each pixel but that did not work as well :
targetData.setAlpha(startX + i, startY + j, sourceData.getAlpha(i, j));
targetData.setPixel(startX + i, startY + j, sourceData.getPixel(i, j));
Here a sample of two SWT images and the result one:
First SWT Image ( size 16x16 , gif format)
Second SWT Image (size 8x16 , gif format)
result SWT image: (size 24x16, gif format)
Note:
Although both images have transparency, the result image doesn't.
I tried to convert the targetData to SWT image instead of saving into file, and the result was the same.
Image resultSWTImage = new Image(Display.getCurrent(), targetData);
As the purpose of merging was for icon decoration.
I was able to perform the merging using this code :
OverlayIcon resultIcon = new OverlayIcon(BaseIconDescriptor, iconDecorationDescriptor, new Point(16, 16));
swt.graphics.Image icon = resultIcon.createImage();
Related
I want to make an application with a small jLabel(50x50) in its corner.
The Problem I now have is that the Image the Label displays is looking really bad.
I also added the same Image as an Icon to a shortcut in windows on my desktop just as a comparison.
Windows on the left side and Java JLabel on the right.
How can I archive a similar scaling result in Jave with no loss in quality?
It does not need to use JLabel.
Code:
ImageIcon imgIcon = new ImageIcon(path);
Image img = imgIcon.getImage();
Image imgScaled = img.getScaledInstance((int) (getWidth()), (int) (getHeight()),
Image.SCALE_SMOOTH);
ImageIcon image = new ImageIcon(imgScaled);
label.setIcon(image);
EDIT:
If you look at these Google Chrome Icons, they are extremely tiny but still sharp and high resolution, how can I archive this in Java?
Your can to use in BufferedImage, this is much higher resolution the JLabel.
You can to create BufferedImage from .png file with ImageIO class.
I see two options, or maybe a combination of this:
You're using a weird resolution image for your ImageIcon
Ratio of width to height is not equal, thus skewed scaling
EDIT In case 2, make sure the JComponent you're using to fetch dimensions from (the one you're calling getWidth and getHeight on) has equal dimensions for both width and height.
I cut your left image, at 62px width/height. First row shows that image scaled, second row shows what happens when I scale the source image down to 32px in graphics program first:
Dimensions, as you can see below, go from 62px up by increments of 10px. Code was run on Java 1.8, Windows 10:
void addSeries(Image srcImg, JPanel targetPanel) {
for (int i = 0; i < 50; i += 10) {
int dimension = 62 + i;
Image imgScaled = srcImg.getScaledInstance(dimension, dimension, Image.SCALE_SMOOTH);
ImageIcon scaledIcon = new ImageIcon(imgScaled);
JLabel label = new JLabel();
label.setIcon(scaledIcon);
targetPanel.add(label);
}
}
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.
I am trying to get the value of the White Colored pixel from a GrayScale image and replace it with another Color but when I run my code, the whole GrayScale image is transfered to another Color. Can anyone please tell me where is fault in the code or how can I get my desired results??
This is the code...
public class gray {
public static void main (String args[])throws IOException{
int width;
int height;
BufferedImage myImage = null;
File f = new File("E:\\eclipse\\workspace\\Graphs\\src\\ColorToGray\\1.png");
myImage = ImageIO.read(f);
width = myImage.getWidth();
height = myImage.getHeight();
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
int pixels[];
pixels = new int[width * height];
myImage.getRGB(0, 0, width, height, pixels, 0, width);
for (int i = 0; i < pixels.length; i++) {
if (pixels[i] == 0xFFFFFF) {
pixels[i] = 0x000000FF;
}
}
File f2 = new File("E:\\eclipse\\workspace\\Graphs\\src\\ColorToGray\\out 1.png");
image.setRGB(0, 0, width, height, pixels, 0, width);
ImageIO.write( image, "jpg", f2);
}
}
Image Before:
Image Before Output
Image After:
Image After Output
I looked into it, and found a bunch of problems.
First of all, when specifying the filename to save, you supply a ".png" extension, but when you call the ImageIO.write() function, you specify file type "jpg". That tends not to work very well. If you try to open up the resulting file, most programs will give you a "this is not a valid .PNG file" error. Windows explorer tries to be smart, and re-interprets the .PNG as a .JPG, but this spared you from the chance of discovering your mistake.
This takes care of the strange redness problem.
However, if you specify "png" in ImageIO.write(), you still don't get the right image. One would expect an image that looks mostly like the original, with just a few patches of blue there where bright white used to be, but instead what we get is an overall brighter version of the original image.
I do not have enough time to look into your original image to find out what is really wrong with it, but I suspect that it is actually a bright image with an alpha mask that makes it look less bright, AND there is something wrong with the way the image gets saved that strips away alpha information, thus the apparent added brightness.
So, I tried your code with another image that I know has no tricks in it, and still your code did not appear to do anything. It turns out that the ARGB format of the int values you get from myImage.getRGB(); returns 255 for "A", which means that you need to be checking for 0xFFFFFFFF, not 0x00FFFFFF.
And of course when you replace a value, you must replace it with 0xFF0000FF, specifying a full alpha value. Replacing a pixel with 0x000000FF has no visible effect, because regardless of the high blue value, alpha is zero, so the pixel would be rendered transparent.
** Important update, see below! **
I am creating a program that changes the pixels of a BufferedImage to a certain color when that pixel fulfills a set of conditions in Java. However, when I write the image to disk, the pixels that should be colored are instead black.
First I define the color, using RGB codes:
Color purple = new Color(82, 0, 99);
int PURPLE = purple.getRGB();
Then I read the image I want to alter from a File into a BufferedImage called "blank":
BufferedImage blank = ImageIO.read(new File("some path"));
Now, loop through the pixels, and when a pixel at location (x, y) matches a criteria, change its color to purple:
blank.setRGB(x, y, PURPLE);
Now, write "blank" to the disk.
File output = new File("some other path");
ImageIO.write(blankIn, "png", output); // try-catch blocks intentionally left out
The resulting file should be "blank" with some purple pixels, but the pixels in question are instead black. I know for a fact that the issue is with setRGB and NOT any import or export functions, because "blank" itself is a color image, and gets written to file as such. I read around and saw a lot of posts recommending that I use Graphics2D and to avoid setRGB, but with no discussion of pixel-by-pixel color changing.
I also tried direct bit manipulation, like this:
blank.setRGB(x, y, ((82 << 16) + (0 << 8) + 99));
I'm probably doing that wrong, but if I put it in correctly it wouldn't matter, because the pixels are getting set to transparent when I do this (regardless of what the numbers say, which is very strange, to say the least).
** When I try this:
blank.setRGB(x, y, Color.RED.getRGB());
My output file is grayscale, so that means setRGB is, in fact, modifying my picture in grayscale. I think this is actually a rather simple issue, but the solution eludes me.
Based on the insights in https://stackoverflow.com/a/21981173 that you found yourself ... (a few minutes after posting the question) ... it seems that it should be sufficient to simply convert the image into ARGB directly after it was loaded:
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
The original image that was imported into Java was actually grayscale, so when Java read it into the BufferedImage, it simply imported it as a grayscale BufferedImage. By adding a very small but imperceptible colored dot in the corner of my image, I was able to get Java to output a correctly colored image.
Unfortunately, this is only a half solution, because I do not know how to fix this programmatically.
SOLUTION:
Convert the BufferedImage from grayscale to ARGB with this snippet:
BufferedImage blank2 = blank;
// Create temporary copy of blank
blank = new BufferedImage(blank.getWidth(), blank.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Recreate blank as an ARGB BufferedImage
ColorConvertOp convert = new ColorConvertOp(null);
// Now create a ColorConvertOp object
convert.filter(blank2, blank);
// Convert blank2 to the blank color scheme and hold it in blank
You want to add this right after blank = ImageIO.read(new File("some path")).
I have an image, call it grayscale.jpg. Now I open that image in The Gimp and change the color mode to RGB and save it as color.jpg. If I view grayscale.jpg and color.jpg in any image viewer, they look exactly the same. But if I open the images with javax.imageio.ImageIO
import javax.imageio.ImageIO;
input = ImageIO.read(new File("grayscale.jpg"));
System.out.format("Grayscale value: %x\n", input.getRGB(200, 200));
input = ImageIO.read(new File("color.jpg"));
System.out.format("Color value: %x\n", input.getRGB(200, 200));
The color image will return the correct value, say 0xff6c6c6c. The grayscale image will return a different, lighter, incorrect value like 0xffaeaeae.
Grayscale value: 0xffaeaeae // Incorrect (Lighter)
Color value: 0xff6c6c6c // Correct
In other words, javax.imageio.ImageIO thinks grayscale images are much lighter than they actually are. How can I accurately read grayscale images?
Edit
Here's more context. My users upload images, which may be grayscale. My Java runs on the server and does some pretty complex image processing. So an ideal solution is to just fix my Java code as opposed to cobbling something together with command line tools.
Your test are irrelevant because you are using JPEG, which is lossy. Depending on the compression, you might have other color values. So, try the same with PNG, which is lossless.
You can use this image to test the correctness of javax.imageio. Convert this one to grayscale with Gimp and make sure you save it as PNG. Then load both (this one and the converted one) the same way. And compare in a for loop all the colors of the y-axis.
Sample code:
BufferedImage inputGrayscale = ImageIO.read(new File("grayscale.png"));
BufferedImage inputColor = ImageIO.read(new File("color.png"));
for (int i = 0; i < 256; ++i)
{
System.out.printf(i + "Grayscale value: %x\n", inputGrayscale.getRGB(10, i));
System.out.printf(i + "Color value: %x\n", inputColor.getRGB(10, i));
System.out.println();
}