Package org.jpedal.color

Source Code of org.jpedal.color.SeparationColorSpace

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
* (C) Copyright 1997-2010, 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


*
* ---------------
* SeparationColorSpace.java
* ---------------
*/

package org.jpedal.color;

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


import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.io.ByteArrayInputStream;
import java.util.*;

/**
* handle Separation ColorSpace and some DeviceN functions
*/
public class SeparationColorSpace extends GenericColorSpace {

  protected GenericColorSpace altCS;

  final static int Black=1009857357;
  final static int PANTONE_BLACK=573970506;
  final private static int Cyan=323563838;
  final private static int Magenta=895186280;
  final public static int Yellow=1010591868;

  protected ColorMapping colorMapper;

    //avoid rereading colorspaces
    protected Map cachedValues=new HashMap();

  private float[] domain;

  /*if we use CMYK*/
  protected int cmykMapping=NOCMYK;

    protected boolean isProcess=false;

  final static protected int NOCMYK=-1;
  final static protected int MYK=1;
  final static protected int CMY=2;
  final static protected int CMK=4;
  final static protected int CY=5;
    final static protected int MY=6;
    final static protected int CM=8;
   
    final static protected int CMYK=7; //use don 6 values where CMYK is first 4

    final static protected int CMYB=9;

  public SeparationColorSpace() {}

  public SeparationColorSpace(PdfObjectReader currentPdfFile,PdfObject colorSpace) {

    value = ColorSpaces.Separation;

    processColorToken(currentPdfFile, colorSpace);
  }

  protected void processColorToken(PdfObjectReader currentPdfFile, PdfObject colorSpace) {

        PdfObject indexed=colorSpace.getDictionary(PdfDictionary.Indexed);
        PdfObject functionObj=colorSpace.getDictionary(PdfDictionary.tintTransform);

    domain = null;

        if(colorSpace.getDictionary(PdfDictionary.Process)!=null)
            isProcess=true;

    //name of color if separation or Components if device and component count
    byte[] name=null;
    byte[][] components=null;
    if(value==ColorSpaces.Separation){
      name=colorSpace.getStringValueAsByte(PdfDictionary.Name);

            if(name!=null)
            components=new byte[][]{name};
      componentCount=1;
    }else{
      components=colorSpace.getStringArray(PdfDictionary.Components);
      componentCount=components.length;
    }

    //test values

    cmykMapping=NOCMYK;

        int[] values=new int[componentCount];
        if(components!=null){
            for(int ii=0;ii<componentCount;ii++){
                values[ii]=PdfDictionary.generateChecksum(1, components[ii].length-1, components[ii]);
            }
        }

        switch(componentCount){

            case 1:
                if(components!=null && (values[0]==Black || values[0]==PANTONE_BLACK)){
                    cmykMapping=Black;
                }

                break;

            case 2:

                if(values[0]==Cyan){
                    if(values[1]==Yellow)
                        cmykMapping=CY;
                    else if(values[1]==Magenta)
                        cmykMapping=CM;
                }else if(values[0]==Magenta && values[1]==Yellow)
                    cmykMapping=MY;

                break;

            case 3:

                if(values[0]==Magenta && values[1]==Yellow && values[2]==Black)
                    cmykMapping=MYK;
                else if(values[0]==Cyan && values[1]==Magenta && values[2]==Yellow)
                    cmykMapping=CMY;
                else if(values[0]==Cyan && values[1]==Magenta && values[2]==Black)
                    cmykMapping=CMK;
                break;

            case 4:

                if(values[0]==Cyan && values[1]==Magenta && values[2]==Yellow && values[3]==Black)
                    cmykMapping=CMYB;
                break;

            case 6:

                if(values[0]==Cyan && values[1]==Magenta && values[2]==Yellow && values[3]==Black)
                    cmykMapping=CMYK;
                break;
        }

    //hard-code myk and cmy
    if(cmykMapping!=NOCMYK){

      altCS=new DeviceCMYKColorSpace();

    }else{

      /**
       * work out colorspace (can also be direct ie /Pattern)
       */
      colorSpace=colorSpace.getDictionary(PdfDictionary.AlternateSpace);

            //System.out.println("Set uncached AlCS "+colorSpace.getObjectRefAsString()+" "+this);
            altCS =ColorspaceFactory.getColorSpaceInstance(currentPdfFile, colorSpace);

            //use alternate as preference if CMYK
            if(altCS.getID()==ColorSpaces.ICC && colorSpace.getParameterConstant(PdfDictionary.Alternate)==ColorSpaces.DeviceCMYK)
                altCS=new DeviceCMYKColorSpace();


    }

    if(name!=null){
      int len=name.length,jj=0,topHex,bottomHex;
      byte[] tempName=new byte[len];
      for(int i=0;i<len;i++){
        if(name[i]=='#'){
          //roll on past #
          i++;

          topHex=name[i];

          //convert to number
          if(topHex>='A' && topHex<='F')
            topHex = topHex - 55
          else if(topHex>='a' && topHex<='f')
            topHex = topHex - 87;
          else if(topHex>='0' && topHex<='9')
            topHex = topHex - 48;

          i++;

          while(name[i]==32 || name[i]==10 || name[i]==13)
            i++;

          bottomHex=name[i];

          if(bottomHex>='A' && bottomHex<='F')
            bottomHex = bottomHex - 55
          else if(bottomHex>='a' && bottomHex<='f')
            bottomHex = bottomHex - 87;
          else if(bottomHex>='0' && bottomHex<='9')
            bottomHex = bottomHex - 48;

          tempName[jj]=(byte) (bottomHex+(topHex<<4));
        }else{
          tempName[jj]=name[i];
        }

        jj++;
      }

      //resize
      if(jj!=len){
        name=new byte[jj];
        System.arraycopy(tempName, 0, name, 0, jj);

      }

      pantoneName=new String(name);
    }

    /**
     * setup transformation
     **/
        if(functionObj==null)
            colorSpace.getDictionary(PdfDictionary.tintTransform);

        if(functionObj==null && indexed!=null)
            functionObj=indexed.getDictionary(PdfDictionary.tintTransform);

    colorMapper=new ColorMapping(currentPdfFile,functionObj);
    domain=functionObj.getFloatArray(PdfDictionary.Domain);

  }

