Ejemplo n.º 1
0
  /**
   * Parse the image stream into a buffered image. Note that this is guaranteed to be called after
   * all the other setXXX methods have been called.
   *
   * <p>NOTE: the color convolving is extremely slow on large images. It would be good to see if it
   * could be moved out into the rendering phases, where we might be able to scale the image down
   * first.</p
   */
  protected BufferedImage parseData(byte[] data) {
    // create the data buffer
    DataBuffer db = new DataBufferByte(data, data.length);

    // pick a color model, based on the number of components and
    // bits per component
    ColorModel cm = getColorModel();

    // create a compatible raster
    SampleModel sm = cm.createCompatibleSampleModel(getWidth(), getHeight());
    WritableRaster raster;
    try {
      raster = Raster.createWritableRaster(sm, db, new Point(0, 0));
    } catch (RasterFormatException e) {
      int tempExpectedSize =
          getWidth()
              * getHeight()
              * getColorSpace().getNumComponents()
              * Math.max(8, getBitsPerComponent())
              / 8;

      if (tempExpectedSize < 3) {
        tempExpectedSize = 3;
      }
      if (tempExpectedSize > data.length) {
        byte[] tempLargerData = new byte[tempExpectedSize];
        System.arraycopy(data, 0, tempLargerData, 0, data.length);
        db = new DataBufferByte(tempLargerData, tempExpectedSize);
        raster = Raster.createWritableRaster(sm, db, new Point(0, 0));
      } else {
        throw e;
      }
    }

    /*
     * Workaround for a bug on the Mac -- a class cast exception in
     * drawImage() due to the wrong data buffer type (?)
     */
    BufferedImage bi = null;
    if (cm instanceof IndexColorModel) {
      IndexColorModel icm = (IndexColorModel) cm;

      // choose the image type based on the size
      int type = BufferedImage.TYPE_BYTE_BINARY;
      if (getBitsPerComponent() == 8) {
        type = BufferedImage.TYPE_BYTE_INDEXED;
      }

      // create the image with an explicit indexed color model.
      bi = new BufferedImage(getWidth(), getHeight(), type, icm);

      // set the data explicitly as well
      bi.setData(raster);
    } else {
      // Raster is already in a format which is supported by Java2D,
      // such as RGB or Gray.
      bi = new BufferedImage(cm, raster, true, null);
    }

    // hack to avoid *very* slow conversion
    ColorSpace cs = cm.getColorSpace();
    ColorSpace rgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    if (!isImageMask() && cs instanceof ICC_ColorSpace && !cs.equals(rgbCS)) {
      ColorConvertOp op = new ColorConvertOp(cs, rgbCS, null);

      BufferedImage converted =
          new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);

      bi = op.filter(bi, converted);
    }

    // add in the alpha data supplied by the SMask, if any
    PDFImage sMaskImage = getSMask();
    if (sMaskImage != null) {
      BufferedImage si = sMaskImage.getImage();
      BufferedImage outImage =
          new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);

      int[] srcArray = new int[this.width];
      int[] maskArray = new int[this.width];

      for (int i = 0; i < this.height; i++) {
        bi.getRGB(0, i, this.width, 1, srcArray, 0, this.width);
        si.getRGB(0, i, this.width, 1, maskArray, 0, this.width);

        for (int j = 0; j < this.width; j++) {
          int ac = 0xff000000;

          maskArray[j] = ((maskArray[j] & 0xff) << 24) | (srcArray[j] & ~ac);
        }

        outImage.setRGB(0, i, this.width, 1, maskArray, 0, this.width);
      }

      bi = outImage;
    }

    return (bi);
  }
