Package org.jpedal.color

Source Code of org.jpedal.color.GenericColorSpace

/**
* ===========================================
* 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


*
* ---------------
* GenericColorSpace.java
* ---------------
*/
package org.jpedal.color;

//standard java
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageInputStream;

import org.jpedal.PdfDecoder;

import org.jpedal.exception.PdfException;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.io.JAIHelper;
import org.jpedal.objects.GraphicsState;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;

import org.jpedal.utils.Strip;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import javax.imageio.metadata.IIOMetadataNode;
import org.w3c.dom.NodeList;

/**
* Provides Color functionality and conversion for pdf
* decoding
*/
public class GenericColorSpace  implements Cloneable, Serializable {

    boolean isConverted=false;

  /**any intent*/
    private String intent=null;

  /** actual raw value*/
    float[] rawValues;

    Map patterns; //holds new PdfObjects

    /**for Patterns*/
  float[][] CTM;

  /**handle shading*/
  float[] inputs;

    /**size for indexed colorspaces*/
    private int size=0;

  /**holds cmyk values if present*/
    float c=-1;
    float y=-1;
    float m=-1;
    float k=-1;

  /**matrices for calculating CIE XYZ colour*/
    float[] W;
    float[] G;
    float[] Ma;
    private float[] B;
    float[] R;

  /**defines rgb colorspace*/
  public static ColorSpace rgbCS;

  public static final String cb = "<color ";

  public static final String ce = "</color>";

  //ID of colorspace (ie DeviceRGB)
    int value = ColorSpaces.DeviceRGB;

  /**conversion Op for translating rasters or images*/
  static ColorConvertOp CSToRGB = null;

  ColorSpace cs;

  PdfPaint currentColor = new PdfColor(0,0,0);

  /**rgb colormodel*/
  static ColorModel rgbModel = null;

  /**currently does nothing but added so we can introduce  profile matching*/
    public static ICC_Profile ICCProfileForRGB =null;


    /**enables optimisations for PDF output - enabled with jvm flag org.jpedal.fasterPNG*/
  public static boolean fasterPNG=false;

  //flag to show problem with colors
    boolean failed=false;

  int alternative=PdfDictionary.Unknown;

    private PdfObject decodeParms=null;

    private boolean hasYCCKimages=false;

    private Object[] cache;

    boolean isPrinting=false;

    public void setPrinting(boolean isPrinting){

        //local handles
        this.isPrinting=isPrinting;

    }

  /**initialise all the colorspaces when first needed */
    protected static void initCMYKColorspace() throws PdfException {

        try {

            if(ICCProfileForRGB ==null){
            rgbModel =
                new ComponentColorModel(
                        rgbCS,
                    new int[] { 8, 8, 8 },
                    false,
                    false,
                    ColorModel.OPAQUE,
                    DataBuffer.TYPE_BYTE);
            }else{
                int compCount=rgbCS.getNumComponents();
                int[] values=new int[compCount];
                for(int i=0;i<compCount;i++)
                    values[i]=8;

                rgbModel =
                new ComponentColorModel( rgbCS,
                    values,
                    false,
                    false,
                    ColorModel.OPAQUE,
                    DataBuffer.TYPE_BYTE);
            }

            /**create CMYK colorspace using icm profile*/
            ICC_Profile p =ICC_Profile.getInstance(GenericColorSpace.class.getResourceAsStream(
            "/org/jpedal/res/cmm/cmyk.icm"));
            ICC_ColorSpace cmykCS = new ICC_ColorSpace(p);

            /**define the conversion. PdfColor.hints can be replaced with null or some hints*/
            CSToRGB = new ColorConvertOp(cmykCS, rgbCS, ColorSpaces.hints);
        } catch (Exception e) {
          if(LogWriter.isOutput())
            LogWriter.writeLog("Exception " + e.getMessage() + " initialising color components");
           
          throw new PdfException("[PDF] Unable to create CMYK colorspace. Check cmyk.icm in jar file");

        }
    }

    protected static Raster readRasterFromJPeg(byte[] data) throws IOException {

        Raster ras=null;
        ImageReader iir=null;
        ImageInputStream iin=null;

        ByteArrayInputStream in = new ByteArrayInputStream(data);

        //suggestion from Carol
        try{
            Iterator iterator = ImageIO.getImageReadersByFormatName("JPEG");

            while (iterator.hasNext()){

                Object o = iterator.next();
                iir = (ImageReader) o;
                if (iir.canReadRaster())
                    break;
            }

            ImageIO.setUseCache(false);

            iin = ImageIO.createImageInputStream((in));
            iir.setInput(iin, true);   //new MemoryCacheImageInputStream(in));

            ras=iir.readRaster(0,null);

        }catch(Exception e){
         
          if(LogWriter.isOutput())
            LogWriter.writeLog("Unable to find JAI jars on classpath");
         
        }finally{
            if(in!=null)
                in.close();

            if(iin!=null){
                iin.flush();
                iin.close();
            }

            if(iir!=null)
                iir.dispose();
        }
        return ras;
    }

    /**
   * reset any defaults if reused
   */
  public void reset(){

    currentColor = new PdfColor(0,0,0);

  }

