get RGB-YCbCr components of image - java

I want to show the jpeg image R_G_B channels as separated images in jlabel and the Y-Cb-Cr channels as well, I got the arrays but don't know how to convert them to images
///
Edit:
thanX very much , this is the method I'm writing ,Now It can display just the upper left quarter of the image ,and show it in a blue color whatever the color channel was?
public void getRGB_YCC(int width,int height,String inFileName) {
R=new int[height][width];G=new int[height][width];
B=new int[height][width];Y=new int[height][width];
Cb1=new int[height][width];Cr1=new int[height][width];
final int values[] = new int[width * height];
int r, g, b, Y_ch,Cb,Cr, y, x;
final PixelGrabber grabber = new PixelGrabber(image.getSource(), 0, 0,width,height, values, 0, width);
try {
if (grabber.grabPixels() != true) {
try {
throw new AWTException("Grabber returned false: " + grabber.getStatus());
} catch (final Exception e) {};
}
} catch (final InterruptedException e) {};
int index = 0;
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
r = values[index] >> 16 & 0xff;
g = values[index] >> 8 & 0xff;
b = values[index] & 0xff;
Y_ch= (int)(0.299 * r + 0.587 * g + 0.114 * b);
Cb= 128 + (int) (-0.16874 * r - 0.33126 * g + 0.5 * b);
Cr= 128 + (int)(0.5 * r - 0.41869 * g - 0.08131 * b);
R [y][x]=r;
G [y][x]=g;
B [y][x]=b;
Y [y][x]=Y_ch;
Cb1[y][x]=Cb;
Cr1[y][x]=Cr;
index++;
}
}
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
for( y=0;y<height;y++)
{
for( x=0;x<width;x++)
{
pixels[x + y*width] =R[y][x]<<16;
}
}
jLabel15.setIcon(new ImageIcon(img));
}

A simple and fast way to get an array of pixels into an image is using BufferedImage:
This example creates a grayscale 8 bit image and retrieves a 'pixel buffer' for it:
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
byte[] pixels = ((DataBufferByte)img.getRaster().getDataBuffer()).getData();
This also works with RGB:
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
You now can set pixels by just writing to the pixels array like pixels[x + y * w] = value and the results are instantly visible.

Related

How to display a 48 bit RGB image (16 bit per channel) in JavaFX?

I'm using JavaFX and I have a 16bit grayscale image that I'm able to show with the following code:
public Image createNewImageFromArrayPixels(int[][] pixels) {
int width = pixels.length;
int height = pixels[0].length;
int[] buffer = from2DArrayTo1DArray(pixels);
ColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_GRAY), //we have grayscale images
new int[]{16}, //bit depth: 16 bit per pixel
false,
false,
Transparency.OPAQUE,
DataBuffer.TYPE_INT); //every pixel has an integer intensity
WritableRaster raster = colorModel.createCompatibleWritableRaster(height, width);
DataBufferInt buff = (DataBufferInt) raster.getDataBuffer();
int[] bufferData = buff.getData();
System.arraycopy(buffer, 0, bufferData, 0, (buffer.length < bufferData.length ? buffer.length : bufferData.length));
BufferedImage bm = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
Image img = SwingFXUtils.toFXImage(bm, null);
return img;
}
Now I want to transform it in a 48bit RGB image (16bit per channel), but I can't understand how.
At the moment I'm able to create a RGB 24bit image (8 bit per channel) by taking the int value of a pixel from the grayscale image and building manually the bytes that will compose the pixels with the following code:
private Image createRGBImageFromGrayPixels(int[][] pixels) {
int width = pixels.length;
int height = pixels[0].length;
BufferedImage bm = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int converted = from16to8(pixels[y][x]);
System.out.println("original " + pixels[y][x] + " = " + converted + " = " + from8to16(converted));
int rgb = converted;
rgb = (rgb << 8) + converted;
rgb = (rgb << 8) + converted;
bm.setRGB(x, y, rgb);
}
}
Image img = SwingFXUtils.toFXImage(bm, null);
return img;
}
private int from16to8(int value) {
int originalStart = 0;
int originalEnd = 65535;
int newStart = 0;
int newEnd = 255;
double scale = (double)(newEnd - newStart) / (originalEnd - originalStart);
double res = newStart + ((value - originalStart) * scale);
System.out.println(res);
int result = Math.round(Math.round(res));
return result;
}
Similarly, I'm also able to create the same structure for 16bits obtaining the desired rgb value, but it is a long and is not accepted by the setRGB() method, so I'm not able to create the bufferedImage, whose type I can't specify.
Can anyone help me with this final steps, please? Thank you in advance.
private Image createRGBImageFromGrayPixels_16(int[][] pixels) {
int width = pixels.length;
int height = pixels[0].length;
BufferedImage bm = new BufferedImage(width, height, BufferedImage...); //BufferedImage.TYPE ???
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
long rgb = pixels[y][x];
rgb = (rgb << 16) + pixels[y][x];
rgb = (rgb << 16) + pixels[y][x];
System.out.println(pixels[y][x] + "\t->\t" + rgb);
System.out.println();
bm.setRGB(x, y, rgb); //ERROR: long type for rgb is not accepted!
}
}
Image img = SwingFXUtils.toFXImage(bm, null);
return img;
}
If needed, I can also install external jar libraries (obviously, only if opersource) that can help me achieving this goal.

