All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.color.DeviceCMYKColorSpace Maven / Gradle / Ivy

There is a newer version: 20151002
Show newest version
/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2015 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
     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


 *
 * ---------------
 * DeviceCMYKColorSpace.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.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jpedal.JDeliHelper;

import org.jpedal.examples.handlers.DefaultImageHelper;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;

import org.jpedal.exception.PdfException;

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

    private static final long serialVersionUID = 4054062852632000027L;

    private float lastC = -1, lastM=-1, lastY=-1, lastK=-1;

    public  static ColorSpace CMYK;

    /**
     * ensure next setColor will not match with old color as value may be out of
     * sync
     */
    @Override
    public void clearCache() {
        lastC = -1;
    }

    /**
     * initialise CMYK profile
     */
    private void initColorspace() {

        /**
         * load the cmyk profile - I am using the Adobe version from the web.
         * There are lots out there.
         */
        InputStream stream = null;

        try {
            final String profile = System.getProperty("org.jpedal.CMYKprofile");

            if (profile == null) {
                stream = this.getClass().getResourceAsStream("/org/jpedal/res/cmm/cmyk.icm");
            } else {
                try {
                    stream = new FileInputStream(profile);
                } catch (final FileNotFoundException ee) {
                    try {
                        throw new PdfException("PdfException attempting to use user profile " + profile + " Message=" + ee);
                    } catch (PdfException ex) {
                        Logger.getLogger(DeviceCMYKColorSpace.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }

            final ICC_Profile p = ICC_Profile.getInstance(stream);
            CMYK = new ICC_ColorSpace(p);

        } catch (final IOException e) {
            LogWriter.writeLog("Exception " + e);
            
            throw new RuntimeException("Problem setting CMYK Colorspace with message " + e + " Possible cause file cmyk.icm corrupted");
        } finally {
            if (stream != null) {
                try {
                    stream.close();
                } catch (final IOException e) {
                    LogWriter.writeLog("Exception " + e);
                }
            }
        }
    }

    /**
     * setup colorspaces
     */
    public DeviceCMYKColorSpace() {

        componentCount = 4;

        if (CMYK == null) {
            initColorspace();
        }

        cs = CMYK;

        setType(ColorSpaces.DeviceCMYK);

    }

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

        final float[] colValues = new float[items];

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

        setColor(colValues, items);
    }

    /**
     * convert CMYK to RGB as defined by Adobe (p354 Section 6.2.4 in Adobe 1.3
     * spec 2nd edition) and set value
     */
    @Override
    public final void setColor(final float[] operand, final int length) {

        //default of black
        c = 1;
        y = 1;
        m = 1;
        k = 1;

        if (length > 3) {
            //get values
            c = operand[0];
            // the cyan
            m = operand[1];
            // the magenta
            y = operand[2];
            // the yellow
            k = operand[3];
        } else {
            //get values
            if (length > 0) {
                c = operand[0];
            }
            // the cyan
            if (length > 1) {
                m = operand[1];
            }
            // the magenta
            if (length > 2) {
                y = operand[2];
            }
            // the yellow
            if (length > 3) {
                k = operand[3];
            }

        }

        if ((lastC == c) && (lastM == m) && (lastY == y) && (lastK == k)) {
            //no change
        } else {
            rawValues = new float[4];
            rawValues[0] = c;
            rawValues[1] = m;
            rawValues[2] = y;
            rawValues[3] = k;

            lastC = c;
            lastM = m;
            lastY = y;
            lastK = k;

            int cc = (int) (c * 255);
            int mm = (int) (m * 255);
            int yy = (int) (y * 255);
            int kk = (int) (k * 255);

            int[] bb = JDeliHelper.convertCMYKtoRGB(cc, mm, yy, kk);
            if (bb == null) {
                convertCMYKToRGBWithJavaProfiles();
            } else {
                this.currentColor = new PdfColor(bb[0], bb[1], bb[2]);
            }         
        }
    }

    private void convertCMYKToRGBWithJavaProfiles() {
        if (c > .99) {
            c = 1.0f;
        } else if (c < 0.01) {
            c = 0.0f;
        }
        if (m > .99) {
            m = 1.0f;
        } else if (m < 0.01) {
            m = 0.0f;
        }
        if (y > .99) {
            y = 1.0f;
        } else if (y < 0.01) {
            y = 0.0f;
        }
        if (k > .99) {
            k = 1.0f;
        } else if (k < 0.01) {
            k = 0.0f;
        }
        
        //we store values to speedup operation
        float[] rgb = null;
        
        if (rgb == null) {
            final float[] cmykValues = {c, m, y, k};
            rgb = CMYK.toRGB(cmykValues);
            
            //check rounding
            for (int jj = 0; jj < 3; jj++) {
                if (rgb[jj] > .99) {
                    rgb[jj] = 1.0f;
                } else if (rgb[jj] < 0.01) {
                    rgb[jj] = 0.0f;
                }
            }
            
            currentColor = new PdfColor(rgb[0], rgb[1], rgb[2]);
        }
    }
    
    /**
     * 

* Convert DCT encoded image bytestream to sRGB *

*

* It uses the internal Java classes and the Adobe icm to convert CMYK and * YCbCr-Alpha - the data is still DCT encoded. *

*

* The Sun class JPEGDecodeParam.java is worth examining because it contains * lots of interesting comments *

*

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

*/ @Override public final BufferedImage JPEGToRGBImage( final byte[] data, final int w, final int h, final float[] decodeArray, final int pX, final int pY, final boolean arrayInverted, final PdfObject XObject) { return nonRGBJPEGToRGBImage(data, w, h, decodeArray, pX, pY); } /** * default RGB implementation just returns data */ @Override public byte[] dataToRGBByteArray(final byte[] data, final int w, final int h, boolean arrayInverted) { int pixelCount = w * h * 4; final int dataSize = data.length; if (pixelCount > dataSize) { //allow for mis-sized pixelCount = dataSize - 3; } final byte[] output = JDeliHelper.convertCMYK2RGB(w, h, pixelCount, data); if(output!=null){ return output; }else{ return convertCMYK2RGBWithJavaProfiles(w, h, pixelCount, data); } } static byte[] convertCMYK2RGBWithJavaProfiles(final int w, final int h, int pixelCount, final byte[] data) { /** * set colorspaces and color models using profiles if set */ final ColorSpace CMYK = DeviceCMYKColorSpace.getColorSpaceInstance(); int C, M, Y, K, lastC = -1, lastM = -1, lastY = -1, lastK = -1; byte[] rgbData = new byte[w * h * 3]; int j = 0; float[] RGB = {0f, 0f, 0f}; //turn YCC in Buffer to CYM using profile for (int i = 0; i < pixelCount; i += 4) { C = (data[i] & 255); M = (data[i + 1] & 255); Y = (data[i + 2] & 255); K = (data[i + 3] & 255); //cache last value, black and white if (C == lastC && M == lastM && Y == lastY && K == lastK) { //no change so use last value } else if (C == 0 && M == 0 && Y == 0 && K == 0) { RGB = new float[]{1f, 1f, 1f}; } else if (C == 255 && M == 255 && Y == 255 && K == 255) { RGB = new float[]{0f, 0f, 0f}; } else { //new value RGB = CMYK.toRGB(new float[]{C / 255f, M / 255f, Y / 255f, K / 255f}); //flag so we can just reuse if next value the same lastC = C; lastM = M; lastY = Y; lastK = K; } //put back as CMY rgbData[j] = (byte) (RGB[0] * 255f); rgbData[j + 1] = (byte) (RGB[1] * 255f); rgbData[j + 2] = (byte) (RGB[2] * 255f); j += 3; } return rgbData; } /** * convert byte[] datastream JPEG to an image in RGB * * @throws PdfException */ @Override public BufferedImage JPEG2000ToRGBImage(final byte[] data, int w, int h, final float[] decodeArray, final int pX, final int pY, final int d) throws PdfException { BufferedImage image = DefaultImageHelper.JPEG2000ToRGBImage(data, w, h, decodeArray, pX, pY); if (image != null) { return image; } else { return JPEG2000ToImage(data, pX, pY, decodeArray); } } /** * convert Index to RGB */ @Override public final byte[] convertIndexToRGB(final byte[] index) { isConverted = true; return convert4Index(index); } public static ColorSpace getColorSpaceInstance() { ColorSpace CMYK = new DeviceCMYKColorSpace().getColorSpace(); //optional alternative CMYK final String CMYKprofile = System.getProperty("org.jpedal.CMYKprofile"); if (CMYKprofile != null) { try { CMYK = new ICC_ColorSpace(ICC_Profile.getInstance(new FileInputStream(CMYKprofile))); } catch (final IOException e) { throw new RuntimeException("Unable to create CMYK colorspace with " + CMYKprofile + "\nPlease check Path and file valid or use built-in " + e); } } return CMYK; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy