Zooming an Image by bilinear Interpolation method in java [duplicate] - java

I am trying to read an image, zoom it in to 80*60 and then zoom out the resulted image 5 times by bilinear Interpolation method. But I get this error : Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4800 . Can anyone help me please?
this is what I have done :
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class BiInterpolationTest {
public static int zh;
public static int zw;
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
int[][] savedImage;
File f = new File ("F:\\Java\\Gray Scale Images\\3.jpg");
savedImage = readimage(f);
BufferedImage grayImage = new BufferedImage(savedImage.length, savedImage[0].length, BufferedImage.TYPE_BYTE_GRAY);
for (int i =0 ; i<savedImage.length ; i ++){
for (int j=0 ; j<savedImage[0].length ; j++){
int rgb = savedImage[i][j];
rgb = (rgb<<16)|(rgb<<8)|(rgb);
grayImage.setRGB(i, j, rgb);
BufferedImage zoomin =ScaledImage(grayImage, 80,60);
zh = zoomin.getHeight();
zw = zoomin.getWidth();
byte[] tempArr;
tempArr = extractBytes(zoomin);
// TODO Auto-generated catch block
byte [] zoomout;
zoomout = bilineraInterpolation(tempArr , 5);
InputStream in = new ByteArrayInputStream(zoomout);
BufferedImage bImageInterpolated;
try {
bImageInterpolated = ImageIO.read(in);
ImageIO.write(bImageInterpolated, "jpg", new File(
"F:/new-darksouls.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static BufferedImage ScaledImage(Image img, int w , int h){
BufferedImage resizedImage = new BufferedImage(w , h , BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2 = resizedImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(img, 0, 0, w, h, null);
g2.dispose();
return resizedImage;
}
/////////////////////////////////////
public static byte[] extractBytes (BufferedImage Image) throws IOException {
BufferedImage bufferedImage = new BufferedImage(Image.getHeight(), Image.getWidth(), BufferedImage.TYPE_BYTE_GRAY);
// get DataBufferBytes from Raster
WritableRaster raster = bufferedImage .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return ( data.getData() );
}
public static int[][] readimage(File filename){
BufferedImage img;
try {
img = ImageIO.read(filename);
// Gray_scaled Image output
int width = img.getWidth();
int height = img.getHeight();
ImagePro.fw=width;
ImagePro.fh = height;
int [][] readimageVal = new int [width][height];
for (int i = 0; i<height ; i++){
for (int j =0 ; j<width ; j++){
Color c = new Color(img.getRGB(j, i));
int r= (int)(c.getRed() * 0.299)&0xff;
int g = (int)(c.getGreen() * 0.587)&0xff;
int b = (int)(c.getBlue() *0.114)&0xff;
int avg = ((r+b+g));
readimageVal[j][i] = avg;
}
}
return readimageVal;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] bilineraInterpolation(byte[] ImgData, int ratio) {
int wf = zw*ratio;
int hf = zh*ratio;
byte[] tempArr = new byte[wf*hf] ;
int A, B, C, D, x, y, index, g ;
float x_ratio = ((float)(zw))/wf ;
float y_ratio = ((float)(zh))/hf ;
float x_diff, y_diff ;
int in = 0 ;
for (int i=0;i<hf;i++) {
for (int j=0;j<wf;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*zw+x ;
// range is 0 to 255 thus bitwise AND with 0xff
A = ImgData[index] & 0xff ;
B = ImgData[index+1] & 0xff ;
C = ImgData[index+zw] & 0xff ;
D = ImgData[index+zw+1] & 0xff ;
g = (int)(
A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff)
) ;
tempArr[in++] = (byte) g ;
}
}
return tempArr ;
}
}

Related

How to zoom out an image by Bilinear Interpolation in java?

I am trying to read an image, zoom it in to 80*60 and then zoom out the resulted image 5 times by bilinear Interpolation method. But I get this error : Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4800 . Can anyone help me please?
this is what I have done :
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
public class BiInterpolationTest {
public static int zh;
public static int zw;
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
int[][] savedImage;
File f = new File ("F:\\Java\\Gray Scale Images\\3.jpg");
savedImage = readimage(f);
BufferedImage grayImage = new BufferedImage(savedImage.length, savedImage[0].length, BufferedImage.TYPE_BYTE_GRAY);
for (int i =0 ; i<savedImage.length ; i ++){
for (int j=0 ; j<savedImage[0].length ; j++){
int rgb = savedImage[i][j];
rgb = (rgb<<16)|(rgb<<8)|(rgb);
grayImage.setRGB(i, j, rgb);
BufferedImage zoomin =ScaledImage(grayImage, 80,60);
zh = zoomin.getHeight();
zw = zoomin.getWidth();
byte[] tempArr;
tempArr = extractBytes(zoomin);
// TODO Auto-generated catch block
byte [] zoomout;
zoomout = bilineraInterpolation(tempArr , 5);
InputStream in = new ByteArrayInputStream(zoomout);
BufferedImage bImageInterpolated;
try {
bImageInterpolated = ImageIO.read(in);
ImageIO.write(bImageInterpolated, "jpg", new File(
"F:/new-darksouls.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static BufferedImage ScaledImage(Image img, int w , int h){
BufferedImage resizedImage = new BufferedImage(w , h , BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2 = resizedImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(img, 0, 0, w, h, null);
g2.dispose();
return resizedImage;
}
/////////////////////////////////////
public static byte[] extractBytes (BufferedImage Image) throws IOException {
BufferedImage bufferedImage = new BufferedImage(Image.getHeight(), Image.getWidth(), BufferedImage.TYPE_BYTE_GRAY);
// get DataBufferBytes from Raster
WritableRaster raster = bufferedImage .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return ( data.getData() );
}
public static int[][] readimage(File filename){
BufferedImage img;
try {
img = ImageIO.read(filename);
// Gray_scaled Image output
int width = img.getWidth();
int height = img.getHeight();
ImagePro.fw=width;
ImagePro.fh = height;
int [][] readimageVal = new int [width][height];
for (int i = 0; i<height ; i++){
for (int j =0 ; j<width ; j++){
Color c = new Color(img.getRGB(j, i));
int r= (int)(c.getRed() * 0.299)&0xff;
int g = (int)(c.getGreen() * 0.587)&0xff;
int b = (int)(c.getBlue() *0.114)&0xff;
int avg = ((r+b+g));
readimageVal[j][i] = avg;
}
}
return readimageVal;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static byte[] bilineraInterpolation(byte[] ImgData, int ratio) {
int wf = zw*ratio;
int hf = zh*ratio;
byte[] tempArr = new byte[wf*hf] ;
int A, B, C, D, x, y, index, g ;
float x_ratio = ((float)(zw))/wf ;
float y_ratio = ((float)(zh))/hf ;
float x_diff, y_diff ;
int in = 0 ;
for (int i=0;i<hf;i++) {
for (int j=0;j<wf;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*zw+x ;
// range is 0 to 255 thus bitwise AND with 0xff
A = ImgData[index] & 0xff ;
B = ImgData[index+1] & 0xff ;
C = ImgData[index+zw] & 0xff ;
D = ImgData[index+zw+1] & 0xff ;
g = (int)(
A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff)
) ;
tempArr[in++] = (byte) g ;
}
}
return tempArr ;
}
}

gray image log transformation in java

I am trying to get a log transformation from a gray image. But with whatever c value I will get a black image. Any idea?
that is my method:
///---------------------------------------------------
public static BufferedImage log_trans (int[][] imageData , int c){
BufferedImage LogImage = new BufferedImage(imageData.length, imageData[0].length, BufferedImage.TYPE_BYTE_GRAY);
double temp;
for (int i =0 ; i<imageData.length ; i ++){
for (int j=0 ; j<imageData[0].length ; j++){
int rgb = imageData[i][j];
rgb = (rgb<<16)|(rgb<<8)|(rgb);
temp = Math.log10(rgb+1);
rgb = (int) (c * temp);
LogImage.setRGB(i, j, rgb);
}}
return LogImage;
}
--------------------------------------------------------------
public static int[][] readimage(File filename){
BufferedImage img;
try {
img = ImageIO.read(filename);
// Gray_scaled Image output
int width = img.getWidth();
int height = img.getHeight();
ImagePro.fw=width;
ImagePro.fh = height;
int [][] readimageVal = new int [width][height];
for (int i = 0; i<height ; i++){
for (int j =0 ; j<width ; j++){
Color c = new Color(img.getRGB(j, i));
int r= (int)(c.getRed() * 0.299)&0xff;
int g = (int)(c.getGreen() * 0.587)&0xff;
int b = (int)(c.getBlue() *0.114)&0xff;
int avg = ((r+b+g));
readimageVal[j][i] = avg;
}
}
return readimageVal;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
It seems that "rgb" is always negative, so temp is always Nan, so in the end "rgb" after:
rgb = (int) (c * temp);
is always 0 and this is why you always get black picture.
After changing your 8th line to:
rgb = (((byte)rgb & 0xFF)<<16)|(((byte)rgb & 0xFF)<<8)|(((byte)rgb & 0xFF));
I get some very dark output, but it's not very nice. I tested for value of "c" being 1, 18000, 180000 and 0x00FFFFFF.

Make a jpg a Shape [duplicate]

I was wondering whether there is any way to convert an image/graphic into a Shape? For example, can I convert the outline of a motorcycle shape into a Shape so I can then use it in Java? I know you can do it with normal squares or with rounded corners, polygons, etc. But is there a way to do a custom shape?
motorcycle.jpg
motorcycle-03.png
ImageOutline.java
This code requires some patience (when running).
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Area;
import javax.imageio.ImageIO;
import java.io.File;
import java.util.Date;
import javax.swing.*;
/* Motorcycle image courtesy of ShutterStock
http://www.shutterstock.com/pic-13585165/stock-vector-travel-motorcycle-silhouette.html */
class ImageOutline {
public static Area getOutline(BufferedImage image, Color color, boolean include, int tolerance) {
Area area = new Area();
for (int x=0; x<image.getWidth(); x++) {
for (int y=0; y<image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x,y));
if (include) {
if (isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x,y,1,1);
area.add(new Area(r));
}
} else {
if (!isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x,y,1,1);
area.add(new Area(r));
}
}
}
}
return area;
}
public static boolean isIncluded(Color target, Color pixel, int tolerance) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return(
(rP-tolerance<=rT) && (rT<=rP+tolerance) &&
(gP-tolerance<=gT) && (gT<=gP+tolerance) &&
(bP-tolerance<=bT) && (bT<=bP+tolerance) );
}
public static BufferedImage drawOutline(int w, int h, Area area) {
final BufferedImage result = new BufferedImage(
w,
h,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = result.createGraphics();
g.setColor(Color.white);
g.fillRect(0,0,w,h);
g.setClip(area);
g.setColor(Color.red);
g.fillRect(0,0,w,h);
g.setClip(null);
g.setStroke(new BasicStroke(1));
g.setColor(Color.blue);
g.draw(area);
return result;
}
public static BufferedImage createAndWrite(
BufferedImage image,
Color color,
boolean include,
int tolerance,
String name)
throws Exception {
int w = image.getWidth();
int h = image.getHeight();
System.out.println("Get Area: " + new Date() + " - " + name);
Area area = getOutline(image, color, include, tolerance);
System.out.println("Got Area: " + new Date() + " - " + name);
final BufferedImage result = drawOutline(w,h,area);
displayAndWriteImage(result, name);
return result;
}
public static void displayAndWriteImage(BufferedImage image, String fileName) throws Exception {
ImageIO.write(image, "png", new File(fileName));
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(image)));
}
public static void main(String[] args) throws Exception {
final BufferedImage outline = ImageIO.read(new File("motorcycle.jpg"));
BufferedImage crop = outline.getSubimage(17,35,420,270);
displayAndWriteImage(crop, "motorcycle-01.png");
BufferedImage crude = createAndWrite(crop, Color.white, false, 60, "motorcycle-02.png");
BufferedImage combo = createAndWrite(crude, Color.red, true, 0, "motorcycle-03.png");
}
}
function getArea_FastHack is build upon Andrew Thompsons work, which was very helpful.
Mine should be faster, however:
(//Edit: and sloppier, too)
import java.awt.*;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
/**
* CustomShape
* based on a Class from Andrew Thompson *
* Source: http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape-in-java/7059497#7059497
* #author Samuel Schneider, Andrew Thompson
*
*
*/
class CustomShape {
private BufferedImage image=null;
/**
* Creates an Area with PixelPerfect precision
* #param color The color that is draws the Custom Shape
* #param tolerance The color tolerance
* #return Area
*/
public Area getArea(Color color, int tolerance) {
if(image==null) return null;
Area area = new Area();
for (int x=0; x<image.getWidth(); x++) {
for (int y=0; y<image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x,y));
if (isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x,y,1,1);
area.add(new Area(r));
}
}
}
return area;
}
public Area getArea_FastHack() {
//Assumes Black as Shape Color
if(image==null) return null;
Area area = new Area();
Rectangle r;
int y1,y2;
for (int x=0; x<image.getWidth(); x++) {
y1=99;
y2=-1;
for (int y=0; y<image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x,y));
//-16777216 entspricht RGB(0,0,0)
if (pixel.getRGB()==-16777216) {
if(y1==99) {y1=y;y2=y;}
if(y>(y2+1)) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
y1=y;y2=y;
}
y2=y;
}
}
if((y2-y1)>=0) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
}
}
return area;
}
public static boolean isIncluded(Color target, Color pixel, int tolerance) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return(
(rP-tolerance<=rT) && (rT<=rP+tolerance) &&
(gP-tolerance<=gT) && (gT<=gP+tolerance) &&
(bP-tolerance<=bT) && (bT<=bP+tolerance) );
}
public CustomShape(String path) {
try {
BufferedImage image = ImageIO.read(new File(path));
this.image = image;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here's something faster but less accurate, useful for collision checking or 2D physics.
Point[] MakePoly(BufferedImage spr,int d,int angle){
//creates an outline of a transparent image, points are stored in an array
//arg0 - BufferedImage source image
//arg1 - Int detail (lower = better)
//arg2 - Int angle threshold in degrees (will remove points with angle differences below this level; 15 is a good value)
// making this larger will make the body faster but less accurate;
int w= spr.getWidth(null); int h= spr.getHeight(null);
// increase array size from 255 if needed
int[] vertex_x=new int[255], vertex_y=new int[255], vertex_k=new int[255];
int numPoints=0, tx=0,ty=0,fy=-1,lx=0,ly=0; vertex_x[0]=0; vertex_y[0]=0; vertex_k[0]=1;
for (tx=0;tx<w;tx+=d) for (ty=0;ty<h;ty+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 )
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; if (fy<0) fy=ty; lx=tx; ly=ty; break; }
for (ty=0;ty<h;ty+=d) for (tx=w-1;tx>=0;tx-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty > ly)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; lx=tx; ly=ty; break; }
for (tx=w-1;tx>=0;tx-=d) for (ty=h-1;ty>=0;ty-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && tx < lx)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
for (ty=h-1;ty>=0;ty-=d) for (tx=0;tx<w;tx+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty < ly && ty > fy)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
double ang1,ang2; for (int i=0;i<numPoints-2;i++) {
ang1 = PointDirection(vertex_x[i],vertex_y[i], vertex_x[i+1],vertex_y[i+1]);
ang2 = PointDirection(vertex_x[i+1],vertex_y[i+1], vertex_x[i+2],vertex_y[i+2]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[i+1] = 0; }
ang1 = PointDirection(vertex_x[numPoints-2],vertex_y[numPoints-2], vertex_x[numPoints-1],vertex_y[numPoints-1]);
ang2 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[numPoints-1] = 0;
ang1 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
ang2 = PointDirection(vertex_x[0],vertex_y[0], vertex_x[1],vertex_y[1]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[0] = 0;
int n=0;for (int i=0;i<numPoints;i++)if(vertex_k[i]==1)n++;
Point[] poly= new Point[n]; n=0; for (int i=0;i<numPoints;i++) if (vertex_k[i]==1)
{ poly[n]=new Point(); poly[n].x=vertex_x[i]; poly[n].y=h-vertex_y[i];n++;} return poly;
}
double PointDirection(double xfrom,double yfrom,double xto,double yto){
return Math.atan2(yto-yfrom,xto-xfrom)*180/Math.PI ;
}

stop repaint() when no more changes in jFrame and exit the program

I have a jFrame which contains an image (i.e. pixels of an image), which keeps on updating according to the algorithm using repaint().
Now I want to stop repaint() when a point comes, at which there are no more changes occuring in the pixels.Also I want to save the final output as an image (.jpg).
Any ideas or solution?
Enter the image path in ImageWindow constructor twice in alternate lines. Same file path.
package smart_blur;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
public final class ImageWindow
{
// This inner class is our canvas.
// We draw the image on it.
class ImagePanel extends JComponent
{
BufferedImage theImage = null;
ImagePanel( BufferedImage image )
{
super();
theImage = image;
}
public BufferedImage getImage( )
{
return theImage;
}
public void setImage( BufferedImage image )
{
theImage = image;
this.updatePanel();
}
public void updatePanel()
{
invalidate();
getParent().doLayout();
repaint();
}
#Override
public void paintComponent( Graphics g )
{
int w = theImage.getWidth( );
int h = theImage.getHeight( );
Boolean t= g.drawImage( theImage, 0,0, this.getWidth(),this.getHeight(), this );
}
} // end ImagePanel inner class
// Constructor
public ImageWindow( String [] args ) {
// open image
BufferedImage image = openImageFile( "DSC_0008.jpg" );
// create a panel for it
ImagePanel theImagePanel = new ImagePanel( image );
// display the panel in a JFrame
createWindowForPanel( theImagePanel, "DSC_0008.jpg" );
// filter the image
filterImage( theImagePanel );
}
public void filterImage( ImagePanel panel ) {
SmartBlurFilter filter = new SmartBlurFilter( );
BufferedImage newImage = filter.filter( panel.getImage( ) );
panel.setImage( newImage );
}
public void createWindowForPanel( ImagePanel theImagePanel, String name ) {
BufferedImage image = theImagePanel.getImage();
JFrame mainFrame = new JFrame();
mainFrame.setTitle( name );
mainFrame.setBounds(0,0,image.getWidth( )+10, image.getHeight( )+10);
mainFrame.setDefaultCloseOperation(3);
mainFrame.getContentPane().add( theImagePanel );
mainFrame.setVisible(true);
}
BufferedImage openImageFile( String fname ) {
BufferedImage img = null;
try {
File f = new File( fname );
if ( f.exists( ) )
img = ImageIO.read(f);
}
catch (Exception e) {
e.printStackTrace();
}
return img;
}
public static void main( String[] args )
{
ImageWindow imageWindow = new ImageWindow( args );
}
}
SmartBlurFilter.java
package smart_blur;
import java.awt.image.Kernel;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.Graphics;
public class SmartBlurFilter {
double SENSITIVITY = 10;
int REGION_SIZE = 5;
float [] kernelArray = {
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1
};
Kernel kernel = new Kernel( 9,9, normalizeKernel( kernelArray ) );
float [] normalizeKernel( float [] ar ) {
int n = 0;
for (int i = 0; i < ar.length; i++)
n += ar[i];
for (int i = 0; i < ar.length; i++)
ar[i] /= n;
return ar;
}
public double lerp( double a,double b, double amt) {
return a + amt * ( b - a );
}
public double getLerpAmount( double a, double cutoff ) {
if ( a > cutoff )
return 1.0;
return a / cutoff;
}
public double rmsError( int [] pixels ) {
double ave = 0;
for ( int i = 0; i < pixels.length; i++ )
ave += ( pixels[ i ] >> 8 ) & 255;
ave /= pixels.length;
double diff = 0;
double accumulator = 0;
for ( int i = 0; i < pixels.length; i++ ) {
diff = ( ( pixels[ i ] >> 8 ) & 255 ) - ave;
diff *= diff;
accumulator += diff;
}
double rms = accumulator / pixels.length;
rms = Math.sqrt( rms );
return rms;
}
int [] getSample( BufferedImage image, int x, int y, int size ) {
int [] pixels = {};
try {
BufferedImage subimage = image.getSubimage( x,y, size, size );
pixels = subimage.getRGB( 0,0,size,size,null,0,size );
}
catch( Exception e ) {
// will arrive here if we requested
// pixels outside the image bounds
}
return pixels;
}
int lerpPixel( int oldpixel, int newpixel, double amt ) {
int oldRed = ( oldpixel >> 16 ) & 255;
int newRed = ( newpixel >> 16 ) & 255;
int red = (int) lerp( (double)oldRed, (double)newRed, amt ) & 255;
int oldGreen = ( oldpixel >> 8 ) & 255;
int newGreen = ( newpixel >> 8 ) & 255;
int green = (int) lerp( (double)oldGreen, (double)newGreen, amt ) & 255;
int oldBlue = oldpixel & 255;
int newBlue = newpixel & 255;
int blue = (int) lerp( (double)oldBlue, (double)newBlue, amt ) & 255;
return ( red << 16 ) | ( green << 8 ) | blue;
}
int [] blurImage( BufferedImage image,
int [] orig, int [] blur, double sensitivity ) {
int newPixel = 0;
double amt = 0;
int size = REGION_SIZE;
for ( int i = 0; i < orig.length; i++ ) {
int w = image.getWidth();
int [] pix = getSample( image, i % w, i / w, size );
if ( pix.length == 0 )
continue;
amt = getLerpAmount ( rmsError( pix ), sensitivity );
newPixel = lerpPixel( blur[ i ], orig[ i ], amt );
orig[ i ] = newPixel;
}
return orig;
}
public BufferedImage filter( BufferedImage image ) {
ConvolveOp convolver = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP,
null);
// clone image into target
BufferedImage target = new BufferedImage(image.getWidth(), image
.getHeight(), image.getType());
Graphics g = target.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
int w = target.getWidth();
int h = target.getHeight();
// get source pixels
int [] pixels = image.getRGB(0, 0, w, h, null, 0, w);
// blur the cloned image
target = convolver.filter(target, image);
// target = convolver.;
// get the blurred pixels
int [] blurryPixels = target.getRGB(0, 0, w, h, null, 0, w);
// go thru the image and interpolate values
pixels = blurImage(image, pixels, blurryPixels, SENSITIVITY);
// replace original pixels with new ones
image.setRGB(0, 0, w, h, pixels, 0, w);
return image;
}
}
When you run the program, you will find smoothing of the image gradually. I want to the program to store the final output as an image (.jpg) when changes in the image stop.

Java Convert a greyscale and sepia version of an image with BufferedImage

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

Categories

Resources