I have this code, in which I extracted the value of RGB for each pixel, but I'm wondering how to store each RGB value in an array so that I can use it further in my project. I want to take these stored RGB values as an input for backpropagation algorithm.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
public class PrintImageARGBPixels
{
public static void main(String args[])throws IOException
{
BufferedImage image = ImageIO.read(new File("C:\\Users\\ark\\Desktop\\project_doc\\logo_1004.jpg"));
int r=0,g=0,b=0;
int w = image.getWidth();
int h = image.getHeight();
System.out.println("Image Dimension: Height-" + h + ", Width-"+ w);
int total_pixels=(h * w);
ArrayList <Color> arr = new ArrayList<Color>();
for(int x=0;x<w;x++)
{
for(int y=0;y<h;y++)
{
int rgb = image.getRGB(x, y);
Color c = new Color(rgb);
r=c.getRed();
g=c.getGreen();
b=c.getBlue();
}
}
Color co = new Color(r,g,b);
arr.add(co);
for(int i=0;i<total_pixels;i++)
System.out.println("Element 1"+i+1+", color: Red " + arr.get(i).getRed() + " Green +arr.get(i).getGreen()+ " Blue " + arr.get(i).getBlue());
}
}
// Store the color objects in an array
int total_pixels = (h * w);
Color[] colors = new Color[total_pixels];
int i = 0;
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
colors[i] = new Color(image.getRGB(x, y));
i++;
}
}
// Later you can retrieve them
for (int i = 0; i < total_pixels; i++)
{
Color c = colors[i];
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
System.out.println("Red" + r + "Green" + g + "Blue" + b);
}
IGNORE THE BELOW, it is my old answer
Use a multidimensional array:
[
[255, 255, 255],
[108, 106, 107],
[100, 100, 55],
...
]
You can then refer to each pixel, [0][x] to get the colour values.
Why don't you just create a RGB Object like this
public class RGB {
private int R, G, B;
public RGB(int R, int G, int B){
this.R = R;
this.G = G;
this.B = B;
}
public int getR() {
return R;
}
public void setR(int r) {
R = r;
}
public int getG() {
return G;
}
public void setG(int g) {
G = g;
}
public int getB() {
return B;
}
public void setB(int b) {
B = b;
}
}
So you can store RGB Objects in your array to use them later.
Greetings!
It can be achieved easier with HashMap, where Key is an int[] (x and y) and value is the another int[] (r, g, b).
Related
I am trying to use the Graphics2D library to add noise to a given image. For example, this: . The issue currently is that the output file is blank. Here is my code:
BufferedImage image = ImageIO.read(new File("src/digit.png"));
BufferedImage output = new BufferedImage(28, 28, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics2D = output.createGraphics();
Random random = new Random();
for (int i = 0; i < output.getHeight(); i++) {
for (int j = 0; j < output.getWidth(); j++) {
Color color = new Color(image.getRGB(j, i));
int choice = random.nextInt(2);
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int rand = random.nextInt(10);
if (choice == 0) {
r += rand;
g += rand;
b += rand;
} else {
r -= rand;
g -= rand;
b -= rand;
}
if (r < 0) {
r = 0;
}
if (g < 0) {
g = 0;
}
if (b < 0) {
b = 0;
}
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
graphics2D.setColor(new Color(r, g, b));
graphics2D.fillRect(j, i, 1, 1);
}
}
File outFile = new File("output.png");
ImageIO.write(output, "png", outFile);
What is the prevailing issue with it?
First of all, I would like to thank #user16320675 for helping debug issues with the code and giving suggestions to make it more efficient. The problem, in the end, was that the image had transparent pixels which by default (when used to create color) was black. I instead wrote a utility function based on this post to identify transparent pixels and make them white.
The resulting image now is:
Code:
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
public class NoiseImage {
public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File("src/digit.png"));
BufferedImage output = new BufferedImage(28, 28, BufferedImage.TYPE_INT_ARGB);
Random random = new Random();
for (int i = 0; i < output.getHeight(); i++) {
for (int j = 0; j < output.getWidth(); j++) {
Color color = new Color(image.getRGB(j, i), true);
if (isTransparent(image.getRGB(j, i))) {
color = new Color(255, 255, 255);
}
int choice = random.nextInt(2);
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int a = color.getAlpha();
int rand = random.nextInt(20);
if (choice == 0) {
r += rand;
g += rand;
b += rand;
a += rand;
} else {
r -= rand;
g -= rand;
b -= rand;
a -= rand;
}
r = isOutOfBounds(r);
g = isOutOfBounds(g);
b = isOutOfBounds(b);
a = isOutOfBounds(a);
output.setRGB(j, i, new Color(r, g, b, a).getRGB());
}
}
File outFile = new File("output.png");
ImageIO.write(output, "png", outFile);
}
private static int isOutOfBounds(int val) {
if (val > 255) {
return 255;
}
return Math.max(val, 0);
}
private static boolean isTransparent(int val) {
return val >> 24 == 0x00;
}
}
I'm looking for some help in applying 2D Gabor Wavelets Formula to an image in java.
This is the formula that I'm using.
Gabor Formula
I need my output to look like this
I've read the image in and its currently stored in a 2D array. My code is as follows:` public void RunGabor() throws IOException
{
double[][]pixels=getImage();
int H= pixels.length;
int W =pixels[0].length;
size=H*W;
gaussian=size/2;
System.out.println(gaussian);
GaborGrid = new int[H][W];
GaborNorm = new int[H][W];
double X=0,Y=0, gx=-gaussian,gy=-gaussian, count=0, total=0;
int ax=0, dy=0;
for(int x=0; x<pixels.length; x++)
{
for(int k=0;k< pixels[0].length; k++)
{
X=gx*Math.cos(theta)+gy*Math.sin(theta);
Y=-gx*Math.sin(theta)+gy*Math.cos(theta);
pixels[dy][ax]=((Math.exp(-(Math.pow(X, 2)+(Math.pow(Y, 2)*
Math.pow(upsi,2)))/(2*Math.pow(sigma, 2))))*
(Math.cos((kappa*X+varphi))));
System.out.println("Pixels" +pixels[dy][ax]);
total+=pixels[dy][ax];
count++;
System.out.println("Count" +count);
gx+=1;
ax++;
}
System.out.println("second loop");
ax=0;
dy++;
gy+=1;
gx=-gaussian;
}
mean=total/count;
System.out.println("Mean" +mean);
NormaliseImage(pixels);
}`
From there it calls a method normaliseImage
public void NormaliseImage(double[][] pixels)
{
double minII = pixels[0][0];
double maxII = pixels[0][0];
for(int y=0; y<pixels.length; y++){
for(int x= 0; x<pixels[0].length; x++){
if(pixels[y][x] <= minII){
minII =pixels[y][x];
}
if(pixels[y][x]>= maxII){
maxII=pixels[y][x];
}
}
My create image class looks like this
public CreateImage(int[][] data, String IMGname)
{
name = IMGname;
width = data[0].length;
height = data.length;
System.out.println("NEW IMAGE 1");
pixels = new int[height*width];
int count=0;
for(int i=0; i<data.length; i++)
{
for(int j=0; j<data[0].length; j++)
{
pixels[count] = (int)Math.abs(data[i][j]);
pixels[count] = convert2pixel(pixels[count]);
count++;
}
}
Create(width, height, pixels, name);
}
public int convert2pixel(int pixel)
{
return ((0xff<<24)|(pixel<<16)|(pixel<<8)|pixel);
}
public int convert2grey(double pixel)
{
int red=((int)pixel>>16) & 0xff;
int green = ((int)pixel>>8) & 0xff;
int blue = (int)pixel & 0xff;
return (int)(0.3*red+0.6*green+0.1*blue);
}
public void Create(int Width, int Height, int pixels[], String n)//throws Exception
{
//System.out.println("Inside Create Image");
MemoryImageSource MemImg = new MemoryImageSource(Width,Height,pixels,0,Width);
Image img2= Toolkit.getDefaultToolkit().createImage(MemImg);
BufferedImage bfi = new BufferedImage(Height,Width, BufferedImage.TYPE_INT_BGR);
Graphics2D g2D = bfi.createGraphics();
g2D.drawImage(img2, 0, 0, Width, Height, null);
try
{
ImageIO.write(bfi, "png", new File(n+".png"));
}
catch(Exception e){}
}
}
My output is just a grey screen, any help would be appreciated.
Update: Gabor Driver Class `
public class Gabor_Driver{
public static void main(String[]args)throws IOException
{
double lamda=75;
double theta=45;
double varphi=90;
double upsi=10;
double bandW=10;
//int size=500;
Gabor gabor = new Gabor(lamda, theta, varphi, upsi, bandW );
}
}
`
Gabor class :
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
public class Gabor
{
CreateImage ci;
private double lamda=0;
private double theta=0;
private double varphi=0;
private double upsi=0;
private double bandW=0;
private double B=0;
private double sigma=0;
private double kappa=0;
private int[][] GaborGrid;
private int[][] GaborNorm;
int size=0;
double toRadians=180/Math.PI, min=500, max=-500, mean=0;;
int gaussian=0;
double rotation;
double GLFmean=0;
//Standard Gabor no quantization
public Gabor(double l, double t, double v, double u, double b) throws IOException
{
lamda=l;
theta=t/toRadians;
varphi=v/toRadians;
upsi=u;
bandW=b;
kappa=(2*Math.PI)/lamda;
Calculate_Sigma();
RunGabor();
}
public void RunGabor() throws IOException
{
double[][]pixels=getImage();
int H= pixels.length;
int W =pixels[0].length;
size=H*W;
gaussian=size/2;
System.out.println(gaussian);
GaborGrid = new int[H][W];
GaborNorm = new int[H][W];
double X=0,Y=0, gx=-gaussian,gy=-gaussian, count=0, total=0;
int ax=0, dy=0;
for(int x=0; x<pixels.length; x++)
{
for(int k=0;k< pixels[0].length; k++)
{
X=gx*Math.cos(theta)+gy*Math.sin(theta);
Y=-gx*Math.sin(theta)+gy*Math.cos(theta);
pixels[dy][ax]=((Math.exp(-(Math.pow(X, 2)+(Math.pow(Y, 2)*
Math.pow(upsi,2)))/(2*Math.pow(sigma, 2))))*
(Math.cos((kappa*X+varphi))));
System.out.println("Pixels" +pixels[dy][ax]);
total+=pixels[dy][ax];
count++;
System.out.println("Count" +count);
gx+=1;
ax++;
}
System.out.println("second loop");
ax=0;
dy++;
gy+=1;
gx=-gaussian;
}
mean=total/count;
System.out.println("Mean" +mean);
NormaliseImage(pixels);
}
public double[][] getImage() throws IOException{
int[][]pixels =null;
double[][] doubles = null;
JFileChooser fc = new JFileChooser();
int returnValue = fc.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fc.getSelectedFile();
BufferedImage image = ImageIO.read(selectedFile);
System.out.println(selectedFile.getName());
int W =image.getWidth();
int H= image.getHeight();
int width = image.getWidth();
int height = image.getHeight();
pixels = new int[height][width];
for (int row = 0; row < height; row++) {
image.getRGB(0, row, width, 1, pixels[row], 0, width);
}
doubles = new double[pixels.length][pixels[0].length];
for(int i=0; i<pixels.length; i++) {
for(int j=0; j<pixels[0].length; j++)
doubles[i][j] = pixels[+i][+j];
}
}
return doubles;
}
public void NormaliseImage(double[][] pixels)
{
double minII = pixels[0][0];
double maxII = pixels[0][0];
for(int y=0; y<pixels.length; y++){
for(int x= 0; x<pixels[0].length; x++){
if(pixels[y][x] <= minII){
minII =pixels[y][x];
}
if(pixels[y][x]>= maxII){
maxII=pixels[y][x];
}
}
}
int count=0;
double total=0;
for(int y=0; y<pixels.length; y++){
for(int x= 0; x<pixels[0].length; x++){
total += pixels[y][x];
count++;
}
}
double average =(double)total/count;
for(int y=0; y<pixels.length; y++){
for(int x= 0; x<pixels[0].length; x++){
double normalise= ((((pixels[y][x]-min))/((max-min)))*255);
if(normalise<=average){
normalise =0;
}
GaborNorm[y][x] = (int) normalise;
}
}
ci = new CreateImage(GaborNorm, "Gabor");
}
private void Calculate_Sigma()
{
B=(1/Math.PI)*(0.588705011)*((Math.pow(2, bandW)+1)/(Math.pow(2, bandW)-1));
sigma=B*lamda;
}
}
Create image class:
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
public class CreateImage
{
int[] pixels;
int width=0, height=0;
String name;
public CreateImage(int[][] data, String IMGname)
{
name = IMGname;
width = data[0].length;
height = data.length;
System.out.println("NEW IMAGE 1");
pixels = new int[height*width];
int count=0;
for(int i=0; i<data.length; i++)
{
for(int j=0; j<data[0].length; j++)
{
pixels[count] = (int)Math.abs(data[i][j]);
pixels[count] = convert2pixel(pixels[count]);
count++;
}
}
Create(width, height, pixels, name);
}
public int convert2pixel(int pixel)
{
return ((0xff<<24)|(pixel<<16)|(pixel<<8)|pixel);
}
public int convert2grey(double pixel)
{
int red=((int)pixel>>16) & 0xff;
int green = ((int)pixel>>8) & 0xff;
int blue = (int)pixel & 0xff;
return (int)(0.3*red+0.6*green+0.1*blue);
}
public void Create(int Width, int Height, int pixels[], String n)//throws Exception
{
//System.out.println("Inside Create Image");
MemoryImageSource MemImg = new MemoryImageSource(Width,Height,pixels,0,Width);
Image img2= Toolkit.getDefaultToolkit().createImage(MemImg);
BufferedImage bfi = new BufferedImage(Height,Width, BufferedImage.TYPE_INT_BGR);
Graphics2D g2D = bfi.createGraphics();
g2D.drawImage(img2, 0, 0, Width, Height, null);
try
{
ImageIO.write(bfi, "png", new File(n+".png"));
}
catch(Exception e){}
}
}
Your calculations are mostly correct. You are calculating the function itself in RunGabor - I think gx, gy should be replaced with x, k. This
for(int x=0; x<pixels.length; x++)
{
for(int k=0;k< pixels[0].length; k++)
{
X=gx*Math.cos(theta)+gy*Math.sin(theta);
Y=-gx*Math.sin(theta)+gy*Math.cos(theta);
pixels[dy][ax]=((Math.exp(-(Math.pow(X, 2)+(Math.pow(Y, 2)*
Math.pow(upsi,2)))/(2*Math.pow(sigma, 2))))*
(Math.cos((kappa*X+varphi))));
should be replaced with
public Kernel getKernel() {
double sigma = calculateSigma(waveLength, bandwidth);
float[] data = new float[width*height];
for(int k = 0, x = -width/2; x <= width/2; x++) {
for(int y = -height/2; y <= height/2; y++) {
for(double orientation : orientations) {
double x1 = x*Math.cos(orientation) + y*Math.sin(orientation);
double y1 = -x*Math.sin(orientation) + y*Math.cos(orientation);
data[k] += (float)(gaborFunction(x1, y1, sigma, aspectRatio, waveLength, phaseOffset));
}
k++;
}
}
But you have to apply the function on the pixels that you are reading, the image. If you look at this other implementation https://github.com/clumsy/gabor-filter/blob/master/src/main/java/GaborFilter.java
you will find many parallels. See if you can fix it.
At least as a first step you should try to print the values of the gabor function either 3x3 or 5x5. If they look reasonable you can go ahead to apply it to the image.
I'm loading a BufferedImage and getting RGB values for the pixels based on their xy location.
After I would like to create an ArrayList containing only the black pixels.
I'm trying to create the list doing this:
List<Integer> blackpixels = new ArrayList<Integer>();
but I get this error at the line where I declare the list:
The type List is not generic; it cannot be parameterized with arguments
Here's my full code:
import java.awt.Color;
import java.awt.List;
import java.awt.image.BufferedImage;
import java.util.*;
public class ImageTest {
public static BufferedImage Threshold(BufferedImage img) {
int height = img.getHeight();
int width = img.getWidth();
BufferedImage finalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
int r = 0;
int g = 0;
int b = 0;
List<Integer> blackpixels = new ArrayList<Integer>();
for (int x = 0; x < width; x++) {
// System.out.println("Row: " + x);
try {
for (int y = 0; y < height; y++) {
//Get RGB values of pixels
int rgb = img.getRGB(x, y);
r = ImageTest.getRed(rgb);
g = ImageTest.getGreen(rgb);
b = ImageTest.getBlue(rgb);
finalImage.setRGB(x,y,ImageTest.mixColor(r, g,b));
System.out.println(r);
}
}
catch (Exception e) {
e.getMessage();
}
}
return finalImage;
}
private static int mixColor(int red, int g, int b) {
return red<<16|g<<8|b;
}
public static int getRed(int rgb) {
return (rgb & 0x00ff0000) >> 16;
}
public static int getGreen(int rgb) {
return (rgb & 0x0000ff00) >> 8;
}
public static int getBlue(int rgb) {
return (rgb & 0x000000ff) >> 0;
}
}
The error you are getting, is that the List you are trying to create comes from java.awt.List instead of java.util.List. If you are not going to use the java.awt.List, just remove the
import java.awt.List;
You are already importing the correct class with import java.util.*;, so after removing the mentioned sentence it should work properly.
I want to read an image and convert and output the original image, a greyscale version, and a sepia version. I am having trouble with the conversion, not very familiar with BufferedImage, and especially having problems with getRGB and setRGB method. I have this so far
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
public class ChangeColor{
static BufferedImage readImage( String Pic ) throws Exception {
BufferedImage image = ImageIO.read( new File("Pic.jpg") );
return( image );
}
public static void saveImage( BufferedImage img, File file ) throws IOException {
ImageWriter writer = null;
java.util.Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
if( iter.hasNext() ){
writer = (ImageWriter)iter.next();
}
ImageOutputStream ios = ImageIO.createImageOutputStream( file );
writer.setOutput(ios);
ImageWriteParam param = new JPEGImageWriteParam( java.util.Locale.getDefault() );
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
param.setCompressionQuality(0.98f);
writer.write(null, new IIOImage( img, null, null ), param);
}
public static BufferedImage color2gray( BufferedImage inImage ) {
int width = inImage.getWidth();
int height = inImage.getHeight();
BufferedImage outImage = new BufferedImage( width, height, BufferedImage.TYPE_3BYTE_BGR );
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
Color c = new Color(image.getRGB(j, i));
int red = (int)(c.getRed() * 0.2126);
int green = (int)(c.getGreen() * 0.7152);
int blue = (int)(c.getBlue() *0.0722);
Color newColor = new Color(red+green+blue,
red+green+blue,red+green+blue);
image.setRGB(j,i,newColor.getRGB());
}
}
return( outImage );
}
public static BufferedImage color2sepia( BufferedImage inImage ) {
int width = inImage.getWidth();
int height = inImage.getHeight();
BufferedImage outImage = new BufferedImage( width, height, BufferedImage.TYPE_3BYTE_BGR );
for(int i=0; i<height; i++){
for(int j=0; j<width; j++){
Color c = new Color(image.getRGB(j, i));
int red = (int)(c.getRed());
int green = (int)(c.getGreen());
int blue = (int)(c.getBlue());
Color newColor = new Color(red* .393)+(green*.769)+(blue* .189),
(red* .349)+(green*.686)+(blue* .168),(red* .272)+(green*.534)+(blue* .131);
image.setRGB(j,i,newColor.getRGB());
}
}
return( outImage );
}
public static void main(String[] args) throws Exception {
BufferedImage colorImage, grayImage, sepiaImage;
if (args.length != 1)
System.out.println( "" );
else
{
colorImage = readImage ( args[0] );
grayImage = color2gray ( colorImage );
sepiaImage = color2sepia( colorImage );
saveImage( grayImage, new File( "greyPic.jpg" + args[0] ) );
saveImage( sepiaImage, new File( "sepiaPic.jpg"+ args[0] ) );
}
}
}
This is an image of what the output should look like:
Thank you.
Gray scaling is rather easy, sepia not so much. I stole the algorithm off the net...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ColorAlteration {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
try {
BufferedImage master = ImageIO.read(new File("C:\\hold\\thumbnails\\_cg_836___Tilting_Windmills___by_Serena_Clearwater.png"));
BufferedImage gray = toGrayScale(master);
BufferedImage sepia = toSepia(master, 80);
JPanel panel = new JPanel(new GridBagLayout());
panel.add(new JLabel(new ImageIcon(master)));
panel.add(new JLabel(new ImageIcon(gray)));
panel.add(new JLabel(new ImageIcon(sepia)));
JOptionPane.showMessageDialog(null, panel);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public static BufferedImage toGrayScale(BufferedImage master) {
BufferedImage gray = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Automatic converstion....
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(master, gray);
return gray;
}
public static BufferedImage toSepia(BufferedImage img, int sepiaIntensity) {
BufferedImage sepia = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
// Play around with this. 20 works well and was recommended
// by another developer. 0 produces black/white image
int sepiaDepth = 20;
int w = img.getWidth();
int h = img.getHeight();
WritableRaster raster = sepia.getRaster();
// We need 3 integers (for R,G,B color values) per pixel.
int[] pixels = new int[w * h * 3];
img.getRaster().getPixels(0, 0, w, h, pixels);
// Process 3 ints at a time for each pixel. Each pixel has 3 RGB
// colors in array
for (int i = 0; i < pixels.length; i += 3) {
int r = pixels[i];
int g = pixels[i + 1];
int b = pixels[i + 2];
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
// Darken blue color to increase sepia effect
b -= sepiaIntensity;
// normalize if out of bounds
if (b < 0) {
b = 0;
}
if (b > 255) {
b = 255;
}
pixels[i] = r;
pixels[i + 1] = g;
pixels[i + 2] = b;
}
raster.setPixels(0, 0, w, h, pixels);
return sepia;
}
}
You can find the original posting for the sepia algorithm here
And because I'm stubborn...I changed the sepia algorithm to work with alpha based images...
public static BufferedImage toSepia(BufferedImage img, int sepiaIntensity) {
BufferedImage sepia = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
// Play around with this. 20 works well and was recommended
// by another developer. 0 produces black/white image
int sepiaDepth = 20;
int w = img.getWidth();
int h = img.getHeight();
WritableRaster raster = sepia.getRaster();
// We need 3 integers (for R,G,B color values) per pixel.
int[] pixels = new int[w * h * 3];
img.getRaster().getPixels(0, 0, w, h, pixels);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int rgb = img.getRGB(x, y);
Color color = new Color(rgb, true);
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
// Darken blue color to increase sepia effect
b -= sepiaIntensity;
// normalize if out of bounds
if (b < 0) {
b = 0;
}
if (b > 255) {
b = 255;
}
color = new Color(r, g, b, color.getAlpha());
sepia.setRGB(x, y, color.getRGB());
}
}
return sepia;
}
I used ##MadProgrammer code to write this code. Which I think it is much more efficient.
Using raster data of the image instead of accessing each byte of image. Although it seems it copys the data into pixels array, it is not used in the program.
You are calling getRGB each time + getWidth() + getHeight() + getRed(), getGreen() + getBlue().
Writing colors directly into your image, I think it is a bottleneck once you write a color using setRGB, you will lose graphic processor benefits. (I read it somewhere, but can't find the link now.)
Converting the color back to Color object and getting it back using getRGB().
All I did was using bit-wise operators which it is very fast and then copied the pixel arrays once I was done working with it. Function call is expensive and I avoided them.
However, thanks for the idea, #MadProgrammer.
public static BufferedImage toSepia(BufferedImage image, int sepiaIntensity) {
int width = image.getWidth();
int height = image.getHeight();
int sepiaDepth = 20;
int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);
for (int i = 0; i < imagePixels.length; i++) {
int color = imagePixels[i];
int r = (color >> 16) & 0xff;
int g = (color >> 8) & 0xff;
int b = (color) & 0xff;
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
// Darken blue color to increase sepia effect
b -= sepiaIntensity;
// normalize if out of bounds
if (b < 0) {
b = 0;
}
if (b > 255) {
b = 255;
}
imagePixels[i] = (color & 0xff000000) + (r << 16) + (g << 8) + b;
}
BufferedImage res = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
res.setRGB(0, 0, width, height, imagePixels, 0, width);
return res;
}
You can create a filter interface for code reuse.
FilterApp
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class FilterApp {
public static ClassLoader loader = FilterApp.class.getClassLoader();
public static String outputDir = "build";
public static void main(String[] args) {
try {
BufferedImage srcImage = loadImage("lobster.jpg");
File dir = new File(outputDir);
if (!dir.exists()) {
dir.mkdirs();
}
for (FilterType filter : FilterType.values()) {
BufferedImage filteredImage = filter.applyFilter(srcImage);
String filename = String.format("%s/lobster_%s", outputDir, filter.name().toLowerCase());
writeImage(filteredImage, filename, "jpg");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static BufferedImage loadImage(String filename) throws IOException {
return ImageIO.read(loader.getResourceAsStream("resources/" + filename));
}
private static void writeImage(BufferedImage image, String filename, String ext) throws IOException {
ImageIO.write(image, ext, new File(filename + '.' + ext));
}
}
FilterType
import java.awt.image.BufferedImage;
import filter.GreyscaleFilter;
import filter.ImageFilter;
import filter.InvertFilter;
import filter.SepiaFilter;
public enum FilterType {
GREYSCALE(new GreyscaleFilter()),
INVERT(new InvertFilter()),
SEPIA_10(new SepiaFilter(10));
private ImageFilter filter;
public ImageFilter getFilter() { return filter; }
public BufferedImage applyFilter(BufferedImage img) {
return this.filter.apply(img);
}
private FilterType(ImageFilter filter) {
this.filter = filter;
}
}
ImageFilter
package filter;
import java.awt.image.BufferedImage;
/** Common Interface for different filters. */
public interface ImageFilter {
public BufferedImage apply(BufferedImage img);
}
GreyscaleFilter
package filter;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
public class GreyscaleFilter implements ImageFilter {
#Override
public BufferedImage apply(BufferedImage img) {
BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(img, result);
return result;
}
}
InvertFilter
package filter;
import java.awt.Color;
import java.awt.image.BufferedImage;
public class InvertFilter implements ImageFilter {
#Override
public BufferedImage apply(BufferedImage img) {
BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int rgb = img.getRGB(x, y);
Color color = new Color(rgb, true);
int r = 255 - color.getRed();
int g = 255 - color.getGreen();
int b = 255 - color.getBlue();
color = new Color(r, g, b, color.getAlpha());
result.setRGB(x, y, color.getRGB());
}
}
return result;
}
}
SepiaFilter
package filter;
import java.awt.Color;
import java.awt.image.BufferedImage;
// Algorithm obtained from http://stackoverflow.com/questions/21899824
public class SepiaFilter implements ImageFilter {
private int intensity;
public void setIntensity(int intensity) { this.intensity = intensity; }
public int getIntensity() { return intensity; }
public SepiaFilter(int intensity) {
this.intensity = intensity;
}
#Override
public BufferedImage apply(BufferedImage img) {
BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
// Play around with this.
// 20 works well and was recommended by another developer.
// 0 produces black/white image
int sepiaDepth = 20;
int w = img.getWidth();
int h = img.getHeight();
// We need 3 integers (for R,G,B color values) per pixel.
int[] pixels = new int[w * h * 3];
img.getRaster().getPixels(0, 0, w, h, pixels);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
int rgb = img.getRGB(x, y);
Color color = new Color(rgb, true);
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int gry = (r + g + b) / 3;
r = g = b = gry;
r = r + (sepiaDepth * 2);
g = g + sepiaDepth;
if (r > 255) { r = 255; }
if (g > 255) { g = 255; }
if (b > 255) { b = 255; }
// Darken blue color to increase sepia effect
b -= this.intensity;
// normalize if out of bounds
if (b < 0) { b = 0; }
if (b > 255) { b = 255; }
color = new Color(r, g, b, color.getAlpha());
result.setRGB(x, y, color.getRGB());
}
}
return result;
}
}
Output
Source Image
Generated Images
i have:
BufferedImage image;
//few lines of code
public void stateChanged(ChangeEvent e)
{
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++)
{
Color color = new Color(image.getRGB(i, j));
int r, g, b;
val = sliderBrightness.getValue();
r = color.getRed() + val;
g = color.getGreen() + val;
b = color.getBlue() + val;
}
}
I haven't got any idea how to solve this problem, what should i modify that Image will react on JSlider brightness?
As shown here, use java.awt.image.RescaleOp to adjust the image's color bands as a function of the slider's position. Despite the name, AlphaTest, the example uses the constructor that applies "to all color (but not alpha) components in a BufferedImage."
public void stateChanged(ChangeEvent e)
{
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++)
{
Color color = new Color(image.getRGB(x, y));
int r, g, b;
val = sliderBrightness.getValue();
r = checkColorRange(color.getRed() + val);
g = checkColorRange(color.getGreen() + val);
b = checkColorRange(color.getBlue() + val);
color = new Color(r, g, b);
image.setRGB(x, y, color.getRGB());
border.setIcon(new ImageIcon(image.getScaledInstance(350, 350, Image.SCALE_SMOOTH)));
border.repaint();
}
}
}
public int checkColorRange(int newColor){
if(newColor > 255){
newColor = 255;
} else if (newColor < 0) {
newColor = 0;
}
return newColor;
}
Also you should use x and y, instead of i and j, for clarity.