Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

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}