  /**private method to do the calculation*/
  private void setColor(float value){

        try{

            if(this.cmykMapping==Black){ //special case coded in

                float[] newOp={0f,0f,0f, value};
                altCS.setColor(newOp,1);

            }else{
            //optimisation for white
            //if(altCS.getID()==ColorSpaces.DeviceCMYK && value==1.0){
            //    altCS.setColor(new float[]{0,0,0,0},4);
            //}else
          {
                //adjust size if needed
                int elements=1;

                if(domain!=null)
                    elements=domain.length/2;

                float[] values = new float[elements];
                for(int j=0;j<elements;j++)
                    values[j] = value;

                float[] operand =colorMapper.getOperandFloat(values);

                altCS.setColor(operand,operand.length);
            }
            }
    }catch(Exception e){
    }
  }

  /** set color (translate and set in alt colorspace */
  public void setColor(float[] operand,int opCount) {

            setColor(operand[0]);
          
  }

  /** set color (translate and set in alt colorspace */
  public void setColor(String[] operand,int opCount) {

    float[] f=new float[1];
    f[0]=Float.parseFloat(operand[0]);

    setColor(f,1);

  }
 
  /**
   * convert data stream to srgb image
   */
  public BufferedImage JPEGToRGBImage( byte[] data,int ww,int hh,float[] decodeArray,int pX,int pY, boolean arrayInverted) {

    BufferedImage image;
    ByteArrayInputStream in = null;

    ImageReader iir=null;
    ImageInputStream iin=null;

    try {

      //read the image data
      in = new ByteArrayInputStream(data);
     
//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);  
      Raster ras=iir.readRaster(0, null);

      ras=cleanupRaster(ras,pX,pY,1); //note uses 1 not count

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

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

      //special case
      if(this.altCS.getID()==ColorSpaces.DeviceGray){
     
        for(int aa=0;aa<rawData.length;aa++)
          rawData[aa]= (byte) (rawData[aa]^255);
        final int[] bands = {0};
        image=new BufferedImage(w,h,BufferedImage.TYPE_BYTE_GRAY);
        Raster raster =Raster.createInterleavedRaster(new DataBufferByte(rawData, rawData.length),w,h,w,1,bands,null);
 
        image.setData(raster);
       
      }else{
        //convert the image in general case
        image=createImage(w, h, rawData, arrayInverted);
      }
    } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Couldn't read JPEG, not even raster: " + ee);
    }

    try {
      in.close();
      iir.dispose();
      iin.close();
    } catch (Exception ee) {

      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem closing  " + ee);
    }

