From 32b7c837825453538b67f115e255327c35c57c6b Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Thu, 8 Jul 2010 14:13:24 +0000 Subject: [PATCH] Added support for CIE Lab colors to AFP output. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_Color@961779 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/afp/goca/GraphicsSetProcessColor.java | 90 ++++++++++++++----- .../apache/fop/afp/ptoca/PtocaBuilder.java | 34 ++++++- 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java index 4d45b22cb..edde6b95f 100644 --- a/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java +++ b/src/java/org/apache/fop/afp/goca/GraphicsSetProcessColor.java @@ -21,9 +21,16 @@ package org.apache.fop.afp.goca; import java.awt.Color; import java.awt.color.ColorSpace; +import java.io.DataOutput; import java.io.IOException; import java.io.OutputStream; +import org.apache.commons.io.output.ByteArrayOutputStream; + +import org.apache.xmlgraphics.java2d.color.CIELabColorSpace; +import org.apache.xmlgraphics.java2d.color.ColorUtil; +import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives; + /** * Sets the current processing color for the following GOCA structured fields */ @@ -37,26 +44,50 @@ public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { * X'08' CIELAB * X'40' Standard OCA color space */ - private static final byte RGB = 0x01, CMYK = 0x04; + private static final byte RGB = 0x01, CMYK = 0x04, CIELAB = 0x08; private final Color color; - - private final float[] colorComponents; + private final int componentsSize; /** * Main constructor * - * @param color - * the color to set + * @param color the color to set */ public GraphicsSetProcessColor(Color color) { - this.color = color; - this.colorComponents = color.getColorComponents(null); + if (color instanceof ColorWithAlternatives) { + ColorWithAlternatives cwa = (ColorWithAlternatives)color; + Color alt = cwa.getFirstAlternativeOfType(ColorSpace.TYPE_CMYK); + if (alt != null) { + this.color = alt; + this.componentsSize = 4; + return; + } + } + ColorSpace cs = color.getColorSpace(); + int colSpaceType = cs.getType(); + if (colSpaceType == ColorSpace.TYPE_CMYK) { + this.color = color; + this.componentsSize = 4; + } else if (cs instanceof CIELabColorSpace) { + //TODO Convert between illuminants if not D50 according to rendering intents + //Right now, we're assuming D50 as the GOCA spec requires. + this.color = color; + //16bit components didn't work, and 8-bit sadly has reduced accuracy. + this.componentsSize = 3; + } else { + if (!color.getColorSpace().isCS_sRGB()) { + this.color = ColorUtil.toSRGBColor(color); + } else { + this.color = color; + } + this.componentsSize = 3; + } } /** {@inheritDoc} */ public int getDataLength() { - return 12 + colorComponents.length; + return 12 + this.componentsSize; } /** {@inheritDoc} */ @@ -66,27 +97,44 @@ public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { /** {@inheritDoc} */ public void writeToStream(OutputStream os) throws IOException { + float[] colorComponents = color.getColorComponents(null); // COLSPCE byte colspace; - int colSpaceType = color.getColorSpace().getType(); + ColorSpace cs = color.getColorSpace(); + int colSpaceType = cs.getType(); + ByteArrayOutputStream baout = new ByteArrayOutputStream(); + byte[] colsizes; if (colSpaceType == ColorSpace.TYPE_CMYK) { colspace = CMYK; + colsizes = new byte[] {0x08, 0x08, 0x08, 0x08}; + for (int i = 0; i < colorComponents.length; i++) { + baout.write(Math.round(colorComponents[i] * 255)); + } } else if (colSpaceType == ColorSpace.TYPE_RGB) { colspace = RGB; + colsizes = new byte[] {0x08, 0x08, 0x08, 0x00}; + for (int i = 0; i < colorComponents.length; i++) { + baout.write(Math.round(colorComponents[i] * 255)); + } + } else if (cs instanceof CIELabColorSpace) { + colspace = CIELAB; + colsizes = new byte[] {0x08, 0x08, 0x08, 0x00}; + DataOutput dout = new java.io.DataOutputStream(baout); + //According to GOCA, I'd expect the multiplicator below to be 255f, not 100f + //But only IBM AFP Workbench seems to support Lab colors and it requires "c * 100f" + int l = Math.round(colorComponents[0] * 100f); + int a = Math.round(colorComponents[1] * 255f) - 128; + int b = Math.round(colorComponents[2] * 255f) - 128; + dout.writeByte(l); + dout.writeByte(a); + dout.writeByte(b); } else { - log.error("unsupported colorspace " + colSpaceType); - colspace = RGB; - } - - // COLSIZE(S) - byte[] colsizes = new byte[] {0x00, 0x00, 0x00, 0x00}; - for (int i = 0; i < colorComponents.length; i++) { - colsizes[i] = (byte) 8; + throw new IllegalStateException(); } int len = getDataLength(); - byte[] data = new byte[len]; + byte[] data = new byte[12]; data[0] = getOrderCode(); // GSPCOL order code data[1] = (byte) (len - 2); // LEN data[2] = 0x00; // reserved; must be zero @@ -100,12 +148,8 @@ public class GraphicsSetProcessColor extends AbstractGraphicsDrawingOrder { data[10] = colsizes[2]; data[11] = colsizes[3]; - // COLVALUE(S) - for (int i = 0; i < colorComponents.length; i++) { - data[i + 12] = (byte) (colorComponents[i] * 255); - } - os.write(data); + baout.writeTo(os); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java index e583b81e6..054292cc1 100644 --- a/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java +++ b/src/java/org/apache/fop/afp/ptoca/PtocaBuilder.java @@ -26,6 +26,9 @@ import java.io.OutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.xmlgraphics.java2d.color.CIELabColorSpace; +import org.apache.xmlgraphics.java2d.color.ColorWithAlternatives; + /** * Generator class for PTOCA data structures. */ @@ -311,9 +314,19 @@ public abstract class PtocaBuilder implements PtocaConstants { * @throws IOException if an I/O error occurs */ public void setExtendedTextColor(Color col) throws IOException { - if (col.equals(currentColor)) { + //Check in both directions + if (col.equals(currentColor) && currentColor.equals(col)) { return; } + if (col instanceof ColorWithAlternatives) { + ColorWithAlternatives cwa = (ColorWithAlternatives)col; + Color alt = cwa.getFirstAlternativeOfType(ColorSpace.TYPE_CMYK); + if (alt != null) { + col = alt; + } + } + ColorSpace cs = col.getColorSpace(); + newControlSequence(); if (col.getColorSpace().getType() == ColorSpace.TYPE_CMYK) { writeByte(0x00); // Reserved; must be zero @@ -332,6 +345,25 @@ public abstract class PtocaBuilder implements PtocaConstants { int component = Math.round(comps[i] * 255); writeByte(component); } + } else if (cs instanceof CIELabColorSpace) { + writeByte(0x00); // Reserved; must be zero + writeByte(0x08); // Color space - 0x08 = CIELAB + writeByte(0x00); // Reserved; must be zero + writeByte(0x00); // Reserved; must be zero + writeByte(0x00); // Reserved; must be zero + writeByte(0x00); // Reserved; must be zero + writeByte(8); // Number of bits in component 1 + writeByte(8); // Number of bits in component 2 + writeByte(8); // Number of bits in component 3 + writeByte(0); // Number of bits in component 4 + //Sadly, 16 bit components don't seem to work + float[] colorComponents = col.getColorComponents(null); + int l = Math.round(colorComponents[0] * 255f); + int a = Math.round(colorComponents[1] * 255f) - 128; + int b = Math.round(colorComponents[2] * 255f) - 128; + writeByte(l); // L* + writeByte(a); // a* + writeByte(b); // b* } else { writeByte(0x00); // Reserved; must be zero writeByte(0x01); // Color space - 0x01 = RGB -- 2.39.5