Fixed some bugs and framework for the image filters

This commit is contained in:
Ziver Koc 2009-04-16 20:51:15 +00:00
parent 9f839fd803
commit 1bde5a6977
13 changed files with 342 additions and 266 deletions

View file

@ -65,7 +65,7 @@ public abstract class ImageFilterProcessor {
// converts the img to raw data // converts the img to raw data
int[][][] data = convertToArray(img, cols, rows); int[][][] data = convertToArray(img, cols, rows);
//processes the image //processes the image
data = process(data, cols, rows); process(data);
//converts back the image //converts back the image
return convertToImage(data, data[0].length, data.length); return convertToImage(data, data[0].length, data.length);
} }
@ -147,11 +147,21 @@ public abstract class ImageFilterProcessor {
return img; return img;
} }
/**
* Runs the image thrue the processor
* @param data The raw image to apply the effect to
*/
public void process(final int[][][] data){
process(data, 0, 0, data[0].length, data.length);
}
/** /**
* The underlying effect is run here * The underlying effect is run here
* @param data The raw image to apply the effect to * @param data The raw image to apply the effect to
* @param cols Columns of the image * @param startX is the x pixel of the image to start from
* @param rows Rows of the image * @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
*/ */
public abstract int[][][] process(final int[][][] data, int cols, int rows); public abstract void process(final int[][][] data, int startX, int startY, int stopX, int stopY);
} }

View file

