/** * Create a Java colorspace for this colorspace. * * @return A color space that can be used for Java AWT operations. * @throws IOException If there is an error creating the color space. */ public ColorSpace createColorSpace() throws IOException { // throw new IOException( "Not implemented" ); try { /// dump some information to help figure these things out // logger().info( array.toString()); PDColorSpace alt = getAlternateColorSpace(); // logger().info(alt.toString()); ColorSpace CS = alt.createColorSpace(); // /dwilson 12/15/07 // logger().info(CS.toString() + " reporting type " + CS.getType() + " and having component // count of " + CS.getNumComponents()); return CS; } catch (IOException IOe) { logger().severe(IOe.toString() + "\n at\n" + FullStackTrace(IOe)); throw IOe; } catch (Exception e) { logger().severe(e.toString() + "\n at\n" + FullStackTrace(e)); throw new IOException("Failed to Create ColorSpace"); } }
private void writeColorSpace(PDColorSpace colorSpace) throws IOException { COSName key = null; if (colorSpace instanceof PDDeviceGray || colorSpace instanceof PDDeviceRGB || colorSpace instanceof PDDeviceCMYK) { key = COSName.getPDFName(colorSpace.getName()); } else { COSDictionary colorSpaces = (COSDictionary) resources.getCOSDictionary().getDictionaryObject(COSName.COLORSPACE); if (colorSpaces == null) { colorSpaces = new COSDictionary(); resources.getCOSDictionary().setItem(COSName.COLORSPACE, colorSpaces); } key = colorSpaces.getKeyForValue(colorSpace.getCOSObject()); if (key == null) { int counter = 0; String csName = "CS"; while (colorSpaces.containsValue(csName + counter)) { counter++; } key = COSName.getPDFName(csName + counter); colorSpaces.setItem(key, colorSpace); } } key.writePDF(output); appendRawCommands(SPACE); }
/** * Method called by the processAllColorSpace if the ColorSpace to check is Separation. Because * this kind of ColorSpace can have an alternate color space, the processAllColorSpace is called * to check this alternate color space. (Indexed, Separation, DeviceN and Pattern can't be a Base * color space) * * @param colorSpace the color space object to check. */ protected void processSeparationColorSpace(PDColorSpace colorSpace) { try { COSBase cosAlt = ((COSArray) colorSpace.getCOSObject()).getObject(2); PDColorSpace altCol = PDColorSpace.create(cosAlt); if (altCol != null) { ColorSpaces acs = ColorSpaces.valueOf(altCol.getName()); switch (acs) { case Separation: case DeviceN: case Pattern: case Indexed: case I: context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE, acs.getLabel() + " color space can't be used as alternate color space")); break; default: processAllColorSpace(altCol); } } } catch (IOException e) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Separation color space : " + e.getMessage(), e)); } }
@Override public void process(Operator operator, List<COSBase> arguments) throws IOException { COSName name = (COSName) arguments.get(0); PDColorSpace cs = context.getResources().getColorSpace(name); context.getGraphicsState().setStrokingColorSpace(cs); context.getGraphicsState().setStrokingColor(cs.getInitialColor()); }
/** * This will set the alternate color space. * * @param cs The alternate color space. */ public void setAlternateColorSpace(PDColorSpace cs) { COSBase space = null; if (cs != null) { space = cs.getCOSObject(); } array.set(2, space); }
/** * Method called by the processAllColorSpace if the ColorSpace to check is DeviceN. Because this * kind of ColorSpace can have alternate color space, the processAllColorSpace is called to check * this alternate color space. (There are no restrictions on the Alternate Color space) * * @param colorSpace the color space object to check. */ protected void processDeviceNColorSpace(PDColorSpace colorSpace) { PDDeviceN deviceN = (PDDeviceN) colorSpace; try { if (iccpw == null) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing")); return; } COSBase cosAlt = ((COSArray) colorSpace.getCOSObject()).getObject(2); PDColorSpace altColor = PDColorSpace.create(cosAlt); if (altColor != null) { processAllColorSpace(altColor); } int numberOfColorants = 0; PDDeviceNAttributes attr = deviceN.getAttributes(); if (attr != null) { final Map<String, PDSeparation> colorants = attr.getColorants(); if (colorants != null) { numberOfColorants = colorants.size(); for (PDSeparation col : colorants.values()) { if (col != null) { processAllColorSpace(col); } } } } int numberOfComponents = deviceN.getNumberOfComponents(); if (numberOfColorants > MAX_DEVICE_N_LIMIT || numberOfComponents > MAX_DEVICE_N_LIMIT) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN, "DeviceN has too many tint components or colorants")); } } catch (IOException e) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read DeviceN color space : " + e.getMessage(), e)); } }
/** * Create the current color from the colorspace and values. * * @return The current awt color. * @throws IOException If there is an error creating the color. */ public Color createColor() throws IOException { Color retval = null; float[] components = colorSpaceValue.toFloatArray(); try { if (colorSpace.getName().equals(PDDeviceRGB.NAME) && 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. retval = new Color(components[0], components[1], components[2]); } else { ColorSpace cs = colorSpace.createColorSpace(); if (colorSpace.getName().equals(PDSeparation.NAME) && components.length == 1) { // Use that component as a single-integer RGB value retval = new Color((int) components[0]); } else { retval = new Color(cs, components, 1f); } } return retval; } catch (java.lang.IllegalArgumentException IAe) { String Values = "Color Values: "; for (int i = 0; i < components.length; i++) { Values = Values + components[i] + "\t"; } logger().severe(IAe.toString() + "\n" + Values + "\n at\n" + FullStackTrace(IAe)); throw IAe; } catch (IOException IOe) { logger().severe(IOe.toString() + "\n at\n" + FullStackTrace(IOe)); throw IOe; } catch (Exception e) { logger().severe(e.toString() + "\n at\n" + FullStackTrace(e)); throw new IOException("Failed to Create Color"); } }
/** * Method called by the processAllColorSpace if the ColorSpace to check is Indexed. Because this * kind of ColorSpace can have a Base color space, the processAllColorSpace is called to check * this base color space. (Indexed and Pattern can't be a Base color space) * * @param colorSpace the color space object to check. */ protected void processIndexedColorSpace(PDColorSpace colorSpace) { PDIndexed indexed = (PDIndexed) colorSpace; PDColorSpace based = indexed.getBaseColorSpace(); ColorSpaces cs = ColorSpaces.valueOf(based.getName()); if (cs == ColorSpaces.Indexed || cs == ColorSpaces.I) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED, "Indexed color space can't be used as Base color space")); return; } if (cs == ColorSpaces.Pattern) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED, "Pattern color space can't be used as Base color space")); return; } processAllColorSpace(based); }
/** * Look up in the closest PDResources objects if there are a default ColorSpace. If there are, * check that is a authorized ColorSpace. * * @param colorSpace * @return true if the default colorspace is a right one, false otherwise. */ protected boolean processDefaultColorSpace(PDColorSpace colorSpace) { boolean result = false; // get default color space PreflightPath vPath = context.getValidationPath(); PDResources resources = vPath.getClosestPathElement(PDResources.class); if (resources != null) { PDColorSpace defaultCS = null; try { if (colorSpace.getName().equals(ColorSpaces.DeviceCMYK.getLabel()) && resources.hasColorSpace(COSName.DEFAULT_CMYK)) { defaultCS = resources.getColorSpace(COSName.DEFAULT_CMYK); } else if (colorSpace.getName().equals(ColorSpaces.DeviceRGB.getLabel()) && resources.hasColorSpace(COSName.DEFAULT_RGB)) { defaultCS = resources.getColorSpace(COSName.DEFAULT_RGB); } else if (colorSpace.getName().equals(ColorSpaces.DeviceGray.getLabel()) && resources.hasColorSpace(COSName.DEFAULT_GRAY)) { defaultCS = resources.getColorSpace(COSName.DEFAULT_GRAY); } } catch (IOException e) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read default color space : " + e.getMessage(), e)); } if (defaultCS != null) { // defaultCS is valid if the number of errors hasn't changed int nbOfErrors = context.getDocument().getResult().getErrorsList().size(); processAllColorSpace(defaultCS); int newNbOfErrors = context.getDocument().getResult().getErrorsList().size(); result = (nbOfErrors == newNbOfErrors); } } return result; }
/** * Method called by the processAllColorSpace if the ColorSpace to check is a ICCBased color space. * Because this kind of ColorSpace can have alternate color space, the processAllColorSpace is * called to check this alternate color space. (Pattern is forbidden as Alternate Color Space) * * @param colorSpace the color space object to check. */ protected void processICCBasedColorSpace(PDColorSpace colorSpace) { PDICCBased iccBased = (PDICCBased) colorSpace; try { ICC_Profile.getInstance(iccBased.getPDStream().createInputStream()); PDColorSpace altpdcs = iccBased.getAlternateColorSpace(); if (altpdcs != null) { ColorSpaces altCsId = ColorSpaces.valueOf(altpdcs.getName()); if (altCsId == ColorSpaces.Pattern) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN, "Pattern is forbidden as AlternateColorSpace of a ICCBased")); } /* * According to the ISO-19005-1:2005 * * A conforming reader shall render ICCBased colour spaces as specified by the ICC specification, * and shall not use the Alternate colour space specified in an ICC profile stream dictionary * * We don't check the alternate ColorSpaces */ } } catch (IllegalArgumentException e) { // this is not a ICC_Profile context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED, "ICCBased color space is invalid: " + e.getMessage(), e)); } catch (IOException e) { context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read ICCBase color space: " + e.getMessage(), e)); } }
/** * Method called by the validate method. According to the ColorSpace, a specific ColorSpace method * is called. * * @param colorSpace the color space object to check. */ protected final void processAllColorSpace(PDColorSpace colorSpace) { ColorSpaces cs = ColorSpaces.valueOf(colorSpace.getName()); switch (cs) { case DeviceRGB: case RGB: processRGBColorSpace(colorSpace); break; case DeviceCMYK: case CMYK: processCYMKColorSpace(colorSpace); break; case CalRGB: case CalGray: case Lab: processCalibratedColorSpace(colorSpace); break; case DeviceGray: case G: processGrayColorSpace(colorSpace); break; case ICCBased: processICCBasedColorSpace(colorSpace); break; case DeviceN: processDeviceNColorSpace(colorSpace); break; case Indexed: case I: processIndexedColorSpace(colorSpace); break; case Separation: processSeparationColorSpace(colorSpace); break; case Pattern: processPatternColorSpace(colorSpace); break; default: context.addValidationError( new ValidationError( ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE, cs.getLabel() + " is unknown as ColorSpace")); } }