Esempio n. 1
0
  public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {

    BufferedImage dst = null;
    try {
      // Calculate and return a Rectangle that identifies the region of
      // the
      // source image that should be read:
      //
      // 1. If param is null, the upper-left corner of the region is (0,
      // 0),
      // and the width and height are specified by the width and height
      // arguments. In other words, the entire image is read.
      //
      // 2. If param is not null
      //
      // 2.1 If param.getSourceRegion() returns a non-null Rectangle, the
      // region is calculated as the intersection of param's Rectangle
      // and the earlier (0, 0, width, height Rectangle).
      //
      // 2.2 param.getSubsamplingXOffset() is added to the region's x
      // coordinate and subtracted from its width.
      //
      // 2.3 param.getSubsamplingYOffset() is added to the region's y
      // coordinate and subtracted from its height.

      int width = getWidth(imageIndex);
      int height = getHeight(imageIndex);

      Rectangle sourceRegion = getSourceRegion(param, width, height);

      // Source subsampling is used to return a scaled-down source image.
      // Default 1 values for X and Y subsampling indicate that a
      // non-scaled
      // source image will be returned.

      int sourceXSubsampling = 1;
      int sourceYSubsampling = 1;

      // The destination offset determines the starting location in the
      // destination where decoded pixels are placed. Default (0, 0)
      // values indicate the upper-left corner.

      Point destinationOffset = new Point(0, 0);

      // If param is not null, override the source subsampling, and
      // destination offset defaults.

      if (param != null) {
        sourceXSubsampling = param.getSourceXSubsampling();
        sourceYSubsampling = param.getSourceYSubsampling();
        destinationOffset = param.getDestinationOffset();
      }

      // Obtain a BufferedImage into which decoded pixels will be placed.
      // This destination will be returned to the application.
      //
      // 1. If param is not null
      //
      // 1.1 If param.getDestination() returns a BufferedImage
      //
      // 1.1.1 Return this BufferedImage
      //
      // Else
      //
      // 1.1.2 Invoke param.getDestinationType ().
      //
      // 1.1.3 If the returned ImageTypeSpecifier equals
      // getImageTypes (0) (see below), return its BufferedImage.
      //
      // 2. If param is null or a BufferedImage has not been obtained
      //
      // 2.1 Return getImageTypes (0)'s BufferedImage.

      dst = getDestination(param, getImageTypes(0), width, height);

      // Create a WritableRaster for the destination.

      WritableRaster wrDst = dst.getRaster();

      JBIG2Bitmap bitmap =
          decoder
              .getPageAsJBIG2Bitmap(imageIndex)
              .getSlice(sourceRegion.x, sourceRegion.y, sourceRegion.width, sourceRegion.height);

      BufferedImage image = bitmap.getBufferedImage();

      int newWidth = (int) (image.getWidth() * (1 / (double) sourceXSubsampling));
      int newHeight = (int) (image.getHeight() * (1 / (double) sourceYSubsampling));

      BufferedImage scaledImage = scaleImage(image.getRaster(), newWidth, newHeight, 1, 1);

      Raster raster = null;

      if (scaledImage != null) {
        raster = scaledImage.getRaster();
      } else raster = image.getRaster();

      wrDst.setRect(destinationOffset.x, destinationOffset.y, raster);

    } catch (RuntimeException e) {
      e.printStackTrace();
    }

    return dst;
  }
  public void readSegment() throws IOException, JBIG2Exception {

    if (JBIG2StreamDecoder.debug) System.out.println("==== Reading Immediate Generic Region ====");

    super.readSegment();

    /** read text region Segment flags */
    readGenericRegionFlags();

    boolean useMMR = genericRegionFlags.getFlagValue(GenericRegionFlags.MMR) != 0;
    int template = genericRegionFlags.getFlagValue(GenericRegionFlags.GB_TEMPLATE);

    short[] genericBAdaptiveTemplateX = new short[4];
    short[] genericBAdaptiveTemplateY = new short[4];

    if (!useMMR) {
      if (template == 0) {
        genericBAdaptiveTemplateX[0] = readATValue();
        genericBAdaptiveTemplateY[0] = readATValue();
        genericBAdaptiveTemplateX[1] = readATValue();
        genericBAdaptiveTemplateY[1] = readATValue();
        genericBAdaptiveTemplateX[2] = readATValue();
        genericBAdaptiveTemplateY[2] = readATValue();
        genericBAdaptiveTemplateX[3] = readATValue();
        genericBAdaptiveTemplateY[3] = readATValue();
      } else {
        genericBAdaptiveTemplateX[0] = readATValue();
        genericBAdaptiveTemplateY[0] = readATValue();
      }

      arithmeticDecoder.resetGenericStats(template, null);
      arithmeticDecoder.start();
    }

    boolean typicalPredictionGenericDecodingOn =
        genericRegionFlags.getFlagValue(GenericRegionFlags.TPGDON) != 0;
    int length = segmentHeader.getSegmentDataLength();

    if (length == -1) {
      /**
       * length of data is unknown, so it needs to be determined through examination of the data.
       * See 7.2.7 - Segment data length of the JBIG2 specification.
       */
      unknownLength = true;

      short match1;
      short match2;

      if (useMMR) {
        // look for 0x00 0x00 (0, 0)

        match1 = 0;
        match2 = 0;
      } else {
        // look for 0xFF 0xAC (255, 172)

        match1 = 255;
        match2 = 172;
      }

      int bytesRead = 0;
      while (true) {
        short bite1 = decoder.readByte();
        bytesRead++;

        if (bite1 == match1) {
          short bite2 = decoder.readByte();
          bytesRead++;

          if (bite2 == match2) {
            length = bytesRead - 2;
            break;
          }
        }
      }

      decoder.movePointer(-bytesRead);
    }

    JBIG2Bitmap bitmap =
        new JBIG2Bitmap(
            regionBitmapWidth, regionBitmapHeight, arithmeticDecoder, huffmanDecoder, mmrDecoder);
    bitmap.clear(0);
    bitmap.readBitmap(
        useMMR,
        template,
        typicalPredictionGenericDecodingOn,
        false,
        null,
        genericBAdaptiveTemplateX,
        genericBAdaptiveTemplateY,
        useMMR ? 0 : length - 18);

    if (inlineImage) {
      PageInformationSegment pageSegment =
          decoder.findPageSegement(segmentHeader.getPageAssociation());
      JBIG2Bitmap pageBitmap = pageSegment.getPageBitmap();

      int extCombOp = regionFlags.getFlagValue(RegionFlags.EXTERNAL_COMBINATION_OPERATOR);

      if (pageSegment.getPageBitmapHeight() == -1
          && regionBitmapYLocation + regionBitmapHeight > pageBitmap.getHeight()) {
        pageBitmap.expand(
            regionBitmapYLocation + regionBitmapHeight,
            pageSegment
                .getPageInformationFlags()
                .getFlagValue(PageInformationFlags.DEFAULT_PIXEL_VALUE));
      }

      pageBitmap.combine(bitmap, regionBitmapXLocation, regionBitmapYLocation, extCombOp);
    } else {
      bitmap.setBitmapNumber(getSegmentHeader().getSegmentNumber());
      decoder.appendBitmap(bitmap);
    }

    if (unknownLength) {
      decoder.movePointer(4);
    }
  }