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