Package org.jpedal.images

Source Code of org.jpedal.images.ImageTransformerDouble

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
* (C) Copyright 1997-2008, IDRsolutions and Contributors.
*
*   This file is part of JPedal
*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


*
* ---------------
* ImageTransformerDouble.java
* ---------------
*/
package org.jpedal.images;

import org.jpedal.PdfDecoder;
import org.jpedal.color.ColorSpaces;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.objects.GraphicsState;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.Matrix;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

/**
* class to shrink and clip an extracted image
* On reparse just calculates co-ords
*/
public class ImageTransformerDouble {
 
  double ny=0,nx=0;

    /**the clip*/
  private Area clip=null;

  /**holds the actual image*/
  private BufferedImage current_image;

  /**matrices used in transformation*/
  private float[][] Trm,Trm1, Trm2,CTM;

  /**image co-ords*/
  private int i_x = 0, i_y = 0, i_w = 0, i_h = 0;
 
  /**dpi scale factor*/
  private float scale=1;

  private boolean scaleImage;

  /**flag to show image clipped*/
  private boolean hasClip=false;
 
  /**tell software to remove unneeded border on hires clip*/
  private boolean removeClippedBorder=true;


    /**
   * pass in image information and apply transformation matrix
   * to image
   */
  public ImageTransformerDouble(
    int dpi,
    GraphicsState currentGS,
    BufferedImage new_image,
    boolean scaleImage,boolean removeClippedBorder) {
   
    this.removeClippedBorder=removeClippedBorder;
   
    /**
     * set values
     */
    //set scaling for final image
    scale=dpi/72;
   
    //save global values
    this.current_image = new_image;
    this.scaleImage=scaleImage;
   
    CTM = currentGS.CTM; //local copy of CTM

    createMatrices();
   
    // get clipped image and co-ords
    if(currentGS.getClippingShape()!=null)
      clip = (Area) currentGS.getClippingShape().clone();
   
    calcCoordinates();

    }
 
  /**
     * applies the shear/rotate of a double transformation to the clipped image
  */
  final public void doubleScaleTransformShear(boolean alreadyTurned){

        float[][] Trm1=this.Trm1;

        boolean isSwapped=false;

        scale(Trm1);

        current_image = ColorSpaceConvertor.convertToARGB(current_image);

        //create a copy of clip (so we don't alter clip)
    if(!isSwapped && clip!=null){
      Area final_clip = (Area) clip.clone();

      clipImage(true,final_clip,alreadyTurned);

      i_x=(int)clip.getBounds2D().getMinX();
      i_y=(int) clip.getBounds2D().getMinY();
      i_w=(int)((clip.getBounds2D().getMaxX())-i_x);
      i_h=(int)((clip.getBounds2D().getMaxY())-i_y);
    }
    }
 
  /**
   * applies the scale of a double transformation to the clipped image
   */
  final public void doubleScaleTransformScale(){
   
    if((CTM[0][0]!=0.0)&(CTM[1][1]!=0.0))
      scale(Trm2);
    //clipImage(true);
   
  }
 
  /**complete image and workout co-ordinates*/
  final public void completeImage(){
   
    //Matrix.show(CTM);
   
    /*if((CTM[0][1]>0 )&(CTM[1][0]>0 )){
      //ShowGUIMessage.showGUIMessage("",current_image,"a ");
      AffineTransform image_at =new AffineTransform();
      image_at.scale(-1,-1);
      image_at.translate(-current_image.getWidth(),-current_image.getHeight());
      AffineTransformOp invert= new AffineTransformOp(image_at,  ColorSpaces.hints);
     
      current_image = invert.filter(current_image,null);
     
    }*/
   
    //ShowGUIMessage.showGUIMessage("",current_image,"a ");
   
    /**/
    if(hasClip){
      i_x=(int)clip.getBounds2D().getMinX();
      i_y=(int) clip.getBounds2D().getMinY();
      i_w=(current_image.getWidth());
      i_h=(current_image.getHeight());
     
      //System.out.println(current_image.getWidth()+" "+current_image.getHeight());
      //System.out.println(i_x+" "+i_y+" "+i_w+" "+i_h+" "+clip.getBounds2D());
     
    }/***/
   
  }
 
