1 /*
2  * $RCSfile: LookupTableJAI.java,v $
3  *
4  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
5  *
6  * Use is subject to license terms.
7  *
8  * $Revision: 1.1 $
9  * $Date: 2005/02/11 04:57:12 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.mediax.jai;
13 import java.awt.Rectangle;
14 import java.awt.Point;
15 import java.awt.image.DataBuffer;
16 import java.awt.image.DataBufferByte;
17 import java.awt.image.DataBufferInt;
18 import java.awt.image.DataBufferShort;
19 import java.awt.image.DataBufferUShort;
20 import java.awt.image.Raster;
21 import java.awt.image.SampleModel;
22 import java.awt.image.WritableRaster;
23 import java.io.IOException;
24 import java.io.ObjectInputStream;
25 import java.io.ObjectOutputStream;
26 import java.io.Serializable;
27 import com.lightcrafts.mediax.jai.remote.SerializableState;
28 import com.lightcrafts.mediax.jai.remote.SerializerFactory;
29 import com.lightcrafts.media.jai.util.DataBufferUtils;
30 
31 /**
32  * A lookup table object associated with the "Lookup" operation.  The
33  * "Lookup" operation is described in
34  * <code>com.lightcrafts.mediax.jai.operator.LookupDescriptor</code>.
35  *
36  * <p>This object represents a single- or multi-banded table of any
37  * JAI supported data type. A single- or multi-banded source image
38  * of integral data types is passed through the table and transformed
39  * into a single- or multi-banded destination image of either integral
40  * and floating point data types.
41  *
42  * <p>The table data may cover only a subrange of the legal range of the
43  * input data type. The subrange is selected by means of an offset parameter
44  * which is to be subtracted from the input value before indexing into the
45  * table array. When only a subranged table is used with a source image, it
46  * is up to the user to make certain that the source image does not have
47  * pixel values outside of the table range. Otherwise,
48  * an ArrayIndexOutOfBoundsException can occur.
49  *
50  * <p>The table data is saved by reference only.
51  *
52  * @see com.lightcrafts.mediax.jai.operator.LookupDescriptor
53  *
54  */
55 public class LookupTableJAI extends Object implements Serializable {
56 
57     /** The table data. */
58     transient DataBuffer data;
59 
60     /** The band offset values */
61     private int[] tableOffsets;
62 
63     /**
64      * Constructs a single-banded byte lookup table. The index offset is 0.
65      *
66      * @param data  The single-banded byte data.
67      * @throws IllegalArgumentException if data is null.
68      */
LookupTableJAI(byte[] data)69     public LookupTableJAI(byte[] data) {
70         if ( data == null ) {
71             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
72         }
73 
74         this.data = new DataBufferByte(data, data.length);
75         this.initOffsets(1, 0);
76     }
77 
78     /**
79      * Constructs a single-banded byte lookup table with an index offset.
80      *
81      * @param data    The single-banded byte data.
82      * @param offset  The offset.
83      * @throws IllegalArgumentException if data is null.
84      */
LookupTableJAI(byte[] data, int offset)85     public LookupTableJAI(byte[] data, int offset) {
86         if ( data == null ) {
87             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
88         }
89 
90         this.initOffsets(1, offset);
91         this.data = new DataBufferByte(data, data.length);
92     }
93 
94     /**
95      * Constructs a multi-banded byte lookup table. The index offset for
96      * each band is 0.
97      *
98      * @param data  The multi-banded byte data in [band][index] format.
99      * @throws IllegalArgumentException if data is null.
100      */
LookupTableJAI(byte[][] data)101     public LookupTableJAI(byte[][] data) {
102         if ( data == null ) {
103             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
104         }
105 
106         this.initOffsets(data.length, 0);
107         this.data = new DataBufferByte(data, data[0].length);
108     }
109 
110     /**
111      * Constructs a multi-banded byte lookup table where all bands have
112      * the same index offset.
113      *
114      * @param data    The multi-banded byte data in [band][index] format.
115      * @param offset  The common offset for all bands.
116      * @throws IllegalArgumentException if data is null.
117      */
LookupTableJAI(byte[][] data, int offset)118     public LookupTableJAI(byte[][] data, int offset) {
119         if ( data == null ) {
120             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
121         }
122 
123         this.initOffsets(data.length, offset);
124         this.data = new DataBufferByte(data, data[0].length);
125     }
126 
127     /**
128      * Constructs a multi-banded byte lookup table where each band has
129      * a different index offset.
130      *
131      * @param data     The multi-banded byte data in [band][index] format.
132      * @param offsets  The offsets for the bands.
133      * @throws IllegalArgumentException if data is null.
134      */
LookupTableJAI(byte[][] data, int[] offsets)135     public LookupTableJAI(byte[][] data, int[] offsets) {
136         if ( data == null ) {
137             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
138         }
139 
140         this.initOffsets(data.length, offsets);
141         this.data = new DataBufferByte(data, data[0].length);
142     }
143 
144     /**
145      * Constructs a single-banded short or unsigned short lookup table.
146      * The index offset is 0.
147      *
148      * @param data      The single-banded short data.
149      * @param isUShort  True if data type is DataBuffer.TYPE_USHORT;
150      *                  false if data type is DataBuffer.TYPE_SHORT.
151      * @throws IllegalArgumentException if data is null.
152      */
LookupTableJAI(short[] data, boolean isUShort)153     public LookupTableJAI(short[] data, boolean isUShort) {
154         if ( data == null ) {
155             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
156         }
157 
158         this.initOffsets(1, 0);
159         if (isUShort) {
160             this.data = new DataBufferUShort(data, data.length);
161         } else {
162             this.data = new DataBufferShort(data, data.length);
163         }
164     }
165 
166     /**
167      * Constructs a single-banded short or unsigned short lookup table with
168      * an index offset.
169      *
170      * @param data      The single-banded short data.
171      * @param offset    The offset.
172      * @param isUShort  True if data type is DataBuffer.TYPE_USHORT;
173      *                  false if data type is DataBuffer.TYPE_SHORT.
174      * @throws IllegalArgumentException if data is null.
175      */
LookupTableJAI(short[] data, int offset, boolean isUShort)176     public LookupTableJAI(short[] data, int offset, boolean isUShort) {
177         if ( data == null ) {
178             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
179         }
180 
181         this.initOffsets(1, offset);
182         if (isUShort) {
183             this.data = new DataBufferUShort(data, data.length);
184         } else {
185             this.data = new DataBufferShort(data, data.length);
186         }
187     }
188 
189     /**
190      * Constructs a multi-banded short or unsigned short lookup table.
191      * The index offset for each band is 0.
192      *
193      * @param data      The multi-banded short data in [band][index] format.
194      * @param isUShort  True if data type is DataBuffer.TYPE_USHORT;
195      *                  false if data type is DataBuffer.TYPE_SHORT.
196      * @throws IllegalArgumentException if data is null.
197      */
LookupTableJAI(short[][] data, boolean isUShort)198     public LookupTableJAI(short[][] data, boolean isUShort) {
199         if ( data == null ) {
200             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
201         }
202 
203         this.initOffsets(data.length, 0);
204         if (isUShort) {
205             this.data = new DataBufferUShort(data, data[0].length);
206         } else {
207             this.data = new DataBufferShort(data, data[0].length);
208         }
209     }
210 
211     /**
212      * Constructs a multi-banded short or unsigned short lookup table where all
213      * bands have the same index offset.
214      *
215      * @param data      The multi-banded short data in [band][index] format.
216      * @param offset    The common offset for all bands.
217      * @param isUShort  True if data type is DataBuffer.TYPE_USHORT;
218      *                  false if data type is DataBuffer.TYPE_SHORT.
219      * @throws IllegalArgumentException if data is null.
220      */
LookupTableJAI(short[][] data, int offset, boolean isUShort)221     public LookupTableJAI(short[][] data, int offset, boolean isUShort) {
222         if ( data == null ) {
223             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
224         }
225 
226         this.initOffsets(data.length, offset);
227         if (isUShort) {
228             this.data = new DataBufferUShort(data, data[0].length);
229         } else {
230             this.data = new DataBufferShort(data, data[0].length);
231         }
232     }
233 
234     /**
235      * Constructs a multi-banded short or unsigned short lookup table where
236      * each band has a different index offset.
237      *
238      * @param data      The multi-banded short data in [band][index] format.
239      * @param offsets   The offsets for the bands.
240      * @param isUShort  True if data type is DataBuffer.TYPE_USHORT;
241      *                  false if data type is DataBuffer.TYPE_SHORT.
242      * @throws IllegalArgumentException if data is null.
243      */
LookupTableJAI(short[][] data, int[] offsets, boolean isUShort)244     public LookupTableJAI(short[][] data, int[] offsets, boolean isUShort) {
245         if ( data == null ) {
246             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
247         }
248 
249         this.initOffsets(data.length, offsets);
250 
251         if (isUShort) {
252             this.data = new DataBufferUShort(data, data[0].length);
253         } else {
254             this.data = new DataBufferShort(data, data[0].length);
255         }
256     }
257 
258     /**
259      * Constructs a single-banded int lookup table. The index offset is 0.
260      *
261      * @param data  The single-banded int data.
262      * @throws IllegalArgumentException if data is null.
263      */
LookupTableJAI(int[] data)264     public LookupTableJAI(int[] data) {
265         if ( data == null ) {
266             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
267         }
268 
269         this.initOffsets(1, 0);
270         this.data = new DataBufferInt(data, data.length);
271     }
272 
273     /**
274      * Constructs a single-banded int lookup table with an index offset.
275      *
276      * @param data    The single-banded int data.
277      * @param offset  The offset.
278      * @throws IllegalArgumentException if data is null.
279      */
LookupTableJAI(int[] data, int offset)280     public LookupTableJAI(int[] data, int offset) {
281         if ( data == null ) {
282             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
283         }
284 
285         this.initOffsets(1, offset);
286         this.data = new DataBufferInt(data, data.length);
287     }
288 
289     /**
290      * Constructs a multi-banded int lookup table. The index offset for
291      * each band is 0.
292      *
293      * @param data  The multi-banded int data in [band][index] format.
294      * @throws IllegalArgumentException if data is null.
295      */
LookupTableJAI(int[][] data)296     public LookupTableJAI(int[][] data) {
297         if ( data == null ) {
298             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
299         }
300 
301         this.initOffsets(data.length, 0);
302         this.data = new DataBufferInt(data, data[0].length);
303     }
304 
305     /**
306      * Constructs a multi-banded int lookup table where all bands have
307      * the same index offset.
308      *
309      * @param data    The multi-banded int data in [band][index] format.
310      * @param offset  The common offset for all bands.
311      * @throws IllegalArgumentException if data is null.
312      */
LookupTableJAI(int[][] data, int offset)313     public LookupTableJAI(int[][] data, int offset) {
314         if ( data == null ) {
315             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
316         }
317 
318         this.initOffsets(data.length, offset);
319         this.data = new DataBufferInt(data, data[0].length);
320     }
321 
322     /**
323      * Constructs a multi-banded int lookup table where each band has
324      * a different index offset.
325      *
326      * @param data     The multi-banded int data in [band][index] format.
327      * @param offsets  The offsets for the bands.
328      * @throws IllegalArgumentException if data is null.
329      */
LookupTableJAI(int[][] data, int[] offsets)330     public LookupTableJAI(int[][] data, int[] offsets) {
331         if ( data == null ) {
332             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
333         }
334 
335         this.initOffsets(data.length, offsets);
336         this.data = new DataBufferInt(data, data[0].length);
337     }
338 
339     /**
340      * Constructs a single-banded float lookup table. The index offset is 0.
341      *
342      * @param data  The single-banded float data.
343      * @throws IllegalArgumentException if data is null.
344      */
LookupTableJAI(float[] data)345     public LookupTableJAI(float[] data) {
346         if ( data == null ) {
347             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
348         }
349 
350         this.initOffsets(1, 0);
351         this.data = DataBufferUtils.createDataBufferFloat(data, data.length);
352     }
353 
354     /**
355      * Constructs a single-banded float lookup table with an index offset.
356      *
357      * @param data    The single-banded float data.
358      * @param offset  The offset.
359      * @throws IllegalArgumentException if data is null.
360      */
LookupTableJAI(float[] data, int offset)361     public LookupTableJAI(float[] data, int offset) {
362         if ( data == null ) {
363             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
364         }
365 
366         this.initOffsets(1, offset);
367         this.data = DataBufferUtils.createDataBufferFloat(data, data.length);
368     }
369 
370     /**
371      * Constructs a multi-banded float lookup table. The index offset for
372      * each band is 0.
373      *
374      * @param data  The multi-banded float data in [band][index] format.
375      * @throws IllegalArgumentException if data is null.
376      */
LookupTableJAI(float[][] data)377     public LookupTableJAI(float[][] data) {
378         if ( data == null ) {
379             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
380         }
381 
382         this.initOffsets(data.length, 0);
383         this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length);
384     }
385 
386     /**
387      * Constructs a multi-banded float lookup table where all bands have
388      * the same index offset.
389      *
390      * @param data    The multi-banded float data in [band][index] format.
391      * @param offset  The common offset for all bands.
392      * @throws IllegalArgumentException if data is null.
393      */
LookupTableJAI(float[][] data, int offset)394     public LookupTableJAI(float[][] data, int offset) {
395         if ( data == null ) {
396             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
397         }
398 
399         this.initOffsets(data.length, offset);
400         this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length);
401     }
402 
403     /**
404      * Constructs a multi-banded float lookup table where each band has
405      * a different index offset.
406      *
407      * @param data     The multi-banded float data in [band][index] format.
408      * @param offsets  The offsets for the bands.
409      * @throws IllegalArgumentException if data is null.
410      */
LookupTableJAI(float[][] data, int[] offsets)411     public LookupTableJAI(float[][] data, int[] offsets) {
412         if ( data == null ) {
413             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
414         }
415 
416         this.initOffsets(data.length, offsets);
417         this.data = DataBufferUtils.createDataBufferFloat(data, data[0].length);
418     }
419 
420     /**
421      * Constructs a single-banded double lookup table. The index offset is 0.
422      *
423      * @param data  The single-banded double data.
424      * @throws IllegalArgumentException if data is null.
425      */
LookupTableJAI(double[] data)426     public LookupTableJAI(double[] data) {
427         if ( data == null ) {
428             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
429         }
430 
431         this.initOffsets(1, 0);
432         this.data = DataBufferUtils.createDataBufferDouble(data, data.length);
433     }
434 
435     /**
436      * Constructs a single-banded double lookup table with an index offset.
437      *
438      * @param data    The single-banded double data.
439      * @param offset  The offset.
440      * @throws IllegalArgumentException if data is null.
441      */
LookupTableJAI(double[] data, int offset)442     public LookupTableJAI(double[] data, int offset) {
443         if ( data == null ) {
444             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
445         }
446 
447         this.initOffsets(1, offset);
448         this.data = DataBufferUtils.createDataBufferDouble(data, data.length);
449     }
450 
451     /**
452      * Constructs a multi-banded double lookup table. The index offset for
453      * each band is 0.
454      *
455      * @param data  The multi-banded double data in [band][index] format.
456      * @throws IllegalArgumentException if data is null.
457      */
LookupTableJAI(double[][] data)458     public LookupTableJAI(double[][] data) {
459         if ( data == null ) {
460             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
461         }
462 
463         this.initOffsets(data.length, 0);
464         this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length);
465     }
466 
467     /**
468      * Constructs a multi-banded double lookup table where all bands have
469      * the same index offset.
470      *
471      * @param data    The multi-banded double data in [band][index] format.
472      * @param offset  The common offset for all bands.
473      * @throws IllegalArgumentException if data is null.
474      */
LookupTableJAI(double[][] data, int offset)475     public LookupTableJAI(double[][] data, int offset) {
476         if ( data == null ) {
477             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
478         }
479 
480         this.initOffsets(data.length, offset);
481         this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length);
482     }
483 
484     /**
485      * Constructs a multi-banded double lookup table where each band has
486      * a different index offset.
487      *
488      * @param data     The multi-banded double data in [band][index] format.
489      * @param offsets  The offsets for the bands.
490      * @throws IllegalArgumentException if data is null.
491      */
LookupTableJAI(double[][] data, int[] offsets)492     public LookupTableJAI(double[][] data, int[] offsets) {
493         if ( data == null ) {
494             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
495         }
496 
497         this.initOffsets(data.length, offsets);
498         this.data = DataBufferUtils.createDataBufferDouble(data, data[0].length);
499     }
500 
501     /**
502      * Returns the table data as a DataBuffer.
503      */
getData()504     public DataBuffer getData() {
505         return data;
506     }
507 
508     /**
509      * Returns the byte table data in array format, or null if the
510      * table's data type is not byte.
511      */
getByteData()512     public byte[][] getByteData() {
513         return data instanceof DataBufferByte ?
514                ((DataBufferByte)data).getBankData() : null;
515     }
516 
517     /**
518      * Returns the byte table data of a specific band in array format,
519      * or null if the table's data type is not byte.
520      */
getByteData(int band)521     public byte[] getByteData(int band) {
522         return data instanceof DataBufferByte ?
523                ((DataBufferByte)data).getData(band) : null;
524     }
525 
526     /**
527      * Returns the short table data in array format, or null if the
528      * table's data type is not short. This includes both signed and
529      * unsigned short table data.
530      *
531      */
getShortData()532     public short[][] getShortData() {
533         if (data instanceof DataBufferUShort) {
534             return ((DataBufferUShort)data).getBankData();
535         } else if (data instanceof DataBufferShort) {
536             return ((DataBufferShort)data).getBankData();
537         } else {
538             return null;
539         }
540     }
541 
542     /**
543      * Returns the short table data of a specific band in array format,
544      * or null if the table's data type is not short.
545      *
546      */
getShortData(int band)547     public short[] getShortData(int band) {
548         if (data instanceof DataBufferUShort) {
549             return ((DataBufferUShort)data).getData(band);
550         } else if (data instanceof DataBufferShort) {
551             return ((DataBufferShort)data).getData(band);
552         } else {
553             return null;
554         }
555     }
556 
557     /**
558      * Returns the integer table data in array format, or null if the
559      * table's data type is not int.
560      *
561      */
getIntData()562     public int[][] getIntData() {
563         return data instanceof DataBufferInt ?
564                ((DataBufferInt)data).getBankData() : null;
565     }
566 
567     /**
568      * Returns the integer table data of a specific band in array format,
569      * or null if table's data type is not int.
570      *
571      */
getIntData(int band)572     public int[] getIntData(int band) {
573         return data instanceof DataBufferInt ?
574                ((DataBufferInt)data).getData(band) : null;
575     }
576 
577     /**
578      * Returns the float table data in array format, or null if the
579      * table's data type is not float.
580      *
581      */
getFloatData()582     public float[][] getFloatData() {
583         return data.getDataType() == DataBuffer.TYPE_FLOAT ?
584                DataBufferUtils.getBankDataFloat(data) : null;
585     }
586 
587     /**
588      * Returns the float table data of a specific band in array format,
589      * or null if table's data type is not float.
590      *
591      */
getFloatData(int band)592     public float[] getFloatData(int band) {
593         return data.getDataType() == DataBuffer.TYPE_FLOAT ?
594                DataBufferUtils.getDataFloat(data, band) : null;
595     }
596 
597     /**
598      * Returns the double table data in array format, or null if the
599      * table's data type is not double.
600      *
601      */
getDoubleData()602     public double[][] getDoubleData() {
603         return data.getDataType() == DataBuffer.TYPE_DOUBLE ?
604                DataBufferUtils.getBankDataDouble(data) : null;
605     }
606 
607     /**
608      * Returns the double table data of a specific band in array format,
609      * or null if table's data type is not double.
610      *
611      */
getDoubleData(int band)612     public double[] getDoubleData(int band) {
613         return data.getDataType() == DataBuffer.TYPE_DOUBLE ?
614                DataBufferUtils.getDataDouble(data, band) : null;
615     }
616 
617     /** Returns the index offsets of entry 0 for all bands. */
getOffsets()618     public int[] getOffsets() {
619         return tableOffsets;
620     }
621 
622     /**
623      * Returns the index offset of entry 0 for the default band.
624      *
625      */
getOffset()626     public int getOffset() {
627         return tableOffsets[0];
628     }
629 
630     /**
631      * Returns the index offset of entry 0 for a specific band.
632      *
633      */
getOffset(int band)634     public int getOffset(int band) {
635         return tableOffsets[band];
636     }
637 
638     /** Returns the number of bands of the table. */
getNumBands()639     public int getNumBands() {
640         return data.getNumBanks();
641     }
642 
643     /**
644      * Returns the number of entries per band of the table.
645      *
646      */
getNumEntries()647     public int getNumEntries() {
648         return data.getSize();
649     }
650 
651     /** Returns the data type of the table data.
652      *
653      */
getDataType()654     public int getDataType() {
655         return data.getDataType();
656     }
657 
658     /**
659      * Returns the number of bands of the destination image, based on
660      * the number of bands of the source image and lookup table.
661      *
662      * @param srcNumBands  The number of bands of the source image.
663      * @return the number of bands in destination image.
664      */
getDestNumBands(int srcNumBands)665     public int getDestNumBands(int srcNumBands) {
666         int tblNumBands = getNumBands();
667         return srcNumBands == 1 ? tblNumBands : srcNumBands;
668     }
669 
670     /**
671      * Returns a <code>SampleModel</code> suitable for holding the output
672      * of a lookup operation on the source data described by a given
673      * SampleModel with this table. The width and height of the destination
674      * SampleModel are the same as that of the source. This method will
675      * return null if the source SampleModel has a non-integral data type.
676      *
677      * @param srcSampleModel  The SampleModel of the source image.
678      *
679      * @throws IllegalArgumentException if srcSampleModel is null.
680      * @return sampleModel suitable for the destination image.
681      */
getDestSampleModel(SampleModel srcSampleModel)682     public SampleModel getDestSampleModel(SampleModel srcSampleModel) {
683         if ( srcSampleModel == null ) {
684             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
685         }
686 
687         return getDestSampleModel(srcSampleModel,
688                                   srcSampleModel.getWidth(),
689                                   srcSampleModel.getHeight());
690     }
691 
692     /**
693      * Returns a <code>SampleModel</code> suitable for holding the output
694      * of a lookup operation on the source data described by a given
695      * SampleModel with this table. This method will return null if the
696      * source SampleModel has a non-integral data type.
697      *
698      * @param srcSampleModel  The SampleModel of the source image.
699      * @param width           The width of the destination SampleModel.
700      * @param height          The height of the destination SampleModel.
701      *
702      * @throws IllegalArgumentException if srcSampleModel is null.
703      * @return sampleModel suitable for the destination image.
704      */
getDestSampleModel(SampleModel srcSampleModel, int width, int height)705     public SampleModel getDestSampleModel(SampleModel srcSampleModel,
706                                           int width,
707                                           int height) {
708         if ( srcSampleModel == null ) {
709             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
710         }
711 
712         if (!isIntegralDataType(srcSampleModel)) {
713             return null;	// source has non-integral data type
714         }
715 
716         return RasterFactory.createComponentSampleModel(srcSampleModel,
717                        getDataType(), width, height,
718                        getDestNumBands(srcSampleModel.getNumBands()));
719     }
720 
721     /**
722      * Validates data type. Returns true if it's one of the integral
723      * data types; false otherwise.
724      *
725      * @throws IllegalArgumentException if sampleModel is null.
726      */
isIntegralDataType(SampleModel sampleModel)727     public boolean isIntegralDataType(SampleModel sampleModel) {
728         if ( sampleModel == null ) {
729             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
730         }
731 
732         return isIntegralDataType(sampleModel.getTransferType());
733     }
734 
735     /**
736      * Returns <code>true</code> if the specified data type is
737      * an integral data type, such as byte, ushort, short, or int.
738      */
isIntegralDataType(int dataType)739     public boolean isIntegralDataType(int dataType) {
740         if ((dataType == DataBuffer.TYPE_BYTE) ||
741             (dataType == DataBuffer.TYPE_USHORT) ||
742             (dataType == DataBuffer.TYPE_SHORT) ||
743             (dataType == DataBuffer.TYPE_INT)){
744             return true;
745         } else {
746             return false;
747         }
748     }
749 
750     /**
751      * Performs lookup on a given value belonging to a given source
752      * band, and returns the result as an int.
753      *
754      * @param band   The source band the value is from.
755      * @param value  The source value to be placed through the lookup table.
756      */
lookup(int band, int value)757     public int lookup(int band, int value) {
758         return data.getElem(band, value-tableOffsets[band]);
759     }
760 
761     /**
762      * Performs lookup on a given value belonging to a given source
763      * band, and returns the result as a float.
764      *
765      * @param band   The source band the value is from.
766      * @param value  The source value to be placed through the lookup table.
767      */
lookupFloat(int band, int value)768     public float lookupFloat(int band, int value) {
769         return data.getElemFloat(band, value-tableOffsets[band]);
770     }
771 
772     /**
773      * Performs lookup on a given value belonging to a given source
774      * band, and returns the result as a double.
775      *
776      * @param band   The source band the value is from.
777      * @param value  The source value to be placed through the lookup table.
778      */
lookupDouble(int band, int value)779     public double lookupDouble(int band, int value) {
780         return data.getElemDouble(band, value-tableOffsets[band]);
781     }
782 
783     /**
784      * Performs table lookup in place on a given WritableRaster. The
785      * The lookup operation must preserve the data type and
786      * SampleModel of the source.  A reference to the supplied
787      * WritableRaster will be returned.
788      *
789      * @throws IllegalArgumentException if the src is null.
790      * @throws IllegalArgumentException if the source's SampleModel
791      *         is not of integral type.
792      * @throws IllegalArgumentException if the lookup operation would
793      *         result in a change in the data type or number of bands
794      *         of the Raster.
795      */
lookup(WritableRaster src)796     public WritableRaster lookup(WritableRaster src) {
797         if ( src == null ) {
798             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
799         }
800 
801         return lookup(src, src, src.getBounds());
802     }
803 
804     /**
805      * Performs table lookup on a source Raster, writing the result
806      * into a supplied WritableRaster. The destination must have a
807      * data type and SampleModel appropriate to the results of the
808      * lookup operation.  The table lookup operation is performed
809      * within a specified rectangle.
810      *
811      * <p> The <code>dst</code> argument may be null, in which case a new
812      * WritableRaster is created using the appropriate SampleModel.
813      *
814      * <p> The rectangle of interest may be null, in which case the
815      * operation will be performed on the intersection of the source
816      * and destination bounding rectangles.
817      *
818      * @param src   A Raster containing the source pixel data.
819      * @param dst   The WritableRaster to be computed, or null.
820      *              If supplied, its data type and number of bands must
821      *              be suitable for the source and lookup table.
822      * @param rect  The rectangle within the tile to be computed.
823      *              If rect is null, the intersection of the source and
824      *              destination bounds will be used.  Otherwise, it
825      *              will be clipped to the intersection of the source
826      *              and destination bounds.
827      * @return      A reference to the supplied WritableRaster, or to a
828      *              new WritableRaster if the supplied one was null.
829      *
830      * @throws IllegalArgumentException if the source is null.
831      * @throws IllegalArgumentException if the source's SampleModel
832      *         is not of integral type.
833      * @throws IllegalArgumentException if the destination's data type
834      *         or number of bands differ from those returned by
835      *         getDataType() and getDestNumBands().
836      */
lookup(Raster src, WritableRaster dst, Rectangle rect)837     public WritableRaster lookup(Raster src,
838                                  WritableRaster dst,
839                                  Rectangle rect) {
840         // Validate source.
841         if (src == null) {
842             throw
843 	      new IllegalArgumentException(JaiI18N.getString("LookupTableJAI1"));
844         }
845 
846         SampleModel srcSampleModel = src.getSampleModel();
847         if (!isIntegralDataType(srcSampleModel)) {
848             throw
849 	      new IllegalArgumentException(JaiI18N.getString("LookupTableJAI2"));
850         }
851 
852         // Validate rectangle.
853         if (rect == null) {
854             rect = src.getBounds();
855         } else {
856             rect = rect.intersection(src.getBounds());
857         }
858 
859         if (dst != null) {
860             rect = rect.intersection(dst.getBounds());
861         }
862 
863         // Validate destination.
864         SampleModel dstSampleModel;
865         if (dst == null) {	// create dst according to table
866             dstSampleModel = getDestSampleModel(srcSampleModel,
867                                                 rect.width, rect.height);
868             dst =
869                 RasterFactory.createWritableRaster(dstSampleModel,
870                                                    new Point(rect.x, rect.y));
871         } else {
872             dstSampleModel = dst.getSampleModel();
873 
874             if (dstSampleModel.getTransferType() != getDataType() ||
875                 dstSampleModel.getNumBands() !=
876                 getDestNumBands(srcSampleModel.getNumBands())) {
877                 throw new
878 		  IllegalArgumentException(JaiI18N.getString("LookupTableJAI3"));
879             }
880         }
881 
882 	// Add bit support?
883         int sTagID = RasterAccessor.findCompatibleTag(null, srcSampleModel);
884         int dTagID = RasterAccessor.findCompatibleTag(null, dstSampleModel);
885 
886         RasterFormatTag sTag = new RasterFormatTag(srcSampleModel,sTagID);
887         RasterFormatTag dTag = new RasterFormatTag(dstSampleModel,dTagID);
888 
889         RasterAccessor s = new RasterAccessor(src, rect, sTag, null);
890         RasterAccessor d = new RasterAccessor(dst, rect, dTag, null);
891 
892         int srcNumBands = s.getNumBands();
893         int srcDataType = s.getDataType();
894 
895         int tblNumBands = getNumBands();
896         int tblDataType = getDataType();
897 
898         int dstWidth = d.getWidth();
899         int dstHeight = d.getHeight();
900         int dstNumBands = d.getNumBands();
901         int dstDataType = d.getDataType();
902 
903         // Source information.
904         int srcLineStride = s.getScanlineStride();
905         int srcPixelStride = s.getPixelStride();
906         int[] srcBandOffsets = s.getBandOffsets();
907 
908         byte[][] bSrcData = s.getByteDataArrays();
909         short[][] sSrcData = s.getShortDataArrays();
910         int[][] iSrcData = s.getIntDataArrays();
911 
912         if (srcNumBands < dstNumBands) {
913             int offset0 = srcBandOffsets[0];
914             srcBandOffsets = new int[dstNumBands];
915             for (int i = 0; i < dstNumBands; i++) {
916                 srcBandOffsets[i] = offset0;
917             }
918 
919             switch (srcDataType) {
920             case DataBuffer.TYPE_BYTE:
921                 byte[] bData0 = bSrcData[0];
922                 bSrcData = new byte[dstNumBands][];
923                 for (int i = 0; i < dstNumBands; i++) {
924                     bSrcData[i] = bData0;
925                 }
926                 break;
927             case DataBuffer.TYPE_USHORT:
928             case DataBuffer.TYPE_SHORT:
929                 short[] sData0 = sSrcData[0];
930                 sSrcData = new short[dstNumBands][];
931                 for (int i = 0; i < dstNumBands; i++) {
932                     sSrcData[i] = sData0;
933                 }
934                 break;
935             case DataBuffer.TYPE_INT:
936                 int[] iData0 = iSrcData[0];
937                 iSrcData = new int[dstNumBands][];
938                 for (int i = 0; i < dstNumBands; i++) {
939                     iSrcData[i] = iData0;
940                 }
941                 break;
942             }
943         }
944 
945         // Table information.
946         int[] tblOffsets = getOffsets();
947 
948         byte[][] bTblData = getByteData();
949         short[][] sTblData = getShortData();
950         int[][] iTblData = getIntData();
951         float[][] fTblData = getFloatData();
952         double[][] dTblData = getDoubleData();
953 
954         if (tblNumBands < dstNumBands) {
955             int offset0 = tblOffsets[0];
956             tblOffsets = new int[dstNumBands];
957             for (int i = 0; i < dstNumBands; i++) {
958                 tblOffsets[i] = offset0;
959             }
960 
961             switch (tblDataType) {
962             case DataBuffer.TYPE_BYTE:
963                 byte[] bData0 = bTblData[0];
964                 bTblData = new byte[dstNumBands][];
965                 for (int i = 0; i < dstNumBands; i++) {
966                     bTblData[i] = bData0;
967                 }
968                 break;
969             case DataBuffer.TYPE_USHORT:
970             case DataBuffer.TYPE_SHORT:
971                 short[] sData0 = sTblData[0];
972                 sTblData = new short[dstNumBands][];
973                 for (int i = 0; i < dstNumBands; i++) {
974                     sTblData[i] = sData0;
975                 }
976                 break;
977             case DataBuffer.TYPE_INT:
978                 int[] iData0 = iTblData[0];
979                 iTblData = new int[dstNumBands][];
980                 for (int i = 0; i < dstNumBands; i++) {
981                     iTblData[i] = iData0;
982                 }
983                 break;
984             case DataBuffer.TYPE_FLOAT:
985                 float[] fData0 = fTblData[0];
986                 fTblData = new float[dstNumBands][];
987                 for (int i = 0; i < dstNumBands; i++) {
988                     fTblData[i] = fData0;
989                 }
990                 break;
991             case DataBuffer.TYPE_DOUBLE:
992                 double[] dData0 = dTblData[0];
993                 dTblData = new double[dstNumBands][];
994                 for (int i = 0; i < dstNumBands; i++) {
995                     dTblData[i] = dData0;
996                 }
997             }
998         }
999 
1000         // Destination information.
1001         int dstLineStride = d.getScanlineStride();
1002         int dstPixelStride = d.getPixelStride();
1003         int[] dstBandOffsets = d.getBandOffsets();
1004 
1005         byte[][] bDstData = d.getByteDataArrays();
1006         short[][] sDstData = d.getShortDataArrays();
1007         int[][] iDstData = d.getIntDataArrays();
1008         float[][] fDstData = d.getFloatDataArrays();
1009         double[][] dDstData = d.getDoubleDataArrays();
1010 
1011         switch (dstDataType) {
1012         case DataBuffer.TYPE_BYTE:
1013             switch (srcDataType) {
1014             case DataBuffer.TYPE_BYTE:
1015                 lookup(srcLineStride, srcPixelStride,
1016                        srcBandOffsets, bSrcData,
1017                        dstWidth, dstHeight, dstNumBands,
1018                        dstLineStride, dstPixelStride,
1019                        dstBandOffsets, bDstData,
1020                        tblOffsets, bTblData);
1021                 break;
1022 
1023             case DataBuffer.TYPE_USHORT:
1024                 lookupU(srcLineStride, srcPixelStride,
1025                         srcBandOffsets, sSrcData,
1026                         dstWidth, dstHeight, dstNumBands,
1027                         dstLineStride, dstPixelStride,
1028                         dstBandOffsets, bDstData,
1029                         tblOffsets, bTblData);
1030                 break;
1031 
1032             case DataBuffer.TYPE_SHORT:
1033                 lookup(srcLineStride, srcPixelStride,
1034                        srcBandOffsets, sSrcData,
1035                        dstWidth, dstHeight, dstNumBands,
1036                        dstLineStride, dstPixelStride,
1037                        dstBandOffsets, bDstData,
1038                        tblOffsets, bTblData);
1039                 break;
1040 
1041             case DataBuffer.TYPE_INT:
1042                 lookup(srcLineStride, srcPixelStride,
1043                        srcBandOffsets, iSrcData,
1044                        dstWidth, dstHeight, dstNumBands,
1045                        dstLineStride, dstPixelStride,
1046                        dstBandOffsets, bDstData,
1047                        tblOffsets, bTblData);
1048                 break;
1049             }
1050             break;
1051 
1052         case DataBuffer.TYPE_USHORT:
1053         case DataBuffer.TYPE_SHORT:
1054             switch (srcDataType) {
1055             case DataBuffer.TYPE_BYTE:
1056                 lookup(srcLineStride, srcPixelStride,
1057                        srcBandOffsets, bSrcData,
1058                        dstWidth, dstHeight, dstNumBands,
1059                        dstLineStride, dstPixelStride,
1060                        dstBandOffsets, sDstData,
1061                        tblOffsets, sTblData);
1062                 break;
1063 
1064             case DataBuffer.TYPE_USHORT:
1065                 lookupU(srcLineStride, srcPixelStride,
1066                         srcBandOffsets, sSrcData,
1067                         dstWidth, dstHeight, dstNumBands,
1068                         dstLineStride, dstPixelStride,
1069                         dstBandOffsets, sDstData,
1070                         tblOffsets, sTblData);
1071                 break;
1072 
1073             case DataBuffer.TYPE_SHORT:
1074                 lookup(srcLineStride, srcPixelStride,
1075                        srcBandOffsets, sSrcData,
1076                        dstWidth, dstHeight, dstNumBands,
1077                        dstLineStride, dstPixelStride,
1078                        dstBandOffsets, sDstData,
1079                        tblOffsets, sTblData);
1080                 break;
1081 
1082             case DataBuffer.TYPE_INT:
1083                 lookup(srcLineStride, srcPixelStride,
1084                        srcBandOffsets, iSrcData,
1085                        dstWidth, dstHeight, dstNumBands,
1086                        dstLineStride, dstPixelStride,
1087                        dstBandOffsets, sDstData,
1088                        tblOffsets, sTblData);
1089                 break;
1090             }
1091             break;
1092 
1093         case DataBuffer.TYPE_INT:
1094             switch (srcDataType) {
1095             case DataBuffer.TYPE_BYTE:
1096                 lookup(srcLineStride, srcPixelStride,
1097                        srcBandOffsets, bSrcData,
1098                        dstWidth, dstHeight, dstNumBands,
1099                        dstLineStride, dstPixelStride,
1100                        dstBandOffsets, iDstData,
1101                        tblOffsets, iTblData);
1102                 break;
1103 
1104             case DataBuffer.TYPE_USHORT:
1105                 lookupU(srcLineStride, srcPixelStride,
1106                         srcBandOffsets, sSrcData,
1107                         dstWidth, dstHeight, dstNumBands,
1108                         dstLineStride, dstPixelStride,
1109                         dstBandOffsets, iDstData,
1110                         tblOffsets, iTblData);
1111                 break;
1112 
1113             case DataBuffer.TYPE_SHORT:
1114                 lookup(srcLineStride, srcPixelStride,
1115                        srcBandOffsets, sSrcData,
1116                        dstWidth, dstHeight, dstNumBands,
1117                        dstLineStride, dstPixelStride,
1118                        dstBandOffsets, iDstData,
1119                        tblOffsets, iTblData);
1120                 break;
1121 
1122             case DataBuffer.TYPE_INT:
1123                 lookup(srcLineStride, srcPixelStride,
1124                        srcBandOffsets, iSrcData,
1125                        dstWidth, dstHeight, dstNumBands,
1126                        dstLineStride, dstPixelStride,
1127                        dstBandOffsets, iDstData,
1128                        tblOffsets, iTblData);
1129                 break;
1130             }
1131             break;
1132 
1133         case DataBuffer.TYPE_FLOAT:
1134             switch (srcDataType) {
1135             case DataBuffer.TYPE_BYTE:
1136                 lookup(srcLineStride, srcPixelStride,
1137                        srcBandOffsets, bSrcData,
1138                        dstWidth, dstHeight, dstNumBands,
1139                        dstLineStride, dstPixelStride,
1140                        dstBandOffsets, fDstData,
1141                        tblOffsets, fTblData);
1142                 break;
1143 
1144             case DataBuffer.TYPE_USHORT:
1145                 lookupU(srcLineStride, srcPixelStride,
1146                         srcBandOffsets, sSrcData,
1147                         dstWidth, dstHeight, dstNumBands,
1148                         dstLineStride, dstPixelStride,
1149                         dstBandOffsets, fDstData,
1150                         tblOffsets, fTblData);
1151                 break;
1152 
1153             case DataBuffer.TYPE_SHORT:
1154                 lookup(srcLineStride, srcPixelStride,
1155                        srcBandOffsets, sSrcData,
1156                        dstWidth, dstHeight, dstNumBands,
1157                        dstLineStride, dstPixelStride,
1158                        dstBandOffsets, fDstData,
1159                        tblOffsets, fTblData);
1160                 break;
1161 
1162             case DataBuffer.TYPE_INT:
1163                 lookup(srcLineStride, srcPixelStride,
1164                        srcBandOffsets, iSrcData,
1165                        dstWidth, dstHeight, dstNumBands,
1166                        dstLineStride, dstPixelStride,
1167                        dstBandOffsets, fDstData,
1168                        tblOffsets, fTblData);
1169                 break;
1170             }
1171             break;
1172 
1173         case DataBuffer.TYPE_DOUBLE:
1174             switch (srcDataType) {
1175             case DataBuffer.TYPE_BYTE:
1176                 lookup(srcLineStride, srcPixelStride,
1177                        srcBandOffsets, bSrcData,
1178                        dstWidth, dstHeight, dstNumBands,
1179                        dstLineStride, dstPixelStride,
1180                        dstBandOffsets, dDstData,
1181                        tblOffsets, dTblData);
1182                 break;
1183 
1184             case DataBuffer.TYPE_USHORT:
1185                 lookupU(srcLineStride, srcPixelStride,
1186                         srcBandOffsets, sSrcData,
1187                         dstWidth, dstHeight, dstNumBands,
1188                         dstLineStride, dstPixelStride,
1189                         dstBandOffsets, dDstData,
1190                         tblOffsets, dTblData);
1191                 break;
1192 
1193             case DataBuffer.TYPE_SHORT:
1194                 lookup(srcLineStride, srcPixelStride,
1195                        srcBandOffsets, sSrcData,
1196                        dstWidth, dstHeight, dstNumBands,
1197                        dstLineStride, dstPixelStride,
1198                        dstBandOffsets, dDstData,
1199                        tblOffsets, dTblData);
1200                 break;
1201 
1202             case DataBuffer.TYPE_INT:
1203                 lookup(srcLineStride, srcPixelStride,
1204                        srcBandOffsets, iSrcData,
1205                        dstWidth, dstHeight, dstNumBands,
1206                        dstLineStride, dstPixelStride,
1207                        dstBandOffsets, dDstData,
1208                        tblOffsets, dTblData);
1209                 break;
1210             }
1211             break;
1212         }
1213 
1214         d.copyDataToRaster();
1215 
1216         return dst;
1217     }
1218 
1219     // byte to byte
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData)1220     private void lookup(int srcLineStride, int srcPixelStride,
1221                         int[] srcBandOffsets, byte[][] srcData,
1222                         int width, int height, int bands,
1223                         int dstLineStride, int dstPixelStride,
1224                         int[] dstBandOffsets, byte[][] dstData,
1225                         int[] tblOffsets, byte[][] tblData) {
1226         for (int b = 0; b < bands; b++) {
1227             byte[] s = srcData[b];
1228             byte[] d = dstData[b];
1229             byte[] t = tblData[b];
1230 
1231             int srcLineOffset = srcBandOffsets[b];
1232             int dstLineOffset = dstBandOffsets[b];
1233             int tblOffset = tblOffsets[b];
1234 
1235             for (int h = 0; h < height; h++) {
1236                 int srcPixelOffset = srcLineOffset;
1237                 int dstPixelOffset = dstLineOffset;
1238 
1239                 srcLineOffset += srcLineStride;
1240                 dstLineOffset += dstLineStride;
1241 
1242                 for (int w = 0; w < width; w++) {
1243                     d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset];
1244 
1245                     srcPixelOffset += srcPixelStride;
1246                     dstPixelOffset += dstPixelStride;
1247                 }
1248             }
1249         }
1250     }
1251 
1252     // ushort to byte
lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData)1253     private void lookupU(int srcLineStride, int srcPixelStride,
1254                          int[] srcBandOffsets, short[][] srcData,
1255                          int width, int height, int bands,
1256                          int dstLineStride, int dstPixelStride,
1257                          int[] dstBandOffsets, byte[][] dstData,
1258                          int[] tblOffsets, byte[][] tblData) {
1259         for (int b = 0; b < bands; b++) {
1260             short[] s = srcData[b];
1261             byte[] d = dstData[b];
1262             byte[] t = tblData[b];
1263 
1264             int srcLineOffset = srcBandOffsets[b];
1265             int dstLineOffset = dstBandOffsets[b];
1266             int tblOffset = tblOffsets[b];
1267 
1268             for (int h = 0; h < height; h++) {
1269                 int srcPixelOffset = srcLineOffset;
1270                 int dstPixelOffset = dstLineOffset;
1271 
1272                 srcLineOffset += srcLineStride;
1273                 dstLineOffset += dstLineStride;
1274 
1275                 for (int w = 0; w < width; w++) {
1276                     d[dstPixelOffset] =
1277                         t[(s[srcPixelOffset]&0xFFFF) - tblOffset];
1278 
1279                     srcPixelOffset += srcPixelStride;
1280                     dstPixelOffset += dstPixelStride;
1281                 }
1282             }
1283         }
1284     }
1285 
1286     // short to byte
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData)1287     private void lookup(int srcLineStride, int srcPixelStride,
1288                         int[] srcBandOffsets, short[][] srcData,
1289                         int width, int height, int bands,
1290                         int dstLineStride, int dstPixelStride,
1291                         int[] dstBandOffsets, byte[][] dstData,
1292                         int[] tblOffsets, byte[][] tblData) {
1293         for (int b = 0; b < bands; b++) {
1294             short[] s = srcData[b];
1295             byte[] d = dstData[b];
1296             byte[] t = tblData[b];
1297 
1298             int srcLineOffset = srcBandOffsets[b];
1299             int dstLineOffset = dstBandOffsets[b];
1300             int tblOffset = tblOffsets[b];
1301 
1302             for (int h = 0; h < height; h++) {
1303                 int srcPixelOffset = srcLineOffset;
1304                 int dstPixelOffset = dstLineOffset;
1305 
1306                 srcLineOffset += srcLineStride;
1307                 dstLineOffset += dstLineStride;
1308 
1309                 for (int w = 0; w < width; w++) {
1310                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1311 
1312                     srcPixelOffset += srcPixelStride;
1313                     dstPixelOffset += dstPixelStride;
1314                 }
1315             }
1316         }
1317     }
1318 
1319     // int to byte
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, byte[][] dstData, int[] tblOffsets, byte[][] tblData)1320     private void lookup(int srcLineStride, int srcPixelStride,
1321                         int[] srcBandOffsets, int[][] srcData,
1322                         int width, int height, int bands,
1323                         int dstLineStride, int dstPixelStride,
1324                         int[] dstBandOffsets, byte[][] dstData,
1325                         int[] tblOffsets, byte[][] tblData) {
1326         for (int b = 0; b < bands; b++) {
1327             int[] s = srcData[b];
1328             byte[] d = dstData[b];
1329             byte[] t = tblData[b];
1330 
1331             int srcLineOffset = srcBandOffsets[b];
1332             int dstLineOffset = dstBandOffsets[b];
1333             int tblOffset = tblOffsets[b];
1334 
1335             for (int h = 0; h < height; h++) {
1336                 int srcPixelOffset = srcLineOffset;
1337                 int dstPixelOffset = dstLineOffset;
1338 
1339                 srcLineOffset += srcLineStride;
1340                 dstLineOffset += dstLineStride;
1341 
1342                 for (int w = 0; w < width; w++) {
1343                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1344 
1345                     srcPixelOffset += srcPixelStride;
1346                     dstPixelOffset += dstPixelStride;
1347                 }
1348             }
1349         }
1350     }
1351 
1352     // byte to short or ushort
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData)1353     private void lookup(int srcLineStride, int srcPixelStride,
1354                         int[] srcBandOffsets, byte[][] srcData,
1355                         int width, int height, int bands,
1356                         int dstLineStride, int dstPixelStride,
1357                         int[] dstBandOffsets, short[][] dstData,
1358                         int[] tblOffsets, short[][] tblData) {
1359         for (int b = 0; b < bands; b++) {
1360             byte[] s = srcData[b];
1361             short[] d = dstData[b];
1362             short[] t = tblData[b];
1363 
1364             int srcLineOffset = srcBandOffsets[b];
1365             int dstLineOffset = dstBandOffsets[b];
1366             int tblOffset = tblOffsets[b];
1367 
1368             for (int h = 0; h < height; h++) {
1369                 int srcPixelOffset = srcLineOffset;
1370                 int dstPixelOffset = dstLineOffset;
1371 
1372                 srcLineOffset += srcLineStride;
1373                 dstLineOffset += dstLineStride;
1374 
1375                 for (int w = 0; w < width; w++) {
1376                     d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset];
1377 
1378                     srcPixelOffset += srcPixelStride;
1379                     dstPixelOffset += dstPixelStride;
1380                 }
1381             }
1382         }
1383     }
1384 
1385     // ushort to short or ushort
lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData)1386     private void lookupU(int srcLineStride, int srcPixelStride,
1387                          int[] srcBandOffsets, short[][] srcData,
1388                          int width, int height, int bands,
1389                          int dstLineStride, int dstPixelStride,
1390                          int[] dstBandOffsets, short[][] dstData,
1391                          int[] tblOffsets, short[][] tblData) {
1392         for (int b = 0; b < bands; b++) {
1393             short[] s = srcData[b];
1394             short[] d = dstData[b];
1395             short[] t = tblData[b];
1396 
1397             int srcLineOffset = srcBandOffsets[b];
1398             int dstLineOffset = dstBandOffsets[b];
1399             int tblOffset = tblOffsets[b];
1400 
1401             for (int h = 0; h < height; h++) {
1402                 int srcPixelOffset = srcLineOffset;
1403                 int dstPixelOffset = dstLineOffset;
1404 
1405                 srcLineOffset += srcLineStride;
1406                 dstLineOffset += dstLineStride;
1407 
1408                 for (int w = 0; w < width; w++) {
1409                     d[dstPixelOffset] =
1410                         t[(s[srcPixelOffset]&0xFFFF) - tblOffset];
1411 
1412                     srcPixelOffset += srcPixelStride;
1413                     dstPixelOffset += dstPixelStride;
1414                 }
1415             }
1416         }
1417     }
1418 
1419     // short to short or ushort
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData)1420     private void lookup(int srcLineStride, int srcPixelStride,
1421                         int[] srcBandOffsets, short[][] srcData,
1422                         int width, int height, int bands,
1423                         int dstLineStride, int dstPixelStride,
1424                         int[] dstBandOffsets, short[][] dstData,
1425                         int[] tblOffsets, short[][] tblData) {
1426         for (int b = 0; b < bands; b++) {
1427             short[] s = srcData[b];
1428             short[] d = dstData[b];
1429             short[] t = tblData[b];
1430 
1431             int srcLineOffset = srcBandOffsets[b];
1432             int dstLineOffset = dstBandOffsets[b];
1433             int tblOffset = tblOffsets[b];
1434 
1435             for (int h = 0; h < height; h++) {
1436                 int srcPixelOffset = srcLineOffset;
1437                 int dstPixelOffset = dstLineOffset;
1438 
1439                 srcLineOffset += srcLineStride;
1440                 dstLineOffset += dstLineStride;
1441 
1442                 for (int w = 0; w < width; w++) {
1443                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1444 
1445                     srcPixelOffset += srcPixelStride;
1446                     dstPixelOffset += dstPixelStride;
1447                 }
1448             }
1449         }
1450     }
1451 
1452     // int to short or ushort
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, short[][] dstData, int[] tblOffsets, short[][] tblData)1453     private void lookup(int srcLineStride, int srcPixelStride,
1454                         int[] srcBandOffsets, int[][] srcData,
1455                         int width, int height, int bands,
1456                         int dstLineStride, int dstPixelStride,
1457                         int[] dstBandOffsets, short[][] dstData,
1458                         int[] tblOffsets, short[][] tblData) {
1459         for (int b = 0; b < bands; b++) {
1460             int[] s = srcData[b];
1461             short[] d = dstData[b];
1462             short[] t = tblData[b];
1463 
1464             int srcLineOffset = srcBandOffsets[b];
1465             int dstLineOffset = dstBandOffsets[b];
1466             int tblOffset = tblOffsets[b];
1467 
1468             for (int h = 0; h < height; h++) {
1469                 int srcPixelOffset = srcLineOffset;
1470                 int dstPixelOffset = dstLineOffset;
1471 
1472                 srcLineOffset += srcLineStride;
1473                 dstLineOffset += dstLineStride;
1474 
1475                 for (int w = 0; w < width; w++) {
1476                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1477 
1478                     srcPixelOffset += srcPixelStride;
1479                     dstPixelOffset += dstPixelStride;
1480                 }
1481             }
1482         }
1483     }
1484 
1485     // byte to int
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData)1486     private void lookup(int srcLineStride, int srcPixelStride,
1487                         int[] srcBandOffsets, byte[][] srcData,
1488                         int width, int height, int bands,
1489                         int dstLineStride, int dstPixelStride,
1490                         int[] dstBandOffsets, int[][] dstData,
1491                         int[] tblOffsets, int[][] tblData) {
1492         if (tblData == null) {
1493             for (int b = 0; b < bands; b++) {
1494                 byte[] s = srcData[b];
1495                 int[] d = dstData[b];
1496 
1497                 int srcLineOffset = srcBandOffsets[b];
1498                 int dstLineOffset = dstBandOffsets[b];
1499 
1500                 for (int h = 0; h < height; h++) {
1501                     int srcPixelOffset = srcLineOffset;
1502                     int dstPixelOffset = dstLineOffset;
1503 
1504                     srcLineOffset += srcLineStride;
1505                     dstLineOffset += dstLineStride;
1506 
1507                     for (int w = 0; w < width; w++) {
1508                         d[dstPixelOffset] =
1509                             data.getElem(b, s[srcPixelOffset]&0xFF);
1510 
1511                         srcPixelOffset += srcPixelStride;
1512                         dstPixelOffset += dstPixelStride;
1513                     }
1514                 }
1515             }
1516         } else {
1517             for (int b = 0; b < bands; b++) {
1518                 byte[] s = srcData[b];
1519                 int[] d = dstData[b];
1520                 int[] t = tblData[b];
1521 
1522                 int srcLineOffset = srcBandOffsets[b];
1523                 int dstLineOffset = dstBandOffsets[b];
1524                 int tblOffset = tblOffsets[b];
1525 
1526                 for (int h = 0; h < height; h++) {
1527                     int srcPixelOffset = srcLineOffset;
1528                     int dstPixelOffset = dstLineOffset;
1529 
1530                     srcLineOffset += srcLineStride;
1531                     dstLineOffset += dstLineStride;
1532 
1533                     for (int w = 0; w < width; w++) {
1534                         d[dstPixelOffset] =
1535                             t[(s[srcPixelOffset]&0xFF) - tblOffset];
1536 
1537                         srcPixelOffset += srcPixelStride;
1538                         dstPixelOffset += dstPixelStride;
1539                     }
1540                 }
1541             }
1542         }
1543     }
1544 
1545     // ushort to int
lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData)1546     private void lookupU(int srcLineStride, int srcPixelStride,
1547                          int[] srcBandOffsets, short[][] srcData,
1548                          int width, int height, int bands,
1549                          int dstLineStride, int dstPixelStride,
1550                          int[] dstBandOffsets, int[][] dstData,
1551                          int[] tblOffsets, int[][] tblData) {
1552         if (tblData == null) {
1553             for (int b = 0; b < bands; b++) {
1554                 short[] s = srcData[b];
1555                 int[] d = dstData[b];
1556 
1557                 int srcLineOffset = srcBandOffsets[b];
1558                 int dstLineOffset = dstBandOffsets[b];
1559 
1560                 for (int h = 0; h < height; h++) {
1561                     int srcPixelOffset = srcLineOffset;
1562                     int dstPixelOffset = dstLineOffset;
1563 
1564                     srcLineOffset += srcLineStride;
1565                     dstLineOffset += dstLineStride;
1566 
1567                     for (int w = 0; w < width; w++) {
1568                         d[dstPixelOffset] =
1569                             data.getElem(b, s[srcPixelOffset]&0xFFFF);
1570 
1571                         srcPixelOffset += srcPixelStride;
1572                         dstPixelOffset += dstPixelStride;
1573                     }
1574                 }
1575             }
1576         } else {
1577             for (int b = 0; b < bands; b++) {
1578                 short[] s = srcData[b];
1579                 int[] d = dstData[b];
1580                 int[] t = tblData[b];
1581 
1582                 int srcLineOffset = srcBandOffsets[b];
1583                 int dstLineOffset = dstBandOffsets[b];
1584                 int tblOffset = tblOffsets[b];
1585 
1586                 for (int h = 0; h < height; h++) {
1587                     int srcPixelOffset = srcLineOffset;
1588                     int dstPixelOffset = dstLineOffset;
1589 
1590                     srcLineOffset += srcLineStride;
1591                     dstLineOffset += dstLineStride;
1592 
1593                     for (int w = 0; w < width; w++) {
1594                         d[dstPixelOffset] =
1595                             t[(s[srcPixelOffset]&0xFFFF) - tblOffset];
1596 
1597                         srcPixelOffset += srcPixelStride;
1598                         dstPixelOffset += dstPixelStride;
1599                     }
1600                 }
1601             }
1602         }
1603     }
1604 
1605     // short to int
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData)1606     private void lookup(int srcLineStride, int srcPixelStride,
1607                         int[] srcBandOffsets, short[][] srcData,
1608                         int width, int height, int bands,
1609                         int dstLineStride, int dstPixelStride,
1610                         int[] dstBandOffsets, int[][] dstData,
1611                         int[] tblOffsets, int[][] tblData) {
1612         if (tblData == null) {
1613             for (int b = 0; b < bands; b++) {
1614                 short[] s = srcData[b];
1615                 int[] d = dstData[b];
1616 
1617                 int srcLineOffset = srcBandOffsets[b];
1618                 int dstLineOffset = dstBandOffsets[b];
1619 
1620                 for (int h = 0; h < height; h++) {
1621                     int srcPixelOffset = srcLineOffset;
1622                     int dstPixelOffset = dstLineOffset;
1623 
1624                     srcLineOffset += srcLineStride;
1625                     dstLineOffset += dstLineStride;
1626 
1627                     for (int w = 0; w < width; w++) {
1628                         d[dstPixelOffset] =
1629                             data.getElem(b, s[srcPixelOffset]);
1630 
1631                         srcPixelOffset += srcPixelStride;
1632                         dstPixelOffset += dstPixelStride;
1633                     }
1634                 }
1635             }
1636         } else {
1637             for (int b = 0; b < bands; b++) {
1638                 short[] s = srcData[b];
1639                 int[] d = dstData[b];
1640                 int[] t = tblData[b];
1641 
1642                 int srcLineOffset = srcBandOffsets[b];
1643                 int dstLineOffset = dstBandOffsets[b];
1644                 int tblOffset = tblOffsets[b];
1645 
1646                 for (int h = 0; h < height; h++) {
1647                     int srcPixelOffset = srcLineOffset;
1648                     int dstPixelOffset = dstLineOffset;
1649 
1650                     srcLineOffset += srcLineStride;
1651                     dstLineOffset += dstLineStride;
1652 
1653                     for (int w = 0; w < width; w++) {
1654                         d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1655 
1656                         srcPixelOffset += srcPixelStride;
1657                         dstPixelOffset += dstPixelStride;
1658                     }
1659                 }
1660             }
1661         }
1662     }
1663 
1664     // int to int
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, int[][] dstData, int[] tblOffsets, int[][] tblData)1665     private void lookup(int srcLineStride, int srcPixelStride,
1666                         int[] srcBandOffsets, int[][] srcData,
1667                         int width, int height, int bands,
1668                         int dstLineStride, int dstPixelStride,
1669                         int[] dstBandOffsets, int[][] dstData,
1670                         int[] tblOffsets, int[][] tblData) {
1671         if (tblData == null) {
1672             for (int b = 0; b < bands; b++) {
1673                 int[] s = srcData[b];
1674                 int[] d = dstData[b];
1675 
1676                 int srcLineOffset = srcBandOffsets[b];
1677                 int dstLineOffset = dstBandOffsets[b];
1678 
1679                 for (int h = 0; h < height; h++) {
1680                     int srcPixelOffset = srcLineOffset;
1681                     int dstPixelOffset = dstLineOffset;
1682 
1683                     srcLineOffset += srcLineStride;
1684                     dstLineOffset += dstLineStride;
1685 
1686                     for (int w = 0; w < width; w++) {
1687                         d[dstPixelOffset] = data.getElem(b, s[srcPixelOffset]);
1688 
1689                         srcPixelOffset += srcPixelStride;
1690                         dstPixelOffset += dstPixelStride;
1691                     }
1692                 }
1693             }
1694         } else {
1695             for (int b = 0; b < bands; b++) {
1696                 int[] s = srcData[b];
1697                 int[] d = dstData[b];
1698                 int[] t = tblData[b];
1699 
1700                 int srcLineOffset = srcBandOffsets[b];
1701                 int dstLineOffset = dstBandOffsets[b];
1702                 int tblOffset = tblOffsets[b];
1703 
1704                 for (int h = 0; h < height; h++) {
1705                     int srcPixelOffset = srcLineOffset;
1706                     int dstPixelOffset = dstLineOffset;
1707 
1708                     srcLineOffset += srcLineStride;
1709                     dstLineOffset += dstLineStride;
1710 
1711                     for (int w = 0; w < width; w++) {
1712                         d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1713 
1714                         srcPixelOffset += srcPixelStride;
1715                         dstPixelOffset += dstPixelStride;
1716                     }
1717                 }
1718             }
1719         }
1720     }
1721 
1722     // byte to float
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData)1723     private void lookup(int srcLineStride, int srcPixelStride,
1724                         int[] srcBandOffsets, byte[][] srcData,
1725                         int width, int height, int bands,
1726                         int dstLineStride, int dstPixelStride,
1727                         int[] dstBandOffsets, float[][] dstData,
1728                         int[] tblOffsets, float[][] tblData) {
1729         for (int b = 0; b < bands; b++) {
1730             byte[] s = srcData[b];
1731             float[] d = dstData[b];
1732             float[] t = tblData[b];
1733 
1734             int srcLineOffset = srcBandOffsets[b];
1735             int dstLineOffset = dstBandOffsets[b];
1736             int tblOffset = tblOffsets[b];
1737 
1738             for (int h = 0; h < height; h++) {
1739                 int srcPixelOffset = srcLineOffset;
1740                 int dstPixelOffset = dstLineOffset;
1741 
1742                 srcLineOffset += srcLineStride;
1743                 dstLineOffset += dstLineStride;
1744 
1745                 for (int w = 0; w < width; w++) {
1746                     d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset];
1747 
1748                     srcPixelOffset += srcPixelStride;
1749                     dstPixelOffset += dstPixelStride;
1750                 }
1751             }
1752         }
1753     }
1754 
1755     // ushort to float
lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData)1756     private void lookupU(int srcLineStride, int srcPixelStride,
1757                          int[] srcBandOffsets, short[][] srcData,
1758                          int width, int height, int bands,
1759                          int dstLineStride, int dstPixelStride,
1760                          int[] dstBandOffsets, float[][] dstData,
1761                          int[] tblOffsets, float[][] tblData) {
1762         for (int b = 0; b < bands; b++) {
1763             short[] s = srcData[b];
1764             float[] d = dstData[b];
1765             float[] t = tblData[b];
1766 
1767             int srcLineOffset = srcBandOffsets[b];
1768             int dstLineOffset = dstBandOffsets[b];
1769             int tblOffset = tblOffsets[b];
1770 
1771             for (int h = 0; h < height; h++) {
1772                 int srcPixelOffset = srcLineOffset;
1773                 int dstPixelOffset = dstLineOffset;
1774 
1775                 srcLineOffset += srcLineStride;
1776                 dstLineOffset += dstLineStride;
1777 
1778                 for (int w = 0; w < width; w++) {
1779                     d[dstPixelOffset] =
1780                         t[(s[srcPixelOffset]&0xFFFF) - tblOffset];
1781 
1782                     srcPixelOffset += srcPixelStride;
1783                     dstPixelOffset += dstPixelStride;
1784                 }
1785             }
1786         }
1787     }
1788 
1789     // short to float
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData)1790     private void lookup(int srcLineStride, int srcPixelStride,
1791                         int[] srcBandOffsets, short[][] srcData,
1792                         int width, int height, int bands,
1793                         int dstLineStride, int dstPixelStride,
1794                         int[] dstBandOffsets, float[][] dstData,
1795                         int[] tblOffsets, float[][] tblData) {
1796         for (int b = 0; b < bands; b++) {
1797             short[] s = srcData[b];
1798             float[] d = dstData[b];
1799             float[] t = tblData[b];
1800 
1801             int srcLineOffset = srcBandOffsets[b];
1802             int dstLineOffset = dstBandOffsets[b];
1803             int tblOffset = tblOffsets[b];
1804 
1805             for (int h = 0; h < height; h++) {
1806                 int srcPixelOffset = srcLineOffset;
1807                 int dstPixelOffset = dstLineOffset;
1808 
1809                 srcLineOffset += srcLineStride;
1810                 dstLineOffset += dstLineStride;
1811 
1812                 for (int w = 0; w < width; w++) {
1813                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1814 
1815                     srcPixelOffset += srcPixelStride;
1816                     dstPixelOffset += dstPixelStride;
1817                 }
1818             }
1819         }
1820     }
1821 
1822     // int to float
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, float[][] dstData, int[] tblOffsets, float[][] tblData)1823     private void lookup(int srcLineStride, int srcPixelStride,
1824                         int[] srcBandOffsets, int[][] srcData,
1825                         int width, int height, int bands,
1826                         int dstLineStride, int dstPixelStride,
1827                         int[] dstBandOffsets, float[][] dstData,
1828                         int[] tblOffsets, float[][] tblData) {
1829         for (int b = 0; b < bands; b++) {
1830             int[] s = srcData[b];
1831             float[] d = dstData[b];
1832             float[] t = tblData[b];
1833 
1834             int srcLineOffset = srcBandOffsets[b];
1835             int dstLineOffset = dstBandOffsets[b];
1836             int tblOffset = tblOffsets[b];
1837 
1838             for (int h = 0; h < height; h++) {
1839                 int srcPixelOffset = srcLineOffset;
1840                 int dstPixelOffset = dstLineOffset;
1841 
1842                 srcLineOffset += srcLineStride;
1843                 dstLineOffset += dstLineStride;
1844 
1845                 for (int w = 0; w < width; w++) {
1846                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1847 
1848                     srcPixelOffset += srcPixelStride;
1849                     dstPixelOffset += dstPixelStride;
1850                 }
1851             }
1852         }
1853     }
1854 
1855     // byte to double
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, byte[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData)1856     private void lookup(int srcLineStride, int srcPixelStride,
1857                         int[] srcBandOffsets, byte[][] srcData,
1858                         int width, int height, int bands,
1859                         int dstLineStride, int dstPixelStride,
1860                         int[] dstBandOffsets, double[][] dstData,
1861                         int[] tblOffsets, double[][] tblData) {
1862         for (int b = 0; b < bands; b++) {
1863             byte[] s = srcData[b];
1864             double[] d = dstData[b];
1865             double[] t = tblData[b];
1866 
1867             int srcLineOffset = srcBandOffsets[b];
1868             int dstLineOffset = dstBandOffsets[b];
1869             int tblOffset = tblOffsets[b];
1870 
1871             for (int h = 0; h < height; h++) {
1872                 int srcPixelOffset = srcLineOffset;
1873                 int dstPixelOffset = dstLineOffset;
1874 
1875                 srcLineOffset += srcLineStride;
1876                 dstLineOffset += dstLineStride;
1877 
1878                 for (int w = 0; w < width; w++) {
1879                     d[dstPixelOffset] = t[(s[srcPixelOffset]&0xFF) - tblOffset];
1880 
1881                     srcPixelOffset += srcPixelStride;
1882                     dstPixelOffset += dstPixelStride;
1883                 }
1884             }
1885         }
1886     }
1887 
1888     // ushort to double
lookupU(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData)1889     private void lookupU(int srcLineStride, int srcPixelStride,
1890                          int[] srcBandOffsets, short[][] srcData,
1891                          int width, int height, int bands,
1892                          int dstLineStride, int dstPixelStride,
1893                          int[] dstBandOffsets, double[][] dstData,
1894                          int[] tblOffsets, double[][] tblData) {
1895         for (int b = 0; b < bands; b++) {
1896             short[] s = srcData[b];
1897             double[] d = dstData[b];
1898             double[] t = tblData[b];
1899 
1900             int srcLineOffset = srcBandOffsets[b];
1901             int dstLineOffset = dstBandOffsets[b];
1902             int tblOffset = tblOffsets[b];
1903 
1904             for (int h = 0; h < height; h++) {
1905                 int srcPixelOffset = srcLineOffset;
1906                 int dstPixelOffset = dstLineOffset;
1907 
1908                 srcLineOffset += srcLineStride;
1909                 dstLineOffset += dstLineStride;
1910 
1911                 for (int w = 0; w < width; w++) {
1912                     d[dstPixelOffset] =
1913                         t[(s[srcPixelOffset]&0xFFFF) - tblOffset];
1914 
1915                     srcPixelOffset += srcPixelStride;
1916                     dstPixelOffset += dstPixelStride;
1917                 }
1918             }
1919         }
1920     }
1921 
1922     // short to double
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, short[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData)1923     private void lookup(int srcLineStride, int srcPixelStride,
1924                         int[] srcBandOffsets, short[][] srcData,
1925                         int width, int height, int bands,
1926                         int dstLineStride, int dstPixelStride,
1927                         int[] dstBandOffsets, double[][] dstData,
1928                         int[] tblOffsets, double[][] tblData) {
1929         for (int b = 0; b < bands; b++) {
1930             short[] s = srcData[b];
1931             double[] d = dstData[b];
1932             double[] t = tblData[b];
1933 
1934             int srcLineOffset = srcBandOffsets[b];
1935             int dstLineOffset = dstBandOffsets[b];
1936             int tblOffset = tblOffsets[b];
1937 
1938             for (int h = 0; h < height; h++) {
1939                 int srcPixelOffset = srcLineOffset;
1940                 int dstPixelOffset = dstLineOffset;
1941 
1942                 srcLineOffset += srcLineStride;
1943                 dstLineOffset += dstLineStride;
1944 
1945                 for (int w = 0; w < width; w++) {
1946                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1947 
1948                     srcPixelOffset += srcPixelStride;
1949                     dstPixelOffset += dstPixelStride;
1950                 }
1951             }
1952         }
1953     }
1954 
1955     // int to double
lookup(int srcLineStride, int srcPixelStride, int[] srcBandOffsets, int[][] srcData, int width, int height, int bands, int dstLineStride, int dstPixelStride, int[] dstBandOffsets, double[][] dstData, int[] tblOffsets, double[][] tblData)1956     private void lookup(int srcLineStride, int srcPixelStride,
1957                         int[] srcBandOffsets, int[][] srcData,
1958                         int width, int height, int bands,
1959                         int dstLineStride, int dstPixelStride,
1960                         int[] dstBandOffsets, double[][] dstData,
1961                         int[] tblOffsets, double[][] tblData) {
1962         for (int b = 0; b < bands; b++) {
1963             int[] s = srcData[b];
1964             double[] d = dstData[b];
1965             double[] t = tblData[b];
1966 
1967             int srcLineOffset = srcBandOffsets[b];
1968             int dstLineOffset = dstBandOffsets[b];
1969             int tblOffset = tblOffsets[b];
1970 
1971             for (int h = 0; h < height; h++) {
1972                 int srcPixelOffset = srcLineOffset;
1973                 int dstPixelOffset = dstLineOffset;
1974 
1975                 srcLineOffset += srcLineStride;
1976                 dstLineOffset += dstLineStride;
1977 
1978                 for (int w = 0; w < width; w++) {
1979                     d[dstPixelOffset] = t[s[srcPixelOffset] - tblOffset];
1980 
1981                     srcPixelOffset += srcPixelStride;
1982                     dstPixelOffset += dstPixelStride;
1983                 }
1984             }
1985         }
1986     }
1987 
1988     /**
1989      * Determine which entry in the <code>LookupTableJAI</code> is closest
1990      * in Euclidean distance to the argument pixel.
1991      *
1992      * @param pixel The pixel the closest entry to which is to be found.
1993      *
1994      * @return the index of the closest entry. If the data array of the
1995      * lookup table is in the format data[numBands][numEntries], then the
1996      * value <i>v</i> for band <i>b</i> of the closest entry is
1997      * <pre>
1998      *     v = data[b][index - lookup.getOffset()]
1999      * </pre>
2000      * where <i>index</i> is the returned value of this method.
2001      *
2002      * @throws IllegalArgumentException if pixel is null.
2003      */
findNearestEntry(float[] pixel)2004     public int findNearestEntry(float[] pixel) {
2005 
2006         if ( pixel == null ) {
2007             throw new IllegalArgumentException(JaiI18N.getString("Generic0"));
2008         }
2009 
2010         int dataType = data.getDataType();
2011         int numBands = getNumBands();
2012         int numEntries = getNumEntries();
2013         int index = -1;
2014 
2015         if(dataType == DataBuffer.TYPE_BYTE) {
2016             byte buffer[][] = getByteData();
2017 
2018             // Find the distance to the first entry and set result to 0.
2019             float minDistance = 0.0F;
2020             index = 0;
2021             for(int b = 0; b < numBands; b++) {
2022                 float delta = pixel[b] - (float)(buffer[b][0] & 0xff);
2023                 minDistance += delta*delta;
2024             }
2025 
2026             // Find the distance to each entry and set the result to
2027             // the index which is closest to the argument.
2028             for(int i = 1; i < numEntries; i++) {
2029                 float distance = 0.0F;
2030                 for(int b = 0; b < numBands; b++) {
2031                     float delta =
2032                         pixel[b] - (float)(buffer[b][i] & 0xff);
2033                     distance += delta*delta;
2034                 }
2035 
2036                 if(distance < minDistance) {
2037                     minDistance = distance;
2038                     index = i;
2039                 }
2040             }
2041         } else if(dataType == DataBuffer.TYPE_SHORT) {
2042             short buffer[][] = getShortData();
2043 
2044             // Find the distance to the first entry and set result to 0.
2045             float minDistance = 0.0F;
2046             index = 0;
2047             for(int b = 0; b < numBands; b++) {
2048                 float delta = pixel[b] - buffer[b][0];
2049                 minDistance += delta*delta;
2050             }
2051 
2052             // Find the distance to each entry and set the result to
2053             // the index which is closest to the argument.
2054             for(int i = 1; i < numEntries; i++) {
2055                 float distance = 0.0F;
2056                 for(int b = 0; b < numBands; b++) {
2057                     float delta = pixel[b] - buffer[b][i];
2058                     distance += delta*delta;
2059                 }
2060 
2061                 if(distance < minDistance) {
2062                     minDistance = distance;
2063                     index = i;
2064                 }
2065             }
2066         } else if(dataType == DataBuffer.TYPE_USHORT) {
2067             short buffer[][] = getShortData();
2068 
2069             // Find the distance to the first entry and set result to 0.
2070             float minDistance = 0.0F;
2071             index = 0;
2072             for(int b = 0; b < numBands; b++) {
2073                 float delta = pixel[b] - (float)(buffer[b][0] & 0xffff);
2074                 minDistance += delta*delta;
2075             }
2076 
2077             // Find the distance to each entry and set the result to
2078             // the index which is closest to the argument.
2079             for(int i = 1; i < numEntries; i++) {
2080                 float distance = 0.0F;
2081                 for(int b = 0; b < numBands; b++) {
2082                     float delta =
2083                         pixel[b] - (float)(buffer[b][i] & 0xffff);
2084                     distance += delta*delta;
2085                 }
2086 
2087                 if(distance < minDistance) {
2088                     minDistance = distance;
2089                     index = i;
2090                 }
2091             }
2092         } else if(dataType == DataBuffer.TYPE_INT) {
2093             int buffer[][] = getIntData();
2094 
2095             // Find the distance to the first entry and set result to 0.
2096             float minDistance = 0.0F;
2097             index = 0;
2098             for(int b = 0; b < numBands; b++) {
2099                 float delta = pixel[b] - buffer[b][0];
2100                 minDistance += delta*delta;
2101             }
2102 
2103             // Find the distance to each entry and set the result to
2104             // the index which is closest to the argument.
2105             for(int i = 1; i < numEntries; i++) {
2106                 float distance = 0.0F;
2107                 for(int b = 0; b < numBands; b++) {
2108                     float delta = pixel[b] - buffer[b][i];
2109                     distance += delta*delta;
2110                 }
2111 
2112                 if(distance < minDistance) {
2113                     minDistance = distance;
2114                     index = i;
2115                 }
2116             }
2117         } else if(dataType == DataBuffer.TYPE_FLOAT) {
2118             float buffer[][] = getFloatData();
2119 
2120             // Find the distance to the first entry and set result to 0.
2121             float minDistance = 0.0F;
2122             index = 0;
2123             for(int b = 0; b < numBands; b++) {
2124                 float delta = pixel[b] - buffer[b][0];
2125                 minDistance += delta*delta;
2126             }
2127 
2128             // Find the distance to each entry and set the result to
2129             // the index which is closest to the argument.
2130             for(int i = 1; i < numEntries; i++) {
2131                 float distance = 0.0F;
2132                 for(int b = 0; b < numBands; b++) {
2133                     float delta = pixel[b] - buffer[b][i];
2134                     distance += delta*delta;
2135                 }
2136 
2137                 if(distance < minDistance) {
2138                     minDistance = distance;
2139                     index = i;
2140                 }
2141             }
2142         } else if(dataType == DataBuffer.TYPE_DOUBLE) {
2143             double buffer[][] = getDoubleData();
2144 
2145             // Find the distance to the first entry and set result to 0.
2146             double minDistance = 0.0F;
2147             index = 0;
2148             for(int b = 0; b < numBands; b++) {
2149                 double delta = pixel[b] - buffer[b][0];
2150                 minDistance += delta*delta;
2151             }
2152 
2153             // Find the distance to each entry and set the result to
2154             // the index which is closest to the argument.
2155             for(int i = 1; i < numEntries; i++) {
2156                 double distance = 0.0F;
2157                 for(int b = 0; b < numBands; b++) {
2158                     double delta = pixel[b] - buffer[b][i];
2159                     distance += delta*delta;
2160                 }
2161 
2162                 if(distance < minDistance) {
2163                     minDistance = distance;
2164                     index = i;
2165                 }
2166             }
2167         } else {
2168             // This can't happen since we control the type of data
2169             throw new RuntimeException(JaiI18N.getString("LookupTableJAI0"));
2170         }
2171 
2172         // Return the index of the closest color plus the offset of the
2173         // default band or -1 on error.
2174         return index == -1 ? index : index + getOffset();
2175     }
2176 
2177     /**
2178       * Serialize the <code>LookupTableJAI</code>.
2179       *
2180       * @param out The <code>ObjectOutputStream</code>.
2181       */
writeObject(ObjectOutputStream out)2182     private void writeObject(ObjectOutputStream out) throws IOException {
2183         out.defaultWriteObject();
2184         out.writeObject(SerializerFactory.getState(data));
2185     }
2186 
2187     /**
2188       * Deserialize the <code>LookupTableJAI</code>.
2189       *
2190       * @param in The <code>ObjectInputStream</code>.
2191       */
readObject(ObjectInputStream in)2192     private void readObject(ObjectInputStream in)
2193         throws IOException, ClassNotFoundException {
2194         in.defaultReadObject();
2195         Object object = in.readObject();
2196         SerializableState ss = (SerializableState)object;
2197         data = (DataBuffer)ss.getObject();
2198     }
2199 
initOffsets(int nbands, int offset)2200     private void initOffsets(int nbands, int offset) {
2201         tableOffsets = new int[nbands];
2202         for (int i=0; i<nbands; i++) {
2203             tableOffsets[i] = offset;
2204         }
2205     }
2206 
initOffsets(int nbands, int[] offset)2207     private void initOffsets(int nbands, int[] offset) {
2208         tableOffsets = new int[nbands];
2209         for (int i=0; i<nbands; i++) {
2210             tableOffsets[i] = offset[i];
2211         }
2212     }
2213 
2214 
2215 }
2216 
2217 
2218