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

org.jpedal.parser.image.ImageCommands Maven / Gradle / Ivy

There is a newer version: 7.15.25
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
 *
 @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);

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy