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

org.jpedal.parser.image.mask.SMaskDecoder 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


 *
 * ---------------
 * SMaskDecoder.java
 * ---------------
 */

package org.jpedal.parser.image.mask;

import java.nio.ByteBuffer;
import java.util.Arrays;
import org.jpedal.color.ColorSpaces;
import org.jpedal.color.GenericColorSpace;
import org.jpedal.color.JPEGDecoder;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.parser.image.JPeg2000ImageDecoder;
import org.jpedal.parser.image.data.ImageData;

/**
 *
 * @author markee
 */
public class SMaskDecoder {
    
    public static byte[] applyJPX_JBIG_Smask(final ImageData imageData, final ImageData smaskData, byte[] maskData, final PdfObject imageObject, final PdfObject maskObject, final GenericColorSpace colorSpace, final GenericColorSpace maskCS){
        byte[] objectData = imageData.getObjectData();
        int iw=imageData.getWidth();
        int ih=imageData.getHeight();
        final int id=imageData.getDepth();
        
        float[] matte = maskObject.getFloatArray(PdfDictionary.Matte);
        
        smaskData.getFilter(maskObject);
        if(smaskData.isDCT()){
            maskData=JPEGDecoder.getBytesFromJPEG(maskData,maskCS,maskObject);
            maskObject.setMixedArray(PdfDictionary.Filter,null);
            maskObject.setDecodedStream(maskData);
        }else if(smaskData.isJPX()){
            maskData=JPeg2000ImageDecoder.getBytesFromJPEG2000(maskData);
            maskObject.setMixedArray(PdfDictionary.Filter,null);
            maskObject.setDecodedStream(maskData);
        }else {
            objectData = ColorSpaceConvertor.normaliseTo8Bit(id, iw, ih, objectData);
        }
                
        final int sw=smaskData.getWidth();
        final int sh=smaskData.getHeight();
        final int sd=smaskData.getDepth();
        
        final float [] decodeArr = maskObject.getFloatArray(PdfDictionary.Decode);
                
        if(decodeArr!=null && decodeArr[0]==1 && decodeArr[1]==0){ // data inverted refer to dec2011/example.pdf
            for (int i = 0; i < maskData.length; i++) {
                maskData[i]^= 0xff;
            }
        }
        
        byte[] index=colorSpace.getIndexedMap();
       
        if(index!=null){
            index=colorSpace.convertIndexToRGB(index);
            int nComp = imageData.getCompCount();
            nComp = colorSpace.getID()==ColorSpaces.DeviceGray ? 3 : nComp;            
            objectData=ColorSpaceConvertor.convertIndexToRGBByte(index, iw, ih, nComp, id, objectData, false, false);
        } else if (imageData.isDCT() || imageData.isJPX() || imageData.isJBIG()) {      
         
        } else if(colorSpace.getID()==ColorSpaces.DeviceGray){
            objectData=colorSpace.dataToRGBByteArray(objectData,iw,ih);
            if(matte!=null){
                matte = new float[]{matte[0],matte[0],matte[0]};
            }
        } else if(colorSpace.getID()==ColorSpaces.CalRGB){
        } else if(colorSpace.getID()==ColorSpaces.DeviceRGB){
        } else {
            objectData=colorSpace.dataToRGBByteArray(objectData,iw,ih);   
        }
        
        maskData = ColorSpaceConvertor.normaliseTo8Bit(sd,sw, sh, maskData);
        
        int imageDim = iw*ih;
        final int maskDim = sw*sh;
        if(imageDim>maskDim){
            maskData  = getScaledBytes(maskData, sw, sh, iw, ih);            
        }else if(maskDim>imageDim){
            objectData = getScaledBytes(objectData, iw, ih, sw, sh);
            imageDim = maskDim;
            iw = sw;
            ih = sh;
        }else{
            //do nothing
        }
        int p = 0;
               
        final ByteBuffer buffer = ByteBuffer.allocate(iw*ih*4);
                        
        if (imageDim == objectData.length) {
            int aa = 0;
            for (int i = 0; i < imageDim; i++) {
                final byte r = objectData[i] ;
                for (int j = 0; j < 3; j++) {
                    buffer.put(r);
                }
                buffer.put(maskData[aa++]); // write out maskData[aa++] directly and lose a ?
            }
        } else {
            if(matte!=null){
                for (int i = 0; i < maskData.length; i++) {
                    final int a = maskData[i] & 0xff;
                    int r = objectData[p++] & 0xff;
                    int g = objectData[p++] & 0xff;
                    int b = objectData[p++] & 0xff;
                    
                    if(a!=0){
                        final double k = 255.0/a;
                        r = (int) ((r-matte[0])*k+matte[0]);
                        g = (int) ((g-matte[1])*k+matte[1]);
                        b = (int) ((b-matte[2])*k+matte[2]);

                        r = r < 0 ? 0 : r > 255 ? 255 : r;
                        g = g < 0 ? 0 : g > 255 ? 255 : g;
                        b = b < 0 ? 0 : b > 255 ? 255 : b;
                    }
                    final byte[] bb = {(byte)r,(byte)g,(byte)b,(byte)a};
                    buffer.put(bb);
                    
                }
            }else{
                final int expected = imageDim*3;
                if(objectData.lengthmaxSize){
                dim=maxSize;
            }
            byte[] rr = new byte[dim];
            byte[] gg = new byte[dim];
            byte[] bb = new byte[dim];
            int p = 0;
            for (int i = 0; i < dim; i++) {
                    rr[i] = data[p++];
                    gg[i] = data[p++];
                    bb[i] = data[p++];
            }
            rr = rescaleComponent(rr, sw, sh, dw, dh);
            gg = rescaleComponent(gg, sw, sh, dw, dh);
            bb = rescaleComponent(bb, sw, sh, dw, dh);
            
            p=0;
            dim = dw*dh;
            final byte[] temp = new byte[dim*3];
            for (int i = 0; i < dim; i++) {
                temp[p++] = rr[i];
                temp[p++] = gg[i];
                temp[p++] = bb[i];
            }
            return temp;
        }
    }
    
    private static byte[] rescaleComponent(byte[] data, final int sw, int sh, final int dw, final int dh){
        if(data.length==1){
            final byte a = data[0];
            data = new byte[dw*dh];
            Arrays.fill(data, a);
            return data;
        }else if(sh==1){
            final byte[] temp = new byte[2*sw];
            System.arraycopy(data, 0, temp, 0, sw);
            System.arraycopy(data, 0, temp, sw, sw);
            sh = 2;
            data = temp;
        }
        
        final float ratioW=sw/(float)dw;
        final float ratioH=sh/(float)dh;
        final byte[] combinedData=new byte[dw*dh];
        final int rawDataSize=data.length;
        int i = 0;
        
        try{
            for(int mY=0;mY> 16);
//            yDiff = y - (yr << 16);
//            yDiffMinus = 65536 - yDiff;
//            yIndex = yr * sw;
//            x = 0;
//            for (int j = 0; j < dw; j++) {
//                xr = (int) (x >> 16);
//                xDiff = x - (xr << 16);
//                xDiffMinus = 65536 - xDiff;
//                index = yIndex + xr;
//
//                A = data[index] & 0xff;
//                B = data[index + 1] & 0xff;
//                C = data[index + sw] & 0xff;
//                D = data[index + sw + 1] & 0xff;
//
//                gray = (int) ((A * xDiffMinus * yDiffMinus
//                        + B * xDiff * yDiffMinus
//                        + C * yDiff * xDiffMinus
//                        + D * xDiff * yDiff) >> 32);
//
//                temp[offset++] = (byte) gray;
//
//                x += xRatio;
//            }
//            y += yRatio;
//        }
//        return temp;
    }
    
    public static byte[] applySMask(byte[] maskData, final ImageData imageData,final GenericColorSpace decodeColorData, final PdfObject newSMask, final PdfObject XObject) {
        
        byte[] objectData=imageData.getObjectData();
        
        /*
        * Image data
        */
        final int w=imageData.getWidth();
        final int h=imageData.getHeight();
        final int d=imageData.getDepth();
        
        /*
        * Smask data (ASSUME single component at moment)
        */
        final int maskW=newSMask.getInt(PdfDictionary.Width);
        final int maskH=newSMask.getInt(PdfDictionary.Height);
        final int maskD=newSMask.getInt(PdfDictionary.BitsPerComponent);
        
        objectData = MaskDataDecoder.convertSmaskData(decodeColorData, objectData, w, h, imageData, d, maskD, maskData, newSMask);
        
        //needs to be 'normalised to 8  bit'
        if(maskD!=8){
            maskData=ColorSpaceConvertor.normaliseTo8Bit(maskD, maskW, maskH, maskData);
        }
        
        //add mask as a element so we now have argb
        if(w==maskW && h==maskH){
            //System.out.println("Same size");
            objectData=buildUnscaledByteArray(w, h, objectData, maskData);
        }else if(w15){
                is4Bit=false;
                break;
            }
        }
        
        if(is4Bit){
            for (int ii=0;ii




© 2015 - 2024 Weber Informatics LLC | Privacy Policy