Source Code Cross Referenced for ImageUtil.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » util » 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.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: ImageUtil.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.2 $
0009:         * $Date: 2006/07/21 20:53:28 $
0010:         * $State: Exp $
0011:         */
0012:        package com.sun.media.jai.util;
0013:
0014:        import java.awt.Point;
0015:        import java.awt.Rectangle;
0016:        import java.awt.RenderingHints;
0017:        import java.awt.image.ColorModel;
0018:        import java.awt.image.ComponentSampleModel;
0019:        import java.awt.image.DataBuffer;
0020:        import java.awt.image.DataBufferByte;
0021:        import java.awt.image.DataBufferInt;
0022:        import java.awt.image.DataBufferShort;
0023:        import java.awt.image.DataBufferUShort;
0024:        import java.awt.image.MultiPixelPackedSampleModel;
0025:        import java.awt.image.Raster;
0026:        import java.awt.image.SampleModel;
0027:        import java.awt.image.SinglePixelPackedSampleModel;
0028:        import java.awt.image.WritableRaster;
0029:        import java.awt.image.renderable.ParameterBlock;
0030:        import java.awt.image.renderable.RenderContext;
0031:        import java.lang.reflect.Method;
0032:        import java.lang.reflect.Modifier;
0033:        import java.math.BigInteger;
0034:        import java.util.Arrays;
0035:        import java.util.Map;
0036:        import java.util.Vector;
0037:        import javax.media.jai.DeferredData;
0038:        import javax.media.jai.JAI;
0039:        import javax.media.jai.KernelJAI;
0040:        import javax.media.jai.PixelAccessor;
0041:        import javax.media.jai.RasterAccessor;
0042:        import javax.media.jai.PlanarImage;
0043:        import javax.media.jai.UnpackedImageData;
0044:        import javax.media.jai.util.ImagingException;
0045:        import javax.media.jai.util.ImagingListener;
0046:        import java.io.ByteArrayOutputStream;
0047:        import java.io.PrintStream;
0048:
0049:        public final class ImageUtil {
0050:
0051:            /** The minimum value of a float. */
0052:            private static final float FLOAT_MIN = -Float.MAX_VALUE;
0053:
0054:            /** The counter for images that use the method generateID to create
0055:             *  a UID.
0056:             */
0057:            private static long counter;
0058:
0059:            /** A constant used to extract a byte from a short or an int. */
0060:            public static final int BYTE_MASK = 0xFF;
0061:
0062:            /** A constant used to extract an unsigned short from an int. */
0063:            public static final int USHORT_MASK = 0xFFFF;
0064:
0065:            /** Clamps a number to the range supported by byte data type. */
0066:            public static final byte clampByte(int in) {
0067:                return (in > 0xFF ? (byte) 0xFF : (in >= 0 ? (byte) in
0068:                        : (byte) 0));
0069:            }
0070:
0071:            /** Clamps a number to the range supported by unsigned short data type. */
0072:            public static final short clampUShort(int in) {
0073:                return (in > 0xFFFF ? (short) 0xFFFF : (in >= 0 ? (short) in
0074:                        : (short) 0));
0075:            }
0076:
0077:            /** Clamps a number to the range supported by short data type. */
0078:            public static final short clampShort(int in) {
0079:                return (in > Short.MAX_VALUE ? Short.MAX_VALUE
0080:                        : (in >= Short.MIN_VALUE ? (short) in : Short.MIN_VALUE));
0081:            }
0082:
0083:            /** Clamps a number to the range supported by integer data type. */
0084:            public static final int clampInt(long in) {
0085:                return (in > Integer.MAX_VALUE ? Integer.MAX_VALUE
0086:                        : (in >= Integer.MIN_VALUE ? (int) in
0087:                                : Integer.MIN_VALUE));
0088:            }
0089:
0090:            /** Clamps a number to the range supported by float data type. */
0091:            public static final float clampFloat(double in) {
0092:                return (in > Float.MAX_VALUE ? Float.MAX_VALUE
0093:                        : (in >= FLOAT_MIN ? (float) in : FLOAT_MIN));
0094:            }
0095:
0096:            /**
0097:             * Clamps and rounds a number to the range supported by
0098:             * byte data type. The input number is float.
0099:             */
0100:            public static final byte clampRoundByte(float in) {
0101:                return (in > 0xFF ? (byte) 0xFF : (in >= 0 ? (byte) (in + 0.5F)
0102:                        : (byte) 0));
0103:            }
0104:
0105:            /**
0106:             * Clamps and rounds a number to the range supported by
0107:             * byte data type. The input number is double.
0108:             */
0109:            public static final byte clampRoundByte(double in) {
0110:                return (in > 0xFF ? (byte) 0xFF : (in >= 0 ? (byte) (in + 0.5)
0111:                        : (byte) 0));
0112:            }
0113:
0114:            /**
0115:             * Clamps and rounds a number to the range supported by
0116:             * unsigned short data type. The input number is float.
0117:             */
0118:            public static final short clampRoundUShort(float in) {
0119:                return (in > 0xFFFF ? (short) 0xFFFF
0120:                        : (in >= 0 ? (short) (in + 0.5F) : (short) 0));
0121:            }
0122:
0123:            /**
0124:             * Clamps and rounds a number to the range supported by
0125:             * unsigned short data type. The input number is double.
0126:             */
0127:            public static final short clampRoundUShort(double in) {
0128:                return (in > 0xFFFF ? (short) 0xFFFF
0129:                        : (in >= 0 ? (short) (in + 0.5) : (short) 0));
0130:            }
0131:
0132:            /**
0133:             * Clamps and rounds a number to the range supported by
0134:             * short data type. The input number is float.
0135:             */
0136:            public static final short clampRoundShort(float in) {
0137:                return (in > Short.MAX_VALUE ? Short.MAX_VALUE
0138:                        : (in >= Short.MIN_VALUE ? (short) Math
0139:                                .floor(in + 0.5F) : Short.MIN_VALUE));
0140:            }
0141:
0142:            /**
0143:             * Clamps and rounds a number to the range supported by
0144:             * short data type. The input number is double.
0145:             */
0146:            public static final short clampRoundShort(double in) {
0147:                return (in > Short.MAX_VALUE ? Short.MAX_VALUE
0148:                        : (in >= Short.MIN_VALUE ? (short) Math.floor(in + 0.5)
0149:                                : Short.MIN_VALUE));
0150:            }
0151:
0152:            /**
0153:             * Clamps and rounds a number to the range supported by
0154:             * integer data type. The input number is float.
0155:             */
0156:            public static final int clampRoundInt(float in) {
0157:                return (in > Integer.MAX_VALUE ? Integer.MAX_VALUE
0158:                        : (in >= Integer.MIN_VALUE ? (int) Math
0159:                                .floor(in + 0.5F) : Integer.MIN_VALUE));
0160:            }
0161:
0162:            /**
0163:             * Clamps and rounds a number to the range supported by
0164:             * integer data type. The input number is double.
0165:             */
0166:            public static final int clampRoundInt(double in) {
0167:                return (in > Integer.MAX_VALUE ? Integer.MAX_VALUE
0168:                        : (in >= Integer.MIN_VALUE ? (int) Math.floor(in + 0.5)
0169:                                : Integer.MIN_VALUE));
0170:            }
0171:
0172:            /** Clamps a positive number to the range supported by byte data type. */
0173:            public static final byte clampBytePositive(int in) {
0174:                return (in > 0xFF ? (byte) 0xFF : (byte) in);
0175:            }
0176:
0177:            /** Clamps a negative number to the range supported by byte data type. */
0178:            public static final byte clampByteNegative(int in) {
0179:                return (in < 0 ? (byte) 0 : (byte) in);
0180:            }
0181:
0182:            /**
0183:             * Clamps a positive number to the range supported by
0184:             * unsigned short data type.
0185:             */
0186:            public static final short clampUShortPositive(int in) {
0187:                return (in > 0xFFFF ? (short) 0xFFFF : (short) in);
0188:            }
0189:
0190:            /*
0191:             * Clamps a negative number to the range supported by
0192:             * unsigned short data type.
0193:             */
0194:            public static final short clampUShortNegative(int in) {
0195:                return (in < 0 ? (short) 0 : (short) in);
0196:            }
0197:
0198:            public static final void copyRaster(RasterAccessor src,
0199:                    RasterAccessor dst) {
0200:                int srcPixelStride = src.getPixelStride();
0201:                int srcLineStride = src.getScanlineStride();
0202:                int[] srcBandOffsets = src.getBandOffsets();
0203:
0204:                int dstPixelStride = dst.getPixelStride();
0205:                int dstLineStride = dst.getScanlineStride();
0206:                int[] dstBandOffsets = dst.getBandOffsets();
0207:
0208:                int width = dst.getWidth() * dstPixelStride;
0209:                int height = dst.getHeight() * dstLineStride;
0210:                int bands = dst.getNumBands();
0211:
0212:                switch (dst.getDataType()) {
0213:                case DataBuffer.TYPE_BYTE:
0214:                    byte[][] bSrcData = src.getByteDataArrays();
0215:                    byte[][] bDstData = dst.getByteDataArrays();
0216:
0217:                    for (int b = 0; b < bands; b++) {
0218:                        byte[] s = bSrcData[b];
0219:                        byte[] d = bDstData[b];
0220:
0221:                        int heightEnd = dstBandOffsets[b] + height;
0222:
0223:                        for (int dstLineOffset = dstBandOffsets[b], srcLineOffset = srcBandOffsets[b]; dstLineOffset < heightEnd; dstLineOffset += dstLineStride, srcLineOffset += srcLineStride) {
0224:
0225:                            int widthEnd = dstLineOffset + width;
0226:
0227:                            for (int dstPixelOffset = dstLineOffset, srcPixelOffset = srcLineOffset; dstPixelOffset < widthEnd; dstPixelOffset += dstPixelStride, srcPixelOffset += srcPixelStride) {
0228:
0229:                                d[dstPixelOffset] = s[srcPixelOffset];
0230:                            }
0231:                        }
0232:                    }
0233:                    break;
0234:
0235:                case DataBuffer.TYPE_USHORT:
0236:                case DataBuffer.TYPE_SHORT:
0237:                    short[][] sSrcData = src.getShortDataArrays();
0238:                    short[][] sDstData = dst.getShortDataArrays();
0239:
0240:                    for (int b = 0; b < bands; b++) {
0241:                        short[] s = sSrcData[b];
0242:                        short[] d = sDstData[b];
0243:
0244:                        int heightEnd = dstBandOffsets[b] + height;
0245:
0246:                        for (int dstLineOffset = dstBandOffsets[b], srcLineOffset = srcBandOffsets[b]; dstLineOffset < heightEnd; dstLineOffset += dstLineStride, srcLineOffset += srcLineStride) {
0247:
0248:                            int widthEnd = dstLineOffset + width;
0249:
0250:                            for (int dstPixelOffset = dstLineOffset, srcPixelOffset = srcLineOffset; dstPixelOffset < widthEnd; dstPixelOffset += dstPixelStride, srcPixelOffset += srcPixelStride) {
0251:
0252:                                d[dstPixelOffset] = s[srcPixelOffset];
0253:                            }
0254:                        }
0255:                    }
0256:                    break;
0257:
0258:                case DataBuffer.TYPE_INT:
0259:                    int[][] iSrcData = src.getIntDataArrays();
0260:                    int[][] iDstData = dst.getIntDataArrays();
0261:
0262:                    for (int b = 0; b < bands; b++) {
0263:                        int[] s = iSrcData[b];
0264:                        int[] d = iDstData[b];
0265:
0266:                        int heightEnd = dstBandOffsets[b] + height;
0267:
0268:                        for (int dstLineOffset = dstBandOffsets[b], srcLineOffset = srcBandOffsets[b]; dstLineOffset < heightEnd; dstLineOffset += dstLineStride, srcLineOffset += srcLineStride) {
0269:
0270:                            int widthEnd = dstLineOffset + width;
0271:
0272:                            for (int dstPixelOffset = dstLineOffset, srcPixelOffset = srcLineOffset; dstPixelOffset < widthEnd; dstPixelOffset += dstPixelStride, srcPixelOffset += srcPixelStride) {
0273:
0274:                                d[dstPixelOffset] = s[srcPixelOffset];
0275:                            }
0276:                        }
0277:                    }
0278:                    break;
0279:
0280:                case DataBuffer.TYPE_FLOAT:
0281:                    float[][] fSrcData = src.getFloatDataArrays();
0282:                    float[][] fDstData = dst.getFloatDataArrays();
0283:
0284:                    for (int b = 0; b < bands; b++) {
0285:                        float[] s = fSrcData[b];
0286:                        float[] d = fDstData[b];
0287:
0288:                        int heightEnd = dstBandOffsets[b] + height;
0289:
0290:                        for (int dstLineOffset = dstBandOffsets[b], srcLineOffset = srcBandOffsets[b]; dstLineOffset < heightEnd; dstLineOffset += dstLineStride, srcLineOffset += srcLineStride) {
0291:
0292:                            int widthEnd = dstLineOffset + width;
0293:
0294:                            for (int dstPixelOffset = dstLineOffset, srcPixelOffset = srcLineOffset; dstPixelOffset < widthEnd; dstPixelOffset += dstPixelStride, srcPixelOffset += srcPixelStride) {
0295:
0296:                                d[dstPixelOffset] = s[srcPixelOffset];
0297:                            }
0298:                        }
0299:                    }
0300:                    break;
0301:
0302:                case DataBuffer.TYPE_DOUBLE:
0303:                    double[][] dSrcData = src.getDoubleDataArrays();
0304:                    double[][] dDstData = dst.getDoubleDataArrays();
0305:
0306:                    for (int b = 0; b < bands; b++) {
0307:                        double[] s = dSrcData[b];
0308:                        double[] d = dDstData[b];
0309:
0310:                        int heightEnd = dstBandOffsets[b] + height;
0311:
0312:                        for (int dstLineOffset = dstBandOffsets[b], srcLineOffset = srcBandOffsets[b]; dstLineOffset < heightEnd; dstLineOffset += dstLineStride, srcLineOffset += srcLineStride) {
0313:
0314:                            int widthEnd = dstLineOffset + width;
0315:
0316:                            for (int dstPixelOffset = dstLineOffset, srcPixelOffset = srcLineOffset; dstPixelOffset < widthEnd; dstPixelOffset += dstPixelStride, srcPixelOffset += srcPixelStride) {
0317:
0318:                                d[dstPixelOffset] = s[srcPixelOffset];
0319:                            }
0320:                        }
0321:                    }
0322:                    break;
0323:                }
0324:
0325:                if (dst.isDataCopy()) {
0326:                    dst.clampDataArrays();
0327:                    dst.copyDataToRaster();
0328:                }
0329:            }
0330:
0331:            /**
0332:             * Determines whether two SampleModels are "equal", i.e.,
0333:             * assignment-compatible.  This signifies that the two SampleModels
0334:             * are either the very same object or are two different objects
0335:             * with identical characteristics.
0336:             */
0337:            public boolean areEqualSampleModels(SampleModel sm1, SampleModel sm2) {
0338:                if (sm1 == sm2) {
0339:                    // Identical objects.
0340:                    return true;
0341:                } else if (sm1.getClass() == sm2.getClass()
0342:                        && sm1.getDataType() == sm2.getDataType()
0343:                        && sm1.getTransferType() == sm2.getTransferType()
0344:                        && sm1.getWidth() == sm2.getWidth()
0345:                        && sm1.getHeight() == sm2.getHeight()) {
0346:                    // At this point all common attributes are equivalent. Next test
0347:                    // those specific to the known direct subclasses of SampleModel.
0348:                    // Subclasses which are not known will always return false.
0349:                    if (sm1 instanceof  ComponentSampleModel) {
0350:                        ComponentSampleModel csm1 = (ComponentSampleModel) sm1;
0351:                        ComponentSampleModel csm2 = (ComponentSampleModel) sm2;
0352:                        return csm1.getPixelStride() == csm2.getPixelStride()
0353:                                && csm1.getScanlineStride() == csm2
0354:                                        .getScanlineStride()
0355:                                && Arrays.equals(csm1.getBankIndices(), csm2
0356:                                        .getBankIndices())
0357:                                && Arrays.equals(csm1.getBandOffsets(), csm2
0358:                                        .getBandOffsets());
0359:                    } else if (sm1 instanceof  MultiPixelPackedSampleModel) {
0360:                        MultiPixelPackedSampleModel mpp1 = (MultiPixelPackedSampleModel) sm1;
0361:                        MultiPixelPackedSampleModel mpp2 = (MultiPixelPackedSampleModel) sm2;
0362:                        return mpp1.getPixelBitStride() == mpp2
0363:                                .getPixelBitStride()
0364:                                && mpp1.getScanlineStride() == mpp2
0365:                                        .getScanlineStride()
0366:                                && mpp1.getDataBitOffset() == mpp2
0367:                                        .getDataBitOffset();
0368:                    } else if (sm1 instanceof  SinglePixelPackedSampleModel) {
0369:                        SinglePixelPackedSampleModel spp1 = (SinglePixelPackedSampleModel) sm1;
0370:                        SinglePixelPackedSampleModel spp2 = (SinglePixelPackedSampleModel) sm2;
0371:                        return spp1.getScanlineStride() == spp2
0372:                                .getScanlineStride()
0373:                                && Arrays.equals(spp1.getBitMasks(), spp2
0374:                                        .getBitMasks());
0375:                    }
0376:                }
0377:
0378:                return false;
0379:            }
0380:
0381:            /// ---- BEGIN Binary data handling methods ----
0382:
0383:            /**
0384:             * Check whether a <code>SampleModel</code> represents a binary
0385:             * data set, i.e., a single band of data with one bit per pixel
0386:             * packed into a <code>MultiPixelPackedSampleModel</code>.
0387:             */
0388:            public static boolean isBinary(SampleModel sm) {
0389:                return sm instanceof  MultiPixelPackedSampleModel
0390:                        && ((MultiPixelPackedSampleModel) sm)
0391:                                .getPixelBitStride() == 1
0392:                        && sm.getNumBands() == 1;
0393:            }
0394:
0395:            /**
0396:             * For the case of binary data (<code>isBinary()</code> returns
0397:             * <code>true</code>), return the binary data as a packed byte array.
0398:             * The data will be packed as eight bits per byte with no bit offset,
0399:             * i.e., the first bit in each image line will be the left-most of the
0400:             * first byte of the line.  The line stride in bytes will be
0401:             * <code>(int)((getWidth()+7)/8)</code>.  The length of the returned
0402:             * array will be the line stride multiplied by <code>getHeight()</code>
0403:             *
0404:             * @return the binary data as a packed array of bytes with zero offset
0405:             * of <code>null</code> if the data are not binary.
0406:             * @throws IllegalArgumentException if <code>isBinary()</code> returns
0407:             * <code>false</code> with the <code>SampleModel</code> of the
0408:             * supplied <code>Raster</code> as argument.
0409:             */
0410:            public static byte[] getPackedBinaryData(Raster raster,
0411:                    Rectangle rect) {
0412:                SampleModel sm = raster.getSampleModel();
0413:                if (!isBinary(sm)) {
0414:                    throw new IllegalArgumentException(JaiI18N
0415:                            .getString("ImageUtil0"));
0416:                }
0417:
0418:                int rectX = rect.x;
0419:                int rectY = rect.y;
0420:                int rectWidth = rect.width;
0421:                int rectHeight = rect.height;
0422:
0423:                DataBuffer dataBuffer = raster.getDataBuffer();
0424:
0425:                int dx = rectX - raster.getSampleModelTranslateX();
0426:                int dy = rectY - raster.getSampleModelTranslateY();
0427:
0428:                MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel) sm;
0429:                int lineStride = mpp.getScanlineStride();
0430:                int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
0431:                int bitOffset = mpp.getBitOffset(dx);
0432:
0433:                int numBytesPerRow = (rectWidth + 7) / 8;
0434:                if (dataBuffer instanceof  DataBufferByte
0435:                        && eltOffset == 0
0436:                        && bitOffset == 0
0437:                        && numBytesPerRow == lineStride
0438:                        && ((DataBufferByte) dataBuffer).getData().length == numBytesPerRow
0439:                                * rectHeight) {
0440:                    return ((DataBufferByte) dataBuffer).getData();
0441:                }
0442:
0443:                byte[] binaryDataArray = new byte[numBytesPerRow * rectHeight];
0444:
0445:                int b = 0;
0446:
0447:                if (bitOffset == 0) {
0448:                    if (dataBuffer instanceof  DataBufferByte) {
0449:                        byte[] data = ((DataBufferByte) dataBuffer).getData();
0450:                        int stride = numBytesPerRow;
0451:                        int offset = 0;
0452:                        for (int y = 0; y < rectHeight; y++) {
0453:                            System.arraycopy(data, eltOffset, binaryDataArray,
0454:                                    offset, stride);
0455:                            offset += stride;
0456:                            eltOffset += lineStride;
0457:                        }
0458:                    } else if (dataBuffer instanceof  DataBufferShort
0459:                            || dataBuffer instanceof  DataBufferUShort) {
0460:                        short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0461:                                .getData()
0462:                                : ((DataBufferUShort) dataBuffer).getData();
0463:
0464:                        for (int y = 0; y < rectHeight; y++) {
0465:                            int xRemaining = rectWidth;
0466:                            int i = eltOffset;
0467:                            while (xRemaining > 8) {
0468:                                short datum = data[i++];
0469:                                binaryDataArray[b++] = (byte) ((datum >>> 8) & 0xFF);
0470:                                binaryDataArray[b++] = (byte) (datum & 0xFF);
0471:                                xRemaining -= 16;
0472:                            }
0473:                            if (xRemaining > 0) {
0474:                                binaryDataArray[b++] = (byte) ((data[i] >>> 8) & 0XFF);
0475:                            }
0476:                            eltOffset += lineStride;
0477:                        }
0478:                    } else if (dataBuffer instanceof  DataBufferInt) {
0479:                        int[] data = ((DataBufferInt) dataBuffer).getData();
0480:
0481:                        for (int y = 0; y < rectHeight; y++) {
0482:                            int xRemaining = rectWidth;
0483:                            int i = eltOffset;
0484:                            while (xRemaining > 24) {
0485:                                int datum = data[i++];
0486:                                binaryDataArray[b++] = (byte) ((datum >>> 24) & 0xFF);
0487:                                binaryDataArray[b++] = (byte) ((datum >>> 16) & 0xFF);
0488:                                binaryDataArray[b++] = (byte) ((datum >>> 8) & 0xFF);
0489:                                binaryDataArray[b++] = (byte) (datum & 0xFF);
0490:                                xRemaining -= 32;
0491:                            }
0492:                            int shift = 24;
0493:                            while (xRemaining > 0) {
0494:                                binaryDataArray[b++] = (byte) ((data[i] >>> shift) & 0xFF);
0495:                                shift -= 8;
0496:                                xRemaining -= 8;
0497:                            }
0498:                            eltOffset += lineStride;
0499:                        }
0500:                    }
0501:                } else { // bitOffset != 0
0502:                    if (dataBuffer instanceof  DataBufferByte) {
0503:                        byte[] data = ((DataBufferByte) dataBuffer).getData();
0504:
0505:                        if ((bitOffset & 7) == 0) {
0506:                            int stride = numBytesPerRow;
0507:                            int offset = 0;
0508:                            for (int y = 0; y < rectHeight; y++) {
0509:                                System.arraycopy(data, eltOffset,
0510:                                        binaryDataArray, offset, stride);
0511:                                offset += stride;
0512:                                eltOffset += lineStride;
0513:                            }
0514:                        } else { // bitOffset % 8 != 0
0515:                            int leftShift = bitOffset & 7;
0516:                            int rightShift = 8 - leftShift;
0517:                            for (int y = 0; y < rectHeight; y++) {
0518:                                int i = eltOffset;
0519:                                int xRemaining = rectWidth;
0520:                                while (xRemaining > 0) {
0521:                                    if (xRemaining > rightShift) {
0522:                                        binaryDataArray[b++] = (byte) (((data[i++] & 0xFF) << leftShift) | ((data[i] & 0xFF) >>> rightShift));
0523:                                    } else {
0524:                                        binaryDataArray[b++] = (byte) ((data[i] & 0xFF) << leftShift);
0525:                                    }
0526:                                    xRemaining -= 8;
0527:                                }
0528:                                eltOffset += lineStride;
0529:                            }
0530:                        }
0531:                    } else if (dataBuffer instanceof  DataBufferShort
0532:                            || dataBuffer instanceof  DataBufferUShort) {
0533:                        short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0534:                                .getData()
0535:                                : ((DataBufferUShort) dataBuffer).getData();
0536:
0537:                        for (int y = 0; y < rectHeight; y++) {
0538:                            int bOffset = bitOffset;
0539:                            for (int x = 0; x < rectWidth; x += 8, bOffset += 8) {
0540:                                int i = eltOffset + bOffset / 16;
0541:                                int mod = bOffset % 16;
0542:                                int left = data[i] & 0xFFFF;
0543:                                if (mod <= 8) {
0544:                                    binaryDataArray[b++] = (byte) (left >>> (8 - mod));
0545:                                } else {
0546:                                    int delta = mod - 8;
0547:                                    int right = data[i + 1] & 0xFFFF;
0548:                                    binaryDataArray[b++] = (byte) ((left << delta) | (right >>> (16 - delta)));
0549:                                }
0550:                            }
0551:                            eltOffset += lineStride;
0552:                        }
0553:                    } else if (dataBuffer instanceof  DataBufferInt) {
0554:                        int[] data = ((DataBufferInt) dataBuffer).getData();
0555:
0556:                        for (int y = 0; y < rectHeight; y++) {
0557:                            int bOffset = bitOffset;
0558:                            for (int x = 0; x < rectWidth; x += 8, bOffset += 8) {
0559:                                int i = eltOffset + bOffset / 32;
0560:                                int mod = bOffset % 32;
0561:                                int left = data[i];
0562:                                if (mod <= 24) {
0563:                                    binaryDataArray[b++] = (byte) (left >>> (24 - mod));
0564:                                } else {
0565:                                    int delta = mod - 24;
0566:                                    int right = data[i + 1];
0567:                                    binaryDataArray[b++] = (byte) ((left << delta) | (right >>> (32 - delta)));
0568:                                }
0569:                            }
0570:                            eltOffset += lineStride;
0571:                        }
0572:                    }
0573:                }
0574:
0575:                return binaryDataArray;
0576:            }
0577:
0578:            /**
0579:             * Returns the binary data unpacked into an array of bytes.
0580:             * The line stride will be the width of the <code>Raster</code>.
0581:             *
0582:             * @throws IllegalArgumentException if <code>isBinary()</code> returns
0583:             * <code>false</code> with the <code>SampleModel</code> of the
0584:             * supplied <code>Raster</code> as argument.
0585:             */
0586:            public static byte[] getUnpackedBinaryData(Raster raster,
0587:                    Rectangle rect) {
0588:                SampleModel sm = raster.getSampleModel();
0589:                if (!isBinary(sm)) {
0590:                    throw new IllegalArgumentException(JaiI18N
0591:                            .getString("ImageUtil0"));
0592:                }
0593:
0594:                int rectX = rect.x;
0595:                int rectY = rect.y;
0596:                int rectWidth = rect.width;
0597:                int rectHeight = rect.height;
0598:
0599:                DataBuffer dataBuffer = raster.getDataBuffer();
0600:
0601:                int dx = rectX - raster.getSampleModelTranslateX();
0602:                int dy = rectY - raster.getSampleModelTranslateY();
0603:
0604:                MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel) sm;
0605:                int lineStride = mpp.getScanlineStride();
0606:                int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
0607:                int bitOffset = mpp.getBitOffset(dx);
0608:
0609:                byte[] bdata = new byte[rectWidth * rectHeight];
0610:                int maxY = rectY + rectHeight;
0611:                int maxX = rectX + rectWidth;
0612:                int k = 0;
0613:
0614:                if (dataBuffer instanceof  DataBufferByte) {
0615:                    byte[] data = ((DataBufferByte) dataBuffer).getData();
0616:                    for (int y = rectY; y < maxY; y++) {
0617:                        int bOffset = eltOffset * 8 + bitOffset;
0618:                        for (int x = rectX; x < maxX; x++) {
0619:                            byte b = data[bOffset / 8];
0620:                            bdata[k++] = (byte) ((b >>> (7 - bOffset & 7)) & 0x0000001);
0621:                            bOffset++;
0622:                        }
0623:                        eltOffset += lineStride;
0624:                    }
0625:                } else if (dataBuffer instanceof  DataBufferShort
0626:                        || dataBuffer instanceof  DataBufferUShort) {
0627:                    short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0628:                            .getData()
0629:                            : ((DataBufferUShort) dataBuffer).getData();
0630:                    for (int y = rectY; y < maxY; y++) {
0631:                        int bOffset = eltOffset * 16 + bitOffset;
0632:                        for (int x = rectX; x < maxX; x++) {
0633:                            short s = data[bOffset / 16];
0634:                            bdata[k++] = (byte) ((s >>> (15 - bOffset % 16)) & 0x0000001);
0635:                            bOffset++;
0636:                        }
0637:                        eltOffset += lineStride;
0638:                    }
0639:                } else if (dataBuffer instanceof  DataBufferInt) {
0640:                    int[] data = ((DataBufferInt) dataBuffer).getData();
0641:                    for (int y = rectY; y < maxY; y++) {
0642:                        int bOffset = eltOffset * 32 + bitOffset;
0643:                        for (int x = rectX; x < maxX; x++) {
0644:                            int i = data[bOffset / 32];
0645:                            bdata[k++] = (byte) ((i >>> (31 - bOffset % 32)) & 0x0000001);
0646:                            bOffset++;
0647:                        }
0648:                        eltOffset += lineStride;
0649:                    }
0650:                }
0651:
0652:                return bdata;
0653:            }
0654:
0655:            /**
0656:             * Sets the supplied <code>Raster</code>'s data from an array
0657:             * of packed binary data of the form returned by
0658:             * <code>getPackedBinaryData()</code>.
0659:             *
0660:             * @throws IllegalArgumentException if <code>isBinary()</code> returns
0661:             * <code>false</code> with the <code>SampleModel</code> of the
0662:             * supplied <code>Raster</code> as argument.
0663:             */
0664:            public static void setPackedBinaryData(byte[] binaryDataArray,
0665:                    WritableRaster raster, Rectangle rect) {
0666:                SampleModel sm = raster.getSampleModel();
0667:                if (!isBinary(sm)) {
0668:                    throw new IllegalArgumentException(JaiI18N
0669:                            .getString("ImageUtil0"));
0670:                }
0671:
0672:                int rectX = rect.x;
0673:                int rectY = rect.y;
0674:                int rectWidth = rect.width;
0675:                int rectHeight = rect.height;
0676:
0677:                DataBuffer dataBuffer = raster.getDataBuffer();
0678:
0679:                int dx = rectX - raster.getSampleModelTranslateX();
0680:                int dy = rectY - raster.getSampleModelTranslateY();
0681:
0682:                MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel) sm;
0683:                int lineStride = mpp.getScanlineStride();
0684:                int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
0685:                int bitOffset = mpp.getBitOffset(dx);
0686:
0687:                int b = 0;
0688:
0689:                if (bitOffset == 0) {
0690:                    if (dataBuffer instanceof  DataBufferByte) {
0691:                        byte[] data = ((DataBufferByte) dataBuffer).getData();
0692:                        if (data == binaryDataArray) {
0693:                            // Optimal case: simply return.
0694:                            return;
0695:                        }
0696:                        int stride = (rectWidth + 7) / 8;
0697:                        int offset = 0;
0698:                        for (int y = 0; y < rectHeight; y++) {
0699:                            System.arraycopy(binaryDataArray, offset, data,
0700:                                    eltOffset, stride);
0701:                            offset += stride;
0702:                            eltOffset += lineStride;
0703:                        }
0704:                    } else if (dataBuffer instanceof  DataBufferShort
0705:                            || dataBuffer instanceof  DataBufferUShort) {
0706:                        short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0707:                                .getData()
0708:                                : ((DataBufferUShort) dataBuffer).getData();
0709:
0710:                        for (int y = 0; y < rectHeight; y++) {
0711:                            int xRemaining = rectWidth;
0712:                            int i = eltOffset;
0713:                            while (xRemaining > 8) {
0714:                                data[i++] = (short) (((binaryDataArray[b++] & 0xFF) << 8) | (binaryDataArray[b++] & 0xFF));
0715:                                xRemaining -= 16;
0716:                            }
0717:                            if (xRemaining > 0) {
0718:                                data[i++] = (short) ((binaryDataArray[b++] & 0xFF) << 8);
0719:                            }
0720:                            eltOffset += lineStride;
0721:                        }
0722:                    } else if (dataBuffer instanceof  DataBufferInt) {
0723:                        int[] data = ((DataBufferInt) dataBuffer).getData();
0724:
0725:                        for (int y = 0; y < rectHeight; y++) {
0726:                            int xRemaining = rectWidth;
0727:                            int i = eltOffset;
0728:                            while (xRemaining > 24) {
0729:                                data[i++] = (int) (((binaryDataArray[b++] & 0xFF) << 24)
0730:                                        | ((binaryDataArray[b++] & 0xFF) << 16)
0731:                                        | ((binaryDataArray[b++] & 0xFF) << 8) | (binaryDataArray[b++] & 0xFF));
0732:                                xRemaining -= 32;
0733:                            }
0734:                            int shift = 24;
0735:                            while (xRemaining > 0) {
0736:                                data[i] |= (int) ((binaryDataArray[b++] & 0xFF) << shift);
0737:                                shift -= 8;
0738:                                xRemaining -= 8;
0739:                            }
0740:                            eltOffset += lineStride;
0741:                        }
0742:                    }
0743:                } else { // bitOffset != 0
0744:                    int stride = (rectWidth + 7) / 8;
0745:                    int offset = 0;
0746:                    if (dataBuffer instanceof  DataBufferByte) {
0747:                        byte[] data = ((DataBufferByte) dataBuffer).getData();
0748:
0749:                        if ((bitOffset & 7) == 0) {
0750:                            for (int y = 0; y < rectHeight; y++) {
0751:                                System.arraycopy(binaryDataArray, offset, data,
0752:                                        eltOffset, stride);
0753:                                offset += stride;
0754:                                eltOffset += lineStride;
0755:                            }
0756:                        } else { // bitOffset % 8 != 0
0757:                            int rightShift = bitOffset & 7;
0758:                            int leftShift = 8 - rightShift;
0759:                            int leftShift8 = 8 + leftShift;
0760:                            int mask = (byte) (255 << leftShift);
0761:                            int mask1 = (byte) ~mask;
0762:
0763:                            for (int y = 0; y < rectHeight; y++) {
0764:                                int i = eltOffset;
0765:                                int xRemaining = rectWidth;
0766:                                while (xRemaining > 0) {
0767:                                    byte datum = binaryDataArray[b++];
0768:
0769:                                    if (xRemaining > leftShift8) {
0770:                                        // when all the bits in this BYTE will be set
0771:                                        // into the data buffer.
0772:                                        data[i] = (byte) ((data[i] & mask) | ((datum & 0xFF) >>> rightShift));
0773:                                        data[++i] = (byte) ((datum & 0xFF) << leftShift);
0774:                                    } else if (xRemaining > leftShift) {
0775:                                        // All the "leftShift" high bits will be set
0776:                                        // into the data buffer.  But not all the
0777:                                        // "rightShift" low bits will be set.
0778:                                        data[i] = (byte) ((data[i] & mask) | ((datum & 0xFF) >>> rightShift));
0779:                                        i++;
0780:                                        data[i] = (byte) ((data[i] & mask1) | ((datum & 0xFF) << leftShift));
0781:                                    } else {
0782:                                        // Less than "leftShift" high bits will be set.
0783:                                        int remainMask = (1 << leftShift
0784:                                                - xRemaining) - 1;
0785:                                        data[i] = (byte) ((data[i] & (mask | remainMask)) | (datum & 0xFF) >>> rightShift
0786:                                                & ~remainMask);
0787:                                    }
0788:                                    xRemaining -= 8;
0789:                                }
0790:                                eltOffset += lineStride;
0791:                            }
0792:                        }
0793:                    } else if (dataBuffer instanceof  DataBufferShort
0794:                            || dataBuffer instanceof  DataBufferUShort) {
0795:                        short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0796:                                .getData()
0797:                                : ((DataBufferUShort) dataBuffer).getData();
0798:
0799:                        int rightShift = bitOffset & 7;
0800:                        int leftShift = 8 - rightShift;
0801:                        int leftShift16 = 16 + leftShift;
0802:                        int mask = (short) (~(255 << leftShift));
0803:                        int mask1 = (short) (65535 << leftShift);
0804:                        int mask2 = (short) ~mask1;
0805:
0806:                        for (int y = 0; y < rectHeight; y++) {
0807:                            int bOffset = bitOffset;
0808:                            int xRemaining = rectWidth;
0809:                            for (int x = 0; x < rectWidth; x += 8, bOffset += 8, xRemaining -= 8) {
0810:                                int i = eltOffset + (bOffset >> 4);
0811:                                int mod = bOffset & 15;
0812:                                int datum = binaryDataArray[b++] & 0xFF;
0813:                                if (mod <= 8) {
0814:                                    // This BYTE is set into one SHORT
0815:                                    if (xRemaining < 8) {
0816:                                        // Mask the bits to be set.
0817:                                        datum &= 255 << 8 - xRemaining;
0818:                                    }
0819:                                    data[i] = (short) ((data[i] & mask) | (datum << leftShift));
0820:                                } else if (xRemaining > leftShift16) {
0821:                                    // This BYTE will be set into two SHORTs
0822:                                    data[i] = (short) ((data[i] & mask1) | ((datum >>> rightShift) & 0xFFFF));
0823:                                    data[++i] = (short) ((datum << leftShift) & 0xFFFF);
0824:                                } else if (xRemaining > leftShift) {
0825:                                    // This BYTE will be set into two SHORTs;
0826:                                    // But not all the low bits will be set into SHORT
0827:                                    data[i] = (short) ((data[i] & mask1) | ((datum >>> rightShift) & 0xFFFF));
0828:                                    i++;
0829:                                    data[i] = (short) ((data[i] & mask2) | ((datum << leftShift) & 0xFFFF));
0830:                                } else {
0831:                                    // Only some of the high bits will be set into
0832:                                    // SHORTs
0833:                                    int remainMask = (1 << leftShift
0834:                                            - xRemaining) - 1;
0835:                                    data[i] = (short) ((data[i] & (mask1 | remainMask)) | ((datum >>> rightShift) & 0xFFFF & ~remainMask));
0836:                                }
0837:                            }
0838:                            eltOffset += lineStride;
0839:                        }
0840:                    } else if (dataBuffer instanceof  DataBufferInt) {
0841:                        int[] data = ((DataBufferInt) dataBuffer).getData();
0842:                        int rightShift = bitOffset & 7;
0843:                        int leftShift = 8 - rightShift;
0844:                        int leftShift32 = 32 + leftShift;
0845:                        int mask = 0xFFFFFFFF << leftShift;
0846:                        int mask1 = ~mask;
0847:
0848:                        for (int y = 0; y < rectHeight; y++) {
0849:                            int bOffset = bitOffset;
0850:                            int xRemaining = rectWidth;
0851:                            for (int x = 0; x < rectWidth; x += 8, bOffset += 8, xRemaining -= 8) {
0852:                                int i = eltOffset + (bOffset >> 5);
0853:                                int mod = bOffset & 31;
0854:                                int datum = binaryDataArray[b++] & 0xFF;
0855:                                if (mod <= 24) {
0856:                                    // This BYTE is set into one INT
0857:                                    int shift = 24 - mod;
0858:                                    if (xRemaining < 8) {
0859:                                        // Mask the bits to be set.
0860:                                        datum &= 255 << 8 - xRemaining;
0861:                                    }
0862:                                    data[i] = (data[i] & (~(255 << shift)))
0863:                                            | (datum << shift);
0864:                                } else if (xRemaining > leftShift32) {
0865:                                    // All the bits of this BYTE will be set into two INTs
0866:                                    data[i] = (data[i] & mask)
0867:                                            | (datum >>> rightShift);
0868:                                    data[++i] = datum << leftShift;
0869:                                } else if (xRemaining > leftShift) {
0870:                                    // This BYTE will be set into two INTs;
0871:                                    // But not all the low bits will be set into INT
0872:                                    data[i] = (data[i] & mask)
0873:                                            | (datum >>> rightShift);
0874:                                    i++;
0875:                                    data[i] = (data[i] & mask1)
0876:                                            | (datum << leftShift);
0877:                                } else {
0878:                                    // Only some of the high bits will be set into INT
0879:                                    int remainMask = (1 << leftShift
0880:                                            - xRemaining) - 1;
0881:                                    data[i] = (data[i] & (mask | remainMask))
0882:                                            | (datum >>> rightShift & ~remainMask);
0883:                                }
0884:                            }
0885:                            eltOffset += lineStride;
0886:                        }
0887:                    }
0888:                }
0889:            }
0890:
0891:            /**
0892:             * Copies data into the packed array of the <code>Raster</code>
0893:             * from an array of unpacked data of the form returned by
0894:             * <code>getUnpackedBinaryData()</code>.
0895:             *
0896:             * <p> If the data are binary, then the target bit will be set if
0897:             * and only if the corresponding byte is non-zero.
0898:             *
0899:             * @throws IllegalArgumentException if <code>isBinary()</code> returns
0900:             * <code>false</code> with the <code>SampleModel</code> of the
0901:             * supplied <code>Raster</code> as argument.
0902:             */
0903:            public static void setUnpackedBinaryData(byte[] bdata,
0904:                    WritableRaster raster, Rectangle rect) {
0905:                SampleModel sm = raster.getSampleModel();
0906:                if (!isBinary(sm)) {
0907:                    throw new IllegalArgumentException(JaiI18N
0908:                            .getString("ImageUtil0"));
0909:                }
0910:
0911:                int rectX = rect.x;
0912:                int rectY = rect.y;
0913:                int rectWidth = rect.width;
0914:                int rectHeight = rect.height;
0915:
0916:                DataBuffer dataBuffer = raster.getDataBuffer();
0917:
0918:                int dx = rectX - raster.getSampleModelTranslateX();
0919:                int dy = rectY - raster.getSampleModelTranslateY();
0920:
0921:                MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel) sm;
0922:                int lineStride = mpp.getScanlineStride();
0923:                int eltOffset = dataBuffer.getOffset() + mpp.getOffset(dx, dy);
0924:                int bitOffset = mpp.getBitOffset(dx);
0925:
0926:                int k = 0;
0927:
0928:                if (dataBuffer instanceof  DataBufferByte) {
0929:                    byte[] data = ((DataBufferByte) dataBuffer).getData();
0930:                    for (int y = 0; y < rectHeight; y++) {
0931:                        int bOffset = eltOffset * 8 + bitOffset;
0932:                        for (int x = 0; x < rectWidth; x++) {
0933:                            if (bdata[k++] != (byte) 0) {
0934:                                data[bOffset / 8] |= (byte) (0x00000001 << (7 - bOffset & 7));
0935:                            }
0936:                            bOffset++;
0937:                        }
0938:                        eltOffset += lineStride;
0939:                    }
0940:                } else if (dataBuffer instanceof  DataBufferShort
0941:                        || dataBuffer instanceof  DataBufferUShort) {
0942:                    short[] data = dataBuffer instanceof  DataBufferShort ? ((DataBufferShort) dataBuffer)
0943:                            .getData()
0944:                            : ((DataBufferUShort) dataBuffer).getData();
0945:                    for (int y = 0; y < rectHeight; y++) {
0946:                        int bOffset = eltOffset * 16 + bitOffset;
0947:                        for (int x = 0; x < rectWidth; x++) {
0948:                            if (bdata[k++] != (byte) 0) {
0949:                                data[bOffset / 16] |= (short) (0x00000001 << (15 - bOffset % 16));
0950:                            }
0951:                            bOffset++;
0952:                        }
0953:                        eltOffset += lineStride;
0954:                    }
0955:                } else if (dataBuffer instanceof  DataBufferInt) {
0956:                    int[] data = ((DataBufferInt) dataBuffer).getData();
0957:                    for (int y = 0; y < rectHeight; y++) {
0958:                        int bOffset = eltOffset * 32 + bitOffset;
0959:                        for (int x = 0; x < rectWidth; x++) {
0960:                            if (bdata[k++] != (byte) 0) {
0961:                                data[bOffset / 32] |= (int) (0x00000001 << (31 - bOffset % 32));
0962:                            }
0963:                            bOffset++;
0964:                        }
0965:                        eltOffset += lineStride;
0966:                    }
0967:                }
0968:            }
0969:
0970:            /** Fill the specified rectangle of <code>raster</code> with the provided
0971:             *  background values.  Suppose the raster is initialized to 0.  Thus,
0972:             *  for binary data, if the provided background values are 0, do nothing.
0973:             */
0974:            public static void fillBackground(WritableRaster raster,
0975:                    Rectangle rect, double[] backgroundValues) {
0976:                rect = rect.intersection(raster.getBounds());
0977:                int numBands = raster.getSampleModel().getNumBands();
0978:                SampleModel sm = raster.getSampleModel();
0979:                PixelAccessor accessor = new PixelAccessor(sm, null);
0980:
0981:                if (isBinary(sm)) {
0982:                    //fill binary data
0983:                    byte value = (byte) (((int) backgroundValues[0]) & 1);
0984:                    if (value == 0)
0985:                        return;
0986:                    int rectX = rect.x;
0987:                    int rectY = rect.y;
0988:                    int rectWidth = rect.width;
0989:                    int rectHeight = rect.height;
0990:
0991:                    int dx = rectX - raster.getSampleModelTranslateX();
0992:                    int dy = rectY - raster.getSampleModelTranslateY();
0993:
0994:                    DataBuffer dataBuffer = raster.getDataBuffer();
0995:                    MultiPixelPackedSampleModel mpp = (MultiPixelPackedSampleModel) sm;
0996:                    int lineStride = mpp.getScanlineStride();
0997:                    int eltOffset = dataBuffer.getOffset()
0998:                            + mpp.getOffset(dx, dy);
0999:                    int bitOffset = mpp.getBitOffset(dx);
1000:
1001:                    switch (sm.getDataType()) {
1002:                    case DataBuffer.TYPE_BYTE: {
1003:                        byte[] data = ((DataBufferByte) dataBuffer).getData();
1004:                        int bits = bitOffset & 7;
1005:                        int otherBits = (bits == 0) ? 0 : 8 - bits;
1006:
1007:                        byte mask = (byte) (255 >> bits);
1008:                        int lineLength = (rectWidth - otherBits) / 8;
1009:                        int bits1 = (rectWidth - otherBits) & 7;
1010:                        byte mask1 = (byte) (255 << (8 - bits1));
1011:                        // If operating within a single byte, merge masks into one
1012:                        // and don't apply second mask after while loop
1013:                        if (lineLength == 0) {
1014:                            mask &= mask1;
1015:                            bits1 = 0;
1016:                        }
1017:
1018:                        for (int y = 0; y < rectHeight; y++) {
1019:                            int start = eltOffset;
1020:                            int end = start + lineLength;
1021:                            if (bits != 0)
1022:                                data[start++] |= mask;
1023:                            while (start < end)
1024:                                data[start++] = (byte) 255;
1025:                            if (bits1 != 0)
1026:                                data[start] |= mask1;
1027:                            eltOffset += lineStride;
1028:                        }
1029:                        break;
1030:                    }
1031:                    case DataBuffer.TYPE_USHORT: {
1032:                        short[] data = ((DataBufferUShort) dataBuffer)
1033:                                .getData();
1034:                        int bits = bitOffset & 15;
1035:                        int otherBits = (bits == 0) ? 0 : 16 - bits;
1036:
1037:                        short mask = (short) (65535 >> bits);
1038:                        int lineLength = (rectWidth - otherBits) / 16;
1039:                        int bits1 = (rectWidth - otherBits) & 15;
1040:                        short mask1 = (short) (65535 << (16 - bits1));
1041:                        // If operating within a single byte, merge masks into one
1042:                        // and don't apply second mask after while loop
1043:                        if (lineLength == 0) {
1044:                            mask &= mask1;
1045:                            bits1 = 0;
1046:                        }
1047:
1048:                        for (int y = 0; y < rectHeight; y++) {
1049:                            int start = eltOffset;
1050:                            int end = start + lineLength;
1051:                            if (bits != 0)
1052:                                data[start++] |= mask;
1053:                            while (start < end)
1054:                                data[start++] = (short) 0xFFFF;
1055:                            if (bits1 != 0)
1056:                                data[start++] |= mask1;
1057:                            eltOffset += lineStride;
1058:                        }
1059:                        break;
1060:                    }
1061:                    case DataBuffer.TYPE_INT: {
1062:                        int[] data = ((DataBufferInt) dataBuffer).getData();
1063:                        int bits = bitOffset & 31;
1064:                        int otherBits = (bits == 0) ? 0 : 32 - bits;
1065:
1066:                        int mask = 0xFFFFFFFF >> bits;
1067:                        int lineLength = (rectWidth - otherBits) / 32;
1068:                        int bits1 = (rectWidth - otherBits) & 31;
1069:                        int mask1 = 0xFFFFFFFF << (32 - bits1);
1070:                        // If operating within a single byte, merge masks into one
1071:                        // and don't apply second mask after while loop
1072:                        if (lineLength == 0) {
1073:                            mask &= mask1;
1074:                            bits1 = 0;
1075:                        }
1076:
1077:                        for (int y = 0; y < rectHeight; y++) {
1078:                            int start = eltOffset;
1079:                            int end = start + lineLength;
1080:                            if (bits != 0)
1081:                                data[start++] |= mask;
1082:                            while (start < end)
1083:                                data[start++] = 0xFFFFFFFF;
1084:                            if (bits1 != 0)
1085:                                data[start++] |= mask1;
1086:                            eltOffset += lineStride;
1087:                        }
1088:                        break;
1089:                    }
1090:
1091:                    }
1092:                } else {
1093:                    int srcSampleType = accessor.sampleType == PixelAccessor.TYPE_BIT ? DataBuffer.TYPE_BYTE
1094:                            : accessor.sampleType;
1095:                    UnpackedImageData uid = accessor.getPixels(raster, rect,
1096:                            srcSampleType, false);
1097:                    rect = uid.rect;
1098:                    int lineStride = uid.lineStride;
1099:                    int pixelStride = uid.pixelStride;
1100:
1101:                    switch (uid.type) {
1102:                    case DataBuffer.TYPE_BYTE:
1103:                        byte[][] bdata = uid.getByteData();
1104:                        for (int b = 0; b < accessor.numBands; b++) {
1105:                            byte value = (byte) backgroundValues[b];
1106:                            byte[] bd = bdata[b];
1107:                            int lastLine = uid.bandOffsets[b] + rect.height
1108:                                    * lineStride;
1109:
1110:                            for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineStride) {
1111:                                int lastPixel = lo + rect.width * pixelStride;
1112:                                for (int po = lo; po < lastPixel; po += pixelStride) {
1113:                                    bd[po] = value;
1114:                                }
1115:                            }
1116:                        }
1117:                        break;
1118:                    case DataBuffer.TYPE_USHORT:
1119:                    case DataBuffer.TYPE_SHORT:
1120:                        short[][] sdata = uid.getShortData();
1121:                        for (int b = 0; b < accessor.numBands; b++) {
1122:                            short value = (short) backgroundValues[b];
1123:                            short[] sd = sdata[b];
1124:                            int lastLine = uid.bandOffsets[b] + rect.height
1125:                                    * lineStride;
1126:
1127:                            for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineStride) {
1128:                                int lastPixel = lo + rect.width * pixelStride;
1129:                                for (int po = lo; po < lastPixel; po += pixelStride) {
1130:                                    sd[po] = value;
1131:                                }
1132:                            }
1133:                        }
1134:                        break;
1135:                    case DataBuffer.TYPE_INT:
1136:                        int[][] idata = uid.getIntData();
1137:                        for (int b = 0; b < accessor.numBands; b++) {
1138:                            int value = (int) backgroundValues[b];
1139:                            int[] id = idata[b];
1140:                            int lastLine = uid.bandOffsets[b] + rect.height
1141:                                    * lineStride;
1142:
1143:                            for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineStride) {
1144:                                int lastPixel = lo + rect.width * pixelStride;
1145:                                for (int po = lo; po < lastPixel; po += pixelStride) {
1146:                                    id[po] = value;
1147:                                }
1148:                            }
1149:                        }
1150:                        break;
1151:                    case DataBuffer.TYPE_FLOAT:
1152:                        float[][] fdata = uid.getFloatData();
1153:                        for (int b = 0; b < accessor.numBands; b++) {
1154:                            float value = (float) backgroundValues[b];
1155:                            float[] fd = fdata[b];
1156:                            int lastLine = uid.bandOffsets[b] + rect.height
1157:                                    * lineStride;
1158:
1159:                            for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineStride) {
1160:                                int lastPixel = lo + rect.width * pixelStride;
1161:                                for (int po = lo; po < lastPixel; po += pixelStride) {
1162:                                    fd[po] = value;
1163:                                }
1164:                            }
1165:                        }
1166:                        break;
1167:                    case DataBuffer.TYPE_DOUBLE:
1168:                        double[][] ddata = uid.getDoubleData();
1169:                        for (int b = 0; b < accessor.numBands; b++) {
1170:                            double value = backgroundValues[b];
1171:                            double[] dd = ddata[b];
1172:                            int lastLine = uid.bandOffsets[b] + rect.height
1173:                                    * lineStride;
1174:
1175:                            for (int lo = uid.bandOffsets[b]; lo < lastLine; lo += lineStride) {
1176:                                int lastPixel = lo + rect.width * pixelStride;
1177:                                for (int po = lo; po < lastPixel; po += pixelStride) {
1178:                                    dd[po] = value;
1179:                                }
1180:                            }
1181:                        }
1182:                        break;
1183:                    }
1184:                }
1185:            }
1186:
1187:            /** When the destination rectangle is not the same as the image bounds,
1188:             *  should fill the border.
1189:             */
1190:            public static void fillBordersWithBackgroundValues(
1191:                    Rectangle outerRect, Rectangle innerRect,
1192:                    WritableRaster raster, double[] backgroundValues) {
1193:                int outerMaxX = outerRect.x + outerRect.width;
1194:                int outerMaxY = outerRect.y + outerRect.height;
1195:
1196:                int innerMaxX = innerRect.x + innerRect.width;
1197:                int innerMaxY = innerRect.y + innerRect.height;
1198:
1199:                if (outerRect.x < innerRect.x) {
1200:                    Rectangle rect = new Rectangle(outerRect.x, innerRect.y,
1201:                            innerRect.x - outerRect.x, outerMaxY - innerRect.y);
1202:                    fillBackground(raster, rect, backgroundValues);
1203:                }
1204:
1205:                if (outerRect.y < innerRect.y) {
1206:                    Rectangle rect = new Rectangle(outerRect.x, outerRect.y,
1207:                            innerMaxX - outerRect.x, innerRect.y - outerRect.y);
1208:                    fillBackground(raster, rect, backgroundValues);
1209:                }
1210:
1211:                if (outerMaxX > innerMaxX) {
1212:                    Rectangle rect = new Rectangle(innerMaxX, outerRect.y,
1213:                            outerMaxX - innerMaxX, innerMaxY - outerRect.y);
1214:                    fillBackground(raster, rect, backgroundValues);
1215:                }
1216:
1217:                if (outerMaxY > innerMaxY) {
1218:                    Rectangle rect = new Rectangle(innerRect.x, innerMaxY,
1219:                            outerMaxX - innerRect.x, outerMaxY - innerMaxY);
1220:                    fillBackground(raster, rect, backgroundValues);
1221:                }
1222:            }
1223:
1224:            /// ---- END Binary data handling methods ----
1225:
1226:            /**
1227:             * Given a kernel and the gain (sharpness) factor of an
1228:             * UnsharpMask operation, compute a modified kernel that
1229:             * would be equivalent to the specified unsharp operation.
1230:             *
1231:             * for UnsharpMask function we have the following formula:
1232:             *
1233:             * dst(i,j) = src(i,j) + gain *
1234:             *			(src(i,j) - SUM  SUM  K(l,m) * src(i+l,j+m))
1235:             *				     l    m
1236:             *
1237:             * Which can be written as :
1238:             *
1239:             * dst(i,j) = SUM  SUM  Q(l,m) * src(i+l,j+m),
1240:             *             l    m
1241:             *
1242:             * where Q(0,0) = 1 + gain * (1 - K(0,0)), and
1243:             *	      Q(l,m) = - gain * K(l,m)  otherwise
1244:             *
1245:             * @param kernel the unsharp mask kernel
1246:             * @param gain the unsharp mask gain (sharpness) factor.
1247:             *
1248:             * @return an equivalent convolution KernelJAI
1249:             */
1250:            public static KernelJAI getUnsharpMaskEquivalentKernel(
1251:                    KernelJAI kernel, float gain) {
1252:
1253:                int width = kernel.getWidth();
1254:                int height = kernel.getHeight();
1255:                int xOrigin = kernel.getXOrigin();
1256:                int yOrigin = kernel.getYOrigin();
1257:
1258:                float oldData[] = kernel.getKernelData();
1259:                float newData[] = new float[oldData.length];
1260:
1261:                int k;
1262:
1263:                for (k = 0; k < width * height; k++)
1264:                    newData[k] = -gain * oldData[k];
1265:
1266:                k = yOrigin * width + xOrigin;
1267:                newData[k] = 1.0f + gain * (1.0f - oldData[k]);
1268:
1269:                return new KernelJAI(width, height, xOrigin, yOrigin, newData);
1270:            }
1271:
1272:            /**
1273:             * Retrieve the indices of a set of tiles in row-major order with
1274:             * the given tile index bounds in x and y.
1275:             */
1276:            public static final Point[] getTileIndices(int txmin, int txmax,
1277:                    int tymin, int tymax) {
1278:                if (txmin > txmax || tymin > tymax) {
1279:                    return null;
1280:                }
1281:
1282:                Point[] tileIndices = new Point[(txmax - txmin + 1)
1283:                        * (tymax - tymin + 1)];
1284:                int k = 0;
1285:                for (int tj = tymin; tj <= tymax; tj++) {
1286:                    for (int ti = txmin; ti <= txmax; ti++) {
1287:                        tileIndices[k++] = new Point(ti, tj);
1288:                    }
1289:                }
1290:
1291:                return tileIndices;
1292:            }
1293:
1294:            /// Method for handling DeferrdData objects in ParameterBlocks.
1295:
1296:            /**
1297:             * If any <code>DeferredData</code> components are detected,
1298:             * the argument is cloned and the <code>DeferredData</code>
1299:             * object is replaced with what its <code>getData()</code> returns.
1300:             */
1301:            public static Vector evaluateParameters(Vector parameters) {
1302:                if (parameters == null) {
1303:                    throw new IllegalArgumentException();
1304:                }
1305:
1306:                Vector paramEval = parameters;
1307:
1308:                int size = parameters.size();
1309:                for (int i = 0; i < size; i++) {
1310:                    Object element = parameters.get(i);
1311:                    if (element instanceof  DeferredData) {
1312:                        if (paramEval == parameters) {
1313:                            paramEval = (Vector) parameters.clone();
1314:                        }
1315:                        paramEval.set(i, ((DeferredData) element).getData());
1316:                    }
1317:                }
1318:
1319:                return paramEval;
1320:            }
1321:
1322:            /**
1323:             * If any <code>DeferredData</code> parameters are detected,
1324:             * a new <code>ParameterBlock</code> is constructed and the
1325:             * <code>DeferredData</code> object is replaced with what its
1326:             * <code>getData()</code> returns.
1327:             */
1328:            public static ParameterBlock evaluateParameters(ParameterBlock pb) {
1329:                if (pb == null) {
1330:                    throw new IllegalArgumentException();
1331:                }
1332:
1333:                Vector parameters = pb.getParameters();
1334:                Vector paramEval = evaluateParameters(parameters);
1335:                return paramEval == parameters ? pb : new ParameterBlock(pb
1336:                        .getSources(), paramEval);
1337:            }
1338:
1339:            /**
1340:             * Derive a compatible <code>ColorModel</code> for the supplied
1341:             * <code>SampleModel</code> using the method specified via the
1342:             * <code>OpImage</code> configuration <code>Map</code>.
1343:             *
1344:             * @return a compatible <code>ColorModel</code> or <code>null</code>.
1345:             */
1346:            public static ColorModel getCompatibleColorModel(SampleModel sm,
1347:                    Map config) {
1348:                ColorModel cm = null;
1349:
1350:                if (config == null
1351:                        || !Boolean.FALSE.equals(config
1352:                                .get(JAI.KEY_DEFAULT_COLOR_MODEL_ENABLED))) {
1353:
1354:                    // Set the default ColorModel
1355:
1356:                    if (config != null
1357:                            && config
1358:                                    .containsKey(JAI.KEY_DEFAULT_COLOR_MODEL_METHOD)) {
1359:                        // Attempt to retrieve the default CM Method.
1360:                        Method cmMethod = (Method) config
1361:                                .get(JAI.KEY_DEFAULT_COLOR_MODEL_METHOD);
1362:
1363:                        // Check method compatibility.
1364:                        Class[] paramTypes = cmMethod.getParameterTypes();
1365:                        if ((cmMethod.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
1366:                            // Method must be static.
1367:                            throw new RuntimeException(JaiI18N
1368:                                    .getString("ImageUtil1"));
1369:                        } else if (cmMethod.getReturnType() != ColorModel.class) {
1370:                            // Method must return a ColorModel.
1371:                            throw new RuntimeException(JaiI18N
1372:                                    .getString("ImageUtil2"));
1373:                        } else if (paramTypes.length != 1
1374:                                || !paramTypes[0].equals(SampleModel.class)) {
1375:                            // Unique Method parameter must be a SampleModel.
1376:                            throw new RuntimeException(JaiI18N
1377:                                    .getString("ImageUtil3"));
1378:                        }
1379:
1380:                        // Set the default ColorModel.
1381:                        try {
1382:                            // Attempt to use the supplied Method.
1383:                            Object[] args = new Object[] { sm };
1384:                            cm = (ColorModel) cmMethod.invoke(null, args);
1385:                        } catch (Exception e) {
1386:                            String message = JaiI18N.getString("ImageUtil4")
1387:                                    + cmMethod.getName();
1388:                            sendExceptionToListener(message,
1389:                                    new ImagingException(message, e));
1390:                            /*
1391:                             // XXX Is this a reasonable Exception to throw?
1392:                             throw new RuntimeException(cmMethod.getName()+" "+
1393:                             e.getMessage());
1394:                             */
1395:                        }
1396:                    } else { // No default method hint set.
1397:                        // Use PlanarImage method.
1398:                        cm = PlanarImage.createColorModel(sm);
1399:                    }
1400:                }
1401:
1402:                return cm;
1403:            }
1404:
1405:            /**
1406:             * Converts the supplied <code>Exception</code>'s stack trace
1407:             * to a <code>String</code>.
1408:             */
1409:            public static String getStackTraceString(Exception e) {
1410:                ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
1411:                PrintStream printStream = new PrintStream(byteStream);
1412:                e.printStackTrace(printStream);
1413:                printStream.flush();
1414:                String stackTraceString = byteStream.toString();
1415:                printStream.close();
1416:                return stackTraceString;
1417:            }
1418:
1419:            public static ImagingListener getImagingListener(
1420:                    RenderingHints hints) {
1421:                ImagingListener listener = null;
1422:                if (hints != null)
1423:                    listener = (ImagingListener) hints
1424:                            .get(JAI.KEY_IMAGING_LISTENER);
1425:
1426:                if (listener == null)
1427:                    listener = JAI.getDefaultInstance().getImagingListener();
1428:                return listener;
1429:            }
1430:
1431:            public static ImagingListener getImagingListener(
1432:                    RenderContext context) {
1433:                return getImagingListener(context.getRenderingHints());
1434:            }
1435:
1436:            /**
1437:             * Generates a UID for the provided <code>Object</code>.
1438:             *  The counter for the objects that request an ID, the hashcode of the
1439:             *  class of the provided object, the hashcode of the provided object,
1440:             *  the current time in milli seconds, and a random number are
1441:             *  concatenated together in a <code>BigInteger</code>.  This
1442:             *  <code>BigInteger</code> is returned as the unique ID.
1443:             */
1444:            public static synchronized Object generateID(Object owner) {
1445:                Class c = owner.getClass();
1446:                counter++;
1447:
1448:                byte[] uid = new byte[32];
1449:                int k = 0;
1450:                for (int i = 7, j = 0; i >= 0; i--, j += 8)
1451:                    uid[k++] = (byte) (counter >> j);
1452:                int hash = c.hashCode();
1453:                for (int i = 3, j = 0; i >= 0; i--, j += 8)
1454:                    uid[k++] = (byte) (hash >> j);
1455:                hash = owner.hashCode();
1456:                for (int i = 3, j = 0; i >= 0; i--, j += 8)
1457:                    uid[k++] = (byte) (hash >> j);
1458:                long time = System.currentTimeMillis();
1459:                for (int i = 7, j = 0; i >= 0; i--, j += 8)
1460:                    uid[k++] = (byte) (time >> j);
1461:                long rand = Double.doubleToLongBits(new Double(Math.random())
1462:                        .doubleValue());
1463:                for (int i = 7, j = 0; i >= 0; i--, j += 8)
1464:                    uid[k++] = (byte) (rand >> j);
1465:                return new BigInteger(uid);
1466:            }
1467:
1468:            static void sendExceptionToListener(String message, Exception e) {
1469:                ImagingListener listener = getImagingListener((RenderingHints) null);
1470:                listener.errorOccurred(message, e, ImageUtil.class, false);
1471:            }
1472:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.