use of org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace in project pdfbox by apache.
the class StandardColorSpaceHelper method processDeviceNColorSpace.
/**
* 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));
}
}
use of org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace in project pdfbox by apache.
the class JPEGFactory method createFromByteArray.
/**
* Creates a new JPEG Image XObject from a byte array containing JPEG data.
*
* @param document the document where the image will be created
* @param byteArray bytes of JPEG image
* @return a new Image XObject
*
* @throws IOException if the input stream cannot be read
*/
public static PDImageXObject createFromByteArray(PDDocument document, byte[] byteArray) throws IOException {
// copy stream
ByteArrayInputStream byteStream = new ByteArrayInputStream(byteArray);
// read image
Raster raster = readJPEGRaster(byteStream);
byteStream.reset();
PDColorSpace colorSpace;
switch(raster.getNumDataElements()) {
case 1:
colorSpace = PDDeviceGray.INSTANCE;
break;
case 3:
colorSpace = PDDeviceRGB.INSTANCE;
break;
case 4:
colorSpace = PDDeviceCMYK.INSTANCE;
break;
default:
throw new UnsupportedOperationException("number of data elements not supported: " + raster.getNumDataElements());
}
// create PDImageXObject from stream
PDImageXObject pdImage = new PDImageXObject(document, byteStream, COSName.DCT_DECODE, raster.getWidth(), raster.getHeight(), 8, colorSpace);
if (colorSpace instanceof PDDeviceCMYK) {
COSArray decode = new COSArray();
decode.add(COSInteger.ONE);
decode.add(COSInteger.ZERO);
decode.add(COSInteger.ONE);
decode.add(COSInteger.ZERO);
decode.add(COSInteger.ONE);
decode.add(COSInteger.ZERO);
decode.add(COSInteger.ONE);
decode.add(COSInteger.ZERO);
pdImage.setDecode(decode);
}
return pdImage;
}
use of org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace in project pdfbox by apache.
the class SampledImageReader method fromAny.
// slower, general-purpose image conversion from any image format
private static BufferedImage fromAny(PDImage pdImage, WritableRaster raster, COSArray colorKey, Rectangle clipped, final int subsampling, final int width, final int height) throws IOException {
int currentSubsampling = subsampling;
final PDColorSpace colorSpace = pdImage.getColorSpace();
final int numComponents = colorSpace.getNumberOfComponents();
final int bitsPerComponent = pdImage.getBitsPerComponent();
final float[] decode = getDecodeArray(pdImage);
DecodeOptions options = new DecodeOptions(currentSubsampling);
options.setSourceRegion(clipped);
// read bit stream
try (ImageInputStream iis = new MemoryCacheImageInputStream(pdImage.createInputStream(options))) {
final int inputWidth;
final int startx;
final int starty;
final int scanWidth;
final int scanHeight;
if (options.isFilterSubsampled()) {
// Decode options were honored, and so there is no need for additional clipping or subsampling
inputWidth = width;
startx = 0;
starty = 0;
scanWidth = width;
scanHeight = height;
currentSubsampling = 1;
} else {
// Decode options not honored, so we need to clip and subsample ourselves.
inputWidth = pdImage.getWidth();
startx = clipped.x;
starty = clipped.y;
scanWidth = clipped.width;
scanHeight = clipped.height;
}
final float sampleMax = (float) Math.pow(2, bitsPerComponent) - 1f;
final boolean isIndexed = colorSpace instanceof PDIndexed;
// init color key mask
float[] colorKeyRanges = null;
BufferedImage colorKeyMask = null;
if (colorKey != null) {
colorKeyRanges = colorKey.toFloatArray();
colorKeyMask = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
}
// calculate row padding
int padding = 0;
if (inputWidth * numComponents * bitsPerComponent % 8 > 0) {
padding = 8 - (inputWidth * numComponents * bitsPerComponent % 8);
}
// read stream
byte[] srcColorValues = new byte[numComponents];
byte[] alpha = new byte[1];
for (int y = 0; y < starty + scanHeight; y++) {
for (int x = 0; x < startx + scanWidth; x++) {
boolean isMasked = true;
for (int c = 0; c < numComponents; c++) {
int value = (int) iis.readBits(bitsPerComponent);
// color key mask requires values before they are decoded
if (colorKeyRanges != null) {
isMasked &= value >= colorKeyRanges[c * 2] && value <= colorKeyRanges[c * 2 + 1];
}
// decode array
final float dMin = decode[c * 2];
final float dMax = decode[(c * 2) + 1];
// interpolate to domain
float output = dMin + (value * ((dMax - dMin) / sampleMax));
if (isIndexed) {
// indexed color spaces get the raw value, because the TYPE_BYTE
// below cannot be reversed by the color space without it having
// knowledge of the number of bits per component
srcColorValues[c] = (byte) Math.round(output);
} else {
// interpolate to TYPE_BYTE
int outputByte = Math.round(((output - Math.min(dMin, dMax)) / Math.abs(dMax - dMin)) * 255f);
srcColorValues[c] = (byte) outputByte;
}
}
// only write to output if within requested region and subsample.
if (x >= startx && y >= starty && x % currentSubsampling == 0 && y % currentSubsampling == 0) {
raster.setDataElements((x - startx) / currentSubsampling, (y - starty) / currentSubsampling, srcColorValues);
// set alpha channel in color key mask, if any
if (colorKeyMask != null) {
alpha[0] = (byte) (isMasked ? 255 : 0);
colorKeyMask.getRaster().setDataElements((x - startx) / currentSubsampling, (y - starty) / currentSubsampling, alpha);
}
}
}
// rows are padded to the nearest byte
iis.readBits(padding);
}
// use the color space to convert the image to RGB
BufferedImage rgbImage = colorSpace.toRGBImage(raster);
// apply color mask, if any
if (colorKeyMask != null) {
return applyColorKeyMask(rgbImage, colorKeyMask);
} else {
return rgbImage;
}
}
}
use of org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace in project pdfbox by apache.
the class Type1ShadingContext method getRaster.
@Override
public Raster getRaster(int x, int y, int w, int h) {
WritableRaster raster = getColorModel().createCompatibleWritableRaster(w, h);
int[] data = new int[w * h * 4];
for (int j = 0; j < h; j++) {
for (int i = 0; i < w; i++) {
int index = (j * w + i) * 4;
boolean useBackground = false;
float[] values = new float[] { x + i, y + j };
rat.transform(values, 0, values, 0, 1);
if (values[0] < domain[0] || values[0] > domain[1] || values[1] < domain[2] || values[1] > domain[3]) {
if (getBackground() == null) {
continue;
}
useBackground = true;
}
// evaluate function
if (useBackground) {
values = getBackground();
} else {
try {
values = type1ShadingType.evalFunction(values);
} catch (IOException e) {
LOG.error("error while processing a function", e);
}
}
// convert color values from shading color space to RGB
PDColorSpace shadingColorSpace = getShadingColorSpace();
if (shadingColorSpace != null) {
try {
values = shadingColorSpace.toRGB(values);
} catch (IOException e) {
LOG.error("error processing color space", e);
}
}
data[index] = (int) (values[0] * 255);
data[index + 1] = (int) (values[1] * 255);
data[index + 2] = (int) (values[2] * 255);
data[index + 3] = 255;
}
}
raster.setPixels(0, 0, w, h, data);
return raster;
}
use of org.apache.pdfbox.pdmodel.graphics.color.PDColorSpace in project pdfbox by apache.
the class XObjImageValidator method checkColorSpaceAndImageMask.
/*
* According to the PDF Reference file, there are some specific rules on following fields ColorSpace, Mask,
* ImageMask and BitsPerComponent. If ImageMask is set to true, ColorSpace and Mask entries are forbidden.
*/
protected void checkColorSpaceAndImageMask() throws ValidationException {
COSBase csImg = this.xobject.getItem(COSName.COLORSPACE);
COSBase bitsPerComp = this.xobject.getItem("BitsPerComponent");
COSBase mask = this.xobject.getItem(COSName.MASK);
if (isImageMaskTrue()) {
if (csImg != null || mask != null) {
context.addValidationError(new ValidationError(ERROR_GRAPHIC_UNEXPECTED_KEY, "ImageMask entry is true, ColorSpace and Mask are forbidden."));
}
Integer bitsPerCompValue = COSUtils.getAsInteger(bitsPerComp, cosDocument);
if (bitsPerCompValue != null && bitsPerCompValue != 1) {
context.addValidationError(new ValidationError(ERROR_GRAPHIC_UNEXPECTED_VALUE_FOR_KEY, "ImageMask entry is true, BitsPerComponent must be absent or 1."));
}
} else {
try {
PreflightConfiguration config = context.getConfig();
ColorSpaceHelperFactory csFact = config.getColorSpaceHelperFact();
PDColorSpace pdCS = PDColorSpace.create(csImg);
ColorSpaceHelper csh = csFact.getColorSpaceHelper(context, pdCS, ColorSpaceRestriction.NO_PATTERN);
csh.validate();
} catch (IOException e) {
LOGGER.debug("Couldn't create PDColorSpace " + csImg, e);
context.addValidationError(new ValidationError(ERROR_GRAPHIC_INVALID_UNKNOWN_COLOR_SPACE));
}
}
}
Aggregations