    /**scale image to size*/
    private void scale(float[][] Trm){
       
      /**
       * transform the image only if needed
       */
      if ((Trm[0][0] != 1.0)|| (Trm[1][1] != 1.0)|| (Trm[0][1] != 0.0)
          || (Trm[1][0] != 0.0)||(scale!=1)) {
 
        int w = current_image.getWidth(); //raw width
        int h = current_image.getHeight(); //raw height
       
        //workout transformation for the image
        AffineTransform image_at =new AffineTransform(Trm[0][0]*scale,-Trm[0][1]*scale,-Trm[1][0]*scale,Trm[1][1]*scale,0,0);
       
        //apply it to the shape first so we can align
        Area r =new Area(new Rectangle(0,0,w,h));
        r.transform(image_at);
       
        //make sure it fits onto image (must start at 0,0)
        ny = r.getBounds2D().getY();
        nx = r.getBounds2D().getX();
        image_at =new AffineTransform(Trm[0][0]*scale,-Trm[0][1]*scale,-Trm[1][0]*scale,Trm[1][1]*scale,-nx,-ny);
       
        //Create the affine operation.
        //ColorSpaces.hints causes single lines to vanish);
        AffineTransformOp invert;
        if((w>10)&(h>10))
          invert = new AffineTransformOp(image_at,  ColorSpaces.hints);
        else
          invert = new AffineTransformOp(image_at,  null);

        //scale image to produce final version
        if(scaleImage)
          current_image = invert.filter(current_image,null);       
       
      }
     
    }

