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