001: /*
002: * $RCSfile: AffineNearestBinaryOpImage.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.3 $
009: * $Date: 2006/07/21 20:41:27 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Rectangle;
015: import java.awt.RenderingHints;
016: import java.awt.geom.AffineTransform;
017: import java.awt.geom.Point2D;
018: import java.awt.image.DataBuffer;
019: import java.awt.image.DataBufferByte;
020: import java.awt.image.DataBufferInt;
021: import java.awt.image.DataBufferUShort;
022: import java.awt.image.MultiPixelPackedSampleModel;
023: import java.awt.image.Raster;
024: import java.awt.image.RenderedImage;
025: import java.awt.image.SampleModel;
026: import java.awt.image.WritableRaster;
027: import java.awt.image.renderable.ParameterBlock;
028: import javax.media.jai.ImageLayout;
029: import javax.media.jai.Interpolation;
030: import javax.media.jai.InterpolationNearest;
031: import javax.media.jai.JAI;
032: import javax.media.jai.OpImage;
033: import javax.media.jai.RasterAccessor;
034: import javax.media.jai.RasterFormatTag;
035: import javax.media.jai.util.Range;
036: import javax.media.jai.BorderExtender;
037: import java.util.Map;
038:
039: /**
040: * An OpImage subclass that performs nearest-neighbour Affine mapping
041: */
042: final class AffineNearestBinaryOpImage extends AffineNearestOpImage {
043:
044: // The background
045: private int black = 0;
046:
047: // Since this operation deals with packed binary data, we do not need
048: // to expand the IndexColorModel
049: private static Map configHelper(Map configuration) {
050:
051: Map config;
052:
053: if (configuration == null) {
054:
055: config = new RenderingHints(
056: JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
057:
058: } else {
059:
060: config = configuration;
061:
062: if (!(config.containsKey(JAI.KEY_REPLACE_INDEX_COLOR_MODEL))) {
063: RenderingHints hints = (RenderingHints) configuration;
064: config = (RenderingHints) hints.clone();
065: config.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL,
066: Boolean.FALSE);
067: }
068: }
069:
070: return config;
071: }
072:
073: /**
074: * Constructs an AffineNearestBinaryOpImage from a RenderedImage source,
075: *
076: * @param source a RenderedImage.
077: * @param layout an ImageLayout optionally containing the tile grid layout,
078: * SampleModel, and ColorModel, or null.
079: * @param interp an Interpolation object to use for resampling
080: * @param transform the desired AffineTransform.
081: */
082: public AffineNearestBinaryOpImage(RenderedImage source,
083: BorderExtender extender, Map config, ImageLayout layout,
084: AffineTransform transform, Interpolation interp,
085: double[] backgroundValues) {
086: super (source, extender, configHelper(config), layout,
087: transform, interp, backgroundValues);
088:
089: // Propagate source's ColorModel and SampleModel but change tile size.
090: if (layout != null) {
091: colorModel = layout.getColorModel(source);
092: } else {
093: colorModel = source.getColorModel();
094: }
095: sampleModel = source.getSampleModel()
096: .createCompatibleSampleModel(tileWidth, tileHeight);
097:
098: // Set the background to color to 1 if the color
099: // model specifies that as "black", otherwise 0.
100: //
101: // This cause problem on the background (Bug 4380285): because
102: // (1) if the tile does not intersect with the source, zeroed tile(white
103: // is created; (2) if the line does not intersect with the source,
104: // zeroed-line is created; (3) if the image area does not equal to
105: // the whole destination rectangle, some white line will be displayed.
106: //
107: //if (colorModel.getRGB(1) == 0xff000000) {
108: // black = 1;
109: //}
110: }
111:
112: /**
113: * Performs an affine transform on a specified rectangle. The sources are
114: * cobbled.
115: *
116: * @param sources an array of source Rasters, guaranteed to provide all
117: * necessary source data for computing the output.
118: * @param dest a WritableRaster tile containing the area to be computed.
119: * @param destRect the rectangle within dest to be processed.
120: */
121: protected void computeRect(Raster[] sources, WritableRaster dest,
122: Rectangle destRect) {
123: Raster source = sources[0];
124:
125: switch (source.getSampleModel().getDataType()) {
126: case DataBuffer.TYPE_BYTE:
127: byteLoop(source, dest, destRect);
128: break;
129:
130: case DataBuffer.TYPE_INT:
131: intLoop(source, dest, destRect);
132: break;
133:
134: case DataBuffer.TYPE_SHORT:
135: case DataBuffer.TYPE_USHORT:
136: shortLoop(source, dest, destRect);
137: break;
138: }
139: }
140:
141: private void byteLoop(Raster source, WritableRaster dest,
142: Rectangle destRect) {
143: float src_rect_x1 = source.getMinX();
144: float src_rect_y1 = source.getMinY();
145: float src_rect_x2 = src_rect_x1 + source.getWidth();
146: float src_rect_y2 = src_rect_y1 + source.getHeight();
147:
148: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
149: .getSampleModel();
150: DataBufferByte sourceDB = (DataBufferByte) source
151: .getDataBuffer();
152: int sourceTransX = source.getSampleModelTranslateX();
153: int sourceTransY = source.getSampleModelTranslateY();
154: int sourceDataBitOffset = sourceSM.getDataBitOffset();
155: int sourceScanlineStride = sourceSM.getScanlineStride();
156:
157: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
158: .getSampleModel();
159: DataBufferByte destDB = (DataBufferByte) dest.getDataBuffer();
160: int destMinX = dest.getMinX();
161: int destMinY = dest.getMinY();
162: int destTransX = dest.getSampleModelTranslateX();
163: int destTransY = dest.getSampleModelTranslateY();
164: int destDataBitOffset = destSM.getDataBitOffset();
165: int destScanlineStride = destSM.getScanlineStride();
166:
167: byte[] sourceData = sourceDB.getData();
168: int sourceDBOffset = sourceDB.getOffset();
169:
170: byte[] destData = destDB.getData();
171: int destDBOffset = destDB.getOffset();
172:
173: Point2D dst_pt = new Point2D.Float();
174: Point2D src_pt = new Point2D.Float();
175:
176: int dst_min_x = destRect.x;
177: int dst_min_y = destRect.y;
178: int dst_max_x = destRect.x + destRect.width;
179: int dst_max_y = destRect.y + destRect.height;
180:
181: int incyStride = incy * sourceScanlineStride;
182: int incy1Stride = incy1 * sourceScanlineStride;
183:
184: black = ((int) backgroundValues[0]) & 1;
185:
186: for (int y = dst_min_y; y < dst_max_y; y++) {
187: // Backward map the first point in the line
188: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
189: dst_pt.setLocation((double) dst_min_x + 0.5,
190: (double) y + 0.5);
191: mapDestPoint(dst_pt, src_pt);
192:
193: // Get the mapped source coordinates
194: float s_x = (float) src_pt.getX();
195: float s_y = (float) src_pt.getY();
196:
197: // Floor to get the integral coordinate
198: int s_ix = (int) Math.floor(s_x);
199: int s_iy = (int) Math.floor(s_y);
200:
201: double fracx = s_x - (double) s_ix;
202: double fracy = s_y - (double) s_iy;
203:
204: int ifracx = (int) Math.floor(fracx * geom_frac_max);
205: int ifracy = (int) Math.floor(fracy * geom_frac_max);
206:
207: int start_s_ix = s_ix;
208: int start_s_iy = s_iy;
209: int start_ifracx = ifracx;
210: int start_ifracy = ifracy;
211:
212: // Compute clipMinX, clipMinY
213: Range clipRange = performScanlineClipping(
214: src_rect_x1,
215: src_rect_y1,
216: // Last point in the source is
217: // x2 = x1 + width - 1
218: // y2 = y1 + height - 1
219: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
220: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
221: int clipMinX = ((Integer) clipRange.getMinValue())
222: .intValue();
223: int clipMaxX = ((Integer) clipRange.getMaxValue())
224: .intValue();
225:
226: if (clipMinX > clipMaxX)
227: continue;
228:
229: int destYOffset = (y - destTransY) * destScanlineStride
230: + destDBOffset;
231: int destXOffset = destDataBitOffset
232: + (dst_min_x - destTransX);
233:
234: int sourceYOffset = (s_iy - sourceTransY)
235: * sourceScanlineStride + sourceDBOffset;
236: int sourceXOffset = s_ix - sourceTransX
237: + sourceDataBitOffset;
238:
239: for (int x = dst_min_x; x < clipMinX; x++) {
240:
241: if (setBackground) {
242: int dindex = destYOffset + (destXOffset >> 3);
243: int dshift = 7 - (destXOffset & 7);
244: int delement = destData[dindex];
245: delement |= black << dshift;
246: destData[dindex] = (byte) delement;
247: }
248:
249: // walk
250: if (ifracx < ifracdx1) {
251: /*
252: // DEBUG
253: s_ix += incx;
254: */
255: ifracx += ifracdx;
256: sourceXOffset += incx;
257: } else {
258: /*
259: // DEBUG
260: s_ix += incx1;
261: */
262: ifracx -= ifracdx1;
263: sourceXOffset += incx1;
264: }
265:
266: if (ifracy < ifracdy1) {
267: /*
268: // DEBUG
269: s_iy += incy;
270: */
271: ifracy += ifracdy;
272: sourceYOffset += incyStride;
273: } else {
274: /*
275: // DEBUG
276: s_iy += incy1;
277: */
278: ifracy -= ifracdy1;
279: sourceYOffset += incy1Stride;
280: }
281:
282: ++destXOffset;
283: }
284:
285: for (int x = clipMinX; x < clipMaxX; x++) {
286: int sindex = sourceYOffset + (sourceXOffset >> 3);
287: byte selement = sourceData[sindex];
288: int val = (selement >> (7 - (sourceXOffset & 7))) & 1;
289:
290: int dindex = destYOffset + (destXOffset >> 3);
291: int dshift = 7 - (destXOffset & 7);
292: int delement = destData[dindex];
293: delement |= val << dshift;
294: destData[dindex] = (byte) delement;
295:
296: // walk
297: if (ifracx < ifracdx1) {
298: /*
299: // DEBUG
300: s_ix += incx;
301: */
302: ifracx += ifracdx;
303: sourceXOffset += incx;
304: } else {
305: /*
306: // DEBUG
307: s_ix += incx1;
308: */
309: ifracx -= ifracdx1;
310: sourceXOffset += incx1;
311: }
312:
313: if (ifracy < ifracdy1) {
314: /*
315: // DEBUG
316: s_iy += incy;
317: */
318: ifracy += ifracdy;
319: sourceYOffset += incyStride;
320: } else {
321: /*
322: // DEBUG
323: s_iy += incy1;
324: */
325: ifracy -= ifracdy1;
326: sourceYOffset += incy1Stride;
327: }
328:
329: ++destXOffset;
330: }
331:
332: for (int x = clipMaxX; x < dst_max_x; x++) {
333:
334: if (setBackground) {
335: int dindex = destYOffset + (destXOffset >> 3);
336: int dshift = 7 - (destXOffset & 7);
337: int delement = destData[dindex];
338: delement |= black << dshift;
339: destData[dindex] = (byte) delement;
340: }
341:
342: // walk
343: if (ifracx < ifracdx1) {
344: /*
345: // DEBUG
346: s_ix += incx;
347: */
348: ifracx += ifracdx;
349: sourceXOffset += incx;
350: } else {
351: /*
352: // DEBUG
353: s_ix += incx1;
354: */
355: ifracx -= ifracdx1;
356: sourceXOffset += incx1;
357: }
358:
359: if (ifracy < ifracdy1) {
360: /*
361: // DEBUG
362: s_iy += incy;
363: */
364: ifracy += ifracdy;
365: sourceYOffset += incyStride;
366: } else {
367: /*
368: // DEBUG
369: s_iy += incy1;
370: */
371: ifracy -= ifracdy1;
372: sourceYOffset += incy1Stride;
373: }
374:
375: ++destXOffset;
376: }
377: }
378: }
379:
380: private void shortLoop(Raster source, WritableRaster dest,
381: Rectangle destRect) {
382: float src_rect_x1 = source.getMinX();
383: float src_rect_y1 = source.getMinY();
384: float src_rect_x2 = src_rect_x1 + source.getWidth();
385: float src_rect_y2 = src_rect_y1 + source.getHeight();
386:
387: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
388: .getSampleModel();
389: DataBufferUShort sourceDB = (DataBufferUShort) source
390: .getDataBuffer();
391: int sourceTransX = source.getSampleModelTranslateX();
392: int sourceTransY = source.getSampleModelTranslateY();
393: int sourceDataBitOffset = sourceSM.getDataBitOffset();
394: int sourceScanlineStride = sourceSM.getScanlineStride();
395:
396: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
397: .getSampleModel();
398: DataBufferUShort destDB = (DataBufferUShort) dest
399: .getDataBuffer();
400: int destMinX = dest.getMinX();
401: int destMinY = dest.getMinY();
402: int destTransX = dest.getSampleModelTranslateX();
403: int destTransY = dest.getSampleModelTranslateY();
404: int destDataBitOffset = destSM.getDataBitOffset();
405: int destScanlineStride = destSM.getScanlineStride();
406:
407: short[] sourceData = sourceDB.getData();
408: int sourceDBOffset = sourceDB.getOffset();
409:
410: short[] destData = destDB.getData();
411: int destDBOffset = destDB.getOffset();
412:
413: Point2D dst_pt = new Point2D.Float();
414: Point2D src_pt = new Point2D.Float();
415:
416: int dst_min_x = destRect.x;
417: int dst_min_y = destRect.y;
418: int dst_max_x = destRect.x + destRect.width;
419: int dst_max_y = destRect.y + destRect.height;
420:
421: int incyStride = incy * sourceScanlineStride;
422: int incy1Stride = incy1 * sourceScanlineStride;
423:
424: black = ((int) backgroundValues[0]) & 1;
425:
426: for (int y = dst_min_y; y < dst_max_y; y++) {
427: // Backward map the first point in the line
428: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
429: dst_pt.setLocation((double) dst_min_x + 0.5,
430: (double) y + 0.5);
431: mapDestPoint(dst_pt, src_pt);
432:
433: // Get the mapped source coordinates
434: float s_x = (float) src_pt.getX();
435: float s_y = (float) src_pt.getY();
436:
437: // Floor to get the integral coordinate
438: int s_ix = (int) Math.floor(s_x);
439: int s_iy = (int) Math.floor(s_y);
440:
441: double fracx = s_x - (double) s_ix;
442: double fracy = s_y - (double) s_iy;
443:
444: int ifracx = (int) Math.floor(fracx * geom_frac_max);
445: int ifracy = (int) Math.floor(fracy * geom_frac_max);
446:
447: int start_s_ix = s_ix;
448: int start_s_iy = s_iy;
449: int start_ifracx = ifracx;
450: int start_ifracy = ifracy;
451:
452: // Compute clipMinX, clipMinY
453: Range clipRange = performScanlineClipping(
454: src_rect_x1,
455: src_rect_y1,
456: // Last point in the source is
457: // x2 = x1 + width - 1
458: // y2 = y1 + height - 1
459: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
460: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
461: int clipMinX = ((Integer) clipRange.getMinValue())
462: .intValue();
463: int clipMaxX = ((Integer) clipRange.getMaxValue())
464: .intValue();
465:
466: if (clipMinX > clipMaxX)
467: continue;
468:
469: int destYOffset = (y - destTransY) * destScanlineStride
470: + destDBOffset;
471: int destXOffset = destDataBitOffset
472: + (dst_min_x - destTransX);
473:
474: int sourceYOffset = (s_iy - sourceTransY)
475: * sourceScanlineStride + sourceDBOffset;
476: int sourceXOffset = s_ix - sourceTransX
477: + sourceDataBitOffset;
478:
479: for (int x = dst_min_x; x < clipMinX; x++) {
480:
481: if (setBackground) {
482: int dindex = destYOffset + (destXOffset >> 4);
483: int dshift = 15 - (destXOffset & 15);
484: int delement = destData[dindex];
485: delement |= black << dshift;
486: destData[dindex] = (short) delement;
487: }
488:
489: // walk
490: if (ifracx < ifracdx1) {
491: /*
492: // DEBUG
493: s_ix += incx;
494: */
495: ifracx += ifracdx;
496: sourceXOffset += incx;
497: } else {
498: /*
499: // DEBUG
500: s_ix += incx1;
501: */
502: ifracx -= ifracdx1;
503: sourceXOffset += incx1;
504: }
505:
506: if (ifracy < ifracdy1) {
507: /*
508: // DEBUG
509: s_iy += incy;
510: */
511: ifracy += ifracdy;
512: sourceYOffset += incyStride;
513: } else {
514: /*
515: // DEBUG
516: s_iy += incy1;
517: */
518: ifracy -= ifracdy1;
519: sourceYOffset += incy1Stride;
520: }
521:
522: ++destXOffset;
523: }
524:
525: for (int x = clipMinX; x < clipMaxX; x++) {
526: int sindex = sourceYOffset + (sourceXOffset >> 4);
527: short selement = sourceData[sindex];
528: int val = (selement >> (15 - (sourceXOffset & 15))) & 1;
529:
530: int dindex = destYOffset + (destXOffset >> 4);
531: int dshift = 15 - (destXOffset & 15);
532: int delement = destData[dindex];
533: delement |= val << dshift;
534: destData[dindex] = (short) delement;
535:
536: // walk
537: if (ifracx < ifracdx1) {
538: /*
539: // DEBUG
540: s_ix += incx;
541: */
542: ifracx += ifracdx;
543: sourceXOffset += incx;
544: } else {
545: /*
546: // DEBUG
547: s_ix += incx1;
548: */
549: ifracx -= ifracdx1;
550: sourceXOffset += incx1;
551: }
552:
553: if (ifracy < ifracdy1) {
554: /*
555: // DEBUG
556: s_iy += incy;
557: */
558: ifracy += ifracdy;
559: sourceYOffset += incyStride;
560: } else {
561: /*
562: // DEBUG
563: s_iy += incy1;
564: */
565: ifracy -= ifracdy1;
566: sourceYOffset += incy1Stride;
567: }
568:
569: ++destXOffset;
570: }
571:
572: for (int x = clipMaxX; x < dst_max_x; x++) {
573: if (setBackground) {
574: int dindex = destYOffset + (destXOffset >> 4);
575: int dshift = 15 - (destXOffset & 15);
576: int delement = destData[dindex];
577: delement |= black << dshift;
578: destData[dindex] = (short) delement;
579: }
580:
581: // walk
582: if (ifracx < ifracdx1) {
583: /*
584: // DEBUG
585: s_ix += incx;
586: */
587: ifracx += ifracdx;
588: sourceXOffset += incx;
589: } else {
590: /*
591: // DEBUG
592: s_ix += incx1;
593: */
594: ifracx -= ifracdx1;
595: sourceXOffset += incx1;
596: }
597:
598: if (ifracy < ifracdy1) {
599: /*
600: // DEBUG
601: s_iy += incy;
602: */
603: ifracy += ifracdy;
604: sourceYOffset += incyStride;
605: } else {
606: /*
607: // DEBUG
608: s_iy += incy1;
609: */
610: ifracy -= ifracdy1;
611: sourceYOffset += incy1Stride;
612: }
613:
614: ++destXOffset;
615: }
616: }
617: }
618:
619: private void intLoop(Raster source, WritableRaster dest,
620: Rectangle destRect) {
621: float src_rect_x1 = source.getMinX();
622: float src_rect_y1 = source.getMinY();
623: float src_rect_x2 = src_rect_x1 + source.getWidth();
624: float src_rect_y2 = src_rect_y1 + source.getHeight();
625:
626: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
627: .getSampleModel();
628: DataBufferInt sourceDB = (DataBufferInt) source.getDataBuffer();
629: int sourceTransX = source.getSampleModelTranslateX();
630: int sourceTransY = source.getSampleModelTranslateY();
631: int sourceDataBitOffset = sourceSM.getDataBitOffset();
632: int sourceScanlineStride = sourceSM.getScanlineStride();
633:
634: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
635: .getSampleModel();
636: DataBufferInt destDB = (DataBufferInt) dest.getDataBuffer();
637: int destMinX = dest.getMinX();
638: int destMinY = dest.getMinY();
639: int destTransX = dest.getSampleModelTranslateX();
640: int destTransY = dest.getSampleModelTranslateY();
641: int destDataBitOffset = destSM.getDataBitOffset();
642: int destScanlineStride = destSM.getScanlineStride();
643:
644: int[] sourceData = sourceDB.getData();
645: int sourceDBOffset = sourceDB.getOffset();
646:
647: int[] destData = destDB.getData();
648: int destDBOffset = destDB.getOffset();
649:
650: Point2D dst_pt = new Point2D.Float();
651: Point2D src_pt = new Point2D.Float();
652:
653: int dst_min_x = destRect.x;
654: int dst_min_y = destRect.y;
655: int dst_max_x = destRect.x + destRect.width;
656: int dst_max_y = destRect.y + destRect.height;
657:
658: int incyStride = incy * sourceScanlineStride;
659: int incy1Stride = incy1 * sourceScanlineStride;
660:
661: black = ((int) backgroundValues[0]) & 1;
662:
663: for (int y = dst_min_y; y < dst_max_y; y++) {
664: // Backward map the first point in the line
665: // The energy is at the (pt_x + 0.5, pt_y + 0.5)
666: dst_pt.setLocation((double) dst_min_x + 0.5,
667: (double) y + 0.5);
668: mapDestPoint(dst_pt, src_pt);
669:
670: // Get the mapped source coordinates
671: float s_x = (float) src_pt.getX();
672: float s_y = (float) src_pt.getY();
673:
674: // Floor to get the integral coordinate
675: int s_ix = (int) Math.floor(s_x);
676: int s_iy = (int) Math.floor(s_y);
677:
678: double fracx = s_x - (double) s_ix;
679: double fracy = s_y - (double) s_iy;
680:
681: int ifracx = (int) Math.floor(fracx * geom_frac_max);
682: int ifracy = (int) Math.floor(fracy * geom_frac_max);
683:
684: int start_s_ix = s_ix;
685: int start_s_iy = s_iy;
686: int start_ifracx = ifracx;
687: int start_ifracy = ifracy;
688:
689: // Compute clipMinX, clipMinY
690: Range clipRange = performScanlineClipping(
691: src_rect_x1,
692: src_rect_y1,
693: // Last point in the source is
694: // x2 = x1 + width - 1
695: // y2 = y1 + height - 1
696: src_rect_x2 - 1, src_rect_y2 - 1, s_ix, s_iy,
697: ifracx, ifracy, dst_min_x, dst_max_x, 0, 0, 0, 0);
698: int clipMinX = ((Integer) clipRange.getMinValue())
699: .intValue();
700: int clipMaxX = ((Integer) clipRange.getMaxValue())
701: .intValue();
702:
703: if (clipMinX > clipMaxX)
704: continue;
705:
706: int destYOffset = (y - destTransY) * destScanlineStride
707: + destDBOffset;
708: int destXOffset = destDataBitOffset
709: + (dst_min_x - destTransX);
710:
711: int sourceYOffset = (s_iy - sourceTransY)
712: * sourceScanlineStride + sourceDBOffset;
713: int sourceXOffset = s_ix - sourceTransX
714: + sourceDataBitOffset;
715:
716: for (int x = dst_min_x; x < clipMinX; x++) {
717: if (setBackground) {
718: int dindex = destYOffset + (destXOffset >> 5);
719: int dshift = 31 - (destXOffset & 31);
720: int delement = destData[dindex];
721: delement |= black << dshift;
722: destData[dindex] = (int) delement;
723: }
724:
725: // walk
726: if (ifracx < ifracdx1) {
727: /*
728: // DEBUG
729: s_ix += incx;
730: */
731: ifracx += ifracdx;
732: sourceXOffset += incx;
733: } else {
734: /*
735: // DEBUG
736: s_ix += incx1;
737: */
738: ifracx -= ifracdx1;
739: sourceXOffset += incx1;
740: }
741:
742: if (ifracy < ifracdy1) {
743: /*
744: // DEBUG
745: s_iy += incy;
746: */
747: ifracy += ifracdy;
748: sourceYOffset += incyStride;
749: } else {
750: /*
751: // DEBUG
752: s_iy += incy1;
753: */
754: ifracy -= ifracdy1;
755: sourceYOffset += incy1Stride;
756: }
757:
758: ++destXOffset;
759: }
760:
761: for (int x = clipMinX; x < clipMaxX; x++) {
762: int sindex = sourceYOffset + (sourceXOffset >> 5);
763: int selement = sourceData[sindex];
764: int val = (selement >> (31 - (sourceXOffset & 31))) & 1;
765:
766: int dindex = destYOffset + (destXOffset >> 5);
767: int dshift = 31 - (destXOffset & 31);
768: int delement = destData[dindex];
769: delement |= val << dshift;
770: destData[dindex] = (int) delement;
771:
772: // walk
773: if (ifracx < ifracdx1) {
774: /*
775: // DEBUG
776: s_ix += incx;
777: */
778: ifracx += ifracdx;
779: sourceXOffset += incx;
780: } else {
781: /*
782: // DEBUG
783: s_ix += incx1;
784: */
785: ifracx -= ifracdx1;
786: sourceXOffset += incx1;
787: }
788:
789: if (ifracy < ifracdy1) {
790: /*
791: // DEBUG
792: s_iy += incy;
793: */
794: ifracy += ifracdy;
795: sourceYOffset += incyStride;
796: } else {
797: /*
798: // DEBUG
799: s_iy += incy1;
800: */
801: ifracy -= ifracdy1;
802: sourceYOffset += incy1Stride;
803: }
804:
805: ++destXOffset;
806: }
807:
808: for (int x = clipMaxX; x < dst_max_x; x++) {
809: if (setBackground) {
810: int dindex = destYOffset + (destXOffset >> 5);
811: int dshift = 31 - (destXOffset & 31);
812: int delement = destData[dindex];
813: delement |= black << dshift;
814: destData[dindex] = (int) delement;
815: }
816:
817: // walk
818: if (ifracx < ifracdx1) {
819: /*
820: // DEBUG
821: s_ix += incx;
822: */
823: ifracx += ifracdx;
824: sourceXOffset += incx;
825: } else {
826: /*
827: // DEBUG
828: s_ix += incx1;
829: */
830: ifracx -= ifracdx1;
831: sourceXOffset += incx1;
832: }
833:
834: if (ifracy < ifracdy1) {
835: /*
836: // DEBUG
837: s_iy += incy;
838: */
839: ifracy += ifracdy;
840: sourceYOffset += incyStride;
841: } else {
842: /*
843: // DEBUG
844: s_iy += incy1;
845: */
846: ifracy -= ifracdy1;
847: sourceYOffset += incy1Stride;
848: }
849:
850: ++destXOffset;
851: }
852: }
853: }
854: }
|