  //show if problem and we should default to Alt
  public boolean isInvalid(){
    return failed;
  }



    //allow user to replace sRGB colorspace
    static{

      //enable user to disable some checks and used indexed output
      String fasterPNG=System.getProperty("org.jpedal.fasterPNG");
      GenericColorSpace.fasterPNG=fasterPNG!=null && fasterPNG.toLowerCase().equals("true");

        String profile=System.getProperty("org.jpedal.RGBprofile");

        if(profile!=null){
            try{
               ICCProfileForRGB = ICC_Profile.getInstance(new FileInputStream(profile));

            }catch(Exception e){
                e.printStackTrace();
                if(LogWriter.isOutput())
                  LogWriter.writeLog("[PDF] Problem " + e.getMessage() + " with ICC data ");

                if(ICCProfileForRGB==null)
                    throw new RuntimeException("Problem wth RGB profile "+profile+ ' ' +e.getMessage());
            }
        }

        if(ICCProfileForRGB !=null){
            rgbCS=new ICC_ColorSpace(ICCProfileForRGB);
        }else
            rgbCS=ColorSpace.getInstance(ColorSpace.CS_sRGB);

    }

    /**
   * get size
   */
  public int getIndexSize(){
    return size;
  }

  /**
   * get color
   */
  public PdfPaint getColor()
  {
    return currentColor;
  }

  /**return the set Java colorspace*/
  public ColorSpace getColorSpace() {
    return cs;
  }

  GenericColorSpace() {

    cs=rgbCS;
  }

  protected void setAlternateColorSpace(int alt){
    alternative = alt;
  }

  public int getAlternateColorSpace(){
    return alternative;
  }
 
  /**store color setting when we push to stack*/
    int r;
    int g;
    int b;
 
  private void setColorStatus(){
   
    int foreground=this.currentColor.getRGB();
   
    r= ((foreground>>16) & 0xFF);
        g= ((foreground>>8) & 0xFF);
        b=((foreground) & 0xFF);
       
    }
 
  public void restoreColorStatus(){
   
        currentColor=new PdfColor(r,g,b);
       
  }

  /**
   * clone graphicsState
   */
  public Object clone()
  {
    //this.setColorStatus();
   
    Object o = null;
    try{
      o = super.clone();
    }catch( Exception e ){
      throw new RuntimeException("Unable to clone object");
    }

    return o;
  }

  /**any indexed colormap*/
    byte[] IndexedColorMap = null;

  /**pantone name if present*/
    String pantoneName=null;

    /**number of colors*/
    int componentCount=3;

  /**handle to graphics state / only set and used by Pattern*/
    GraphicsState gs;

  int pageWidth,pageHeight;

