// package accessible for SubsampleBinaryToGrayOpImage4x4, etc... static ImageLayout layoutHelper( RenderedImage source, float scaleX, float scaleY, ImageLayout il, Map config) { ImageLayout layout = (il == null) ? new ImageLayout() : (ImageLayout) il.clone(); // to compute dWidth and dHeight // fTol and dWi, dHi must be the same as in computeDestInfo(..) // due to static method, a few lines of coding are repeated int srcWidth = source.getWidth(); int srcHeight = source.getHeight(); float f_dw = scaleX * srcWidth; float f_dh = scaleY * srcHeight; float fTol = .1F * Math.min(scaleX / (f_dw + 1.0F), scaleY / (f_dh + 1.0F)); int dWi = (int) (f_dw); int dHi = (int) (f_dh); // let it be int in the almost int case // espacially in the true int case with float calculation errors if (Math.abs(Math.round(f_dw) - f_dw) < fTol) { dWi = Math.round(f_dw); } if (Math.abs(Math.round(f_dh) - f_dh) < fTol) { dHi = Math.round(f_dh); } // Set the top left coordinate of the destination layout.setMinX((int) (scaleX * source.getMinX())); layout.setMinY((int) (scaleY * source.getMinY())); layout.setWidth(dWi); layout.setHeight(dHi); // sample model SampleModel sm = layout.getSampleModel(null); if (sm == null || sm.getDataType() != DataBuffer.TYPE_BYTE || !(sm instanceof PixelInterleavedSampleModel || sm instanceof SinglePixelPackedSampleModel && sm.getNumBands() == 1)) { // Width and height will be corrected in OpImage.layoutHelper sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, 1, 1, 1, 1, new int[] {0}); } layout.setSampleModel(sm); ColorModel cm = layout.getColorModel(null); if (cm == null || !JDKWorkarounds.areCompatibleDataModels(sm, cm)) { layout.setColorModel(ImageUtil.getCompatibleColorModel(sm, config)); } return layout; }
/** * Fills in the portions of a given <code>Raster</code> that lie outside the bounds of a given * <code>PlanarImage</code> with suitably reflected copies of the entire image. * * <p>The portion of <code>raster</code> that lies within <code>im.getBounds()</code> is not * altered. * * @param raster The <code>WritableRaster</code> the border area of which is to be filled with * suitably reflected copies of portions of the specified image. * @param im The <code>PlanarImage</code> the data of which is to be reflected and used to fill * the <code>WritableRaster</code> border. * @throws <code>IllegalArgumentException</code> if either parameter is <code>null</code>. */ public final void extend(WritableRaster raster, PlanarImage im) { if (raster == null || im == null) { throw new IllegalArgumentException(JaiI18N.getString("Generic0")); } int width = raster.getWidth(); int height = raster.getHeight(); int minX = raster.getMinX(); int maxX = minX + width; int minY = raster.getMinY(); int maxY = minY + height; int imMinX = im.getMinX(); int imMinY = im.getMinY(); int imWidth = im.getWidth(); int imHeight = im.getHeight(); int validMinX = Math.max(imMinX, minX); int validMaxX = Math.min(imMinX + imWidth, maxX); int validMinY = Math.max(imMinY, minY); int validMaxY = Math.min(imMinY + imHeight, maxY); if (validMinX > validMaxX || validMinY > validMaxY) { // Raster does not intersect image. Determine the location // and size of the smallest rectangle containing the Raster // and which intersects the image. if (validMinX > validMaxX) { // no intersetion in X if (minX == validMinX) { minX = im.getMaxX() - 1; } else { maxX = im.getMinX(); } } if (validMinY > validMaxY) { // no intersetion in Y if (minY == validMinY) { minY = im.getMaxY() - 1; } else { maxY = im.getMinY(); } } // Create minimum Raster. WritableRaster wr = raster.createCompatibleWritableRaster(minX, minY, maxX - minX, maxY - minY); // Extend the data. extend(wr, im); // Create a child with same bounds as the target Raster. Raster child = wr.createChild( raster.getMinX(), raster.getMinY(), raster.getWidth(), raster.getHeight(), raster.getMinX(), raster.getMinY(), null); // Copy the data from the child. JDKWorkarounds.setRect(raster, child, 0, 0); return; } Rectangle rect = new Rectangle(); // Notionally extend the source image by treating it as a single // tile of an infinite tiled image. Adjacent tiles are reflections // of one another. // Compute the min and max X and Y tile indices of the area // intersected by the output raster. int minTileX = PlanarImage.XToTileX(minX, imMinX, imWidth); int maxTileX = PlanarImage.XToTileX(maxX - 1, imMinX, imWidth); int minTileY = PlanarImage.YToTileY(minY, imMinY, imHeight); int maxTileY = PlanarImage.YToTileY(maxY - 1, imMinY, imHeight); // Loop over the tiles for (int tileY = minTileY; tileY <= maxTileY; tileY++) { int ty = tileY * imHeight + imMinY; for (int tileX = minTileX; tileX <= maxTileX; tileX++) { int tx = tileX * imWidth + imMinX; // Don't touch the central "tile" (actual image) if (tileX == 0 && tileY == 0) { continue; } boolean flipX = (Math.abs(tileX) % 2) == 1; boolean flipY = (Math.abs(tileY) % 2) == 1; // Clip the tile bounds against the bounds of the Raster. // Keep track of the (x, y) offset of the start of the tile. rect.x = tx; rect.y = ty; rect.width = imWidth; rect.height = imHeight; int xOffset = 0; if (rect.x < minX) { xOffset = minX - rect.x; rect.x = minX; rect.width -= xOffset; } int yOffset = 0; if (rect.y < minY) { yOffset = minY - rect.y; rect.y = minY; rect.height -= yOffset; } if (rect.x + rect.width > maxX) { rect.width = maxX - rect.x; } if (rect.y + rect.height > maxY) { rect.height = maxY - rect.y; } int imX; if (flipX) { if (xOffset == 0) { imX = imMinX + imWidth - rect.width; } else { imX = imMinX; } } else { imX = imMinX + xOffset; } int imY; if (flipY) { if (yOffset == 0) { imY = imMinY + imHeight - rect.height; } else { imY = imMinY; } } else { imY = imMinY + yOffset; } // Create a child raster with coordinates within the // actual image. WritableRaster child = RasterFactory.createWritableChild( raster, rect.x, rect.y, rect.width, rect.height, imX, imY, null); // Copy the data into the Raster im.copyData(child); if (flipX) { flipX(child); } if (flipY) { flipY(child); } } } }