All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.idrsolutions.pdf.color.shading.TensorContext Maven / Gradle / Ivy

There is a newer version: 20151002
Show newest version
/*
 * ===========================================
 * 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
 *
     This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


 *
 * ---------------
 * 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() getShapes() {
        return shapes;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy