Example #1
0
  public ColorMapping(PdfObjectReader currentPdfFile, PdfObject functionObj) {

    // needed for this class
    functionType = functionObj.getInt(PdfDictionary.FunctionType);

    /** setup the translation function */
    function = FunctionFactory.getFunction(functionObj, currentPdfFile);
  }
  public void checkParentForResources(final PdfObject pdfObject) {

    /** if no resource, check parent for one (in theory should recurse up whole tree) */
    if (pdfObject.getDictionary(PdfDictionary.Resources) == null) {

      final String parent = pdfObject.getStringKey(PdfDictionary.Parent);

      if (parent != null) {
        final PdfObject parentObj = new PageObject(parent);
        readObject(parentObj);

        final PdfObject resObj = parentObj.getDictionary(PdfDictionary.Resources);

        if (resObj != null) {
          pdfObject.setDictionary(PdfDictionary.Resources, resObj);
        }
      }
    }
  }
Example #3
0
  public CCITT(PdfObject decodeParms, int width, int height) {

    super(decodeParms);

    this.width = width;
    this.height = height;

    // check JAI loaded on first call
    JAIHelper.confirmJAIOnClasspath();

    // get EncodedByteAligned
    if (decodeParms != null)
      EncodedByteAligned = decodeParms.getBoolean(PdfDictionary.EncodedByteAlign);
  }
  public static int setNameTreeValue(
      final PdfObject pdfObject,
      int i,
      final byte[] raw,
      final int length,
      final boolean ignoreRecursion,
      final int PDFkeyInt,
      final PdfFileReader objectReader) {

    boolean isRef = false;

    // move to start
    while (raw[i] != '[') { // can be number as well

      if (raw[i] == '(') { // allow for W (7)
        isRef = false;
        break;
      }

      // allow for number as in refer 9 0 R
      if (raw[i] >= '0' && raw[i] <= '9') {
        isRef = true;
        break;
      }

      i++;
    }

    // allow for direct or indirect
    byte[] data = raw;

    int start = i, j = i;

    int count = 0;

    // read ref data and slot in
    if (isRef) {
      // number
      final int[] values = StreamReaderUtils.readRefFromStream(raw, i);

      i = values[2];
      final int generation = values[1];
      final int number = values[0];

      if (raw[i] != 82) // we are expecting R to end ref
      {
        throw new RuntimeException(
            "3. Unexpected value in file "
                + raw[i]
                + " - please send to IDRsolutions for analysis");
      }

      if (!ignoreRecursion) {

        // read the Dictionary data
        data =
            objectReader.readObjectAsByteArray(
                pdfObject, objectReader.isCompressed(number, generation), number, generation);

        // allow for data in Linear object not yet loaded
        if (data == null) {
          pdfObject.setFullyResolved(false);

          if (debugFastCode) {
            System.out.println(padding + "Data not yet loaded");
          }

          i = length;
          return i;
        }

        // lose obj at start
        j = 3;
        while (data[j - 1] != 106
            && data[j - 2] != 98
            && data[j - 3] != 111
            && data[j - 3] != '<') {
          j++;
        }

        j = StreamReaderUtils.skipSpaces(data, j);

        // reset pointer
        start = j;
      }
    }

    // move to end
    while (j < data.length) {

      if (data[j] == '[' || data[j] == '(') {
        count++;
      } else if (data[j] == ']' || data[j] == ')') {
        count--;
      }

      if (count == 0) {
        break;
      }

      j++;
    }

    if (!ignoreRecursion) {
      final int stringLength = j - start + 1;
      byte[] newString = new byte[stringLength];

      System.arraycopy(data, start, newString, 0, stringLength);
      if (pdfObject.getObjectType() != PdfDictionary.Encrypt) {
        final DecryptionFactory decryption = objectReader.getDecryptionObject();
        if (decryption != null) {
          try {
            newString =
                decryption.decrypt(
                    newString, pdfObject.getObjectRefAsString(), false, null, false, false);
          } catch (final PdfSecurityException e) {
            LogWriter.writeLog("Exception: " + e.getMessage());
          }
        }
      }

      pdfObject.setTextStreamValue(PDFkeyInt, newString);

      if (debugFastCode) {
        System.out.println(padding + "name=" + new String(newString) + " set in " + pdfObject);
      }
    }

    // roll on
    if (!isRef) {
      i = j;
    }
    return i;
  }
  public static int setNameStringValue(
      final PdfObject pdfObject,
      int i,
      final byte[] raw,
      final boolean isMap,
      final Object PDFkey,
      final int PDFkeyInt,
      final PdfFileReader objectReader) {

    byte[] stringBytes;

    // move cursor to end of last command if needed
    while (raw[i] != 10
        && raw[i] != 13
        && raw[i] != 32
        && raw[i] != 47
        && raw[i] != '('
        && raw[i] != '<') {
      i++;
    }

    i = StreamReaderUtils.skipSpaces(raw, i);

    // work out if direct (ie /String or read ref 27 0 R
    int j2 = i;
    byte[] arrayData = raw;

    boolean isIndirect = raw[i] != 47 && raw[i] != 40 && raw[i] != 60; // Some /NAME values start (

    final boolean startsWithBrace = raw[i] == 40;

    // delete
    // @speed - lose this code once Filters done properly
    /*
     * just check its not /Filter [/FlateDecode ] or [] or [ /ASCII85Decode /FlateDecode ]
     * by checking next valid char not /
     */
    boolean isInsideArray = false;
    if (isIndirect) {
      int aa = i + 1;
      aa = StreamReaderUtils.skipSpaces(raw, aa);

      if (raw[aa] == 47 || raw[aa] == ']') {
        isIndirect = false;
        i = aa + 1;
        isInsideArray = true;
      }
    }

    if (isIndirect) { // its in another object so we need to fetch

      final int[] values = StreamReaderUtils.readRefFromStream(raw, i);
      final int ref = values[0];
      final int generation = values[1];
      i = values[2];

      if (raw[i] != 82) { // we are expecting R to end ref
        throw new RuntimeException(
            padding + "2. Unexpected value in file - please send to IDRsolutions for analysis");
      }

      // read the Dictionary data
      arrayData =
          objectReader.readObjectAsByteArray(
              pdfObject, objectReader.isCompressed(ref, generation), ref, generation);

      // allow for data in Linear object not yet loaded
      if (arrayData == null) {
        pdfObject.setFullyResolved(false);

        if (debugFastCode) {
          System.out.println(padding + "Data not yet loaded");
        }

        return raw.length;
      }

      // lose obj at start and roll onto /
      if (arrayData[0] == 47) {
        j2 = 0;
      } else {
        j2 = 3;

        while (arrayData[j2] != 47) {
          j2++;
        }
      }
    }

    // lose /
    j2++;

    // allow for no value with /Intent//Filter
    if (arrayData[j2] == 47) {
      return j2 - 1;
    }

    int end = j2 + 1;

    if (isInsideArray) { // values inside []

      // move cursor to start of text
      j2 = StreamReaderUtils.skipSpacesOrOtherCharacter(arrayData, j2, 47);

      int slashes = 0;

      // count chars
      byte lastChar = 0;
      while (true) {

        if (arrayData[end] == ']') {
          break;
        }

        if (arrayData[end] == 47
            && (lastChar == 32 || lastChar == 10 || lastChar == 13)) // count the / if gap before
        {
          slashes++;
        }

        lastChar = arrayData[end];
        end++;

        if (end == arrayData.length) {
          break;
        }
      }

      // set value and ensure space gap
      final int charCount = end - slashes;
      int ptr = 0;
      stringBytes = new byte[charCount - j2];

      byte nextChar, previous = 0;
      for (int ii = j2; ii < charCount; ii++) {
        nextChar = arrayData[ii];
        if (nextChar == 47) {
          if (previous != 32 && previous != 10 && previous != 13) {
            stringBytes[ptr] = 32;
            ptr++;
          }
        } else {
          stringBytes[ptr] = nextChar;
          ptr++;
        }

        previous = nextChar;
      }
    } else { // its in data stream directly or (string)

      // count chars
      while (true) {

        if (startsWithBrace) {
          if (arrayData[end] == ')' && !ObjectUtils.isEscaped(arrayData, end)) {
            break;
          }
        } else if (arrayData[end] == 32
            || arrayData[end] == 10
            || arrayData[end] == 13
            || arrayData[end] == 47
            || arrayData[end] == 62) {
          break;
        }

        end++;

        if (end == arrayData.length) {
          break;
        }
      }

      // set value
      final int charCount = end - j2;
      stringBytes = new byte[charCount];
      System.arraycopy(arrayData, j2, stringBytes, 0, charCount);
    }

    if (isMap) {
      pdfObject.setName(PDFkey, StringUtils.getTextString(stringBytes, false));
    } else {
      pdfObject.setName(PDFkeyInt, stringBytes);
    }

    if (debugFastCode) {
      System.out.println(
          padding + "String set as =" + new String(stringBytes) + "< written to " + pdfObject);
    }

    // put cursor in correct place (already there if ref)
    if (!isIndirect) {
      i = end - 1;
    }

    return i;
  }
  /**
   * read 1.5 compression stream ref table
   *
   * @throws PdfException
   */
  private PdfObject readCompressedStream(
      PdfObject rootObj,
      int pointer,
      final PdfFileReader currentPdfFile,
      final ObjectReader objectReader,
      final PdfObject linearObj)
      throws PdfException {

    while (pointer != -1) {

      /** get values to read stream ref */
      movePointer(pointer);

      final byte[] raw = objectReader.readObjectData(-1, null);

      /** read the object name from the start */
      final StringBuilder objectName = new StringBuilder();
      char current1, last = ' ';
      int matched = 0, i1 = 0;
      while (i1 < raw.length) {
        current1 = (char) raw[i1];

        // treat returns same as spaces
        if (current1 == 10 || current1 == 13) {
          current1 = ' ';
        }

        if (current1 == ' ' && last == ' ') { // lose duplicate or spaces
          matched = 0;
        } else if (current1 == pattern.charAt(matched)) { // looking for obj at end
          matched++;
        } else {
          matched = 0;
          objectName.append(current1);
        }
        if (matched == 3) {
          break;
        }
        last = current1;
        i1++;
      }

      // add end and put into Map
      objectName.append('R');

      final PdfObject pdfObject = new CompressedObject(objectName.toString());
      pdfObject.setCompressedStream(true);
      final ObjectDecoder objectDecoder = new ObjectDecoder(currentPdfFile);
      objectDecoder.readDictionaryAsObject(pdfObject, 0, raw);

      // read the field sizes
      final int[] fieldSizes = pdfObject.getIntArray(PdfDictionary.W);

      // read the xrefs stream
      byte[] xrefs = pdfObject.getDecodedStream();

      // if encr
      if (xrefs == null) {
        xrefs = currentPdfFile.readStream(pdfObject, true, true, false, false, true, null);
      }

      final int[] Index = pdfObject.getIntArray(PdfDictionary.Index);
      if (Index == null) { // single set of values

        // System.out.println("-------------1.Offsets-------------"+current+" "+numbEntries);
        CompressedObjects.readCompressedOffsets(
            0, 0, pdfObject.getInt(PdfDictionary.Size), fieldSizes, xrefs, offset, pdf_datafile);

      } else { // pairs of values in Index[] array
        final int count = Index.length;
        int pntr = 0;

        for (int aa = 0; aa < count; aa += 2) {

          // System.out.println("-------------2.Offsets-------------"+Index[aa]+" "+Index[aa+1]);

          pntr =
              CompressedObjects.readCompressedOffsets(
                  pntr, Index[aa], Index[aa + 1], fieldSizes, xrefs, offset, pdf_datafile);
        }
      }

      /**
       * now process trailer values - only first set of table values for root, encryption and info
       */
      if (rootObj == null) {

        rootObj = pdfObject.getDictionary(PdfDictionary.Root);

        /** handle encryption */
        encryptObj = pdfObject.getDictionary(PdfDictionary.Encrypt);

        if (encryptObj != null) {

          final byte[][] IDs = pdfObject.getStringArray(PdfDictionary.ID);
          if (IDs != null && this.ID == null) {
            // only the first encountered ID should be used as a fileID for decryption
            this.ID = IDs[0];
          }
        }

        infoObject = pdfObject.getDictionary(PdfDictionary.Info);
      }

      // make sure first values used if several tables and code for prev so long as not linearized
      // may need adjusting as more examples turn up
      if (linearObj != null) {
        pointer = -1;
      } else {
        pointer = pdfObject.getInt(PdfDictionary.Prev);

        // a non-compressed object table can follow a compressed one so we need to allow for this
        if (!isCompressedStream(pointer, (int) eof)) {
          return readLegacyReferenceTable(rootObj, pointer, (int) eof, currentPdfFile);
        }
      }
    }

    return rootObj;
  }
  /** read reference table from file so we can locate objects in pdf file and read the trailers */
  private PdfObject readLegacyReferenceTable(
      PdfObject rootObj, int pointer, final int eof, final PdfFileReader currentPdfFile)
      throws PdfException {

    int endTable, current = 0; // current object number
    byte[] Bytes;
    int bufSize = 1024;

    /** read and decode 1 or more trailers */
    while (true) {

      try {

        // allow for pointer outside file
        Bytes = Trailer.readTrailer(bufSize, pointer, eof, pdf_datafile);

      } catch (final Exception e) {

        try {
          closeFile();
        } catch (final IOException e1) {
          if (LogWriter.isOutput()) {
            LogWriter.writeLog("Exception " + e + " closing file " + e1);
          }
        }
        throw new PdfException("Exception " + e + " reading trailer");
      }

      if (Bytes == null) // safety catch
      {
        break;
      }

      /** get trailer */
      int i = 0;

      final int maxLen = Bytes.length;

      // for(int a=0;a<100;a++)
      //	System.out.println((char)Bytes[i+a]);
      while (i < maxLen) { // look for trailer keyword
        if (Bytes[i] == 116
            && Bytes[i + 1] == 114
            && Bytes[i + 2] == 97
            && Bytes[i + 3] == 105
            && Bytes[i + 4] == 108
            && Bytes[i + 5] == 101
            && Bytes[i + 6] == 114) {
          break;
        }

        i++;
      }

      // save endtable position for later
      endTable = i;

      if (i == Bytes.length) {
        break;
      }

      // move to beyond <<
      while (Bytes[i] != 60 && Bytes[i - 1] != 60) {
        i++;
      }

      i++;
      final PdfObject pdfObject = new CompressedObject("1 0 R");
      Dictionary.readDictionary(pdfObject, i, Bytes, -1, true, currentPdfFile, false);

      // move to beyond >>
      int level = 0;
      while (true) {

        if (Bytes[i] == 60 && Bytes[i - 1] == 60) {
          level++;
          i++;
        } else if (Bytes[i] == '[') {
          i++;
          while (Bytes[i] != ']') {
            i++;
            if (i == Bytes.length) {
              break;
            }
          }
        } else if (Bytes[i] == 62 && Bytes[i - 1] == 62) {
          level--;
          i++;
        }

        if (level == 0) {
          break;
        }

        i++;
      }

      // handle optional XRefStm
      final int XRefStm = pdfObject.getInt(PdfDictionary.XRefStm);

      if (XRefStm != -1) {
        pointer = XRefStm;
      } else { // usual way

        boolean hasRef = true;

        /** handle spaces and comments */
        while (Bytes[i] == 10 || Bytes[i] == 13) {
          i++;
        }

        while (Bytes[i] == '%') {
          while (Bytes[i] != 10) {

            i++;
          }
          i++;
        }
        /* fix for /Users/markee/Downloads/oneiderapartnerbrochure_web_1371798737.pdf
        /**/

        // look for xref as end of startref
        while (Bytes[i] != 116
            && Bytes[i + 1] != 120
            && Bytes[i + 2] != 114
            && Bytes[i + 3] != 101
            && Bytes[i + 4] != 102) {

          if (Bytes[i] == 'o' && Bytes[i + 1] == 'b' && Bytes[i + 2] == 'j') {
            hasRef = false;
            break;
          }
          i++;
        }

        if (hasRef) {

          i += 8;
          // move to start of value ignoring spaces or returns
          while ((i < maxLen) && (Bytes[i] == 10 || Bytes[i] == 32 || Bytes[i] == 13)) {
            i++;
          }

          final int s = i;

          // allow for characters between xref and startref
          while (i < maxLen && Bytes[i] != 10 && Bytes[i] != 32 && Bytes[i] != 13) {
            i++;
          }

          /** convert xref to string to get pointer */
          if (s != i) {
            pointer = NumberUtils.parseInt(s, i, Bytes);
          }
        }
      }

      i = 0;

      // allow for bum data at start
      while (Bytes[i] == 13 || Bytes[i] == 10 || Bytes[i] == 9) {
        i++;
      }

      if (pointer == -1) {
        if (LogWriter.isOutput()) {
          LogWriter.writeLog("No startRef");
        }

        /** now read the objects for the trailers */
      } else if (Bytes[i] == 120
          && Bytes[i + 1] == 114
          && Bytes[i + 2] == 101
          && Bytes[i + 3] == 102) { // make sure starts xref

        i = 5;

        // move to start of value ignoring spaces or returns
        while (Bytes[i] == 10 || Bytes[i] == 32 || Bytes[i] == 13) {
          i++;
        }

        current = offset.readXRefs(current, Bytes, endTable, i, eof, pdf_datafile);

        /**
         * now process trailer values - only first set of table values for root, encryption and info
         */
        if (rootObj == null) {

          rootObj = pdfObject.getDictionary(PdfDictionary.Root);

          encryptObj = pdfObject.getDictionary(PdfDictionary.Encrypt);
          if (encryptObj != null) {

            final byte[][] IDs = pdfObject.getStringArray(PdfDictionary.ID);
            if (IDs != null && this.ID == null) {
              // only the first encountered ID should be used as a fileID for decryption
              this.ID = IDs[0];
            }
          }

          infoObject = pdfObject.getDictionary(PdfDictionary.Info);
        }

        // make sure first values used if several tables and code for prev
        pointer = pdfObject.getInt(PdfDictionary.Prev);

        // see if other trailers
        if (pointer != -1 && pointer < this.eof) {
          // reset values for loop
          bufSize = 1024;

          // track ref table so we can work out object length
          offset.addXref(pointer);

        } else // reset if fails second test above
        {
          pointer = -1;
        }

      } else {
        pointer = -1;

        // needs to be read to pick up potential /Pages value
        //noinspection ObjectAllocationInLoop
        rootObj = new PageObject(BrokenRefTable.findOffsets(pdf_datafile, offset));
        currentPdfFile.readObject(rootObj);

        offset.setRefTableInvalid(true);
      }
      if (pointer == -1) {
        break;
      }
    }

    if (encryptObj == null
        && rootObj != null) { // manual check for broken file (ignore if Encrypted)

      int type = -1;

      int status = rootObj.getStatus();
      byte[] data = rootObj.getUnresolvedData();

      try {

        final ObjectDecoder objectDecoder = new ObjectDecoder(currentPdfFile);
        objectDecoder.checkResolved(rootObj);

        type = rootObj.getParameterConstant(PdfDictionary.Type);

      } catch (Exception e) { // we need to ignore so just catch, put back as was and log

        rootObj.setStatus(status);
        rootObj.setUnresolvedData(data, status);
        if (LogWriter.isOutput()) {
          LogWriter.writeLog("[PDF] Exception reading type on root object " + e);
        }
      }

      // something gone wrong so manually index
      if (type == PdfDictionary.Font) { // see 21153 - ref table in wrong order
        rootObj = null; // /will reset in code at end
      }
    }

    // something gone wrong so manually index
    if (rootObj == null) { // see 21382

      offset.clear();
      offset.reuse();

      // needs to be read to pick up potential /Pages value
      //noinspection ObjectAllocationInLoop
      rootObj = new PageObject(BrokenRefTable.findOffsets(pdf_datafile, offset));
      currentPdfFile.readObject(rootObj);

      offset.setRefTableInvalid(true);
    }

    return rootObj;
  }
  public void setJavascriptForObject(
      final FormObject formObject, final int parentType, final int actionType) {
    final String JSscript;

    final PdfObject actionObj;
    final PdfObject JSobj;

    final PdfObject additionalObject = formObject.getDictionary(parentType);

    final ObjectDecoder objectDecoder = new ObjectDecoder(this.objectReader);
    objectDecoder.checkResolved(additionalObject);

    if (additionalObject == null) {
      return;
    }

    if (actionType == parentType) {
      actionObj = additionalObject;
    } else {
      if (actionType == PdfDictionary.C2) // special case
      {
        actionObj = additionalObject.getDictionary(PdfDictionary.C);
      } else {
        actionObj = additionalObject.getDictionary(actionType);
      }
    }

    if (actionObj == null) {
      //				throw new RuntimeException("Failed on actionType="+actionType+"
      // "+formObject.getPDFRef()+
      //						"\nformObject="+formObject+" parentObject="+additionalObject+
      //						"\nadditionalObject="+additionalObject.getTextStreamValue(PdfDictionary.T)
      //						+"\nadditionalObject="+formObject.getTextStreamValue(PdfDictionary.T));
    } else {

      objectDecoder.checkResolved(actionObj);

      JSobj = actionObj.getDictionary(PdfDictionary.JS);

      if (JSobj != null) {

        final byte[] data = JSobj.getDecodedStream();
        JSscript = StringUtils.getTextString(data, true);

      } else {
        JSscript = actionObj.getTextStreamValue(PdfDictionary.JS);
      }

      // store
      if (JSscript != null) {
        // use name to reference Js if name is null use ref. seems to be slower, but better on
        // abacus/L295KantoonVaadt.pdf
        String name = formObject.getTextStreamValue(PdfDictionary.T);
        if (name == null) {
          name = formObject.getObjectRefAsString();
        }
        javascript.storeJavascript(name, JSscript, actionType);

        // old version
        //
        // javascript.storeJavascript(formObject.getObjectRefAsString(),JSscript,actionType);
      }
    }
  }
  public BufferedImage convert(
      final DecoderResults resultsFromDecode,
      final int displayRotation,
      final PdfResources res,
      final ExternalHandlers externalHandlers,
      final int renderMode,
      final PdfPageData pageData,
      final AcroRenderer formRenderer,
      final float scaling,
      final PdfObjectReader currentPdfFile,
      final int pageIndex,
      final boolean imageIsTransparent,
      final String currentPageOffset)
      throws PdfException {

    final ObjectStore localStore = new ObjectStore();

    /** read page or next pages */
    final PdfObject pdfObject = new PageObject(currentPageOffset);
    currentPdfFile.readObject(pdfObject);

    currentPdfFile.checkParentForResources(pdfObject);

    // ensure set (needed for XFA)
    pdfObject.setPageNumber(pageIndex);

    final PdfObject Resources = pdfObject.getDictionary(PdfDictionary.Resources);

    imageDisplay = getDisplay(pageIndex, localStore, imageIsTransparent);

    if (!imageDisplay.isHTMLorSVG()) {

      if (options.getPageColor() != null) {
        imageDisplay.setValue(
            DynamicVectorRenderer.ALT_BACKGROUND_COLOR, options.getPageColor().getRGB());
      }

      if (options.getTextColor() != null) {
        imageDisplay.setValue(
            DynamicVectorRenderer.ALT_FOREGROUND_COLOR, options.getTextColor().getRGB());

        if (options.getChangeTextAndLine()) {
          imageDisplay.setValue(DynamicVectorRenderer.FOREGROUND_INCLUDE_LINEART, 1);
        } else {
          imageDisplay.setValue(DynamicVectorRenderer.FOREGROUND_INCLUDE_LINEART, 0);
        }

        imageDisplay.setValue(
            DynamicVectorRenderer.COLOR_REPLACEMENT_THRESHOLD,
            options.getReplacementColorThreshold());
      }
    }

    final PdfStreamDecoder currentImageDecoder =
        formRenderer.getStreamDecoder(currentPdfFile, true, null, true);

    currentImageDecoder.setParameters(
        true,
        true,
        renderMode,
        PdfDecoderInt.TEXT,
        false,
        externalHandlers.getMode().equals(GUIModes.JAVAFX));

    externalHandlers.addHandlers(currentImageDecoder);

    // currentImageDecoder.setObjectValue(ValueTypes.Name, filename);
    currentImageDecoder.setObjectValue(ValueTypes.ObjectStore, localStore);
    currentImageDecoder.setMultiplyer(multiplyer);
    currentImageDecoder.setObjectValue(ValueTypes.PDFPageData, pageData);
    currentImageDecoder.setIntValue(ValueTypes.PageNum, pageIndex);

    currentImageDecoder.setRenderer(imageDisplay);
    externalHandlers.addHandlers(currentImageDecoder);

    res.setupResources(currentImageDecoder, true, Resources, pageIndex, currentPdfFile);

    // can for max
    if (multiplyer == -2) {

      multiplyer = -1;
      currentImageDecoder.setMultiplyer(multiplyer);

      final PdfStreamDecoderForSampling currentImageDecoder2 =
          new PdfStreamDecoderForSampling(currentPdfFile);
      currentImageDecoder2.setParameters(
          true, true, renderMode, 0, false, externalHandlers.getMode().equals(GUIModes.JAVAFX));

      // currentImageDecoder2.setObjectValue(ValueTypes.Name, filename);
      currentImageDecoder2.setObjectValue(ValueTypes.ObjectStore, localStore);
      currentImageDecoder2.setMultiplyer(multiplyer);
      currentImageDecoder2.setObjectValue(ValueTypes.PDFPageData, pageData);
      currentImageDecoder2.setIntValue(ValueTypes.PageNum, pageIndex);
      currentImageDecoder2.setRenderer(imageDisplay);

      res.setupResources(currentImageDecoder2, true, Resources, pageIndex, currentPdfFile);

      externalHandlers.addHandlers(currentImageDecoder2);

      /** bare minimum to get value */
      multiplyer = currentImageDecoder2.decodePageContentForImageSampling(pdfObject);

      int bestQualityMaxScalingToUse = 0;
      if (instance_bestQualityMaxScaling != null) {
        bestQualityMaxScalingToUse = instance_bestQualityMaxScaling;
      } else if (bestQualityMaxScaling != null) {
        bestQualityMaxScalingToUse = bestQualityMaxScaling;
      }

      if (bestQualityMaxScalingToUse > 0 && multiplyer > bestQualityMaxScalingToUse) {
        multiplyer = bestQualityMaxScalingToUse;
      }

      currentImageDecoder2.setMultiplyer(multiplyer);
      currentImageDecoder.setMultiplyer(multiplyer);
    }

    if (!allowPagesSmallerThanPageSize
        && !instance_allowPagesSmallerThanPageSize
        && multiplyer < 1
        && multiplyer > 0) {
      multiplyer = 1;
    }

    // allow for value not set
    if (multiplyer == -1) {
      multiplyer = 1;
    }

    /** setup positions,transformations and image */
    imageScaling =
        PDFtoImageConvertorSwing.setPageParametersForImage(
            scaling * multiplyer, pageIndex, pageData);

    setParams(scaling, pageData, pageIndex);

    final BufferedImage image =
        pageToImage(imageIsTransparent, currentImageDecoder, scaling, pdfObject, formRenderer);

    resultsFromDecode.update(currentImageDecoder, false);

    /** draw acroform data onto Panel */
    if (formRenderer != null
        && formRenderer.hasFormsOnPage(pageIndex)
        && !formRenderer.ignoreForms()) {

      resultsFromDecode.resetColorSpaces();

      if (!formRenderer.getCompData().hasformsOnPageDecoded(pageIndex)) {
        formRenderer.createDisplayComponentsForPage(pageIndex, currentImageDecoder);
      }

      if (isFX) {
        // done in fx image code
      } else if (!formRenderer.getCompData().formsRasterizedForDisplay()) {

        if (!formRenderer.useXFA()) {

          java.util.List[] formsOrdered = formRenderer.getCompData().getFormList(true);

          // get unsorted components and iterate over forms
          for (Object nextVal : formsOrdered[pageIndex]) {

            if (nextVal != null) {
              formRenderer
                  .getFormFlattener()
                  .drawFlattenedForm(
                      currentImageDecoder,
                      (org.jpedal.objects.raw.FormObject) nextVal,
                      false,
                      (PdfObject) formRenderer.getFormResources()[0]);
            }
          }

        } else {
          formRenderer
              .getCompData()
              .renderFormsOntoG2(
                  image.getGraphics(),
                  pageIndex,
                  0,
                  displayRotation,
                  null,
                  null,
                  pageData.getMediaBoxHeight(pageIndex));
        }
      } else {

        final java.util.List[] formsOrdered = formRenderer.getCompData().getFormList(true);

        // get unsorted components and iterate over forms
        for (final Object nextVal : formsOrdered[pageIndex]) {

          if (nextVal != null) {

            formRenderer
                .getFormFlattener()
                .drawFlattenedForm(
                    currentImageDecoder,
                    (org.jpedal.objects.raw.FormObject) nextVal,
                    false,
                    (PdfObject) formRenderer.getFormResources()[0]);
          }
        }
      }
    }

    if (currentImageDecoder != null) {
      currentImageDecoder.dispose();
    }

    localStore.flush();
    return image;
  }
  public static boolean convert(
      byte[] objectData,
      ImageData imageData,
      GenericColorSpace decodeColorData,
      PdfObject newSMask,
      PdfObjectReader currentPdfFile)
      throws PdfException {

    newSMask.setFloatArray(PdfDictionary.Decode, new float[] {1, 0});

    final PdfArrayIterator Filters = newSMask.getMixedArray(PdfDictionary.Filter);

    boolean isMaskJPX = false;
    // check not handled elsewhere
    int firstValue;
    if (Filters != null && Filters.hasMoreTokens()) {
      while (Filters.hasMoreTokens()) {
        firstValue = Filters.getNextValueAsConstant(true);
        // isDCT=firstValue==PdfFilteredReader.DCTDecode;
        isMaskJPX = firstValue == PdfFilteredReader.JPXDecode;
      }
    }

    byte[] objData = currentPdfFile.readStream(newSMask, true, true, false, false, false, null);

    imageData.setObjectData(objData);
    imageData.setDepth(1);
    imageData.setWidth(newSMask.getInt(PdfDictionary.Width));
    imageData.setHeight(newSMask.getInt(PdfDictionary.Height));
    int newDepth = newSMask.getInt(PdfDictionary.BitsPerComponent);

    // JPEG2000 causes us special difficulties as we not actually decoding objectData because
    // it is JPEG2000 and we decode as part of image handling because Java does byte[] to image
    // directly
    //
    // This code fixes specific example by getting the actual data and ignoring empty mask but will
    // probably need developing further if we find other examples
    if (isMaskJPX) { // see case 17665 for example
      BufferedImage img =
          decodeColorData.JPEG2000ToRGBImage(
              imageData.getObjectData(),
              imageData.getWidth(),
              imageData.getHeight(),
              null,
              -1,
              -1,
              8);
      img = ColorSpaceConvertor.convertColorspace(img, 10);

      objData = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
      imageData.setObjectData(objData);
      boolean isEmptyMask = true;
      for (final byte b : objectData) {
        if (b != 0) {
          isEmptyMask = false;
          break;
        }
      }
      if (isEmptyMask) {
        imageData.setObjectData(null);
      }

      // we need to unset this as e have handled the JPX filter
      newSMask.setMixedArray(PdfDictionary.Filter, null);
    }

    if (newDepth != PdfDictionary.Unknown) {
      imageData.setDepth(newDepth);
    }

    return objData == null;
  }