  /**
   * <p>Convert DCT encoded image bytestream to sRGB</p>
   * <p>It uses the internal Java classes
   * and the Adobe icm to convert CMYK and YCbCr-Alpha - the data is still DCT encoded.</p>
   * <p>The Sun class JPEGDecodeParam.java is worth examining because it contains lots
   * of interesting comments</p>
   * <p>I tried just using the new IOImage.read() but on type 3 images, all my clipping code
   * stopped working so I am still using 1.3</p>
   */
  final protected BufferedImage nonRGBJPEGToRGBImage(
            byte[] data, int w, int h, float[] decodeArray,int pX,int pY) {

        boolean isProcessed=false;

        BufferedImage image = null;
    ByteArrayInputStream in = null;


        ImageReader iir=null;
    ImageInputStream iin=null;

    try {

            if(CSToRGB==null)
            initCMYKColorspace();

            CSToRGB = new ColorConvertOp(cs, rgbCS, ColorSpaces.hints);

            in = new ByteArrayInputStream(data);

            int cmykType=getJPEGTransform(data);

            //suggestion from Carol
            try{
                Iterator iterator = ImageIO.getImageReadersByFormatName("JPEG");

                while (iterator.hasNext())
                {
                    Object o = iterator.next();
                    iir = (ImageReader) o;
                    if (iir.canReadRaster())
                        break;
                }

            }catch(Exception e){
              if(LogWriter.isOutput())
                LogWriter.writeLog("Unable to find JAI jars on classpath");
             
                return null;
            }

            //iir = (ImageReader)ImageIO.getImageReadersByFormatName("JPEG").next();
            ImageIO.setUseCache(false);

            iin = ImageIO.createImageInputStream((in));
            iir.setInput(iin, true);   //new MemoryCacheImageInputStream(in));

            Raster ras=iir.readRaster(0,null);

            //invert
            if(decodeArray!=null){

              //decodeArray=Strip.removeArrayDeleminators(decodeArray).trim();

              if((decodeArray.length==6 && decodeArray[0]==1f && decodeArray[1]==0f &&
                  decodeArray[2]==1f && decodeArray[3]==0f &&
                  decodeArray[4]==1f && decodeArray[5]==0f )||
                  (decodeArray.length>2 &&
                      decodeArray[0]==1f && decodeArray[1]==0)){

                        DataBuffer buf=ras.getDataBuffer();

                        int count=buf.getSize();

                        for(int ii=0;ii<count;ii++)
                           buf.setElem(ii,255-buf.getElem(ii));
              }else if(decodeArray.length==6 &&
                  decodeArray[0]==0f && decodeArray[1]==1f &&
                  decodeArray[2]==0f && decodeArray[3]==1f &&
                  decodeArray[4]==0f && decodeArray[5]==1f){
               // }else if(decodeArray.indexOf("0 1 0 1 0 1 0 1")!=-1){//identity
               // }else if(decodeArray.indexOf("0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0")!=-1){//identity
                }else if(decodeArray!=null && decodeArray.length>0){
                }
            }

            if(cs.getNumComponents()==4){ //if 4 col CMYK of ICC translate

                isProcessed=true;

                try{
                    if(cmykType==2){

                        hasYCCKimages=true;
                        image = ColorSpaceConvertor.iccConvertCMYKImageToRGB(((DataBufferByte)ras.getDataBuffer()).getData(),w,h);

                    }else{

                      ras=cleanupRaster(ras,pX,pY,4);
                      w=ras.getWidth();
                      h=ras.getHeight();

                        /**generate the rgb image*/
                        WritableRaster rgbRaster =rgbModel.createCompatibleWritableRaster(w, h);

                        // if(cmykType!=0)
                        CSToRGB.filter(ras, rgbRaster);
                        image =new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
                        image.setData(rgbRaster);

                        //slower in tests
                        //image=new BufferedImage(rgbModel,rgbRaster,false,null);

                    }
                }catch(Exception e){
                    e.printStackTrace();
                   
                    if(LogWriter.isOutput())
                      LogWriter.writeLog("Problem with JPEG conversion");
                }
            }else if(cmykType!=0){

              image=iir.read(0);

              image=cleanupImage(image,pX,pY,value);

                isProcessed=true;

            }

            //test

            if(!isProcessed){
            /**1.3 version or vanilla version*/
                WritableRaster rgbRaster;

                if (cmykType == 4) { //CMYK

                  ras=cleanupRaster(ras,pX,pY,4);

                  int width = ras.getWidth();
                  int height = ras.getHeight();

                    rgbRaster =rgbModel.createCompatibleWritableRaster(width, height);
                    CSToRGB.filter(ras, rgbRaster);
                    image =new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
                    image.setData(rgbRaster);

                } else { //type 7 - these seem to crash the new 1.4 IO routines as far as I can see

                    boolean isYCC=false;
                    try{
                        IIOMetadata metadata = iir.getImageMetadata(0);
                        String metadataFormat = metadata.getNativeMetadataFormatName();
                        IIOMetadataNode iioNode = (IIOMetadataNode) metadata.getAsTree(metadataFormat);

                        NodeList children = iioNode.getElementsByTagName("app14Adobe");
                        if (children.getLength() > 0) {
                            isYCC=true;
                        }
                    }catch(Exception ee){
                      if(LogWriter.isOutput())
                        LogWriter.writeLog("[PDF] Unable to read metadata on Jpeg "+ee);
                    }

                    if(LogWriter.isOutput())
                      LogWriter.writeLog("COLOR_ID_YCbCr image");

                    if(isYCC){ //sample file debug2/pdf4134.pdf suggests we need this change
                        image=ImageIO.read(new ByteArrayInputStream(data));
                    }else{
                        //try with iccConvertCMYKImageToRGB(byte[] buffer,int w,int h) and delete if works
                        image=ColorSpaceConvertor.algorithmicConvertYCbCrToRGB(((DataBufferByte)ras.getDataBuffer()).getData(),w,h);
                    }

                    image=cleanupImage(image,pX,pY,value);
                    image = ColorSpaceConvertor.convertToRGB(image);
                }
            }

        } catch (Exception ee) {
      image = null;
            ee.printStackTrace();
           
            if(LogWriter.isOutput())
              LogWriter.writeLog("Couldn't read JPEG, not even raster: " + ee);
        }catch(Error err ){
          if(iir!=null)
        iir.dispose();
      if(iin!=null){
        try {
          iin.flush();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }

    try {
      in.close();
      iir.dispose();
      iin.close();
    } catch (Exception ee) {
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem closing  " + ee);
    }

    return image;

  }

  protected static BufferedImage cleanupImage(BufferedImage image,int pX, int pY, int colorspaceType){

   
      try{
    final boolean marksNewCode=true;

    int imageType=image.getType();

    if(getSampling(image.getWidth(), image.getHeight(), pX, pY)<=1 || imageType==BufferedImage.TYPE_CUSTOM)
      return image;

    if(marksNewCode && imageType==BufferedImage.TYPE_3BYTE_BGR){
      return cleanupBGRImage(image, pX, pY);
    }else{
      if(imageType==5)
        image= ColorSpaceConvertor.convertToRGB(image);

      Raster ras=cleanupRaster(image.getData(),pX, pY, image.getColorModel().getNumColorComponents());


      image =new BufferedImage(ras.getWidth(),ras.getHeight(),image.getType());
      image.setData(ras);

          return image;
        }

      }catch(Error err){
        if(LogWriter.isOutput())
          LogWriter.writeLog("[PDF] Error in cleanupImage "+err);
      }

      return image;
  }

  private static int getSampling(int w, int h,int pX, int pY){

    int sampling=1; //keep as multiple of 2
    int newW=w,newH=h;

    if(pX>0 && pY>0){

      int smallestH=pY<<2; //double so comparison works
      int smallestW=pX<<2;

      //cannot be smaller than page
      while(newW>smallestW && newH>smallestH){
        sampling=sampling<<1;
        newW=newW>>1;
        newH=newH>>1;
      }

      int scaleX=w/pX;
      if(scaleX<1)
        scaleX=1;

      int scaleY=h/pY;
      if(scaleY<1)
        scaleY=1;

      //choose smaller value so at least size of page
      sampling=scaleX;
      if(sampling>scaleY)
        sampling=scaleY;
    }

    return sampling;
  }

  protected static Raster cleanupRaster(Raster ras,int pX,int pY,int comp) {

    byte[] buffer=null;
    int[] intBuffer=null;
    int type=0;
    DataBuffer data=ras.getDataBuffer();
    if(data instanceof DataBufferInt)
      type=1;
    else
      type=0;

    if(type==1)
      intBuffer=((DataBufferInt)data).getData();
    else{
      int layerCount=ras.getNumBands();
      if(layerCount==comp){
        buffer=((DataBufferByte)data).getData();
      }else if(layerCount==1){
        byte[] rawBuffer=((DataBufferByte)ras.getDataBuffer()).getData();
        int size=rawBuffer.length;
        int realSize=size*comp;
        int j=0,i=0;
        buffer=new byte[realSize];
        while(true){
          for(int a=0;a<comp;a++){
            buffer[j]=rawBuffer[i];
            j++;
          }
          i++;

          if(i>=size)
            break;
        }
      }else{
      }
    }

    int sampling=1; //keep as multiple of 2

    int w=ras.getWidth();
    int h=ras.getHeight();

    int newW=w,newH=h;

    if(pX>0 && pY>0){

      int smallestH=pY<<2; //double so comparison works
      int smallestW=pX<<2;

      //cannot be smaller than page
      while(newW>smallestW && newH>smallestH){
        sampling=sampling<<1;
        newW=newW>>1;
        newH=newH>>1;
      }

      int scaleX=w/pX;
      if(scaleX<1)
        scaleX=1;

      int scaleY=h/pY;
      if(scaleY<1)
        scaleY=1;

      //choose smaller value so at least size of page
      sampling=scaleX;
      if(sampling>scaleY)
        sampling=scaleY;
    }

    //switch to 8 bit and reduce bw image size by averaging
    if(sampling>1){

      newW=w/sampling;
      newH=h/sampling;

      int x=0,y=0,xx=0,yy=0,jj=0,origLineLength=w;
      try{

        byte[] newData=new byte[newW*newH*comp];

        if(type==0)
          origLineLength= w*comp;

        for(y=0;y<newH;y++){
          for(x=0;x<newW;x++){

            //allow for edges in number of pixels left
            int wCount=sampling,hCount=sampling;
            int wGapLeft=w-x;
            int hGapLeft=h-y;
            if(wCount>wGapLeft)
              wCount=wGapLeft;
            if(hCount>hGapLeft)
              hCount=hGapLeft;

            for(jj=0;jj<comp;jj++){
              int byteTotal=0,count=0;
              //count pixels in sample we will make into a pixel (ie 2x2 is 4 pixels , 4x4 is 16 pixels)
              for(yy=0;yy<hCount;yy++){
                for(xx=0;xx<wCount;xx++){
                  if(type==0)
                    byteTotal=byteTotal+(buffer[((yy+(y*sampling))*origLineLength)+(((x*sampling*comp)+(xx*comp)+jj))] & 255);
                  else
                    byteTotal=byteTotal+((intBuffer[((yy+(y*sampling))*origLineLength)+(x*sampling)+xx]>>(8*(2-jj))) & 255);

                  count++;
                }
              }

              //set value as white or average of pixels
              if(count>0)
                newData[jj+(x*comp)+(newW*y*comp)]=(byte)((byteTotal)/count);
            }
          }
        }

        int[] bands=new int[comp];
        for(int jj2=0;jj2<comp;jj2++)
          bands[jj2]=jj2;


        ras=Raster.createInterleavedRaster(new DataBufferByte(newData,newData.length), newW, newH, newW*comp, comp, bands, null);

      }catch(Exception e){

        e.printStackTrace();
       
        if(LogWriter.isOutput())
          LogWriter.writeLog("Problem with Image");
      }

    }

    return ras;
  }

  private static BufferedImage cleanupBGRImage(BufferedImage img, int pX, int pY) {

    //hack to fix bug on Linux (also effects Windows 1.5 so disabled)
    if(System.getProperty("java.version").startsWith("1.5")){     
    //if(PdfDecoder.isRunningOnLinux && System.getProperty("java.version").startsWith("1.5")){
      return img;
    }

    Raster ras= img.getData();
    int comp=img.getColorModel().getNumColorComponents();

    byte[] buffer=null;
    int[] intBuffer=null;
    int type=0;
    DataBuffer data=ras.getDataBuffer();
    if(data instanceof DataBufferInt)
      type=1;
    else
      type=0;

    if(type==1)
      intBuffer=((DataBufferInt)data).getData();
    else{
      int layerCount=ras.getNumBands();
      if(layerCount==comp){
        buffer=((DataBufferByte)data).getData();
      }else if(layerCount==1){
        byte[] rawBuffer=((DataBufferByte)ras.getDataBuffer()).getData();
        int size=rawBuffer.length;
        int realSize=size*comp;
        int j=0,i=0;
        buffer=new byte[realSize];
        while(true){
          for(int a=0;a<comp;a++){
            buffer[j]=rawBuffer[i];
            j++;
          }
          i++;

          if(i>=size)
            break;
        }
      }else{
      }
    }

    int sampling=1; //keep as multiple of 2

    int w=ras.getWidth();
    int h=ras.getHeight();


    int newW=w,newH=h;

    if(pX>0 && pY>0){

      int smallestH=pY<<2; //double so comparison works
      int smallestW=pX<<2;

      //cannot be smaller than page
      while(newW>smallestW && newH>smallestH){
        sampling=sampling<<1;
        newW=newW>>1;
        newH=newH>>1;
      }

      int scaleX=w/pX;
      if(scaleX<1)
        scaleX=1;

      int scaleY=h/pY;
      if(scaleY<1)
        scaleY=1;

      //choose smaller value so at least size of page
      sampling=scaleX;
      if(sampling>scaleY)
        sampling=scaleY;
    }

    //switch to 8 bit and reduce bw image size by averaging
    if(sampling>1){

      WritableRaster newRas=((WritableRaster)ras);

      newW=w/sampling;
      newH=h/sampling;

      int x=0,y=0,xx=0,yy=0,jj=0,origLineLength=w;
      try{


        int[] newData=new int[comp];

        if(type==0)
          origLineLength= w*comp;

        for(y=0;y<newH;y++){
          for(x=0;x<newW;x++){

            //allow for edges in number of pixels left
            int wCount=sampling,hCount=sampling;
            int wGapLeft=w-x;
            int hGapLeft=h-y;
            if(wCount>wGapLeft)
              wCount=wGapLeft;
            if(hCount>hGapLeft)
              hCount=hGapLeft;

            for(jj=0;jj<comp;jj++){
              int byteTotal=0,count=0;
              //count pixels in sample we will make into a pixel (ie 2x2 is 4 pixels , 4x4 is 16 pixels)
              for(yy=0;yy<hCount;yy++){
                for(xx=0;xx<wCount;xx++){
                  if(type==0)
                    byteTotal=byteTotal+(buffer[((yy+(y*sampling))*origLineLength)+(((x*sampling*comp)+(xx*comp)+jj))] & 255);
                  else
                    byteTotal=byteTotal+((intBuffer[((yy+(y*sampling))*origLineLength)+(x*sampling)+xx]>>(8*(2-jj))) & 255);

                  count++;
                }
              }

              //set value as white or average of pixels
              if(count>0){
                if(jj==0)
                  newData[2]=((byteTotal)/count);
                else if(jj==2)
                  newData[0]=((byteTotal)/count);
                else
                  newData[jj]=((byteTotal)/count);

              }

            }

            //write back into ras
            newRas.setPixels(x, y,1,1, newData);//changed to setPixels from setPixel for JAVA ME

            //System.out.println(x+"/"+newW+" "+y+"/"+newH+" "+newData[0]+" "+newData[1]);
          }
        }

        //put back data and trim
        img=new BufferedImage(newW,newH,img.getType());
        img.setData(newRas);
        //img=img.getSubimage(0,0,newW,newH); slower so replaced

      }catch(Exception e){

        e.printStackTrace();
        if(LogWriter.isOutput())
          LogWriter.writeLog("Problem with Image");
      }

    }

    return img;
  }

  /**Toms routine to read the image type - you can also use
   * int colorType = decoder.getJPEGDecodeParam().getEncodedColorID();
   */
  private static int getJPEGTransform(byte[] data) {
    int xform = 0;

    for (int i=0,imax=data.length-2; i<imax; ) {

      int type = data[i+1] & 0xff// want unsigned bytes!
      //out_.println("+"+i+": "+Integer.toHexString(type)/*+", len="+len*/);
      i += 2// 0xff and type

      if (type==0x01 || (0xd0 <= type&&type <= 0xda)) {

      } else if (type==0xda) {
        i = i + ((data[i]&0xff)<<8) + (data[i+1]&0xff);
        while (true) {
          for ( ; i<imax; i++) if ((data[i]&0xff)==0xff && data[i+1]!=0) break;
          int rst = data[i+1]&0xff;
          if (0xd0 <= rst&&rst <= 0xd7) i+=2; else break;
        }

      } else {
        /*if (0xc0 <= type&&type <= 0xcf) {  // SOF
         Nf = data[i+7] & 0xff;  // 1, 3=YCbCr, 4=YCCK or CMYK
         } else*/ if (type == 0xee) {  // Adobe
           if (data[i+2]=='A' && data[i+3]=='d' && data[i+4]=='o' && data[i+5]=='b' && data[i+6]=='e') { xform = data[i+13]&0xff; break; }
         }
         i = i + ((data[i]&0xff)<<8) + (data[i+1]&0xff);
      }
    }

    return xform;
  }


  public void setIndex(byte[] IndexedColorMap,int size) {

    //    set the data for an object
    this.IndexedColorMap = IndexedColorMap;
    this.size=size;

  //  System.out.println("Set index ="+IndexedColorMap);
  }

  public void setIndex(String CMap,String name,int count) {

    StringBuffer rawValues = new StringBuffer();
    this.size=count;

        //see if hex or octal values and make a lisr
    if (CMap.startsWith("(\\")) {

      //get out the octal values to hex
      StringTokenizer octal_values =new StringTokenizer(CMap, "(\\)");

      while (octal_values.hasMoreTokens()) {
        int next_value = Integer.parseInt(octal_values.nextToken(), 8);
        String hex_value = Integer.toHexString(next_value);
        //pad with 0 if required
        if (hex_value.length() < 2)
          rawValues.append('0');

        rawValues.append(hex_value);
      }
    } else if (CMap.startsWith("(")) {

      //should never happen as remapped in ObjectReader

    } else {

      //get rest of hex data minus any <>
      if (CMap.startsWith("<"))
        CMap =CMap.substring(1, CMap.length() - 1).trim();
      rawValues = new StringBuffer(CMap);

    }

    //workout components size
    int total_components = 1;
    if ((name.contains("RGB"))|(name.contains("ICC")))
      total_components = 3;
    else if (name.contains("CMYK"))
      total_components = 4;

    IndexedColorMap = new byte[(count + 1) * total_components];

    //make sure no spaces in array
    rawValues=Strip.stripAllSpaces(rawValues);

        //put into lookup array
    for (int entries = 0; entries < count + 1; entries++) {
      for (int comp = 0; comp < total_components; comp++) {
        int p = (entries * total_components * 2) + (comp * 2);

        int col_value =Integer.parseInt(rawValues.substring(p, p + 2),16);
        IndexedColorMap[(entries * total_components) + comp] =(byte) col_value;

      }
    }
    }

  /**
   * lookup a component for index colorspace
   */
  protected int getIndexedColorComponent(int count) {
    int value =  255;

    if(IndexedColorMap!=null){
      value=IndexedColorMap[count];

      if (value < 0)
        value = 256 + value;

    }
    return value;

  }

  /**return indexed COlorMap
     */
  public byte[] getIndexedMap() {

    //return IndexedColorMap;
    /**/
    if(IndexedColorMap==null)
      return null;

    int size=IndexedColorMap.length;
    byte[] copy=new byte[size];
    System.arraycopy(IndexedColorMap, 0, copy, 0, size);

    return copy;
    /**/
  }

  /**
   * convert color value to sRGB color
   */
  public void setColor(String[] value,int operandCount){

  }


  /**
   * convert color value to sRGB color
   */
  public void setColor(float[] value,int operandCount){


  }


    /**
   * convert byte[] datastream JPEG to an image in RGB
   */
  public BufferedImage JPEGToRGBImage(byte[] data,int w,int h,float[] decodeArray,int pX,int pY, boolean arrayInverted) {


    BufferedImage image = null;
    ByteArrayInputStream bis=null;

    try {


      /**1.4 code*/
      //
      bis=new ByteArrayInputStream(data);
      /**if(PdfDecoder.use13jPEGConversion){
        com.sun.image.codec.jpeg.JPEGImageDecoder decoder =com.sun.image.codec.jpeg.JPEGCodec.createJPEGDecoder(bis);
        image = decoder.decodeAsBufferedImage();
        decoder =null;
      }else{/**/
      ImageIO.setUseCache(false);
      image =ImageIO.read(bis);
      //}
     
      if(image!=null && !fasterPNG){

        if(value!=ColorSpaces.DeviceGray) //crashes Linux
            image=cleanupImage(image,pX,pY,value);
       
        if(value!=ColorSpaces.DeviceGray)
          image=ColorSpaceConvertor.convertToRGB(image);
       
      }

        } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem reading JPEG: " + ee);
     
      ee.printStackTrace();
    }

    if(bis!=null){
      try {
        bis.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

        if(arrayInverted && this.value ==ColorSpaces.DeviceGray ) {

            DataBufferByte rgb = (DataBufferByte) image.getRaster().getDataBuffer();
      byte[] rawData=rgb.getData();

            for(int aa=0;aa<rawData.length;aa++){  //flip the bytes
                rawData[aa]= (byte) (rawData[aa]^255);
            }

            image.setData(Raster.createRaster(image.getSampleModel(),new DataBufferByte(rawData,rawData.length),null));
        }

    return image;
  }

    /**
   * convert byte[] datastream JPEG to an image in RGB
   * @throws PdfException
   */
  public BufferedImage  JPEG2000ToRGBImage(byte[] data,int w,int h,float[] decodeArray,int pX,int pY) throws PdfException{

        BufferedImage image = null;

    ByteArrayInputStream in = null;
        ImageReader iir;

    try {
      in = new ByteArrayInputStream(data);

      /**1.4 code*/
      //standard java 1.4 IO

      iir = (ImageReader)ImageIO.getImageReadersByFormatName("JPEG2000").next();

      } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem reading JPEG 2000: " + ee);

            String message="Exception "+ee+" with JPeg 2000 Image from iir = (ImageReader)ImageIO.getImageReadersByFormatName(\"JPEG2000\").next();";


            if(!JAIHelper.isJAIused())
            message="JPeg 2000 Images and JAI not setup.\nYou need both JAI and imageio.jar on classpath, " +
        "and the VM parameter -Dorg.jpedal.jai=true switch turned on";

            throw new PdfException(message);
        }

        if(iir==null)
        return null;

        try{
            //  ImageIO.setUseCache(false);
            ImageInputStream iin = ImageIO.createImageInputStream(in);

            try{
                iir.setInput(iin, true);   //new MemoryCacheImageInputStream(in));

                image = iir.read(0);

                //does not work correctly if indexed so we manipulate the data
                //if you need to alter check  the images on page 42, 53, 71, 80, 89, 98, 107 and 114 are displayed in black
                //infinite/Plumbing_Fixtures_2_V1_replaced.pdf
                byte[] index = getIndexedMap();
                if(index!=null && value==ColorSpaces.DeviceRGB){

                    data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
                    image=ColorSpaceConvertor.convertIndexedToFlat(8,w, h, data, index,false,false);

                }
            }catch(Exception e){

                if(LogWriter.isOutput())
                    LogWriter.writeLog("Problem reading JPEG 2000: " + e);

                e.printStackTrace();
                image=null;
            }finally {
               iir.dispose();
               iin.close();
               in.close();
            }

            if(image!=null){

                image=cleanupImage(image,pX,pY,value);

                //ensure white background
                if(image.getType()== BufferedImage.TYPE_BYTE_INDEXED){
                    BufferedImage oldImage=image;
                    int newW=image.getWidth();
                    int newH=image.getHeight();
                    image=new BufferedImage(newW, newH, BufferedImage.TYPE_INT_RGB);
                    Graphics2D g2= (Graphics2D) image.getGraphics();
                    g2.setPaint(Color.WHITE);
                    g2.fillRect(0,0,newW,newH);
                    g2.drawImage(oldImage,0,0,null);

                }

                image=ColorSpaceConvertor.convertToRGB(image);

            }
        } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem reading JPEG 2000: " + ee);

            String message="Exception "+ee+" with JPeg 2000 Image";

            if(!JAIHelper.isJAIused())
            message="JPeg 2000 Images and JAI not setup.\nYou need both JAI and imageio.jar on classpath, " +
        "and the VM parameter -Dorg.jpedal.jai=true switch turned on";

            throw new PdfException(message);
      //ee.printStackTrace();
    } catch (Error ee2) {
      image = null;
            ee2.printStackTrace();
           
            if(LogWriter.isOutput())
              LogWriter.writeLog("Problem reading JPEG 2000: " + ee2);

      throw new PdfException("JPeg 2000 Images need both JAI (imageio.jar) on classpath, " +
        "and the VM parameter -Dorg.jpedal.jai=true switch turned on");
      //ee.printStackTrace();
    }

    return image;
  }

  /**
   * convert color content of data to sRGB data
    */
  public BufferedImage dataToRGB(byte[] data,int w,int h){

      BufferedImage image =new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
      Raster raster = ColorSpaceConvertor.createInterleavedRaster(data,w,h);
      image.setData(raster);

      return image;
  }

  /**
   * convert image to sRGB image
    */
  public static BufferedImage BufferedImageToRGBImage(BufferedImage image){

      return image;
  }

  /**get colorspace ID*/
  public int getID(){
    return value;
  }

  /**
   * create a CIE values for conversion to RGB colorspace
   */
  final public void setCIEValues(float[] W,float[] B,float[] R,float[] Ma, float[] G){

    /**set to CIEXYZ colorspace*/
    cs = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);

    //set values
    this.G = G;
    this.Ma = Ma;
    this.W = W;
    this.B = B;
    this.R = R;

  }

