Package org.apache.padaf.preflight.graphics.color

Source Code of org.apache.padaf.preflight.graphics.color.StandardColorSpaceHelper

/*****************************************************************************
*
* 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.padaf.preflight.graphics.color;

import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN;
import static org.apache.padaf.preflight.ValidationConstants.ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE;
import static org.apache.padaf.preflight.ValidationConstants.MAX_DEVICE_N_LIMIT;

import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.padaf.preflight.DocumentHandler;
import org.apache.padaf.preflight.ValidationException;
import org.apache.padaf.preflight.ValidationResult.ValidationError;
import org.apache.padaf.preflight.graphics.ICCProfileWrapper;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSObject;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace;
import org.apache.pdfbox.pdmodel.graphics.color.PDColorSpaceFactory;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceN;
import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceNAttributes;
import org.apache.pdfbox.pdmodel.graphics.color.PDICCBased;
import org.apache.pdfbox.pdmodel.graphics.color.PDIndexed;
import org.apache.pdfbox.pdmodel.graphics.color.PDSeparation;

/**
* This class doesn't define restrictions on ColorSpace. It checks only the
* consistency of the Color space with the DestOutputIntent.
*/
public class StandardColorSpaceHelper implements ColorSpaceHelper {
  /**
   * The color space object to check, this object is used to instantiate the
   * pdcs object.
   */
  protected COSBase csObject = null;
  /**
   * The document handler which contains useful information to process the
   * validation.
   */
  protected DocumentHandler handler = null;
  /**
   * The ICCProfile contained in the DestOutputIntent
   */
  protected ICCProfileWrapper iccpw = null;
  /**
   * High level object which represents the colors space to check.
   */
  protected PDColorSpace pdcs = null;

  StandardColorSpaceHelper(COSBase _csObject, DocumentHandler _handler) {
    this.csObject = _csObject;
    this.handler = _handler;
    this.iccpw = this.handler.getIccProfileWrapper();
  }

  StandardColorSpaceHelper(PDColorSpace _cs, DocumentHandler _handler) {
    this.handler = _handler;
    this.pdcs = _cs;
    this.iccpw = this.handler.getIccProfileWrapper();
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * net.awl.edoc.pdfa.validation.graphics.color.ColorSpaceHelper#validate(java
   * .util.List)
   */
  public final boolean validate(List<ValidationError> result) throws ValidationException {
    // ---- Create a PDFBox ColorSpace object
    if (pdcs == null && csObject != null) {
      try {
        if (csObject instanceof COSObject) {
          pdcs = PDColorSpaceFactory.createColorSpace(((COSObject)csObject).getObject());
        } else {
          pdcs = PDColorSpaceFactory.createColorSpace(csObject);
        }
      } catch (IOException e) {
        throw new ValidationException("Unable to create a PDColorSpace : "
            + e.getMessage(), e);
      }
    }

    if ( pdcs == null ) {
      throw new ValidationException(
          "Unable to create a PDColorSpace with the value null");
    }

    return processAllColorSpace(pdcs, result);
  }

