/** * Compute the source region and destination dimensions taking any parameter settings into * account. */ private static void computeRegions( Rectangle sourceBounds, Dimension destSize, ImageWriteParam p) { ImageWriteParam param; int periodX = 1; int periodY = 1; if (p != null) { int[] sourceBands = p.getSourceBands(); if (sourceBands != null && (sourceBands.length != 1 || sourceBands[0] != 0)) { throw new IllegalArgumentException("Cannot sub-band image!"); } // Get source region and subsampling factors Rectangle sourceRegion = p.getSourceRegion(); if (sourceRegion != null) { // Clip to actual image bounds sourceRegion = sourceRegion.intersection(sourceBounds); sourceBounds.setBounds(sourceRegion); } // Adjust for subsampling offsets int gridX = p.getSubsamplingXOffset(); int gridY = p.getSubsamplingYOffset(); sourceBounds.x += gridX; sourceBounds.y += gridY; sourceBounds.width -= gridX; sourceBounds.height -= gridY; // Get subsampling factors periodX = p.getSourceXSubsampling(); periodY = p.getSourceYSubsampling(); } // Compute output dimensions destSize.setSize( (sourceBounds.width + periodX - 1) / periodX, (sourceBounds.height + periodY - 1) / periodY); if (destSize.width <= 0 || destSize.height <= 0) { throw new IllegalArgumentException("Empty source region!"); } }
public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException { if (iis == null) { throw new IllegalStateException(I18N.getString("WBMPImageReader1")); } checkIndex(imageIndex); clearAbortRequest(); processImageStarted(imageIndex); if (param == null) param = getDefaultReadParam(); // read header readHeader(); Rectangle sourceRegion = new Rectangle(0, 0, 0, 0); Rectangle destinationRegion = new Rectangle(0, 0, 0, 0); computeRegions( param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); // If the destination is provided, then use it. Otherwise, create new one BufferedImage bi = param.getDestination(); if (bi == null) bi = new BufferedImage( destinationRegion.x + destinationRegion.width, destinationRegion.y + destinationRegion.height, BufferedImage.TYPE_BYTE_BINARY); boolean noTransform = destinationRegion.equals(new Rectangle(0, 0, width, height)) && destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight())); // Get the image data. WritableRaster tile = bi.getWritableTile(0, 0); // Get the SampleModel. MultiPixelPackedSampleModel sm = (MultiPixelPackedSampleModel) bi.getSampleModel(); if (noTransform) { if (abortRequested()) { processReadAborted(); return bi; } // If noTransform is necessary, read the data. iis.read( ((DataBufferByte) tile.getDataBuffer()).getData(), 0, height * sm.getScanlineStride()); processImageUpdate(bi, 0, 0, width, height, 1, 1, new int[] {0}); processImageProgress(100.0F); } else { int len = (this.width + 7) / 8; byte[] buf = new byte[len]; byte[] data = ((DataBufferByte) tile.getDataBuffer()).getData(); int lineStride = sm.getScanlineStride(); iis.skipBytes(len * sourceRegion.y); int skipLength = len * (scaleY - 1); // cache the values to avoid duplicated computation int[] srcOff = new int[destinationRegion.width]; int[] destOff = new int[destinationRegion.width]; int[] srcPos = new int[destinationRegion.width]; int[] destPos = new int[destinationRegion.width]; for (int i = destinationRegion.x, x = sourceRegion.x, j = 0; i < destinationRegion.x + destinationRegion.width; i++, j++, x += scaleX) { srcPos[j] = x >> 3; srcOff[j] = 7 - (x & 7); destPos[j] = i >> 3; destOff[j] = 7 - (i & 7); } for (int j = 0, y = sourceRegion.y, k = destinationRegion.y * lineStride; j < destinationRegion.height; j++, y += scaleY) { if (abortRequested()) break; iis.read(buf, 0, len); for (int i = 0; i < destinationRegion.width; i++) { // get the bit and assign to the data buffer of the raster int v = (buf[srcPos[i]] >> srcOff[i]) & 1; data[k + destPos[i]] |= v << destOff[i]; } k += lineStride; iis.skipBytes(skipLength); processImageUpdate(bi, 0, j, destinationRegion.width, 1, 1, 1, new int[] {0}); processImageProgress(100.0F * j / destinationRegion.height); } } if (abortRequested()) processReadAborted(); else processImageComplete(); return bi; }