@ -6,18 +6,35 @@ package zutil.image;
* *
*/ */
public class ImageUtil { public class ImageUtil {
/** /**
* Returns the peek value in the image * Returns the peek value in the image
* *
* @param data The image data * @param data The image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 The peak value of the image * @return The peak value of the image
*/ */
public static int peakValue(int[][][] data, int cols, int rows) { public static int peakValue(int[][][] data) {
return peakValue(data, 0, 0, data[0].length, data.length);
}
/**
* Returns the peek value in the image
*
* @param data The image 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
* @return The peak value of the image
*/
public static int peakValue(int[][][] data, int startX, int startY, int stopX, int stopY) {
int peak = 0; int peak = 0;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
if(data[y][x][1] > peak) peak = data[y][x][1]; if(data[y][x][1] > peak) peak = data[y][x][1];
if(data[y][x][2] > peak) peak = data[y][x][2]; if(data[y][x][2] > peak) peak = data[y][x][2];
if(data[y][x][3] > peak) peak = data[y][x][3]; if(data[y][x][3] > peak) peak = data[y][x][3];
@ -30,13 +47,15 @@ public class ImageUtil {
* Normalizes the image data by the given scale * Normalizes the image data by the given scale
* *
* @param data The image data * @param data The image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 scale The scale to normalize the image by * @param scale The scale to normalize the image by
*/ */
public static void normalize(int[][][] data, int cols, int rows, double scale) { public static void normalize(int[][][] data, int startX, int startY, int stopX, int stopY, double scale) {
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
data[y][x][1] = (int)(data[y][x][1] * scale); data[y][x][1] = (int)(data[y][x][1] * scale);
data[y][x][2] = (int)(data[y][x][2] * scale); data[y][x][2] = (int)(data[y][x][2] * scale);
data[y][x][3] = (int)(data[y][x][3] * scale); data[y][x][3] = (int)(data[y][x][3] * scale);
@ -49,13 +68,15 @@ public class ImageUtil {
* *
* @param output The output data array * @param output The output data array
* @param data The image data * @param data The image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 scale The scale to normalize the image by * @param scale The scale to normalize the image by
*/ */
public static void normalize(int[][][] output, int[][][] data, int cols, int rows, double scale) { public static void normalize(int[][][] output, int[][][] data, int startX, int startY, int stopX, int stopY, double scale) {
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
output[y][x][1] = (int)(data[y][x][1] * scale); output[y][x][1] = (int)(data[y][x][1] * scale);
output[y][x][2] = (int)(data[y][x][2] * scale); output[y][x][2] = (int)(data[y][x][2] * scale);
output[y][x][3] = (int)(data[y][x][3] * scale); output[y][x][3] = (int)(data[y][x][3] * scale);
@ -64,19 +85,21 @@ public class ImageUtil {
} }
/** /**
* Returns the rms value of the image * Returns the RMS value of the image
* (The RMS value is a measure of the width of the color distribution.) * (The RMS value is a measure of the width of the color distribution.)
* *
* @param data The image data * @param data is the image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @param startY is the y pixel of the image to start from
* @return The rms value for the image * @param stopX is the x pixel of the image to stop
* @param stopY is the y pixel of the image to stop
* @return The RMS value for the image
*/ */
public static int rms(int[][][] data, int cols, int rows){ public static int rms(int[][][] data, int startX, int startY, int stopX, int stopY){
int pixelCount = 0; int pixelCount = 0;
long accum = 0; long accum = 0;
for(int y=0; y <rows ;y++){ for(int y=startY; y <stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
accum += data[y][x][1] * data[y][x][1]; accum += data[y][x][1] * data[y][x][1];
accum += data[y][x][2] * data[y][x][2]; accum += data[y][x][2] * data[y][x][2];
accum += data[y][x][3] * data[y][x][3]; accum += data[y][x][3] * data[y][x][3];
@ -92,13 +115,15 @@ public class ImageUtil {
* Multiplies the given image data by the given value * Multiplies the given image data by the given value
* *
* @param data The image data * @param data The image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 scale The number to scale the image by * @param scale The number to scale the image by
*/ */
public static void scale(int[][][] data, int cols, int rows, double scale){ public static void scale(int[][][] data, int startX, int startY, int stopX, int stopY, double scale){
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
data[y][x][1] *= scale; data[y][x][1] *= scale;
data[y][x][2] *= scale; data[y][x][2] *= scale;
data[y][x][3] *= scale; data[y][x][3] *= scale;
@ -110,15 +135,27 @@ public class ImageUtil {
* Returns the mean value of the given image data * Returns the mean value of the given image data
* *
* @param data The image data * @param data The image data
* @param cols The column count
* @param rows The row count
* @return The mean value of the image * @return The mean value of the image
*/ */
public static int meanValue(int[][][] data,int cols, int rows){ public static int meanValue(int[][][] data){
return meanValue(data, 0, 0, data[0].length, data.length);
}
/**
* Returns the mean value of the given image data
*
* @param data The image 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
* @return The mean value of the image
*/
public static int meanValue(int[][][] data, int startX, int startY, int stopX, int stopY){
int pixelCount = 0; int pixelCount = 0;
long accum = 0; long accum = 0;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
accum += data[y][x][1]; accum += data[y][x][1];
accum += data[y][x][2]; accum += data[y][x][2];
accum += data[y][x][3]; accum += data[y][x][3];
@ -133,13 +170,15 @@ public class ImageUtil {
* Adds the mean value to the image data * Adds the mean value to the image data
* *
* @param data The image data * @param data The image data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 mean The mean value * @param mean The mean value
*/ */
public static void addMeanValue(int[][][] data,int cols, int rows, int mean){ public static void addMeanValue(int[][][] data, int startX, int startY, int stopX, int stopY, int mean){
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
data[y][x][1] += mean; data[y][x][1] += mean;
data[y][x][2] += mean; data[y][x][2] += mean;
data[y][x][3] += mean; data[y][x][3] += mean;
@ -191,21 +230,48 @@ public class ImageUtil {
* Copies the given array to a new one that it returns * Copies the given array to a new one that it returns
* *
* @param data The data to duplicate * @param data The data to duplicate
* @param cols The amount of columns * @return an copy of the array
* @param rows The amount of rows */
public static int[][][] copyArray(int[][][] data){
return copyArray(data, 0, 0, data[0].length, data.length);
}
/**
* Copies the given array to a new one that it returns
*
* @param data The data to duplicate
* @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 The array copy * @return The array copy
*/ */
public static int[][][] copyArray(int[][][] data,int cols,int rows){ public static int[][][] copyArray(int[][][] data, int startX, int startY, int stopX, int stopY){
int[][][] copy = new int[rows][cols][4]; int[][][] copy = new int[data.length][data[0].length][4];
for(int y=0; y<rows ;y++){ return copyArray(data, copy, startX, startY, stopX, stopY);
for(int x=0; x<cols ;x++){ }
copy[y][x][0] = data[y][x][0];
copy[y][x][1] = data[y][x][1]; /**
copy[y][x][2] = data[y][x][2]; * Copies the given array to a new one that it returns
copy[y][x][3] = data[y][x][3]; *
* @param data The data to duplicate
* @param dest is the array to copy the data to
* @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 the dest array
*/
public static int[][][] copyArray(int[][][] data, int[][][] dest, int startX, int startY, int stopX, int stopY){
for(int y=startY; y<stopY ;y++){
for(int x=startX; x<stopX ;x++){
dest[y][x][0] = data[y][x][0];
dest[y][x][1] = data[y][x][1];
dest[y][x][2] = data[y][x][2];
dest[y][x][3] = data[y][x][3];
} }
} }
return copy; return dest;
} }
/** /**
@ -213,15 +279,17 @@ public class ImageUtil {
* are in the range 0-255 * are in the range 0-255
* *
* @param data The image data * @param data The image data
* @param cols The amount of columns * @param startX is the x pixel of the image to start from
* @param rows The amount of rows * @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
*/ */
public static void clip(int[][][] data, int cols, int rows){ public static void clip(int[][][] data, int startX, int startY, int stopX, int stopY){
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
data[y][x][1] = clip(data[y][x][1]); data[y][x][1] = clip(data[y][x][1]);
data[y][x][1] = clip(data[y][x][2]); data[y][x][2] = clip(data[y][x][2]);
data[y][x][1] = clip(data[y][x][3]); data[y][x][3] = clip(data[y][x][3]);
} }
} }
} }

View file

@ -28,67 +28,64 @@ public class BlurFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
int inputPeak = ImageUtil.peakValue(data, cols, rows); int inputPeak = ImageUtil.peakValue(data);
int[][][] output = new int[rows][cols][4]; int[][][] tmpData = new int[data.length][data[0].length][4];
int[][][] tmpData = ImageUtil.copyArray(data, cols, rows);
//Perform the convolution one or more times in succession //Perform the convolution one or more times in succession
int redSum, greenSum, blueSum, outputPeak; int redSum, greenSum, blueSum, outputPeak;
for(int i=0; i<blurValue ;i++){ for(int i=0; i<blurValue ;i++){
//Iterate on each pixel as a registration point. //Iterate on each pixel as a registration point.
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, (blurValue-1)*(rows-2), i*(rows-2)+y)); setProgress(ZMath.percent(0, (blurValue-1)*(stopY-startY-2), i*(stopY-startY-2)+y));
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
if(x == 0 || x == cols-1 || y == 0 || y == rows-1){ if(x == 0 || x == data[0].length-1 || y == 0 || y == data.length-1){
redSum = tmpData[y][x][1] * 9; redSum = data[y][x][1] * 9;
greenSum = tmpData[y][x][2] * 9; greenSum = data[y][x][2] * 9;
blueSum = tmpData[y][x][3] * 9; blueSum = data[y][x][3] * 9;
} }
else{ else{
redSum = redSum =
tmpData[y - 1][x - 1][1] + data[y - 1][x - 1][1] +
tmpData[y - 1][x - 0][1] + data[y - 1][x - 0][1] +
tmpData[y - 1][x + 1][1] + data[y - 1][x + 1][1] +
tmpData[y - 0][x - 1][1] + data[y - 0][x - 1][1] +
tmpData[y - 0][x - 0][1] + data[y - 0][x - 0][1] +
tmpData[y - 0][x + 1][1] + data[y - 0][x + 1][1] +
tmpData[y + 1][x - 1][1] + data[y + 1][x - 1][1] +
tmpData[y + 1][x - 0][1] + data[y + 1][x - 0][1] +
tmpData[y + 1][x + 1][1]; data[y + 1][x + 1][1];
greenSum = greenSum =
tmpData[y - 1][x - 1][2] + data[y - 1][x - 1][2] +
tmpData[y - 1][x - 0][2] + data[y - 1][x - 0][2] +
tmpData[y - 1][x + 1][2] + data[y - 1][x + 1][2] +
tmpData[y - 0][x - 1][2] + data[y - 0][x - 1][2] +
tmpData[y - 0][x - 0][2] + data[y - 0][x - 0][2] +
tmpData[y - 0][x + 1][2] + data[y - 0][x + 1][2] +
tmpData[y + 1][x - 1][2] + data[y + 1][x - 1][2] +
tmpData[y + 1][x - 0][2] + data[y + 1][x - 0][2] +
tmpData[y + 1][x + 1][2]; data[y + 1][x + 1][2];
blueSum = blueSum =
tmpData[y - 1][x - 1][3] + data[y - 1][x - 1][3] +
tmpData[y - 1][x - 0][3] + data[y - 1][x - 0][3] +
tmpData[y - 1][x + 1][3] + data[y - 1][x + 1][3] +
tmpData[y - 0][x - 1][3] + data[y - 0][x - 1][3] +
tmpData[y - 0][x - 0][3] + data[y - 0][x - 0][3] +
tmpData[y - 0][x + 1][3] + data[y - 0][x + 1][3] +
tmpData[y + 1][x - 1][3] + data[y + 1][x - 1][3] +
tmpData[y + 1][x - 0][3] + data[y + 1][x - 0][3] +
tmpData[y + 1][x + 1][3]; data[y + 1][x + 1][3];
} }
output[y][x][0] = tmpData[y][x][0]; tmpData[y][x][0] = data[y][x][0];
output[y][x][1] = redSum; tmpData[y][x][1] = redSum;
output[y][x][2] = greenSum; tmpData[y][x][2] = greenSum;
output[y][x][3] = blueSum; tmpData[y][x][3] = blueSum;
} }
} }
// getting the new peak value and normalizing the image // getting the new peak value and normalizing the image
outputPeak = ImageUtil.peakValue(output, cols, rows); outputPeak = ImageUtil.peakValue(tmpData);
ImageUtil.normalize(tmpData, output, cols, rows, ((double)inputPeak)/outputPeak ); ImageUtil.normalize(data, tmpData, startX, startY, stopX, stopY, ((double)inputPeak)/outputPeak );
} }
return tmpData;
} }
} }

View file

@ -52,7 +52,7 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
// making sure the scales are right // making sure the scales are right
if(redScale > 100) redScale = 100; if(redScale > 100) redScale = 100;
else if(redScale < 0) redScale = 0; else if(redScale < 0) redScale = 0;
@ -62,29 +62,26 @@ public class ColorIntensityFilter extends ImageFilterProcessor{
if(blueScale > 100) blueScale = 100; if(blueScale > 100) blueScale = 100;
else if(blueScale < 0) blueScale = 0; else if(blueScale < 0) blueScale = 0;
int[][][] output = new int[rows][cols][4];
// Applying the color intensity to the image // Applying the color intensity to the image
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, rows-1, y)); setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
if(!invert){ if(!invert){
// inversion // inversion
output[y][x][0] = data[y][x][0]; data[y][x][0] = data[y][x][0];
output[y][x][1] = 255 - data[y][x][1] * redScale/100; data[y][x][1] = 255 - data[y][x][1] * redScale/100;
output[y][x][2] = 255 - data[y][x][2] * greenScale/100; data[y][x][2] = 255 - data[y][x][2] * greenScale/100;
output[y][x][3] = 255 - data[y][x][3] * blueScale/100; data[y][x][3] = 255 - data[y][x][3] * blueScale/100;
} }
else{ else{
output[y][x][0] = data[y][x][0]; data[y][x][0] = data[y][x][0];
output[y][x][1] = data[y][x][1] * redScale/100; data[y][x][1] = data[y][x][1] * redScale/100;
output[y][x][2] = data[y][x][2] * greenScale/100; data[y][x][2] = data[y][x][2] * greenScale/100;
output[y][x][3] = data[y][x][3] * blueScale/100; data[y][x][3] = data[y][x][3] * blueScale/100;
} }
} }
} }
return output;
} }
} }

