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

org.apache.pdfbox.pdmodel.graphics.color.PDColorState Maven / Gradle / Ivy

Go to download

The Apache PDFBox library is an open source Java tool for working with PDF documents.

There is a newer version: 3.0.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pdfbox.pdmodel.graphics.color;

import java.awt.Color;
import java.awt.Paint;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.io.IOException;
import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.pdmodel.graphics.pattern.PDPatternResources;

/**
 * This class represents a color space and the color value for that colorspace.
 * 
 * @author Ben Litchfield
 * 
 */
public class PDColorState implements Cloneable
{

    /**
     * Log instance.
     */
    private static final Log LOG = LogFactory.getLog(PDColorState.class);

    /**
     * The default color that can be set to replace all colors in {@link ICC_ColorSpace ICC color spaces}.
     * 
     * @see #setIccOverrideColor(Color)
     */
    private static volatile Color iccOverrideColor = null;
    static
    {
        try
        {
            iccOverrideColor = Color.getColor("org.apache.pdfbox.ICC_override_color");
        }
        catch (SecurityException e)
        {
        }
    }

    /**
     * Sets the default color to replace all colors in {@link ICC_ColorSpace ICC color spaces}. This will work around a
     * potential JVM crash caused by broken native ICC color manipulation code in the Sun class libraries.
     * 

* The default override can be specified by setting the color code in * org.apache.pdfbox.ICC_override_color system property (see {@link Color#getColor(String)}. If this * system property is not specified, then the override is not enabled unless this method is explicitly called. * * @param color ICC override color, or null to disable the override * @see PDFBOX-511 * @since Apache PDFBox 0.8.1 */ public static void setIccOverrideColor(Color color) { iccOverrideColor = color; } private PDColorSpace colorSpace = new PDDeviceGray(); private COSArray colorSpaceValue = new COSArray(); private PDPatternResources pattern = null; /** * Cached Java AWT color based on the current color space and value. The value is cleared whenever the color space * or value is set. * * @see #getJavaColor() */ private Color color = null; private Paint paint = null; /** * Default constructor. * */ public PDColorState() { setColorSpaceValue(new float[] { 0 }); } /** * {@inheritDoc} */ public Object clone() { PDColorState retval = new PDColorState(); retval.colorSpace = colorSpace; retval.colorSpaceValue.clear(); retval.colorSpaceValue.addAll(colorSpaceValue); retval.setPattern(getPattern()); return retval; } /** * Returns the Java AWT color based on the current color space and value. * * @return current Java AWT color * @throws IOException if the current color can not be created */ public Color getJavaColor() throws IOException { if (color == null && colorSpaceValue.size() > 0) { color = createColor(); } return color; } /** * Returns the Java AWT paint based on the current pattern. * * @param pageHeight the height of the current page * @return current Java AWT paint * * @throws IOException if the current color can not be created */ public Paint getPaint(int pageHeight) throws IOException { if (paint == null && pattern != null) { paint = pattern.getPaint(pageHeight); } return paint; } /** * Create the current color from the colorspace and values. * * @return The current awt color. * @throws IOException If there is an error creating the color. */ private Color createColor() throws IOException { float[] components = colorSpaceValue.toFloatArray(); try { String csName = colorSpace.getName(); if (PDDeviceRGB.NAME.equals(csName) && components.length == 3) { // for some reason, when using RGB and the RGB colorspace // the new Color doesn't maintain exactly the same values // I think some color conversion needs to take place first // for now we will just make rgb a special case. return new Color(components[0], components[1], components[2]); } else if (PDLab.NAME.equals(csName)) { // transform the color values from Lab- to RGB-space float[] csComponents = colorSpace.getJavaColorSpace().toRGB(components); return new Color(csComponents[0], csComponents[1], csComponents[2]); } else { if (components.length == 1) { if (PDSeparation.NAME.equals(csName)) { // Use that component as a single-integer RGB value return new Color((int) components[0]); } if (PDDeviceGray.NAME.equals(csName)) { // Handling DeviceGray as a special case as with JVM 1.5.0_15 // and maybe others printing on Windows fails with an // ArrayIndexOutOfBoundsException when selecting colors // and strokes e.g. sun.awt.windows.WPrinterJob.setTextColor return new Color(components[0], components[0], components[0]); } } Color override = iccOverrideColor; ColorSpace cs = colorSpace.getJavaColorSpace(); if (cs instanceof ICC_ColorSpace && override != null) { LOG.warn("Using an ICC override color to avoid a potential" + " JVM crash (see PDFBOX-511)"); return override; } else { return new Color(cs, components, 1f); } } } // Catch IOExceptions from PDColorSpace.getJavaColorSpace(), but // possibly also IllegalArgumentExceptions or other RuntimeExceptions // from the potentially complex color management code. catch (Exception e) { Color cGuess; String sMsg = "Unable to create the color instance " + Arrays.toString(components) + " in color space " + colorSpace + "; guessing color ... "; try { switch (components.length) { case 1:// Use that component as a single-integer RGB value cGuess = new Color((int) components[0]); sMsg += "\nInterpretating as single-integer RGB"; break; case 3: // RGB cGuess = new Color(components[0], components[1], components[2]); sMsg += "\nInterpretating as RGB"; break; case 4: // CMYK // do a rough conversion to RGB as I'm not getting the CMYK to work. // http://www.codeproject.com/KB/applications/xcmyk.aspx float r, g, b, k; k = components[3]; r = components[0] * (1f - k) + k; g = components[1] * (1f - k) + k; b = components[2] * (1f - k) + k; r = (1f - r); g = (1f - g); b = (1f - b); cGuess = new Color(r, g, b); sMsg += "\nInterpretating as CMYK"; break; default: sMsg += "\nUnable to guess using " + components.length + " components; using black instead"; cGuess = Color.BLACK; } } catch (Exception e2) { sMsg += "\nColor interpolation failed; using black instead\n"; sMsg += e2.toString(); cGuess = Color.BLACK; } LOG.warn(sMsg, e); return cGuess; } } /** * Constructor with an existing color set. Default colorspace is PDDeviceGray. * * @param csValues The color space values. */ public PDColorState(COSArray csValues) { colorSpaceValue = csValues; } /** * This will get the current colorspace. * * @return The current colorspace. */ public PDColorSpace getColorSpace() { return colorSpace; } /** * This will set the current colorspace. * * @param value The new colorspace. */ public void setColorSpace(PDColorSpace value) { colorSpace = value; // Clear color/paint cache and current pattern color = null; paint = null; pattern = null; } /** * This will get the color space values. Either 1 for gray or 3 for RGB. * * @return The colorspace values. */ public float[] getColorSpaceValue() { return colorSpaceValue.toFloatArray(); } /** * This will get the color space values. Either 1 for gray or 3 for RGB. * * @return The colorspace values. */ public COSArray getCOSColorSpaceValue() { return colorSpaceValue; } /** * This will update the colorspace values. * * @param value The new colorspace values. */ public void setColorSpaceValue(float[] value) { colorSpaceValue.setFloatArray(value); // Clear color/paint cache and current pattern color = null; paint = null; pattern = null; } /** * This will get the current pattern. * * @return The current pattern. */ public PDPatternResources getPattern() { return pattern; } /** * This will update the current pattern. * * @param patternValue The new pattern. */ public void setPattern(PDPatternResources patternValue) { pattern = patternValue; // Clear color/paint cache color = null; paint = null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy