How to clear pixel of BufferedImage in java? - java

In java, I read an image and then go through the pixels and if its color distance is < 30, then I want to clear the image by changing its alpha to 0. This is my code:
But this is not working. It is having no effect...
Does anyone see the problem?
Thanks
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
public class Recognize {
public static void main(String args[]) throws IOException {
Path path = Paths.get("images/fish.png");
File file = path.toFile();
if (file.exists()) {
InputStream stream = Files.newInputStream(path);
BufferedImage bufferedImage = ImageIO.read(stream);
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
if (width > 0 && height > 0) {
int TLpixel = bufferedImage.getRGB(0, 0);
Color TLcolor = new Color(TLpixel);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
int pixel = bufferedImage.getRGB(i, j);
Color color = new Color(pixel);
double distance = ColourDistance(TLcolor, color);
//System.out.println(distance);
if (distance < 30) {
int mc = (0 << 24) | 0x00ffffff;
int newcolor = pixel & mc;
bufferedImage.setRGB(i, j, newcolor);
}
}
}
File outputfile = new File("images/fish_new.png");
ImageIO.write(bufferedImage, "png", outputfile);
}
}
}
public static int[] printPixelARGB(int pixel) {
int alpha = (pixel >> 24) & 0xff;
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
return new int[] {red, green, blue, alpha};
}
public static double ColourDistance(Color c1, Color c2) {
double rmean = ( c1.getRed() + c2.getRed() )/2;
int r = c1.getRed() - c2.getRed();
int g = c1.getGreen() - c2.getGreen();
int b = c1.getBlue() - c2.getBlue();
double weightR = 2 + rmean/256;
double weightG = 4.0;
double weightB = 2 + (255-rmean)/256;
return Math.sqrt(weightR*r*r + weightG*g*g + weightB*b*b);
}
}

By "clearing" the pixel you obviously meant "to make the pixel transparent".
In order to be able to make a pixel transparent, the image has to support transparent pixels. Whether or not a BufferedImage supports transparent pixels depends on the type of the BufferedImage. After loading a BufferedImage with ImageIO, you hardly know the type of the image. But you can easily convert the image into an image with a known type (that supports transparency) by passing it to a method like this:
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;
}

Related

Search for color in BufferedImage Java

I currently have a script that can create a bufferedimage of the screen, and then list the value for a specific pixel. However, I'm trying to search the entire bufferedimage for a specific color. Is there a way to do this?
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException, AWTException {
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
int x = 10;
int y = 10;
int clr = image.getRGB(x, y);
int red = (clr & 0x00ff0000) >> 16;
int green = (clr & 0x0000ff00) >> 8;
int blue = clr & 0x000000ff;
System.out.println("Red = " + red);
System.out.println("Green = " + green);
System.out.println("Blue = " + blue);
}
}
You could use nested for loops for every (x, y) coordinate of the image (with x between 0 and image.getWidth(), and y between 0 and image.getHeight()) and compare if the color at the given position is equal to the color you are looking for.

Want to reduce bit size for RGB levels of an image

I want to reduce the image color quantization from 16 to 8 bit. This is my code so far. It only makes the image transparent. From what I've learnt, I'm supposed to take each individual pixel and divide by factor of bit size reduction. What am I doing wrong here?
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.util.Scanner;
public class ConvertImage{
public static void main(String args[])throws IOException{
BufferedImage image = null;
File f = null;
try {
f = new File("lennapng.png");
image = ImageIO.read(f);
}catch(IOException e){
System.out.println(e);
}
//get width and height
int width = image.getWidth();
int height = image.getHeight();
width = image.getWidth();
height = image.getHeight();
for(int y = 0; y < height; y++) {
for(int x = 0; x <height; x++) {
int p = image.getRGB(x, y);
// System.out.println("rgb "+ rgb);
int a = (p>>24) & 0xff;
int r = (p>>16) & 0xff;
int g = (p>>8) & 0xff;
int b = p&0xff;
r= r*16/256;
g= g*16/256;
b = b*16/256;
//set new RGB
p = (a<<12) | (r<<8) | (g<<4) | b;
image.setRGB(x, y, p);
}
}
try{
f = new File("output.png");
ImageIO.write(image, "png", f);
}catch(IOException e){
System.out.println(e);
}
}
}