View file

@ -30,18 +30,14 @@ public class ContrastBrightnessFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
int mean = ImageUtil.meanValue(data, cols, rows); int mean = ImageUtil.meanValue(data);
int[][][] output = ImageUtil.copyArray(data, cols, rows); ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, mean*(-1));
ImageUtil.scale(data, startX, startY, stopX, stopY, contrast);
ImageUtil.addMeanValue(output, cols, rows, mean*(-1)); ImageUtil.addMeanValue(data, startX, startY, stopX, stopY, (int)(brightness*mean));
ImageUtil.scale(output, cols, rows, contrast);
ImageUtil.addMeanValue(output, cols, rows, (int)(brightness*mean));
ImageUtil.clip(output ,cols, rows); ImageUtil.clip(data , startX, startY, stopX, stopY);
return output;
} }
} }

View file

@ -38,36 +38,32 @@ public class DitheringFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
int error, index; int error, index;
int[] currentPixel; int[] currentPixel;
int[][][] output = ImageUtil.copyArray(data, cols, rows);
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, rows-1, y)); setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
currentPixel = output[y][x]; currentPixel = data[y][x];
index = findNearestColor(currentPixel, palette); index = findNearestColor(currentPixel, palette);
output[y][x] = palette[index]; data[y][x] = palette[index];
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
error = currentPixel[i] - palette[index][i]; error = currentPixel[i] - palette[index][i];
if (x + 1 < cols) { if (x + 1 < data[0].length) {
output[y+0][x+1][i] = ImageUtil.clip( output[y+0][x+1][i] + (error*7)/16 ); data[y+0][x+1][i] = ImageUtil.clip( data[y+0][x+1][i] + (error*7)/16 );
} }
if (y + 1 < rows) { if (y + 1 < data.length) {
if (x - 1 > 0) if (x - 1 > 0)
output[y+1][x-1][i] = ImageUtil.clip( output[y+1][x-1][i] + (error*3)/16 ); data[y+1][x-1][i] = ImageUtil.clip( data[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 ); data[y+1][x+0][i] = ImageUtil.clip( data[y+1][x+0][i] + (error*5)/16 );
if (x + 1 < cols) if (x + 1 < data[0].length)
output[y+1][x+1][i] = ImageUtil.clip( output[y+1][x+1][i] + (error*1)/16 ); data[y+1][x+1][i] = ImageUtil.clip( data[y+1][x+1][i] + (error*1)/16 );
} }
} }
} }
} }
return output;
} }
private static int findNearestColor(int[] color, int[][] palette) { private static int findNearestColor(int[] color, int[][] palette) {

View file

@ -4,6 +4,7 @@ import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor; import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath; import zutil.math.ZMath;
public class FaceDetectionFilter extends ImageFilterProcessor{ public class FaceDetectionFilter extends ImageFilterProcessor{
@ -13,35 +14,37 @@ public class FaceDetectionFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(int[][][] data, int cols, int rows) { public void process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int[][][] IRgBy = convertARGBToIRgBy(data, cols, rows); int[][][] IRgBy = convertARGBToIRgBy(data, startX, startY, stopX, stopY);
MedianFilter median = new MedianFilter(null, 4*getSCALE(cols,rows), new boolean[]{false,false,true,true}); MedianFilter median = new MedianFilter(null, 4*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,false,true,true});
IRgBy = median.process(IRgBy, cols, rows); median.process(IRgBy);
setProgress(ZMath.percent(0, 4, 1)); setProgress(ZMath.percent(0, 4, 1));
//********* Texture Map ******** //********* Texture Map ********
median = new MedianFilter(null, 8*getSCALE(cols,rows), new boolean[]{false,true,false,false}); median = new MedianFilter(null, 8*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,true,false,false});
int[][][] textureMap = median.process(IRgBy, cols, rows); int[][][] textureMap = ImageUtil.copyArray(IRgBy);
median.process(IRgBy);
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
textureMap[y][x][1] = Math.abs(IRgBy[y][x][1]-textureMap[y][x][1]); textureMap[y][x][1] = Math.abs(IRgBy[y][x][1]-textureMap[y][x][1]);
} }
} }
median = new MedianFilter(null, 12*getSCALE(cols,rows), new boolean[]{false,true,false,false}); median = new MedianFilter(null, 12*getSCALE(stopX-startX, stopY-startY), new boolean[]{false,true,false,false});
textureMap = median.process(textureMap, cols, rows); textureMap = ImageUtil.copyArray(IRgBy);
median.process(textureMap);
setProgress(ZMath.percent(0, 4, 2)); setProgress(ZMath.percent(0, 4, 2));
//*********** Hue & Saturation ********* //*********** Hue & Saturation *********
int[][] skinMap = new int[rows][cols]; int[][] skinMap = new int[data.length][data[0].length];
int[][] hueMap = new int[rows][cols]; int[][] hueMap = new int[data.length][data[0].length];
int[][] saturationMap = new int[rows][cols]; int[][] saturationMap = new int[data.length][data[0].length];
int hue, saturation; int hue, saturation;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
// hue = (atan^2(Rg,By)) // hue = (atan^2(Rg,By))
hue = (int)( Math.atan2(IRgBy[y][x][2], IRgBy[y][x][3]) * 360/2*Math.PI); hue = (int)( Math.atan2(IRgBy[y][x][2], IRgBy[y][x][3]) * 360/2*Math.PI);
// saturation = sqrt(Rg^2+By^2) // saturation = sqrt(Rg^2+By^2)
@ -61,28 +64,30 @@ public class FaceDetectionFilter extends ImageFilterProcessor{
setProgress(ZMath.percent(0, 4, 3)); setProgress(ZMath.percent(0, 4, 3));
//************** SkinMap dilation ******************** //************** SkinMap dilation ********************
skinMap = dilation(skinMap , cols, rows); skinMap = dilation(skinMap , startX, startY, stopX, stopY);
//***************************************************** //*****************************************************
setProgress(100); setProgress(100);
//return convertArrayToARGBchannel(hueMap, cols, rows, -150, 150, 1); //return convertArrayToARGBchannel(hueMap, startX, startY, stopX, stopY, -150, 150, 1);
//return convertArrayToARGBchannel(saturationMap, cols, rows, 0, 70, 1); //return convertArrayToARGBchannel(saturationMap, startX, startY, stopX, stopY, 0, 70, 1);
return convertArrayToARGBchannel(skinMap, cols, rows, 0, 1, 2); ImageUtil.copyArray(
convertArrayToARGBchannel(skinMap, startX, startY, stopX, stopY, 0, 1, 2),
data, startX, startY, stopX, stopY);
} }
private int[][] dilation(int[][] data, int cols, int rows){ private int[][] dilation(int[][] data, int startX, int startY, int stopX, int stopY){
int[][] output = new int[rows][cols]; int[][] output = new int[data.length][data[0].length];
int radX = 8; int radX = 8;
int radY = 8; int radY = 8;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
if(data[y][x] == 1){ if(data[y][x] == 1){
for(int dy=y-radY; dy<y+radY ;dy++){ for(int dy=y-radY; dy<y+radY ;dy++){
for(int dx=x-radX; dx<x+radX ;dx++){ for(int dx=x-radX; dx<x+radX ;dx++){
if(dy >= 0 && dy < rows && dx >= 0 && dx < cols) if(dy >= 0 && dy < data.length && dx >= 0 && dx < data[0].length)
output[dy][dx] = 1; output[dy][dx] = 1;
} }
} }
@ -99,18 +104,20 @@ public class FaceDetectionFilter extends ImageFilterProcessor{
* Converts the given data array to a color image * Converts the given data array to a color image
* *
* @param data The 2d data * @param data The 2d data
* @param cols The size of the image data * @param startX is the x pixel of the image to start from
* @param rows The size of the image data * @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 min The minimum value in the data
* @param max The maximum value in the data * @param max The maximum value in the data
* @param channel The color channel to apply the data to * @param channel The color channel to apply the data to
* @return A ARGB array * @return A ARGB array
*/ */
public int[][][] convertArrayToARGBchannel(int[][] data, int cols, int rows,int min, int max, int channel){ public int[][][] convertArrayToARGBchannel(int[][] data, int startX, int startY, int stopX, int stopY,int min, int max, int channel){
int[][][] output = new int[rows][cols][4]; int[][][] output = new int[data.length][data[0].length][4];
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
output[y][x][0] = 255; output[y][x][0] = 255;
output[y][x][channel] = (int) ZMath.percent(min, max, data[y][x]); output[y][x][channel] = (int) ZMath.percent(min, max, data[y][x]);
} }
@ -126,15 +133,17 @@ public class FaceDetectionFilter extends ImageFilterProcessor{
* By = L(B)-[L(G)+L(R)]/2 * By = L(B)-[L(G)+L(R)]/2
* *
* @param data The RGB data * @param data The RGB data
* @param cols The number of columns * @param startX is the x pixel of the image to start from
* @param rows The number of rows * @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 IRgBy data * @return IRgBy data
*/ */
public int[][][] convertARGBToIRgBy(int[][][] data, int cols, int rows){ public int[][][] convertARGBToIRgBy(int[][][] data, int startX, int startY, int stopX, int stopY){
int[][][] output = new int[rows][cols][4]; int[][][] output = new int[data.length][data[0].length][4];
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
output[y][x][0] = data[y][x][0]; output[y][x][0] = data[y][x][0];
// I= [L(R)+L(B)+L(G)]/3 // I= [L(R)+L(B)+L(G)]/3
output[y][x][1] = ( output[y][x][1] = (
@ -158,8 +167,8 @@ public class FaceDetectionFilter extends ImageFilterProcessor{
} }
private int getSCALE(int cols, int rows){ private int getSCALE(int width, int height){
return (cols+rows)/320; return (width+height)/320;
} }

View file

@ -4,6 +4,7 @@ import java.awt.image.BufferedImage;
import zutil.algo.sort.sortable.SortableDataList; import zutil.algo.sort.sortable.SortableDataList;
import zutil.image.ImageFilterProcessor; import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath; import zutil.math.ZMath;
/** /**
@ -60,44 +61,42 @@ public class MedianFilter extends ImageFilterProcessor{
pixelValue[x][y] := colorArray[window width / 2][window height / 2]; pixelValue[x][y] := colorArray[window width / 2][window height / 2];
*/ */
@Override @Override
public int[][][] process(int[][][] data, int cols, int rows) { public void process(int[][][] data, int startX, int startY, int stopX, int stopY) {
int[][][] output = new int[rows][cols][4]; int[][][] tmpData = ImageUtil.copyArray(data);
int edgeX = windowSize / 2; int edgeX = windowSize / 2;
int edgeY = windowSize / 2; int edgeY = windowSize / 2;
int[][] tmpArray = new int[4][256*2]; int[][] tmpArray = new int[4][256*2];
int pixelCount = 0; int pixelCount = 0;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, rows-1, y)); setProgress(ZMath.percent(0, stopY-startY-1, y));
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
pixelCount = 0; pixelCount = 0;
for(int fy=0; fy<windowSize ;fy++){ for(int fy=0; fy<windowSize ;fy++){
for(int fx=0; fx<windowSize ;fx++){ for(int fx=0; fx<windowSize ;fx++){
if(y+fy-edgeY >= 0 && y+fy-edgeY < rows && x+fx-edgeX >= 0 && x+fx-edgeX < cols){ if(y+fy-edgeY >= 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] //colorArray[fx][fy] := pixelvalue[x + fx - edgex][y + fy - edgey]
if(channels[0]) tmpArray[0][ getMedianIndex( data[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( data[y + fy - edgeY][x + fx - edgeX][1] ) ]++; if(channels[1]) tmpArray[1][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][1] ) ]++;
if(channels[2]) tmpArray[2][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][2] ) ]++; if(channels[2]) tmpArray[2][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][2] ) ]++;
if(channels[3]) tmpArray[3][ getMedianIndex( data[y + fy - edgeY][x + fx - edgeX][3] ) ]++; if(channels[3]) tmpArray[3][ getMedianIndex( tmpData[y + fy - edgeY][x + fx - edgeX][3] ) ]++;
pixelCount++; pixelCount++;
} }
} }
} }
if(channels[0])output[y][x][0] = findMedian(tmpArray[0], pixelCount/2); if(channels[0]) data[y][x][0] = findMedian(tmpArray[0], pixelCount/2);
else output[y][x][0] = data[y][x][0]; else data[y][x][0] = tmpData[y][x][0];
if(channels[1])output[y][x][1] = findMedian(tmpArray[1], pixelCount/2); if(channels[1]) data[y][x][1] = findMedian(tmpArray[1], pixelCount/2);
else output[y][x][1] = data[y][x][1]; else data[y][x][1] = tmpData[y][x][1];
if(channels[2])output[y][x][2] = findMedian(tmpArray[2], pixelCount/2); if(channels[2]) data[y][x][2] = findMedian(tmpArray[2], pixelCount/2);
else output[y][x][2] = data[y][x][2]; else data[y][x][2] = tmpData[y][x][2];
if(channels[3])output[y][x][3] = findMedian(tmpArray[3], pixelCount/2); if(channels[3]) data[y][x][3] = findMedian(tmpArray[3], pixelCount/2);
else output[y][x][3] = data[y][x][3]; else data[y][x][3] = tmpData[y][x][3];
} }
} }
return output;
} }
private int getMedianIndex(int i){ private int getMedianIndex(int i){

View file

@ -3,15 +3,17 @@ package zutil.image.filters;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import zutil.image.ImageFilterProcessor; import zutil.image.ImageFilterProcessor;
import zutil.image.ImageUtil;
import zutil.math.ZMath; import zutil.math.ZMath;
public class ResizeImage extends ImageFilterProcessor{ public class ResizeImage extends ImageFilterProcessor{
private int width; private int width;
private int hight; private int height;
private int[][][] newData;
/** /**
* Will create a ResizeImage object and fix the hight with the aspect * Will create a ResizeImage object and fix the height with the aspect
* of the width * of the width
* *
* @param img The image to resize * @param img The image to resize
@ -26,38 +28,45 @@ public class ResizeImage extends ImageFilterProcessor{
* *
* @param img The image to resize * @param img The image to resize
* @param w The new width if -1 then it will be scaled whit aspect of the hight * @param w The new width if -1 then it will be scaled whit aspect of the hight
* @param h The new hight if -1 then it will be scaled whit aspect of the width * @param h The new height if -1 then it will be scaled whit aspect of the width
*/ */
public ResizeImage(BufferedImage img, int w, int h){ public ResizeImage(BufferedImage img, int w, int h){
super(img); super(img);
width = w; width = w;
hight = h; height = h;
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
if(width < 1){ if(width < 1){
hight = (int)(((double)width/cols)*rows); height = (int)(((double)width/(stopX-startX))*(stopY-startY));
} }
else if(hight < 1){ else if(height < 1){
width = (int)(((double)hight/rows)*cols); width = (int)(((double)height/(stopY-startY))*(stopX-startY));
} }
int[][][] tmp = new int[hight][width][4]; newData = new int[height][width][4];
double xScale = ((double)cols/width); double xScale = ((double)(stopX-startX)/width);
double yScale = ((double)rows/hight); double yScale = ((double)(stopY-startY)/height);
for(int y=0; y<width ;y++){ for(int y=0; y<width ;y++){
setProgress(ZMath.percent(0, width-1, y)); setProgress(ZMath.percent(0, width-1, y));
for(int x=0; x<hight ;x++){ for(int x=0; x<height ;x++){
tmp[y][x][0] = data[(int)(y*yScale)][(int)(x*xScale)][0]; newData[y][x][0] = data[(int)(y*yScale)][(int)(x*xScale)][0];
tmp[y][x][1] = data[(int)(y*yScale)][(int)(x*xScale)][1]; newData[y][x][1] = data[(int)(y*yScale)][(int)(x*xScale)][1];
tmp[y][x][2] = data[(int)(y*yScale)][(int)(x*xScale)][2]; newData[y][x][2] = data[(int)(y*yScale)][(int)(x*xScale)][2];
tmp[y][x][3] = data[(int)(y*yScale)][(int)(x*xScale)][3]; newData[y][x][3] = data[(int)(y*yScale)][(int)(x*xScale)][3];
} }
} }
return tmp; 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;
}
} }

View file

@ -41,15 +41,14 @@ public class SpotLightFilter extends ImageFilterProcessor{
} }
@Override @Override
public int[][][] process(final int[][][] data, int cols, int rows) { public void process(final int[][][] data, int startX, int startY, int stopX, int stopY) {
if(xPos < 0) xPos = cols/2; if(xPos < 0) xPos = data[0].length/2;
if(yPos < 0) yPos = rows/2; if(yPos < 0) yPos = data.length/2;
int[][][] output = new int[rows][cols][4];
double scale, dx, dy, distance; double scale, dx, dy, distance;
for(int y=0; y<rows ;y++){ for(int y=startY; y<stopY ;y++){
setProgress(ZMath.percent(0, rows-1, y)); setProgress(ZMath.percent(0, (stopY-startY)-1, y));
for(int x=0; x<cols ;x++){ for(int x=startX; x<stopX ;x++){
dx = x-xPos; dx = x-xPos;
dy = y-yPos; dy = y-yPos;
@ -62,13 +61,12 @@ public class SpotLightFilter extends ImageFilterProcessor{
scale = 1-(distance/radius); scale = 1-(distance/radius);
} }
output[y][x][0] = data[y][x][0]; data[y][x][0] = data[y][x][0];
output[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1])); data[y][x][1] = ImageUtil.clip((int)(scale * data[y][x][1]));
output[y][x][2] = ImageUtil.clip((int)(scale * data[y][x][2])); data[y][x][2] = ImageUtil.clip((int)(scale * data[y][x][2]));
output[y][x][3] = ImageUtil.clip((int)(scale * data[y][x][3])); data[y][x][3] = ImageUtil.clip((int)(scale * data[y][x][3]));
} }
} }
return output;
} }
} }

