Source code: non_com/media/jai/RasterFactory.java
1 /*
2 * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * -Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * -Redistribution in binary form must reproduct the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
15 * be used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * This software is provided "AS IS," without a warranty of any kind. ALL
19 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
20 * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
21 * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
22 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
23 * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
24 * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
25 * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
26 * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
27 * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGES.
29 *
30 * You acknowledge that Software is not designed,licensed or intended for use in
31 * the design, construction, operation or maintenance of any nuclear facility.
32 */
33 package non_com.media.jai;
34
35 import non_com.media.jai.codec.JaiI18N;
36
37 import java.awt.Point;
38 import java.awt.Rectangle;
39 import java.awt.Transparency;
40 import java.awt.color.ColorSpace;
41 import java.awt.image.BandedSampleModel;
42 import java.awt.image.ComponentColorModel;
43 import java.awt.image.ComponentSampleModel;
44 import java.awt.image.DataBuffer;
45 import java.awt.image.DataBufferByte;
46 import java.awt.image.DataBufferInt;
47 import java.awt.image.DataBufferShort;
48 import java.awt.image.DataBufferUShort;
49 import java.awt.image.PixelInterleavedSampleModel;
50 import java.awt.image.Raster;
51 import java.awt.image.RasterFormatException;
52 import java.awt.image.SampleModel;
53 import java.awt.image.WritableRaster;
54
55 /**
56 * A convenience class for the construction of various types of <code>WritableRaster</code>
57 * and <code>SampleModel</code> objects. <p>
58 *
59 * This class provides the capability of creating <code>Raster</code>s with the
60 * enumerated data types in the java.awt.image.DataBuffer. <p>
61 *
62 * In some cases, instances of <code>ComponentSampleModelJAI</code>, a subclass
63 * of <code>java.awt.image.ComponentSampleModel</code> are instantiated instead
64 * of <code>java.awt.image.BandedSampleModel</code> in order to work around
65 * bugs in the current release of the Java 2 SDK.
66 *
67 */
68 public class RasterFactory {
69
70 /**
71 * Creates a <code>WritableRaster</code> based on a <code>PixelInterleavedSampleModel</code>
72 * with the specified data type, width, height, and number of bands. <p>
73 *
74 * The upper left corner of the <code>WritableRaster</code> is given by the
75 * <code>location</code> argument. If <code>location</code> is <code>null</code>
76 * , (0, 0) will be used. The <code>dataType</code> parameter should be one
77 * of the enumerated values defined in the <code>DataBuffer</code> class.
78 *
79 * @param dataType The data type of the <code>SampleModel</code>
80 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>,
81 * <code>TYPE_SHORT</code>, <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>
82 * , or <code>TYPE_DOUBLE</code>.
83 * @param width The desired width of the <code>WritableRaster</code>
84 * .
85 * @param height The desired height of the <code>WritableRaster</code>
86 * .
87 * @param numBands The desired number of bands.
88 * @param location A <code>Point</code> indicating the
89 * starting coordinates of the <code>WritableRaster</code>.
90 * @return Description of the Returned Value
91 * @throws IllegalArgumentException if <code>numbands</code> is <code><1</code>
92 * .
93 */
94 public static WritableRaster createInterleavedRaster(int dataType,
95 int width, int height,
96 int numBands,
97 Point location) {
98 if (numBands < 1) {
99 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory0"));
100 }
101 int[] bandOffsets = new int[numBands];
102 for (int i = 0; i < numBands; i++) {
103 bandOffsets[i] = numBands - 1 - i;
104 }
105 return createInterleavedRaster(dataType, width, height,
106 width * numBands, numBands,
107 bandOffsets, location);
108 }
109
110
111 /**
112 * Creates a <code>WritableRaster</code> based on a <code>PixelInterleavedSampleModel</code>
113 * with the specified data type, width, height, scanline stride, pixel
114 * stride, and band offsets. The number of bands is inferred from
115 * bandOffsets.length. <p>
116 *
117 * The upper left corner of the <code>WritableRaster</code> is given by the
118 * <code>location</code> argument. If <code>location</code> is <code>null</code>
119 * , (0, 0) will be used. The <code>dataType</code> parameter should be one
120 * of the enumerated values defined in the <code>DataBuffer</code> class.
121 *
122 * @param dataType The data type of the <code>WritableRaster</code>
123 * , one of the enumerated dataType values in java.awt.image.DataBuffer.
124 * @param width The desired width of the <code>WritableRaster</code>
125 * .
126 * @param height The desired height of the <code>WritableRaster</code>
127 * .
128 * @param scanlineStride The desired scanline stride.
129 * @param pixelStride The desired pixel stride.
130 * @param bandOffsets An array of <code>int</code>s indicating
131 * the relative offsets of the bands within a pixel.
132 * @param location A <code>Point</code> indicating the
133 * starting coordinates of the <code>WritableRaster</code>.
134 * @return Description of the Returned Value
135 * @throws IllegalArgumentException if <code>bandOffsets</code> is <code>null</code>
136 * , <code>dataType</code> is not one of the enumerated dataType value of
137 * java.awt.image.DataBuffer.
138 * @throws IllegalArgumentException if the number of array elements required
139 * by the returned <code>WritableRaster</code> would exceed <code>Integer.MAX_VALUE</code>
140 * .
141 */
142 public static WritableRaster createInterleavedRaster(int dataType,
143 int width, int height,
144 int scanlineStride,
145 int pixelStride,
146 int bandOffsets[],
147 Point location) {
148
149 if (bandOffsets == null) {
150 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory4"));
151 }
152
153 DataBuffer d;
154 int bands = bandOffsets.length;
155
156 int maxBandOff = bandOffsets[0];
157 for (int i = 1; i < bands; i++) {
158 if (bandOffsets[i] > maxBandOff) {
159 maxBandOff = bandOffsets[i];
160 }
161 }
162
163 long lsize = (long) maxBandOff +
164 (long) scanlineStride * (height - 1) + (long) pixelStride * (width - 1) +
165 1L;
166 if (lsize > (long) Integer.MAX_VALUE) {
167 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory16"));
168 }
169 int size = (int) lsize;
170
171 switch (dataType) {
172 case DataBuffer.TYPE_BYTE:
173 d = new DataBufferByte(size);
174 break;
175 case DataBuffer.TYPE_USHORT:
176 d = new DataBufferUShort(size);
177 break;
178 case DataBuffer.TYPE_SHORT:
179 d = new DataBufferShort(size);
180 break;
181 case DataBuffer.TYPE_INT:
182 d = new DataBufferInt(size);
183 break;
184 case DataBuffer.TYPE_FLOAT:
185 d = new DataBufferFloat(size);
186 break;
187 case DataBuffer.TYPE_DOUBLE:
188 d = new DataBufferDouble(size);
189 break;
190 default:
191 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory3"));
192 }
193
194 return createInterleavedRaster(d, width, height, scanlineStride,
195 pixelStride, bandOffsets, location);
196 }
197
198
199 /**
200 * Creates a <code>WritableRaster</code> based on a <code>ComponentSampleModel</code>
201 * with the specified data type, width, height, and number of bands. <p>
202 *
203 * Note that the <code>Raster</code>'s <code>SampleModel</code> will be of
204 * type <code>ComponentSampleModel</code>, not <code>BandedSampleModel</code>
205 * as might be expected. <p>
206 *
207 * The upper left corner of the <code>WritableRaster</code> is given by the
208 * <code>location</code> argument. If <code>location</code> is <code>null</code>
209 * , (0, 0) will be used. The <code>dataType</code> parameter should be one
210 * of the enumerated values defined in the <code>DataBuffer</code> class.
211 *
212 * @param dataType The data type of the <code>WritableRaster</code>
213 * , one of the enumerated dataType values in java.awt.image.DataBuffer.
214 * @param width The desired width of the <code>WritableRaster</code>
215 * .
216 * @param height The desired height of the <code>WritableRaster</code>
217 * .
218 * @param bands The desired number of bands.
219 * @param location A <code>Point</code> indicating the
220 * starting coordinates of the <code>WritableRaster</code>.
221 * @return Description of the Returned Value
222 * @throws IllegalArgumentException if <code>bands</code> is <code><1</code>
223 * .
224 */
225 public static WritableRaster createBandedRaster(int dataType,
226 int width, int height,
227 int bands,
228 Point location) {
229 if (bands < 1) {
230 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory0"));
231 }
232 int[] bankIndices = new int[bands];
233 int[] bandOffsets = new int[bands];
234 for (int i = 0; i < bands; i++) {
235 bankIndices[i] = i;
236 bandOffsets[i] = 0;
237 }
238
239 return createBandedRaster(dataType, width, height, width,
240 bankIndices, bandOffsets,
241 location);
242 }
243
244
245 /**
246 * Creates a <code>WritableRaster</code> based on a <code>ComponentSampleModel</code>
247 * with the specified data type, width, height, scanline stride, bank indices
248 * and band offsets. The number of bands is inferred from <code>bankIndices.length</code>
249 * and <code>bandOffsets.length</code>, which must be the same. <p>
250 *
251 * Note that the <code>Raster</code>'s <code>SampleModel</code> will be of
252 * type <code>ComponentSampleModel</code>, not <code>BandedSampleModel</code>
253 * as might be expected. <p>
254 *
255 * The upper left corner of the <code>WritableRaster</code> is given by the
256 * <code>location</code> argument. The <code>dataType</code> parameter should
257 * be one of the enumerated values defined in the <code>DataBuffer</code>
258 * class.
259 *
260 * @param dataType The data type of the <code>WritableRaster</code>
261 * , one of the enumerated dataType values in java.awt.image.DataBuffer.
262 * @param width The desired width of the <code>WritableRaster</code>
263 * .
264 * @param height The desired height of the <code>WritableRaster</code>
265 * .
266 * @param scanlineStride The desired scanline stride.
267 * @param bankIndices An array of <code>int</code>s indicating
268 * the bank index for each band.
269 * @param bandOffsets An array of <code>int</code>s indicating
270 * the relative offsets of the bands within a pixel.
271 * @param location A <code>Point</code> indicating the
272 * starting coordinates of the <code>WritableRaster</code>.
273 * @return Description of the Returned Value
274 * @throws IllegalArgumentException if <code>bankIndices</code> is <code>null</code>
275 * , <code>bandOffsets</code> is <code>null</code>, if <code>bandOffsets.length</code>
276 * is <code>!=</code> <code>bankIndices.length</code>, if <code>dataType</code>
277 * is not one of the enumerated datatypes of java.awt.image.DataBuffer.
278 */
279 public static WritableRaster createBandedRaster(int dataType,
280 int width, int height,
281 int scanlineStride,
282 int bankIndices[],
283 int bandOffsets[],
284 Point location) {
285 DataBuffer d;
286 int bands = bandOffsets.length;
287
288 if (bankIndices == null) {
289 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory1"));
290 }
291 if (bandOffsets == null) {
292 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory4"));
293 }
294
295 if (bandOffsets.length != bankIndices.length) {
296 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory2"));
297 }
298
299 // Figure out the #banks and the largest band offset
300 int maxBank = bankIndices[0];
301 int maxBandOff = bandOffsets[0];
302 for (int i = 1; i < bands; i++) {
303 if (bankIndices[i] > maxBank) {
304 maxBank = bankIndices[i];
305 }
306 if (bandOffsets[i] > maxBandOff) {
307 maxBandOff = bandOffsets[i];
308 }
309 }
310
311 int banks = maxBank + 1;
312 long lsize = (long) maxBandOff + (long) scanlineStride * (height - 1) +
313 (long) (width - 1) + 1L;
314 if (lsize > (long) Integer.MAX_VALUE) {
315 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory16"));
316 }
317 int size = (int) lsize;
318
319 switch (dataType) {
320 case DataBuffer.TYPE_BYTE:
321 d = new DataBufferByte(size, banks);
322 break;
323 case DataBuffer.TYPE_USHORT:
324 d = new DataBufferUShort(size, banks);
325 break;
326 case DataBuffer.TYPE_SHORT:
327 d = new DataBufferShort(size, banks);
328 break;
329 case DataBuffer.TYPE_INT:
330 d = new DataBufferInt(size, banks);
331 break;
332 case DataBuffer.TYPE_FLOAT:
333 d = new DataBufferFloat(size, banks);
334 break;
335 case DataBuffer.TYPE_DOUBLE:
336 d = new DataBufferDouble(size, banks);
337 break;
338 default:
339 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory3"));
340 }
341
342 return createBandedRaster(d, width, height, scanlineStride,
343 bankIndices, bandOffsets, location);
344 }
345
346
347 /**
348 * Creates a <code>WritableRaster</code> based on a <code>SinglePixelPackedSampleModel</code>
349 * with the specified data type, width, height, and band masks. The number of
350 * bands is inferred from <code>bandMasks.length</code>. <p>
351 *
352 * The upper left corner of the <code>WritableRaster</code> is given by the
353 * <code>location</code> argument. If <code>location</code> is <code>null</code>
354 * , (0, 0) will be used. The <code>dataType</code> parameter should be one
355 * of the enumerated values defined in the <code>DataBuffer</code> class.
356 *
357 * @param dataType The data type of the <code>WritableRaster</code>
358 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>
359 * or <code>TYPE_INT</code>.
360 * @param width The desired width of the <code>WritableRaster</code>
361 * .
362 * @param height The desired height of the <code>WritableRaster</code>
363 * .
364 * @param location A <code>Point</code> indicating the
365 * starting coordinates of the <code>WritableRaster</code>.
366 * @param bandMasks Description of Parameter
367 * @return Description of the Returned Value
368 * @throws IllegalArgumentException is thrown if the <code>dataType</code>
369 * is not of either TYPE_BYTE or TYPE_USHORT or TYPE_INT.
370 */
371 public static WritableRaster createPackedRaster(int dataType,
372 int width, int height,
373 int bandMasks[],
374 Point location) {
375 return Raster.createPackedRaster(dataType,
376 width, height, bandMasks, location);
377 }
378
379
380 /**
381 * Creates a <code>WritableRaster</code> based on a packed <code>SampleModel</code>
382 * with the specified data type, width, height, number of bands, and bits per
383 * band. If the number of bands is one, the <code>SampleModel</code> will be
384 * a <code>MultiPixelPackedSampleModel</code>. <p>
385 *
386 * If the number of bands is more than one, the <code>SampleModel</code> will
387 * be a <code>SinglePixelPackedSampleModel</code>, with each band having
388 * <code>bitsPerBand</code> bits. In either case, the requirements on <code>dataType</code>
389 * and <code>bitsPerBand</code> imposed by the corresponding <code>SampleModel</code>
390 * must be met. <p>
391 *
392 * The upper left corner of the <code>WritableRaster</code> is given by the
393 * <code>location</code> argument. If <code>location</code> is <code>null</code>
394 * , (0, 0) will be used. The <code>dataType</code> parameter should be one
395 * of the enumerated values defined in the <code>DataBuffer</code> class.
396 *
397 * @param dataType The data type of the <code>WritableRaster</code>
398 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>
399 * or <code>TYPE_INT</code>.
400 * @param width The desired width of the <code>WritableRaster</code>
401 * .
402 * @param height The desired height of the <code>WritableRaster</code>
403 * .
404 * @param numBands The desired number of bands.
405 * @param bitsPerBand The number of bits per band.
406 * @param location A <code>Point</code> indicating the
407 * starting coordinates of the <code>WritableRaster</code>.
408 * @return Description of the Returned Value
409 * @throws IllegalArgumentException is thrown if the <code>dataType</code>
410 * is not of either TYPE_BYTE or TYPE_USHORT or TYPE_INT.
411 * @throws IllegalArgumentException is thrown if bitsPerBand is negative or
412 * zero.
413 */
414 public static WritableRaster createPackedRaster(int dataType,
415 int width, int height,
416 int numBands,
417 int bitsPerBand,
418 Point location) {
419 if (bitsPerBand <= 0) {
420 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory15"));
421 }
422
423 return Raster.createPackedRaster(dataType, width, height, numBands,
424 bitsPerBand, location);
425 }
426
427
428 /**
429 * Creates a <code>WritableRaster</code> based on a <code>PixelInterleavedSampleModel</code>
430 * with the specified <code>DataBuffer</code>, width, height, scanline
431 * stride, pixel stride, and band offsets. The number of bands is inferred
432 * from <code>bandOffsets.length</code>. The upper left corner of the <code>WritableRaster</code>
433 * is given by the <code>location</code> argument. If <code>location</code>
434 * is <code>null</code>, (0, 0) will be used.
435 *
436 * @param dataBuffer The <code>DataBuffer</code> to be used.
437 * @param width The desired width of the <code>WritableRaster</code>
438 * .
439 * @param height The desired height of the <code>WritableRaster</code>
440 * .
441 * @param scanlineStride The desired scanline stride.
442 * @param pixelStride The desired pixel stride.
443 * @param bandOffsets An array of <code>int</code>s indicating
444 * the relative offsets of the bands within a pixel.
445 * @param location A <code>Point</code> indicating the
446 * starting coordinates of the <code>WritableRaster</code>.
447 * @return Description of the Returned Value
448 * @throws IllegalArgumentException if <code>bandOffsets</code> is <code>null</code>
449 * , if <code>pixelStride*width</code> is <code>></code> <code>scanlineStride</code>
450 * , if <code>dataType</code>of the DataBuffer is not one the enumerated
451 * dataType value of java.awt.image.DataBuffer.
452 */
453 public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer,
454 int width, int height,
455 int scanlineStride,
456 int pixelStride,
457 int bandOffsets[],
458 Point location) {
459
460 if (bandOffsets == null) {
461 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory4"));
462 }
463 if (location == null) {
464 location = new Point(0, 0);
465 }
466 int dataType = dataBuffer.getDataType();
467
468 switch (dataType) {
469 case DataBuffer.TYPE_BYTE:
470 case DataBuffer.TYPE_USHORT:
471 PixelInterleavedSampleModel csm =
472 new PixelInterleavedSampleModel(dataType, width, height,
473 pixelStride,
474 scanlineStride,
475 bandOffsets);
476 return Raster.createWritableRaster(csm, dataBuffer, location);
477 case DataBuffer.TYPE_INT:
478 case DataBuffer.TYPE_SHORT:
479 case DataBuffer.TYPE_FLOAT:
480 case DataBuffer.TYPE_DOUBLE:
481 int minBandOff = bandOffsets[0];
482 int maxBandOff = bandOffsets[0];
483 for (int i = 1; i < bandOffsets.length; i++) {
484 minBandOff = Math.min(minBandOff, bandOffsets[i]);
485 maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
486 }
487 maxBandOff -= minBandOff;
488 if (maxBandOff > scanlineStride) {
489 throw new IllegalArgumentException(
490 JaiI18N.getString("RasterFactory5"));
491 }
492 if (pixelStride * width > scanlineStride) {
493 throw new IllegalArgumentException(
494 JaiI18N.getString("RasterFactory6"));
495 }
496 if (pixelStride < maxBandOff) {
497 throw new IllegalArgumentException(
498 JaiI18N.getString("RasterFactory7"));
499 }
500
501 SampleModel sm =
502 new ComponentSampleModelJAI(dataType, width, height,
503 pixelStride,
504 scanlineStride,
505 bandOffsets);
506 return Raster.createWritableRaster(sm, dataBuffer, location);
507 default:
508 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory3"));
509 }
510 }
511
512
513 /**
514 * Creates a <code>WritableRaster</code> based on a <code>ComponentSampleModel</code>
515 * with the specified <code>DataBuffer</code>, width, height, scanline
516 * stride, bank indices, and band offsets. The number of bands is inferred
517 * from <code>bankIndices.length</code> and <code>bandOffsets.length</code>,
518 * which must be the same. The upper left corner of the <code>WritableRaster</code>
519 * is given by the <code>location</code> argument. If <code>location</code>
520 * is <code>null</code>, (0, 0) will be used. <p>
521 *
522 * Note that the <code>Raster</code>'s <code>SampleModel</code> will be of
523 * type <code>ComponentSampleModel</code>, not <code>BandedSampleModel</code>
524 * as might be expected.
525 *
526 * @param dataBuffer The <code>DataBuffer</code> to be used.
527 * @param width The desired width of the <code>WritableRaster</code>
528 * .
529 * @param height The desired height of the <code>WritableRaster</code>
530 * .
531 * @param scanlineStride The desired scanline stride.
532 * @param bankIndices An array of <code>int</code>s indicating
533 * the bank index for each band.
534 * @param bandOffsets An array of <code>int</code>s indicating
535 * the relative offsets of the bands within a pixel.
536 * @param location A <code>Point</code> indicating the
537 * starting coordinates of the <code>WritableRaster</code>.
538 * @return Description of the Returned Value
539 * @throws IllegalArgumentException if <code>bankIndices</code> is <code>null</code>
540 * , if <code>bandOffsets</code> is <code>null</code>, if <code>bandOffsets.length</code>
541 * is <code>!=</code> <code>bankIndices.length</code>, if <code>dataType</code>
542 * is not one of the enumerated datatypes of java.awt.image.DataBuffer.
543 */
544 public static WritableRaster createBandedRaster(DataBuffer dataBuffer,
545 int width, int height,
546 int scanlineStride,
547 int bankIndices[],
548 int bandOffsets[],
549 Point location) {
550 if (location == null) {
551 location = new Point(0, 0);
552 }
553 int dataType = dataBuffer.getDataType();
554
555 if (bankIndices == null) {
556 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory1"));
557 }
558 if (bandOffsets == null) {
559 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory4"));
560 }
561
562 int bands = bankIndices.length;
563 if (bandOffsets.length != bands) {
564 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory2"));
565 }
566
567 SampleModel bsm =
568 new ComponentSampleModelJAI(dataType, width, height,
569 1, scanlineStride,
570 bankIndices, bandOffsets);
571
572 switch (dataType) {
573 case DataBuffer.TYPE_BYTE:
574 case DataBuffer.TYPE_USHORT:
575 case DataBuffer.TYPE_INT:
576 case DataBuffer.TYPE_SHORT:
577 case DataBuffer.TYPE_FLOAT:
578 case DataBuffer.TYPE_DOUBLE:
579 return Raster.createWritableRaster(bsm, dataBuffer, location);
580 default:
581 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory3"));
582 }
583 }
584
585
586 /**
587 * Creates a <code>WritableRaster</code> based on a <code>SinglePixelPackedSampleModel</code>
588 * with the specified <code>DataBuffer</code>, width, height, scanline
589 * stride, and band masks. The number of bands is inferred from <code>bandMasks.length</code>
590 * . The upper left corner of the <code>WritableRaster</code> is given by the
591 * <code>location</code> argument. If <code>location</code> is <code>null</code>
592 * , (0, 0) will be used.
593 *
594 * @param dataBuffer The <code>DataBuffer</code> to be used.
595 * @param width The desired width of the <code>WritableRaster</code>
596 * .
597 * @param height The desired height of the <code>WritableRaster</code>
598 * .
599 * @param scanlineStride The desired scanline stride.
600 * @param bandMasks An array of <code>int</code>s indicating
601 * the bitmasks for each band within a pixel.
602 * @param location A <code>Point</code> indicating the
603 * starting coordinates of the <code>WritableRaster</code>.
604 * @return Description of the Returned Value
605 * @throws IllegalArgumentException is thrown if the <code>dataType</code>
606 * is not of either TYPE_BYTE or TYPE_USHORT or TYPE_INT.
607 */
608 public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
609 int width,
610 int height,
611 int scanlineStride,
612 int bandMasks[],
613 Point location) {
614 return Raster.createPackedRaster(dataBuffer, width, height,
615 scanlineStride,
616 bandMasks,
617 location);
618 }
619
620
621 /**
622 * Creates a <code>WritableRaster</code> based on a <code>MultiPixelPackedSampleModel</code>
623 * with the specified <code>DataBuffer</code>, width, height, and bits per
624 * pixel. The upper left corner of the <code>WritableRaster</code> is given
625 * by the <code>location</code> argument. If <code>location</code> is <code>null</code>
626 * , (0, 0) will be used.
627 *
628 * @param dataBuffer The <code>DataBuffer</code> to be used.
629 * @param width The desired width of the <code>WritableRaster</code>
630 * .
631 * @param height The desired height of the <code>WritableRaster</code>
632 * .
633 * @param bitsPerPixel The desired pixel depth.
634 * @param location A <code>Point</code> indicating the
635 * starting coordinates of the <code>WritableRaster</code>.
636 * @return Description of the Returned Value
637 * @throws IllegalArgumentException is thrown if the <code>dataType</code>
638 * of the <code>dataBuffer</code> is not of either TYPE_BYTE or
639 * TYPE_USHORT or TYPE_INT.
640 */
641 public static WritableRaster createPackedRaster(DataBuffer dataBuffer,
642 int width,
643 int height,
644 int bitsPerPixel,
645 Point location) {
646 return Raster.createPackedRaster(dataBuffer, width, height,
647 bitsPerPixel, location);
648 }
649
650
651 /**
652 * Creates a <code>WritableRaster</code> with the specified <code>SampleModel</code>
653 * and <code>DataBuffer</code>. The upper left corner of the <code>WritableRaster</code>
654 * is given by the <code>location</code> argument. If <code>location</code>
655 * is <code>null</code>, (0, 0) will be used.
656 *
657 * @param sampleModel The <code>SampleModel</code> to be used.
658 * @param dataBuffer The <code>DataBuffer</code> to be used.
659 * @param location A <code>Point</code> indicating the starting
660 * coordinates of the <code>WritableRaster</code>.
661 * @return Description of the Returned Value
662 */
663 public static Raster createRaster(SampleModel sampleModel,
664 DataBuffer dataBuffer,
665 Point location) {
666 return Raster.createRaster(sampleModel, dataBuffer, location);
667 }
668
669
670 /**
671 * Creates a <code>WritableRaster</code> with the specified <code>SampleModel</code>
672 * . The upper left corner of the <code>WritableRaster</code> is given by the
673 * <code>location</code> argument. If <code>location</code> is <code>null</code>
674 * , (0, 0) will be used.
675 *
676 * @param sampleModel The <code>SampleModel</code> to use.
677 * @param location A <code>Point</code> indicating the starting
678 * coordinates of the <code>WritableRaster</code>.
679 * @return Description of the Returned Value
680 */
681 public static WritableRaster createWritableRaster(SampleModel sampleModel,
682 Point location) {
683 if (location == null) {
684 location = new Point(0, 0);
685 }
686
687 return createWritableRaster(sampleModel,
688 sampleModel.createDataBuffer(),
689 location);
690 }
691
692
693 /**
694 * Creates a <code>WritableRaster</code> with the specified <code>SampleModel</code>
695 * and <code>DataBuffer</code>. The upper left corner of the <code>WritableRaster</code>
696 * is given by the <code>location</code> argument. If <code>location</code>
697 * is <code>null</code>, (0, 0) will be used.
698 *
699 * @param sampleModel The <code>SampleModel</code> to be used.
700 * @param dataBuffer The <code>DataBuffer</code> to be used.
701 * @param location A <code>Point</code> indicating the starting
702 * coordinates of the <code>WritableRaster</code>.
703 * @return Description of the Returned Value
704 */
705 public static WritableRaster createWritableRaster(SampleModel sampleModel,
706 DataBuffer dataBuffer,
707 Point location) {
708 return Raster.createWritableRaster(sampleModel, dataBuffer, location);
709 }
710
711
712 /**
713 * Returns a new WritableRaster which shares all or part of the supplied
714 * WritableRaster's DataBuffer. The new WritableRaster will possess a
715 * reference to the supplied WritableRaster, accessible through its
716 * getParent() and getWritableParent() methods. <p>
717 *
718 * This method provides a workaround for a bug in the implementation of
719 * WritableRaster.createWritableChild in the initial relase of the Java2
720 * platform. <p>
721 *
722 * The <code>parentX</code>, <code>parentY</code>, <code>width</code> and
723 * <code>height</code> parameters form a Rectangle in this WritableRaster's
724 * coordinate space, indicating the area of pixels to be shared. An error
725 * will be thrown if this Rectangle is not contained with the bounds of the
726 * supplied WritableRaster. <p>
727 *
728 * The new WritableRaster may additionally be translated to a different
729 * coordinate system for the plane than that used by the supplied
730 * WritableRaster. The childMinX and childMinY parameters give the new (x, y)
731 * coordinate of the upper-left pixel of the returned WritableRaster; the
732 * coordinate (childMinX, childMinY) in the new WritableRaster will map to
733 * the same pixel as the coordinate (parentX, parentY) in the supplied
734 * WritableRaster. <p>
735 *
736 * The new WritableRaster may be defined to contain only a subset of the
737 * bands of the supplied WritableRaster, possibly reordered, by means of the
738 * bandList parameter. If bandList is null, it is taken to include all of the
739 * bands of the supplied WritableRaster in their current order. <p>
740 *
741 * To create a new WritableRaster that contains a subregion of the supplied
742 * WritableRaster, but shares its coordinate system and bands, this method
743 * should be called with childMinX equal to parentX, childMinY equal to
744 * parentY, and bandList equal to null.
745 *
746 * @param raster The parent WritableRaster.
747 * @param parentX X coordinate of the upper left corner of
748 * the shared rectangle in this WritableRaster's coordinates.
749 * @param parentY Y coordinate of the upper left corner of
750 * the shared rectangle in this WritableRaster's coordinates.
751 * @param width Width of the shared rectangle starting at (
752 * <code>parentX</code>, <code>parentY</code>).
753 * @param height Height of the shared rectangle starting at
754 * (<code>parentX</code>, <code>parentY</code>).
755 * @param childMinX X coordinate of the upper left corner of
756 * the returned WritableRaster.
757 * @param childMinY Y coordinate of the upper left corner of
758 * the returned WritableRaster.
759 * @param bandList Array of band indices, or null to use all
760 * bands.
761 * @return Description of the Returned Value
762 * @throws RasterFormatException if the subregion is outside of the raster
763 * bounds.
764 */
765 public static WritableRaster createWritableChild(WritableRaster raster,
766 int parentX,
767 int parentY,
768 int width,
769 int height,
770 int childMinX,
771 int childMinY,
772 int bandList[]) {
773 if (parentX < raster.getMinX()) {
774 throw new RasterFormatException(JaiI18N.getString("RasterFactory9"));
775 }
776 if (parentY < raster.getMinY()) {
777 throw new
778 RasterFormatException(JaiI18N.getString("RasterFactory10"));
779 }
780 if (parentX + width > raster.getWidth() + raster.getMinX()) {
781 throw new
782 RasterFormatException(JaiI18N.getString("RasterFactory11"));
783 }
784 if (parentY + height > raster.getHeight() + raster.getMinY()) {
785 throw new
786 RasterFormatException(JaiI18N.getString("RasterFactory12"));
787 }
788
789 SampleModel sampleModel = raster.getSampleModel();
790 DataBuffer dataBuffer = raster.getDataBuffer();
791 int sampleModelTranslateX = raster.getSampleModelTranslateX();
792 int sampleModelTranslateY = raster.getSampleModelTranslateY();
793
794 SampleModel sm;
795
796 if (bandList != null) {
797 sm = sampleModel.createCompatibleSampleModel(
798 sampleModel.getWidth(),
799 sampleModel.getHeight());
800 sm = sm.createSubsetSampleModel(bandList);
801 }
802 else {
803 sm = sampleModel;
804 }
805
806 int deltaX = childMinX - parentX;
807 int deltaY = childMinY - parentY;
808
809 return new WritableRasterJAI(sm,
810 dataBuffer,
811 new Rectangle(childMinX, childMinY,
812 width, height),
813 new Point(sampleModelTranslateX + deltaX,
814 sampleModelTranslateY + deltaY),
815 raster);
816 }
817
818
819 /**
820 * Creates a banded <code>SampleModel</code> with a given data type, width,
821 * height, number of bands, bank indices, and band offsets. <p>
822 *
823 * Note that the returned <code>SampleModel</code> will be of type <code>ComponentSampleModel</code>
824 * , not <code>BandedSampleModel</code> as might be expected. Its behavior
825 * will be equivalent to that of a <code>BandedSampleModel</code>, and in
826 * particular its pixel stride will always be 1.
827 *
828 * @param dataType The data type of the <code>SampleModel</code>
829 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>,
830 * <code>TYPE_SHORT</code>, <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>
831 * , or <code>TYPE_DOUBLE</code>.
832 * @param width The desired width of the <code>SampleModel</code>
833 * .
834 * @param height The desired height of the <code>SampleModel</code>
835 * .
836 * @param numBands The desired number of bands.
837 * @param bankIndices An array of <code>int</code>s indicating
838 * the bank index for each band.
839 * @param bandOffsets An array of <code>int</code>s indicating
840 * the relative offsets of the bands within a pixel.
841 * @return Description of the Returned Value
842 * @throws IllegalArgumentException if <code>numBands</code> is <code><1</code>
843 * , if <code>bandOffsets.length</code> is <code>!=</code> <code>bankIndices.length</code>
844 * .
845 */
846 public static SampleModel createBandedSampleModel(int dataType,
847 int width,
848 int height,
849 int numBands,
850 int bankIndices[],
851 int bandOffsets[]) {
852 if (numBands < 1) {
853 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory0"));
854 }
855 if (bankIndices == null) {
856 bankIndices = new int[numBands];
857 for (int i = 0; i < numBands; i++) {
858 bankIndices[i] = i;
859 }
860 }
861 if (bandOffsets == null) {
862 bandOffsets = new int[numBands];
863 for (int i = 0; i < numBands; i++) {
864 bandOffsets[i] = 0;
865 }
866 }
867 if (bandOffsets.length != bankIndices.length) {
868 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory2"));
869 }
870 return new ComponentSampleModelJAI(dataType,
871 width, height, 1, width,
872 bankIndices,
873 bandOffsets);
874 }
875
876
877 /**
878 * Creates a banded <code>SampleModel</code> with a given data type, width,
879 * height, and number of bands. The bank indices and band offsets are set to
880 * default values. <p>
881 *
882 * Note that the returned <code>SampleModel</code> will be of type <code>ComponentSampleModel</code>
883 * , not <code>BandedSampleModel</code> as might be expected. Its behavior
884 * will be equivalent to that of a <code>BandedSampleModel</code>, and in
885 * particular its pixel stride will always be 1.
886 *
887 * @param dataType The data type of the <code>SampleModel</code>, one of
888 * <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>, <code>TYPE_SHORT</code>
889 * , <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>, or <code>TYPE_DOUBLE</code>
890 * .
891 * @param width The desired width of the <code>SampleModel</code>.
892 * @param height The desired height of the <code>SampleModel</code>.
893 * @param numBands The desired number of bands.
894 * @return Description of the Returned Value
895 */
896 public static SampleModel createBandedSampleModel(int dataType,
897 int width,
898 int height,
899 int numBands) {
900 return createBandedSampleModel(dataType,
901 width, height, numBands, null, null);
902 }
903
904
905 /**
906 * Creates a pixel interleaved <code>SampleModel</code> with a given data
907 * type, width, height, pixel and scanline strides, and band offsets.
908 *
909 * @param dataType The data type of the <code>SampleModel</code>
910 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>,
911 * <code>TYPE_SHORT</code>, <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>
912 * , or <code>TYPE_DOUBLE</code>.
913 * @param width The desired width of the <code>SampleModel</code>
914 * .
915 * @param height The desired height of the <code>SampleModel</code>
916 * .
917 * @param pixelStride The desired pixel stride.
918 * @param scanlineStride The desired scanline stride.
919 * @param bandOffsets An array of <code>int</code>s indicating
920 * the relative offsets of the bands within a pixel.
921 * @return Description of the Returned Value
922 * @throws IllegalArgumentException if <code>bandOffsets</code> is <code>null</code>
923 * , if the <code>pixelStride*width</code> is <code>></code> than <code>scanlineStride</code>
924 * , if the <code>dataType</code> is not one of the above mentioned
925 * datatypes.
926 */
927 public static SampleModel
928 createPixelInterleavedSampleModel(int dataType,
929 int width, int height,
930 int pixelStride,
931 int scanlineStride,
932 int bandOffsets[]) {
933 if (bandOffsets == null) {
934 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory4"));
935 }
936 int minBandOff = bandOffsets[0];
937 int maxBandOff = bandOffsets[0];
938 for (int i = 1; i < bandOffsets.length; i++) {
939 minBandOff = Math.min(minBandOff, bandOffsets[i]);
940 maxBandOff = Math.max(maxBandOff, bandOffsets[i]);
941 }
942 maxBandOff -= minBandOff;
943 if (maxBandOff > scanlineStride) {
944 throw new IllegalArgumentException(
945 JaiI18N.getString("RasterFactory5"));
946 }
947 if (pixelStride * width > scanlineStride) {
948 throw new IllegalArgumentException(
949 JaiI18N.getString("RasterFactory6"));
950 }
951 if (pixelStride < maxBandOff) {
952 throw new IllegalArgumentException(
953 JaiI18N.getString("RasterFactory7"));
954 }
955
956 switch (dataType) {
957 case DataBuffer.TYPE_BYTE:
958 case DataBuffer.TYPE_USHORT:
959 return new PixelInterleavedSampleModel(dataType,
960 width, height,
961 pixelStride,
962 scanlineStride,
963 bandOffsets);
964 case DataBuffer.TYPE_INT:
965 case DataBuffer.TYPE_SHORT:
966 case DataBuffer.TYPE_FLOAT:
967 case DataBuffer.TYPE_DOUBLE:
968 return new ComponentSampleModelJAI(dataType,
969 width, height,
970 pixelStride,
971 scanlineStride,
972 bandOffsets);
973 default:
974 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory3"));
975 }
976 }
977
978
979 /**
980 * Creates a pixel interleaved <code>SampleModel</code> with a given data
981 * type, width, height, and number of bands. The pixel stride, scanline
982 * stride, and band offsets are set to default values.
983 *
984 * @param dataType The data type of the <code>SampleModel</code>
985 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>,
986 * <code>TYPE_SHORT</code>, <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>
987 * , or <code>TYPE_DOUBLE</code>.
988 * @param width The desired width of the <code>SampleModel</code>
989 * .
990 * @param height The desired height of the <code>SampleModel</code>
991 * .
992 * @param numBands The desired number of bands.
993 * @return Description of the Returned Value
994 * @throws IllegalArgumentException if <code>numBands</code> is <code><1</code>
995 * .
996 */
997 public static SampleModel
998 createPixelInterleavedSampleModel(int dataType,
999 int width,
1000 int height,
1001 int numBands) {
1002 if (numBands < 1) {
1003 throw new IllegalArgumentException(JaiI18N.getString("RasterFactory0"));
1004 }
1005 int[] bandOffsets = new int[numBands];
1006 for (int i = 0; i < numBands; i++) {
1007 bandOffsets[i] = numBands - 1 - i;
1008 }
1009
1010 return createPixelInterleavedSampleModel(dataType, width, height,
1011 numBands, numBands * width, bandOffsets);
1012 }
1013
1014
1015 /**
1016 * Creates a component <code>SampleModel</code> with a given data type,
1017 * width, height, and number of bands that is "compatible" with a given
1018 * SampleModel.
1019 *
1020 * @param sm The <code>SampleModel</code> to be compatible with.
1021 * @param dataType The data type of the <code>SampleModel</code>, one of
1022 * <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>, <code>TYPE_SHORT</code>
1023 * , <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>, or <code>TYPE_DOUBLE</code>
1024 * .
1025 * @param width The desired width of the <code>SampleModel</code>.
1026 * @param height The desired height of the <code>SampleModel</code>.
1027 * @param numBands The desired number of bands.
1028 * @return Description of the Returned Value
1029 */
1030 public static SampleModel createComponentSampleModel(SampleModel sm,
1031 int dataType,
1032 int width,
1033 int height,
1034 int numBands) {
1035 if (sm instanceof BandedSampleModel) {
1036 return createBandedSampleModel(dataType, width, height, numBands);
1037 }
1038 else {
1039 // default SampleModel
1040 return createPixelInterleavedSampleModel(
1041 dataType, width, height, numBands);
1042 }
1043 }
1044
1045
1046 /**
1047 * Creates a component-based <code>ColorModel</code> with a given data type,
1048 * color space, and transparency type. Currently this method does not support
1049 * data type <code>DataBuffer.TYPE_SHORT</code>. If useAlpha is false, both
1050 * premultiplied and transparency input are ignored and they are set to be
1051 * <code> false</code> and <code> Transparency.OPQAUE </code>, respectively.
1052 *
1053 * @param dataType The data type of the <code>ColorModel</code>
1054 * , one of <code>DataBuffer.TYPE_BYTE</code>, <code>TYPE_USHORT</code>,
1055 * <code>TYPE_INT</code>, <code>TYPE_FLOAT</code>, or <code>TYPE_DOUBLE</code>
1056 * .
1057 * @param colorSpace An instance of <code>ColorSpace</code>
1058 * .
1059 * @param useAlpha <code>true</code> if alpha is
1060 * to be used.
1061 * @param premultiplied <code>true</code> if alpha
1062 * values are premultiplied. If <code>useAlpha</code> is <code>false</code>
1063 * , the value of <code>premultiplied</code> is ignored.
1064 * @param transparency One of <code>Transparency.OPAQUE</code>
1065 * , <code>Transparency.BITMASK</code>, or <code>Transparency.TRANSLUCENT</code>
1066 * . If <code>useAlpha</code> is <code>false</code>, the value of <code>transparency</code>
1067 * is ignored. If <code>useAlpha</code> is <code>true</code>, <code>transparency</code>
1068 * must not equal <code>Transparency.OPQAUE</code>.
1069 * @return Description of the Returned
1070 * Value
1071 * @throws IllegalArgumentExceptionException if <code>colorSpace</code> is
1072 * <code>null</code>.
1073 * @throws IllegalArgumentException if <code>transparency</code>
1074 * has an unknown value, if <code>useAlpha == true</code> but <code>transparency == Transparency.OPAQUE</code>
1075 * , or if <code>dataType</code> is not one of the standard types listed
1076 * above.
1077 */
1078 public static ComponentColorModel createComponentColorModel(int dataType,
1079 ColorSpace colorSpace,
1080 boolean useAlpha,
1081 boolean premultiplied,
1082 int transparency) {
1083
1084 if (colorSpace == null) {
1085 throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
1086 }
1087
1088 if ((transparency != Transparency.OPAQUE) &&
1089 (transparency != Transparency.BITMASK) &&
1090 (transparency != Transparency.TRANSLUCENT)) {
1091 // Illegal value for transparency
1092 throw new
1093 IllegalArgumentException(JaiI18N.getString("RasterFactory13"));
1094 }
1095
1096 if (useAlpha && (transparency == Transparency.OPAQUE)) {
1097 throw new
1098 IllegalArgumentException(JaiI18N.getString("RasterFactory14"));
1099 }
1100
1101 if (!useAlpha) {
1102 premultiplied = false;
1103 transparency = Transparency.OPAQUE;
1104 }
1105
1106 int bands = colorSpace.getNumComponents();
1107 if (useAlpha) {
1108 ++bands;
1109 }
1110
1111 int dataTypeSize = DataBuffer.getDataTypeSize(dataType);
1112 int[] bits = new int[bands];
1113 for (int i = 0; i < bands; i++) {
1114 bits[i] = dataTypeSize;
1115 }
1116
1117 switch (dataType) {
1118 case DataBuffer.TYPE_BYTE:
1119 return new ComponentColorModel(colorSpace,
1120 bits,
1121 useAlpha,
1122 premultiplied,
1123 transparency,
1124 dataType);
1125 case DataBuffer.TYPE_USHORT:
1126 return new ComponentColorModel(colorSpace,
1127 bits,
1128 useAlpha,
1129 premultiplied,
1130 transparency,
1131 dataType);
1132 /// case DataBuffer.TYPE_SHORT:
1133 /// return new ShortComponentColorModel(colorSpace,
1134 /// bits,
1135 /// useAlpha,
1136 /// premultiplied,
1137 /// transparency);
1138 case DataBuffer.TYPE_INT:
1139 return new ComponentColorModel(colorSpace,
1140 bits,
1141 useAlpha,
1142 premultiplied,
1143 transparency,
1144 dataType);
1145 case DataBuffer.TYPE_FLOAT:
1146 return new FloatDoubleColorModel(colorSpace,
1147 useAlpha,
1148 premultiplied,
1149 transparency,
1150 dataType);
1151 case DataBuffer.TYPE_DOUBLE:
1152 return new FloatDoubleColorModel(colorSpace,
1153 useAlpha,
1154 premultiplied,
1155 transparency,
1156 dataType);
1157 default:
1158 throw new IllegalArgumentException(
1159 JaiI18N.getString("RasterFactory8"));
1160 }
1161 }
1162}
1163
1164class WritableRasterJAI extends WritableRaster {
1165
1166
1167 protected WritableRasterJAI(SampleModel sampleModel,
1168 DataBuffer dataBuffer,
1169 Rectangle aRegion,
1170 Point sampleModelTranslate,
1171 WritableRaster parent) {
1172 super(sampleModel, dataBuffer, aRegion,
1173 sampleModelTranslate, parent);
1174 }
1175}