001: /*
002: * $RCSfile: TransposeOpImage.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.2 $
009: * $Date: 2005/12/13 21:23:06 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Point;
015: import java.awt.Rectangle;
016: import java.awt.image.ColorModel;
017: import java.awt.image.DataBuffer;
018: import java.awt.image.IndexColorModel;
019: import java.awt.image.Raster;
020: import java.awt.image.RenderedImage;
021: import java.awt.image.WritableRaster;
022: import java.awt.image.renderable.ParameterBlock;
023: import javax.media.jai.GeometricOpImage;
024: import javax.media.jai.ImageLayout;
025: import javax.media.jai.IntegerSequence;
026: import javax.media.jai.OpImage;
027: import javax.media.jai.PlanarImage;
028: import javax.media.jai.RasterAccessor;
029: import javax.media.jai.RasterFormatTag;
030: import javax.media.jai.RasterFactory;
031: import java.util.Map;
032:
033: /**
034: * An OpImage class to perform transposition and 90 degree rotation
035: * of an image.
036: *
037: * @since EA2
038: *
039: */
040: public class TransposeOpImage extends GeometricOpImage {
041:
042: /** The Transpose type */
043: protected int type;
044:
045: /**
046: * Store source width & height
047: */
048: protected int src_width, src_height;
049:
050: protected Rectangle sourceBounds;
051:
052: // Set the bounds and tile grid of the output image.
053: private static ImageLayout layoutHelper(ImageLayout layout,
054: RenderedImage source, int type) {
055: ImageLayout newLayout;
056: if (layout != null) {
057: newLayout = (ImageLayout) layout.clone();
058: } else {
059: newLayout = new ImageLayout();
060: }
061:
062: // Set the size of the destination to exactly cover the
063: // forward-mapped source image bounds
064: Rectangle sourceBounds = new Rectangle(source.getMinX(), source
065: .getMinY(), source.getWidth(), source.getHeight());
066: Rectangle rect = mapRect(sourceBounds, sourceBounds, type, true);
067:
068: newLayout.setMinX(rect.x);
069: newLayout.setMinY(rect.y);
070: newLayout.setWidth(rect.width);
071: newLayout.setHeight(rect.height);
072:
073: // Make each destination tile correspond to a source tile
074: Rectangle tileRect = new Rectangle(source.getTileGridXOffset(),
075: source.getTileGridYOffset(), source.getTileWidth(),
076: source.getTileHeight());
077: rect = mapRect(tileRect, sourceBounds, type, true);
078:
079: // Respect any pre-existing tile grid settings
080: if (newLayout.isValid(ImageLayout.TILE_GRID_X_OFFSET_MASK)) {
081: newLayout.setTileGridXOffset(rect.x);
082: }
083: if (newLayout.isValid(ImageLayout.TILE_GRID_Y_OFFSET_MASK)) {
084: newLayout.setTileGridYOffset(rect.y);
085: }
086: if (newLayout.isValid(ImageLayout.TILE_WIDTH_MASK)) {
087: newLayout.setTileWidth(Math.abs(rect.width));
088: }
089: if (newLayout.isValid(ImageLayout.TILE_HEIGHT_MASK)) {
090: newLayout.setTileHeight(Math.abs(rect.height));
091: }
092:
093: return newLayout;
094: }
095:
096: /**
097: * Constructs an TransposeOpImage from a RenderedImage source,
098: * and Transpose type. The image dimensions are determined by
099: * forward-mapping the source bounds.
100: * The tile grid layout, SampleModel, and ColorModel are specified
101: * by the image source, possibly overridden by values from the
102: * ImageLayout parameter.
103: *
104: * @param source a RenderedImage.
105: * @param layout an ImageLayout optionally containing the tile grid layout,
106: * SampleModel, and ColorModel, or null.
107: * @param type the desired Tranpose type.
108: */
109: public TransposeOpImage(RenderedImage source, Map config,
110: ImageLayout layout, int type) {
111: super (vectorize(source), layoutHelper(layout, source, type),
112: config, true, null, // BorderExtender
113: null, null); // Interpolation (superclass defaults to nearest neighbor)
114:
115: // If the source has an IndexColorModel, override the default setting
116: // in OpImage. The dest shall have exactly the same SampleModel and
117: // ColorModel as the source.
118: // Note, in this case, the source should have an integral data type.
119: ColorModel srcColorModel = source.getColorModel();
120: if (srcColorModel instanceof IndexColorModel) {
121: sampleModel = source.getSampleModel()
122: .createCompatibleSampleModel(tileWidth, tileHeight);
123: colorModel = srcColorModel;
124: }
125:
126: // store the Transpose type
127: this .type = type;
128:
129: // Store the source width & height
130: this .src_width = source.getWidth();
131: this .src_height = source.getHeight();
132:
133: this .sourceBounds = new Rectangle(source.getMinX(), source
134: .getMinY(), source.getWidth(), source.getHeight());
135: }
136:
137: /**
138: * Forward map the source Rectangle.
139: */
140: protected Rectangle forwardMapRect(Rectangle sourceRect,
141: int sourceIndex) {
142: return mapRect(sourceRect, sourceBounds, type, true);
143: }
144:
145: /**
146: * Backward map the destination Rectangle.
147: */
148: protected Rectangle backwardMapRect(Rectangle destRect,
149: int sourceIndex) {
150: return mapRect(destRect, sourceBounds, type, false);
151: }
152:
153: /**
154: * Map a point according to the transposition type.
155: * If <code>mapForwards</code> is <code>true</code>,
156: * the point is considered to lie in the source image and
157: * is mapping into the destination space. Otherwise,
158: * the point lies in the destination and is mapped
159: * into the source space.
160: *
161: * <p> In either case, the bounds of the source image
162: * must be supplied. The bounds are given by the indices
163: * of the upper left and lower right pixels, i.e.,
164: * maxX = minX + width - 1 and similarly for maxY.
165: */
166: protected static void mapPoint(int[] pt, int minX, int minY,
167: int maxX, int maxY, int type, boolean mapForwards) {
168: int sx = pt[0];
169: int sy = pt[1];
170: int dx = -1;
171: int dy = -1;
172:
173: switch (type) {
174: case 0: // FLIP_VERTICAL
175: dx = sx;
176: dy = minY + maxY - sy;
177: break;
178:
179: case 1: // FLIP_HORIZONTAL
180: dx = minX + maxX - sx;
181: dy = sy;
182: break;
183:
184: case 2: // FLIP_DIAGONAL
185: dx = minX - minY + sy;
186: dy = minY - minX + sx;
187: break;
188:
189: case 3: // FLIP_ANTIDIAGONAL
190: if (mapForwards) {
191: dx = minX + maxY - sy;
192: dy = minY + maxX - sx;
193: } else {
194: dx = minY + maxX - sy;
195: dy = minX + maxY - sx;
196: }
197: break;
198:
199: case 4: // ROTATE_90
200: if (mapForwards) {
201: dx = minX + maxY - sy;
202: dy = minY - minX + sx;
203: } else {
204: dx = minX - minY + sy;
205: dy = minX + maxY - sx;
206: }
207: break;
208:
209: case 5: // ROTATE_180
210: dx = minX + maxX - sx;
211: dy = minY + maxY - sy;
212: break;
213:
214: case 6: // ROTATE_270
215: if (mapForwards) {
216: dx = minX - minY + sy;
217: dy = maxX + minY - sx;
218: } else {
219: dx = maxX + minY - sy;
220: dy = minY - minX + sx;
221: }
222: break;
223: }
224:
225: pt[0] = dx;
226: pt[1] = dy;
227: }
228:
229: private static Rectangle mapRect(Rectangle rect,
230: Rectangle sourceBounds, int type, boolean mapForwards) {
231: int sMinX = sourceBounds.x;
232: int sMinY = sourceBounds.y;
233: int sMaxX = sMinX + sourceBounds.width - 1;
234: int sMaxY = sMinY + sourceBounds.height - 1;
235: int dMinX, dMinY, dMaxX, dMaxY;
236:
237: int[] pt = new int[2];
238: pt[0] = rect.x;
239: pt[1] = rect.y;
240: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, mapForwards);
241: dMinX = dMaxX = pt[0];
242: dMinY = dMaxY = pt[1];
243:
244: pt[0] = rect.x + rect.width - 1;
245: pt[1] = rect.y;
246: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, mapForwards);
247: dMinX = Math.min(dMinX, pt[0]);
248: dMinY = Math.min(dMinY, pt[1]);
249: dMaxX = Math.max(dMaxX, pt[0]);
250: dMaxY = Math.max(dMaxY, pt[1]);
251:
252: pt[0] = rect.x;
253: pt[1] = rect.y + rect.height - 1;
254: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, mapForwards);
255: dMinX = Math.min(dMinX, pt[0]);
256: dMinY = Math.min(dMinY, pt[1]);
257: dMaxX = Math.max(dMaxX, pt[0]);
258: dMaxY = Math.max(dMaxY, pt[1]);
259:
260: pt[0] = rect.x + rect.width - 1;
261: pt[1] = rect.y + rect.height - 1;
262: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, mapForwards);
263: dMinX = Math.min(dMinX, pt[0]);
264: dMinY = Math.min(dMinY, pt[1]);
265: dMaxX = Math.max(dMaxX, pt[0]);
266: dMaxY = Math.max(dMaxY, pt[1]);
267:
268: return new Rectangle(dMinX, dMinY, dMaxX - dMinX + 1, dMaxY
269: - dMinY + 1);
270: }
271:
272: public Raster computeTile(int tileX, int tileY) {
273: // Create a new WritableRaster.
274: Point org = new Point(tileXToX(tileX), tileYToY(tileY));
275: WritableRaster dest = createWritableRaster(sampleModel, org);
276:
277: // Output bounds are initially equal to the tile bounds.
278: int destMinX = dest.getMinX();
279: int destMinY = dest.getMinY();
280: int destMaxX = destMinX + dest.getWidth();
281: int destMaxY = destMinY + dest.getHeight();
282:
283: // Clip output bounds to the dest image bounds.
284: Rectangle bounds = getBounds();
285: if (destMinX < bounds.x) {
286: destMinX = bounds.x;
287: }
288: int boundsMaxX = bounds.x + bounds.width;
289: if (destMaxX > boundsMaxX) {
290: destMaxX = boundsMaxX;
291: }
292: if (destMinY < bounds.y) {
293: destMinY = bounds.y;
294: }
295: int boundsMaxY = bounds.y + bounds.height;
296: if (destMaxY > boundsMaxY) {
297: destMaxY = boundsMaxY;
298: }
299:
300: if (destMinX >= destMaxX || destMinY >= destMaxY) {
301: return dest; // nothing to write
302: }
303:
304: // Initialize the (possibly clipped) destination Rectangle.
305: Rectangle destRect = new Rectangle(destMinX, destMinY, destMaxX
306: - destMinX, destMaxY - destMinY);
307:
308: // Initialize X and Y split sequences with the dest bounds
309: IntegerSequence xSplits = new IntegerSequence(destMinX,
310: destMaxX);
311: xSplits.insert(destMinX);
312: xSplits.insert(destMaxX);
313:
314: IntegerSequence ySplits = new IntegerSequence(destMinY,
315: destMaxY);
316: ySplits.insert(destMinY);
317: ySplits.insert(destMaxY);
318:
319: // Overlay the forward-mapped source tile grid
320: PlanarImage src = getSource(0);
321: int sMinX = src.getMinX();
322: int sMinY = src.getMinY();
323: int sWidth = src.getWidth();
324: int sHeight = src.getHeight();
325: int sMaxX = sMinX + sWidth - 1;
326: int sMaxY = sMinY + sHeight - 1;
327: int sTileWidth = src.getTileWidth();
328: int sTileHeight = src.getTileHeight();
329: int sTileGridXOffset = src.getTileGridXOffset();
330: int sTileGridYOffset = src.getTileGridYOffset();
331:
332: int xStart = 0;
333: int xGap = 0;
334: int yStart = 0;
335: int yGap = 0;
336:
337: // Insert splits from source image.
338: //
339: // We can think of the splits as forming an infinite sequence
340: // xStart + kx*xGap, yStart + ky*yGap, where kx and ky range
341: // over all integers, negative and positive.
342:
343: // Forward map the source tile grid origin Note that in cases
344: // where an axis is "flipped" an adjustment must be made. For
345: // example, consider flipping an image horizontally.
346: // If the image has a tile X origin of 0, a tile width
347: // of 50, and a total width of 100, then forward mapping the
348: // points (0, 0) and (50, 0) yields the points (99, 0) and
349: // (49, 0). In the original image, the tile split lines lay
350: // to the left of the pixel; in the flipped image, they lie
351: // to the right of the forward mapped pixels. Thus 1 must
352: // be added to the forward mapped pixel position to get the
353: // correct split location.
354: int[] pt = new int[2];
355: pt[0] = sTileGridXOffset;
356: pt[1] = sTileGridYOffset;
357: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, true);
358: xStart = pt[0];
359: yStart = pt[1];
360:
361: // Forward map the input tile size
362: switch (type) {
363: case 0: // FLIP_VERTICAL
364: ++yStart;
365: xGap = sTileWidth;
366: yGap = sTileHeight;
367: break;
368:
369: case 1: // FLIP_HORIZONTAL
370: ++xStart;
371: xGap = sTileWidth;
372: yGap = sTileHeight;
373: break;
374:
375: case 2: // FLIP_DIAGONAL
376: xGap = sTileHeight;
377: yGap = sTileWidth;
378: break;
379:
380: case 3: // FLIP_ANTIDIAGONAL
381: ++xStart;
382: ++yStart;
383: xGap = sTileHeight;
384: yGap = sTileWidth;
385: break;
386:
387: case 4: // ROTATE_90
388: ++xStart;
389: xGap = sTileHeight;
390: yGap = sTileWidth;
391: break;
392:
393: case 5: // ROTATE_180
394: ++xStart;
395: ++yStart;
396: xGap = sTileWidth;
397: yGap = sTileHeight;
398: break;
399:
400: case 6: // ROTATE_270
401: ++yStart;
402: xGap = sTileHeight;
403: yGap = sTileWidth;
404: break;
405: }
406:
407: // Now we identify the source splits that intersect
408: // the destination rectangle and merge them in.
409: int kx = (int) Math.floor((double) (destMinX - xStart) / xGap);
410: int xSplit = xStart + kx * xGap;
411: while (xSplit < destMaxX) {
412: xSplits.insert(xSplit);
413: xSplit += xGap;
414: }
415:
416: int ky = (int) Math.floor((double) (destMinY - yStart) / yGap);
417: int ySplit = yStart + ky * yGap;
418: while (ySplit < destMaxY) {
419: ySplits.insert(ySplit);
420: ySplit += yGap;
421: }
422:
423: // Allocate memory for source Rasters.
424: Raster[] sources = new Raster[1];
425:
426: //
427: // Divide destRect into sub rectangles based on the source
428: // splits, and compute each sub rectangle separately.
429: //
430: int x1, x2, y1, y2, w, h;
431: Rectangle subRect = new Rectangle();
432:
433: ySplits.startEnumeration();
434: for (y1 = ySplits.nextElement(); ySplits.hasMoreElements(); y1 = y2) {
435: y2 = ySplits.nextElement();
436: h = y2 - y1;
437:
438: xSplits.startEnumeration();
439: for (x1 = xSplits.nextElement(); xSplits.hasMoreElements(); x1 = x2) {
440: x2 = xSplits.nextElement();
441: w = x2 - x1;
442:
443: // Get sources
444:
445: // Backwards map the starting destination point
446: pt[0] = x1;
447: pt[1] = y1;
448: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, false);
449:
450: // Determine the source tile involved
451: int tx = src.XToTileX(pt[0]);
452: int ty = src.YToTileY(pt[1]);
453: sources[0] = src.getTile(tx, ty);
454:
455: subRect.x = x1;
456: subRect.y = y1;
457: subRect.width = w;
458: subRect.height = h;
459: computeRect(sources, dest, subRect);
460: }
461: }
462:
463: return dest;
464: }
465:
466: protected void computeRect(Raster[] sources, WritableRaster dest,
467: Rectangle destRect) {
468: // Retrieve format tags.
469: RasterFormatTag[] formatTags = getFormatTags();
470: Raster src = sources[0];
471:
472: //
473: // Get the minX, minY, width & height of sources raster
474: //
475: PlanarImage source = getSource(0);
476: int sMinX = source.getMinX();
477: int sMinY = source.getMinY();
478: int sWidth = source.getWidth();
479: int sHeight = source.getHeight();
480: int sMaxX = sMinX + sWidth - 1;
481: int sMaxY = sMinY + sHeight - 1;
482:
483: int translateX = src.getSampleModelTranslateX();
484: int translateY = src.getSampleModelTranslateY();
485:
486: //
487: // Get data for the source rectangle & the destination rectangle
488: Rectangle srcRect = src.getBounds();
489:
490: RasterAccessor srcAccessor = new RasterAccessor(src, srcRect,
491: formatTags[0], getSource(0).getColorModel());
492: RasterAccessor dstAccessor = new RasterAccessor(dest, destRect,
493: formatTags[1], getColorModel());
494:
495: int incr1 = 0, incr2 = 0, s_x = 0, s_y = 0;
496: int srcPixelStride = srcAccessor.getPixelStride();
497: int srcScanlineStride = srcAccessor.getScanlineStride();
498:
499: // Backwards map starting point of destination rectangle
500: int[] pt = new int[2];
501: pt[0] = destRect.x;
502: pt[1] = destRect.y;
503: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, false);
504: s_x = pt[0];
505: s_y = pt[1];
506:
507: // Determine source stride along dest row (incr1) and column (incr2)
508: switch (type) {
509: case 0: // FLIP_VERTICAL
510: incr1 = srcPixelStride;
511: incr2 = -srcScanlineStride;
512: break;
513:
514: case 1: // FLIP_HORIZONTAL
515: incr1 = -srcPixelStride;
516: incr2 = srcScanlineStride;
517: break;
518:
519: case 2: // FLIP_DIAGONAL;
520: incr1 = srcScanlineStride;
521: incr2 = srcPixelStride;
522: break;
523:
524: case 3: // FLIP_ANTIDIAGONAL
525: incr1 = -srcScanlineStride;
526: incr2 = -srcPixelStride;
527: break;
528:
529: case 4: // ROTATE_90
530: incr1 = -srcScanlineStride;
531: incr2 = srcPixelStride;
532: break;
533:
534: case 5: // ROTATE_180
535: incr1 = -srcPixelStride;
536: incr2 = -srcScanlineStride;
537: break;
538:
539: case 6: // ROTATE_270
540: incr1 = srcScanlineStride;
541: incr2 = -srcPixelStride;
542: break;
543: }
544:
545: switch (dstAccessor.getDataType()) {
546: case DataBuffer.TYPE_BYTE:
547: byteLoop(srcAccessor, destRect, translateX, translateY,
548: dstAccessor, incr1, incr2, s_x, s_y);
549: break;
550:
551: case DataBuffer.TYPE_INT:
552: intLoop(srcAccessor, destRect, translateX, translateY,
553: dstAccessor, incr1, incr2, s_x, s_y);
554: break;
555:
556: case DataBuffer.TYPE_SHORT:
557: case DataBuffer.TYPE_USHORT:
558: shortLoop(srcAccessor, destRect, translateX, translateY,
559: dstAccessor, incr1, incr2, s_x, s_y);
560: break;
561:
562: case DataBuffer.TYPE_FLOAT:
563: floatLoop(srcAccessor, destRect, translateX, translateY,
564: dstAccessor, incr1, incr2, s_x, s_y);
565: break;
566:
567: case DataBuffer.TYPE_DOUBLE:
568: doubleLoop(srcAccessor, destRect, translateX, translateY,
569: dstAccessor, incr1, incr2, s_x, s_y);
570: break;
571: }
572:
573: //
574: // If the RasterAccessor object set up a temporary buffer for the
575: // op to write to, tell the RasterAccessor to write that data
576: // to the raster, that we're done with it.
577: //
578: if (dstAccessor.isDataCopy()) {
579: dstAccessor.clampDataArrays();
580: dstAccessor.copyDataToRaster();
581: }
582: }
583:
584: private void byteLoop(RasterAccessor src, Rectangle destRect,
585: int srcTranslateX, int srcTranslateY, RasterAccessor dst,
586: int incr1, int incr2, int s_x, int s_y) {
587: int dwidth = dst.getWidth();
588: int dheight = dst.getHeight();
589: int dnumBands = dst.getNumBands();
590:
591: byte dstDataArrays[][] = dst.getByteDataArrays();
592: int dstBandOffsets[] = dst.getBandOffsets();
593: int dstPixelStride = dst.getPixelStride();
594: int dstScanlineStride = dst.getScanlineStride();
595:
596: byte srcDataArrays[][] = src.getByteDataArrays();
597: int bandOffsets[] = src.getOffsetsForBands();
598: int srcPixelStride = src.getPixelStride();
599: int srcScanlineStride = src.getScanlineStride();
600:
601: int dst_num_bands = dst.getNumBands();
602:
603: int dst_min_x = destRect.x;
604: int dst_min_y = destRect.y;
605: int dst_max_x = destRect.x + destRect.width;
606: int dst_max_y = destRect.y + destRect.height;
607:
608: // Translate to/from SampleModel space & Raster space
609: int posy = (s_y - srcTranslateY) * srcScanlineStride;
610: int posx = (s_x - srcTranslateX) * srcPixelStride;
611: int srcScanlineOffset = posx + posy;
612: int dstScanlineOffset = 0;
613:
614: // loop around
615: for (int y = dst_min_y; y < dst_max_y; y++) {
616: for (int k2 = 0; k2 < dst_num_bands; k2++) {
617: byte[] srcDataArray = srcDataArrays[k2];
618: byte[] dstDataArray = dstDataArrays[k2];
619:
620: int dstPixelOffset = dstScanlineOffset
621: + dstBandOffsets[k2];
622: int srcPixelOffset = srcScanlineOffset
623: + bandOffsets[k2];
624:
625: for (int x = dst_min_x; x < dst_max_x; x++) {
626: dstDataArray[dstPixelOffset] = srcDataArray[srcPixelOffset];
627: srcPixelOffset += incr1;
628:
629: // Go to next pixel
630: dstPixelOffset += dstPixelStride;
631: }
632: }
633:
634: srcScanlineOffset += incr2;
635:
636: // Got the next line in the destination rectangle
637: dstScanlineOffset += dstScanlineStride;
638: }
639: }
640:
641: private void intLoop(RasterAccessor src, Rectangle destRect,
642: int srcTranslateX, int srcTranslateY, RasterAccessor dst,
643: int incr1, int incr2, int s_x, int s_y) {
644: int dwidth = dst.getWidth();
645: int dheight = dst.getHeight();
646: int dnumBands = dst.getNumBands();
647:
648: int dstDataArrays[][] = dst.getIntDataArrays();
649: int dstBandOffsets[] = dst.getBandOffsets();
650: int dstPixelStride = dst.getPixelStride();
651: int dstScanlineStride = dst.getScanlineStride();
652:
653: int srcDataArrays[][] = src.getIntDataArrays();
654: int bandOffsets[] = src.getOffsetsForBands();
655: int srcPixelStride = src.getPixelStride();
656: int srcScanlineStride = src.getScanlineStride();
657:
658: int dst_num_bands = dst.getNumBands();
659:
660: int dst_min_x = destRect.x;
661: int dst_min_y = destRect.y;
662: int dst_max_x = destRect.x + destRect.width;
663: int dst_max_y = destRect.y + destRect.height;
664:
665: // Translate to/from SampleModel space & Raster space
666: int posy = (s_y - srcTranslateY) * srcScanlineStride;
667: int posx = (s_x - srcTranslateX) * srcPixelStride;
668: int srcScanlineOffset = posx + posy;
669: int dstScanlineOffset = 0;
670:
671: // loop around
672: for (int y = dst_min_y; y < dst_max_y; y++) {
673: for (int k2 = 0; k2 < dst_num_bands; k2++) {
674: int[] srcDataArray = srcDataArrays[k2];
675: int[] dstDataArray = dstDataArrays[k2];
676:
677: int dstPixelOffset = dstScanlineOffset
678: + dstBandOffsets[k2];
679: int srcPixelOffset = srcScanlineOffset
680: + bandOffsets[k2];
681:
682: for (int x = dst_min_x; x < dst_max_x; x++) {
683: dstDataArray[dstPixelOffset] = srcDataArray[srcPixelOffset];
684: srcPixelOffset += incr1;
685:
686: // Go to next pixel
687: dstPixelOffset += dstPixelStride;
688: }
689: }
690:
691: srcScanlineOffset += incr2;
692:
693: // Got the next line in the destination rectangle
694: dstScanlineOffset += dstScanlineStride;
695: }
696: }
697:
698: private void shortLoop(RasterAccessor src, Rectangle destRect,
699: int srcTranslateX, int srcTranslateY, RasterAccessor dst,
700: int incr1, int incr2, int s_x, int s_y) {
701: int dwidth = dst.getWidth();
702: int dheight = dst.getHeight();
703: int dnumBands = dst.getNumBands();
704:
705: short dstDataArrays[][] = dst.getShortDataArrays();
706: int dstBandOffsets[] = dst.getBandOffsets();
707: int dstPixelStride = dst.getPixelStride();
708: int dstScanlineStride = dst.getScanlineStride();
709:
710: short srcDataArrays[][] = src.getShortDataArrays();
711: int bandOffsets[] = src.getOffsetsForBands();
712: int srcPixelStride = src.getPixelStride();
713: int srcScanlineStride = src.getScanlineStride();
714:
715: int dst_num_bands = dst.getNumBands();
716:
717: int dst_min_x = destRect.x;
718: int dst_min_y = destRect.y;
719: int dst_max_x = destRect.x + destRect.width;
720: int dst_max_y = destRect.y + destRect.height;
721:
722: // Translate to/from SampleModel space & Raster space
723: int posy = (s_y - srcTranslateY) * srcScanlineStride;
724: int posx = (s_x - srcTranslateX) * srcPixelStride;
725: int srcScanlineOffset = posx + posy;
726: int dstScanlineOffset = 0;
727:
728: // loop around
729: for (int y = dst_min_y; y < dst_max_y; y++) {
730: for (int k2 = 0; k2 < dst_num_bands; k2++) {
731: short[] srcDataArray = srcDataArrays[k2];
732: short[] dstDataArray = dstDataArrays[k2];
733:
734: int dstPixelOffset = dstScanlineOffset
735: + dstBandOffsets[k2];
736: int srcPixelOffset = srcScanlineOffset
737: + bandOffsets[k2];
738:
739: for (int x = dst_min_x; x < dst_max_x; x++) {
740: dstDataArray[dstPixelOffset] = srcDataArray[srcPixelOffset];
741: srcPixelOffset += incr1;
742:
743: // Go to next pixel
744: dstPixelOffset += dstPixelStride;
745: }
746: }
747:
748: srcScanlineOffset += incr2;
749:
750: // Got the next line in the destination rectangle
751: dstScanlineOffset += dstScanlineStride;
752: }
753: }
754:
755: private void floatLoop(RasterAccessor src, Rectangle destRect,
756: int srcTranslateX, int srcTranslateY, RasterAccessor dst,
757: int incr1, int incr2, int s_x, int s_y) {
758: int dwidth = dst.getWidth();
759: int dheight = dst.getHeight();
760: int dnumBands = dst.getNumBands();
761:
762: float dstDataArrays[][] = dst.getFloatDataArrays();
763: int dstBandOffsets[] = dst.getBandOffsets();
764: int dstPixelStride = dst.getPixelStride();
765: int dstScanlineStride = dst.getScanlineStride();
766:
767: float srcDataArrays[][] = src.getFloatDataArrays();
768: int bandOffsets[] = src.getOffsetsForBands();
769: int srcPixelStride = src.getPixelStride();
770: int srcScanlineStride = src.getScanlineStride();
771:
772: int dst_num_bands = dst.getNumBands();
773:
774: int dst_min_x = destRect.x;
775: int dst_min_y = destRect.y;
776: int dst_max_x = destRect.x + destRect.width;
777: int dst_max_y = destRect.y + destRect.height;
778:
779: // Translate to/from SampleModel space & Raster space
780: int posy = (s_y - srcTranslateY) * srcScanlineStride;
781: int posx = (s_x - srcTranslateX) * srcPixelStride;
782: int srcScanlineOffset = posx + posy;
783: int dstScanlineOffset = 0;
784:
785: // loop around
786: for (int y = dst_min_y; y < dst_max_y; y++) {
787: for (int k2 = 0; k2 < dst_num_bands; k2++) {
788: float[] srcDataArray = srcDataArrays[k2];
789: float[] dstDataArray = dstDataArrays[k2];
790:
791: int dstPixelOffset = dstScanlineOffset
792: + dstBandOffsets[k2];
793: int srcPixelOffset = srcScanlineOffset
794: + bandOffsets[k2];
795:
796: for (int x = dst_min_x; x < dst_max_x; x++) {
797: dstDataArray[dstPixelOffset] = srcDataArray[srcPixelOffset];
798: srcPixelOffset += incr1;
799:
800: // Go to next pixel
801: dstPixelOffset += dstPixelStride;
802: }
803: }
804:
805: srcScanlineOffset += incr2;
806:
807: // Got the next line in the destination rectangle
808: dstScanlineOffset += dstScanlineStride;
809: }
810: }
811:
812: private void doubleLoop(RasterAccessor src, Rectangle destRect,
813: int srcTranslateX, int srcTranslateY, RasterAccessor dst,
814: int incr1, int incr2, int s_x, int s_y) {
815: int dwidth = dst.getWidth();
816: int dheight = dst.getHeight();
817: int dnumBands = dst.getNumBands();
818:
819: double dstDataArrays[][] = dst.getDoubleDataArrays();
820: int dstBandOffsets[] = dst.getBandOffsets();
821: int dstPixelStride = dst.getPixelStride();
822: int dstScanlineStride = dst.getScanlineStride();
823:
824: double srcDataArrays[][] = src.getDoubleDataArrays();
825: int bandOffsets[] = src.getOffsetsForBands();
826: int srcPixelStride = src.getPixelStride();
827: int srcScanlineStride = src.getScanlineStride();
828:
829: int dst_num_bands = dst.getNumBands();
830:
831: int dst_min_x = destRect.x;
832: int dst_min_y = destRect.y;
833: int dst_max_x = destRect.x + destRect.width;
834: int dst_max_y = destRect.y + destRect.height;
835:
836: // Translate to/from SampleModel space & Raster space
837: int posy = (s_y - srcTranslateY) * srcScanlineStride;
838: int posx = (s_x - srcTranslateX) * srcPixelStride;
839: int srcScanlineOffset = posx + posy;
840: int dstScanlineOffset = 0;
841:
842: // loop around
843: for (int y = dst_min_y; y < dst_max_y; y++) {
844: for (int k2 = 0; k2 < dst_num_bands; k2++) {
845: double[] srcDataArray = srcDataArrays[k2];
846: double[] dstDataArray = dstDataArrays[k2];
847:
848: int dstPixelOffset = dstScanlineOffset
849: + dstBandOffsets[k2];
850: int srcPixelOffset = srcScanlineOffset
851: + bandOffsets[k2];
852:
853: for (int x = dst_min_x; x < dst_max_x; x++) {
854: dstDataArray[dstPixelOffset] = srcDataArray[srcPixelOffset];
855: srcPixelOffset += incr1;
856:
857: // Go to next pixel
858: dstPixelOffset += dstPixelStride;
859: }
860: }
861:
862: srcScanlineOffset += incr2;
863:
864: // Got the next line in the destination rectangle
865: dstScanlineOffset += dstScanlineStride;
866: }
867: }
868: }
|