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

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

The newest version!
/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/java-pdf-library-support/
 *
 * (C) Copyright 1997-2013, 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


 *
 * ---------------
 * 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.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

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 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 = null;

	/**
	 * ensure next setColor will not match with old color as value may be out of sync
	 */
	@Override
	public void clearCache() {
		this.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 {

			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 (Exception ee) {
					throw new PdfException("PdfException attempting to use user profile " + profile + " Message=" + ee);
				}
			}

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

		}
		catch (Exception e) {
			if (LogWriter.isOutput()) 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 (IOException e) {
					if (LogWriter.isOutput()) LogWriter.writeLog("Exception " + e);
				}
			}
		}
	}

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

		this.componentCount = 4;

		if (CMYK == null) initColorspace();

		this.cs = CMYK;

		this.value = ColorSpaces.DeviceCMYK;
	}

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

		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
	final public void setColor(float[] operand, int length) {

		boolean newVersion = true;

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

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

		}

		float r, g, b;
		if ((this.lastC == this.c) && (this.lastM == this.m) && (this.lastY == this.y) && (this.lastK == this.k)) {}
		else {

			// store values
			this.rawValues = new float[4];
			this.rawValues[0] = this.c;
			this.rawValues[1] = this.m;
			this.rawValues[2] = this.y;
			this.rawValues[3] = this.k;

			if (!newVersion) {
				// convert the colours the old way
				r = (this.c + this.k);
				if (r > 1) r = 1;
				g = (this.m + this.k);
				if (g > 1) g = 1;
				b = (this.y + this.k);
				if (b > 1) b = 1;

				// set the colour
				this.currentColor = new PdfColor((int) (255 * (1 - r)), (int) (255 * (1 - g)), (int) (255 * (1 - b)));

			}
			else
				if ((this.c == 0) && (this.y == 0) && (this.m == 0) && (this.k == 0)) {
					this.currentColor = new PdfColor(1.0f, 1.0f, 1.0f);

				}
				else {
					if (this.c > .99) this.c = 1.0f;
					else
						if (this.c < 0.01) this.c = 0.0f;
					if (this.m > .99) this.m = 1.0f;
					else
						if (this.m < 0.01) this.m = 0.0f;
					if (this.y > .99) this.y = 1.0f;
					else
						if (this.y < 0.01) this.y = 0.0f;
					if (this.k > .99) this.k = 1.0f;
					else
						if (this.k < 0.01) this.k = 0.0f;

					// we store values to speedup operation
					float[] rgb = null;

					if (rgb == null) {
						float[] cmykValues = { this.c, this.m, this.y, this.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;
						}
					}
					this.currentColor = new PdfColor(rgb[0], rgb[1], rgb[2]);

				}
			this.lastC = this.c;
			this.lastM = this.m;
			this.lastY = this.y;
			this.lastK = this.k;
		}
	}

	/**
	 * 

* 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 final public BufferedImage JPEGToRGBImage(byte[] data, int w, int h, float[] decodeArray, int pX, int pY, boolean arrayInverted, PdfObject XObject) { return nonRGBJPEGToRGBImage(data, w, h, decodeArray, pX, pY); } /** * convert byte[] datastream JPEG to an image in RGB * * @throws PdfException */ @Override public BufferedImage JPEG2000ToRGBImage(byte[] data, int w, int h, float[] decodeArray, int pX, int pY) throws PdfException { BufferedImage image; ByteArrayInputStream in; Raster ras; try { in = new ByteArrayInputStream(data); ImageReader iir = 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 */ byte[] index = this.getIndexedMap(); 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, ras.createCompatibleWritableRaster(), false, null); image.setData(ras); // 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); CSToRGB = new ColorConvertOp(this.cs, image.getColorModel().getColorSpace(), ColorSpaces.hints); image = new BufferedImage(w, h, image.getType()); } else { if (CSToRGB == null) initCMYKColorspace(); rgbRaster = ColorSpaceConvertor.createCompatibleWritableRaaster(rgbModel, w, h); CSToRGB = new ColorConvertOp(this.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 (see http://www.idrsolutions.com/additional-jars/) 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 (see http://www.idrsolutions.com/additional-jars/) on classpath"); } return image; } /** * convert Index to RGB */ @Override final public byte[] convertIndexToRGB(byte[] index) { this.isConverted = true; return convert4Index(index); } public static ColorSpace getColorSpaceInstance() { ColorSpace CMYK = new DeviceCMYKColorSpace().getColorSpace(); // optional alternative CMYK String CMYKprofile = System.getProperty("org.jpedal.CMYKprofile"); if (CMYKprofile != null) { try { CMYK = new ICC_ColorSpace(ICC_Profile.getInstance(new FileInputStream(CMYKprofile))); } catch (Exception e) { throw new RuntimeException("Unable to create CMYK colorspace with " + CMYKprofile + "\nPlease check Path and file valid or use built-in"); } } return CMYK; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy