package imagetools; import java.awt.Color; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; /** * Rotate an image using a matrix. This can also be used to crop a skewed image which can then be rotated. * * Rotational Matrix should be something like * * [cos(theta),-sin(theta) * sin(theta),-cos(theta)] * * @author aevens * */ public class Rotate implements Proximity { private double theta; private Image image=Image.getInstance(); private boolean crop=false; public Rotate(){ } public boolean isCrop() { return crop; } public void setCrop(boolean crop) { this.crop = crop; } /** * Set a buffered image */ @Override public void setImage(BufferedImage img) { // TODO set image from buffered image image.setImage(img); } /** * Get the Buffered Image * @return */ public BufferedImage getBufferedImage() { // TODO returns a buffered image return image.getImage(); } /** * Get the Image Object */ @Override public Image getImage(){ return image; } /** * Set an image from a file path */ @Override public void setImage(String inpath) { // TODO set image from path 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(); } } } /** * Set the image path */ @Override public void setPath(String inpath) { // TODO set path and get file image.setPath(inpath); } /** * Get the image path */ @Override public String getPath(){ return image.getPath(); } /** * Set an image from a byte array * @param bytes */ public void setImage(byte[] bytes) { // TODO set image from bytes (warning: meta data will be stripped) // byte array to read in image ByteArrayInputStream bis = new ByteArrayInputStream(bytes); // attempt to read in image try { image.setImage(ImageIO.read(bis)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Gets the angle to use in rotating * @return */ public double getTheta() { return theta; } /** * Sets the angle to Use in Rotating * * @param theta */ public void setTheta(double theta) { this.theta = theta; } /** * Get the image bytes * @return */ public byte[] getImageBytes() { // TODO returns a jpeg turned to bytes BufferedImage proxyimage=image.getImage(); // the byte array byte[] ibytes = null; // the byte array outputstream ByteArrayOutputStream baos = new ByteArrayOutputStream(); // convert image to byte array try { ImageIO.write(proxyimage, "jpg", baos); ibytes = baos.toByteArray(); baos.flush(); baos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // return byte array unless failure return ibytes; } /** * Save image */ @Override public void save() { // TODO save the image image.save(); } /** * Delete an image */ @Override public void delete(){ image.delete(); } private void rotate(){ //create the rotational matrix (for some reason [y][x] felt more right as in move up a level or iterate further) double[][] newpos=new double[2][2]; newpos[0][0]=Math.cos(theta); newpos[0][1]=(Math.sin(theta)*-1); newpos[1][0]=Math.sin(theta); newpos[1][1]=Math.cos(theta); //set a new 'Canvas' BufferedImage bi=new BufferedImage(image.getWidth(),image.getWidth(),BufferedImage.TYPE_3BYTE_BGR); BufferedImage oldbi=image.getImage(); int newx=-1; int newy=-1; Color rgb; //perform the rotate multiplication by figuring out thew new x,y coordinates for each point for(int w=0;w<image.getWidth();w++){ for(int h=0;h<image.getHeight();h++){ rgb=new Color(oldbi.getRGB(w, h)); newx=(int)Math.ceil(w*newpos[0][0]+h*newpos[0][1]); newy=(int)Math.ceil(w*newpos[1][0]+h*newpos[1][1]); //set the coordinates of our new image canvas if(newx>=0 & newx< bi.getWidth() & newy>=0 & newy<bi.getHeight()){ bi.setRGB(newx, newy, rgb.getRGB()); } //reset everything for gc and insurance rgb=null; newx=-1; newy=-1; } } image.setImage(bi); } /** * Get the starting y coordinate of color in an image either int or dec. * @param starty * @param bi * @param backwards * @return */ private int getStartColorY(int startx, int starty, BufferedImage bi, boolean increment){ //TODO find the start of color inc. or dec. the y coord. in an image int y=starty; int x=startx; Color c=new Color(bi.getRGB(x, y)); while(y>0 & y<bi.getHeight() & c.getRed()==0 & c.getBlue()==0 & c.getGreen()==0) { y=(increment)?y+1:y-1; c=new Color(bi.getRGB(x, y)); } if(increment==true & y==bi.getHeight()) { y=0; } else if(increment==false & y==0){ y=bi.getHeight()-1; } return y; } /** * Get the starting x coordinate of color in an image either inc. or dec. * @param startx * @param bi * @param backwards * @return */ private int getStartColorX(int startx,int starty,BufferedImage bi,boolean increment){ //TODO Find the start of color inc. or dec. an x coord in the image int y=starty; int x=startx; Color c=new Color(bi.getRGB(x, y)); while(x>0 & x<bi.getWidth() & c.getRed()==0 & c.getBlue()==0 & c.getGreen()==0) { x=(increment)?x+1:x-1; c=new Color(bi.getRGB(x, y)); } if(increment==true & x==bi.getWidth()) { x=0; } else if(increment==false & x==0){ x=bi.getWidth()-1; } return x; } private void performCrop(){ BufferedImage bi=image.getImage(); if(bi != null){ //determine start and end coordinates for our crop int tempx=0; int startx=0; int endx=bi.getWidth()-1; int starty=0; int endy=0; //get the proper startx int x=0; int y=0; tempx=getStartColorX(0,0, bi, true); y=(image.getHeight()-1); x=0; x=getStartColorX(0,y,bi,true); if(x>tempx){ startx=x; } else{ startx=tempx; } //get the proper endx x=bi.getWidth()-1; y=0; tempx=getStartColorX(x,y,bi,false); y=(bi.getHeight()-1); x=(bi.getWidth()-1); x=getStartColorX(x,y,bi,false); if(tempx<endx){ endx=tempx; } else{ endx=x; } //get the starty y=0; x=0; y=getStartColorY(x,y,bi,true); tempx=y; y=0; x=bi.getWidth()-1; y=getStartColorY(x,y,bi,true); if(tempx>y){ starty=tempx; } else{ starty=y; } //get the endy y=bi.getHeight()-1; x=0; y=getStartColorY(x,y,bi,false); tempx=y; y=bi.getHeight()-1; x=bi.getWidth()-1; y=getStartColorY(x,y,bi,false); if(tempx<y){ endy=tempx; } else{ endy=y; } //perform our crop if(startx >=0 & endx< bi.getWidth()){ Crop crp=new Crop(); crp.crop(startx, 0,(endx-startx), (starty-endy)); image.setImage(crp.getBufferedImage()); } } } public void crop(){ performCrop(); } public void run(){ if(image.getImage()!= null){ rotate(); } else{ try{ throw new NullPointerException("No Image Provided to Rotate!\n"); }catch(NullPointerException e){ e.printStackTrace(); } } } }