  /**
   * Method called by the validate method. According to the ColorSpace, a
   * specific ColorSpace method is called.
   *
   * @param pdcs
   *          the color space object to check.
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the validation succeed, false otherwise.
   */
  protected final boolean processAllColorSpace(PDColorSpace pdcs,
      List<ValidationError> result) {
    ColorSpaces cs = ColorSpaces.valueOf(pdcs.getName());
   
    switch (cs) {
    case DeviceRGB:
    case DeviceRGB_SHORT:
      return processRGBColorSpace(result);

    case DeviceCMYK:
    case DeviceCMYK_SHORT:
      return processCYMKColorSpace(result);

    case CalRGB:
    case CalGray:
    case Lab:
      return processCalibratedColorSpace(result);

    case DeviceGray:
    case DeviceGray_SHORT:
      return processGrayColorSpace(result);

    case ICCBased:
      return processICCBasedColorSpace(pdcs, result);

    case DeviceN:
      return processDeviceNColorSpace(pdcs, result);

    case Indexed:
    case Indexed_SHORT:
      return processIndexedColorSpace(pdcs, result);

    case Separation:
      return processSeparationColorSpace(pdcs, result);

    case Pattern:
      return processPatternColorSpace(result);

    default:
      result
      .add(new ValidationError(ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE, cs.getLabel() + " is unknown as ColorSpace"));
      return false;
    }
  }

  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is
   * DeviceRGB.
   *
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processRGBColorSpace(List<ValidationError> result) {
    // ---- ICCProfile must contain a RGB Color Space
    if (iccpw == null) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
      return false;     
    } if (!iccpw.isRGBColorSpace()) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_RGB, "DestOutputProfile isn't RGB ColorSpace"));
      return false;
    }
    return true;
  }

  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is
   * DeviceCYMK.
   *
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processCYMKColorSpace(List<ValidationError> result) {
    // ---- ICCProfile must contain a CYMK Color Space
    if (iccpw == null) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
      return false;     
    } if (!iccpw.isCMYKColorSpace()) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_CMYK, "DestOutputProfile isn't CMYK ColorSpace"));
      return false;
    }
    return true;
  }

  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is a
   * Pattern.
   *
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processPatternColorSpace(List<ValidationError> result) {
    if (iccpw == null) {
      result
      .add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
      return false;
    }
    return true;
  }

  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is
   * DeviceGray.
   *
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processGrayColorSpace(List<ValidationError> result) {
    // ---- OutputIntent is mandatory
    if (iccpw == null) {
      result
      .add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
      return false;
    }
    return true;
  }

  /**
   * Method called by the processAllColorSpace if the ColorSpace to check is a
   * Clibrated Color (CalGary, CalRGB, Lab).
   *
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processCalibratedColorSpace(List<ValidationError> result) {
    // ---- OutputIntent isn't mandatory
    return true;
  }

  /**
   * 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 pdcs
   *          the color space object to check.
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processICCBasedColorSpace(PDColorSpace pdcs,
      List<ValidationError> result) {
    PDICCBased iccBased = (PDICCBased) pdcs;
    try {
      ICC_Profile iccp = ICC_Profile.getInstance(iccBased.getPDStream().getByteArray());
      if (iccp == null) {
        result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_ICCBASED, "Unable to read ICCBase color space "));
        return false;
      }
      List<PDColorSpace> altCs = iccBased.getAlternateColorSpaces();
      for (PDColorSpace altpdcs : altCs) {
        if (altpdcs != null) {

          ColorSpaces altCsId = ColorSpaces.valueOf(altpdcs.getName());
          if (altCsId == ColorSpaces.Pattern) {
            result.add(new ValidationError(
                ERROR_GRAPHIC_INVALID_PATTERN_COLOR_SPACE_FORBIDDEN, "Pattern is forbidden as AlternateColorSpace of a ICCBased"));
            return false;
          }
          /*
           * 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 (IOException e) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read ICCBase color space : " + e.getMessage()));
      return false;
    }

    return true;
  }

  /**
   * 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 pdcs
   *          the color space object to check.
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processDeviceNColorSpace(PDColorSpace pdcs,
      List<ValidationError> result) {
    PDDeviceN deviceN = (PDDeviceN) pdcs;
    try {
      if (iccpw == null) {
        result.add(new ValidationError(
            ERROR_GRAPHIC_INVALID_COLOR_SPACE_MISSING, "DestOutputProfile is missing"));
        return false;
      }

      PDColorSpace altColor = deviceN.getAlternateColorSpace();
      boolean res = true;
      if (altColor != null) {
        res = processAllColorSpace(altColor, result);
      }

      int numberOfColorants = 0;
      PDDeviceNAttributes attr = deviceN.getAttributes();
      if (attr != null) {
        Map colorants = attr.getColorants();
        if (colorants != null) {
          numberOfColorants = colorants.size();
          for (Object col : colorants.values()) {
            if (col != null) {
              res = res && processAllColorSpace((PDColorSpace) col, result);
            }
          }
        }
      }
      int numberOfComponents = deviceN.getNumberOfComponents();
      if (numberOfColorants > MAX_DEVICE_N_LIMIT || numberOfComponents > MAX_DEVICE_N_LIMIT ) {
        result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE_TOO_MANY_COMPONENTS_DEVICEN, "DeviceN has too many tint components or colorants"))
        res = false;
      }
      return res;
    } catch (IOException e) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read DeviceN color space : " + e.getMessage()));
      return false;
    }
  }

  /**
   * 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 pdcs
   *          the color space object to check.
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processIndexedColorSpace(PDColorSpace pdcs,
      List<ValidationError> result) {
    PDIndexed indexed = (PDIndexed) pdcs;
    try {
      PDColorSpace based = indexed.getBaseColorSpace();
      ColorSpaces cs = ColorSpaces.valueOf(based.getName());
      if (cs == ColorSpaces.Indexed || cs == ColorSpaces.Indexed_SHORT) {
        result.add(new ValidationError(
            ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,"Indexed color space can't be used as Base color space"));
        return false;
      }
      if (cs == ColorSpaces.Pattern) {
        result.add(new ValidationError(
            ERROR_GRAPHIC_INVALID_COLOR_SPACE_INDEXED,"Pattern color space can't be used as Base color space"));
        return false;
      }
      return processAllColorSpace(based, result);
    } catch (IOException e) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Indexed color space : " + e.getMessage()));
      return false;
    }
  }

  /**
   * 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 pdcs
   *          the color space object to check.
   * @param result
   *          the list of error to update if the validation fails.
   * @return true if the color space is valid, false otherwise.
   */
  protected boolean processSeparationColorSpace(PDColorSpace pdcs,
      List<ValidationError> result) {
    PDSeparation separation = (PDSeparation) pdcs;
    try {

      PDColorSpace altCol = separation.getAlternateColorSpace();
      if (altCol != null) {
        ColorSpaces acs = ColorSpaces.valueOf(altCol.getName());
        switch (acs) {
        case Separation:
        case DeviceN:
        case Pattern:
        case Indexed:
        case Indexed_SHORT:
          result.add(new ValidationError(
              ERROR_GRAPHIC_INVALID_COLOR_SPACE_ALTERNATE, acs.getLabel() + " color space can't be used as alternate color space"));
          return false;
        default:
          return processAllColorSpace(altCol, result);
        }
      }

      return true;
    } catch (IOException e) {
      result.add(new ValidationError(ERROR_GRAPHIC_INVALID_COLOR_SPACE, "Unable to read Separation color space : " + e.getMessage()));
      return false;
    }
  }
}
TOP

Related Classes of org.apache.padaf.preflight.graphics.color.StandardColorSpaceHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.