  /**
   * convert 4 component index to 3
    */
  final protected byte[] convert4Index(byte[] data){
    return convertIndex(data,4);
  }

  /**
   * convert 4 component index to 3
    */
    private byte[] convertIndex(byte[] data, int compCount){

        if(compCount==4 && this.value==ColorSpaces.DeviceCMYK){

            int len=data.length;

            byte[] rgb=new byte[len*3/4];
            int j2=0;

            for(int ii=0;ii<len;ii=ii+4){

                float[] vals=new float[4];
                for(int j=0;j<4;j++)
                vals[j]=(data[ii+j] & 255)/255f;
                this.setColor(vals,4);

                int foreground=this.currentColor.getRGB();
                rgb[j2]=(byte) ((foreground>>16) & 0xFF);
                rgb[j2+1]=(byte) ((foreground>>8) & 0xFF);
                rgb[j2+2]=(byte) ((foreground) & 0xFF);

                j2=j2+3;
                if(len-4-ii<4)
                    ii=len;
            }

            return rgb;
        }

    try {

      /**turn it into a BufferedImage so we can convert then extract the data*/
      int width = data.length / compCount;
      int height = 1;
      DataBuffer db = new DataBufferByte(data, data.length);
      int[] bands;
      WritableRaster raster;
            DataBuffer convertedData =null;

      int[] bands4 = { 0, 1, 2, 3 };
      int[] bands3 = { 0, 1, 2};
      if(compCount==4)
        bands=bands4;
      else
        bands=bands3;

            {
                raster =Raster.createInterleavedRaster(db,width,height,width * compCount,compCount,bands,null);

                if(CSToRGB==null)
                    initCMYKColorspace();
                CSToRGB = new ColorConvertOp(cs, rgbCS, ColorSpaces.hints);

                WritableRaster rgbRaster =
                    rgbModel.createCompatibleWritableRaster(width, height);

                CSToRGB.filter(raster, rgbRaster);

                convertedData = rgbRaster.getDataBuffer();

                /**put into byte array*/
                int size = width * height * 3;
                data = new byte[size];


                for (int ii = 0; ii < size; ii++){
                    data[ii] = (byte) convertedData.getElem(ii);
                }
            }
    } catch (Exception ee) {
      if(LogWriter.isOutput())
        LogWriter.writeLog("Exception  " + ee + " converting colorspace");
    }

    return data;
  }