Converting certain pixels' RGB color to another color

Programming Language: Java
I am trying to convert certain pixels of this image to a different color to reveal a "Secret Message."
Most of the pixels are:
Red = 0, Green = 64, Blue = 0
The pixels that I want changed to R = 255, G = 255, B = 255 are:
Red = 5, Green = 64, Blue = 5
import java.io.File;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Color;
public class ASSN2p2
{
private static int makeRGBColor(int red, int green, int blue)
{
int rgb = 0;
rgb = red*65536 + green*256 + blue;
return rgb;
}
private static int getRed(int pixel)
{
return (pixel >> 16) & 0xFF;
}
private static int getGreen(int pixel)
{
return (pixel >> 8) & 0xFF;
}
private static int getBlue(int pixel)
{
return (pixel) & 0xFF;
}
public static void main(String args[]) throws IOException
{
// int width = 300;
// int height = 200;
BufferedImage image = null;
File f = null;
try
{
f = new File("D:\\2016-2017\\Fall2016\\201_CSCE_Programming\\Assignment 2\\secretmessage.png");
image = ImageIO.read(f);
image = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
System.out.println("Reading Complete");
BufferedImage output = new BufferedImage(image.getWidth(), image.getHeight(),BufferedImage.TYPE_INT_ARGB);
//--------------------------------------
//-------------------------------------------
for (int y = 0; y < image.getHeight(); y++)
{
for (int x = 0; x < image.getWidth(); x++)
{
int pixel = image.getRGB(x, y);
int r,g,b;
r = getRed(pixel);
g = getGreen(pixel);
b = getBlue(pixel);
if ((r == 5) && (g == 64) && (b == 5))
{
r = 64;
b = 64;
b = 64;
image.setRGB(x,y,makeRGBColor(r,g,b));
} }
}
}
catch(IOException e)
{
System.out.println("Error: "+e);
}
// printPixelARGB(pixel);
// System.out.println("");
try
{
f = new File("D:\\2016-2017\\Fall2016\\201_CSCE_Programming\\Assignment 2\\output.png");
ImageIO.write(image, "png", f);
System.out.println("Writing Complete");
}
catch(IOException e)
{
System.out.println("Error: "+e);
}
}
}
This produces this:
I am having trouble understanding what has gone wrong!
Any assistance will be appreciated!
I believe that you're missing the alpha component of your new color. Change your code to:
private static int makeRGBColor(int red, int green, int blue) {
int rgb = 0xff000000 | (red << 16) | (green << 8) | blue;
return rgb;
}
to make sure that the alpha is set to full, otherwise your image will look completely transparent.

DCT of buffered image using JTransform - Java