Converting subimage to RGB-A

I am working on a 2D platform game and I have a sprite sheet which includes the sprites of tiles and blocks.
I noticed that there was a pink-ish background behind the transparent sprites so I thought that Java wasn't loading the sprites as PNG and I tried to re-draw the sprite on a new bufferedImage, pixel by pixel checking if the pixel was R=255, G=63, B=52 but unfortunately, the code wasn't able to detect that either and at this point I have no more options left to try.
I made sure that the "pink" color values are correct by using a color picker.
original spritesheet (transparent):
The class that loads the sprite(s) is:
public class SpriteSheet {
private BufferedImage image;
public SpriteSheet(BufferedImage image) {
this.image = image;
}
public BufferedImage grabImage(int col, int row, int width, int height) {
BufferedImage alpha = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
BufferedImage img = image.getSubimage(
(col * width) - width,
(row * height) - height,
width,
height);
int w = img.getWidth();
int h = img.getHeight();
for(int y = 0; y < h; y++) {
for(int x = 0; x < w; x++) {
int pixel = img.getRGB(x, y);
int red, green, blue;
red = (pixel >> 16) & 0xff;
green = (pixel >> 8) & 0xff;
blue = (pixel) & 0xff;
if(red == 255 && green == 63 && blue == 52)
alpha.setRGB(x, y, new Color(0, 0, 0, 0).getRGB());
else
alpha.setRGB(x, y, pixel);
}
}
return alpha;
}
}
the class that loads the sprite sheet is:
public class Texture {
SpriteSheet bs, ss;
private BufferedImage block_sheet = null;
public BufferedImage[] block = new BufferedImage[3];
public Texture() {
BufferedImageLoader loader = new BufferedImageLoader();
try {
block_sheet = loader.loadImage("/tiles.png");
} catch(Exception e) {
e.printStackTrace();
}
bs = new SpriteSheet(block_sheet);
getTextures();
}
private void getTextures() {
block[0] = bs.grabImage(1, 1, 32, 32);
block[1] = bs.grabImage(2, 1, 32, 32);
block[2] = bs.grabImage(4, 1, 32, 32);
}
}
How do I get rid of the pink-ish background and keep transparency?
I dont understand why you're using subImage.
try {
BufferedImage img = ImageIO.read(new File("D:/image.png"));
for (int i = 0; i < img.getWidth(); i++) {
for (int j = 0; j < img.getHeight(); j++) {
Color pixelcolor = new Color(img.getRGB(i, j));
int r = pixelcolor.getRed();
int g = pixelcolor.getGreen();
int b = pixelcolor.getBlue();
if (r == 255 && g == 63 && b == 52) {
int rgb = new Color(255, 255, 255).getRGB();
img.setRGB(i, j, rgb);
}
}
}
ImageIO.write(img, "png", new File("D:/transparent.png"));
} catch (Exception e) {
System.err.println(e.getMessage());
}
cough, It worked all along, I had forgotten to disable the test blocks which was representing the blocks. Realized this after some time.
So the transparency was working fine. I just saw the rectangle i was drawing behind it.

How to convert image to black & white image and remove shadow in andorid Using OpenCV

