001: /*
002: * $RCSfile: ScaleGeneralOpImage.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:42 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Rectangle;
015: import java.awt.image.DataBuffer;
016: import java.awt.image.Raster;
017: import java.awt.image.RenderedImage;
018: import java.awt.image.WritableRaster;
019: import java.awt.image.renderable.ParameterBlock;
020: import javax.media.jai.BorderExtender;
021: import javax.media.jai.ImageLayout;
022: import javax.media.jai.Interpolation;
023: import javax.media.jai.OpImage;
024: import javax.media.jai.PlanarImage;
025: import javax.media.jai.RasterAccessor;
026: import javax.media.jai.RasterFormatTag;
027: import javax.media.jai.ScaleOpImage;
028: import java.util.Map;
029: import com.sun.media.jai.util.Rational;
030:
031: /**
032: * An <code>OpImage</code> that performs scaling using a general interpolation.
033: *
034: */
035: final class ScaleGeneralOpImage extends ScaleOpImage {
036:
037: /* The number of subsampleBits */
038: private int subsampleBits;
039:
040: /* 2 ^ subsampleBits */
041: private int one;
042:
043: Rational half = new Rational(1, 2);
044:
045: // Interpolation kernel related information.
046: private int interp_width, interp_height, interp_left, interp_top;
047:
048: long invScaleYInt, invScaleYFrac;
049: long invScaleXInt, invScaleXFrac;
050:
051: /**
052: * Constructs a ScaleGeneralOpImage from a RenderedImage source,
053: *
054: * @param source a RenderedImage.
055: * @param extender a BorderExtender, or null.
056:
057: * @param layout an ImageLayout optionally containing the tile grid layout,
058: * SampleModel, and ColorModel, or null.
059: * @param xScale scale factor along x axis.
060: * @param yScale scale factor along y axis.
061: * @param xTrans translation factor along x axis.
062: * @param yTrans translation factor along y axis.
063: * @param interp a Interpolation object to use for resampling.
064: */
065: public ScaleGeneralOpImage(RenderedImage source,
066: BorderExtender extender, Map config, ImageLayout layout,
067: float xScale, float yScale, float xTrans, float yTrans,
068: Interpolation interp) {
069:
070: super (source, layout, config, true, extender, interp, xScale,
071: yScale, xTrans, yTrans);
072:
073: subsampleBits = interp.getSubsampleBitsH();
074:
075: // Internal precision required for position calculations
076: one = 1 << subsampleBits;
077:
078: // Get the width and height and padding of the Interpolation kernel.
079: interp_width = interp.getWidth();
080: interp_height = interp.getHeight();
081: interp_left = interp.getLeftPadding();
082: interp_top = interp.getTopPadding();
083:
084: if (invScaleYRational.num > invScaleYRational.denom) {
085: invScaleYInt = invScaleYRational.num
086: / invScaleYRational.denom;
087: invScaleYFrac = invScaleYRational.num
088: % invScaleYRational.denom;
089: } else {
090: invScaleYInt = 0;
091: invScaleYFrac = invScaleYRational.num;
092: }
093:
094: if (invScaleXRational.num > invScaleXRational.denom) {
095: invScaleXInt = invScaleXRational.num
096: / invScaleXRational.denom;
097: invScaleXFrac = invScaleXRational.num
098: % invScaleXRational.denom;
099: } else {
100: invScaleXInt = 0;
101: invScaleXFrac = invScaleXRational.num;
102: }
103: }
104:
105: /**
106: * Performs a scale operation on a specified rectangle. The sources are
107: * cobbled.
108: *
109: * @param sources an array of source Rasters, guaranteed to provide all
110: * necessary source data for computing the output.
111: * @param dest a WritableRaster containing the area to be computed.
112: * @param destRect the rectangle within dest to be processed.
113: */
114: protected void computeRect(Raster[] sources, WritableRaster dest,
115: Rectangle destRect) {
116: // Retrieve format tags.
117: RasterFormatTag[] formatTags = getFormatTags();
118:
119: Raster source = sources[0];
120: // Get the source rectangle
121: Rectangle srcRect = source.getBounds();
122:
123: RasterAccessor srcAccessor = new RasterAccessor(source,
124: srcRect, formatTags[0], getSource(0).getColorModel());
125:
126: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
127: formatTags[1], getColorModel());
128:
129: int dwidth = destRect.width;
130: int dheight = destRect.height;
131: int srcPixelStride = srcAccessor.getPixelStride();
132: int srcScanlineStride = srcAccessor.getScanlineStride();
133:
134: int[] ypos = new int[dheight];
135: int[] xpos = new int[dwidth];
136:
137: int xfracvalues[] = null, yfracvalues[] = null;
138: float xfracvaluesFloat[] = null, yfracvaluesFloat[] = null;
139:
140: switch (dstAccessor.getDataType()) {
141: case DataBuffer.TYPE_BYTE:
142: case DataBuffer.TYPE_SHORT:
143: case DataBuffer.TYPE_USHORT:
144: case DataBuffer.TYPE_INT:
145: yfracvalues = new int[dheight];
146: xfracvalues = new int[dwidth];
147: preComputePositionsInt(destRect, srcRect.x, srcRect.y,
148: srcPixelStride, srcScanlineStride, xpos, ypos,
149: xfracvalues, yfracvalues);
150: break;
151:
152: case DataBuffer.TYPE_FLOAT:
153: case DataBuffer.TYPE_DOUBLE:
154: yfracvaluesFloat = new float[dheight];
155: xfracvaluesFloat = new float[dwidth];
156: preComputePositionsFloat(destRect, srcRect.x, srcRect.y,
157: srcPixelStride, srcScanlineStride, xpos, ypos,
158: xfracvaluesFloat, yfracvaluesFloat);
159: break;
160:
161: default:
162: throw new RuntimeException(JaiI18N
163: .getString("OrderedDitherOpImage0"));
164: }
165:
166: switch (dstAccessor.getDataType()) {
167:
168: case DataBuffer.TYPE_BYTE:
169: byteLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
170: xfracvalues, yfracvalues);
171: break;
172:
173: case DataBuffer.TYPE_SHORT:
174: shortLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
175: xfracvalues, yfracvalues);
176: break;
177:
178: case DataBuffer.TYPE_USHORT:
179: ushortLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
180: xfracvalues, yfracvalues);
181: break;
182:
183: case DataBuffer.TYPE_INT:
184: intLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
185: xfracvalues, yfracvalues);
186: break;
187:
188: case DataBuffer.TYPE_FLOAT:
189: floatLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
190: xfracvaluesFloat, yfracvaluesFloat);
191: break;
192:
193: case DataBuffer.TYPE_DOUBLE:
194: doubleLoop(srcAccessor, destRect, dstAccessor, xpos, ypos,
195: xfracvaluesFloat, yfracvaluesFloat);
196: break;
197:
198: default:
199: throw new RuntimeException(JaiI18N
200: .getString("OrderedDitherOpImage0"));
201: }
202:
203: // If the RasterAccessor object set up a temporary buffer for the
204: // op to write to, tell the RasterAccessor to write that data
205: // to the raster now that we're done with it.
206: if (dstAccessor.isDataCopy()) {
207: dstAccessor.clampDataArrays();
208: dstAccessor.copyDataToRaster();
209: }
210: }
211:
212: private void preComputePositionsInt(Rectangle destRect,
213: int srcRectX, int srcRectY, int srcPixelStride,
214: int srcScanlineStride, int xpos[], int ypos[],
215: int xfracvalues[], int yfracvalues[]) {
216:
217: int dwidth = destRect.width;
218: int dheight = destRect.height;
219:
220: // Loop variables based on the destination rectangle to be calculated.
221: int dx = destRect.x;
222: int dy = destRect.y;
223:
224: long syNum = dy, syDenom = 1;
225:
226: // Subtract the X translation factor sy -= transY
227: syNum = syNum * transYRationalDenom - transYRationalNum
228: * syDenom;
229: syDenom *= transYRationalDenom;
230:
231: // Add 0.5
232: syNum = 2 * syNum + syDenom;
233: syDenom *= 2;
234:
235: // Multply by invScaleX
236: syNum *= invScaleYRationalNum;
237: syDenom *= invScaleYRationalDenom;
238:
239: // Subtract 0.5
240: syNum = 2 * syNum - syDenom;
241: syDenom *= 2;
242:
243: // Separate the x source coordinate into integer and fractional part
244: int srcYInt = Rational.floor(syNum, syDenom);
245: long srcYFrac = syNum % syDenom;
246: if (srcYInt < 0) {
247: srcYFrac = syDenom + srcYFrac;
248: }
249:
250: // Normalize - Get a common denominator for the fracs of
251: // src and invScaleY
252: long commonYDenom = syDenom * invScaleYRationalDenom;
253: srcYFrac *= invScaleYRationalDenom;
254: long newInvScaleYFrac = invScaleYFrac * syDenom;
255:
256: // Precalculate the x positions and store them in an array.
257: long sxNum = dx, sxDenom = 1;
258:
259: // Subtract the X translation factor sx -= transX
260: sxNum = sxNum * transXRationalDenom - transXRationalNum
261: * sxDenom;
262: sxDenom *= transXRationalDenom;
263:
264: // Add 0.5
265: sxNum = 2 * sxNum + sxDenom;
266: sxDenom *= 2;
267:
268: // Multply by invScaleX
269: sxNum *= invScaleXRationalNum;
270: sxDenom *= invScaleXRationalDenom;
271:
272: // Subtract 0.5
273: sxNum = 2 * sxNum - sxDenom;
274: sxDenom *= 2;
275:
276: // Separate the x source coordinate into integer and fractional part
277: int srcXInt = Rational.floor(sxNum, sxDenom);
278: long srcXFrac = sxNum % sxDenom;
279: if (srcXInt < 0) {
280: srcXFrac = sxDenom + srcXFrac;
281: }
282:
283: // Normalize - Get a common denominator for the fracs of
284: // src and invScaleX
285: long commonXDenom = sxDenom * invScaleXRationalDenom;
286: srcXFrac *= invScaleXRationalDenom;
287: long newInvScaleXFrac = invScaleXFrac * sxDenom;
288:
289: for (int i = 0; i < dwidth; i++) {
290: xpos[i] = (srcXInt - srcRectX) * srcPixelStride;
291: xfracvalues[i] = (int) (((float) srcXFrac / (float) commonXDenom) * one);
292:
293: // Move onto the next source pixel.
294:
295: // Add the integral part of invScaleX to the integral part
296: // of srcX
297: srcXInt += invScaleXInt;
298:
299: // Add the fractional part of invScaleX to the fractional part
300: // of srcX
301: srcXFrac += newInvScaleXFrac;
302:
303: // If the fractional part is now greater than equal to the
304: // denominator, divide so as to reduce the numerator to be less
305: // than the denominator and add the overflow to the integral part.
306: if (srcXFrac >= commonXDenom) {
307: srcXInt += 1;
308: srcXFrac -= commonXDenom;
309: }
310: }
311:
312: for (int i = 0; i < dheight; i++) {
313:
314: // Calculate the source position in the source data array.
315: ypos[i] = (srcYInt - srcRectY) * srcScanlineStride;
316:
317: // Calculate the yfrac value
318: yfracvalues[i] = (int) (((float) srcYFrac / (float) commonYDenom) * one);
319:
320: // Move onto the next source pixel.
321:
322: // Add the integral part of invScaleY to the integral part
323: // of srcY
324: srcYInt += invScaleYInt;
325:
326: // Add the fractional part of invScaleY to the fractional part
327: // of srcY
328: srcYFrac += newInvScaleYFrac;
329:
330: // If the fractional part is now greater than equal to the
331: // denominator, divide so as to reduce the numerator to be less
332: // than the denominator and add the overflow to the integral part.
333: if (srcYFrac >= commonYDenom) {
334: srcYInt += 1;
335: srcYFrac -= commonYDenom;
336: }
337: }
338: }
339:
340: private void preComputePositionsFloat(Rectangle destRect,
341: int srcRectX, int srcRectY, int srcPixelStride,
342: int srcScanlineStride, int xpos[], int ypos[],
343: float xfracvaluesFloat[], float yfracvaluesFloat[]) {
344:
345: int dwidth = destRect.width;
346: int dheight = destRect.height;
347:
348: // Loop variables based on the destination rectangle to be calculated.
349: int dx = destRect.x;
350: int dy = destRect.y;
351:
352: long syNum = dy, syDenom = 1;
353:
354: // Subtract the X translation factor sy -= transY
355: syNum = syNum * transYRationalDenom - transYRationalNum
356: * syDenom;
357: syDenom *= transYRationalDenom;
358:
359: // Add 0.5
360: syNum = 2 * syNum + syDenom;
361: syDenom *= 2;
362:
363: // Multply by invScaleX
364: syNum *= invScaleYRationalNum;
365: syDenom *= invScaleYRationalDenom;
366:
367: // Subtract 0.5
368: syNum = 2 * syNum - syDenom;
369: syDenom *= 2;
370:
371: // Separate the x source coordinate into integer and fractional part
372: int srcYInt = Rational.floor(syNum, syDenom);
373: long srcYFrac = syNum % syDenom;
374: if (srcYInt < 0) {
375: srcYFrac = syDenom + srcYFrac;
376: }
377:
378: // Normalize - Get a common denominator for the fracs of
379: // src and invScaleY
380: long commonYDenom = syDenom * invScaleYRationalDenom;
381: srcYFrac *= invScaleYRationalDenom;
382: long newInvScaleYFrac = invScaleYFrac * syDenom;
383:
384: // Precalculate the x positions and store them in an array.
385: long sxNum = dx, sxDenom = 1;
386:
387: // Subtract the X translation factor sx -= transX
388: sxNum = sxNum * transXRationalDenom - transXRationalNum
389: * sxDenom;
390: sxDenom *= transXRationalDenom;
391:
392: // Add 0.5
393: sxNum = 2 * sxNum + sxDenom;
394: sxDenom *= 2;
395:
396: // Multply by invScaleX
397: sxNum *= invScaleXRationalNum;
398: sxDenom *= invScaleXRationalDenom;
399:
400: // Subtract 0.5
401: sxNum = 2 * sxNum - sxDenom;
402: sxDenom *= 2;
403:
404: // Separate the x source coordinate into integer and fractional part
405: int srcXInt = Rational.floor(sxNum, sxDenom);
406: long srcXFrac = sxNum % sxDenom;
407: if (srcXInt < 0) {
408: srcXFrac = sxDenom + srcXFrac;
409: }
410:
411: // Normalize - Get a common denominator for the fracs of
412: // src and invScaleX
413: long commonXDenom = sxDenom * invScaleXRationalDenom;
414: srcXFrac *= invScaleXRationalDenom;
415: long newInvScaleXFrac = invScaleXFrac * sxDenom;
416:
417: for (int i = 0; i < dwidth; i++) {
418:
419: xpos[i] = (srcXInt - srcRectX) * srcPixelStride;
420: xfracvaluesFloat[i] = (float) srcXFrac
421: / (float) commonXDenom;
422:
423: // Move onto the next source pixel.
424:
425: // Add the integral part of invScaleX to the integral part
426: // of srcX
427: srcXInt += invScaleXInt;
428:
429: // Add the fractional part of invScaleX to the fractional part
430: // of srcX
431: srcXFrac += newInvScaleXFrac;
432:
433: // If the fractional part is now greater than equal to the
434: // denominator, divide so as to reduce the numerator to be less
435: // than the denominator and add the overflow to the integral part.
436: if (srcXFrac >= commonXDenom) {
437: srcXInt += 1;
438: srcXFrac -= commonXDenom;
439: }
440: }
441:
442: for (int i = 0; i < dheight; i++) {
443:
444: // Calculate the source position in the source data array.
445: ypos[i] = (srcYInt - srcRectY) * srcScanlineStride;
446:
447: // Calculate the yfrac value
448: yfracvaluesFloat[i] = (float) srcYFrac
449: / (float) commonYDenom;
450:
451: // Move onto the next source pixel.
452:
453: // Add the integral part of invScaleY to the integral part
454: // of srcY
455: srcYInt += invScaleYInt;
456:
457: // Add the fractional part of invScaleY to the fractional part
458: // of srcY
459: srcYFrac += newInvScaleYFrac;
460:
461: // If the fractional part is now greater than equal to the
462: // denominator, divide so as to reduce the numerator to be less
463: // than the denominator and add the overflow to the integral part.
464: if (srcYFrac >= commonYDenom) {
465: srcYInt += 1;
466: srcYFrac -= commonYDenom;
467: }
468: }
469: }
470:
471: private void byteLoop(RasterAccessor src, Rectangle destRect,
472: RasterAccessor dst, int xpos[], int ypos[],
473: int xfracvalues[], int yfracvalues[]) {
474:
475: int srcPixelStride = src.getPixelStride();
476: int srcScanlineStride = src.getScanlineStride();
477:
478: int dwidth = destRect.width;
479: int dheight = destRect.height;
480: int dnumBands = dst.getNumBands();
481: byte dstDataArrays[][] = dst.getByteDataArrays();
482: int dstBandOffsets[] = dst.getBandOffsets();
483: int dstPixelStride = dst.getPixelStride();
484: int dstScanlineStride = dst.getScanlineStride();
485:
486: byte srcDataArrays[][] = src.getByteDataArrays();
487: int bandOffsets[] = src.getBandOffsets();
488:
489: int dstOffset = 0;
490:
491: // Number of samples required for the interpolation
492: int samples[][] = new int[interp_height][interp_width];
493: int xfrac, yfrac;
494: int s;
495: int posx, posy;
496:
497: // Putting band loop outside
498: for (int k = 0; k < dnumBands; k++) {
499: byte dstData[] = dstDataArrays[k];
500: byte srcData[] = srcDataArrays[k];
501: int dstScanlineOffset = dstBandOffsets[k];
502: int bandOffset = bandOffsets[k];
503:
504: for (int j = 0; j < dheight; j++) {
505:
506: int dstPixelOffset = dstScanlineOffset;
507: yfrac = yfracvalues[j];
508:
509: posy = ypos[j] + bandOffset;
510:
511: for (int i = 0; i < dwidth; i++) {
512: xfrac = xfracvalues[i];
513: posx = xpos[i];
514:
515: // Get the required number of surrounding sample values
516: // and put them in the samples array
517:
518: int start = interp_left * srcPixelStride
519: + interp_top * srcScanlineStride;
520: start = posx + posy - start;
521: int countH = 0, countV = 0;
522:
523: for (int yloop = 0; yloop < interp_height; yloop++) {
524:
525: int startY = start;
526:
527: for (int xloop = 0; xloop < interp_width; xloop++) {
528: samples[countV][countH++] = srcData[start] & 0xff;
529: start += srcPixelStride;
530: }
531:
532: countV++;
533: countH = 0;
534: start = startY + srcScanlineStride;
535: }
536:
537: // Perform the interpolation
538: s = interp.interpolate(samples, xfrac, yfrac);
539:
540: // clamp the value to byte range
541: if (s > 255) {
542: s = 255;
543: } else if (s < 0) {
544: s = 0;
545: }
546:
547: dstData[dstPixelOffset] = (byte) (s & 0xff);
548: dstPixelOffset += dstPixelStride;
549: }
550: dstScanlineOffset += dstScanlineStride;
551: }
552: }
553: }
554:
555: private void shortLoop(RasterAccessor src, Rectangle destRect,
556: RasterAccessor dst, int xpos[], int ypos[],
557: int xfracvalues[], int yfracvalues[]) {
558:
559: int srcPixelStride = src.getPixelStride();
560: int srcScanlineStride = src.getScanlineStride();
561:
562: int dwidth = destRect.width;
563: int dheight = destRect.height;
564: int dnumBands = dst.getNumBands();
565: short dstDataArrays[][] = dst.getShortDataArrays();
566: int dstBandOffsets[] = dst.getBandOffsets();
567: int dstPixelStride = dst.getPixelStride();
568: int dstScanlineStride = dst.getScanlineStride();
569:
570: short srcDataArrays[][] = src.getShortDataArrays();
571: int bandOffsets[] = src.getBandOffsets();
572:
573: int dstOffset = 0;
574:
575: // Number of samples required for the interpolation
576: int samples[][] = new int[interp_height][interp_width];
577:
578: int posy, posx;
579: int xfrac, yfrac;
580: int s;
581:
582: // Putting band loop outside
583: for (int k = 0; k < dnumBands; k++) {
584: short dstData[] = dstDataArrays[k];
585: short srcData[] = srcDataArrays[k];
586: int dstScanlineOffset = dstBandOffsets[k];
587: int bandOffset = bandOffsets[k];
588:
589: for (int j = 0; j < dheight; j++) {
590:
591: int dstPixelOffset = dstScanlineOffset;
592: yfrac = yfracvalues[j];
593: posy = ypos[j] + bandOffset;
594:
595: for (int i = 0; i < dwidth; i++) {
596: xfrac = xfracvalues[i];
597: posx = xpos[i];
598:
599: // Get the required number of surrounding sample values
600: int start = interp_left * srcPixelStride
601: + interp_top * srcScanlineStride;
602: start = posx + posy - start;
603: int countH = 0, countV = 0;
604:
605: for (int yloop = 0; yloop < interp_height; yloop++) {
606:
607: int startY = start;
608:
609: for (int xloop = 0; xloop < interp_width; xloop++) {
610: samples[countV][countH++] = srcData[start];
611: start += srcPixelStride;
612: }
613:
614: countV++;
615: countH = 0;
616: start = startY + srcScanlineStride;
617: }
618:
619: s = interp.interpolate(samples, xfrac, yfrac);
620:
621: // clamp the value to short range
622: if (s > Short.MAX_VALUE) {
623: s = Short.MAX_VALUE;
624: } else if (s < Short.MIN_VALUE) {
625: s = Short.MIN_VALUE;
626: }
627:
628: dstData[dstPixelOffset] = (short) s;
629: dstPixelOffset += dstPixelStride;
630: }
631: dstScanlineOffset += dstScanlineStride;
632: }
633: }
634: }
635:
636: private void ushortLoop(RasterAccessor src, Rectangle destRect,
637: RasterAccessor dst, int xpos[], int ypos[],
638: int xfracvalues[], int yfracvalues[]) {
639:
640: int srcPixelStride = src.getPixelStride();
641: int srcScanlineStride = src.getScanlineStride();
642:
643: int dwidth = destRect.width;
644: int dheight = destRect.height;
645: int dnumBands = dst.getNumBands();
646: short dstDataArrays[][] = dst.getShortDataArrays();
647: int dstBandOffsets[] = dst.getBandOffsets();
648: int dstPixelStride = dst.getPixelStride();
649: int dstScanlineStride = dst.getScanlineStride();
650:
651: short srcDataArrays[][] = src.getShortDataArrays();
652: int bandOffsets[] = src.getBandOffsets();
653:
654: int dstOffset = 0;
655:
656: // Number of samples required for the interpolation
657: int samples[][] = new int[interp_height][interp_width];
658: int posy, posx;
659: int xfrac, yfrac;
660: int s;
661:
662: // Putting band loop outside
663: for (int k = 0; k < dnumBands; k++) {
664:
665: short dstData[] = dstDataArrays[k];
666: short srcData[] = srcDataArrays[k];
667: int dstScanlineOffset = dstBandOffsets[k];
668: int bandOffset = bandOffsets[k];
669:
670: for (int j = 0; j < dheight; j++) {
671:
672: int dstPixelOffset = dstScanlineOffset;
673: yfrac = yfracvalues[j];
674: posy = ypos[j] + bandOffset;
675:
676: for (int i = 0; i < dwidth; i++) {
677:
678: xfrac = xfracvalues[i];
679: posx = xpos[i];
680:
681: // Get the required number of surrounding sample values
682: int start = interp_left * srcPixelStride
683: + interp_top * srcScanlineStride;
684: start = posx + posy - start;
685: int countH = 0, countV = 0;
686: for (int yloop = 0; yloop < interp_height; yloop++) {
687:
688: int startY = start;
689:
690: for (int xloop = 0; xloop < interp_width; xloop++) {
691: samples[countV][countH++] = srcData[start] & 0xffff;
692: start += srcPixelStride;
693: }
694:
695: countV++;
696: countH = 0;
697: start = startY + srcScanlineStride;
698: }
699:
700: s = interp.interpolate(samples, xfrac, yfrac);
701:
702: // clamp the value to ushort range
703: if (s > 65536) {
704: s = 65536;
705: } else if (s < 0) {
706: s = 0;
707: }
708:
709: dstData[dstPixelOffset] = (short) (s & 0xffff);
710: dstPixelOffset += dstPixelStride;
711: }
712: dstScanlineOffset += dstScanlineStride;
713: }
714: }
715: }
716:
717: // identical to byteLoops, except datatypes have changed. clumsy,
718: // but there's no other way in Java
719: private void intLoop(RasterAccessor src, Rectangle destRect,
720: RasterAccessor dst, int xpos[], int ypos[],
721: int xfracvalues[], int yfracvalues[]) {
722:
723: int srcPixelStride = src.getPixelStride();
724: int srcScanlineStride = src.getScanlineStride();
725:
726: int dwidth = destRect.width;
727: int dheight = destRect.height;
728: int dnumBands = dst.getNumBands();
729: int dstDataArrays[][] = dst.getIntDataArrays();
730: int dstBandOffsets[] = dst.getBandOffsets();
731: int dstPixelStride = dst.getPixelStride();
732: int dstScanlineStride = dst.getScanlineStride();
733:
734: int srcDataArrays[][] = src.getIntDataArrays();
735: int bandOffsets[] = src.getBandOffsets();
736:
737: int dstOffset = 0;
738:
739: // Number of samples required for the interpolation
740: int samples[][] = new int[interp_height][interp_width];
741: int posy, posx;
742: int xfrac, yfrac;
743: int s;
744:
745: // Putting band loop outside
746: for (int k = 0; k < dnumBands; k++) {
747:
748: int dstData[] = dstDataArrays[k];
749: int srcData[] = srcDataArrays[k];
750: int dstScanlineOffset = dstBandOffsets[k];
751: int bandOffset = bandOffsets[k];
752:
753: for (int j = 0; j < dheight; j++) {
754:
755: int dstPixelOffset = dstScanlineOffset;
756: yfrac = yfracvalues[j];
757: posy = ypos[j] + bandOffset;
758:
759: for (int i = 0; i < dwidth; i++) {
760:
761: xfrac = xfracvalues[i];
762: posx = xpos[i];
763:
764: // Get the required number of surrounding sample values
765: int start = interp_left * srcPixelStride
766: + interp_top * srcScanlineStride;
767: start = posx + posy - start;
768: int countH = 0, countV = 0;
769: for (int yloop = 0; yloop < interp_height; yloop++) {
770:
771: int startY = start;
772:
773: for (int xloop = 0; xloop < interp_width; xloop++) {
774: samples[countV][countH++] = srcData[start];
775: start += srcPixelStride;
776: }
777:
778: countV++;
779: countH = 0;
780: start = startY + srcScanlineStride;
781: }
782:
783: s = interp.interpolate(samples, xfrac, yfrac);
784:
785: dstData[dstPixelOffset] = s;
786: dstPixelOffset += dstPixelStride;
787: }
788: dstScanlineOffset += dstScanlineStride;
789: }
790: }
791: }
792:
793: private void floatLoop(RasterAccessor src, Rectangle destRect,
794: RasterAccessor dst, int xpos[], int ypos[],
795: float xfracvaluesFloat[], float yfracvaluesFloat[]) {
796:
797: int srcPixelStride = src.getPixelStride();
798: int srcScanlineStride = src.getScanlineStride();
799:
800: int dwidth = destRect.width;
801: int dheight = destRect.height;
802: int dnumBands = dst.getNumBands();
803: float dstDataArrays[][] = dst.getFloatDataArrays();
804: int dstBandOffsets[] = dst.getBandOffsets();
805: int dstPixelStride = dst.getPixelStride();
806: int dstScanlineStride = dst.getScanlineStride();
807:
808: float srcDataArrays[][] = src.getFloatDataArrays();
809: int bandOffsets[] = src.getBandOffsets();
810:
811: int dstOffset = 0;
812:
813: // Number of samples required for the interpolation
814: float samples[][] = new float[interp_height][interp_width];
815:
816: int posy, posx;
817: float xfrac, yfrac;
818: float s;
819:
820: // Putting band loop outside
821: for (int k = 0; k < dnumBands; k++) {
822:
823: float dstData[] = dstDataArrays[k];
824: float srcData[] = srcDataArrays[k];
825: int dstScanlineOffset = dstBandOffsets[k];
826: int bandOffset = bandOffsets[k];
827:
828: for (int j = 0; j < dheight; j++) {
829:
830: int dstPixelOffset = dstScanlineOffset;
831: yfrac = yfracvaluesFloat[j];
832: posy = ypos[j] + bandOffset;
833:
834: for (int i = 0; i < dwidth; i++) {
835:
836: xfrac = xfracvaluesFloat[i];
837: posx = xpos[i];
838:
839: // Get the required number of surrounding sample values
840: int start = interp_left * srcPixelStride
841: + interp_top * srcScanlineStride;
842: start = posx + posy - start;
843: int countH = 0, countV = 0;
844: for (int yloop = 0; yloop < interp_height; yloop++) {
845:
846: int startY = start;
847:
848: for (int xloop = 0; xloop < interp_width; xloop++) {
849: samples[countV][countH++] = srcData[start];
850: start += srcPixelStride;
851: }
852:
853: countV++;
854: countH = 0;
855: start = startY + srcScanlineStride;
856: }
857:
858: s = interp.interpolate(samples, xfrac, yfrac);
859:
860: if (s > Float.MAX_VALUE) {
861: s = Float.MAX_VALUE;
862: } else if (s < -Float.MAX_VALUE) {
863: s = -Float.MAX_VALUE;
864: }
865:
866: dstData[dstPixelOffset] = (float) s;
867: dstPixelOffset += dstPixelStride;
868: }
869: dstScanlineOffset += dstScanlineStride;
870: }
871: }
872: }
873:
874: private void doubleLoop(RasterAccessor src, Rectangle destRect,
875: RasterAccessor dst, int xpos[], int ypos[],
876: float xfracvaluesFloat[], float yfracvaluesFloat[]) {
877:
878: int srcPixelStride = src.getPixelStride();
879: int srcScanlineStride = src.getScanlineStride();
880:
881: int dwidth = destRect.width;
882: int dheight = destRect.height;
883: int dnumBands = dst.getNumBands();
884: double dstDataArrays[][] = dst.getDoubleDataArrays();
885: int dstBandOffsets[] = dst.getBandOffsets();
886: int dstPixelStride = dst.getPixelStride();
887: int dstScanlineStride = dst.getScanlineStride();
888:
889: double srcDataArrays[][] = src.getDoubleDataArrays();
890: int bandOffsets[] = src.getBandOffsets();
891:
892: int dstOffset = 0;
893:
894: // Number of samples required for the interpolation
895: double samples[][] = new double[interp_height][interp_width];
896:
897: int posy, posx;
898: double s;
899: float xfrac, yfrac;
900:
901: // Putting band loop outside
902: for (int k = 0; k < dnumBands; k++) {
903:
904: double dstData[] = dstDataArrays[k];
905: double srcData[] = srcDataArrays[k];
906: int dstScanlineOffset = dstBandOffsets[k];
907: int bandOffset = bandOffsets[k];
908:
909: for (int j = 0; j < dheight; j++) {
910:
911: int dstPixelOffset = dstScanlineOffset;
912: yfrac = yfracvaluesFloat[j];
913: posy = ypos[j] + bandOffset;
914:
915: for (int i = 0; i < dwidth; i++) {
916:
917: xfrac = xfracvaluesFloat[i];
918: posx = xpos[i];
919:
920: // Get the required number of surrounding sample values
921: int start = interp_left * srcPixelStride
922: + interp_top * srcScanlineStride;
923: start = posx + posy - start;
924: int countH = 0, countV = 0;
925: for (int yloop = 0; yloop < interp_height; yloop++) {
926:
927: int startY = start;
928:
929: for (int xloop = 0; xloop < interp_width; xloop++) {
930: samples[countV][countH++] = srcData[start];
931: start += srcPixelStride;
932: }
933:
934: countV++;
935: countH = 0;
936: start = startY + srcScanlineStride;
937: }
938:
939: s = interp.interpolate(samples, xfrac, yfrac);
940:
941: dstData[dstPixelOffset] = s;
942: dstPixelOffset += dstPixelStride;
943: }
944: dstScanlineOffset += dstScanlineStride;
945: }
946: }
947: }
948:
949: }
|