Ejemplo n.º 2
0
  /**
   * Read a PDFImage from an image dictionary and stream
   *
   * @param obj the PDFObject containing the image's dictionary and stream
   * @param resources the current resources
   * @param useAsSMask - flag for switching colors in case image is used as sMask internally this is
   *     needed for handling transparency in smask images.
   */
  public static PDFImage createImage(PDFObject obj, Map resources, boolean useAsSMask)
      throws IOException {
    // create the image
    PDFImage image = new PDFImage(obj);

    // get the width (required)
    PDFObject widthObj = obj.getDictRef("Width");
    if (widthObj == null) {
      throw new PDFParseException("Unable to read image width: " + obj);
    }
    image.setWidth(widthObj.getIntValue());

    // get the height (required)
    PDFObject heightObj = obj.getDictRef("Height");
    if (heightObj == null) {
      throw new PDFParseException("Unable to get image height: " + obj);
    }
    image.setHeight(heightObj.getIntValue());

    // figure out if we are an image mask (optional)
    PDFObject imageMaskObj = obj.getDictRef("ImageMask");
    if (imageMaskObj != null) {
      image.setImageMask(imageMaskObj.getBooleanValue());
    }
    // read the bpc and colorspace (required except for masks)
    if (image.isImageMask()) {
      image.setBitsPerComponent(1);
      // create the indexed color space for the mask
      // [PATCHED by [email protected]] - default value od Decode according to PDF spec. is [0,
      // 1]
      // so the color arry should be:
      // [PATCHED by XOND] - switched colors in case the image is used as SMask for another image,
      // otherwise transparency isn't
      //					   handled correctly.
      Color[] colors =
          useAsSMask
              ? new Color[] {Color.WHITE, Color.BLACK}
              : new Color[] {Color.BLACK, Color.WHITE};
      PDFObject imageMaskDecode = obj.getDictRef("Decode");
      if (imageMaskDecode != null) {
        PDFObject[] decodeArray = imageMaskDecode.getArray();
        float decode0 = decodeArray[0].getFloatValue();
        if (decode0 == 1.0f) {
          colors =
              useAsSMask
                  ? new Color[] {Color.BLACK, Color.WHITE}
                  : new Color[] {Color.WHITE, Color.BLACK};
        }

        float[] decode = new float[decodeArray.length];
        for (int i = 0; i < decodeArray.length; i++) {
          decode[i] = decodeArray[i].getFloatValue();
        }
        image.setDecode(decode);
      }

      image.setColorSpace(new IndexedColor(colors));
    } else {
      // get the bits per component (required)
      PDFObject bpcObj = obj.getDictRef("BitsPerComponent");
      if (bpcObj == null) {
        throw new PDFParseException("Unable to get bits per component: " + obj);
      }
      image.setBitsPerComponent(bpcObj.getIntValue());

      // get the color space (required)
      PDFObject csObj = obj.getDictRef("ColorSpace");
      if (csObj == null) {
        throw new PDFParseException("No ColorSpace for image: " + obj);
      }

      PDFColorSpace cs = PDFColorSpace.getColorSpace(csObj, resources);
      image.setColorSpace(cs);

      // read the decode array
      PDFObject decodeObj = obj.getDictRef("Decode");
      if (decodeObj != null) {
        PDFObject[] decodeArray = decodeObj.getArray();

        float[] decode = new float[decodeArray.length];
        for (int i = 0; i < decodeArray.length; i++) {
          decode[i] = decodeArray[i].getFloatValue();
        }

        image.setDecode(decode);
      }

      // read the soft mask.
      // If ImageMask is true, this entry must not be present.
      // (See implementation note 52 in Appendix H.)
      PDFObject sMaskObj = obj.getDictRef("SMask");
      if (sMaskObj == null) {
        // try the explicit mask, if there is no SoftMask
        sMaskObj = obj.getDictRef("Mask");
      }

      if (sMaskObj != null) {
        if (sMaskObj.getType() == PDFObject.STREAM) {
          try {
            PDFImage sMaskImage = PDFImage.createImage(sMaskObj, resources, true);
            image.setSMask(sMaskImage);
          } catch (IOException ex) {
            p("ERROR: there was a problem parsing the mask for this object");
            dump(obj);
            ex.printStackTrace(System.out);
          }
        } else if (sMaskObj.getType() == PDFObject.ARRAY) {
          // retrieve the range of the ColorKeyMask
          // colors outside this range will not be painted.
          try {
            image.setColorKeyMask(sMaskObj);
          } catch (IOException ex) {
            p("ERROR: there was a problem parsing the color mask for this object");
            dump(obj);
            ex.printStackTrace(System.out);
          }
        }
      }
    }

    return image;
  }