    return image;

  }
 
  /**
   * convert data stream to srgb image
   */
  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);
        iir.dispose();
        iin.close();
        in.close();
      }catch(Exception e){

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

                e.printStackTrace();
                return null;
      }
     
      image=cleanupImage(image,pX,pY,value);

      w = image.getWidth();
      h = image.getHeight();

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

      //convert the image
      image=createImage(w, h, rawData, false);

    } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Couldn't read JPEG, not even raster: " + ee);
    }

    try {
      in.close();
      iir.dispose();
      //iin.close();
    } catch (Exception ee) {

      if(LogWriter.isOutput())
        LogWriter.writeLog("Problem closing  " + ee);
    }

    return image;

  }

  /**
   * convert separation stream to RGB and return as an image
   */
  public BufferedImage  dataToRGB(byte[] data,int w,int h) {

    BufferedImage image=null;

    try {

      //convert data
      image=createImage(w, h, data, false);

    } catch (Exception ee) {
      image = null;
     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Couldn't convert Separation colorspace data: " + ee);
    }

    return image;

  }

  /**
   * turn raw data into an image
   */
  private BufferedImage createImage(int w, int h, byte[] rgb, boolean arrayInverted) {

    BufferedImage image;
       
    int pixelCount=3*w*h;
    byte[] imageData=new byte[pixelCount];

    //convert data to RGB format
    int byteCount=rgb.length;
    int pixelReached=0;

        //cache table for speed
    float[][] lookuptable=new float[3][256];
    for(int i=0;i<256;i++)
      lookuptable[0][i]=-1;

        for (byte aRgb : rgb) {

            int value = (aRgb & 255);

            if (lookuptable[0][value] == -1) {
                if (arrayInverted)
                    setColor(1f - (value / 255f));
                else
                    setColor(value / 255f);

                lookuptable[0][value] = ((Color) this.getColor()).getRed();
                lookuptable[1][value] = ((Color) this.getColor()).getGreen();
                lookuptable[2][value] = ((Color) this.getColor()).getBlue();

            }

            for (int comp = 0; comp < 3; comp++) {
                imageData[pixelReached] = (byte) lookuptable[comp][value];
                pixelReached++;
            }

        }

    //create the RGB image
    image =new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
    Raster raster = ColorSpaceConvertor.createInterleavedRaster(imageData, w, h);
    image.setData(raster);

    return image;
  }

  /**
   * create rgb index for color conversion
   */
  public byte[] convertIndexToRGB(byte[] data){

        isConverted=true;
       
    byte[] newdata=new byte[3*256]; //converting to RGB so size known

    try {

      int outputReached=0;
      float[] opValues=new float[1];
      Color currentCol=null;
      float[] operand;
      int byteCount=data.length;
      float[] values = new float[componentCount];

      //scan each byte and convert
      for(int i=0;i<byteCount;i=i+componentCount){

        //turn into rgb and store
        if(this.componentCount==1 && value==ColorSpaces.Separation && colorMapper==null){ //separation (fix bug with 1 component DeviceN with second check)
          opValues=new float[1];
          opValues[1]= (data[i] & 255);
          setColor(opValues,1);
          currentCol=(Color)this.getColor();
        }else{ //convert deviceN

          for(int j=0;j<componentCount;j++)
            values[j] = (data[i+j] & 255)/255f;

          operand = colorMapper.getOperandFloat(values);

          altCS.setColor(operand,operand.length);
          currentCol=(Color)altCS.getColor();

        }

        newdata[outputReached]=(byte) currentCol.getRed();
        outputReached++;
        newdata[outputReached]=(byte)currentCol.getGreen();
        outputReached++;
        newdata[outputReached]=(byte)currentCol.getBlue();
        outputReached++;

      }

    } catch (Exception ee) {

     
      if(LogWriter.isOutput())
        LogWriter.writeLog("Exception  " + ee + " converting colorspace");
     
     
    }

    return newdata;   
  }
 
  /**
   * get color
   */
  public PdfPaint getColor() {
   
    return altCS.getColor();
   
  }
 
  /**
   * clone graphicsState
   */
  final public Object clone()
  {
   
    this.setColorStatus();
   
    Object o = null;
    try{
      o = super.clone();
    }catch( Exception e ){
      throw new RuntimeException("Unable to clone object");
    }

    return o;
  }
 
  private void setColorStatus(){
   
    int foreground=altCS.currentColor.getRGB();
   
    r= ((foreground>>16) & 0xFF);
        g= ((foreground>>8) & 0xFF);
        b=((foreground) & 0xFF);

  }
 
  public void restoreColorStatus(){

        altCS.currentColor=new PdfColor(r,g,b);

        //values may now be wrong in cache code so force reset
        altCS.clearCache();
  }

  /**
   * get alt colorspace for separation colorspace
   */
  public GenericColorSpace getAltColorSpace()
  {
    return altCS;
  }

}
TOP

Related Classes of org.jpedal.color.SeparationColorSpace

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.