Java SWT: Displaying image Pixel by Pixel but Blues look Yellow - java

I am displaying an image Pixel by Pixel. All the blues look yellow. I suspect the issue is with the PalletteData or with the following line(The Pixel object just holds the int representation of the colour):
p = (pixel.Alpha<<24) | (pixel.Red<<16) | (pixel.Green<<8) | pixel.Blue;
Note: as the call is from Java to C++ accross JNI, there are some conversions:
Each colour is read in to an unsigned char. Then it is converted to char to pass accross JNI. Then is read as a byte on the Java side. Then converted to Int
Here is the full listing. Can you see what my problem is?
PaletteData palette=new PaletteData(0xff0000,0x00ff00,0xff);
ImageData imageData = new ImageData(width, height,32,palette);
int pixelVecLoc=0;
for (int h = 0; h<1300; h++)
{
for (int w = 0; w<1300; w++)
{
int p = 0;
Pixel pixel = pixelVec.get(pixelVecLoc);
p = (pixel.Alpha<<24) | (pixel.Red<<16) | (pixel.Green<<8) | pixel.Blue;
imageData.setPixel(w, h, p);
pixelVecLoc++;
}
}
imageData = imageData.scaledTo(600, 500);
Image image = ImageDescriptor.createFromImageData(imageData).createImage();
//Image image = new GVImageProcessingJNIWrapper().GetBMPFromGTX();
e.gc.drawImage(image, 0, 0);

I figured it out!!! It was the conversion from byte to int.
I needed to use this:
Byte.toUnsignedInt

Related

How to convert a Binary String into Gray scale image?

I'm reading a serial port from a money counter machine and I'm expecting to get a serial number of a banknote sent from the money counter.
I read the byte array from the machine and converted it to a binaryString using the code below:
public void serialEvent(SerialPortEvent serialPortEvent) {
ArrayList<String> list = new ArrayList<>();
String s1 = new String();
if (serialPortEvent.getEventType() != SerialPort.LISTENING_EVENT_DATA_AVAILABLE) {
return;
}
byte[] readBuffer = new byte[comPort.bytesAvailable()];
int numRead = comPort.readBytes(readBuffer, readBuffer.length);
//System.out.println("Read " + numRead + " bytes.");
for (Byte b : readBuffer) {
//image is more than 500 bytes, all other data is less than 500
if (numRead <= 500) {
break;
}
s1 = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
//new line byte, everytime it shows up I add a new line
if (s1.equals("01000101")) {
System.out.println();
continue;
}
System.out.print(s1);
The picture below is the screenshot from s1 String that I got from System.out and as you can see there is the serial number represented by 1s, and the background is represented by 0s.
My question now is how to convert this String to an image file?
I'm guessing I need to make an 1d or 2d array from this String and make an image where 0s represent white pixels and 1s represent black pixels, but I'm not sure how to do this and I need some help?
Thanks in advance.
EDIT:
I can get the ASCII output using this code:
public void serialEvent(SerialPortEvent serialPortEvent) {
InputStream in = comPort.getInputStream();
Reader in2 = new InputStreamReader(in, StandardCharsets.US_ASCII);
try
{
for (int j = 0; j < 10000; ++j) {
System.out.print((char)in2.read());
in.close();
}
} catch (Exception e) { e.printStackTrace(); }
comPort.closePort();
}
});
Text Output
This is the text output of the serial port.
EDIT 2:
Data that I got from the manufacturer of the machine.
Data from the manufacturer
EDIT 3:
Here is a drawn picture using Graphics Java library.
PBM File Format
You can almost directly write your ASCII art string into a PBM file.
Check the file format here: https://netpbm.sourceforge.net/doc/pbm.html
Other file format
If you prefer to create BMP | GIF | JPEG | PNG | TIFF | WBMP (the formats supported by ImageIO), follow this procedure:
First create a BufferedImage using it's constructor.
Retrieve the Graphics context from the BufferedImage.
Draw your pixels into the Graphics context.
Initialize the background using setColor(Color.white), fillRect.
For each 1 draw a black rectangle: setColor, fillRect
You just have to count your bits so you know the coordinates of the rectagle.
Finally save the BufferedImage to file using ImageIO.write()
Converting from your ascii strings could look like this:
Graphics g = ...
// assuming your string values are stored in the array strings
for(int y=0; y<strings.length, y++) {
String line = strings[y];
for(int x=0; x<line.length(); x++) {
if (line.charAt(x)=='1') {
g.setColor(Color.black);
g.fillRect(x, y, 1, 1);
}
}
}

