Source Code Cross Referenced for OrderedDitherOpImage.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » opimage » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » Java Advanced Imaging » com.sun.media.jai.opimage 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: OrderedDitherOpImage.java,v $
0003:         *
0004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * Use is subject to license terms.
0007:         *
0008:         * $Revision: 1.1 $
0009:         * $Date: 2005/02/11 04:56:38 $
0010:         * $State: Exp $
0011:         */
0012:        package com.sun.media.jai.opimage;
0013:
0014:        import java.awt.Rectangle;
0015:        import java.awt.image.ColorModel;
0016:        import java.awt.image.DataBuffer;
0017:        import java.awt.image.IndexColorModel;
0018:        import java.awt.image.MultiPixelPackedSampleModel;
0019:        import java.awt.image.Raster;
0020:        import java.awt.image.RenderedImage;
0021:        import java.awt.image.SampleModel;
0022:        import java.awt.image.WritableRaster;
0023:        import java.lang.ref.SoftReference;
0024:        import java.util.Arrays;
0025:        import java.util.Map;
0026:        import java.util.Vector;
0027:        import javax.media.jai.ColorCube;
0028:        import javax.media.jai.ImageLayout;
0029:        import javax.media.jai.KernelJAI;
0030:        import javax.media.jai.OpImage;
0031:        import javax.media.jai.PointOpImage;
0032:        import javax.media.jai.RasterAccessor;
0033:        import javax.media.jai.RasterFormatTag;
0034:        import javax.media.jai.RasterFactory;
0035:        import com.sun.media.jai.util.JDKWorkarounds;
0036:        import com.sun.media.jai.util.ImageUtil;
0037:
0038:        /**
0039:         * An <code>OpImage</code> implementing the ordered dither operation as
0040:         * described in <code>javax.media.jai.operator.OrderedDitherDescriptor</code>.
0041:         *
0042:         * <p>This <code>OpImage</code> performs dithering of its source image into
0043:         * a single band image using a specified color cube and dither mask.
0044:         *
0045:         * @see javax.media.jai.KernelJAI
0046:         * @see javax.media.jai.ColorCube
0047:         *
0048:         * @since EA3
0049:         *
0050:         */
0051:        final class OrderedDitherOpImage extends PointOpImage {
0052:            /**
0053:             * Flag indicating that the generic implementation is used.
0054:             */
0055:            private static final int TYPE_OD_GENERAL = 0;
0056:
0057:            /**
0058:             * Flag indicating that the optimized three-band implementation is used
0059:             * (byte data only).
0060:             */
0061:            private static final int TYPE_OD_BYTE_LUT_3BAND = 1;
0062:
0063:            /**
0064:             * Flag indicating that the optimized N-band implementation is used
0065:             * (byte data only).
0066:             */
0067:            private static final int TYPE_OD_BYTE_LUT_NBAND = 2;
0068:
0069:            /**
0070:             * Maximim dither LUT size: 16x16 4-band byte dither mask.
0071:             */
0072:            private static final int DITHER_LUT_LENGTH_MAX = 16 * 16 * 4 * 256;
0073:
0074:            /**
0075:             * The maximum number of elements in the <code>DitherLUT</code> cache.
0076:             */
0077:            private static final int DITHER_LUT_CACHE_LENGTH_MAX = 4;
0078:
0079:            /**
0080:             * A cache of <code>SoftReference</code>s to <code>DitherLUT</code>
0081:             * inner class instances.
0082:             */
0083:            private static Vector ditherLUTCache = new Vector(0,
0084:                    DITHER_LUT_CACHE_LENGTH_MAX);
0085:
0086:            /**
0087:             * Flag indicating the implementation to be used.
0088:             */
0089:            private int odType = TYPE_OD_GENERAL;
0090:
0091:            /**
0092:             * The number of bands in the source image.
0093:             */
0094:            protected int numBands;
0095:
0096:            /**
0097:             * The array of color cube dimensions-less-one.
0098:             */
0099:            protected int[] dims;
0100:
0101:            /**
0102:             * The array of color cube multipliers.
0103:             */
0104:            protected int[] mults;
0105:
0106:            /**
0107:             * The adjusted offset of the color cube.
0108:             */
0109:            protected int adjustedOffset;
0110:
0111:            /**
0112:             * The width of the dither mask.
0113:             */
0114:            protected int maskWidth;
0115:
0116:            /**
0117:             * The height of the dither mask.
0118:             */
0119:            protected int maskHeight;
0120:
0121:            /**
0122:             * The dither mask matrix scaled by 255.
0123:             */
0124:            protected byte[][] maskDataByte;
0125:
0126:            /**
0127:             * The dither mask matrix scaled to USHORT range.
0128:             */
0129:            protected int[][] maskDataInt;
0130:
0131:            /**
0132:             * The dither mask matrix scaled to "unsigned int" range.
0133:             */
0134:            protected long[][] maskDataLong;
0135:
0136:            /**
0137:             * The dither mask matrix.
0138:             */
0139:            protected float[][] maskDataFloat;
0140:
0141:            /**
0142:             * An inner class instance representing a dither lookup table. Used
0143:             * for byte data only when the table size is within a specified limit.
0144:             */
0145:            protected DitherLUT odLUT = null;
0146:
0147:            /**
0148:             * Force the destination image to be single-banded.
0149:             */
0150:            private static ImageLayout layoutHelper(ImageLayout layout,
0151:                    RenderedImage source, ColorCube colorMap) {
0152:                ImageLayout il;
0153:                if (layout == null) {
0154:                    il = new ImageLayout(source);
0155:                } else {
0156:                    il = (ImageLayout) layout.clone();
0157:                }
0158:
0159:                // Get the SampleModel.
0160:                SampleModel sm = il.getSampleModel(source);
0161:
0162:                // Ensure an appropriate SampleModel.
0163:                if (colorMap.getNumBands() == 1
0164:                        && colorMap.getNumEntries() == 2
0165:                        && !ImageUtil.isBinary(il.getSampleModel(source))) {
0166:                    sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
0167:                            il.getTileWidth(source), il.getTileHeight(source),
0168:                            1);
0169:                    il.setSampleModel(sm);
0170:                }
0171:
0172:                // Make sure that this OpImage is single-banded.
0173:                if (sm.getNumBands() != 1) {
0174:                    // TODO: Force to SHORT or USHORT if FLOAT or DOUBLE?
0175:                    sm = RasterFactory.createComponentSampleModel(sm, sm
0176:                            .getTransferType(), sm.getWidth(), sm.getHeight(),
0177:                            1);
0178:                    il.setSampleModel(sm);
0179:
0180:                    // Clear the ColorModel mask if needed.
0181:                    ColorModel cm = il.getColorModel(null);
0182:                    if (cm != null
0183:                            && !JDKWorkarounds.areCompatibleDataModels(sm, cm)) {
0184:                        // Clear the mask bit if incompatible.
0185:                        il.unsetValid(ImageLayout.COLOR_MODEL_MASK);
0186:                    }
0187:                }
0188:
0189:                // Set an IndexColorModel on the image if:
0190:                // a. none is provided in the layout;
0191:                // b. source, destination, and colormap have byte data type;
0192:                // c. the colormap has 3 bands; and
0193:                // d. the source ColorModel is either null or is non-null
0194:                //    and has a ColorSpace equal to CS_sRGB.
0195:                if ((layout == null || !il
0196:                        .isValid(ImageLayout.COLOR_MODEL_MASK))
0197:                        && source.getSampleModel().getDataType() == DataBuffer.TYPE_BYTE
0198:                        && il.getSampleModel(null).getDataType() == DataBuffer.TYPE_BYTE
0199:                        && colorMap.getDataType() == DataBuffer.TYPE_BYTE
0200:                        && colorMap.getNumBands() == 3) {
0201:                    ColorModel cm = source.getColorModel();
0202:                    if (cm == null
0203:                            || (cm != null && cm.getColorSpace().isCS_sRGB())) {
0204:                        int size = colorMap.getNumEntries();
0205:                        byte[][] cmap = new byte[3][256];
0206:                        for (int i = 0; i < 3; i++) {
0207:                            byte[] band = cmap[i];
0208:                            byte[] data = colorMap.getByteData(i);
0209:                            int offset = colorMap.getOffset(i);
0210:                            int end = offset + size;
0211:                            for (int j = 0; j < offset; j++) {
0212:                                band[j] = (byte) 0;
0213:                            }
0214:                            for (int j = offset; j < end; j++) {
0215:                                band[j] = data[j - offset];
0216:                            }
0217:                            for (int j = end; j < 256; j++) {
0218:                                band[j] = (byte) 0xFF;
0219:                            }
0220:                        }
0221:
0222:                        il.setColorModel(new IndexColorModel(8, 256, cmap[0],
0223:                                cmap[1], cmap[2]));
0224:                    }
0225:                }
0226:
0227:                return il;
0228:            }
0229:
0230:            /**
0231:             * Constructs an OrderedDitherOpImage object. May be used to convert a
0232:             * single- or multi-band image into a single-band image with a color map.
0233:             *
0234:             * <p>The image dimensions are derived from the source image. The tile
0235:             * grid layout, SampleModel, and ColorModel may optionally be specified
0236:             * by an ImageLayout object.
0237:             *
0238:             * @param source A RenderedImage.
0239:             * @param layout An ImageLayout optionally containing the tile grid layout,
0240:             * SampleModel, and ColorModel, or null.
0241:             * @param colorMap The color map to use which must have a number of bands
0242:             * equal to the number of bands in the source image. The offset of this
0243:             * <code>ColorCube</code> must be the same for all bands.
0244:             * @param ditherMask An an array of <code>KernelJAI</code> objects the
0245:             * dimension of which must equal the number of bands in the source image.
0246:             * The <i>n</i>th element of the array contains a <code>KernelJAI</code>
0247:             * object which represents the dither mask matrix for the corresponding
0248:             * band. All <code>KernelJAI</code> objects in the array must have the
0249:             * same dimensions and contain floating point values between 0.0F and 1.0F.
0250:             */
0251:            public OrderedDitherOpImage(RenderedImage source, Map config,
0252:                    ImageLayout layout, ColorCube colorMap,
0253:                    KernelJAI[] ditherMask) {
0254:                // Construct as a PointOpImage.
0255:                super (source, layoutHelper(layout, source, colorMap), config,
0256:                        true);
0257:
0258:                // Initialize the instance variables derived from the color map.
0259:                numBands = colorMap.getNumBands();
0260:                mults = (int[]) colorMap.getMultipliers().clone();
0261:                dims = (int[]) colorMap.getDimsLessOne().clone();
0262:                adjustedOffset = colorMap.getAdjustedOffset();
0263:
0264:                // Initialize the instance variables derived from the dither mask.
0265:                maskWidth = ditherMask[0].getWidth();
0266:                maskHeight = ditherMask[0].getHeight();
0267:
0268:                // Initialize the data required to effect the operation.
0269:                // XXX Postpone until first invocation of computeRect()?
0270:                initializeDitherData(sampleModel.getTransferType(), ditherMask);
0271:
0272:                // Set flag to permit in-place operation.
0273:                permitInPlaceOperation();
0274:            }
0275:
0276:            /**
0277:             * An inner class represting a lookup table to be used in the optimized
0278:             * implementations of ordered dithering of byte data.
0279:             */
0280:            private class DitherLUT {
0281:                // Clones of color cube and dither mask data used to create the
0282:                // dithering lookup table.
0283:                private int[] dimsCache;
0284:                private int[] multsCache;
0285:                private byte[][] maskDataCache;
0286:
0287:                // Stride values of the dither lookup table.
0288:                public int ditherLUTBandStride;
0289:                public int ditherLUTRowStride;
0290:                public int ditherLUTColStride;
0291:
0292:                // The dither lookup table.
0293:                public byte[] ditherLUT;
0294:
0295:                /**
0296:                 * Create an inner class object representing an ordered dither
0297:                 * lookup table for byte data.
0298:                 *
0299:                 * @param dims The color cube dimensions less one.
0300:                 * @param mults The color cube multipliers.
0301:                 * @param maskData The dither mask data scaled to byte range.
0302:                 */
0303:                DitherLUT(int[] dims, int[] mults, byte[][] maskData) {
0304:                    // Clone the constructor parameters.
0305:                    dimsCache = (int[]) dims.clone();
0306:                    multsCache = (int[]) mults.clone();
0307:                    maskDataCache = new byte[maskData.length][];
0308:                    for (int i = 0; i < maskData.length; i++) {
0309:                        maskDataCache[i] = (byte[]) maskData[i].clone();
0310:                    }
0311:
0312:                    // Set dither lookup table stride values.
0313:                    ditherLUTColStride = 256;
0314:                    ditherLUTRowStride = maskWidth * ditherLUTColStride;
0315:                    ditherLUTBandStride = maskHeight * ditherLUTRowStride;
0316:
0317:                    //
0318:                    // Construct the big dither table. If indexed as a
0319:                    // multi-dimensional array this would be equivalent to:
0320:                    //
0321:                    //   ditherLUT[band][ditherRow][ditherColumn][grayLevel]
0322:                    //
0323:                    // where ditherRow, Col are modulo the dither mask size.
0324:                    //
0325:                    // To minimize the table construction cost, precalculate
0326:                    // the bin value for a given band and gray level. Then use
0327:                    // the dithermask threshold value to determine whether to bump
0328:                    // the value up one level. Thus most of the work is done in the
0329:                    // outer loops, with a simple comparison left for the inner loop.
0330:                    //
0331:                    ditherLUT = new byte[numBands * ditherLUTBandStride];
0332:
0333:                    int pDithBand = 0;
0334:                    int maskSize2D = maskWidth * maskHeight;
0335:                    for (int band = 0; band < numBands; band++) {
0336:                        int step = dims[band];
0337:                        int delta = mults[band];
0338:                        byte[] maskDataBand = maskData[band];
0339:                        int sum = 0;
0340:                        for (int gray = 0; gray < 256; gray++) {
0341:                            int tmp = sum;
0342:                            int frac = (int) (tmp & 0xff);
0343:                            int bin = tmp >> 8;
0344:                            int lowVal = bin * delta;
0345:                            int highVal = lowVal + delta;
0346:                            int pDith = pDithBand + gray;
0347:                            for (int dcount = 0; dcount < maskSize2D; dcount++) {
0348:                                int threshold = maskDataBand[dcount] & 0xff;
0349:                                if (frac > threshold) {
0350:                                    ditherLUT[pDith] = (byte) (highVal & 0xff);
0351:                                } else {
0352:                                    ditherLUT[pDith] = (byte) (lowVal & 0xff);
0353:                                }
0354:                                pDith += 256;
0355:                            } // end dithermask entry
0356:                            sum += step;
0357:                        } // end gray level
0358:                        pDithBand += ditherLUTBandStride;
0359:                    } // end band
0360:                }
0361:
0362:                /**
0363:                 * Determine whether the internal table of this <code>DitherLUT</code>
0364:                 * is the same as that which would be generated using the supplied
0365:                 * parameters.
0366:                 *
0367:                 * @param dims The color cube dimensions less one.
0368:                 * @param mults The color cube multipliers.
0369:                 * @param maskData The dither mask data scaled to byte range.
0370:                 *
0371:                 * @return Value indicating equivalence of dither LUTs.
0372:                 */
0373:                public boolean equals(int[] dims, int[] mults, byte[][] maskData) {
0374:                    // Check dimensions.
0375:                    if (dims.length != dimsCache.length) {
0376:                        return false;
0377:                    }
0378:
0379:                    for (int i = 0; i < dims.length; i++) {
0380:                        if (dims[i] != dimsCache[i])
0381:                            return false;
0382:                    }
0383:
0384:                    // Check multipliers.
0385:                    if (mults.length != multsCache.length) {
0386:                        return false;
0387:                    }
0388:
0389:                    for (int i = 0; i < mults.length; i++) {
0390:                        if (mults[i] != multsCache[i])
0391:                            return false;
0392:                    }
0393:
0394:                    // Check dither mask.
0395:                    if (maskData.length != maskDataByte.length) {
0396:                        return false;
0397:                    }
0398:
0399:                    for (int i = 0; i < maskData.length; i++) {
0400:                        if (maskData[i].length != maskDataCache[i].length)
0401:                            return false;
0402:                        byte[] refData = maskDataCache[i];
0403:                        byte[] data = maskData[i];
0404:                        for (int j = 0; j < maskData[i].length; j++) {
0405:                            if (data[j] != refData[j])
0406:                                return false;
0407:                        }
0408:                    }
0409:
0410:                    return true;
0411:                }
0412:            } // End inner class DitherLUT.
0413:
0414:            /**
0415:             * Initialize data type-dependent fields including the dither mask data
0416:             * arrays and, for optimized byte cases, the dither lookup table object.
0417:             *
0418:             * @param dataType The data type as defined in <code>DataBuffer</code>.
0419:             * @param ditherMask The dither mask represented as an array of
0420:             * <code>KernelJAI</code> objects.
0421:             */
0422:            private void initializeDitherData(int dataType,
0423:                    KernelJAI[] ditherMask) {
0424:                switch (dataType) {
0425:                case DataBuffer.TYPE_BYTE: {
0426:                    maskDataByte = new byte[ditherMask.length][];
0427:                    for (int i = 0; i < maskDataByte.length; i++) {
0428:                        float[] maskData = ditherMask[i].getKernelData();
0429:                        maskDataByte[i] = new byte[maskData.length];
0430:                        for (int j = 0; j < maskData.length; j++) {
0431:                            maskDataByte[i][j] = (byte) ((int) (maskData[j] * 255.0F) & 0xff);
0432:                        }
0433:                    }
0434:
0435:                    initializeDitherLUT();
0436:                }
0437:                    break;
0438:
0439:                case DataBuffer.TYPE_SHORT:
0440:                case DataBuffer.TYPE_USHORT: {
0441:                    int scaleFactor = (int) Short.MAX_VALUE
0442:                            - (int) Short.MIN_VALUE;
0443:                    maskDataInt = new int[ditherMask.length][];
0444:                    for (int i = 0; i < maskDataInt.length; i++) {
0445:                        float[] maskData = ditherMask[i].getKernelData();
0446:                        maskDataInt[i] = new int[maskData.length];
0447:                        for (int j = 0; j < maskData.length; j++) {
0448:                            maskDataInt[i][j] = (int) (maskData[j] * scaleFactor);
0449:                        }
0450:                    }
0451:                }
0452:                    break;
0453:
0454:                case DataBuffer.TYPE_INT: {
0455:                    long scaleFactor = (long) Integer.MAX_VALUE
0456:                            - (long) Integer.MIN_VALUE;
0457:                    maskDataLong = new long[ditherMask.length][];
0458:                    for (int i = 0; i < maskDataLong.length; i++) {
0459:                        float[] maskData = ditherMask[i].getKernelData();
0460:                        maskDataLong[i] = new long[maskData.length];
0461:                        for (int j = 0; j < maskData.length; j++) {
0462:                            maskDataLong[i][j] = (long) (maskData[j] * scaleFactor);
0463:                        }
0464:                    }
0465:                }
0466:                    break;
0467:
0468:                case DataBuffer.TYPE_FLOAT:
0469:                case DataBuffer.TYPE_DOUBLE: {
0470:                    maskDataFloat = new float[ditherMask.length][];
0471:                    for (int i = 0; i < maskDataFloat.length; i++) {
0472:                        maskDataFloat[i] = ditherMask[i].getKernelData();
0473:                    }
0474:                }
0475:                    break;
0476:
0477:                default:
0478:                    throw new RuntimeException(JaiI18N
0479:                            .getString("OrderedDitherOpImage0"));
0480:                }
0481:            }
0482:
0483:            /**
0484:             * For byte data only, initialize the dither lookup table if it is small
0485:             * enough and set the type of ordered dither implementation to use.
0486:             */
0487:            private synchronized void initializeDitherLUT() {
0488:                // Check whether a DitherLUT may be used.
0489:                if (numBands * maskHeight * maskWidth * 256 > DITHER_LUT_LENGTH_MAX) {
0490:                    odType = TYPE_OD_GENERAL; // NB: This is superfluous.
0491:                    return;
0492:                }
0493:
0494:                // If execution has proceeded to this point then this is one of the
0495:                // optimized cases so set the type flag accordingly.
0496:                odType = numBands == 3 ? TYPE_OD_BYTE_LUT_3BAND
0497:                        : TYPE_OD_BYTE_LUT_NBAND;
0498:
0499:                // Check whether an equivalent DitherLUT object already exists.
0500:                int index = 0;
0501:                while (index < ditherLUTCache.size()) {
0502:                    SoftReference lutRef = (SoftReference) ditherLUTCache
0503:                            .get(index);
0504:                    DitherLUT lut = (DitherLUT) lutRef.get();
0505:                    if (lut == null) {
0506:                        // The reference has been cleared: remove the Vector element
0507:                        // but do not increment the loop index.
0508:                        ditherLUTCache.remove(index);
0509:                    } else {
0510:                        if (lut.equals(dims, mults, maskDataByte)) {
0511:                            // Found an equivalent DitherLUT so use it and exit loop.
0512:                            odLUT = lut;
0513:                            break;
0514:                        }
0515:                        // Move on to the next Vector element.
0516:                        index++;
0517:                    }
0518:                }
0519:
0520:                // Create a new DitherLUT if an equivalent one was not found.
0521:                if (odLUT == null) {
0522:                    odLUT = new DitherLUT(dims, mults, maskDataByte);
0523:                    // Cache a reference to the DitherLUT if there is room.
0524:                    if (ditherLUTCache.size() < DITHER_LUT_CACHE_LENGTH_MAX) {
0525:                        ditherLUTCache.add(new SoftReference(odLUT));
0526:                    }
0527:                }
0528:            }
0529:
0530:            /**
0531:             * Computes a tile of the dithered destination image.
0532:             *
0533:             * @param sources   Cobbled sources, guaranteed to provide all the
0534:             *                  source data necessary for computing the rectangle.
0535:             * @param dest      The tile containing the rectangle to be computed.
0536:             * @param destRect  The rectangle within the tile to be computed.
0537:             */
0538:            protected void computeRect(Raster[] sources, WritableRaster dest,
0539:                    Rectangle destRect) {
0540:                // Set format tags
0541:                RasterFormatTag[] formatTags = null;
0542:                if (ImageUtil.isBinary(getSampleModel())
0543:                        && !ImageUtil.isBinary(getSourceImage(0)
0544:                                .getSampleModel())) {
0545:                    // XXX Workaround for bug 4521097. This branch of the if-block
0546:                    // should be deleted once bug 4668327 is fixed.
0547:                    RenderedImage[] sourceArray = new RenderedImage[] { getSourceImage(0) };
0548:                    RasterFormatTag[] sourceTags = RasterAccessor
0549:                            .findCompatibleTags(sourceArray, sourceArray[0]);
0550:                    RasterFormatTag[] destTags = RasterAccessor
0551:                            .findCompatibleTags(sourceArray, this );
0552:                    formatTags = new RasterFormatTag[] { sourceTags[0],
0553:                            destTags[1] };
0554:                } else {
0555:                    // Retrieve format tags.
0556:                    formatTags = getFormatTags();
0557:                }
0558:
0559:                RasterAccessor src = new RasterAccessor(sources[0], destRect,
0560:                        formatTags[0], getSource(0).getColorModel());
0561:                RasterAccessor dst = new RasterAccessor(dest, destRect,
0562:                        formatTags[1], getColorModel());
0563:
0564:                switch (src.getDataType()) {
0565:                case DataBuffer.TYPE_BYTE:
0566:                    computeRectByte(src, dst);
0567:                    break;
0568:                case DataBuffer.TYPE_SHORT:
0569:                    computeRectShort(src, dst);
0570:                    break;
0571:                case DataBuffer.TYPE_USHORT:
0572:                    computeRectUShort(src, dst);
0573:                    break;
0574:                case DataBuffer.TYPE_INT:
0575:                    computeRectInt(src, dst);
0576:                    break;
0577:                case DataBuffer.TYPE_FLOAT:
0578:                    computeRectFloat(src, dst);
0579:                    break;
0580:                case DataBuffer.TYPE_DOUBLE:
0581:                    computeRectDouble(src, dst);
0582:                    break;
0583:                default:
0584:                    throw new RuntimeException(JaiI18N
0585:                            .getString("OrderedDitherOpImage1"));
0586:                }
0587:
0588:                dst.copyDataToRaster();
0589:            }
0590:
0591:            /**
0592:             * Computes a <code>Rectangle</code> of data for byte imagery.
0593:             */
0594:            private void computeRectByte(RasterAccessor src, RasterAccessor dst) {
0595:                int sbands = src.getNumBands();
0596:                int sLineStride = src.getScanlineStride();
0597:                int sPixelStride = src.getPixelStride();
0598:                int[] sBandOffsets = src.getBandOffsets();
0599:                byte[][] sData = src.getByteDataArrays();
0600:
0601:                int dwidth = dst.getWidth();
0602:                int dheight = dst.getHeight();
0603:                int dLineStride = dst.getScanlineStride();
0604:                int dPixelStride = dst.getPixelStride();
0605:                int dBandOffset = dst.getBandOffset(0);
0606:                byte[] dData = dst.getByteDataArray(0);
0607:
0608:                int xMod = dst.getX() % maskWidth;
0609:                int y0 = dst.getY();
0610:
0611:                switch (odType) {
0612:                case TYPE_OD_BYTE_LUT_3BAND:
0613:                case TYPE_OD_BYTE_LUT_NBAND:
0614:                    int[] srcLineOffsets = (int[]) sBandOffsets.clone();
0615:                    int[] srcPixelOffsets = (int[]) srcLineOffsets.clone();
0616:                    int dLineOffset = dBandOffset;
0617:
0618:                    for (int h = 0; h < dheight; h++) {
0619:                        int yMod = (y0 + h) % maskHeight;
0620:
0621:                        if (odType == TYPE_OD_BYTE_LUT_3BAND) {
0622:                            computeLineByteLUT3(sData, srcPixelOffsets,
0623:                                    sPixelStride, dData, dLineOffset,
0624:                                    dPixelStride, dwidth, xMod, yMod);
0625:                        } else {
0626:                            computeLineByteLUTN(sData, srcPixelOffsets,
0627:                                    sPixelStride, dData, dLineOffset,
0628:                                    dPixelStride, dwidth, xMod, yMod);
0629:                        }
0630:
0631:                        for (int i = 0; i < sbands; i++) {
0632:                            srcLineOffsets[i] += sLineStride;
0633:                            srcPixelOffsets[i] = srcLineOffsets[i];
0634:                        }
0635:                        dLineOffset += dLineStride;
0636:                    }
0637:
0638:                    break;
0639:                case TYPE_OD_GENERAL:
0640:                default:
0641:                    computeRectByteGeneral(sData, sBandOffsets, sLineStride,
0642:                            sPixelStride, dData, dBandOffset, dLineStride,
0643:                            dPixelStride, dwidth, dheight, xMod, y0);
0644:                }
0645:            }
0646:
0647:            /**
0648:             * Dithers a line of 3-band byte data using a DitherLUT.
0649:             */
0650:            private void computeLineByteLUT3(byte[][] sData,
0651:                    int[] sPixelOffsets, int sPixelStride, byte[] dData,
0652:                    int dPixelOffset, int dPixelStride, int dwidth, int xMod,
0653:                    int yMod) {
0654:                int ditherLUTBandStride = odLUT.ditherLUTBandStride;
0655:                int ditherLUTRowStride = odLUT.ditherLUTRowStride;
0656:                int ditherLUTColStride = odLUT.ditherLUTColStride;
0657:                byte[] ditherLUT = odLUT.ditherLUT;
0658:
0659:                int base = adjustedOffset;
0660:
0661:                int dlut0 = yMod * ditherLUTRowStride;
0662:                int dlut1 = dlut0 + ditherLUTBandStride;
0663:                int dlut2 = dlut1 + ditherLUTBandStride;
0664:
0665:                int dlutLimit = dlut0 + ditherLUTRowStride;
0666:
0667:                int xDelta = xMod * ditherLUTColStride;
0668:                int pDtab0 = dlut0 + xDelta;
0669:                int pDtab1 = dlut1 + xDelta;
0670:                int pDtab2 = dlut2 + xDelta;
0671:
0672:                byte[] sData0 = sData[0];
0673:                byte[] sData1 = sData[1];
0674:                byte[] sData2 = sData[2];
0675:
0676:                for (int count = dwidth; count > 0; count--) {
0677:                    int idx = (ditherLUT[pDtab0
0678:                            + (sData0[sPixelOffsets[0]] & 0xff)] & 0xff)
0679:                            + (ditherLUT[pDtab1
0680:                                    + (sData1[sPixelOffsets[1]] & 0xff)] & 0xff)
0681:                            + (ditherLUT[pDtab2
0682:                                    + (sData2[sPixelOffsets[2]] & 0xff)] & 0xff);
0683:
0684:                    dData[dPixelOffset] = (byte) ((idx + base) & 0xff);
0685:
0686:                    sPixelOffsets[0] += sPixelStride;
0687:                    sPixelOffsets[1] += sPixelStride;
0688:                    sPixelOffsets[2] += sPixelStride;
0689:
0690:                    dPixelOffset += dPixelStride;
0691:
0692:                    pDtab0 += ditherLUTColStride;
0693:
0694:                    if (pDtab0 >= dlutLimit) {
0695:                        pDtab0 = dlut0;
0696:                        pDtab1 = dlut1;
0697:                        pDtab2 = dlut2;
0698:                    } else {
0699:                        pDtab1 += ditherLUTColStride;
0700:                        pDtab2 += ditherLUTColStride;
0701:                    }
0702:                }
0703:            }
0704:
0705:            /**
0706:             * Dithers a line of N-band byte data using a DitherLUT.
0707:             */
0708:            private void computeLineByteLUTN(byte[][] sData,
0709:                    int[] sPixelOffsets, int sPixelStride, byte[] dData,
0710:                    int dPixelOffset, int dPixelStride, int dwidth, int xMod,
0711:                    int yMod) {
0712:                int ditherLUTBandStride = odLUT.ditherLUTBandStride;
0713:                int ditherLUTRowStride = odLUT.ditherLUTRowStride;
0714:                int ditherLUTColStride = odLUT.ditherLUTColStride;
0715:                byte[] ditherLUT = odLUT.ditherLUT;
0716:
0717:                int base = adjustedOffset;
0718:
0719:                int dlutRow = yMod * ditherLUTRowStride;
0720:                int dlutCol = dlutRow + xMod * ditherLUTColStride;
0721:                int dlutLimit = dlutRow + ditherLUTRowStride;
0722:
0723:                for (int count = dwidth; count > 0; count--) {
0724:                    int dlutBand = dlutCol;
0725:                    int idx = base;
0726:                    for (int i = 0; i < numBands; i++) {
0727:                        idx += (ditherLUT[dlutBand
0728:                                + (sData[i][sPixelOffsets[i]] & 0xff)] & 0xff);
0729:                        dlutBand += ditherLUTBandStride;
0730:                        sPixelOffsets[i] += sPixelStride;
0731:                    }
0732:
0733:                    dData[dPixelOffset] = (byte) (idx & 0xff);
0734:
0735:                    dPixelOffset += dPixelStride;
0736:
0737:                    dlutCol += ditherLUTColStride;
0738:
0739:                    if (dlutCol >= dlutLimit) {
0740:                        dlutCol = dlutRow;
0741:                    }
0742:                }
0743:            }
0744:
0745:            /**
0746:             * Computes a <code>Rectangle</code> of data for byte imagery using the
0747:             * general, unoptimized algorithm.
0748:             */
0749:            private void computeRectByteGeneral(byte[][] sData,
0750:                    int[] sBandOffsets, int sLineStride, int sPixelStride,
0751:                    byte[] dData, int dBandOffset, int dLineStride,
0752:                    int dPixelStride, int dwidth, int dheight, int xMod, int y0) {
0753:                if (adjustedOffset > 0) {
0754:                    Arrays.fill(dData, (byte) (adjustedOffset & 0xff));
0755:                }
0756:
0757:                int sbands = sBandOffsets.length;
0758:                for (int b = 0; b < sbands; b++) {
0759:                    byte[] s = sData[b];
0760:                    byte[] d = dData;
0761:
0762:                    byte[] maskData = maskDataByte[b];
0763:
0764:                    int sLineOffset = sBandOffsets[b];
0765:                    int dLineOffset = dBandOffset;
0766:
0767:                    for (int h = 0; h < dheight; h++) {
0768:                        int yMod = (y0 + h) % maskHeight;
0769:
0770:                        // Determine the index of the first dither mask point in
0771:                        // this line for the current band.
0772:                        int maskYBase = yMod * maskWidth;
0773:
0774:                        // Determine the value one greater than the maximum valid
0775:                        // dither mask index for this band.
0776:                        int maskLimit = maskYBase + maskWidth;
0777:
0778:                        // Initialize the dither mask index which is a value
0779:                        // guaranteed to be in range.
0780:                        int maskIndex = maskYBase + xMod;
0781:
0782:                        int sPixelOffset = sLineOffset;
0783:                        int dPixelOffset = dLineOffset;
0784:
0785:                        for (int w = 0; w < dwidth; w++) {
0786:                            int tmp = (s[sPixelOffset] & 0xff) * dims[b];
0787:                            int frac = (int) (tmp & 0xff);
0788:                            tmp >>= 8;
0789:                            if (frac > (int) (maskData[maskIndex] & 0xff)) {
0790:                                tmp++;
0791:                            }
0792:
0793:                            // Accumulate the value into the destination data array.
0794:                            int result = (d[dPixelOffset] & 0xff) + tmp
0795:                                    * mults[b];
0796:                            d[dPixelOffset] = (byte) (result & 0xff);
0797:
0798:                            sPixelOffset += sPixelStride;
0799:                            dPixelOffset += dPixelStride;
0800:
0801:                            if (++maskIndex >= maskLimit) {
0802:                                maskIndex = maskYBase;
0803:                            }
0804:                        }
0805:
0806:                        sLineOffset += sLineStride;
0807:                        dLineOffset += dLineStride;
0808:                    }
0809:                }
0810:
0811:                if (adjustedOffset < 0) {
0812:                    // Shift the result by the adjusted offset of the color map.
0813:                    int length = dData.length;
0814:                    for (int i = 0; i < length; i++) {
0815:                        dData[i] = (byte) ((dData[i] & 0xff) + adjustedOffset);
0816:                    }
0817:                }
0818:            }
0819:
0820:            /**
0821:             * Computes a <code>Rectangle</code> of data for signed short imagery.
0822:             */
0823:            private void computeRectShort(RasterAccessor src, RasterAccessor dst) {
0824:                int sbands = src.getNumBands();
0825:                int sLineStride = src.getScanlineStride();
0826:                int sPixelStride = src.getPixelStride();
0827:                int[] sBandOffsets = src.getBandOffsets();
0828:                short[][] sData = src.getShortDataArrays();
0829:
0830:                int dwidth = dst.getWidth();
0831:                int dheight = dst.getHeight();
0832:                int dLineStride = dst.getScanlineStride();
0833:                int dPixelStride = dst.getPixelStride();
0834:                int dBandOffset = dst.getBandOffset(0);
0835:                short[] dData = dst.getShortDataArray(0);
0836:
0837:                // Initialize the destination data to the color cube adjusted offset
0838:                // to permit accumulation of the result for each band.
0839:                if (adjustedOffset != 0) {
0840:                    Arrays.fill(dData, (short) (adjustedOffset & 0xffff));
0841:                }
0842:
0843:                int xMod = dst.getX() % maskWidth;
0844:                int y0 = dst.getY();
0845:
0846:                for (int b = 0; b < sbands; b++) {
0847:                    short[] s = sData[b];
0848:                    short[] d = dData;
0849:
0850:                    int[] maskData = maskDataInt[b];
0851:
0852:                    int sLineOffset = sBandOffsets[b];
0853:                    int dLineOffset = dBandOffset;
0854:
0855:                    for (int h = 0; h < dheight; h++) {
0856:                        int sPixelOffset = sLineOffset;
0857:                        int dPixelOffset = dLineOffset;
0858:
0859:                        sLineOffset += sLineStride;
0860:                        dLineOffset += dLineStride;
0861:
0862:                        // Determine the index of the first dither mask point in
0863:                        // this line for the current band.
0864:                        int maskYBase = ((y0 + h) % maskHeight) * maskWidth;
0865:
0866:                        // Determine the value one greater than the maximum valid
0867:                        // dither mask index for this band.
0868:                        int maskLimit = maskYBase + maskWidth;
0869:
0870:                        // Initialize the dither mask index which is a value
0871:                        // guaranteed to be in range.
0872:                        int maskIndex = maskYBase + xMod;
0873:
0874:                        for (int w = 0; w < dwidth; w++) {
0875:                            int tmp = (s[sPixelOffset] - Short.MIN_VALUE)
0876:                                    * dims[b];
0877:                            int frac = (int) (tmp & 0xffff);
0878:
0879:                            // Accumulate the value into the destination data array.
0880:                            int result = (int) (d[dPixelOffset] & 0xffff)
0881:                                    + (tmp >> 16) * mults[b];
0882:                            if (frac > maskData[maskIndex]) {
0883:                                result += mults[b];
0884:                            }
0885:                            d[dPixelOffset] = (short) (result & 0xffff);
0886:
0887:                            sPixelOffset += sPixelStride;
0888:                            dPixelOffset += dPixelStride;
0889:
0890:                            if (++maskIndex >= maskLimit) {
0891:                                maskIndex = maskYBase;
0892:                            }
0893:                        }
0894:                    }
0895:                }
0896:            }
0897:
0898:            /**
0899:             * Computes a <code>Rectangle</code> of data for unsigned short imagery.
0900:             */
0901:            private void computeRectUShort(RasterAccessor src,
0902:                    RasterAccessor dst) {
0903:                int sbands = src.getNumBands();
0904:                int sLineStride = src.getScanlineStride();
0905:                int sPixelStride = src.getPixelStride();
0906:                int[] sBandOffsets = src.getBandOffsets();
0907:                short[][] sData = src.getShortDataArrays();
0908:
0909:                int dwidth = dst.getWidth();
0910:                int dheight = dst.getHeight();
0911:                int dLineStride = dst.getScanlineStride();
0912:                int dPixelStride = dst.getPixelStride();
0913:                int dBandOffset = dst.getBandOffset(0);
0914:                short[] dData = dst.getShortDataArray(0);
0915:
0916:                // Initialize the destination data to the color cube adjusted offset
0917:                // to permit accumulation of the result for each band.
0918:                if (adjustedOffset != 0) {
0919:                    Arrays.fill(dData, (short) (adjustedOffset & 0xffff));
0920:                }
0921:
0922:                int xMod = dst.getX() % maskWidth;
0923:                int y0 = dst.getY();
0924:
0925:                for (int b = 0; b < sbands; b++) {
0926:                    short[] s = sData[b];
0927:                    short[] d = dData;
0928:
0929:                    int[] maskData = maskDataInt[b];
0930:
0931:                    int sLineOffset = sBandOffsets[b];
0932:                    int dLineOffset = dBandOffset;
0933:
0934:                    for (int h = 0; h < dheight; h++) {
0935:                        int sPixelOffset = sLineOffset;
0936:                        int dPixelOffset = dLineOffset;
0937:
0938:                        sLineOffset += sLineStride;
0939:                        dLineOffset += dLineStride;
0940:
0941:                        // Determine the index of the first dither mask point in
0942:                        // this line for the current band.
0943:                        int maskYBase = ((y0 + h) % maskHeight) * maskWidth;
0944:
0945:                        // Determine the value one greater than the maximum valid
0946:                        // dither mask index for this band.
0947:                        int maskLimit = maskYBase + maskWidth;
0948:
0949:                        // Initialize the dither mask index which is a value
0950:                        // guaranteed to be in range.
0951:                        int maskIndex = maskYBase + xMod;
0952:
0953:                        for (int w = 0; w < dwidth; w++) {
0954:                            int tmp = (s[sPixelOffset] & 0xffff) * dims[b];
0955:                            int frac = (int) (tmp & 0xffff);
0956:
0957:                            // Accumulate the value into the destination data array.
0958:                            int result = (int) (d[dPixelOffset] & 0xffff)
0959:                                    + (tmp >> 16) * mults[b];
0960:                            if (frac > maskData[maskIndex]) {
0961:                                result += mults[b];
0962:                            }
0963:                            d[dPixelOffset] = (short) (result & 0xffff);
0964:
0965:                            sPixelOffset += sPixelStride;
0966:                            dPixelOffset += dPixelStride;
0967:
0968:                            if (++maskIndex >= maskLimit) {
0969:                                maskIndex = maskYBase;
0970:                            }
0971:                        }
0972:                    }
0973:                }
0974:            }
0975:
0976:            /**
0977:             * Computes a <code>Rectangle</code> of data for integer imagery.
0978:             */
0979:            private void computeRectInt(RasterAccessor src, RasterAccessor dst) {
0980:                int sbands = src.getNumBands();
0981:                int sLineStride = src.getScanlineStride();
0982:                int sPixelStride = src.getPixelStride();
0983:                int[] sBandOffsets = src.getBandOffsets();
0984:                int[][] sData = src.getIntDataArrays();
0985:
0986:                int dwidth = dst.getWidth();
0987:                int dheight = dst.getHeight();
0988:                int dLineStride = dst.getScanlineStride();
0989:                int dPixelStride = dst.getPixelStride();
0990:                int dBandOffset = dst.getBandOffset(0);
0991:                int[] dData = dst.getIntDataArray(0);
0992:
0993:                // Initialize the destination data to the color cube adjusted offset
0994:                // to permit accumulation of the result for each band.
0995:                if (adjustedOffset != 0) {
0996:                    Arrays.fill(dData, adjustedOffset);
0997:                }
0998:
0999:                int xMod = dst.getX() % maskWidth;
1000:                int y0 = dst.getY();
1001:
1002:                for (int b = 0; b < sbands; b++) {
1003:                    int[] s = sData[b];
1004:                    int[] d = dData;
1005:
1006:                    long[] maskData = maskDataLong[b];
1007:
1008:                    int sLineOffset = sBandOffsets[b];
1009:                    int dLineOffset = dBandOffset;
1010:
1011:                    for (int h = 0; h < dheight; h++) {
1012:                        int sPixelOffset = sLineOffset;
1013:                        int dPixelOffset = dLineOffset;
1014:
1015:                        sLineOffset += sLineStride;
1016:                        dLineOffset += dLineStride;
1017:
1018:                        // Determine the index of the first dither mask point in
1019:                        // this line for the current band.
1020:                        int maskYBase = ((y0 + h) % maskHeight) * maskWidth;
1021:
1022:                        // Determine the value one greater than the maximum valid
1023:                        // dither mask index for this band.
1024:                        int maskLimit = maskYBase + maskWidth;
1025:
1026:                        // Initialize the dither mask index which is a value
1027:                        // guaranteed to be in range.
1028:                        int maskIndex = maskYBase + xMod;
1029:
1030:                        for (int w = 0; w < dwidth; w++) {
1031:                            long tmp = ((long) s[sPixelOffset] - (long) Integer.MIN_VALUE)
1032:                                    * dims[b];
1033:                            long frac = (long) (tmp & 0xffffffff);
1034:
1035:                            // Accumulate the value into the destination data array.
1036:                            int result = d[dPixelOffset] + ((int) (tmp >> 32))
1037:                                    * mults[b];
1038:                            if (frac > maskData[maskIndex]) {
1039:                                result += mults[b];
1040:                            }
1041:                            d[dPixelOffset] = result;
1042:
1043:                            sPixelOffset += sPixelStride;
1044:                            dPixelOffset += dPixelStride;
1045:
1046:                            if (++maskIndex >= maskLimit) {
1047:                                maskIndex = maskYBase;
1048:                            }
1049:                        }
1050:                    }
1051:                }
1052:            }
1053:
1054:            /**
1055:             * Computes a <code>Rectangle</code> of data for float imagery.
1056:             */
1057:            private void computeRectFloat(RasterAccessor src, RasterAccessor dst) {
1058:                int sbands = src.getNumBands();
1059:                int sLineStride = src.getScanlineStride();
1060:                int sPixelStride = src.getPixelStride();
1061:                int[] sBandOffsets = src.getBandOffsets();
1062:                float[][] sData = src.getFloatDataArrays();
1063:
1064:                int dwidth = dst.getWidth();
1065:                int dheight = dst.getHeight();
1066:                int dLineStride = dst.getScanlineStride();
1067:                int dPixelStride = dst.getPixelStride();
1068:                int dBandOffset = dst.getBandOffset(0);
1069:                float[] dData = dst.getFloatDataArray(0);
1070:
1071:                // Initialize the destination data to the color cube adjusted offset
1072:                // to permit accumulation of the result for each band.
1073:                if (adjustedOffset != 0) {
1074:                    Arrays.fill(dData, (float) adjustedOffset);
1075:                }
1076:
1077:                int xMod = dst.getX() % maskWidth;
1078:                int y0 = dst.getY();
1079:
1080:                for (int b = 0; b < sbands; b++) {
1081:                    float[] s = sData[b];
1082:                    float[] d = dData;
1083:
1084:                    float[] maskData = maskDataFloat[b];
1085:
1086:                    int sLineOffset = sBandOffsets[b];
1087:                    int dLineOffset = dBandOffset;
1088:
1089:                    for (int h = 0; h < dheight; h++) {
1090:                        int sPixelOffset = sLineOffset;
1091:                        int dPixelOffset = dLineOffset;
1092:
1093:                        sLineOffset += sLineStride;
1094:                        dLineOffset += dLineStride;
1095:
1096:                        // Determine the index of the first dither mask point in
1097:                        // this line for the current band.
1098:                        int maskYBase = ((y0 + h) % maskHeight) * maskWidth;
1099:
1100:                        // Determine the value one greater than the maximum valid
1101:                        // dither mask index for this band.
1102:                        int maskLimit = maskYBase + maskWidth;
1103:
1104:                        // Initialize the dither mask index which is a value
1105:                        // guaranteed to be in range.
1106:                        int maskIndex = maskYBase + xMod;
1107:
1108:                        for (int w = 0; w < dwidth; w++) {
1109:                            int tmp = (int) (s[sPixelOffset] * dims[b]);
1110:                            float frac = s[sPixelOffset] * dims[b] - tmp;
1111:
1112:                            // Accumulate the value into the destination data array.
1113:                            float result = d[dPixelOffset] + tmp * mults[b];
1114:                            if (frac > maskData[maskIndex]) {
1115:                                result += mults[b];
1116:                            }
1117:                            d[dPixelOffset] = result;
1118:
1119:                            sPixelOffset += sPixelStride;
1120:                            dPixelOffset += dPixelStride;
1121:
1122:                            if (++maskIndex >= maskLimit) {
1123:                                maskIndex = maskYBase;
1124:                            }
1125:                        }
1126:                    }
1127:                }
1128:            }
1129:
1130:            /**
1131:             * Computes a <code>Rectangle</code> of data for double imagery.
1132:             */
1133:            private void computeRectDouble(RasterAccessor src,
1134:                    RasterAccessor dst) {
1135:                int sbands = src.getNumBands();
1136:                int sLineStride = src.getScanlineStride();
1137:                int sPixelStride = src.getPixelStride();
1138:                int[] sBandOffsets = src.getBandOffsets();
1139:                double[][] sData = src.getDoubleDataArrays();
1140:
1141:                int dwidth = dst.getWidth();
1142:                int dheight = dst.getHeight();
1143:                int dLineStride = dst.getScanlineStride();
1144:                int dPixelStride = dst.getPixelStride();
1145:                int dBandOffset = dst.getBandOffset(0);
1146:                double[] dData = dst.getDoubleDataArray(0);
1147:
1148:                // Initialize the destination data to the color cube adjusted offset
1149:                // to permit accumulation of the result for each band.
1150:                if (adjustedOffset != 0) {
1151:                    Arrays.fill(dData, (double) adjustedOffset);
1152:                }
1153:
1154:                int xMod = dst.getX() % maskWidth;
1155:                int y0 = dst.getY();
1156:
1157:                for (int b = 0; b < sbands; b++) {
1158:                    double[] s = sData[b];
1159:                    double[] d = dData;
1160:
1161:                    float[] maskData = maskDataFloat[b];
1162:
1163:                    int sLineOffset = sBandOffsets[b];
1164:                    int dLineOffset = dBandOffset;
1165:
1166:                    for (int h = 0; h < dheight; h++) {
1167:                        int sPixelOffset = sLineOffset;
1168:                        int dPixelOffset = dLineOffset;
1169:
1170:                        sLineOffset += sLineStride;
1171:                        dLineOffset += dLineStride;
1172:
1173:                        // Determine the index of the first dither mask point in
1174:                        // this line for the current band.
1175:                        int maskYBase = ((y0 + h) % maskHeight) * maskWidth;
1176:
1177:                        // Determine the value one greater than the maximum valid
1178:                        // dither mask index for this band.
1179:                        int maskLimit = maskYBase + maskWidth;
1180:
1181:                        // Initialize the dither mask index which is a value
1182:                        // guaranteed to be in range.
1183:                        int maskIndex = maskYBase + xMod;
1184:
1185:                        for (int w = 0; w < dwidth; w++) {
1186:                            int tmp = (int) (s[sPixelOffset] * dims[b]);
1187:                            float frac = (float) (s[sPixelOffset] * dims[b] - tmp);
1188:
1189:                            // Accumulate the value into the destination data array.
1190:                            double result = d[dPixelOffset] + tmp * mults[b];
1191:                            if (frac > maskData[maskIndex]) {
1192:                                result += mults[b];
1193:                            }
1194:                            d[dPixelOffset] = result;
1195:
1196:                            sPixelOffset += sPixelStride;
1197:                            dPixelOffset += dPixelStride;
1198:
1199:                            if (++maskIndex >= maskLimit) {
1200:                                maskIndex = maskYBase;
1201:                            }
1202:                        }
1203:                    }
1204:                }
1205:            }
1206:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.