I have a code that turns a RGB bitmap into a bitmap of black and white colors, using this code:
public static Bitmap setDefaultValues(Bitmap bmp) {
Mat srcMat = new Mat();
org.opencv.android.Utils.bitmapToMat(bmp, srcMat, true);
final Bitmap bitmap = Bitmap.createBitmap(srcMat.clone().width(), srcMat.clone().height(), Bitmap.Config.ARGB_8888);
Imgproc.cvtColor(srcMat, srcMat, Imgproc.COLOR_BGR2GRAY, 0);
Mat srcMat1 = srcMat;
Imgproc.GaussianBlur(srcMat1, srcMat1, new Size(3, 3), 0);
//Mat srcMat1 = new Mat(srcMat.rows(), srcMat.cols(), CV_8UC1);
//int kernalsize = 3;
//Imgproc.bilateralFilter(srcMat, srcMat1, kernalsize, kernalsize * 2, kernalsize / 2);
srcMat1.convertTo(srcMat1, 0, 1.9, -120);
srcMat1.convertTo(srcMat1, CvType.CV_8U, 1.9, -120);
Imgproc.cvtColor(srcMat1, srcMat1, Imgproc.COLOR_GRAY2RGBA, 4);
org.opencv.android.Utils.matToBitmap(srcMat, bitmap, true);
return bitmap;
}
I have implement this code for convert RGB image into black and white.
this is return me as right, but my question is here i cant remove shadow from image.
also i have compare other application this is convert perfectly, i don't understand where i am wrong.
this is original Image :
this is my application output
this is other application output
So please help me how can i achieve my goal.
Please use following code for convert your color image to black and white.
public static Bitmap createContrast(Bitmap src, double value) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// get contrast value
double contrast = Math.pow((100 + value) / 100, 2);
// scan through all pixels
for(int x = 0; x < width; ++x) {
for(int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// apply filter contrast for every channel R, G, B
R = Color.red(pixel);
R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(R < 0) { R = 0; }
else if(R > 255) { R = 255; }
G = Color.red(pixel);
G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(G < 0) { G = 0; }
else if(G > 255) { G = 255; }
B = Color.red(pixel);
B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if(B < 0) { B = 0; }
else if(B > 255) { B = 255; }
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;}
Please try this if you will get the solution
public static Bitmap test(Bitmap src){
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
// use 128 as threshold, above -> white, below -> black
if (gray > 128) {
gray = 255;
}
else{
gray = 0;
}
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));
}
}
return bmOut;
}
Please see the answer on this thread. He has explained and provide a good result in output.
#Threshold image using opencv (Java)

How to extract Y, Cb and Cr color components?

I need to decompose a given colored picture in three separate pictures, so that each color component (Y, Cb, Cr) is stored in one picture like here.
Maybe has an idea how I could get these three pictures with
separately Y, Cb or Cr color components? With following peace of code I can just read out the file and convert the color model from RGB to YCbCr.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class SpaceConverter {
static int [] colorComponentsYCbCr = new int[3];
static int [] colorComponentsRGB = new int[3];
public static void getRGBComponents (int color)
{
colorComponentsRGB [0] = (color & 0xff);
colorComponentsRGB [1] = (color & 0x00ff) >> 8;
colorComponentsRGB [2] = (color & 0x0000ff) >> 16;
}
public static void convertYCbCr2RGB(int [] componentsYCbCrToConvert)
{
int Y = componentsYCbCrToConvert [0];
int Cb = componentsYCbCrToConvert [1];
int Cr = componentsYCbCrToConvert [2];
colorComponentsRGB = new int [3];
colorComponentsRGB [0] = (int) (Y + 1.402 * (Cr - 128));
colorComponentsRGB [1] = (int) (Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128));
colorComponentsRGB [2] = (int) (Y + 1.772 * (Cb - 128));
}
public static void convertRGB2YCbCr(int [] componentsRGB)
{
int blue = componentsRGB [0];
int green = componentsRGB [1];
int red = componentsRGB [2];
colorComponentsYCbCr [0] = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
colorComponentsYCbCr [1] = (int) (128-0.169 * red-0.331 * green + 0.500 * blue);
colorComponentsYCbCr [2] = (int) (128+0.500 * red - 0.419 * green - 0.081 * blue);
}
public static void getColoredCrPicture(BufferedImage image)
{
File f = null;
// get width and height
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y<height; y++)
{
for (int x = 0; x<width; x++)
{
int color = image.getRGB(x, y);
getRGBComponents(color);
convertRGB2YCbCr(colorComponentsRGB);
int Y = colorComponentsYCbCr[0];
int Cb = colorComponentsYCbCr[1];
int Cr = colorComponentsYCbCr[2];
Y = 0;
Cb = 0;
int p = (Y << 24) | (Cb << 16) | (Cr<<8);
image.setRGB(x, y, p);
}
}
try
{
f = new File("/Users/MAC/Documents/workspace/ColorConverter/src/outputX.jpg");
ImageIO.write(image, "jpg", f);
}
catch(IOException e)
{
System.out.println(e);
}
}
public static void getColoredCbPicture(BufferedImage image)
{
File f = null;
// get width and height
int width = image.getWidth();
int height = image.getHeight();
for (int y = 0; y<height; y++)
{
for (int x = 0; x<width; x++)
{
int color = image.getRGB(x, y);
getRGBComponents(color);
convertRGB2YCbCr(colorComponentsRGB);
int Y = colorComponentsYCbCr[0];
int Cb = colorComponentsYCbCr[1];
int Cr = colorComponentsYCbCr[2];
Y = 0;
Cr = 0;
int p = (Y << 24) | (Cb<< 16) | (Cr <<8);
image.setRGB(x, y, p);
}
}
try
{
f = new File("/Users/MAC/Documents/workspace/ColorConverter/src/outputCb.jpg");
ImageIO.write(image, "jpg", f);
System.out.println("WRITE Status: OK");
}
catch(IOException e)
{
System.out.println(e);
}
}
public static BufferedImage loadPicture()
{
File f = null;
BufferedImage img = null;
// read Image
try
{
f = new File("/Users/MAC/Documents/workspace/ColorConverter/src/VILLA.JPG");
img = ImageIO.read(f);
System.out.println("READ Status: OK");
getColoredCbPicture(img);
}
catch(IOException e)
{
System.out.println(e);
}
return img;
}
public static void main(String[] args)
{
BufferedImage image = null;
loadPicture();
getColoredCbPicture(image);
}
}
It sounds like what you are looking to do is take an RGB image, convert it to YCbCr and display each of the three channels in YCbCr as a separate RGB image.
You already have code that converts from RGB to YCbCr . You will also need code that will do the reverse conversion so you can go from YCbCr to RGB.
You will want to use this same logic, but actually create three Y'CrCb images: (Y, 0, 0), (0, Cb, 0) and (0, 0, Cr). Then convert each of these three images to RGB. These three images will be an RGB representation of each of the three YCbCr channels.

