Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* ===========================================
* 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@
*
* ---------------
* TensorContext.java
* ---------------
*/
package com.idrsolutions.pdf.color.shading;
import java.awt.Color;
import java.awt.PaintContext;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jpedal.color.GenericColorSpace;
import org.jpedal.function.PDFFunction;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
/**
* @author suda
*/
public class TensorContext implements PaintContext {
private final GenericColorSpace shadingColorSpace;
private final float[] background;
private int bitsPerCoordinate;
private int bitsPerComponent;
private int bitsPerFlag;
private int colCompCount;
private float[] decodeArr;
// private final float[][] CTM;
private ArrayList pp; //patch points
private ArrayList pc; // patch colors
private final ArrayList shapes;
private BitReader reader;
private final PDFFunction[] function;
private final boolean isRecursive;
private AffineTransform invAffine = invAffine = new AffineTransform();
/**
* constructor uses cached shapes values to create a context
*
* @param shapes
* @param background
*/
TensorContext(final AffineTransform xform, final GenericColorSpace shadingColorSpace, final ArrayList shapes, final float[] background, final float[][] mm, final PDFFunction[] function) {
this.shapes = shapes;
this.background = background;
this.shadingColorSpace = shadingColorSpace;
isRecursive = shapes.size() < 50;
AffineTransform shadeAffine = new AffineTransform();
if (mm != null) {
shadeAffine = new AffineTransform(mm[0][0], mm[0][1], mm[1][0], mm[1][1], mm[2][0], mm[2][1]);
}
try {
final AffineTransform invXF = xform.createInverse();
final AffineTransform invSH = shadeAffine.createInverse();
invSH.concatenate(invXF);
invAffine = (AffineTransform) invSH.clone();
} catch (final NoninvertibleTransformException ex) {
LogWriter.writeLog("Exception " + ex + ' ');
}
this.function = function;
}
TensorContext(final AffineTransform xform, final GenericColorSpace shadingColorSpace, final float[] background, final PdfObject shadingObject, final float[][] mm, final PDFFunction[] function) {
this.shadingColorSpace = shadingColorSpace;
this.background = background;
bitsPerComponent = shadingObject.getInt(PdfDictionary.BitsPerComponent);
bitsPerFlag = shadingObject.getInt(PdfDictionary.BitsPerFlag);
bitsPerCoordinate = shadingObject.getInt(PdfDictionary.BitsPerCoordinate);
decodeArr = shadingObject.getFloatArray(PdfDictionary.Decode);
final boolean hasSmallBits = bitsPerFlag < 8 || bitsPerComponent < 8 || bitsPerCoordinate < 8;
reader = new BitReader(shadingObject.getDecodedStream(), hasSmallBits);
colCompCount = shadingColorSpace.getColorComponentCount();
if (decodeArr != null) {
colCompCount = (decodeArr.length - 4) / 2;
}
AffineTransform shadeAffine = new AffineTransform();
if (mm != null) {
shadeAffine = new AffineTransform(mm[0][0], mm[0][1], mm[1][0], mm[1][1], mm[2][0], mm[2][1]);
}
try {
final AffineTransform invXF = xform.createInverse();
final AffineTransform invSH = shadeAffine.createInverse();
invSH.concatenate(invXF);
invAffine = (AffineTransform) invSH.clone();
} catch (final NoninvertibleTransformException ex) {
LogWriter.writeLog("Exception " + ex + ' ');
}
this.function = function;
pp = new ArrayList();
pc = new ArrayList();
shapes = new ArrayList();
process();
adjustPoints();
isRecursive = shapes.size() < 50;
}
/**
* process the datastream and update the variables
*/
private void process() {
while (reader.getPointer() < reader.getTotalBitLen()) {
final int flag = reader.getPositive(bitsPerFlag);
final Point2D[] a4 = new Point2D[4];
final Color[] a2 = new Color[2];
final float[] cc = new float[colCompCount];
switch (flag) {
case 0:
for (int i = 0; i < 12; i++) {
final Point2D p = getPointCoords();
pp.add(p);
}
for (int i = 0; i < 4; i++) {
getPointCoords(); //ignore this data at the moment
}
for (int i = 0; i < 4; i++) {
for (int z = 0; z < colCompCount; z++) {
cc[z] = reader.getFloat(bitsPerComponent);
}
final Color color = calculateColor(cc);
pc.add(color);
}
break;
case 1:
a4[0] = pp.get(pp.size() - 9);
a4[1] = pp.get(pp.size() - 8);
a4[2] = pp.get(pp.size() - 7);
a4[3] = pp.get(pp.size() - 6);
pp.addAll(Arrays.asList(a4).subList(0, 4));
for (int i = 0; i < 8; i++) {
final Point2D p = getPointCoords();
pp.add(p);
}
for (int i = 0; i < 4; i++) {
getPointCoords();
}
a2[0] = pc.get(pc.size() - 3);
a2[1] = pc.get(pc.size() - 2);
pc.addAll(Arrays.asList(a2));
for (int i = 0; i < 2; i++) {
for (int z = 0; z < colCompCount; z++) {
cc[z] = reader.getFloat(bitsPerComponent);
}
final Color color = calculateColor(cc);
pc.add(color);
}
//do color mapping
break;
case 2:
a4[0] = pp.get(pp.size() - 6);
a4[1] = pp.get(pp.size() - 5);
a4[2] = pp.get(pp.size() - 4);
a4[3] = pp.get(pp.size() - 3);
pp.addAll(Arrays.asList(a4).subList(0, 4));
for (int i = 0; i < 8; i++) {
final Point2D p = getPointCoords();
pp.add(p);
}
for (int i = 0; i < 4; i++) {
getPointCoords();
}
a2[0] = pc.get(pc.size() - 2);
a2[1] = pc.get(pc.size() - 1);
pc.addAll(Arrays.asList(a2));
for (int i = 0; i < 2; i++) {
for (int z = 0; z < colCompCount; z++) {
cc[z] = reader.getFloat(bitsPerComponent);
}
final Color color = calculateColor(cc);
pc.add(color);
}
// do color mapping
break;
case 3:
a4[0] = pp.get(pp.size() - 3);
a4[1] = pp.get(pp.size() - 2);
a4[2] = pp.get(pp.size() - 1);
a4[3] = pp.get(pp.size() - 12);
pp.addAll(Arrays.asList(a4).subList(0, 4));
for (int i = 0; i < 8; i++) {
final Point2D p = getPointCoords();
pp.add(p);
}
for (int i = 0; i < 4; i++) {
getPointCoords();
}
a2[0] = pc.get(pc.size() - 1);
a2[1] = pc.get(pc.size() - 4);
pc.addAll(Arrays.asList(a2));
for (int i = 0; i < 2; i++) {
for (int z = 0; z < colCompCount; z++) {
cc[z] = reader.getFloat(bitsPerComponent);
}
final Color color = calculateColor(cc);
pc.add(color);
}
break;
}
}
}
/**
* convert small points to x,y full space points
*/
private void adjustPoints() {
if (decodeArr != null) { //some odd files have decode array as null
final float xMin = decodeArr[0];
final float xMax = decodeArr[1];
final float yMin = decodeArr[2];
final float yMax = decodeArr[3];
final float xw = xMax - xMin;
final float yw = yMax - yMin;
final ArrayList tempPoints = new ArrayList();
for (final Point2D p : pp) {
float xx = (float) p.getX();
float yy = (float) p.getY();
xx = (xw * xx) + xMin;
yy = (yw * yy) + yMin;
tempPoints.add(new Point2D.Float(xx, yy));
}
pp.clear();
for (final Point2D t : tempPoints) {
pp.add(t);
}
}
final Point2D[] pArr = new Point2D[pp.size()];
for (int i = 0; i < pArr.length; i++) {
pArr[i] = pp.get(i);
}
final int totalPatches = pp.size() / 12;
int offset = 0;
for (int i = 0; i < totalPatches; i++) {
final Point2D[] pointArr = new Point2D[12];
final Color[] colors = {pc.get(i * 4), pc.get(i * 4 + 1), pc.get(i * 4 + 2), pc.get(i * 4 + 3)};
System.arraycopy(pArr, offset, pointArr, 0, 12);
final Shape67 sh = new Shape67(pointArr, colors);
shapes.add(sh);
offset += 12;
}
}
private Point2D getPointCoords() {
float x = 0;
float y = 0;
for (int z = 0; z < 2; z++) {
switch (z) {
case 0:
x = reader.getFloat(bitsPerCoordinate);
break;
case 1:
y = reader.getFloat(bitsPerCoordinate);
break;
}
}
return new Point2D.Float(x, y);
}
@Override
public void dispose() {
reader = null;
}
@Override
public ColorModel getColorModel() {
return ColorModel.getRGBdefault();
}
@Override
public Raster getRaster(final int xStart, final int yStart, final int w, final int h) {
final WritableRaster raster = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB).getRaster();
final int[] data = ((DataBufferInt) raster.getDataBuffer()).getData();
if (background != null) {
int pos = 0;
shadingColorSpace.setColor(background, 4);
final Color c = (Color) shadingColorSpace.getColor();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
data[pos++] = 255 << 24 | c.getRGB();
}
}
}
final Rectangle rect = new Rectangle(xStart, yStart, w, h);
final Shape rr = invAffine.createTransformedShape(rect);
final Rectangle2D rect2D = rr.getBounds2D();
final List foundList = new ArrayList();
for (final Shape67 sh : shapes) {
if (sh.getMinX() < rect2D.getMaxX()
&& sh.getMinY() < rect2D.getMaxY()
&& sh.getShape().intersects(rect2D)) {
foundList.add(sh);
}
}
float xx, yy;
for (final Shape67 sh : foundList) {
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
final float[] src = {x + xStart, y + yStart};
invAffine.transform(src, 0, src, 0, 1);
xx = src[0];
yy = src[1];
final GeneralPath path = sh.getShape();
// check with bounds first before going to shape to speedup execution
if (path.contains(xx, yy)) {
final Point2D p = new Point2D.Float(xx, yy);
final Color result = sh.findPointColor(p, isRecursive);
if (result != null) {
final int base = (y * w + x);
data[base] = 255 << 24 | result.getRGB();
}
}
}
}
}
return raster;
}
private Color calculateColor(final float[] val) {
final Color col;
if (function == null) {
shadingColorSpace.setColor(val, colCompCount);
col = new Color(shadingColorSpace.getColor().getRGB());
} else {
final float[] colValues = ShadingFactory.applyFunctions(function, val);
shadingColorSpace.setColor(colValues, colValues.length);
col = (Color) shadingColorSpace.getColor();
}
return col;
}
public ArrayList getShapes() {
return shapes;
}
}