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); } }