Package org.jpedal.color

Source Code of org.jpedal.color.ICCColorSpace

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


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

import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.image.*;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

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

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


/**
* handle ICCColorSpace
*/
public class ICCColorSpace
extends GenericColorSpace {

  //cache values to speed up translation
  private int[] a1,b1,c1;
 
  private Map cache=new HashMap();

  boolean isCached=false;
 
  /**
   * reset any defaults if reused
   */
  public void reset(){
   
    super.reset();
   
    isConverted=false;
   
    //set cache to -1 as flag
//    a1=new int[256];
//    b1=new int[256];
//    c1=new int[256];
//
//    for(int i=0;i<256;i++){
//      a1[i]=-1;
//      b1[i]=-1;
//      c1[i]=-1;
//
//    }
//
//    cache.clear();
   
    isCached=true;
  }


  public ICCColorSpace(PdfObject colorSpace) {

    //set cache to -1 as flag
    a1=new int[256];
    b1=new int[256];
    c1=new int[256];
         
    for(int i=0;i<256;i++){
      a1[i]=-1;
      b1[i]=-1;
      c1[i]=-1;
     
    }

    value = ColorSpaces.ICC;
    cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);

    byte[] icc_data=colorSpace.getDecodedStream();

    if (icc_data == null){

      if(LogWriter.isOutput())
        LogWriter.writeLog("Error in ICC data");
        }else {
      try{
        cs = new ICC_ColorSpace(ICC_Profile.getInstance(icc_data));
      }catch(Exception e){
        if(LogWriter.isOutput())
          LogWriter.writeLog("[PDF] Problem "+e.getMessage()+" with ICC data ");
        failed=true;
      }
    }

    componentCount=cs.getNumComponents();
  }


  /**
   * set color (in terms of rgb)
   */
  final public void setColor(String[] number_values,int items) {

    //if(isCached)
    //  System.out.println("BsetColor "+size);
   
    float[] colValues=new float[items];

    for(int ii=0;ii<items;ii++)
      colValues[ii]=Float.parseFloat(number_values[ii]);

    setColor(colValues,items);
  }

  /**set color*/
  final public void setColor(float[] operand,int size) {


    //if(isCached)
    //  System.out.println("setColor "+size);
   
        float[] values=new float[size];
    int[] lookup=new int[size];

        rawValues=new float[size];

        for(int i=0;i<size;i++){
      float val=operand[i];

            rawValues[i]=val;

            values[i]=val;
            if(val>1)
          lookup[i]=(int)(val);
            else
      lookup[i]=(int)(val*255);
     
    }

    if(size==3 && (a1[lookup[0]]!=-1) &&
        (b1[lookup[1]]!=-1)&&(c1[lookup[2]]!=-1))
    {
      currentColor=new PdfColor(a1[lookup[0]],b1[lookup[1]],c1[lookup[2]]);
            //System.out.println("cached "+operand[0]+" "+operand[1]+" "+operand[2]+" "+this);
           
    }else if(size==4 && cache.get((lookup[0] << 24) + (lookup[1] << 16) + (lookup[2] << 8) + lookup[3])!=null){

      Object val=cache.get((lookup[0] << 24) + (lookup[1] << 16) + (lookup[2] << 8) + lookup[3]);
      int raw = (Integer) val;
      int r = ((raw >> 16) & 255);
      int g = ((raw >> 8) & 255);
      int b = ((raw) & 255);
     
      currentColor=new PdfColor(r,g,b);
     
    }else{

            try{

          values=cs.toRGB(values);

            }catch(Exception ee){
                //file with invalid values appears to work if we just replace
                float[] newValues={values[0],values[0],values[0]};
                values=newValues;
            }
      currentColor=new PdfColor(values[0],values[1],values[2]);

      if(size==3){
        a1[lookup[0]]=(int)(values[0]*255);
        b1[lookup[1]]=(int)(values[1]*255);
        c1[lookup[2]]=(int)(values[2]*255);

               
      }else if(size==4){ //not used except as flag
       
        int raw = ((int)(values[0]*255) << 16) +
        ((int)(values[1]*255) << 8) +
        (int)(values[2]*255);

        //store values in cache
        cache.put((lookup[0] << 24) + (lookup[1] << 16) + (lookup[2] << 8) + lookup[3], raw);
               
            }
    }
  }

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

        isConverted=true;

    if(componentCount==4)
      return convert4Index(data);
    else
      return data;

  }   

  /**
   * <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>
   */
  public BufferedImage JPEGToRGBImage(
      byte[] data,int w,int h,float[] decodeArray,int pX,int pY, boolean arrayInverted) {

    if(data.length>9 && data[6] == 'J' && data[7] == 'F' && data[8] == 'I' && data[9] == 'F'){
      return nonRGBJPEGToRGBImage(data,w,h, null,pX,pY);
    }else
            return algorithmicICCToRGB(data,w,h,false,pX,pY,decodeArray);

  }

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

    byte[] index=this.getIndexedMap();
   
    if(cs.getNumComponents()==3 || index!=null)
      return super.JPEG2000ToRGBImage(data, w, h, decodeArray, pX, pY);
   
    BufferedImage image;

    ByteArrayInputStream in;

    Raster ras;

    try {
      in = new ByteArrayInputStream(data);

      ImageReader iir = (ImageReader) ImageIO.getImageReadersByFormatName("JPEG2000").next();
      ImageInputStream iin = ImageIO.createImageInputStream(in);


      iir.setInput(iin, true);

      /**
       * indexes are a completely different game
       * CMYK has 4 color components (C,M,Y,K) for each pixel
       * indexed has 1 component pointing to value in lookup table
       * so need a totally different approach
       */
     
     
      if(index!=null){

        //make it RGB
        if(!isIndexConverted()){
          index=convertIndexToRGB(index);
        }

        //get data for image (its an index so just refers to color numbers
        RenderedImage renderimage = iir.readAsRenderedImage(0,iir.getDefaultReadParam());
        ras=renderimage.getData();

        //and build a standard rgb image
        ColorModel cm=new IndexColorModel(8, index.length/3, index, 0, false);
        image = new BufferedImage(cm,(WritableRaster) ras.createCompatibleWritableRaster(), false, null);

        //downsample to reduce size if huge
        image=cleanupImage(image,pX,pY, image.getType());

      }else{ //non-indexed routine
       
        //This works except image is wrong so we read and convert
        image=iir.read(0);
        ras=image.getRaster();

        //apply if set
        if(decodeArray!=null){

          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!=null && decodeArray.length>0){
          }
        }

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

        //generate the rgb image
        WritableRaster rgbRaster;
      if(image.getType()==13){ //indexed variant
          rgbRaster = ColorSpaceConvertor.createCompatibleWritableRaaster(image.getColorModel(), w, h);
          //me does not allow colorconvertop
          CSToRGB = new ColorConvertOp(cs, image.getColorModel().getColorSpace(), ColorSpaces.hints);
          image =new BufferedImage(w,h,image.getType());
        }else{

          if(CSToRGB==null)
            initCMYKColorspace();
          rgbRaster=ColorSpaceConvertor.createCompatibleWritableRaaster(rgbModel,w, h);

          //me does not allow colorconvertop

          CSToRGB = new ColorConvertOp(cs, rgbCS, ColorSpaces.hints);
            CSToRGB.filter(ras, rgbRaster);
         
          image =new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);

        }

        image.setData(rgbRaster);
       
      }
     
      iir.dispose();
      iin.close();
      in.close();

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

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

      ee.printStackTrace();
      throw new PdfException("Exception "+ee+" with JPEG2000 image - please ensure imageio.jar (from JAI library) on classpath");
    } catch (Error ee2) {
      ee2.printStackTrace();

      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem reading JPEG 2000 with error " + ee2);

      throw new PdfException("Error with JPEG2000 image - please ensure imageio.jar (from JAI library) on classpath");
    }

    return image;
  }


  private BufferedImage algorithmicICCToRGB(
      byte[] data, int w, int h,boolean debug, int pX, int pY, float[] decodeArray) {

    BufferedImage image = null;

    ImageReader iir=null;
    ImageInputStream iin=null;

    ByteArrayInputStream in = new ByteArrayInputStream(data);

    try{

      //iir = (ImageReader)ImageIO.getImageReadersByFormatName("JPEG").next();
     
      //suggestion from Carol
            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));

      Raster ras=iir.readRaster(0,null);
     
      //some images need this
      if(iir.getRawImageType(0)==null || alternative==-1)
        return nonRGBJPEGToRGBImage(data,w,h, decodeArray,pX,pY);
     
      ras=cleanupRaster(ras,pX,pY,componentCount);
      w=ras.getWidth();
      h=ras.getHeight();    

      byte[] new_data = new byte[w * h * 3];

      //reuse variable
      data=((DataBufferByte)ras.getDataBuffer()).getData();

      int pixelCount = w * h*3;
      float lastR=0,lastG=0,lastB=0;
      int pixelReached = 0;
      float lastIn1=-1,lastIn2=-1,lastIn3=-1;

      for (int i = 0; i < pixelCount; i = i + 3) {

        float in1 = ((data[i] & 255))/255f;
        float in2 = ((data[1+i] & 255))/255f;
        float in3 = ((data[2+i] & 255))/255f;

        float[] outputValues;
        if((lastIn1==in1)&&(lastIn2==in2)&&(lastIn3==in3)){
          //use existing values  
        }else{//work out new

          if (debug)
            System.out.println(in1+" "+in2+ ' ' +in3);

          float[] inputValues={in1,in2,in3};

          outputValues=cs.toRGB(inputValues);
          outputValues=inputValues;

          //reset values
          lastR=(outputValues[0]*255);
          lastG=(outputValues[1]*255);
          lastB=(outputValues[2]*255);

          lastIn1=in1;
          lastIn2=in2;
          lastIn3=in3;
        }

        new_data[pixelReached++] =(byte) lastR;
        new_data[pixelReached++] = (byte)lastG;
        new_data[pixelReached++] = (byte)lastB;

        /**
        buffer.setElemDouble(pixelReached++,x*outRed);
        buffer.setElemDouble(pixelReached++,x*outGreen);
        buffer.setElemDouble(pixelReached++,x*outBlue);
         */
      }



      try {
        /***/
        int[] bands = {0,1,2};

        DataBuffer db = new DataBufferByte(new_data, new_data.length);
        image =new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);

        Raster raster =Raster.createInterleavedRaster(db,w,h,w * 3,3,bands,null);
        image.setData(raster);

      } catch (Exception e) {
        e.printStackTrace();
       
        if(LogWriter.isOutput())
          LogWriter.writeLog("Exception " + e + " with 24 bit RGB image");
      }

    }catch(Exception e){
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem with color conversion");
     
   
    }

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

Related Classes of org.jpedal.color.ICCColorSpace

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.