I'm trying to get the DCT of a bufferedImage using JTransform. When I visualise the transform it currently looks like this http://tinypic.com/r/2vcxhzo/8
In order to use Jtransform I need to convert the BufferedImage to a 2d double array. I've tried two different methods to change the bufferedImage to a double array
public double[][] convertTo2DArray(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster()
.getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
double[][] result = new double[height][width];
final boolean hasAlphaChannel = image.getAlphaRaster() != null;
if (hasAlphaChannel) {
final int pixelLength = 4;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
argb += ((int) pixels[pixel + 1] & 0xff); // blue
argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
} else {
final int pixelLength = 3;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += -16777216; // 255 alpha
argb += ((int) pixels[pixel] & 0xff); // blue
argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
}
return result;
}
I've also tried
private double[][] bufferedImageToArray(BufferedImage image) {
int h = image.getHeight();
int w = image.getWidth();
int[][] array = new int[h][w];
double[][] result;
for (int count = 0; count < h; count++) {
for (int loop = 0; loop < w; loop++) {
int gray = image.getRGB(loop, count) & 0xFF;
// add values to array
array[count][loop] = gray;
}
}
result = toDoubleArray(array);
return result;
}
I've implemented the transform as
public double[][] applyDCT(double[][] image) {
DoubleDCT_2D transform = new DoubleDCT_2D(image.length, image[0].length);
transform.forward(image, true);
return image;
}
I tried using OpenCV's dct transform but it gives the same output as shown in the link.
Ty something like that (I kept only the blue channel for simplicity). It shows the energy compaction in the upper left corner of the result image.
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestDCT
{
public static void main(String[] args)
{
ImageIcon icon = new ImageIcon(args[0]);
Image image = icon.getImage();
int w = image.getWidth(null);
int h = image.getHeight(null);
GraphicsDevice gs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0];
GraphicsConfiguration gc = gs.getDefaultConfiguration();
BufferedImage img = gc.createCompatibleImage(w, h, Transparency.OPAQUE);
img.getGraphics().drawImage(image, 0, 0, null);
int[] rgb1 = new int[w*h];
img.getRaster().getDataElements(0, 0, w, h, rgb1);
double[] array = new double[w*h];
for (int i=0; i<w*h; i++)
array[i] = (double) (rgb1[i] & 0xFF);
org.jtransforms.dct.DoubleDCT_2D tr = new org.jtransforms.dct.DoubleDCT_2D(w, h);
tr.forward(array, true);
for (int i=0; i<w*h; i++)
{
// Grey levels
int val= Math.min((int) (array[i]+128), 255);
rgb1[i] = (val <<16) | (val << 8) | val;
}
img.getRaster().setDataElements(0, 0, w, h, rgb1);
icon = new ImageIcon(img);
JFrame frame = new JFrame("FFT");
frame.setBounds(20, 30, w, h);
frame.add(new JLabel(icon));
frame.setVisible(true);
}
}

Can't use fisheye lens effect on my image in Java