    /**workout the transformation as 1 or 2 transformations*/
    private void createMatrices(){
     
      int w = current_image.getWidth(); //raw width
      int h = current_image.getHeight(); //raw height

      //build transformation matrix by hand to avoid errors in rounding
      Trm = new float[3][3];
      Trm[0][0] = (CTM[0][0] / w);
      Trm[0][1] = (CTM[0][1] / w);
      Trm[0][2] = 0;
      Trm[1][0] = (CTM[1][0] / h);
      Trm[1][1] = (CTM[1][1] / h);
      Trm[1][2] = 0;
      Trm[2][0] = CTM[2][0];
      Trm[2][1] = CTM[2][1];
      Trm[2][2] = 1;

      //round numbers if close to 1
      for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 3; x++) {
          if ((Trm[x][y] > .99) & (Trm[x][y] < 1))
            Trm[x][y] = 1;
        }
      }
     
      /**now work out as 2 matrices*/
      Trm1=new float[3][3];
      Trm2=new float[3][3];
     
      //used to handle sheer
      float x1=1,x2=0,y1=1,y2=0;
     
      x1=CTM[0][0];
      if(x1<0)
        x1=-x1;
      x2=CTM[0][1];
      if(x2<0)
        x2=-x2;
     
      y1=CTM[1][1];
      if(y1<0)
        y1=-y1;
      y2=CTM[1][0];
      if(y2<0)
        y2=-y2;

            //factor out scaling to produce just the sheer/rotation
      if((CTM[0][0]==0.0)|(CTM[1][1]==0.0)){
        Trm1=Trm;

            }else if((CTM[0][1]==0.0)&&(CTM[1][0]==0.0)){

        Trm1[0][0] = w/(CTM[0][0]);
        Trm1[0][1] = 0;
        Trm1[0][2] = 0;
     
        Trm1[1][0] =0;
        Trm1[1][1] = h/(CTM[1][1]);
        Trm1[1][2] = 0;
       
        Trm1[2][0] = 0;
        Trm1[2][1] = 0;
        Trm1[2][2] = 1;


        Trm1=Matrix.multiply(Trm,Trm1);

        //round numbers if close to 1
        for (int y = 0; y < 3; y++) {
          for (int x = 0; x < 3; x++) {
            if ((Trm1[x][y] > .99) & (Trm1[x][y] < 1))
              Trm1[x][y] = 1;
          }
        }
      }else{ //its got sheer/rotation
       
        if(x1>x2)
          Trm1[0][0] = w/(CTM[0][0]);
        else
          Trm1[0][0] = w/(CTM[0][1]);
        if (Trm1[0][0]<0)
          Trm1[0][0]=-Trm1[0][0];
        Trm1[0][1] = 0;
        Trm1[0][2] = 0;
     
        Trm1[1][0] =0;
       
        if(y1>y2)
          Trm1[1][1] = h/(CTM[1][1]);
        else
          Trm1[1][1] = h/(CTM[1][0]);
        if (Trm1[1][1]<0)
          Trm1[1][1]=-Trm1[1][1];
        Trm1[1][2] = 0;
       
        Trm1[2][0] = 0;
        Trm1[2][1] = 0;
        Trm1[2][2] = 1;
       
       
        Trm1=Matrix.multiply(Trm,Trm1);
       
        //round numbers if close to 1
        for (int y = 0; y < 3; y++) {
          for (int x = 0; x < 3; x++) {
            if ((Trm1[x][y] > .99) & (Trm1[x][y] < 1))
              Trm1[x][y] = 1;
          }
        }
      }

            //create a transformation with just the scaling
      if(x1>x2)
        Trm2[0][0] = (CTM[0][0] / w);
      else
        Trm2[0][0] = (CTM[0][1] / w);
     
      if(Trm2[0][0] <0)
        Trm2[0][0] =-Trm2[0][0] ;
      Trm2[0][1] = 0;
      Trm2[0][2] = 0;
      Trm2[1][0] = 0;
      if(y1>y2)
        Trm2[1][1] = (CTM[1][1] / h);
      else
        Trm2[1][1] = (CTM[1][0] / h);
     
      if(Trm2[1][1] <0)
        Trm2[1][1] =-Trm2[1][1] ;
     
      Trm2[1][2] = 0;
      Trm2[2][0] = 0;
      Trm2[2][1] = 0;
      Trm2[2][2] = 1;
     
      //round numbers if close to 1
      for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 3; x++) {
          if ((Trm2[x][y] > .99) & (Trm2[x][y] < 1))
            Trm2[x][y] = 1;
        }
      }
        }
   
    /**
     * workout correct screen co-ords allow for rotation
     */
    private final void calcCoordinates(){
     
      if ((CTM[1][0] == 0) &( (CTM[0][1] == 0))){
       
        i_x = (int) CTM[2][0];
        i_y = (int) CTM[2][1];
     
        i_w =(int) CTM[0][0];
        i_h =(int) CTM[1][1];
        if(i_w<0)
          i_w=-i_w;
       
        if(i_h<0)
          i_h=-i_h;
       
      }else{ //some rotation/skew
        i_w=(int) (Math.sqrt((CTM[0][0] * CTM[0][0]) + (CTM[0][1] * CTM[0][1])));
        i_h =(int) (Math.sqrt((CTM[1][1] * CTM[1][1]) + (CTM[1][0] * CTM[1][0])));
       
        if((CTM[1][0]>0)&(CTM[0][1]<0)){
          i_x = (int) (CTM[2][0]);
          i_y = (int) (CTM[2][1]+CTM[0][1]);
          //System.err.println("AA "+i_w+" "+i_h);
         
        }else if((CTM[1][0]<0)&(CTM[0][1]>0)){
          i_x = (int) (CTM[2][0]+CTM[1][0]);
          i_y = (int) (CTM[2][1]);
          //System.err.println("BB "+i_w+" "+i_h);
        }else if((CTM[1][0]>0)&(CTM[0][1]>0)){
          i_x = (int) (CTM[2][0]);
          i_y = (int) (CTM[2][1]);
          //System.err.println("CC "+i_w+" "+i_h);
        }else{
          //System.err.println("DD "+i_w+" "+i_h);
          i_x = (int) (CTM[2][0]);
          i_y =(int) (CTM[2][1]);
        }
           
      }
     
      //System.err.println(i_x+" "+i_y+" "+i_w+" "+i_h);
      //Matrix.show(CTM);
      //alter to allow for back to front or reversed 
      if ( CTM[1][1]< 0)
        i_y = i_y - i_h;
      if ( CTM[0][0]< 0)
        i_x = i_x - i_w;
     
//ShowGUIMessage.showGUIMessage("",current_image,"xx="+i_x+" "+i_y+" "+i_w+" "+i_h+" h="+current_image.getHeight());
     
 
    }
  //////////////////////////////////////////////////////////////////////////
  /**
   * get y of image (x1,y1 is top left)
   */
  final public int getImageY() {
    return i_y;
  }
  //////////////////////////////////////////////////////////////////////////
  /**
   * get image
   */
  final public BufferedImage getImage() {
    return current_image;
  }
  //////////////////////////////////////////////////////////////////////////
  /**
   * get width of image
   */
  final public int getImageW() {
    return i_w;
  }
  //////////////////////////////////////////////////////////////////////////
  /**
   * get height of image
   */
  final public int getImageH() {
    return i_h;
  }
  //////////////////////////////////////////////////////////////////////////
  /**
   * get X of image (x,y is top left)
   */
  final public int getImageX() {
    return i_x;
  }
 
      /**
       * clip the image
       */
      final private void clipImage(boolean singleScale, Area final_clip, boolean alreadyTurned) {

        //if not working at 72 dpi, alter clip to fit
        if(scale!=1){
          AffineTransform af=AffineTransform.getScaleInstance(scale,scale);
          final_clip.transform(af);
        }
        /**
         * invert the clip
         */
        double shape_x = final_clip.getBounds2D().getX();
        double shape_y = final_clip.getBounds2D().getY();
        //double shape_h = final_clip.getBounds2D().getHeight();

        int image_w = current_image.getWidth();
        int image_h = current_image.getHeight();

        AffineTransform image_at =new AffineTransform();
        image_at.scale(1,-1);
        image_at.translate(0,-current_image.getHeight());
        AffineTransformOp invert= new AffineTransformOp(image_at,  ColorSpaces.hints);

        current_image = invert.filter(current_image,null);

                AffineTransform align_clip = new AffineTransform();

        double dx=-(CTM[2][0])*scale,dy= -((CTM[2][1])*scale);

        if(CTM[1][0]<0)
          dx=dx-CTM[1][0] ;
        if((CTM[0][0]<0)&&(CTM[1][0]>=0))
          dx=dx-CTM[1][0] ;

        if(CTM[0][1]<0)
          dy=dy-CTM[0][1];
        if(CTM[1][1]<0){
          if(CTM[0][1]>0)
            dy=dy-CTM[0][1];
          else if(CTM[1][1]<0)
            dy=dy-CTM[1][1];
        }
        align_clip.translate(dx,dy );

        final_clip.transform(align_clip);

        AffineTransform invert2=new AffineTransform(1/Trm2[0][0],0,0,1/Trm2[1][1],0,0);
        //System.out.println("invert2="+invert2);

                if((!alreadyTurned)||((Trm[1][0]==0)&&(Trm[0][1]==0)))
                final_clip.transform(invert2);

        //co-ords of transformed shape
        //reset sizes to remove area clipped
        int x = (int) final_clip.getBounds().getX();
        int y = (int) final_clip.getBounds().getY();
        int w = (int) final_clip.getBounds().getWidth();
        int h = (int) final_clip.getBounds().getHeight();

                //fix for 'mirror' image on Mac
                if(x<0)
                final_clip.transform(AffineTransform.getTranslateInstance(-x,0));

                /**
         * create inverse of clip and paint on to add transparency
         */
        Area inverseClip =new Area(new Rectangle(0,0,image_w,image_h));
        inverseClip.exclusiveOr(final_clip);
        Graphics2D image_g2 = current_image.createGraphics(); //g2 of canvas
        image_g2.setComposite(AlphaComposite.Clear);
        image_g2.fill(inverseClip);

        AffineTransform image_at2 =new AffineTransform();
        image_at2.scale(1,-1);
        image_at2.translate(0,-current_image.getHeight());
        AffineTransformOp invert3= new AffineTransformOp(image_at2,  ColorSpaces.hints);

                //mac os needs this stage!
        current_image=current_image.getSubimage(0,0,current_image.getWidth(),current_image.getHeight());

                current_image = invert3.filter(current_image,null);

                //Matrix.show(CTM);


                //get image (now clipped )

        //if(count>21)
        //ShowGUIMessage.showGUIMessage("2count="+count,current_image,"2count="+count);
        //count++;

        //check for rounding errors
        if (y < 0) {
          h = h - y;
          y = 0;
        //  System.err.println("Negative");

        }else{

          y=image_h-h-y;

          //allow for fp error
          if(y<0)
            y=0;

        }

        if (x < 0) {
          w = w - x;
          x = 0;
        }

        if (w > image_w)
          w = image_w;
        if (h > image_h)
          h = image_h;

        if (y + h > image_h)
          h = image_h - y;

        if (x + w > image_w)
          w = image_w - x;

                //extract if needed
        if(removeClippedBorder){

          if((x==0)&&(y==0)&&(w==current_image.getWidth())&&(h==current_image.getHeight())){
            //dont bother if no change
          }else{
            try {
              current_image = current_image.getSubimage(x, y, w, h);
            } catch (Exception e) {
              LogWriter.writeLog("Exception " + e + " extracting clipped image with values x="+x+" y="+y+" w="+w+" h="+h+" from image "+current_image);


            }catch(Error err){
            }
          }
        }

        /***/

        //work out new co-ords from shape and current
        double x1, y1;
        if (i_x > shape_x)
          x1 = i_x;
        else
          x1 = shape_x;
        if (i_y > shape_y)
          y1 = i_y;
        else
          y1 = shape_y;

        i_x = (int) x1;
        i_y = (int) y1;
        i_w = w;
        i_h =  h;
      }
 
}
TOP

Related Classes of org.jpedal.images.ImageTransformerDouble

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.