1 /*
2  * $RCSfile: WarpGeneralOpImage.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:56:47 $
10  * $State: Exp $
11  */
12 package com.lightcrafts.media.jai.opimage;
13 import java.awt.Rectangle;
14 import java.awt.image.ColorModel;
15 import java.awt.image.DataBuffer;
16 import java.awt.image.IndexColorModel;
17 import java.awt.image.RenderedImage;
18 import java.awt.image.WritableRaster;
19 import com.lightcrafts.mediax.jai.BorderExtender;
20 import com.lightcrafts.mediax.jai.ImageLayout;
21 import com.lightcrafts.mediax.jai.Interpolation;
22 import com.lightcrafts.mediax.jai.PlanarImage;
23 import com.lightcrafts.mediax.jai.RasterAccessor;
24 import com.lightcrafts.mediax.jai.RasterFormatTag;
25 import java.util.Map;
26 import com.lightcrafts.mediax.jai.Warp;
27 import com.lightcrafts.mediax.jai.WarpOpImage;
28 import com.lightcrafts.mediax.jai.iterator.RandomIter;
29 import com.lightcrafts.mediax.jai.iterator.RandomIterFactory;
30 import com.lightcrafts.media.jai.util.ImageUtil;
31 
32 /**
33  * An <code>OpImage</code> implementing the general "Warp" operation as
34  * described in <code>com.lightcrafts.mediax.jai.operator.WarpDescriptor</code>.
35  * It supports all interpolation cases.
36  *
37  * @since EA2
38  * @see com.lightcrafts.mediax.jai.Warp
39  * @see com.lightcrafts.mediax.jai.WarpOpImage
40  * @see com.lightcrafts.mediax.jai.operator.WarpDescriptor
41  * @see WarpRIF
42  *
43  */
44 final class WarpGeneralOpImage extends WarpOpImage {
45 
46     /** Color table representing source's IndexColorModel. */
47     private byte[][] ctable = null;
48 
49     /**
50      * Constructs a WarpGeneralOpImage.
51      *
52      * @param source  The source image.
53      * @param extender A BorderExtender, or null.
54      * @param layout  The destination image layout.
55      * @param warp    An object defining the warp algorithm.
56      * @param interp  An object describing the interpolation method.
57      */
WarpGeneralOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, Warp warp, Interpolation interp, double[] backgroundValues)58     public WarpGeneralOpImage(RenderedImage source,
59                               BorderExtender extender,
60                               Map config,
61                               ImageLayout layout,
62                               Warp warp,
63                               Interpolation interp,
64                               double[] backgroundValues) {
65         super(source,
66               layout,
67               config,
68               false,
69               extender,
70               interp,
71               warp,
72               backgroundValues);
73 
74         /*
75          * If the source has IndexColorModel, get the RGB color table.
76          * Note, in this case, the source should have an integral data type.
77          * And dest always has data type byte.
78          */
79         ColorModel srcColorModel = source.getColorModel();
80         if (srcColorModel instanceof IndexColorModel) {
81             IndexColorModel icm = (IndexColorModel)srcColorModel;
82             ctable = new byte[3][icm.getMapSize()];
83             icm.getReds(ctable[0]);
84             icm.getGreens(ctable[1]);
85             icm.getBlues(ctable[2]);
86         }
87     }
88 
89     /** Warps a rectangle. */
computeRect(PlanarImage[] sources, WritableRaster dest, Rectangle destRect)90     protected void computeRect(PlanarImage[] sources,
91                                WritableRaster dest,
92                                Rectangle destRect) {
93         // Retrieve format tags.
94         RasterFormatTag[] formatTags = getFormatTags();
95 
96         RasterAccessor d = new RasterAccessor(dest, destRect,
97                                formatTags[1], getColorModel());
98 
99         switch (d.getDataType()) {
100         case DataBuffer.TYPE_BYTE:
101             computeRectByte(sources[0], d);
102             break;
103         case DataBuffer.TYPE_USHORT:
104             computeRectUShort(sources[0], d);
105             break;
106         case DataBuffer.TYPE_SHORT:
107             computeRectShort(sources[0], d);
108             break;
109         case DataBuffer.TYPE_INT:
110             computeRectInt(sources[0], d);
111             break;
112         case DataBuffer.TYPE_FLOAT:
113             computeRectFloat(sources[0], d);
114             break;
115         case DataBuffer.TYPE_DOUBLE:
116             computeRectDouble(sources[0], d);
117             break;
118         }
119 
120         if (d.isDataCopy()) {
121             d.clampDataArrays();
122             d.copyDataToRaster();
123         }
124     }
125 
computeRectByte(PlanarImage src, RasterAccessor dst)126     private void computeRectByte(PlanarImage src, RasterAccessor dst) {
127         int lpad, rpad, tpad, bpad;
128         if(interp != null) {
129             lpad = interp.getLeftPadding();
130             rpad = interp.getRightPadding();
131             tpad = interp.getTopPadding();
132             bpad = interp.getBottomPadding();
133         } else {
134             lpad = rpad = tpad = bpad = 0;
135         }
136 
137         int minX, maxX, minY, maxY;
138         RandomIter iter;
139         if(extender != null) {
140             minX = src.getMinX();
141             maxX = src.getMaxX();
142             minY = src.getMinY();
143             maxY = src.getMaxY();
144             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
145                                              src.getMinY() - tpad,
146                                              src.getWidth() + lpad + rpad,
147                                              src.getHeight() + tpad + bpad);
148             iter = RandomIterFactory.create(src.getExtendedData(bounds,
149                                                                 extender),
150                                             bounds);
151         } else {
152             minX = src.getMinX() + lpad;
153             maxX = src.getMaxX() - rpad;
154             minY = src.getMinY() + tpad;
155             maxY = src.getMaxY() - bpad;
156             iter = RandomIterFactory.create(src, src.getBounds());
157         }
158 
159         int kwidth = interp.getWidth();
160         int kheight = interp.getHeight();
161 
162         int dstWidth = dst.getWidth();
163         int dstHeight = dst.getHeight();
164         int dstBands = dst.getNumBands();
165 
166         int lineStride = dst.getScanlineStride();
167         int pixelStride = dst.getPixelStride();
168         int[] bandOffsets = dst.getBandOffsets();
169         byte[][] data = dst.getByteDataArrays();
170 
171         int precH = 1 << interp.getSubsampleBitsH();
172         int precV = 1 << interp.getSubsampleBitsV();
173 
174         float[] warpData = new float[2 * dstWidth];
175 
176         int[][] samples = new int[kheight][kwidth];
177 
178         int lineOffset = 0;
179 
180         byte[] backgroundByte = new byte[dstBands];
181 	for (int i = 0; i < dstBands; i++)
182 	    backgroundByte[i] = (byte)backgroundValues[i];
183 
184         if (ctable == null) {	// source does not have IndexColorModel
185             for (int h = 0; h < dstHeight; h++) {
186                 int pixelOffset = lineOffset;
187                 lineOffset += lineStride;
188 
189                 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
190 
191                 int count = 0;
192                 for (int w = 0; w < dstWidth; w++) {
193                     float sx = warpData[count++];
194                     float sy = warpData[count++];
195 
196                     int xint = floor(sx);
197                     int yint = floor(sy);
198                     int xfrac = (int)((sx - xint) * precH);
199                     int yfrac = (int)((sy - yint) * precV);
200 
201                     if (xint < minX || xint >= maxX ||
202                         yint < minY || yint >= maxY) {
203                         /* Fill with a background color. */
204                         if (setBackground) {
205                             for (int b = 0; b < dstBands; b++) {
206                                 data[b][pixelOffset+bandOffsets[b]] =
207                                     backgroundByte[b];
208                             }
209                         }
210                     } else {
211                         xint -= lpad;
212                         yint -= tpad;
213 
214                         for (int b = 0; b < dstBands; b++) {
215                             for (int j = 0; j < kheight; j++) {
216                                 for (int i = 0; i < kwidth; i++) {
217                                     samples[j][i] = iter.getSample(
218                                         xint+i, yint+j, b) & 0xFF;
219                                 }
220                             }
221 
222                             data[b][pixelOffset+bandOffsets[b]] =
223                                 ImageUtil.clampByte(
224                                 interp.interpolate(samples, xfrac, yfrac));
225                         }
226                     }
227 
228                     pixelOffset += pixelStride;
229                 }
230             }
231         } else {	// source has IndexColorModel
232             for (int h = 0; h < dstHeight; h++) {
233                 int pixelOffset = lineOffset;
234                 lineOffset += lineStride;
235 
236                 warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
237 
238                 int count = 0;
239                 for (int w = 0; w < dstWidth; w++) {
240                     float sx = warpData[count++];
241                     float sy = warpData[count++];
242 
243                     int xint = floor(sx);
244                     int yint = floor(sy);
245                     int xfrac = (int)((sx - xint) * precH);
246                     int yfrac = (int)((sy - yint) * precV);
247 
248                     if (xint < minX || xint >= maxX ||
249                         yint < minY || yint >= maxY) {
250                         /* Fill with a background color. */
251                         if (setBackground) {
252                             for (int b = 0; b < dstBands; b++) {
253                                 data[b][pixelOffset+bandOffsets[b]] =
254                                     backgroundByte[b];
255                             }
256                         }
257                     } else {
258                         xint -= lpad;
259                         yint -= tpad;
260 
261                         for (int b = 0; b < dstBands; b++) {
262                             byte[] t = ctable[b];
263 
264                             for (int j = 0; j < kheight; j++) {
265                                 for (int i = 0; i < kwidth; i++) {
266                                     samples[j][i] = t[iter.getSample(
267                                         xint+i, yint+j, 0) & 0xFF] & 0xFF;
268                                 }
269                             }
270 
271                             data[b][pixelOffset+bandOffsets[b]] =
272                                 ImageUtil.clampByte(
273                                 interp.interpolate(samples, xfrac, yfrac));
274                         }
275                     }
276 
277                     pixelOffset += pixelStride;
278                 }
279             }
280         }
281     }
282 
computeRectUShort(PlanarImage src, RasterAccessor dst)283     private void computeRectUShort(PlanarImage src, RasterAccessor dst) {
284         int lpad, rpad, tpad, bpad;
285         if(interp != null) {
286             lpad = interp.getLeftPadding();
287             rpad = interp.getRightPadding();
288             tpad = interp.getTopPadding();
289             bpad = interp.getBottomPadding();
290         } else {
291             lpad = rpad = tpad = bpad = 0;
292         }
293 
294         int minX, maxX, minY, maxY;
295         RandomIter iter;
296         if(extender != null) {
297             minX = src.getMinX();
298             maxX = src.getMaxX();
299             minY = src.getMinY();
300             maxY = src.getMaxY();
301             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
302                                              src.getMinY() - tpad,
303                                              src.getWidth() + lpad + rpad,
304                                              src.getHeight() + tpad + bpad);
305             iter = RandomIterFactory.create(src.getExtendedData(bounds,
306                                                                 extender),
307                                             bounds);
308         } else {
309             minX = src.getMinX() + lpad;
310             maxX = src.getMaxX() - rpad;
311             minY = src.getMinY() + tpad;
312             maxY = src.getMaxY() - bpad;
313             iter = RandomIterFactory.create(src, src.getBounds());
314         }
315 
316         int kwidth = interp.getWidth();
317         int kheight = interp.getHeight();
318 
319         int dstWidth = dst.getWidth();
320         int dstHeight = dst.getHeight();
321         int dstBands = dst.getNumBands();
322 
323         int lineStride = dst.getScanlineStride();
324         int pixelStride = dst.getPixelStride();
325         int[] bandOffsets = dst.getBandOffsets();
326         short[][] data = dst.getShortDataArrays();
327 
328         int precH = 1 << interp.getSubsampleBitsH();
329         int precV = 1 << interp.getSubsampleBitsV();
330 
331         float[] warpData = new float[2 * dstWidth];
332 
333         int[][] samples = new int[kheight][kwidth];
334 
335         int lineOffset = 0;
336 
337 	short[] backgroundUShort = new short[dstBands];
338 	for (int i = 0; i < dstBands; i++)
339 	    backgroundUShort[i] = (short)backgroundValues[i];
340 
341         for (int h = 0; h < dstHeight; h++) {
342             int pixelOffset = lineOffset;
343             lineOffset += lineStride;
344 
345             warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
346 
347             int count = 0;
348             for (int w = 0; w < dstWidth; w++) {
349                 float sx = warpData[count++];
350                 float sy = warpData[count++];
351 
352                 int xint = floor(sx);
353                 int yint = floor(sy);
354                 int xfrac = (int)((sx - xint) * precH);
355                 int yfrac = (int)((sy - yint) * precV);
356 
357                 if (xint < minX || xint >= maxX ||
358                     yint < minY || yint >= maxY) {
359                     /* Fill with a background color. */
360                     if (setBackground) {
361                         for (int b = 0; b < dstBands; b++) {
362                             data[b][pixelOffset+bandOffsets[b]] =
363                                 backgroundUShort[b];
364                         }
365                     }
366                 } else {
367                     xint -= lpad;
368                     yint -= tpad;
369 
370                     for (int b = 0; b < dstBands; b++) {
371                         for (int j = 0; j < kheight; j++) {
372                             for (int i = 0; i < kwidth; i++) {
373                                 samples[j][i] = iter.getSample(
374                                     xint+i, yint+j, b) & 0xFFFF;
375                             }
376                         }
377 
378                         data[b][pixelOffset+bandOffsets[b]] =
379                             ImageUtil.clampUShort(
380                             interp.interpolate(samples, xfrac, yfrac));
381                     }
382                 }
383 
384                 pixelOffset += pixelStride;
385             }
386         }
387     }
388 
computeRectShort(PlanarImage src, RasterAccessor dst)389     private void computeRectShort(PlanarImage src, RasterAccessor dst) {
390         int lpad, rpad, tpad, bpad;
391         if(interp != null) {
392             lpad = interp.getLeftPadding();
393             rpad = interp.getRightPadding();
394             tpad = interp.getTopPadding();
395             bpad = interp.getBottomPadding();
396         } else {
397             lpad = rpad = tpad = bpad = 0;
398         }
399 
400         int minX, maxX, minY, maxY;
401         RandomIter iter;
402         if(extender != null) {
403             minX = src.getMinX();
404             maxX = src.getMaxX();
405             minY = src.getMinY();
406             maxY = src.getMaxY();
407             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
408                                              src.getMinY() - tpad,
409                                              src.getWidth() + lpad + rpad,
410                                              src.getHeight() + tpad + bpad);
411             iter = RandomIterFactory.create(src.getExtendedData(bounds,
412                                                                 extender),
413                                             bounds);
414         } else {
415             minX = src.getMinX() + lpad;
416             maxX = src.getMaxX() - rpad;
417             minY = src.getMinY() + tpad;
418             maxY = src.getMaxY() - bpad;
419             iter = RandomIterFactory.create(src, src.getBounds());
420         }
421 
422         int kwidth = interp.getWidth();
423         int kheight = interp.getHeight();
424 
425         int dstWidth = dst.getWidth();
426         int dstHeight = dst.getHeight();
427         int dstBands = dst.getNumBands();
428 
429         int lineStride = dst.getScanlineStride();
430         int pixelStride = dst.getPixelStride();
431         int[] bandOffsets = dst.getBandOffsets();
432         short[][] data = dst.getShortDataArrays();
433 
434         int precH = 1 << interp.getSubsampleBitsH();
435         int precV = 1 << interp.getSubsampleBitsV();
436 
437         float[] warpData = new float[2 * dstWidth];
438 
439         int[][] samples = new int[kheight][kwidth];
440 
441         int lineOffset = 0;
442 
443         short[] backgroundShort = new short[dstBands];
444 	for (int i = 0; i < dstBands; i++)
445 	    backgroundShort[i] = (short)backgroundValues[i];
446 
447         for (int h = 0; h < dstHeight; h++) {
448             int pixelOffset = lineOffset;
449             lineOffset += lineStride;
450 
451             warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
452 
453             int count = 0;
454             for (int w = 0; w < dstWidth; w++) {
455                 float sx = warpData[count++];
456                 float sy = warpData[count++];
457 
458                 int xint = floor(sx);
459                 int yint = floor(sy);
460                 int xfrac = (int)((sx - xint) * precH);
461                 int yfrac = (int)((sy - yint) * precV);
462 
463                 if (xint < minX || xint >= maxX ||
464                     yint < minY || yint >= maxY) {
465                     /* Fill with a background color. */
466                     if (setBackground) {
467                         for (int b = 0; b < dstBands; b++) {
468                             data[b][pixelOffset+bandOffsets[b]] =
469                                 backgroundShort[b];
470                         }
471                     }
472                 } else {
473                     xint -= lpad;
474                     yint -= tpad;
475 
476                     for (int b = 0; b < dstBands; b++) {
477                         for (int j = 0; j < kheight; j++) {
478                             for (int i = 0; i < kwidth; i++) {
479                                 samples[j][i] = iter.getSample(
480                                     xint+i, yint+j, b);
481                             }
482                         }
483 
484                         data[b][pixelOffset+bandOffsets[b]] =
485                             ImageUtil.clampShort(
486                             interp.interpolate(samples, xfrac, yfrac));
487                     }
488                 }
489 
490                 pixelOffset += pixelStride;
491             }
492         }
493     }
494 
computeRectInt(PlanarImage src, RasterAccessor dst)495     private void computeRectInt(PlanarImage src, RasterAccessor dst) {
496         int lpad, rpad, tpad, bpad;
497         if(interp != null) {
498             lpad = interp.getLeftPadding();
499             rpad = interp.getRightPadding();
500             tpad = interp.getTopPadding();
501             bpad = interp.getBottomPadding();
502         } else {
503             lpad = rpad = tpad = bpad = 0;
504         }
505 
506         int minX, maxX, minY, maxY;
507         RandomIter iter;
508         if(extender != null) {
509             minX = src.getMinX();
510             maxX = src.getMaxX();
511             minY = src.getMinY();
512             maxY = src.getMaxY();
513             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
514                                              src.getMinY() - tpad,
515                                              src.getWidth() + lpad + rpad,
516                                              src.getHeight() + tpad + bpad);
517             iter = RandomIterFactory.create(src.getExtendedData(bounds,
518                                                                 extender),
519                                             bounds);
520         } else {
521             minX = src.getMinX() + lpad;
522             maxX = src.getMaxX() - rpad;
523             minY = src.getMinY() + tpad;
524             maxY = src.getMaxY() - bpad;
525             iter = RandomIterFactory.create(src, src.getBounds());
526         }
527 
528         int kwidth = interp.getWidth();
529         int kheight = interp.getHeight();
530 
531         int dstWidth = dst.getWidth();
532         int dstHeight = dst.getHeight();
533         int dstBands = dst.getNumBands();
534 
535         int lineStride = dst.getScanlineStride();
536         int pixelStride = dst.getPixelStride();
537         int[] bandOffsets = dst.getBandOffsets();
538         int[][] data = dst.getIntDataArrays();
539 
540         int precH = 1 << interp.getSubsampleBitsH();
541         int precV = 1 << interp.getSubsampleBitsV();
542 
543         float[] warpData = new float[2 * dstWidth];
544 
545         int[][] samples = new int[kheight][kwidth];
546 
547         int lineOffset = 0;
548 
549 	int[] backgroundInt = new int[dstBands];
550 	for (int i = 0; i < dstBands; i++)
551 	    backgroundInt[i] = (int)backgroundValues[i];
552 
553         for (int h = 0; h < dstHeight; h++) {
554             int pixelOffset = lineOffset;
555             lineOffset += lineStride;
556 
557             warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
558 
559             int count = 0;
560             for (int w = 0; w < dstWidth; w++) {
561                 float sx = warpData[count++];
562                 float sy = warpData[count++];
563 
564                 int xint = floor(sx);
565                 int yint = floor(sy);
566                 int xfrac = (int)((sx - xint) * precH);
567                 int yfrac = (int)((sy - yint) * precV);
568 
569                 if (xint < minX || xint >= maxX ||
570                     yint < minY || yint >= maxY) {
571                     /* Fill with a background color. */
572                     if (setBackground) {
573                         for (int b = 0; b < dstBands; b++) {
574                             data[b][pixelOffset+bandOffsets[b]] =
575                                 backgroundInt[b];
576                         }
577                     }
578                 } else {
579                     xint -= lpad;
580                     yint -= tpad;
581 
582                     for (int b = 0; b < dstBands; b++) {
583                         for (int j = 0; j < kheight; j++) {
584                             for (int i = 0; i < kwidth; i++) {
585                                 samples[j][i] = iter.getSample(
586                                     xint+i, yint+j, b);
587                             }
588                         }
589 
590                         data[b][pixelOffset+bandOffsets[b]] =
591                             interp.interpolate(samples, xfrac, yfrac);
592                     }
593                 }
594 
595                 pixelOffset += pixelStride;
596             }
597         }
598     }
599 
computeRectFloat(PlanarImage src, RasterAccessor dst)600     private void computeRectFloat(PlanarImage src, RasterAccessor dst) {
601         int lpad, rpad, tpad, bpad;
602         if(interp != null) {
603             lpad = interp.getLeftPadding();
604             rpad = interp.getRightPadding();
605             tpad = interp.getTopPadding();
606             bpad = interp.getBottomPadding();
607         } else {
608             lpad = rpad = tpad = bpad = 0;
609         }
610 
611         int minX, maxX, minY, maxY;
612         RandomIter iter;
613         if(extender != null) {
614             minX = src.getMinX();
615             maxX = src.getMaxX();
616             minY = src.getMinY();
617             maxY = src.getMaxY();
618             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
619                                              src.getMinY() - tpad,
620                                              src.getWidth() + lpad + rpad,
621                                              src.getHeight() + tpad + bpad);
622             iter = RandomIterFactory.create(src.getExtendedData(bounds,
623                                                                 extender),
624                                             bounds);
625         } else {
626             minX = src.getMinX() + lpad;
627             maxX = src.getMaxX() - rpad;
628             minY = src.getMinY() + tpad;
629             maxY = src.getMaxY() - bpad;
630             iter = RandomIterFactory.create(src, src.getBounds());
631         }
632 
633         int kwidth = interp.getWidth();
634         int kheight = interp.getHeight();
635 
636         int dstWidth = dst.getWidth();
637         int dstHeight = dst.getHeight();
638         int dstBands = dst.getNumBands();
639 
640         int lineStride = dst.getScanlineStride();
641         int pixelStride = dst.getPixelStride();
642         int[] bandOffsets = dst.getBandOffsets();
643         float[][] data = dst.getFloatDataArrays();
644 
645         float[] warpData = new float[2 * dstWidth];
646 
647         float[][] samples = new float[kheight][kwidth];
648 
649         int lineOffset = 0;
650 
651         float[] backgroundFloat = new float[dstBands];
652 	for (int i = 0; i < dstBands; i++)
653 	    backgroundFloat[i] = (float)backgroundValues[i];
654 
655         for (int h = 0; h < dstHeight; h++) {
656             int pixelOffset = lineOffset;
657             lineOffset += lineStride;
658 
659             warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
660 
661             int count = 0;
662             for (int w = 0; w < dstWidth; w++) {
663                 float sx = warpData[count++];
664                 float sy = warpData[count++];
665 
666                 int xint = floor(sx);
667                 int yint = floor(sy);
668                 float xfrac = sx - xint;
669                 float yfrac = sy - yint;
670 
671                 if (xint < minX || xint >= maxX ||
672                     yint < minY || yint >= maxY) {
673                     /* Fill with a background color. */
674                     if (setBackground) {
675                         for (int b = 0; b < dstBands; b++) {
676                             data[b][pixelOffset+bandOffsets[b]] =
677                                 backgroundFloat[b];
678                         }
679                     }
680                 } else {
681                     xint -= lpad;
682                     yint -= tpad;
683 
684                     for (int b = 0; b < dstBands; b++) {
685                         for (int j = 0; j < kheight; j++) {
686                             for (int i = 0; i < kwidth; i++) {
687                                 samples[j][i] = iter.getSampleFloat(
688                                     xint+i, yint+j, b);
689                             }
690                         }
691 
692                         data[b][pixelOffset+bandOffsets[b]] =
693                             interp.interpolate(samples, xfrac, yfrac);
694                     }
695                 }
696 
697                 pixelOffset += pixelStride;
698             }
699         }
700     }
701 
computeRectDouble(PlanarImage src, RasterAccessor dst)702     private void computeRectDouble(PlanarImage src, RasterAccessor dst) {
703         int lpad, rpad, tpad, bpad;
704         if(interp != null) {
705             lpad = interp.getLeftPadding();
706             rpad = interp.getRightPadding();
707             tpad = interp.getTopPadding();
708             bpad = interp.getBottomPadding();
709         } else {
710             lpad = rpad = tpad = bpad = 0;
711         }
712 
713         int minX, maxX, minY, maxY;
714         RandomIter iter;
715         if(extender != null) {
716             minX = src.getMinX();
717             maxX = src.getMaxX();
718             minY = src.getMinY();
719             maxY = src.getMaxY();
720             Rectangle bounds = new Rectangle(src.getMinX() - lpad,
721                                              src.getMinY() - tpad,
722                                              src.getWidth() + lpad + rpad,
723                                              src.getHeight() + tpad + bpad);
724             iter = RandomIterFactory.create(src.getExtendedData(bounds,
725                                                                 extender),
726                                             bounds);
727         } else {
728             minX = src.getMinX() + lpad;
729             maxX = src.getMaxX() - rpad;
730             minY = src.getMinY() + tpad;
731             maxY = src.getMaxY() - bpad;
732             iter = RandomIterFactory.create(src, src.getBounds());
733         }
734 
735         int kwidth = interp.getWidth();
736         int kheight = interp.getHeight();
737 
738         int dstWidth = dst.getWidth();
739         int dstHeight = dst.getHeight();
740         int dstBands = dst.getNumBands();
741 
742         int lineStride = dst.getScanlineStride();
743         int pixelStride = dst.getPixelStride();
744         int[] bandOffsets = dst.getBandOffsets();
745         double[][] data = dst.getDoubleDataArrays();
746 
747         float[] warpData = new float[2 * dstWidth];
748 
749         double[][] samples = new double[kheight][kwidth];
750 
751         int lineOffset = 0;
752 
753         for (int h = 0; h < dstHeight; h++) {
754             int pixelOffset = lineOffset;
755             lineOffset += lineStride;
756 
757             warp.warpRect(dst.getX(), dst.getY()+h, dstWidth, 1, warpData);
758 
759             int count = 0;
760             for (int w = 0; w < dstWidth; w++) {
761                 float sx = warpData[count++];
762                 float sy = warpData[count++];
763 
764                 int xint = floor(sx);
765                 int yint = floor(sy);
766                 float xfrac = sx - xint;
767                 float yfrac = sy - yint;
768 
769                 if (xint < minX || xint >= maxX ||
770                     yint < minY || yint >= maxY) {
771                     /* Fill with a background color. */
772                     if (setBackground) {
773                         for (int b = 0; b < dstBands; b++) {
774                             data[b][pixelOffset+bandOffsets[b]] =
775                                 backgroundValues[b];
776                         }
777                     }
778                 } else {
779                     xint -= lpad;
780                     yint -= tpad;
781 
782                     for (int b = 0; b < dstBands; b++) {
783                         for (int j = 0; j < kheight; j++) {
784                             for (int i = 0; i < kwidth; i++) {
785                                 samples[j][i] = iter.getSampleDouble(
786                                     xint+i, yint+j, b);
787                             }
788                         }
789 
790                         data[b][pixelOffset+bandOffsets[b]] =
791                             interp.interpolate(samples, xfrac, yfrac);
792                     }
793                 }
794 
795                 pixelOffset += pixelStride;
796             }
797         }
798     }
799 
800     /** Returns the "floor" value of a float. */
floor(float f)801     private static final int floor(float f) {
802         return f >= 0 ? (int)f : (int)f - 1;
803     }
804 }
805