I want to use fisheye lens algorithm in Java, but I can't implement a main method.
At the bottom of this site, I found java code, that implements fisheye algorithm, but there wasn't any main() method. I've tried to implement a main() method by my own, but so far I just can display image, but I can't use the barrel() method on that image which should make fisheye effect on my image.
Could you please correct my main method, or implement a new one, that loads some image(bufferedImage) and then use barrel() method on that image?
My code so far is:
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DisplayImage {
float xscale;
float yscale;
float xshift;
float yshift;
int [] s;
public BufferedImage barrel (BufferedImage input, float k){
float centerX=input.getWidth()/2; //center of distortion
float centerY=input.getHeight()/2;
int width = input.getWidth(); //image bounds
int height = input.getHeight();
BufferedImage dst = new BufferedImage(width, height,BufferedImage.TYPE_INT_ARGB); //output pic
xshift = calc_shift(0,centerX-1,centerX,k);
float newcenterX = width-centerX;
float xshift_2 = calc_shift(0,newcenterX-1,newcenterX,k);
yshift = calc_shift(0,centerY-1,centerY,k);
float newcenterY = height-centerY;
float yshift_2 = calc_shift(0,newcenterY-1,newcenterY,k);
xscale = (width-xshift-xshift_2)/width;
yscale = (height-yshift-yshift_2)/height;
for(int j=0;j<dst.getHeight();j++){
for(int i=0;i<dst.getWidth();i++){
float x = getRadialX((float)i,(float)j,centerX,centerY,k);
float y = getRadialY((float)i,(float)j,centerX,centerY,k);
sampleImage(input,x,y);
int color = ((s[1]&0x0ff)<<16)|((s[2]&0x0ff)<<8)|(s[3]&0x0ff);
// System.out.print(i+" "+j+" \\");
dst.setRGB(i, j, color);
}
}
return dst;
}
void sampleImage(BufferedImage arr, float idx0, float idx1)
{
s = new int [4];
if(idx0<0 || idx1<0 || idx0>(arr.getHeight()-1) || idx1>(arr.getWidth()-1)){
s[0]=0;
s[1]=0;
s[2]=0;
s[3]=0;
return;
}
float idx0_fl=(float) Math.floor(idx0);
float idx0_cl=(float) Math.ceil(idx0);
float idx1_fl=(float) Math.floor(idx1);
float idx1_cl=(float) Math.ceil(idx1);
int [] s1 = getARGB(arr,(int)idx0_fl,(int)idx1_fl);
int [] s2 = getARGB(arr,(int)idx0_fl,(int)idx1_cl);
int [] s3 = getARGB(arr,(int)idx0_cl,(int)idx1_cl);
int [] s4 = getARGB(arr,(int)idx0_cl,(int)idx1_fl);
float x = idx0 - idx0_fl;
float y = idx1 - idx1_fl;
s[0]= (int) (s1[0]*(1-x)*(1-y) + s2[0]*(1-x)*y + s3[0]*x*y + s4[0]*x*(1-y));
s[1]= (int) (s1[1]*(1-x)*(1-y) + s2[1]*(1-x)*y + s3[1]*x*y + s4[1]*x*(1-y));
s[2]= (int) (s1[2]*(1-x)*(1-y) + s2[2]*(1-x)*y + s3[2]*x*y + s4[2]*x*(1-y));
s[3]= (int) (s1[3]*(1-x)*(1-y) + s2[3]*(1-x)*y + s3[3]*x*y + s4[3]*x*(1-y));
}
int [] getARGB(BufferedImage buf,int x, int y){
int rgb = buf.getRGB(x, y); // Returns by default ARGB.
int [] scalar = new int[4];
scalar[0] = (rgb >>> 24) & 0xFF;
scalar[1] = (rgb >>> 16) & 0xFF;
scalar[2] = (rgb >>> 8) & 0xFF;
scalar[3] = (rgb >>> 0) & 0xFF;
return scalar;
}
float getRadialX(float x,float y,float cx,float cy,float k){
x = (x*xscale+xshift);
y = (y*yscale+yshift);
float res = x+((x-cx)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy)));
return res;
}
float getRadialY(float x,float y,float cx,float cy,float k){
x = (x*xscale+xshift);
y = (y*yscale+yshift);
float res = y+((y-cy)*k*((x-cx)*(x-cx)+(y-cy)*(y-cy)));
return res;
}
float thresh = 1;
float calc_shift(float x1,float x2,float cx,float k){
float x3 = (float)(x1+(x2-x1)*0.5);
float res1 = x1+((x1-cx)*k*((x1-cx)*(x1-cx)));
float res3 = x3+((x3-cx)*k*((x3-cx)*(x3-cx)));
if(res1>-thresh && res1 < thresh)
return x1;
if(res3<0){
return calc_shift(x3,x2,cx,k);
}
else{
return calc_shift(x1,x3,cx,k);
}
}
public static void main(String avg[]) throws IOException
{
BufferedImage img=ImageIO.read(new File("image.jpg"));
ImageIcon icon=new ImageIcon(img);
JFrame frame=new JFrame();
frame.setLayout(new FlowLayout());
frame.setSize(625,648);
JLabel lbl=new JLabel();
lbl.setIcon(icon);
frame.add(lbl);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Code is working, but it only display image. I want to use barrel() method on my image, which will do the fisheye effect. Because I am newbie to java, I can't do that, please help.
Refer to this site:
http://popscan.blogspot.in/2012/04/fisheye-lens-equation-simple-fisheye.html
It contains the concept as well as working source at the end of the article.
make your function static
public static BufferedImage barrel (BufferedImage input, float k)
and change
public static void main(String avg[]) throws IOException
{
BufferedImage img=ImageIO.read(new File("image.jpg"));
//now pass this image to your barrel method and return in new image
//note that, method can be called now without instatntiating any object, as it is static now
BufferImage barrelImage = barrel(img,2.0);
ImageIcon icon=new ImageIcon(barrelImage);
...
...
}
So I finally implemented desired fisheye! Just because of this and this site. I am giving here really messy but working code for anyone with similar problem:
package fisheye;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class DitherMain {
static String imageString = "image.bmp";
BufferedImage startImage, endImage;
int[] startPixels, endPixels, imR, imG, imB;
int width, height;
public static void main(String[] args){
new DitherMain(loadImage(imageString));
}
//this object transforms the old image and writes the new image
DitherMain(BufferedImage img){
//filing the image into startpixels
startImage = img;
width = img.getWidth();
height = img.getHeight();
startPixels = new int[width*height];
img.getRGB(0, 0, width, height, startPixels, 0, width);
endPixels = fisheye(startPixels, width, height);
transformPixels();
WritableRaster wRaster = endImage.getData().createCompatibleWritableRaster();
wRaster.setSamples(0, 0, width, height, 0, imR);
wRaster.setSamples(0, 0, width, height, 1, imG);
wRaster.setSamples(0, 0, width, height, 2, imB);
endImage.setData(wRaster);
System.out.println(endImage);
//writing the file for endImage into the harddrive
writeFile();
}
void transformPixels(){
//endPixels = startPixels;
endImage = startImage;
imR = new int[endPixels.length];
imG = new int[endPixels.length];
imB = new int[endPixels.length];
for(int i = 0; i < endPixels.length; i++){
imR[i] = (endPixels[i] >> 16) & 0x000000FF;
imG[i] = (endPixels[i] >> 8) & 0x000000FF;
imB[i] = endPixels[i] & 0x000000FF;
}
}
void writeFile(){
try {
ImageIO.write(endImage,"BMP",new File("RESULT.bmp"));
} catch (IOException e) {
e.printStackTrace();
}
}
//this method just loads a specific buffered image
public static BufferedImage loadImage(String fileName){
BufferedImage img;
try{
img=ImageIO.read(new File("image.bmp"));
//img = ImageIO.read(DitherMain.class.getResource(fileName));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
return img;
}
public static int[] fisheye(int[] srcpixels, double w, double h) {
/*
* Fish eye effect
* tejopa, 2012-04-29
* http://popscan.blogspot.com
* http://www.eemeli.de
*/
// create the result data
int[] dstpixels = new int[(int)(w*h)];
// for each row
for (int y=0;y<h;y++) {
// normalize y coordinate to -1 ... 1
double ny = ((2*y)/h)-1;
// pre calculate ny*ny
double ny2 = ny*ny;
// for each column
for (int x=0;x<w;x++) {
// normalize x coordinate to -1 ... 1
double nx = ((2*x)/w)-1;
// pre calculate nx*nx
double nx2 = nx*nx;
// calculate distance from center (0,0)
// this will include circle or ellipse shape portion
// of the image, depending on image dimensions
// you can experiment with images with different dimensions
double r = Math.sqrt(nx2+ny2);
// discard pixels outside from circle!
if (0.0<=r&&r<=1.0) {
double nr = Math.sqrt(1.0-r*r);
// new distance is between 0 ... 1
nr = (r + (1.0-nr)) / 2.0;
// discard radius greater than 1.0
if (nr<=1.0) {
// calculate the angle for polar coordinates
double theta = Math.atan2(ny,nx);
// calculate new x position with new distance in same angle
double nxn = nr*Math.cos(theta);
// calculate new y position with new distance in same angle
double nyn = nr*Math.sin(theta);
// map from -1 ... 1 to image coordinates
int x2 = (int)(((nxn+1)*w)/2.0);
// map from -1 ... 1 to image coordinates
int y2 = (int)(((nyn+1)*h)/2.0);
// find (x2,y2) position from source pixels
int srcpos = (int)(y2*w+x2);
// make sure that position stays within arrays
if (srcpos>=0 & srcpos < w*h) {
// get new pixel (x2,y2) and put it to target array at (x,y)
dstpixels[(int)(y*w+x)] = srcpixels[srcpos];
}
}
}
}
}
//return result pixels
return dstpixels;
}
}

Categories