View file

@ -58,7 +58,7 @@ public class HttpPrintStream extends PrintStream{
public void sendHeader(String header) throws Exception{ public void sendHeader(String header) throws Exception{
if(cookie == null) if(cookie == null)
throw new Exception("Header already sent!!!"); throw new Exception("Header already sent!!!");
super.println(header); super.print(header+"\n");
} }
/** /**
@ -69,27 +69,25 @@ public class HttpPrintStream extends PrintStream{
} }
/** /**
* NOT TO BE USED!!!! * Prints an string
* use printOrBuffer(String s) instead
*/ */
@Deprecated
public void print(String s){ public void print(String s){
super.print(s); printOrBuffer(s);
} }
/** /**
* prints to all * prints to all
*/ */
public void printOrBuffer(String s){ private void printOrBuffer(String s){
if(buffer_enabled){ if(buffer_enabled){
buffer.append(s); buffer.append(s);
} }
else{ else{
if(cookie != null){ if(cookie != null){
for(String key : cookie.keySet()){ for(String key : cookie.keySet()){
super.println("Set-Cookie: "+key+"="+cookie.get(key)+"; "); super.print("Set-Cookie: "+key+"="+cookie.get(key)+"; \n");
} }
super.println(" \n"); super.print(" \n");
cookie = null; cookie = null;
} }
super.print(s); super.print(s);
@ -115,21 +113,21 @@ public class HttpPrintStream extends PrintStream{
} }
public void println(){ println("");} public void println(){ println("");}
public void println(boolean x){ println(""+x);} public void println(boolean x){ println(String.valueOf(x));}
public void println(char x){ println(""+x);} public void println(char x){ println(String.valueOf(x));}
public void println(char[] x){ println(new String(x));} public void println(char[] x){ println(new String(x));}
public void println(double x){ println(""+x);} public void println(double x){ println(String.valueOf(x));}
public void println(float x){ println(""+x);} public void println(float x){ println(String.valueOf(x));}
public void println(int x){ println(""+x);} public void println(int x){ println(String.valueOf(x));}
public void println(long x){ println(""+x);} public void println(long x){ println(String.valueOf(x));}
public void println(Object x){ println(""+x);} public void println(Object x){ println(String.valueOf(x));}
public void print(boolean x){ printOrBuffer(""+x);} public void print(boolean x){ printOrBuffer(String.valueOf(x));}
public void print(char x){ printOrBuffer(""+x);} public void print(char x){ printOrBuffer(String.valueOf(x));}
public void print(char[] x){ printOrBuffer(new String(x));} public void print(char[] x){ printOrBuffer(new String(x));}
public void print(double x){ printOrBuffer(""+x);} public void print(double x){ printOrBuffer(String.valueOf(x));}
public void print(float x){ printOrBuffer(""+x);} public void print(float x){ printOrBuffer(String.valueOf(x));}
public void print(int x){ printOrBuffer(""+x);} public void print(int x){ printOrBuffer(String.valueOf(x));}
public void print(long x){ printOrBuffer(""+x);} public void print(long x){ printOrBuffer(String.valueOf(x));}
public void print(Object x){ printOrBuffer(""+x);} public void print(Object x){ printOrBuffer(String.valueOf(x));}
} }

View file

@ -3,7 +3,6 @@ package zutil.test;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import zutil.FileFinder;
import zutil.network.http.HttpPage; import zutil.network.http.HttpPage;
import zutil.network.http.HttpPrintStream; import zutil.network.http.HttpPrintStream;
import zutil.network.http.HttpServer; import zutil.network.http.HttpServer;

View file

@ -61,13 +61,13 @@ public class ImageProcessorTest implements ProgressListener{
BufferedImage procImg = null; BufferedImage procImg = null;
try { try {
//ImageFilterProcessor processor = new SpotLightFilter(img,100,100,100); //ImageFilterProcessor processor = new BlurFilter(img, 10);
//ImageFilterProcessor processor = new ContrastBrightnessFilter(img);
//ImageFilterProcessor processor = new ColorIntensityFilter(img, true); //ImageFilterProcessor processor = new ColorIntensityFilter(img, true);
ImageFilterProcessor processor = new BlurFilter(img, 100); //ImageFilterProcessor processor = new ContrastBrightnessFilter(img);
//ImageFilterProcessor processor = new DitheringFilter(img); ImageFilterProcessor processor = new DitheringFilter(img);
//ImageFilterProcessor processor = new ResizeImage(img,100,100);
//ImageFilterProcessor processor = new MedianFilter(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 FaceDetectionFilter(img);
processor.setProgressListener(this); processor.setProgressListener(this);