001: /*
002: * $RCSfile: TransposeBinaryOpImage.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:46 $
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.RenderingHints;
017: import java.awt.image.ColorModel;
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.IndexColorModel;
023: import java.awt.image.MultiPixelPackedSampleModel;
024: import java.awt.image.Raster;
025: import java.awt.image.RenderedImage;
026: import java.awt.image.SampleModel;
027: import java.awt.image.WritableRaster;
028: import java.awt.image.renderable.ParameterBlock;
029: import javax.media.jai.ImageLayout;
030: import javax.media.jai.OpImage;
031: import javax.media.jai.PlanarImage;
032: import javax.media.jai.RasterAccessor;
033: import javax.media.jai.RasterFormatTag;
034: import javax.media.jai.RasterFactory;
035: import java.util.Map;
036: import javax.media.jai.JAI;
037: import javax.media.jai.WarpAffine;
038: import javax.media.jai.WarpOpImage;
039:
040: /**
041: * An OpImage class to perform a transpose (flip) of an image with a
042: * single 1-bit channel, represented using a
043: * MultiPixelPackedSampleModel and byte, short, or int DataBuffer.
044: *
045: * @since 1.0.1
046: * @see TransposeOpImage
047: */
048: final class TransposeBinaryOpImage extends TransposeOpImage {
049:
050: // Force the SampleModel and ColorModel to be the same as for
051: // the source image.
052: private static ImageLayout layoutHelper(ImageLayout layout,
053: SampleModel sm, ColorModel cm) {
054: ImageLayout newLayout;
055: if (layout != null) {
056: newLayout = (ImageLayout) layout.clone();
057: } else {
058: newLayout = new ImageLayout();
059: }
060:
061: newLayout.setSampleModel(sm);
062: newLayout.setColorModel(cm);
063:
064: return newLayout;
065: }
066:
067: // Since this operation deals with packed binary data, we do not need
068: // to expand the IndexColorModel
069: private static Map configHelper(Map configuration) {
070:
071: Map config;
072:
073: if (configuration == null) {
074: config = new RenderingHints(
075: JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
076: } else {
077:
078: config = configuration;
079:
080: if (!(config.containsKey(JAI.KEY_REPLACE_INDEX_COLOR_MODEL))) {
081: RenderingHints hints = (RenderingHints) configuration;
082: config = (RenderingHints) hints.clone();
083: config.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL,
084: Boolean.FALSE);
085: }
086: }
087:
088: return config;
089: }
090:
091: /**
092: * Constructs an TransposeBinaryOpImage from a RenderedImage source,
093: * and Transpose type. The image dimensions are determined by
094: * forward-mapping the source bounds.
095: * The tile grid layout, SampleModel, and ColorModel are specified
096: * by the image source, possibly overridden by values from the
097: * ImageLayout parameter.
098: *
099: * @param source a RenderedImage.
100: * @param layout an ImageLayout optionally containing the tile grid layout,
101: * SampleModel, and ColorModel, or null.
102: * @param type the desired Tranpose type.
103: */
104: public TransposeBinaryOpImage(RenderedImage source, Map config,
105: ImageLayout layout, int type) {
106: super (source, configHelper(config), layoutHelper(layout, source
107: .getSampleModel(), source.getColorModel()), type);
108: }
109:
110: protected void computeRect(Raster[] sources, WritableRaster dest,
111: Rectangle destRect) {
112: Raster source = sources[0];
113:
114: MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel) source
115: .getSampleModel();
116: int srcScanlineStride = mppsm.getScanlineStride();
117:
118: int incr1 = 0, incr2 = 0, s_x = 0, s_y = 0;
119:
120: int bits = 8;
121: int dataType = source.getSampleModel().getDataType();
122: if (dataType == DataBuffer.TYPE_USHORT) {
123: bits = 16;
124: } else if (dataType == DataBuffer.TYPE_INT) {
125: bits = 32;
126: }
127:
128: PlanarImage src = getSource(0);
129: int sMinX = src.getMinX();
130: int sMinY = src.getMinY();
131: int sWidth = src.getWidth();
132: int sHeight = src.getHeight();
133: int sMaxX = sMinX + sWidth - 1;
134: int sMaxY = sMinY + sHeight - 1;
135:
136: // Backwards map starting point of destination rectangle
137: int[] pt = new int[2];
138: pt[0] = destRect.x;
139: pt[1] = destRect.y;
140: mapPoint(pt, sMinX, sMinY, sMaxX, sMaxY, type, false);
141: s_x = pt[0];
142: s_y = pt[1];
143:
144: // Determine source stride along dest row (incr1) and column (incr2)
145: switch (type) {
146: case 0: // FLIP_VERTICAL
147: incr1 = 1;
148: incr2 = -bits * srcScanlineStride;
149: break;
150:
151: case 1: // FLIP_HORIZONTAL
152: incr1 = -1;
153: incr2 = bits * srcScanlineStride;
154: break;
155:
156: case 2: // FLIP_DIAGONAL;
157: incr1 = bits * srcScanlineStride;
158: incr2 = 1;
159: break;
160:
161: case 3: // FLIP_ANTIDIAGONAL
162: incr1 = -bits * srcScanlineStride;
163: incr2 = -1;
164: break;
165:
166: case 4: // ROTATE_90
167: incr1 = -bits * srcScanlineStride;
168: incr2 = 1;
169: break;
170:
171: case 5: // ROTATE_180
172: incr1 = -1;
173: incr2 = -bits * srcScanlineStride;
174: break;
175:
176: case 6: // ROTATE_270
177: incr1 = bits * srcScanlineStride;
178: incr2 = -1;
179: break;
180: }
181:
182: switch (source.getSampleModel().getDataType()) {
183: case DataBuffer.TYPE_BYTE:
184: byteLoop(source, dest, destRect, incr1, incr2, s_x, s_y);
185: break;
186:
187: case DataBuffer.TYPE_SHORT:
188: case DataBuffer.TYPE_USHORT:
189: shortLoop(source, dest, destRect, incr1, incr2, s_x, s_y);
190: break;
191:
192: case DataBuffer.TYPE_INT:
193: intLoop(source, dest, destRect, incr1, incr2, s_x, s_y);
194: break;
195: }
196: }
197:
198: private void byteLoop(Raster source, WritableRaster dest,
199: Rectangle destRect, int incr1, int incr2, int s_x, int s_y) {
200: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
201: .getSampleModel();
202: DataBufferByte sourceDB = (DataBufferByte) source
203: .getDataBuffer();
204: int sourceTransX = source.getSampleModelTranslateX();
205: int sourceTransY = source.getSampleModelTranslateY();
206: int sourceDataBitOffset = sourceSM.getDataBitOffset();
207: int sourceScanlineStride = sourceSM.getScanlineStride();
208:
209: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
210: .getSampleModel();
211: DataBufferByte destDB = (DataBufferByte) dest.getDataBuffer();
212: int destMinX = dest.getMinX();
213: int destMinY = dest.getMinY();
214: int destTransX = dest.getSampleModelTranslateX();
215: int destTransY = dest.getSampleModelTranslateY();
216: int destDataBitOffset = destSM.getDataBitOffset();
217: int destScanlineStride = destSM.getScanlineStride();
218:
219: byte[] sourceData = sourceDB.getData();
220: int sourceDBOffset = sourceDB.getOffset();
221:
222: byte[] destData = destDB.getData();
223: int destDBOffset = destDB.getOffset();
224:
225: int dx = destRect.x;
226: int dy = destRect.y;
227: int dwidth = destRect.width;
228: int dheight = destRect.height;
229:
230: int sourceOffset = 8 * (s_y - sourceTransY)
231: * sourceScanlineStride + 8 * sourceDBOffset
232: + (s_x - sourceTransX) + sourceDataBitOffset;
233:
234: int destOffset = 8 * (dy - destTransY) * destScanlineStride + 8
235: * destDBOffset + (dx - destTransX) + destDataBitOffset;
236:
237: for (int j = 0; j < dheight; j++) {
238: int sOffset = sourceOffset;
239: int dOffset = destOffset;
240: int selement, val, dindex, delement;
241:
242: int i = 0;
243: while ((i < dwidth) && ((dOffset & 7) != 0)) {
244: selement = sourceData[sOffset >> 3];
245: val = (selement >> (7 - (sOffset & 7))) & 0x1;
246:
247: dindex = dOffset >> 3;
248: int dshift = 7 - (dOffset & 7);
249: delement = destData[dindex];
250: delement |= val << dshift;
251: destData[dindex] = (byte) delement;
252:
253: sOffset += incr1;
254: ++dOffset;
255: ++i;
256: }
257:
258: dindex = dOffset >> 3;
259: if ((incr1 & 7) == 0) {
260: //
261: // We are stepping along Y in the source so the shift
262: // position for each source pixel is fixed for the entire
263: // destination scanline.
264: //
265: int shift = 7 - (sOffset & 7);
266: int offset = sOffset >> 3;
267: int incr = incr1 >> 3;
268:
269: while (i < dwidth - 7) {
270: selement = sourceData[offset];
271: val = (selement >> shift) & 0x1;
272: delement = val << 7;
273: offset += incr;
274:
275: selement = sourceData[offset];
276: val = (selement >> shift) & 0x1;
277: delement |= val << 6;
278: offset += incr;
279:
280: selement = sourceData[offset];
281: val = (selement >> shift) & 0x1;
282: delement |= val << 5;
283: offset += incr;
284:
285: selement = sourceData[offset];
286: val = (selement >> shift) & 0x1;
287: delement |= val << 4;
288: offset += incr;
289:
290: selement = sourceData[offset];
291: val = (selement >> shift) & 0x1;
292: delement |= val << 3;
293: offset += incr;
294:
295: selement = sourceData[offset];
296: val = (selement >> shift) & 0x1;
297: delement |= val << 2;
298: offset += incr;
299:
300: selement = sourceData[offset];
301: val = (selement >> shift) & 0x1;
302: delement |= val << 1;
303: offset += incr;
304:
305: selement = sourceData[offset];
306: val = (selement >> shift) & 0x1;
307: delement |= val;
308: offset += incr;
309:
310: destData[dindex] = (byte) delement;
311:
312: sOffset += 8 * incr1;
313: dOffset += 8;
314: i += 8;
315: ++dindex;
316: }
317: } else {
318: //
319: // If we are here, incr1 must be 1 or -1.
320: // There are further optimization opportunites here.
321: //
322: while (i < dwidth - 7) {
323: selement = sourceData[sOffset >> 3];
324: val = (selement >> (7 - (sOffset & 7))) & 0x1;
325: delement = val << 7;
326: sOffset += incr1;
327:
328: selement = sourceData[sOffset >> 3];
329: val = (selement >> (7 - (sOffset & 7))) & 0x1;
330: delement |= val << 6;
331: sOffset += incr1;
332:
333: selement = sourceData[sOffset >> 3];
334: val = (selement >> (7 - (sOffset & 7))) & 0x1;
335: delement |= val << 5;
336: sOffset += incr1;
337:
338: selement = sourceData[sOffset >> 3];
339: val = (selement >> (7 - (sOffset & 7))) & 0x1;
340: delement |= val << 4;
341: sOffset += incr1;
342:
343: selement = sourceData[sOffset >> 3];
344: val = (selement >> (7 - (sOffset & 7))) & 0x1;
345: delement |= val << 3;
346: sOffset += incr1;
347:
348: selement = sourceData[sOffset >> 3];
349: val = (selement >> (7 - (sOffset & 7))) & 0x1;
350: delement |= val << 2;
351: sOffset += incr1;
352:
353: selement = sourceData[sOffset >> 3];
354: val = (selement >> (7 - (sOffset & 7))) & 0x1;
355: delement |= val << 1;
356: sOffset += incr1;
357:
358: selement = sourceData[sOffset >> 3];
359: val = (selement >> (7 - (sOffset & 7))) & 0x1;
360: delement |= val;
361: sOffset += incr1;
362:
363: destData[dindex] = (byte) delement;
364:
365: dOffset += 8;
366: i += 8;
367: ++dindex;
368: }
369: }
370:
371: while (i < dwidth) {
372: selement = sourceData[sOffset >> 3];
373: val = (selement >> (7 - (sOffset & 7))) & 0x1;
374:
375: dindex = dOffset >> 3;
376: int dshift = 7 - (dOffset & 7);
377: delement = destData[dindex];
378: delement |= val << dshift;
379: destData[dindex] = (byte) delement;
380:
381: sOffset += incr1;
382: ++dOffset;
383: ++i;
384: }
385:
386: sourceOffset += incr2;
387: destOffset += 8 * destScanlineStride;
388: }
389: }
390:
391: private void shortLoop(Raster source, Raster dest,
392: Rectangle destRect, int incr1, int incr2, int s_x, int s_y) {
393: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
394: .getSampleModel();
395: DataBufferUShort sourceDB = (DataBufferUShort) source
396: .getDataBuffer();
397: int sourceTransX = source.getSampleModelTranslateX();
398: int sourceTransY = source.getSampleModelTranslateY();
399: int sourceDataBitOffset = sourceSM.getDataBitOffset();
400: int sourceScanlineStride = sourceSM.getScanlineStride();
401:
402: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
403: .getSampleModel();
404: DataBufferUShort destDB = (DataBufferUShort) dest
405: .getDataBuffer();
406: int destMinX = dest.getMinX();
407: int destMinY = dest.getMinY();
408: int destTransX = dest.getSampleModelTranslateX();
409: int destTransY = dest.getSampleModelTranslateY();
410: int destDataBitOffset = destSM.getDataBitOffset();
411: int destScanlineStride = destSM.getScanlineStride();
412:
413: short[] sourceData = sourceDB.getData();
414: int sourceDBOffset = sourceDB.getOffset();
415:
416: short[] destData = destDB.getData();
417: int destDBOffset = destDB.getOffset();
418:
419: int dx = destRect.x;
420: int dy = destRect.y;
421: int dwidth = destRect.width;
422: int dheight = destRect.height;
423:
424: int sourceOffset = 16 * (s_y - sourceTransY)
425: * sourceScanlineStride + 16 * sourceDBOffset
426: + (s_x - sourceTransX) + sourceDataBitOffset;
427:
428: int destOffset = 16 * (dy - destTransY) * destScanlineStride
429: + 16 * destDBOffset + (dx - destTransX)
430: + destDataBitOffset;
431:
432: for (int j = 0; j < dheight; j++) {
433: int sOffset = sourceOffset;
434: int dOffset = destOffset;
435: int selement, val, dindex, delement;
436:
437: int i = 0;
438: while ((i < dwidth) && ((dOffset & 15) != 0)) {
439: selement = sourceData[sOffset >> 4];
440: val = (selement >> (15 - (sOffset & 15))) & 0x1;
441:
442: dindex = dOffset >> 4;
443: int dshift = 15 - (dOffset & 15);
444: delement = destData[dindex];
445: delement |= val << dshift;
446: destData[dindex] = (short) delement;
447:
448: sOffset += incr1;
449: ++dOffset;
450: ++i;
451: }
452:
453: dindex = dOffset >> 4;
454: if ((incr1 & 15) == 0) {
455: int shift = 15 - (sOffset & 5);
456: int offset = sOffset >> 4;
457: int incr = incr1 >> 4;
458:
459: while (i < dwidth - 15) {
460: delement = 0;
461: for (int b = 15; b >= 0; b--) {
462: selement = sourceData[offset];
463: val = (selement >> shift) & 0x1;
464: delement |= val << b;
465: offset += incr;
466: }
467:
468: destData[dindex] = (short) delement;
469:
470: sOffset += 16 * incr1;
471: dOffset += 16;
472: i += 16;
473: ++dindex;
474: }
475: } else {
476: while (i < dwidth - 15) {
477: delement = 0;
478: for (int b = 15; b >= 0; b--) {
479: selement = sourceData[sOffset >> 4];
480: val = (selement >> (15 - (sOffset & 15))) & 0x1;
481: delement |= val << b;
482: sOffset += incr1;
483: }
484:
485: destData[dindex] = (short) delement;
486:
487: dOffset += 15;
488: i += 16;
489: ++dindex;
490: }
491: }
492:
493: while (i < dwidth) {
494: selement = sourceData[sOffset >> 4];
495: val = (selement >> (15 - (sOffset & 15))) & 0x1;
496:
497: dindex = dOffset >> 4;
498: int dshift = 15 - (dOffset & 15);
499: delement = destData[dindex];
500: delement |= val << dshift;
501: destData[dindex] = (short) delement;
502:
503: sOffset += incr1;
504: ++dOffset;
505: ++i;
506: }
507:
508: sourceOffset += incr2;
509: destOffset += 16 * destScanlineStride;
510: }
511: }
512:
513: private void intLoop(Raster source, Raster dest,
514: Rectangle destRect, int incr1, int incr2, int s_x, int s_y) {
515: MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
516: .getSampleModel();
517: DataBufferInt sourceDB = (DataBufferInt) source.getDataBuffer();
518: int sourceTransX = source.getSampleModelTranslateX();
519: int sourceTransY = source.getSampleModelTranslateY();
520: int sourceDataBitOffset = sourceSM.getDataBitOffset();
521: int sourceScanlineStride = sourceSM.getScanlineStride();
522:
523: MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest
524: .getSampleModel();
525: DataBufferInt destDB = (DataBufferInt) dest.getDataBuffer();
526: int destMinX = dest.getMinX();
527: int destMinY = dest.getMinY();
528: int destTransX = dest.getSampleModelTranslateX();
529: int destTransY = dest.getSampleModelTranslateY();
530: int destDataBitOffset = destSM.getDataBitOffset();
531: int destScanlineStride = destSM.getScanlineStride();
532:
533: int[] sourceData = sourceDB.getData();
534: int sourceDBOffset = sourceDB.getOffset();
535:
536: int[] destData = destDB.getData();
537: int destDBOffset = destDB.getOffset();
538:
539: int dx = destRect.x;
540: int dy = destRect.y;
541: int dwidth = destRect.width;
542: int dheight = destRect.height;
543:
544: int sourceOffset = 32 * (s_y - sourceTransY)
545: * sourceScanlineStride + 32 * sourceDBOffset
546: + (s_x - sourceTransX) + sourceDataBitOffset;
547:
548: int destOffset = 32 * (dy - destTransY) * destScanlineStride
549: + 32 * destDBOffset + (dx - destTransX)
550: + destDataBitOffset;
551:
552: for (int j = 0; j < dheight; j++) {
553: int sOffset = sourceOffset;
554: int dOffset = destOffset;
555: int selement, val, dindex, delement;
556:
557: int i = 0;
558: while ((i < dwidth) && ((dOffset & 31) != 0)) {
559: selement = sourceData[sOffset >> 5];
560: val = (selement >> (31 - (sOffset & 31))) & 0x1;
561:
562: dindex = dOffset >> 5;
563: int dshift = 31 - (dOffset & 31);
564: delement = destData[dindex];
565: delement |= val << dshift;
566: destData[dindex] = (int) delement;
567:
568: sOffset += incr1;
569: ++dOffset;
570: ++i;
571: }
572:
573: dindex = dOffset >> 5;
574: if ((incr1 & 31) == 0) {
575: int shift = 31 - (sOffset & 5);
576: int offset = sOffset >> 5;
577: int incr = incr1 >> 5;
578:
579: while (i < dwidth - 31) {
580: delement = 0;
581: for (int b = 31; b >= 0; b--) {
582: selement = sourceData[offset];
583: val = (selement >> shift) & 0x1;
584: delement |= val << b;
585: offset += incr;
586: }
587:
588: destData[dindex] = (int) delement;
589:
590: sOffset += 32 * incr1;
591: dOffset += 32;
592: i += 32;
593: ++dindex;
594: }
595: } else {
596: while (i < dwidth - 31) {
597: delement = 0;
598: for (int b = 31; b >= 0; b--) {
599: selement = sourceData[sOffset >> 5];
600: val = (selement >> (31 - (sOffset & 31))) & 0x1;
601: delement |= val << b;
602: sOffset += incr1;
603: }
604:
605: destData[dindex] = (int) delement;
606:
607: dOffset += 31;
608: i += 32;
609: ++dindex;
610: }
611: }
612:
613: while (i < dwidth) {
614: selement = sourceData[sOffset >> 5];
615: val = (selement >> (31 - (sOffset & 31))) & 0x1;
616:
617: dindex = dOffset >> 5;
618: int dshift = 31 - (dOffset & 31);
619: delement = destData[dindex];
620: delement |= val << dshift;
621: destData[dindex] = (int) delement;
622:
623: sOffset += incr1;
624: ++dOffset;
625: ++i;
626: }
627:
628: sourceOffset += incr2;
629: destOffset += 32 * destScanlineStride;
630: }
631: }
632: }
|