Manipulating the Alpha value of BufferedImage

In the code i'm setting the alpha value of a pixel to 100 for entire image and I want the Alpha value to be 100 while reading the image. But at the retrieving part it gives me 255(Default Value) . What is wrong ? and how to solve it ? Any Help would be appreciated...
class Demo
{
Demo()
{
try
{
BufferedImage im2 = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
File f2 = new File("test2.jpg");
im2 = ImageIO.read(f2);
int width1 = im2.getWidth();
int height1 = im2.getHeight();
for(int i=0;i<height1;i++)
{
for(int j=0;j<width1;j++)
{
Color c = new Color(50,0,0,100); //Set the alpha value to 100
im2.setRGB(j,i,c.getRGB()); // for every pixel
}
}
File f = new File("Demo_copy.jpg");
ImageIO.write(im2,"jpg",f);
// Retrieving.........
BufferedImage im1;
File f1 = new File("Demo_copy.jpg");
im1 = ImageIO.read(f1);
int width = im1.getWidth();
int height = im1.getHeight();
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
int pixel = im1.getRGB(j,i);
Color c = new Color(pixel,true);
int a = c.getAlpha();
System.out.println("Alpha value is :"+a); // Printing Alpha : 255 for every pixel
}
}
}catch(Exception e){}
}
public static void main(String [] ar)
{
new Demo();
}
}
The new BufferedImage(...) you assign to im2 is just thrown away (garbage collected) after you assign a new value from ImageIO.read(..). As the new value is a JPEG and doesn't have alpha, it does not matter what alpha values you set. They will always stay 255 (completely opaque).
Instead, you probably want to do something like this:
// Read opaque image...
BufferedImage img = ImageIO.read(new File("test2.jpg"));
// ...convert image to TYPE_INT_ARGB...
BufferedImage im2 = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = im2.createGraphics();
try {
g.drawImage(img, 0, 0, null);
}
finally {
g.dispose();
}
// ... loop over and change alpha in im2 as before
Finally, you should write the image in a format that supports lossless alpha, like PNG instead of JPEG, to be sure you get the values you expect:
ImageIO.write(im2,"PNG", new File("Demo_copy.png"));
PS: It might just work using JPEG too, as the built-in Java ImageIO JPEG plugin supports reading/writing JPEGs with alpha values. However, most other software will misinterpret these as CMYK JPEGs, and the colors will look all wrong. Also, JPEG is lossy, so you will most likely not see the exact alpha value (100) as you would expect on the receiving end. That's why I suggest using PNG. TIFF or other format that supports alpha would also work, but requires extra plugins.

Finding the color at coordinates in a PNG image in Java

With a URL of a PNG image (or the data at that url, in String form), how could one use Java to find the RGB (or similar) value at a set of coordinates?
Thanks in advance!
This example should have all you need:
http://www.daniweb.com/software-development/java/threads/114513
To cite the relevant part of the thread:
File inputFile = new File("image.png");
BufferedImage bufferedImage = ImageIO.read(inputFile);
int w = bufferedImage.getWidth();
int h = bufferedImage.getHeight(null);
//Get Pixels
int [] rgbs = new int[w*h];
bufferedImage.getRGB(0, 0, w, h, rgbs, 0, w); //Get all pixels
and then to get a particular pixel, see the docs:
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferedImage.html#getRGB(int,%20int,%20int,%20int,%20int%91%93,%20int,%20int)
i.e.:
int pixel = rgbs[offset + (y-startY)*scansize + (x-startX)];
If you just want one pixel, you can use getRGB(x, y):
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferedImage.html#getRGB(int,%20int)
i.e.:
int pixel = bufferedImage.getRGB(x, y);

