/* * Copyright (C) Jerry Huxtable 1998-2001. All rights reserved. */ package com.jhlabs.jai; import java.util.*; import java.awt.*; import java.awt.image.*; import java.awt.image.renderable.*; import javax.media.jai.*; /** * A JAI operation descriptor for the Mosaic operation. This operation produces * an image from a grid of tile sources, each tile being a separate JAI image. * All source images must be the same size and have the same tile size, sample * model and color model. The resulting image will have a tile size the same as * the sources. The parameters are the number of rows and columns in * the grid and a two dimensional array of the source tiles. * @author Jerry Huxtable */ public class MosaicDescriptor extends OperationDescriptorImpl implements RenderedImageFactory { private static final String[][] resources = { {"GlobalName", "Mosaic"}, {"LocalName", "Mosaic"}, {"Vendor", "com.jhlabs"}, {"Description", "An operation that tiles together images"}, {"DocURL", "http://www.jhlabs.com/MosaicDescriptor.html"}, {"Version", "1.0"}, {"arg0Desc", "rows"}, {"arg1Desc", "cols"}, }; private static final String[] paramNames = { "rows", "cols", }; /** * The class types for the parameters of the "Mosaic" operation. */ private static final Class[] paramClasses = { java.lang.Integer.class, java.lang.Integer.class, }; /** * The default parameter values for the "Mosaic" operation * when using a ParameterBlockJAI. */ private static final Object[] paramDefaults = { new Integer(0), new Integer(0), }; private static boolean registered = false; public static void register() { if (!registered) { OperationRegistry or = JAI.getDefaultInstance().getOperationRegistry(); MosaicDescriptor d = new MosaicDescriptor(); String operationName = "mosaic"; String productName = "com.jhlabs"; or.registerOperationDescriptor(d, operationName); or.registerRIF(operationName, productName, d); registered = true; } } /** * Construct a MosaicDescriptor. */ public MosaicDescriptor() { super(resources, 0, paramClasses, paramNames, paramDefaults); } /** * Creates a MosaicOpImage with the given ParameterBlock if the * MosaicOpImage can handle the particular ParameterBlock. */ public RenderedImage create(ParameterBlock paramBlock, RenderingHints renderHints) { if (!validateParameters(paramBlock)) return null; return new MosaicOpImage( ((Integer)paramBlock.getObjectParameter(0)).intValue(), ((Integer)paramBlock.getObjectParameter(1)).intValue(), paramBlock.getSources() ); } /** * Checks that all parameters in the ParameterBlock have the * correct type before constructing the MosaicOpImage */ public boolean validateParameters(ParameterBlock paramBlock) { for (int i = 0; i < this.getNumParameters(); i++) { Object arg = paramBlock.getObjectParameter(i); if (arg == null) { return false; } if ((i == 0 || i == 1) && !(arg instanceof Integer)) return false; } return true; } } /** * The MosaicOpImage class. * @see MosaicDescriptor */ class MosaicOpImage extends OpImage { /** * The number of rows in the mosaic. */ private int rows; /** * The number of columns in the mosaic. */ private int cols; /** * The image tile width. */ private int tileWidth; /** * The image tile height. */ private int tileHeight; /** * The image width. */ private int width; /** * The image height. */ private int height; /** * The number of tiles across the image. */ private int tilesX; /** * The number of tiles down the image. */ private int tilesY; /** * The width of the source tiles. */ private int majorTileWidth; /** * The height of the source tiles. */ private int majorTileHeight; public MosaicOpImage(int rows, int cols, Vector sources) { super((Vector)null, null, null, true); this.rows = rows; this.cols = cols; if (sources.size() < rows*cols) throw new IllegalArgumentException("Not enough sources supplied to MosaicOperator"); int count = sources.size(); for (int i = 0; i < count; i++) addSource((PlanarImage)sources.elementAt(i)); PlanarImage baseTile = (PlanarImage)sources.firstElement(); majorTileWidth = baseTile.getWidth(); majorTileHeight = baseTile.getHeight(); tileWidth = baseTile.getTileWidth(); tileHeight = baseTile.getTileHeight(); width = cols * majorTileWidth; height = rows * majorTileHeight; tilesX = (width + tileWidth - 1) / tileWidth; tilesY = (height + tileHeight - 1) / tileHeight; SampleModel sampleModel = baseTile.getSampleModel(); ColorModel colorModel = baseTile.getColorModel(); ImageLayout imageLayout = new ImageLayout(0, 0, width, height, 0, 0, tileWidth, tileHeight, sampleModel, colorModel); setImageLayout(imageLayout); } public Raster computeTile(int x, int y) { DataBuffer dataBuffer = sampleModel.createDataBuffer(); if (x < 0 || x >= tilesX || y < 0 || y >= tilesY) { System.out.println("Error: illegal tile requested from a MosaicOpImage."); Raster raster = Raster.createRaster(sampleModel, dataBuffer, new Point(x * tileWidth, y * tileHeight)); return raster; } try { int tx = x * tileWidth / majorTileWidth; int ty = y * tileHeight / majorTileHeight; Rectangle r = new Rectangle(tileWidth * (x % (majorTileWidth/tileWidth)), tileHeight * (y % (majorTileHeight/tileHeight)), tileWidth, tileHeight); PlanarImage op = getSourceImage(ty*cols+tx); Raster raster = null; synchronized(op) { raster = op.getData(r); raster = raster.createTranslatedChild(x * tileWidth, y * tileHeight); } return raster; } catch (Exception e) { e.printStackTrace(); } return Raster.createRaster(sampleModel, dataBuffer, new Point(x * tileWidth, y * tileHeight)); } public Rectangle mapDestRect(Rectangle rectangle, int i) { return rectangle; } public Rectangle mapSourceRect(Rectangle rectangle, int i) { return rectangle; } }