  /**
   * convert Index to RGB
    */
  public byte[] convertIndexToRGB(byte[] index){

    return index;
  }

  /**
   * get an xml string with the color info
   */
  public String getXMLColorToken(){

    String colorToken="";

    //only cal if not set
    if(c==-1){ //approximate
      if(currentColor instanceof Color){
        Color col=(Color)currentColor;
        float c=(255-col.getRed())/255f;
        float m=(255-col.getGreen())/255f;
        float y=(255-col.getBlue())/255f;
        float k=c;
        if(k<m)
          k=m;
        if(k<y)
          k=y;

        if(pantoneName==null)
            colorToken=GenericColorSpace.cb+"C='"+c+"' M='"+m+"' Y='"+y+"' K='"+k+"' >";
        else
            colorToken=GenericColorSpace.cb+"C='"+c+"' M='"+m+"' Y='"+y+"' K='"+k+"' pantoneName='"+pantoneName+"' >";
      }else{
        colorToken=GenericColorSpace.cb+"type='shading'>";
      }
    }else{
        if(pantoneName==null)
          colorToken=GenericColorSpace.cb+"C='"+c+"' M='"+m+"' Y='"+y+"' K='"+k+"' >";
      else
          colorToken=GenericColorSpace.cb+"C='"+c+"' M='"+m+"' Y='"+y+"' K='"+k+"' pantoneName='"+pantoneName+"' >";
    }

    return colorToken;
  }

