diff --git a/src/zutil/image/ImageFilterProcessor.java b/src/zutil/image/ImageFilterProcessor.java index 20472f7..89d1e1e 100644 --- a/src/zutil/image/ImageFilterProcessor.java +++ b/src/zutil/image/ImageFilterProcessor.java @@ -22,12 +22,19 @@ public abstract class ImageFilterProcessor { /** * Sets the listener - * @param listener The listener, null to disable the progress + * @param listener is the listener, null to disable the progress */ public void setProgressListener(ProgressListener listener){ this.progress = listener; } + /** + * Returns the listener + */ + public ProgressListener getProgressListener(){ + return this.progress; + } + /** * Sets the progress in percent */ @@ -65,23 +72,23 @@ public abstract class ImageFilterProcessor { // converts the img to raw data int[][][] data = convertToArray(img, cols, rows); //processes the image - process(data); + data = process(data); //converts back the image return convertToImage(data, data[0].length, data.length); } /** - * Creates a Integer array whit the pixel data of the image + * Creates a Integer array with the pixel data of the image * int[row][col][4] * 0 -> Alpha data * Red data * Green data * 4 -> Blue data * - * @param img The image to convert - * @param cols Columns of the image - * @param rows Rows of the image - * @return A Integer array + * @param img is the image to convert + * @param cols is the columns of the image + * @param rows is the rows of the image + * @return A is the integer array * @throws InterruptedException */ public static int[][][] convertToArray(BufferedImage img, int cols, int rows) throws InterruptedException{ @@ -101,13 +108,13 @@ public abstract class ImageFilterProcessor { // Reading in the color data for(int x=0; x> 24) & 0xFF; + data[y][x][0] = ((aRow[x] >> 24) & 0xFF); //Red data - data[y][x][1] = (aRow[x] >> 16) & 0xFF; + data[y][x][1] = ((aRow[x] >> 16) & 0xFF); //Green data - data[y][x][2] = (aRow[x] >> 8) & 0xFF; + data[y][x][2] = ((aRow[x] >> 8) & 0xFF); //Blue data - data[y][x][3] = (aRow[x])& 0xFF; + data[y][x][3] = ((aRow[x])& 0xFF); } } return data; @@ -117,9 +124,9 @@ public abstract class ImageFilterProcessor { /** * Converts a pixel data array to a java Image object * - * @param pixels The pixel data array - * @param cols Columns of the image - * @param rows Rows of the image + * @param pixels is the pixel data array + * @param cols is the columns of the image + * @param rows is the rows of the image * @return A Image */ public static BufferedImage convertToImage(int[][][] pixels, int cols, int rows){ @@ -148,20 +155,22 @@ public abstract class ImageFilterProcessor { } /** - * Runs the image thrue the processor - * @param data The raw image to apply the effect to + * Runs the image thru the processor + * @param data is the raw image to apply the effect to. This will NOT be altered */ - public void process(final int[][][] data){ - process(data, 0, 0, data[0].length, data.length); + public int[][][] process(int[][][] data){ + return process(data, 0, 0, data[0].length, data.length); } /** * The underlying effect is run here - * @param data The raw image to apply the effect to + * + * @param data is the raw image to apply the effect to. This will NOT be altered * @param startX is the x pixel of the image to start from * @param startY is the y pixel of the image to start from * @param stopX is the x pixel of the image to stop * @param stopY is the y pixel of the image to stop + * @return either the modified data parameter or an new array */ - public abstract void process(final int[][][] data, int startX, int startY, int stopX, int stopY); + public abstract int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY); } diff --git a/src/zutil/image/ImageUtil.java b/src/zutil/image/ImageUtil.java index b5df54c..3c13e2f 100644 --- a/src/zutil/image/ImageUtil.java +++ b/src/zutil/image/ImageUtil.java @@ -17,8 +17,8 @@ public class ImageUtil { * @param stopY is the y pixel of the image to stop * @return The peak value of the image */ - public static int peakValue(int[][][] data) { - return peakValue(data, 0, 0, data[0].length, data.length); + public static int getPeakValue(int[][][] data) { + return getPeakValue(data, 0, 0, data[0].length, data.length); } /** @@ -31,7 +31,7 @@ public class ImageUtil { * @param stopY is the y pixel of the image to stop * @return The peak value of the image */ - public static int peakValue(int[][][] data, int startX, int startY, int stopX, int stopY) { + public static int getPeakValue(int[][][] data, int startX, int startY, int stopX, int stopY) { int peak = 0; for(int y=startY; y 100) redScale = 100; + if(redScale > 1) redScale = 1; else if(redScale < 0) redScale = 0; - if(greenScale > 100) greenScale = 100; + if(greenScale > 1) greenScale = 1; else if(greenScale < 0) greenScale = 0; - if(blueScale > 100) blueScale = 100; + if(blueScale > 1) blueScale = 1; else if(blueScale < 0) blueScale = 0; // Applying the color intensity to the image @@ -69,19 +70,20 @@ public class ColorIntensityFilter extends ImageFilterProcessor{ for(int x=startX; x 0) - data[y+1][x-1][i] = ImageUtil.clip( data[y+1][x-1][i] + (error*3)/16 ); - data[y+1][x+0][i] = ImageUtil.clip( data[y+1][x+0][i] + (error*5)/16 ); + output[y+1][x-1][i] = ImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 ); + output[y+1][x+0][i] = ImageUtil.clip( output[y+1][x+0][i] + (error*5)/16 ); if (x + 1 < data[0].length) - data[y+1][x+1][i] = ImageUtil.clip( data[y+1][x+1][i] + (error*1)/16 ); + output[y+1][x+1][i] = ImageUtil.clip( output[y+1][x+1][i] + (error*1)/16 ); } } } } + + return output; } private static int findNearestColor(int[] color, int[][] palette) { diff --git a/src/zutil/image/filters/FaceDetectionFilter.java b/src/zutil/image/filters/FaceDetectionFilter.java deleted file mode 100644 index f1c76d6..0000000 --- a/src/zutil/image/filters/FaceDetectionFilter.java +++ /dev/null @@ -1,180 +0,0 @@ -package zutil.image.filters; - -import java.awt.Rectangle; -import java.awt.image.BufferedImage; - -import zutil.image.ImageFilterProcessor; -import zutil.image.ImageUtil; -import zutil.math.ZMath; - -public class FaceDetectionFilter extends ImageFilterProcessor{ - - public FaceDetectionFilter(BufferedImage img) { - super(img); - } - - @Override - public void process(int[][][] data, int startX, int startY, int stopX, int stopY) { - int[][][] IRgBy = convertARGBToIRgBy(data, startX, startY, stopX, stopY); - - MedianFilter median = new MedianFilter(null, 4*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,false,true,true}); - median.process(IRgBy); - setProgress(ZMath.percent(0, 4, 1)); - - //********* Texture Map ******** - median = new MedianFilter(null, 8*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,true,false,false}); - int[][][] textureMap = ImageUtil.copyArray(IRgBy); - median.process(IRgBy); - - for(int y=startY; y= 120 && hue <= 160) && (saturation >= 10 && saturation <= 60)) || - (textureMap[y][x][1] < 4.5 && (hue >= 150 && hue <= 180) && (saturation >= 20 && saturation <= 80)) ){ - skinMap[y][x] = 1; - } - } - } - setProgress(ZMath.percent(0, 4, 3)); - - //************** SkinMap dilation ******************** - skinMap = dilation(skinMap , startX, startY, stopX, stopY); - - - //***************************************************** - setProgress(100); - //return convertArrayToARGBchannel(hueMap, startX, startY, stopX, stopY, -150, 150, 1); - //return convertArrayToARGBchannel(saturationMap, startX, startY, stopX, stopY, 0, 70, 1); - ImageUtil.copyArray( - convertArrayToARGBchannel(skinMap, startX, startY, stopX, stopY, 0, 1, 2), - data, startX, startY, stopX, stopY); - } - - private int[][] dilation(int[][] data, int startX, int startY, int stopX, int stopY){ - int[][] output = new int[data.length][data[0].length]; - int radX = 8; - int radY = 8; - - for(int y=startY; y= 0 && dy < data.length && dx >= 0 && dx < data[0].length) - output[dy][dx] = 1; - } - } - - } - } - } - - return output; - } - - - /** - * Converts the given data array to a color image - * - * @param data The 2d data - * @param startX is the x pixel of the image to start from - * @param startY is the y pixel of the image to start from - * @param stopX is the x pixel of the image to stop - * @param stopY is the y pixel of the image to stop - * @param min The minimum value in the data - * @param max The maximum value in the data - * @param channel The color channel to apply the data to - * @return A ARGB array - */ - public int[][][] convertArrayToARGBchannel(int[][] data, int startX, int startY, int stopX, int stopY,int min, int max, int channel){ - int[][][] output = new int[data.length][data[0].length][4]; - - for(int y=startY; y= 0 && y+fy-edgeY < data.length && x+fx-edgeX >= 0 && x+fx-edgeX < data[0].length){ //colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey] - if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++; + if(channels[0]) tmpArray[0][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][0] ) ]++; if(channels[1]) tmpArray[1][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][1] ) ]++; if(channels[2]) tmpArray[2][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][2] ) ]++; if(channels[3]) tmpArray[3][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][3] ) ]++; @@ -87,23 +87,21 @@ public class MedianFilter extends ImageFilterProcessor{ } } - if(channels[0]) data[y][x][0] = findMedian(tmpArray[0], pixelCount/2); - else data[y][x][0] = tmpData[y][x][0]; - if(channels[1]) data[y][x][1] = findMedian(tmpArray[1], pixelCount/2); - else data[y][x][1] = tmpData[y][x][1]; - if(channels[2]) data[y][x][2] = findMedian(tmpArray[2], pixelCount/2); - else data[y][x][2] = tmpData[y][x][2]; - if(channels[3]) data[y][x][3] = findMedian(tmpArray[3], pixelCount/2); - else data[y][x][3] = tmpData[y][x][3]; + if(channels[0]) tmpData[y][x][0] = findMedian(tmpArray[0], pixelCount/2); + if(channels[1]) tmpData[y][x][1] = findMedian(tmpArray[1], pixelCount/2); + if(channels[2]) tmpData[y][x][2] = findMedian(tmpArray[2], pixelCount/2); + if(channels[3]) tmpData[y][x][3] = findMedian(tmpArray[3], pixelCount/2); } } + + return tmpData; } - + private int getMedianIndex(int i){ if(i < 0) return Math.abs(i); else return i+256; } - + private int findMedian(int[] median, int medianCount){ int sum = 0; int ret = 0; @@ -114,11 +112,11 @@ public class MedianFilter extends ImageFilterProcessor{ ret = i-256; } } - + return ret; } - - + + class SortableARGB implements SortableDataList{ private int[][][] data; private int cols; @@ -153,12 +151,12 @@ public class MedianFilter extends ImageFilterProcessor{ data[ getY(a) ][ getX(a) ][ channel ] = data[ getY(b) ][ getX(b) ][ channel ]; data[ getY(b) ][ getX(b) ][ channel ] = tmp; } - - + + private int getX(int a){ return a % cols; } - + private int getY(int a){ return a / cols; } diff --git a/src/zutil/image/filters/ResizeImage.java b/src/zutil/image/filters/ResizeImage.java index c81e9be..5836bff 100644 --- a/src/zutil/image/filters/ResizeImage.java +++ b/src/zutil/image/filters/ResizeImage.java @@ -3,7 +3,6 @@ package zutil.image.filters; import java.awt.image.BufferedImage; import zutil.image.ImageFilterProcessor; -import zutil.image.ImageUtil; import zutil.math.ZMath; public class ResizeImage extends ImageFilterProcessor{ @@ -37,7 +36,7 @@ public class ResizeImage extends ImageFilterProcessor{ } @Override - public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) { + public int[][][] process(final int[][][] data, int startX, int startY, int stopX, int stopY) { if(width < 1){ height = (int)(((double)width/(stopX-startX))*(stopY-startY)); } @@ -59,14 +58,6 @@ public class ResizeImage extends ImageFilterProcessor{ } } - ImageUtil.copyArray(newData, data, 0, 0, width, height); - } - - /** - * Returns the resulting image after processing - * @return an image or null if not processed - */ - public int[][][] getResult(){ return newData; } } diff --git a/src/zutil/image/filters/SobelEdgeDetectionFilter.java b/src/zutil/image/filters/SobelEdgeDetectionFilter.java new file mode 100644 index 0000000..3fca408 --- /dev/null +++ b/src/zutil/image/filters/SobelEdgeDetectionFilter.java @@ -0,0 +1,64 @@ +package zutil.image.filters; + +import java.awt.image.BufferedImage; + +import zutil.image.ImageFilterProcessor; +import zutil.math.ZMath; + +/** + * Generates an image that contains the edges of the source image + * + * @author Ziver + * INFO: http://en.wikipedia.org/wiki/Sobel_operator + */ +public class SobelEdgeDetectionFilter extends ImageFilterProcessor{ + private static final double[][] xG_kernel = new double[][]{ + {+1, 0, -1}, + {+2, 0, -2}, + {+1, 0, -1} + }; + private static final double[][] yG_kernel = new double[][]{ + {+1, +2, +1}, + { 0, 0, 0}, + {-1, -2, -1} + }; + + + public SobelEdgeDetectionFilter(BufferedImage img) { + super(img); + } + + @Override + public int[][][] process(int[][][] data, int startX, int startY, int stopX, int stopY) { + ConvolutionFilter conv = new ConvolutionFilter(xG_kernel); + int[][][] xG = conv.process(data, startX, startY, stopX, stopY); + setProgress(33); + + conv = new ConvolutionFilter(yG_kernel); + int[][][] yG = conv.process(data, startX, startY, stopX, stopY); + setProgress(66); + + int[][][] output = new int[data.length][data[0].length][4]; + for(int y=startY; y implements Set, Serializable } /** - * @param o The Serializable object to search for - * @return If the object contains in the filter or false - * if the Object is not Serializable + * @param o is the Serializable object to search for + * @return If the object contains in the filter or + * false if the Object is not Serializable */ public boolean contains(Object o) { try { @@ -131,7 +131,7 @@ public class BloomFilter implements Set, Serializable } /** - * @return The false posetive probability of the current state of the filter + * @return The false positive probability of the current state of the filter */ public double falsePosetiveProbability(){ return Math.pow(0.6185, bits.size()/content_size); diff --git a/src/zutil/test/ImageProcessorTest.java b/src/zutil/test/ImageProcessorTest.java index 2284c0c..7fd7ce0 100644 --- a/src/zutil/test/ImageProcessorTest.java +++ b/src/zutil/test/ImageProcessorTest.java @@ -20,18 +20,21 @@ import javax.swing.JLabel; import zutil.ProgressListener; import zutil.image.ImageFilterProcessor; +import zutil.image.filters.GaussianBlurFilter; import zutil.image.filters.BlurFilter; import zutil.image.filters.ColorIntensityFilter; import zutil.image.filters.ContrastBrightnessFilter; import zutil.image.filters.DitheringFilter; -import zutil.image.filters.FaceDetectionFilter; +import zutil.image.filters.MeanBlurFilter; import zutil.image.filters.MedianFilter; import zutil.image.filters.ResizeImage; +import zutil.image.filters.SobelEdgeDetectionFilter; import zutil.image.filters.SpotLightFilter; @SuppressWarnings("unused") public class ImageProcessorTest implements ProgressListener{ - private static String imgPath = "exemple.gif"; + private static String imgPath = "test.gif"; + //private static String imgPath = "test2.jpg"; private JLabel processedLabel; private JLabel orginalLabel; @@ -61,14 +64,16 @@ public class ImageProcessorTest implements ProgressListener{ BufferedImage procImg = null; try { - //ImageFilterProcessor processor = new BlurFilter(img, 10); + //ImageFilterProcessor processor = new SobelEdgeDetectionFilter(img); + ImageFilterProcessor processor = new GaussianBlurFilter(img); + //ImageFilterProcessor processor = new BlurFilter(img, 100); //ImageFilterProcessor processor = new ColorIntensityFilter(img, true); //ImageFilterProcessor processor = new ContrastBrightnessFilter(img); - ImageFilterProcessor processor = new DitheringFilter(img); + //ImageFilterProcessor processor = new DitheringFilter(img); + //ImageFilterProcessor processor = new MeanBlurFilter(img); //ImageFilterProcessor processor = new MedianFilter(img); //ImageFilterProcessor processor = new ResizeImage(img,100,100); - //ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); - //ImageFilterProcessor processor = new FaceDetectionFilter(img); + //ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); processor.setProgressListener(this); procImg = processor.process(); diff --git a/exemple.gif b/test.gif similarity index 100% rename from exemple.gif rename to test.gif diff --git a/test2.jpg b/test2.jpg new file mode 100644 index 0000000..2ef349d Binary files /dev/null and b/test2.jpg differ