OSDN Git Service

b3a9962e48d9d282e8ee13a8085a4aca4ef56600
[pf3gnuchains/gcc-fork.git] / libjava / java / awt / image / ComponentSampleModel.java
1 /* Copyright (C) 2000, 2002  Free Software Foundation
2
3 This file is part of GNU Classpath.
4
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING.  If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA.
19
20 As a special exception, if you link this library with other files to
21 produce an executable, this library does not by itself cause the
22 resulting executable to be covered by the GNU General Public License.
23 This exception does not however invalidate any other reasons why the
24 executable file might be covered by the GNU General Public License. */
25
26 package java.awt.image;
27
28 import gnu.java.awt.Buffers;
29
30 /* FIXME: This class does not yet support data type TYPE_SHORT */
31
32 /**
33  * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
34  */
35 public class ComponentSampleModel extends SampleModel
36 {
37   protected int[] bandOffsets;
38   protected int[] bankIndices;
39   
40   // FIXME: Should we really shadow the numBands in the superclass?
41   //protected int numBands;
42   
43   /** Used when creating data buffers. */
44   protected int numBanks;
45
46   protected int scanlineStride;
47   
48   protected int pixelStride;
49   
50   private boolean tightPixelPacking = false;
51   
52   public ComponentSampleModel(int dataType,
53                               int w, int h,
54                               int pixelStride,
55                               int scanlineStride,
56                               int[] bandOffsets)
57   {
58     this(dataType, w, h, pixelStride, scanlineStride,
59          new int[bandOffsets.length], bandOffsets);
60   }
61     
62   public ComponentSampleModel(int dataType,
63                               int w, int h,
64                               int pixelStride,
65                               int scanlineStride,
66                               int[] bankIndices,
67                               int[] bandOffsets)
68   {
69     super(dataType, w, h, bandOffsets.length);
70     if ((pixelStride<0) || (scanlineStride<0) || 
71         (bandOffsets.length<1) ||
72         (bandOffsets.length != bankIndices.length))
73       throw new IllegalArgumentException();
74     
75     this.bandOffsets = bandOffsets;
76     this.bankIndices = bankIndices;
77
78     for (int b=0; b<bankIndices.length; b++)
79       this.numBanks = Math.max(this.numBanks, bankIndices[b]+1);
80
81     this.scanlineStride = scanlineStride;
82     this.pixelStride = pixelStride;
83
84     // See if we can use some speedups
85
86     /* FIXME: May these checks should be reserved for the
87        PixelInterleavedSampleModel? */
88         
89     if (pixelStride == numBands)
90       {
91         tightPixelPacking = true;
92         for (int b=0; b<numBands; b++) {
93           if ((bandOffsets[b] != b) || (bankIndices[b] !=0))
94             {
95               tightPixelPacking = false;
96               break;
97             }
98         }
99       }
100   }             
101
102   public SampleModel createCompatibleSampleModel(int w, int h)
103   {
104     return new ComponentSampleModel(dataType, w, h, pixelStride,
105                                     scanlineStride, bankIndices,
106                                     bandOffsets);
107   }
108
109   public SampleModel createSubsetSampleModel(int[] bands)
110   {
111     int numBands = bands.length;
112     
113     int[] bankIndices = new int[numBands];
114     int[] bandOffsets = new int[numBands];
115     for (int b=0; b<numBands; b++)
116       {
117         bankIndices[b] = this.bankIndices[bands[b]];
118         bandOffsets[b] = this.bandOffsets[bands[b]];
119       }
120
121     return new ComponentSampleModel(dataType, width, height, pixelStride,
122                                     scanlineStride, bankIndices,
123                                     bandOffsets);
124   }
125
126   public DataBuffer createDataBuffer()
127   {
128     // Maybe this value should be precalculated in the constructor?
129     int highestOffset = 0;
130     for (int b=0; b<numBands; b++)
131       {
132         highestOffset = Math.max(highestOffset, bandOffsets[b]);
133       }
134     int size = pixelStride*(width-1) + scanlineStride*(height-1) +
135       highestOffset + 1;
136     
137     return Buffers.createBuffer(getDataType(), size, numBanks);
138   }
139
140   public int getOffset(int x, int y)
141   {
142     return getOffset(x, y, 0);
143   }
144
145   public int getOffset(int x, int y, int b)
146   {
147     return bandOffsets[b] + pixelStride*x + scanlineStride*y;
148   }
149
150   public final int[] getSampleSize()
151   {
152     int size = DataBuffer.getDataTypeSize(getDataType());
153     int[] sizes = new int[numBands];
154
155     java.util.Arrays.fill(sizes, size);
156     return sizes;
157   }
158
159   public final int getSampleSize(int band)
160   {
161     return DataBuffer.getDataTypeSize(getDataType());
162   }
163
164   public final int[] getBankIndices()
165   {
166     return bankIndices;
167   }
168
169   public final int[] getBandOffsets()
170   {
171     return bandOffsets;
172   }
173
174   public final int getScanlineStride()
175   {
176     return scanlineStride;
177   }
178
179   public final int getPixelStride()
180   {
181     return pixelStride;
182   }
183
184   public final int getNumDataElements()
185   {
186     return numBands;
187   }
188
189   public Object getDataElements(int x, int y, Object obj, DataBuffer data)
190   {
191     int xyOffset = pixelStride*x + scanlineStride*y;
192     
193     int[] totalBandDataOffsets = new int[numBands];
194     
195     /* Notice that band and bank offsets are different. Band offsets
196        are managed by the sample model, and bank offsets are managed
197        by the data buffer. Both must be accounted for. */
198     
199     /* FIXME: For single pixels, it is probably easier to simple
200        call getElem instead of calculating the bank offset ourself.
201        
202        On the other hand, then we need to push the value through
203        the int type returned by the getElem method.  */
204     
205     int[] bankOffsets = data.getOffsets();
206     
207     for (int b=0; b<numBands; b++)
208       {
209         totalBandDataOffsets[b] = 
210           bandOffsets[b]+bankOffsets[bankIndices[b]] + xyOffset;
211       }
212         
213     try
214       {
215         switch (getTransferType())
216           {
217           case DataBuffer.TYPE_BYTE:
218             DataBufferByte inByte = (DataBufferByte) data;
219             byte[] outByte = (byte[]) obj;
220             if (outByte == null) outByte = new byte[numBands];
221                 
222             for (int b=0; b<numBands; b++)
223               {
224                 int dOffset = totalBandDataOffsets[b];
225                 outByte[b] = inByte.getData(bankIndices[b])[dOffset];
226               }
227             return outByte;
228                 
229           case DataBuffer.TYPE_USHORT:
230             DataBufferUShort inUShort = (DataBufferUShort) data;
231             short[] outUShort = (short[]) obj;
232             if (outUShort == null) outUShort = new short[numBands];
233                 
234             for (int b=0; b<numBands; b++)
235               {
236                 int dOffset = totalBandDataOffsets[b];
237                 outUShort[b] = inUShort.getData(bankIndices[b])[dOffset];
238               }
239             return outUShort;
240
241           case DataBuffer.TYPE_INT:
242             DataBufferInt inInt = (DataBufferInt) data;
243             int[] outInt = (int[]) obj;
244             if (outInt == null) outInt = new int[numBands];
245                 
246             for (int b=0; b<numBands; b++)
247               {
248                 int dOffset = totalBandDataOffsets[b];
249                 outInt[b] = inInt.getData(bankIndices[b])[dOffset];
250               }
251             return outInt;
252                 
253             // FIXME: Fill in the other possible types.
254           default:
255               throw new IllegalStateException("unknown transfer type " +
256                                               getTransferType());
257           }
258       }
259     catch (ArrayIndexOutOfBoundsException aioobe)
260       {
261         String msg = "While reading data elements, " +
262           "x=" + x + ", y=" + y +", " + ", xyOffset=" + xyOffset +
263           ", data.getSize()=" + data.getSize() + ": " + aioobe;
264         throw new ArrayIndexOutOfBoundsException(msg);
265       }
266   }
267
268   public Object getDataElements(int x, int y, int w, int h, Object obj,
269                                 DataBuffer data)
270   {
271     if (!tightPixelPacking)
272       {
273         return super.getDataElements(x, y, w, h, obj, data);
274       }
275
276     // using get speedup
277     
278     // We can copy whole rows
279     int rowSize = w*numBands;
280     int dataSize = rowSize*h;
281     
282     DataBuffer transferBuffer =
283       Buffers.createBuffer(getTransferType(), obj, dataSize);
284     obj = Buffers.getData(transferBuffer);
285
286     int inOffset =
287       pixelStride*x +
288       scanlineStride*y +
289       data.getOffset(); // Assumes only one band is used
290
291     /* We don't add band offsets since we assume that bands have
292        offsets 0, 1, 2, ... */
293
294     // See if we can copy everything in one go
295     if (scanlineStride == rowSize)
296       {
297         // Collapse scan lines:
298         rowSize *= h;
299         // We ignore scanlineStride since it won't be of any use
300         h = 1;
301       }
302
303     int outOffset = 0;
304     Object inArray = Buffers.getData(data);
305     for (int yd = 0; yd<h; yd++)
306       {
307         System.arraycopy(inArray, inOffset, obj, outOffset, rowSize);
308         inOffset  += scanlineStride;
309         outOffset += rowSize;
310       }
311     return obj;
312   }
313
314   public void setDataElements(int x, int y, int w, int h,
315                               Object obj, DataBuffer data)
316   {
317     if (!tightPixelPacking)
318       {
319         super.setDataElements(x, y, w, h, obj, data);
320         return;
321       }
322
323     // using set speedup, we can copy whole rows
324     int rowSize = w*numBands;
325     int dataSize = rowSize*h;
326     
327     DataBuffer transferBuffer =
328       Buffers.createBufferFromData(getTransferType(), obj, dataSize);
329
330     int[] bankOffsets = data.getOffsets();
331
332     int outOffset =
333       pixelStride*x +
334       scanlineStride*y +
335       bankOffsets[0]; // same assuptions as in get...
336
337     // See if we can copy everything in one go
338     if (scanlineStride == rowSize)
339       {
340         // Collapse scan lines:
341         scanlineStride = rowSize *= h;
342         h = 1;
343       }
344
345     int inOffset = 0;
346     Object outArray = Buffers.getData(data);
347     for (int yd = 0; yd<h; yd++)
348       {
349         System.arraycopy(obj, inOffset, outArray, outOffset, rowSize);
350         outOffset += scanlineStride;
351         inOffset  += rowSize;
352       }
353   }
354
355   public int[] getPixel(int x, int y, int[] iArray, DataBuffer data)
356   {
357     int offset = pixelStride*x + scanlineStride*y;
358     if (iArray == null) iArray = new int[numBands];
359     for (int b=0; b<numBands; b++)
360       {
361         iArray[b] = data.getElem(bankIndices[b], offset+bandOffsets[b]);
362       }
363     return iArray;
364   }
365
366   public int[] getPixels(int x, int y, int w, int h, int[] iArray,
367                          DataBuffer data)
368   {
369     int offset = pixelStride*x + scanlineStride*y;
370     if (iArray == null) iArray = new int[numBands*w*h];
371     int outOffset = 0;
372     for (y=0; y<h; y++)
373       {
374         int lineOffset = offset;
375         for (x=0; x<w; x++)
376           {
377             for (int b=0; b<numBands; b++)
378               {
379                 iArray[outOffset++] = 
380                   data.getElem(bankIndices[b], lineOffset+bandOffsets[b]);
381               }
382             lineOffset += pixelStride;
383           }
384         offset += scanlineStride;
385       }
386     return iArray;
387   }
388     
389   public int getSample(int x, int y, int b, DataBuffer data)
390   {
391     return data.getElem(bankIndices[b], getOffset(x, y, b));
392   }
393
394   public void setDataElements(int x, int y, Object obj, DataBuffer data)
395   {
396     int offset = pixelStride*x + scanlineStride*y;
397     int[] totalBandDataOffsets = new int[numBands];
398     int[] bankOffsets = data.getOffsets();
399     for (int b=0; b<numBands; b++)
400       totalBandDataOffsets[b] =
401         bandOffsets[b]+bankOffsets[bankIndices[b]] + offset;
402
403     switch (getTransferType())
404       {
405       case DataBuffer.TYPE_BYTE:
406         {
407           DataBufferByte out = (DataBufferByte) data;
408           byte[] in = (byte[]) obj;
409           
410           for (int b=0; b<numBands; b++)
411             out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
412           
413           return;
414         }
415       case DataBuffer.TYPE_USHORT:
416         {
417           DataBufferUShort out = (DataBufferUShort) data;
418           short[] in = (short[]) obj;
419           
420           for (int b=0; b<numBands; b++)
421             out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
422           
423           return;
424         }
425       case DataBuffer.TYPE_INT:
426         {
427           DataBufferInt out = (DataBufferInt) data;
428           int[] in = (int[]) obj;
429           
430           for (int b=0; b<numBands; b++)
431             out.getData(bankIndices[b])[totalBandDataOffsets[b]] = in[b];
432           
433           return;
434         }
435       default:
436         throw new UnsupportedOperationException("transfer type not " +
437                                                 "implemented");
438       }
439   }
440   
441   public void setPixel(int x, int y, int[] iArray, DataBuffer data)
442   {
443     int offset = pixelStride*x + scanlineStride*y;
444     for (int b=0; b<numBands; b++)
445       data.setElem(bankIndices[b], offset+bandOffsets[b], iArray[b]);
446   }
447     
448   public void setSample(int x, int y, int b, int s, DataBuffer data)
449   {
450     data.setElem(bankIndices[b], getOffset(x, y, b), s);
451   }
452 }