  /**
   * pass in list of patterns
   */
  public void setPattern(Map patterns,int pageWidth, int pageHeight,float[][] CTM) {

        this.patterns=patterns;

        this.pageWidth=pageWidth;
        this.pageHeight=pageHeight;
        this.CTM=CTM;
        //System.out.println("set pattern called");
  }

  /** used by generic decoder to asign color*/
  public void setColor(PdfPaint col) {
    this.currentColor=col;
  }

  /** used by generic decoder to assign color if invisible*/
  public void setColorIsTransparent() {
    this.currentColor=new PdfColor(255,0,0,0);
  }

  /**return number of values used for color (ie 3 for rgb)*/
  public int getColorComponentCount() {

    return componentCount;
  }

  /**pattern colorspace needs access to graphicsState*/
  public void setGS(GraphicsState currentGraphicsState) {

    this.gs=currentGraphicsState;

  }

  public void setIntent(String intent) {
    this.intent = intent;
  }
    public String getIntent() {
    return intent;
  }


  /**return raw values - only currently works for CMYK*/
  public float[] getRawValues() {
    return rawValues;
  }

    /**
     * flag to show if YCCK image decoded so we can draw attention to user
     * @return
     */
    public boolean isImageYCCK() {
        return hasYCCKimages;
    }

