Source code: org/modama/jaiutil/operators/MosaicDescriptor.java
1 /*
2 * Copyright (C) Jerry Huxtable 1998-2001. All rights reserved.
3 */
4 package org.modama.jaiutil.operators;
5
6 import java.util.*;
7 import java.awt.*;
8 import java.awt.image.*;
9 import java.awt.image.renderable.*;
10 import javax.media.jai.*;
11
12
13 /**
14 * A JAI operation descriptor for the Mosaic operation. This operation produces
15 * an image from a grid of tile sources, each tile being a separate JAI image.
16 * All source images must be the same size and have the same tile size, sample
17 * model and color model. The resulting image will have a tile size the same as
18 * the sources. The parameters are the number of rows and columns in
19 * the grid and a two dimensional array of the source tiles.
20 * @author Jerry Huxtable
21 */
22 public class MosaicDescriptor extends OperationDescriptorImpl implements RenderedImageFactory {
23
24 private static final String[][] resources = {
25 {"GlobalName", "Mosaic2"},
26 {"LocalName", "Mosaic2"},
27 {"Vendor", "com.jhlabs"},
28 {"Description", "An operation that tiles together images"},
29 {"DocURL", "http://www.jhlabs.com/MosaicDescriptor.html"},
30 {"Version", "1.0"},
31 {"arg0Desc", "rows"},
32 {"arg1Desc", "cols"},
33 };
34
35 private static final String[] paramNames = {
36 "rows",
37 "cols",
38 };
39
40 /**
41 * The class types for the parameters of the "Mosaic" operation.
42 */
43 private static final Class[] paramClasses = {
44 java.lang.Integer.class,
45 java.lang.Integer.class,
46 };
47
48 /**
49 * The default parameter values for the "Mosaic" operation
50 * when using a ParameterBlockJAI.
51 */
52 private static final Object[] paramDefaults = {
53 new Integer(0),
54 new Integer(0),
55 };
56
57 private static boolean registered = false;
58
59 public static void register() {
60 if (!registered) {
61 OperationRegistry or = JAI.getDefaultInstance().getOperationRegistry();
62
63 MosaicDescriptor d = new MosaicDescriptor();
64 String operationName = "mosaic2";
65 String productName = "com.jhlabs";
66 or.registerOperationDescriptor(d, operationName);
67 or.registerRIF(operationName, productName, d);
68 registered = true;
69 }
70 }
71
72 /**
73 * Construct a MosaicDescriptor.
74 */
75 public MosaicDescriptor() {
76 super(resources, 0, paramClasses, paramNames, paramDefaults);
77 }
78
79 /**
80 * Creates a MosaicOpImage with the given ParameterBlock if the
81 * MosaicOpImage can handle the particular ParameterBlock.
82 */
83 public RenderedImage create(ParameterBlock paramBlock, RenderingHints renderHints) {
84 if (!validateParameters(paramBlock))
85 return null;
86
87 return new MosaicOpImage(
88 ((Integer)paramBlock.getObjectParameter(0)).intValue(),
89 ((Integer)paramBlock.getObjectParameter(1)).intValue(),
90 paramBlock.getSources()
91 );
92 }
93
94 /**
95 * Checks that all parameters in the ParameterBlock have the
96 * correct type before constructing the MosaicOpImage
97 */
98 public boolean validateParameters(ParameterBlock paramBlock) {
99 for (int i = 0; i < this.getNumParameters(); i++) {
100 Object arg = paramBlock.getObjectParameter(i);
101 if (arg == null) {
102 return false;
103 }
104 if ((i == 0 || i == 1) && !(arg instanceof Integer))
105 return false;
106 }
107 return true;
108 }
109 }
110
111 /**
112 * The MosaicOpImage class.
113 * @see org.modama.jaiutil.operators.MosaicDescriptor
114 */
115 class MosaicOpImage extends OpImage {
116
117 /**
118 * The number of rows in the mosaic.
119 */
120 private int rows;
121
122 /**
123 * The number of columns in the mosaic.
124 */
125 private int cols;
126
127 /**
128 * The image tile width.
129 */
130 private int tileWidth;
131
132 /**
133 * The image tile height.
134 */
135 private int tileHeight;
136
137 /**
138 * The image width.
139 */
140 private int width;
141
142 /**
143 * The image height.
144 */
145 private int height;
146
147 /**
148 * The number of tiles across the image.
149 */
150 private int tilesX;
151
152 /**
153 * The number of tiles down the image.
154 */
155 private int tilesY;
156
157 /**
158 * The width of the source tiles.
159 */
160 private int majorTileWidth;
161
162 /**
163 * The height of the source tiles.
164 */
165 private int majorTileHeight;
166
167 public MosaicOpImage(int rows, int cols, Vector sources) {
168 super(sources, null, null, true);
169 this.rows = rows;
170 this.cols = cols;
171
172 //if (sources.size() < rows*cols)
173 // throw new IllegalArgumentException("Not enough sources supplied to MosaicOperator");
174
175 int count = sources.size();
176 for (int i = 0; i < count; i++)
177 addSource((PlanarImage)sources.elementAt(i));
178
179 PlanarImage baseTile = (PlanarImage)sources.firstElement();
180 majorTileWidth = baseTile.getWidth();
181 majorTileHeight = baseTile.getHeight();
182 tileWidth = baseTile.getTileWidth();
183 tileHeight = baseTile.getTileHeight();
184 width = cols * majorTileWidth;
185 height = rows * majorTileHeight;
186
187 tilesX = (width + tileWidth - 1) / tileWidth;
188 tilesY = (height + tileHeight - 1) / tileHeight;
189
190 SampleModel sampleModel = baseTile.getSampleModel();
191 ColorModel colorModel = baseTile.getColorModel();
192
193 ImageLayout imageLayout = new ImageLayout(0, 0, width, height, 0, 0, tileWidth, tileHeight, sampleModel, colorModel);
194 setImageLayout(imageLayout);
195 }
196
197 public Raster computeTile(int x, int y) {
198 DataBuffer dataBuffer = sampleModel.createDataBuffer();
199
200 if (x < 0 || x >= tilesX || y < 0 || y >= tilesY) {
201 System.out.println("Error: illegal tile requested from a MosaicOpImage.");
202 Raster raster = Raster.createRaster(sampleModel, dataBuffer, new Point(x * tileWidth, y * tileHeight));
203 return raster;
204 }
205 try {
206 int tx = x * tileWidth / majorTileWidth;
207 int ty = y * tileHeight / majorTileHeight;
208 Rectangle r = new Rectangle(tileWidth * (x % (majorTileWidth/tileWidth)), tileHeight * (y % (majorTileHeight/tileHeight)), tileWidth, tileHeight);
209 PlanarImage op = getSourceImage(ty*cols+tx);
210 Raster raster = null;
211 synchronized(op) {
212 raster = op.getData(r);
213 raster = raster.createTranslatedChild(x * tileWidth, y * tileHeight);
214 }
215 return raster;
216 }
217 catch (Exception e) {
218 e.printStackTrace();
219 }
220 return Raster.createRaster(sampleModel, dataBuffer, new Point(x * tileWidth, y * tileHeight));
221 }
222
223 public Rectangle mapDestRect(Rectangle rectangle, int i) {
224 return rectangle;
225 }
226
227 public Rectangle mapSourceRect(Rectangle rectangle, int i) {
228 return rectangle;
229 }
230 }