package imagetools;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
/**
* Performs a Gaussian Blur over the Image, Specifically for getting Captures
*
* Gaussian blurs differ from mean filters in that they use the Gaussian function (1/standarddeviation*sqrt(2*pi))*e^(((-.5*x-mean)/standarddeviation)^2) as a multiplier
*
* An average blur exists in the denoise class as well since a mean filter accomplishes both tasks
*
* @author aevans 7/29/2013
* @version update 1/29/2014 - added proximity pattern
*/
public class Blur implements Proximity {
//get the singleton instance
private Image image=Image.getInstance();
public Blur() {
// Empty Constructor, for if the image object is not null
}
public Blur(BufferedImage img) {
// TODO constructor with only buffered image
if (img != null) {
image.setImage(img);
} else {
// without an image provided, throw a new exception
try {
throw new NoImgException();
} catch (NoImgException e) {
e.printStackTrace();
}
}
}
public Blur(BufferedImage img, String inpath) {
// TODO set image with BufferedImage and run blur
Pattern p=Pattern.compile("(?mi)(\\.jpg|\\.jpeg|\\.gif|\\.bmp)");
Matcher m=p.matcher(inpath);
if(m.find()){
try {
image.setPath(inpath);
image.setImage(ImageIO.read(new File(inpath)));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
try{
throw new FileTypeException("Image must be a jpg,gif,bmp,or jpeg");
}catch(FileTypeException e){
e.printStackTrace();
}
}
}
public Blur(String inpath) {
// TODO constructor that takes in the path and attempts to create an
// image and run blur
Pattern p=Pattern.compile("(?mi)(\\.jpg|\\.jpeg|\\.gif|\\.bmp)");
Matcher m=p.matcher(inpath);
if(m.find()){
image.setPath(inpath);
try {
image.setImage(ImageIO.read(new File(image.getPath())));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
try{
throw new FileTypeException("Image must be a jpg, gif, bmp, or jpeg");
}catch(FileTypeException e){
e.printStackTrace();
}
}
}
@Override
public void setImage(String inpath) {
// TODO set image via string and run blur
Pattern p=Pattern.compile("(?mi)(\\.jpg|\\.jpeg|\\.gif|\\.bmp)");
Matcher m=p.matcher(inpath);
if(m.find()){
image.setPath(inpath);
try {
image.setImage(ImageIO.read(new File(image.getPath())));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
try{
throw new FileTypeException("Image must be a jpg, gif, bmp, or jpeg");
}catch(FileTypeException e){
e.printStackTrace();
}
}
}
public BufferedImage getBufferedImage() {
// TODO return the image
return image.getImage();
}
@Override
public Image getImage(){
return image;
}
@Override
public void setImage(BufferedImage inimg) {
// TODO set image via buffered image
if (inimg != null) {
image.setImage(inimg);
} else {
try {
throw new NoImgException();
} catch (NoImgException e) {
e.printStackTrace();
}
}
}
@Override
public void delete() {
// TODO Auto-generated method stub
image.delete();
}
@Override
public void setPath(String path) {
// TODO Auto-generated method stub
image.setPath(path);
}
@Override
public String getPath() {
// TODO Auto-generated method stub
return image.getPath();
}
public void average_blur() {
// TODO call the average blur script
blur_average();
}
public void blurImage(double radius) {
// TODO blur the image using gauss
blur_gauss(radius);
}
private void blur_gauss(double radius) {
// TODO create a kernel and implement a gaussian blur
// this is a somewhat lazy implementation setting a definite center and
// not wrapping to avoid black space
// the radius of the kernal should be at least 3*the blur factor
BufferedImage proxyimage=image.getImage();
int rows_and_columns = (int) Math.round(radius);
while (rows_and_columns % 2 == 0 & rows_and_columns != 0) {
rows_and_columns++;
}
while (rows_and_columns > proxyimage.getWidth()) {
rows_and_columns = 3;
}
int centerx = ((rows_and_columns + 1) / 2) - 1;
int centery = ((rows_and_columns + 1) / 2) - 1;
// the kernel sum
float sum_multiplier = 0;
/* get the kernel */
// the base for gaussian filtering
float base_start = (float) (1 / (2 * Math.PI * Math.pow(radius, 2)));
// the multiplier matrix to be applied to every pixel, ensured to be one
float[][] arr = new float[rows_and_columns][rows_and_columns];
// the central coordinates
for (int i = 0; i < rows_and_columns; i++) {
for (int j = 0; j < rows_and_columns; j++) {
float exp = 0;
// calculate the corners
exp = (float) -1.0
* (float) ((Math.pow((Math.abs(i - centerx)), 2) + (Math
.pow(Math.abs(j - centery), 2))) / (2 * Math
.pow(radius, 2)));
float base = (float) (base_start * Math.exp(exp));
arr[i][j] = base;
sum_multiplier += base;
}
}
/* replace the values by multiplying by the sum_multiplier */
// get the multiplier
sum_multiplier = (float) 1 / sum_multiplier;
// multiply by the sum multiplier for each number
for (int i = 0; i < rows_and_columns; i++) {
for (int j = 0; j < rows_and_columns; j++) {
arr[i][j] = arr[i][j] * sum_multiplier;
}
}
// blur the image using the matrix
complete_gauss(arr, rows_and_columns, centerx, centery);
}
private void complete_gauss(float[][] arr, int rows_and_columns,int centerx, int centery) {
// TODO complete the gaussian blur by applying the kernel for each pixel
BufferedImage proxyimage=image.getImage();
// the blurred image
BufferedImage image2 = new BufferedImage(proxyimage.getWidth(),proxyimage.getHeight(), BufferedImage.TYPE_INT_RGB);
// the r,g,b, values
int r = 0;
int g = 0;
int b = 0;
int i = 0;
int j = 0;
// the image height and width
int width = image2.getWidth();
int height = image2.getHeight();
int tempi = 0;
int tempj = 0;
int thisx = 0;
int thisy = 0;
if (arr.length != 1) {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
// the values surrounding the pixel and the resulting blur
// multiply pixel and its neighbors by the appropriate
// ammount
i = (int) -Math.ceil((double) rows_and_columns / 2);
j = (int) -Math.ceil((double) rows_and_columns / 2);
while (i < Math.ceil((double) rows_and_columns / 2)
& j < Math.ceil((double) rows_and_columns / 2)) {
// sets the pixel coordinates
thisx = x + i;
if (thisx < 0) {
thisx = proxyimage.getWidth() - 1;
} else if (thisx >= proxyimage.getWidth()) {
thisx = 0;
}
thisy = y + j;
if (thisy < 0) {
thisy = proxyimage.getHeight() - 1;
} else if (thisy >= proxyimage.getHeight()) {
thisy = 0;
}
// the implementation
tempi = (int) (Math
.round(((double) rows_and_columns / 2)) + i);
tempj = (int) (Math
.round(((double) rows_and_columns / 2)) + j);
if (tempi >= arr[0].length) {
tempi = 0;
}
if (tempj >= arr[0].length) {
tempj = 0;
}
r += (new Color(proxyimage.getRGB((thisx), (thisy)))
.getRed() * arr[tempi][tempj]);
g += (new Color(proxyimage.getRGB((thisx), (thisy)))
.getGreen() * arr[tempi][tempj]);
b += (new Color(proxyimage.getRGB((thisx), (thisy)))
.getBlue() * arr[tempi][tempj]);
j++;
if (j == Math.round((double) rows_and_columns / 2)) {
j = 0;
i++;
}
}
// set the new rgb values with a brightening factor
r = Math.min(
255,
Math.max(
0,
r
+ ((int) Math.round(arr[0].length
* arr[0].length))));
g = Math.min(
255,
Math.max(
0,
g
+ ((int) Math.round(arr[0].length
* arr[0].length))));
b = Math.min(
255,
Math.max(
0,
b
+ ((int) Math.round(arr[0].length
* arr[0].length))));
Color rgb = new Color(r, g, b);
image2.setRGB(x, y, rgb.getRGB());
r = 0;
g = 0;
b = 0;
i = 0;
j = 0;
}
}
image.setImage(image2);
}
}
private void blur_average() {
// TODO perform an average denoise may work for most images
/*
* the kernel applied is1/9|1/9|1/91/9|1/9|1/91/9|1/9|1/9
*
* this is a blur and a denoise in one so calling it again only causes a
* blurier image
*/
BufferedImage proxyimage=image.getImage();
// the new image to be stored as a denoised image
BufferedImage image2 = new BufferedImage(proxyimage.getWidth(),proxyimage.getHeight(), BufferedImage.TYPE_INT_RGB);
// the current position properties
int x = 0;
int y = 0;
// a neighbor pixel to add to the map
// the image width and height properties
int width = proxyimage.getWidth();
int height = proxyimage.getHeight();
// loop through pixels getting neighbors and resetting colors
for (x = 1; x < width - 1; x++) {
for (y = 1; y < height - 1; y++) {
// get the neighbor pixels for the transform
Color c00 = new Color(proxyimage.getRGB(x - 1, y - 1));
Color c01 = new Color(proxyimage.getRGB(x - 1, y));
Color c02 = new Color(proxyimage.getRGB(x - 1, y + 1));
Color c10 = new Color(proxyimage.getRGB(x, y - 1));
Color c11 = new Color(proxyimage.getRGB(x, y));
Color c12 = new Color(proxyimage.getRGB(x, y + 1));
Color c20 = new Color(proxyimage.getRGB(x + 1, y - 1));
Color c21 = new Color(proxyimage.getRGB(x + 1, y));
Color c22 = new Color(proxyimage.getRGB(x + 1, y + 1));
// apply the kernel for r
int r = c00.getRed() / 9 + c01.getRed() / 9 + c02.getRed() / 9
+ c10.getRed() / 9 + c11.getRed() / 9 + c12.getRed()
/ 9 + c20.getRed() / 9 + c21.getRed() / 9
+ c22.getRed() / 9;
// apply the kernel for g
int g = c00.getGreen() / 9 + c01.getGreen() / 9
+ c02.getGreen() / 9 + c10.getGreen() / 9
+ c11.getGreen() / 9 + c12.getGreen() / 9
+ c20.getGreen() / 9 + c21.getGreen() / 9
+ c22.getGreen() / 9;
// apply the transformation for b
int b = c00.getBlue() / 9 + c01.getBlue() / 9 + c02.getBlue()
+ c10.getBlue() / 9 + c11.getBlue() / 9 + c12.getBlue()
/ 9 + c20.getBlue() / 9 + c21.getBlue() / 9
+ c22.getBlue() / 9;
// set the new rgb values
r = Math.min(255, Math.max(0, r));
g = Math.min(255, Math.max(0, g));
b = Math.min(255, Math.max(0, b));
Color c = new Color(r, g, b);
image2.setRGB(x, y, c.getRGB());
}
}
// reset the image
image.setImage(image2);
}
public void save() {
// TODO save the image
image.save();
}
}