Take monochrome picture (black and white) with Android

I would like to take a picture in true black and white in my app. I searched for solutions (in this site too), but I always found solution to put a photo in gray scale (for example in this topic), but it's not what I am looking for ...
I also found a topic proposing this :
public static Bitmap createContrast(Bitmap src, double value) {
// image size
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// get contrast value
double contrast = Math.pow((100 + value) / 100, 2);
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
// apply filter contrast for every channel R, G, B
R = Color.red(pixel);
R = (int) (((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if (R < 0) {
R = 0;
} else if (R > 255) {
R = 255;
}
G = Color.red(pixel);
G = (int) (((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if (G < 0) {
G = 0;
} else if (G > 255) {
G = 255;
}
B = Color.red(pixel);
B = (int) (((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
if (B < 0) {
B = 0;
} else if (B > 255) {
B = 255;
}
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
But the image quality is horrible ...
Is anyone having an idea please?
Thank you
If you like the image to be 1bit black/white you can use a simple (& slow) threshold algorithm
public static Bitmap createBlackAndWhite(Bitmap src) {
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
// use 128 as threshold, above -> white, below -> black
if (gray > 128)
gray = 255;
else
gray = 0;
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));
}
}
return bmOut;
}
But depending on what that will not look good, for better results you need a dithering algorithm, see Algorithm overview - this one is the threshold method.
For 256 levels of gray conversion:
according to http://www.mathworks.de/help/toolbox/images/ref/rgb2gray.html you calculate the gray value of each pixel as gray = 0.2989 * R + 0.5870 * G + 0.1140 * B which would translate to
public static Bitmap createGrayscale(Bitmap src) {
int width = src.getWidth();
int height = src.getHeight();
// create output bitmap
Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
// color information
int A, R, G, B;
int pixel;
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = src.getPixel(x, y);
A = Color.alpha(pixel);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, gray, gray, gray));
}
}
return bmOut;
}
But that is pretty slow since you have to do that for millions of pixels separately.
https://stackoverflow.com/a/9377943/995891 has a much nicer way of achieving the same.
// code from that answer put into method from above
public static Bitmap createGrayscale(Bitmap src) {
int width = src.getWidth();
int height = src.getHeight();
Bitmap bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOut);
ColorMatrix ma = new ColorMatrix();
ma.setSaturation(0);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(ma));
canvas.drawBitmap(src, 0, 0, paint);
return bmOut;
}
G = Color.red(pixel);
G = Color.green(pixel);
B = Color.red(pixel);
B = Color.blue(pixel);
See if this changes (in bold) helps.

Categories