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(); } }