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-2016 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
*
* ---------------
* ImageDecoder.java
* ---------------
*/
package org.jpedal.parser.image;
import com.idrsolutions.pdf.color.shading.BitReader;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.TexturePaint;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import org.jpedal.color.*;
import org.jpedal.exception.PdfException;
import org.jpedal.external.ErrorTracker;
import org.jpedal.external.ImageDataHandler;
import org.jpedal.external.ImageHandler;
import org.jpedal.images.ImageTransformer;
import org.jpedal.images.ImageTransformerDouble;
import org.jpedal.images.SamplingFactory;
import org.jpedal.io.ColorSpaceConvertor;
import org.jpedal.io.ObjectStore;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.objects.PdfImageData;
import org.jpedal.objects.PdfPageData;
import org.jpedal.objects.raw.PdfArrayIterator;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.parser.BaseDecoder;
import org.jpedal.parser.ParserOptions;
import org.jpedal.parser.PdfObjectCache;
import org.jpedal.parser.ValueTypes;
import org.jpedal.parser.image.data.ImageData;
import org.jpedal.parser.image.downsample.DownSampler;
import org.jpedal.parser.image.mask.MaskDataDecoder;
import org.jpedal.parser.image.mask.MaskDecoder;
import org.jpedal.parser.image.mask.SMaskDecoder;
import org.jpedal.parser.image.utils.ConvertMaskToImage;
import org.jpedal.render.SwingDisplay;
import org.jpedal.utils.LogWriter;
public class ImageDecoder extends BaseDecoder{
private boolean cacheLargeImages;
//Allow print to use transparency in printing instead of removing it
public static boolean allowPrintTransparency;
protected ParserOptions parserOptions;
final PdfImageData pdfImages;
private boolean getSamplingOnly;
//flag to show if image transparent*/
boolean isMask=true;
String imagesInFile;
PdfObjectCache cache;
final ImageHandler customImageHandler;
final PdfPageData pageData;
final ObjectStore objectStoreStreamRef;
//name of current image in pdf
String currentImage = "";
final ErrorTracker errorTracker;
final PdfObjectReader currentPdfFile;
//images on page
public final int imageCount;
public ImageDecoder(final int imageCount, final PdfObjectReader currentPdfFile, final ErrorTracker errorTracker, final ImageHandler customImageHandler, final ObjectStore objectStoreStreamRef, final PdfImageData pdfImages, final PdfPageData pageData, final String imagesInFile) {
this.imageCount=imageCount;
this.currentPdfFile=currentPdfFile;
this.errorTracker=errorTracker;
this.customImageHandler=customImageHandler;
this.objectStoreStreamRef=objectStoreStreamRef;
this.pdfImages=pdfImages;
this.pageData=pageData;
this.imagesInFile=imagesInFile;
}
private GenericColorSpace setupXObjectColorspace(final PdfObject XObject, final ImageData imageData){
final int width=imageData.getWidth();
final int height=imageData.getHeight();
final int depth=imageData.getDepth();
//handle colour information
GenericColorSpace decodeColorData=new DeviceRGBColorSpace();
final PdfArrayIterator ColorSpace=XObject.getMixedArray(PdfDictionary.ColorSpace);
if(ColorSpace.getTokenCount()>0){ //if not set will be zero
decodeColorData= ColorspaceFactory.getColorSpaceInstance(currentPdfFile, ColorSpace);
}
decodeColorData.setPrinting(parserOptions.isPrinting());
//track colorspace use
cache.put(PdfObjectCache.ColorspacesUsed, decodeColorData.getID(),"x");
//fix for odd itext file (/PDFdata/baseline_screens/debug3/Leistung.pdf)
final byte[] indexData=decodeColorData.getIndexedMap();
if(depth==8){
final byte[] objectData=imageData.getObjectData();
if(indexData!=null && decodeColorData.getID()==ColorSpaces.DeviceRGB && width*height==objectData.length) {
final PdfObject newMask = XObject.getDictionary(PdfDictionary.Mask);
final int[] maskArray = XObject.getIntArray(PdfDictionary.Mask);
if (newMask != null || maskArray!=null) {
//this specific case has all zeros
if (maskArray != null && maskArray.length == 2 && maskArray[0] == 255 && maskArray[0] == maskArray[1] && decodeColorData.getIndexedMap() != null && decodeColorData.getIndexedMap().length == 768) {
//see if index looks corrupt (ie all zeros) We exit as soon as we have disproved
boolean isCorrupt = true;
for (int jj = 0; jj < 768; jj++) {
if (indexData[jj] != 0) {
isCorrupt = false;
jj = 768;
}
}
if (isCorrupt) {
decodeColorData = new DeviceGrayColorSpace();
}
}
}
}
}
//pass through decode params
final PdfObject parms=XObject.getDictionary(PdfDictionary.DecodeParms);
if(parms!=null) {
decodeColorData.setDecodeParms(parms);
}
return decodeColorData;
}
public BufferedImage processImageXObject(PdfObject XObject, String image_name, byte[] objectData, final String details) throws PdfException {
BufferedImage image=null;
//add filename to make it unique
image_name = parserOptions.getFileName()+ '-' + image_name;
// System.out.println("XObject="+XObject+" "+XObject.getObjectRefAsString());
PdfObject newSMask=XObject.getDictionary(PdfDictionary.SMask);
final PdfObject newMask=XObject.getDictionary(PdfDictionary.Mask);
final int[] maskArray=XObject.getIntArray(PdfDictionary.Mask);
ImageData imageData=new ImageData(XObject, objectData);
imageData.getFilter(XObject);
GenericColorSpace decodeColorData = setupXObjectColorspace(XObject, imageData);
imageData.setCompCount(decodeColorData.getColorSpace().getNumComponents());
/*
* New code to apply SMask and Mask to data
* (note old isMask)
*/
byte[] convertedData=XObject.getConvertedData();
if(convertedData!=null){ //reuse converted mask data
objectData=convertedData;
decodeColorData=new DeviceRGBColorSpace();
//imageData.setObjectData(objectData);
imageData=null;
}else if(newSMask!=null || newMask!=null || maskArray!=null){
if(newSMask!=null && XObject.getInt(PdfDictionary.Width)==1 && XObject.getInt(PdfDictionary.Height)==1 && XObject.getInt(PdfDictionary.BitsPerComponent)==8){ //swap out the image with inverted SMask if empty
//silly case we handle in code below // /baseline_screens/11dec/grayscale.pdf
}else{
//WE NEED TO CONVERT JPG to raw DATA in IMAGE
if(imageData.isDCT()){
objectData=JPEGDecoder.getBytesFromJPEG(objectData,decodeColorData,XObject);
imageData.setObjectData(objectData);
XObject.setMixedArray(PdfDictionary.Filter,null);
XObject.setDecodedStream(objectData);
}else if(imageData.isJPX()){
objectData=JPeg2000ImageDecoder.getBytesFromJPEG2000(objectData);
if(decodeColorData.getID() == ColorSpaces.DeviceN){
objectData = ((DeviceNColorSpace)decodeColorData).getRGBBytes(objectData, imageData.getWidth(), imageData.getHeight());
}
imageData.setObjectData(objectData);
XObject.setMixedArray(PdfDictionary.Filter,null);
XObject.setDecodedStream(objectData);
decodeColorData=new DeviceRGBColorSpace();
}
if(newSMask!=null){
///WE NEED TO CONVERT JPG to raw DATA in smask as well
ImageData smaskImageData=new ImageData(newSMask, null);
smaskImageData.getFilter(newSMask);
GenericColorSpace maskColorSpace = setupXObjectColorspace(newSMask, smaskImageData);
byte[] maskData =currentPdfFile.readStream(newSMask,true,true,false, false,false, newSMask.getCacheName(currentPdfFile.getObjectReader()));
if(1==1){
objectData = SMaskDecoder.applyJPX_JBIG_Smask(imageData, smaskImageData, maskData,XObject, newSMask, decodeColorData, maskColorSpace);
}else{ // old method
maskData = MaskDataDecoder.getSMaskData(maskData,smaskImageData, newSMask,setupXObjectColorspace(newSMask, smaskImageData));
objectData=SMaskDecoder.applySMask(maskData,imageData,decodeColorData, newSMask,XObject);
}
XObject.setConvertedData(objectData);
}else{ //mask
byte[] index=decodeColorData.getIndexedMap();
if(index!=null){
index=decodeColorData.convertIndexToRGB(index);
if(maskArray!=null){
return getIndexedMaskImage(index, imageData, maskArray);
}
objectData=ColorSpaceConvertor.convertIndexToRGBByte(index, imageData.getWidth(), imageData.getHeight(), imageData.getCompCount(), imageData.getDepth(), objectData, false, false);
decodeColorData=new DeviceRGBColorSpace();
imageData.setObjectData(objectData);
decodeColorData.setIndex(null, 0);
// imageData.setCompCount(3);
// imageData.setDepth(8);
}
///WE NEED TO CONVERT JPG to raw DATA in mask as well
ImageData maskImageData;
if(newMask==null){
maskImageData=new ImageData(XObject, objectData);
}else{
maskImageData=new ImageData(newMask, objectData);
}
if(maskArray!=null){
return MaskDataDecoder.applyMaskArray(imageData, maskArray);
}
byte[] maskData= currentPdfFile.readStream(newMask, true, true, false, false, false, newMask.getCacheName(currentPdfFile.getObjectReader()));
maskData = MaskDataDecoder.getSMaskData(maskData,maskImageData, newMask,setupXObjectColorspace(newMask, maskImageData));
objectData=MaskDecoder.applyMask(imageData,decodeColorData,newMask,XObject,maskData);
XObject.setConvertedData(objectData);
decodeColorData=new DeviceRGBColorSpace();
XObject.setDictionary(PdfDictionary.Mask, null);
XObject.setIntArray(PdfDictionary.Mask, null);
}
// String dest="/Users/markee/Desktop/deviceRGB/"+org.jpedal.DevFlags.currentFile.substring(org.jpedal.DevFlags.currentFile.lastIndexOf("/"));
// ObjectStore.copy(org.jpedal.DevFlags.currentFile, dest);
//also set SMask to null (will set image to DeviceRGB below
//XObject.setDictionary(PdfDictionary.SMask, null);
imageData=null;
}
}
//reset if changed in Mask/SMask code
if(imageData==null){
imageData=new ImageData(XObject, objectData);
decodeColorData = new DeviceRGBColorSpace(true); //sets to 4 comp ARGB
imageData.setCompCount(4);
newSMask=null;
}
isMask= XObject.getBoolean(PdfDictionary.ImageMask);
LogWriter.writeLog("Processing XObject: " + image_name + ' ' + XObject.getObjectRefAsString() + " width=" + imageData.getWidth() + " Height=" + imageData.getHeight() +
" Depth=" + imageData.getDepth() + " colorspace=" + decodeColorData);
//allow user to process image
if(customImageHandler != null && !(customImageHandler instanceof ImageDataHandler)){
image= customImageHandler.processImageData(gs,XObject); //user gets raw JPEG data
}
//deal with special case of 1x1 pixel backed onto large inverted Smask which would be very slow in Generic code
//see (11dec/grayscale.pdf)
if(newSMask!=null && XObject.getInt(PdfDictionary.Width)==1 && XObject.getInt(PdfDictionary.Height)==1 && XObject.getInt(PdfDictionary.BitsPerComponent)==8){ //swap out the image with inverted SMask if empty
image = ConvertMaskToImage.convert(newSMask, currentPdfFile);
}else if(customImageHandler==null ||(image==null && !customImageHandler.alwaysIgnoreGenericHandler())) {
image = processImage(decodeColorData, imageData, isMask, XObject);
}
//add details to string so we can pass back
if(ImageCommands.trackImages && image!=null && details!=null){
setImageInfo(imageData, details, decodeColorData, image);
}
return image;
}
private static BufferedImage getIndexedMaskImage(byte[] index, ImageData imageData, int[] maskArray) {
int d = imageData.getDepth();
int p = 0;
int c = 0;
boolean[] invisible = new boolean[1 << d];
for (int i = 0; i < maskArray.length; i+=2) {
int start = maskArray[i];
int end = maskArray[i+1];
if(start==end){
invisible[start] = true;
}else{
for (int j = start; j < end; j++) {
invisible[j] = true;
}
}
}
int[] indexColors = new int[index.length / 3];
for (int i = 0; i < indexColors.length; i++) {
indexColors[i] = (255 << 24) | ((index[c++] & 0xff) << 16) | ((index[c++] & 0xff) << 8) | (index[c++] & 0xff);
}
BitReader reader = new BitReader(imageData.getObjectData(), d < 8);
BufferedImage img = new BufferedImage(imageData.getWidth(), imageData.getHeight(), BufferedImage.TYPE_INT_ARGB);
int output[] = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
int imageDim = imageData.getWidth() * imageData.getHeight();
int w = imageData.getWidth();
int wc = 0;
for (int i = 0; i < imageDim; i++) {
int v = reader.getPositive(d);
if(!invisible[v]){
output[p++] = indexColors[v];
}else{
p++;
}
wc++;
if (wc == w) {
int balance = 8 - (reader.getPointer() % 8);
wc = 0;
if (balance != 8) {
reader.getPositive(balance);
}
}
}
return img;
}
private void setImageInfo(final ImageData imageData, final String details, GenericColorSpace decodeColorData, BufferedImage image) {
final int width=imageData.getWidth();
final int height=imageData.getHeight();
//work out effective dpi
float dpi = gs.CTM[0][0];
if(dpi ==0) {
dpi = gs.CTM[0][1];
}
if(dpi <0) {
dpi = -dpi;
}
dpi =(int)(width/dpi*100);
//add details to string
final StringBuilder imageInfo=new StringBuilder(details);
imageInfo.append(" w=");
imageInfo.append(width);
imageInfo.append(" h=");
imageInfo.append(height);
imageInfo.append(' ');
imageInfo.append((int) dpi);
imageInfo.append(' ');
imageInfo.append(ColorSpaces.IDtoString(decodeColorData.getID()));
imageInfo.append(" (");
imageInfo.append(image.getWidth());
imageInfo.append(' ');
imageInfo.append(image.getHeight());
imageInfo.append(" type=");
imageInfo.append(image.getType());
imageInfo.append(')');
if(imagesInFile.isEmpty()) {
imagesInFile = imageInfo.toString();
} else {
imageInfo.append('\n');
imageInfo.append(imagesInFile);
imagesInFile=imageInfo.toString();
}
}
public void setSamplingOnly(final boolean getSamplingOnly){
this.getSamplingOnly=getSamplingOnly;
}
public String getImagesInFile() {
return this.imagesInFile;
}
@Override
public void setParams(final ParserOptions parserOptions) {
this.parserOptions=parserOptions;
//Set flag to allow tunring on/off transparency optimisations in printing
String value = System.getProperty("org.jpedal.printTransparency");
if(value!=null){
ImageDecoder.allowPrintTransparency = parserOptions.isPrinting() && value.equalsIgnoreCase("true");
}
//Set flag to allow tunring on/off transparency optimisations in printing
value = System.getProperty("org.jpedal.viewerLargeImageCaching");
if(value!=null){
cacheLargeImages = value.equalsIgnoreCase("true");
}
}
/**
* save the current image, clipping and
* resizing clip. This gives us a clipped hires copy.
*/
public void generateClippedImage(BufferedImage image) {
final int pageRotation=pageData.getRotation(parserOptions.getPageNumber());
//object to scale and clip. Creating instance does the scaling
final ImageTransformerDouble image_transformation = new ImageTransformerDouble(gs, image, parserOptions.createScaledVersion(), 1, pageRotation);
//extract images either scaled/clipped or scaled then clipped
if(image_transformation!=null){
image_transformation.doubleScaleTransformShear();
//get intermediate image and save
image = image_transformation.getImage();
}
//convert mask into proper image if saving clipped images
if(isMask){
image = convertMaskToImage(image,gs.nonstrokeColorSpace.getColor().getRGB());
}
//@suda - image saved here is being saved out as garbage. Do we need to alter colorspace or issue in our image decoder.
//releate comment in JDeliHelper
if(objectStoreStreamRef.saveStoredImageAsBytes("CLIP_"+currentImage, image, false)) {
errorTracker.addPageFailureMessage("Problem saving " + image);
}
//complete the image and workout co-ordinates
image_transformation.completeImage();
//get final image to allow for way we draw 'upside down'
image = image_transformation.getImage();
//allow for null image returned (ie if too small)
if (image != null) {
//store final image on disk & in memory
if(parserOptions.imagesNeeded()){
//get initial values
float x = image_transformation.getImageX();
float y = image_transformation.getImageY();
float w = image_transformation.getImageW();
float h = image_transformation.getImageH();
pdfImages.setImageInfo(currentImage, parserOptions.getPageNumber(), x, y, w, h);
}
//
// //save the scaled/clipped version of image if allowed
// if(parserOptions.isFinalImagesExtracted()){
//
// image_transformation.doubleScaleTransformScale();
//
// objectStoreStreamRef.saveStoredImage(
// currentImage,
// ImageCommands.addBackgroundToMask(image, isMask),
// false,
// "png");
//
// }
}
}
private static BufferedImage convertMaskToImage(final BufferedImage outputImage, final int foreground) {
final int[] maskCol = {((foreground >> 16) & 0xFF), ((foreground >> 8) & 0xFF),((foreground) & 0xFF),255};
final BufferedImage img = new BufferedImage(outputImage.getWidth(), outputImage.getHeight(), outputImage.getType());
final Raster src = outputImage.getRaster();
final WritableRaster dest = img.getRaster();
final int[] values = new int[4];
final int w=outputImage.getWidth(),h=outputImage.getHeight();
for (int yy = 0; yy < h; yy++) {
for (int xx = 0; xx < w; xx++) {
//get raw color data
src.getPixel(xx, yy, values);
//System.out.println(values[0]+" "+values[1]+" "+values[2]+" "+values[3]+" ");
//if not transparent, fill with color
if (values[3] > 2) {
dest.setPixel(xx, yy, maskCol);
}
}
}
return img;
}
/**
* save the current image in raw and scaled/clipped version
* @param image
*/
public void generateTransformedImageSingle(BufferedImage image) {
//
if(parserOptions.isRawImagesExtracted()){
objectStoreStreamRef.saveStoredImageAsBytes('R'+currentImage,image,false);
}
// get clipped image and co-ords
final Area clipping_shape = gs.getClippingShape();
//object to scale and clip. Creating instance does the scaling
final ImageTransformer image_transformation =new ImageTransformer(gs,image);
//get initial values
float x = image_transformation.getImageX();
float y = image_transformation.getImageY();
float w = image_transformation.getImageW();
float h = image_transformation.getImageH();
//apply clip as well if exists and not inline image
if (customImageHandler!=null && clipping_shape != null && clipping_shape.getBounds().getWidth()>1 &&
clipping_shape.getBounds().getHeight()>1 && !customImageHandler.imageHasBeenScaled()) {
//see if clip is wider than image and ignore if so
if (!clipping_shape.contains(x, y, w, h)) {
//do the clipping
image_transformation.clipImage(clipping_shape);
//get ALTERED values
x = image_transformation.getImageX();
y = image_transformation.getImageY();
w = image_transformation.getImageW();
h = image_transformation.getImageH();
}
}
image = image_transformation.getImage();
//allow for null image returned (ie if too small)
if (image != null) {
pdfImages.setImageInfo(currentImage, parserOptions.getPageNumber(), x, y, w, h);
//save the scaled/clipped version of image if allowed
if(parserOptions.isFinalImagesExtracted()){
objectStoreStreamRef.saveStoredImageAsBytes(currentImage,ImageCommands.addBackgroundToMask(image, isMask), false);
}
}
}
/**
* read in the image and process and save raw image
*/
BufferedImage processImage(GenericColorSpace decodeColorData,
final ImageData imageData, final boolean imageMask,
final PdfObject XObject) throws PdfException {
//track its use
cache.put(PdfObjectCache.ColorspacesUsed, decodeColorData.getID(), "x");
imageData.getFilter(XObject);
BufferedImage image = null;//
//allow user to process image
if(customImageHandler instanceof ImageDataHandler){
image = customImageHandler.processImageData(gs, XObject);
} else if (imageData.isJPX()) {
removeJPXEncodingFromImageData(imageData, XObject);
} else if(imageData.isDCT()) {
int adobeColorTransform = 1;
PdfObject decodeParms=XObject.getDictionary(PdfDictionary.DecodeParms);
if(decodeParms!=null){
adobeColorTransform = decodeParms.getInt(PdfDictionary.ColorTransform);
}
byte[] objectData;
try {
objectData = JPEGDecoder.getUnconvertedBytesFromJPEG(imageData.getObjectData(), adobeColorTransform);
if (objectData == null) { //fix for lgpl version
objectData = JPEGDecoder.getBytesFromJPEGWithImageIO(imageData.getObjectData(), decodeColorData, XObject);
decodeColorData = new DeviceRGBColorSpace();
imageData.setCompCount(3);
imageData.setDecodeArray(null);
}
} catch (Exception e) {
LogWriter.writeLog("[PDF] Exception " + e + " Processing JPEG data in ImageDecoder");
objectData = JPEGDecoder.getBytesFromJPEGWithImageIO(imageData.getObjectData(), decodeColorData, XObject);
decodeColorData = new DeviceRGBColorSpace();
imageData.setCompCount(3);
imageData.setDecodeArray(null);
}
XObject.setMixedArray(PdfDictionary.Filter, null);
XObject.setDecodedStream(objectData);
imageData.setObjectData(objectData);
imageData.setDCT(false);
imageData.setDepth(8);
imageData.wasDCT(true);
}
if(image!=null){
return image;
}else{
return convertDataToImage(imageMask, imageData, XObject, decodeColorData);
}
}
static void removeJPXEncodingFromImageData(final ImageData imageData, final PdfObject XObject) {
final byte[] objectData = JPeg2000ImageDecoder.getUnconvertedBytesFromJPEG2000(imageData.getObjectData());
imageData.setObjectData(objectData);
XObject.setMixedArray(PdfDictionary.Filter, null);
XObject.setDecodedStream(objectData);
imageData.setDepth(8);
imageData.setIsJPX(false);
}
private BufferedImage convertDataToImage(final boolean imageMask, final ImageData imageData, final PdfObject XObject, GenericColorSpace decodeColorData) {
int sampling=1;
BufferedImage image;
//setup any imageMask
byte[] maskCol =null;
if (imageMask) {
maskCol=ImageCommands.getMaskColor(gs);
}
//setup sub-sampling
if(parserOptions.isRenderPage() && streamType!= ValueTypes.PATTERN){
setDownsampledImageSize(imageData, XObject,multiplyer,decodeColorData);
}
//down-sample size if displaying (some cases excluded at present)
if(parserOptions.isRenderPage() &&
decodeColorData.getID()!=ColorSpaces.ICC &&
imageData.getMode()!=ImageCommands.ID &&
(imageData.getDepth()==1 || imageData.getDepth()==8)
&& imageData.getpX()>0 && imageData.getpY()>0 && (SamplingFactory.isPrintDownsampleEnabled || !parserOptions.isPrinting())){
sampling=setSampling(imageData, decodeColorData);
if(sampling>1 && multiplyer>1){
sampling = (int) (sampling/ multiplyer);
}
}
//get sampling and exit from this code as we don't need to go further
if(getSamplingOnly){
int w=imageData.getWidth();
int h=imageData.getHeight();
if(imageData.getpX()>0 && imageData.getpY()>0){
final float scaleX=(((float)w)/imageData.getpX());
final float scaleY=(((float)h)/imageData.getpY());
if(scaleX>100 || scaleY>100){
//ignore
}else if(scaleX 0 && decodeColorData.getIndexedMap()==null){ //for the moment ignore if indexed (we may need to recode)
ImageCommands.applyDecodeArray(imageData.getObjectData(), imageData.getDepth(), decodeArray,decodeColorData.getID());
}
//apply any transfer function directly to data (does not work on DCT data)
final Object[] TRvalues=gs.getTR();
if(TRvalues!=null){ //array of values
ImageCommands.applyTR(imageData, TRvalues, currentPdfFile);
}
//switch to 8 bit and reduce bw image size by averaging
if(sampling>1 && !imageData.wasDCT()){
//choose whether we cache raw data so we can redecode images at different resolutions in Viewer
if(cacheLargeImages && decodeColorData.getIndexedMap()==null){
decodeColorData.dataToRGBByteArray(imageData.getObjectData(), imageData.getWidth(), imageData.getHeight());
if(SwingDisplay.testSampling){
System.out.println("cached image full size= "+imageData.getWidth()+", "+imageData.getHeight()+" Bits="+imageData.getDepth()+
" "+decodeColorData+" count="+imageData.getCompCount()+" bytes="+imageData.getObjectData().length);
}
objectStoreStreamRef.saveRawImageData(parserOptions.getPageNumber() + String.valueOf(imageCount),imageData.getObjectData(),
imageData.getWidth(),imageData.getHeight(),imageData.getDepth(), imageData.getpX(), imageData.getpY(),
maskCol,ColorSpaces.DeviceRGB);
}
decodeColorData = DownSampler.downSampleImage(decodeColorData, imageData, maskCol, sampling);
}
if (maskCol!=null) {
image = ImageDataToJavaImage.makeMaskImage(parserOptions, gs, current,imageData, decodeColorData, maskCol);
} else { //handle other types
LogWriter.writeLog( imageData.getWidth() + "W * " + imageData.getHeight() + "H BPC=" + imageData.getDepth() + ' ' + decodeColorData);
image =ImageDataToJavaImage.makeImage(decodeColorData,imageData);
}
if(image == null && !imageData.isRemoved()){
parserOptions.imagesProcessedFully=false;
}
if (maskCol!=null && gs.nonstrokeColorSpace.getColor().isTexture()) { //case 19095 vistair
float mm[][] = gs.CTM;
int w=imageData.getWidth();
int h=imageData.getHeight();
AffineTransform affine = new AffineTransform(mm[0][0], mm[0][1], mm[1][0], mm[1][1], mm[2][0], mm[2][1]);
BufferedImage temp = ((PatternColorSpace)gs.nonstrokeColorSpace).getRawImage(affine);
BufferedImage scrap = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
if(temp!=null){
TexturePaint tp = new TexturePaint(temp, new Rectangle(0,0,temp.getWidth(),temp.getHeight()));
Graphics2D g2 = scrap.createGraphics();
g2.setPaint(tp);
Rectangle rect = new Rectangle(0,0,w,h);
g2.fill(rect);
}
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (image.getRGB(x, y) == -16777216) { //255 0 0 0
int pRGB = scrap.getRGB(x, y);
image.setRGB(x, y, pRGB);
}
}
}
}
return image;
}
private int setSampling(final ImageData imageData, GenericColorSpace decodeColorData) {
//see what we could reduce to and still be big enough for page
int sampling=1;
int w=imageData.getWidth();
int h=imageData.getHeight();
int newW=w;
int newH=h;
int pX=imageData.getpX();
int pY=imageData.getpY();
//limit size (allow bigger grayscale
if(multiplyer<=1 && !parserOptions.isPrinting()){
int maxAllowed=1000;
if(decodeColorData.getID()==ColorSpaces.DeviceGray){
maxAllowed=4000;
}
if(pX>maxAllowed) {
pX = maxAllowed;
}
if(pY>maxAllowed) {
pY = maxAllowed;
}
}
final int smallestH=pY<<2; //double so comparison works
final int smallestW=pX<<2;
//cannot be smaller than page
while(newW>smallestW && newH>smallestH){
sampling <<= 1;
newW >>= 1;
newH >>= 1;
}
int scaleX=w/pX;
if(scaleX<1) {
scaleX = 1;
}
int scaleY=h/pY;
if(scaleY<1) {
scaleY = 1;
}
//choose smaller value so at least size of page
sampling=scaleX;
if(sampling>scaleY) {
sampling = scaleY;
}
imageData.setpX(pX);
imageData.setpY(pY);
return sampling;
}
private void setDownsampledImageSize(final ImageData imageData, final PdfObject XObject, final float multiplyer, final GenericColorSpace decodeColorData) {
int w=imageData.getWidth();
int h=imageData.getHeight();
if(parserOptions.isPrinting() && SamplingFactory.isPrintDownsampleEnabled && w<4000){
imageData.setpX(pageData.getCropBoxWidth(parserOptions.getPageNumber())*4);
imageData.setpY(pageData.getCropBoxHeight(parserOptions.getPageNumber())*4);
}else if(SamplingFactory.downsampleLevel== SamplingFactory.high || getSamplingOnly){// && w>500 && h>500){ // ignore small items
//ensure all positive for comparison
final float[][] CTM=new float[3][3];
for(int ii=0;ii<3;ii++){
for(int jj=0;jj<3;jj++){
if(gs.CTM[ii][jj]<0) {
CTM[ii][jj] = -gs.CTM[ii][jj];
} else {
CTM[ii][jj] = gs.CTM[ii][jj];
}
}
}
if(CTM[0][0]==0 || CTM[0][0]1){
imageData.setpX((int) (imageData.getpX()* multiplyer));
imageData.setpY((int) (imageData.getpX()* multiplyer));
}
//avoid for scanned text
if(imageData.getDepth()==1 && !hasMask &&
decodeColorData.getID()== ColorSpaces.DeviceGray && imageData.getHeight()<300){
imageData.setpX(0);
imageData.setpY(0);
}
}
public void setRes(final PdfObjectCache cache) {
this.cache=cache;
}
public int processImage(final String s, final int dataPointer, final PdfObject xObject)throws Exception {
return 0;
}
public int processImage(final int dataPointer, final int startInlineStream, final byte[] stream, final int tokenNumber)throws Exception {
return 0;
}
}