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