    public void setDecodeParms(PdfObject parms) {
        this.decodeParms=parms;
    }

    public boolean isIndexConverted() {
        return isConverted;
    }

    private static final int multiplier=100000;

    public Color getCachedShadingColor(float val) {

        if(cache==null)
            return null;
        else
            return (Color) cache[(int) (val * multiplier)];
    }

    public void setShadedColor(float val, Color col) {

        if(cache==null)
        cache=new Object[multiplier+1];

        cache[((int) (val * multiplier))]=col;
    }

    /**
     * method to flush any caching values for cases where may need resetting (ie in CMYK where restore will render
     * lastvalues in setColor used for caching invalid
     */
    public void clearCache() {

    }

    public static ColorSpace getColorSpaceInstance() {

        ColorSpace rgbCS=ColorSpace.getInstance(ColorSpace.CS_sRGB);

        String profile=System.getProperty("org.jpedal.RGBprofile");

        if(profile!=null){
            try{
                rgbCS=new ICC_ColorSpace(ICC_Profile.getInstance(new FileInputStream(profile)));

                System.out.println("use "+profile);
            }catch(Exception e){
                e.printStackTrace();
                if(LogWriter.isOutput())
                    LogWriter.writeLog("[PDF] Problem " + e.getMessage() + " with ICC data ");
            }
        }

        return rgbCS;
    }
}
TOP

Related Classes of org.jpedal.color.GenericColorSpace

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.