org.jpedal.parser.image.ImageCommands Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of OpenViewerFX Show documentation
Show all versions of OpenViewerFX Show documentation
Open Source (LGPL) JavaFX PDF Viewer for NetBeans plugin
/*
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.idrsolutions.com
* Help section for developers at http://www.idrsolutions.com/support/
*
* (C) Copyright 1997-2017 IDRsolutions and Contributors.
*
* This file is part of JPedal/JPDF2HTML5
*
@LICENSE@
*
* ---------------
* ImageCommands.java
* ---------------
*/
package org.jpedal.parser.image;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import org.jpedal.color.ColorSpaces;
import org.jpedal.constants.PDFflags;
import org.jpedal.function.FunctionFactory;
import org.jpedal.function.PDFFunction;
import org.jpedal.io.PdfFileReader;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.io.security.DecryptionFactory;
import org.jpedal.objects.GraphicsState;
import org.jpedal.objects.raw.FunctionObject;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.parser.image.data.ImageData;
public class ImageCommands {
public static final int ID = 0;
public static final int XOBJECT = 2;
public static boolean trackImages;
public static boolean rejectSuperimposedImages = true;
static {
final String operlapValue = System.getProperty("org.jpedal.rejectsuperimposedimages");
if (operlapValue != null) {
ImageCommands.rejectSuperimposedImages = (operlapValue.toLowerCase().contains("true"));
}
//hidden value to turn on function
final String imgSetting = System.getProperty("org.jpedal.trackImages");
if (imgSetting != null) {
trackImages = (imgSetting.toLowerCase().contains("true"));
}
}
/**
*/
static byte[] getMaskColor(final GraphicsState gs) {
final byte[] maskCol = new byte[4];
final int foreground = gs.nonstrokeColorSpace.getColor().getRGB();
maskCol[0] = (byte) ((foreground >> 16) & 0xFF);
maskCol[1] = (byte) ((foreground >> 8) & 0xFF);
maskCol[2] = (byte) ((foreground) & 0xFF);
return maskCol;
}
/**
* Test whether the data representing a line is uniform along it height
*/
static boolean isRepeatingLine(final byte[] lineData, final int height) {
if (lineData.length % height != 0) {
return false;
}
final int step = lineData.length / height;
for (int x = 0; x < (lineData.length / height) - 1; x++) {
int targetIndex = step;
while (targetIndex < lineData.length - 1) {
if (lineData[x] != lineData[targetIndex]) {
return false;
}
targetIndex += step;
}
}
return true;
}
static BufferedImage addBackgroundToMask(BufferedImage image, final boolean isMask) {
if (isMask) {
final int cw = image.getWidth();
final int ch = image.getHeight();
final BufferedImage background = new BufferedImage(cw, ch, BufferedImage.TYPE_INT_RGB);
final Graphics2D g2 = background.createGraphics();
g2.setColor(Color.white);
g2.fillRect(0, 0, cw, ch);
g2.drawImage(image, 0, 0, null);
image = background;
}
return image;
}
/**
* apply TR
*/
static void applyTR(final ImageData imageData, final Object[] TR, final PdfObjectReader currentPdfFile) {
try {
final PDFFunction[] functions = getFunctions(TR, currentPdfFile);
if (functions != null) {
final int w = imageData.getWidth();
final int h = imageData.getHeight();
final byte[] data = imageData.getObjectData();
final int compCount = imageData.getCompCount();
//System.out.println(data.length + " " + w + " " + h + " " + (data.length / (w * h)) + " " + compCount);
int ptr = 0;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
for (int a = 0; a < compCount; a++) {
final float[] raw = {(data[ptr] & 255) / 255f};
if (functions[a] != null) {
final float[] processed = functions[a].compute(raw);
data[ptr] = (byte) (255 * processed[0]);
}
ptr++;
}
}
}
//imageData.setObjectData(data);
}
} catch (final Exception e) {
e.printStackTrace(System.out);
}
}
private static PDFFunction[] getFunctions(final Object[] TRvalues, final PdfObjectReader currentPdfFile) {
PDFFunction[] functions = null;
int total = 0;
final byte[][] kidList = (byte[][]) TRvalues[1];
if (kidList != null) {
total = kidList.length;
functions = new PDFFunction[total];
}
//read functions
for (int count = 0; count < total; count++) {
if (kidList[count] == null) {
continue;
}
final String ref = new String(kidList[count]);
PdfObject Function = new FunctionObject(ref);
//handle /Identity as null or read
final byte[] possIdent = kidList[count];
if (possIdent != null && possIdent.length > 4 && possIdent[0] == 47 && possIdent[1] == 73 && possIdent[2] == 100 && possIdent[3] == 101)//(/Identity
{
Function = null;
} else {
currentPdfFile.readObject(Function);
}
if (Function != null) {
functions[count] = FunctionFactory.getFunction(Function, currentPdfFile);
}
}
return functions;
}
/**
* apply DecodeArray
*/
public static void applyDecodeArray(final byte[] data, final int d, final float[] decodeArray, final int type) {
final int count = decodeArray.length;
int maxValue = 0;
for (final float aDecodeArray : decodeArray) {
if (maxValue < aDecodeArray) {
maxValue = (int) aDecodeArray;
}
}
/*
* see if will not change output
* and ignore if unnecessary
*/
boolean isIdentify = true; //assume true and disprove
final int compCount = decodeArray.length;
for (int comp = 0; comp < compCount; comp += 2) {
if ((decodeArray[comp] != 0.0f) || ((decodeArray[comp + 1] != 1.0f) && (decodeArray[comp + 1] != 255.0f))) {
isIdentify = false;
comp = compCount;
}
}
if (isIdentify) {
return;
}
if (d == 1) { //bw straight switch (ignore gray)
//changed for /baseline_screens/11dec/Jones contract for Dotloop.pdf
if (decodeArray[0] > decodeArray[1]) {
//if(type!=ColorSpaces.DeviceGray){ // || (decodeArray[0]>decodeArray[1] && XObject instanceof MaskObject)){
final int byteCount = data.length;
for (int ii = 0; ii < byteCount; ii++) {
data[ii] = (byte) ~data[ii];
}
}
} else if ((d == 8 && maxValue > 1) && (type == ColorSpaces.DeviceRGB || type == ColorSpaces.CalRGB || type == ColorSpaces.DeviceCMYK)) {
int j = 0;
for (int ii = 0; ii < data.length; ii++) {
int currentByte = (data[ii] & 0xff);
if (currentByte < decodeArray[j]) {
currentByte = (int) decodeArray[j];
} else if (currentByte > decodeArray[j + 1]) {
currentByte = (int) decodeArray[j + 1];
}
j += 2;
if (j == decodeArray.length) {
j = 0;
}
data[ii] = (byte) currentByte;
}
} else if (d == 8 && maxValue == 1 && type == ColorSpaces.DeviceCMYK) {
final int[] tempDecode = new int[decodeArray.length];
for (int i = 0; i < decodeArray.length; i++) {
tempDecode[i] = (int) (decodeArray[i] * 255);
}
int j = 0;
for (int ii = 0; ii < data.length; ii++) {
int pp = (data[ii] & 0xff);
pp = (pp * (tempDecode[j + 1] - tempDecode[j]) / 255) + tempDecode[j];
j += 2;
if (j == decodeArray.length) {
j = 0;
}
data[ii] = (byte) pp;
}
} else {
/*
* apply array
*
* Assumes black and white or gray colorspace
* */
maxValue = (d << 1);
final int divisor = maxValue - 1;
for (int ii = 0; ii < data.length; ii++) {
final byte currentByte = data[ii];
int dd = 0;
int newByte = 0;
int min = 0, max = 1;
for (int bits = 7; bits > -1; bits--) {
int current = (currentByte >> bits) & 1;
current = (int) (decodeArray[min] + (current * ((decodeArray[max] - decodeArray[min]) / (divisor))));
if (current > maxValue) {
current = maxValue;
}
if (current < 0) {
current = 0;
}
current = ((current & 1) << bits);
newByte += current;
//rotate around array
dd += 2;
if (dd == count) {
dd = 0;
min = 0;
max = 1;
} else {
min += 2;
max += 2;
}
}
data[ii] = (byte) newByte;
}
}
}
static boolean isExtractionAllowed(final PdfObjectReader currentPdfFile) {
final PdfFileReader objectReader = currentPdfFile.getObjectReader();
final DecryptionFactory decryption = objectReader.getDecryptionObject();
return decryption == null || decryption.getBooleanValue(PDFflags.IS_EXTRACTION_ALLOWED);
}
}