Java beginner: convert an image to a binary array

this is what I've gone so far and I can't seem to go further because I don't understand bitwise operations on the RGB
// Read from a file
File file = new File("src/a.gif");
image = ImageO.read(file);
int[] rgbarr = image.getRGB(0, 0, 13, 15, null, 0, 13);// image is 13*15
System.out.println(rgbarr.length);
for (int i : rgbarr)
{
System.out.println(i);
}
Output: was values such as -16777216 and -1 Because I've already made an image black and white just to ease my understanding
But in our case here let's suppose it would be just random image , how do I get from normal RGB image to binary values (0 or 1) for each pixel.
I'm betting that each int in the array is a packed ARGB value;
boolean [] output = new boolean[rgbarr.length];
for ( int i=0; i<rgbarr.length; ++i ) {
int a = (rgbarr[i] >> 24 ) & 0x0FF;
int r = (rgbarr[i] >> 16 ) & 0x0FF;
int g = (rgbarr[i] >> 8 ) & 0x0FF;
int b = (rgbarr[i] ) & 0x0FF;
output[i] = (0.30*r + 0.59*g + 0.11*b) > 127;
}
The output equation I choose was taken from a definition of Luminance from wikipedia. You can change the scales so long as the coefficients add up to 1.
You can do some thing like this,
BufferedImage img = (BufferedImage) image;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img , "jpg", baos);
byte[] previewByte = baos.toByteArray();
Hope this helps!!
You already have RGB values in the int[], that is color of each pixel. You could compare this to a specific background color, like black, to get a 1-bit pixel value. Then maybe set a bit in another appropriately sized byte[] array...

About java ByteArrayOutputStream class

BufferedImage bufferedImage = ImageIO.read(new File("/...icon.jpg"));
// this writes the bufferedImage into a byte array called resultingBytes
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", byteArrayOut);
byte[] resultingBytes = byteArrayOut.toByteArray();
I use the above code to get a JEPG image as a byte array. I want to know what exactly is in this byte array. Does this array contain any file header information or just pixel values? And for example, if I want to reverse this image's color, what is a good way to do so?
Thanks so much!
It's a complete JPEG file, in memory.
EDIT: If you want to manipulate pixel data as an array, you may find Raster more helpful:
E.g.:
Raster raster = bufferedImage.getData();
You can then call one of the Raster.getPixels methods.
The ByteArrayOutputStream contains whatever you wrote to it. Nothing more, nothing less. So your question is really about ImageIO.write(). Which writes out an encoding of an image according to the encoding type you supply. Which was JPEG.
Here is how you read real pixel values. The JPEG information is much harder to do anything with!
public static void main(String... args) throws IOException {
String u = "http://blog.stackoverflow.com/wp-content/uploads/stackoverflow-logo-300.png";
BufferedImage old = ImageIO.read(new URL(u));
BufferedImage inverted = new BufferedImage(old.getWidth(),
old.getHeight(),
BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < old.getHeight(); y++) {
for (int x = 0; x < old.getWidth(); x++) {
Color oldColor = new Color(old.getRGB(x, y));
// reverse all but the alpha channel
Color invertedColor = new Color(255 - oldColor.getRed(),
255 - oldColor.getGreen(),
255 - oldColor.getBlue());
inverted.setRGB(x, y, invertedColor.getRGB());
}
}
ImageIO.write(inverted, "png", new File("test.png"));
}

Categories