Source Code Cross Referenced for LookupOp.java in  » 6.0-JDK-Core » AWT » java » awt » image » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2000 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.awt.image;
027
028        import java.awt.color.ColorSpace;
029        import java.awt.geom.Rectangle2D;
030        import java.awt.Rectangle;
031        import java.awt.RenderingHints;
032        import java.awt.geom.Point2D;
033        import sun.awt.image.ImagingLib;
034
035        /**
036         * This class implements a lookup operation from the source
037         * to the destination.  The LookupTable object may contain a single array
038         * or multiple arrays, subject to the restrictions below.
039         * <p>
040         * For Rasters, the lookup operates on bands.  The number of
041         * lookup arrays may be one, in which case the same array is
042         * applied to all bands, or it must equal the number of Source
043         * Raster bands.
044         * <p>
045         * For BufferedImages, the lookup operates on color and alpha components.
046         * The number of lookup arrays may be one, in which case the
047         * same array is applied to all color (but not alpha) components.
048         * Otherwise, the number of lookup arrays may
049         * equal the number of Source color components, in which case no
050         * lookup of the alpha component (if present) is performed.
051         * If neither of these cases apply, the number of lookup arrays
052         * must equal the number of Source color components plus alpha components,
053         * in which case lookup is performed for all color and alpha components.
054         * This allows non-uniform rescaling of multi-band BufferedImages.
055         * <p>
056         * BufferedImage sources with premultiplied alpha data are treated in the same
057         * manner as non-premultiplied images for purposes of the lookup.  That is,
058         * the lookup is done per band on the raw data of the BufferedImage source
059         * without regard to whether the data is premultiplied.  If a color conversion
060         * is required to the destination ColorModel, the premultiplied state of
061         * both source and destination will be taken into account for this step.
062         * <p>
063         * Images with an IndexColorModel cannot be used.
064         * <p>
065         * If a RenderingHints object is specified in the constructor, the
066         * color rendering hint and the dithering hint may be used when color
067         * conversion is required.
068         * <p>
069         * This class allows the Source to be the same as the Destination.
070         * 
071         * @version 10 Feb 1997
072         * @see LookupTable
073         * @see java.awt.RenderingHints#KEY_COLOR_RENDERING
074         * @see java.awt.RenderingHints#KEY_DITHERING
075         */
076
077        public class LookupOp implements  BufferedImageOp, RasterOp {
078            private LookupTable ltable;
079            private int numComponents;
080            RenderingHints hints;
081
082            /**
083             * Constructs a <code>LookupOp</code> object given the lookup 
084             * table and a <code>RenderingHints</code> object, which might 
085             * be <code>null</code>.
086             * @param lookup the specified <code>LookupTable</code>
087             * @param hints the specified <code>RenderingHints</code>,
088             *        or <code>null</code>
089             */
090            public LookupOp(LookupTable lookup, RenderingHints hints) {
091                this .ltable = lookup;
092                this .hints = hints;
093                numComponents = ltable.getNumComponents();
094            }
095
096            /**
097             * Returns the <code>LookupTable</code>.
098             * @return the <code>LookupTable</code> of this
099             *         <code>LookupOp</code>.
100             */
101            public final LookupTable getTable() {
102                return ltable;
103            }
104
105            /**
106             * Performs a lookup operation on a <code>BufferedImage</code>.  
107             * If the color model in the source image is not the same as that
108             * in the destination image, the pixels will be converted
109             * in the destination.  If the destination image is <code>null</code>,
110             * a <code>BufferedImage</code> will be created with an appropriate 
111             * <code>ColorModel</code>.  An <code>IllegalArgumentException</code>
112             * might be thrown if the number of arrays in the 
113             * <code>LookupTable</code> does not meet the restrictions
114             * stated in the class comment above, or if the source image
115             * has an <code>IndexColorModel</code>.
116             * @param src the <code>BufferedImage</code> to be filtered
117             * @param dst the <code>BufferedImage</code> in which to 
118             *            store the results of the filter operation
119             * @return the filtered <code>BufferedImage</code>.
120             * @throws IllegalArgumentException if the number of arrays in the
121             *         <code>LookupTable</code> does not meet the restrictions
122             *         described in the class comments, or if the source image
123             *         has an <code>IndexColorModel</code>.
124             */
125            public final BufferedImage filter(BufferedImage src,
126                    BufferedImage dst) {
127                ColorModel srcCM = src.getColorModel();
128                int numBands = srcCM.getNumColorComponents();
129                ColorModel dstCM;
130                if (srcCM instanceof  IndexColorModel) {
131                    throw new IllegalArgumentException("LookupOp cannot be "
132                            + "performed on an indexed image");
133                }
134                int numComponents = ltable.getNumComponents();
135                if (numComponents != 1
136                        && numComponents != srcCM.getNumComponents()
137                        && numComponents != srcCM.getNumColorComponents()) {
138                    throw new IllegalArgumentException(
139                            "Number of arrays in the " + " lookup table ("
140                                    + numComponents
141                                    + " is not compatible with the "
142                                    + " src image: " + src);
143                }
144
145                boolean needToConvert = false;
146
147                int width = src.getWidth();
148                int height = src.getHeight();
149
150                if (dst == null) {
151                    dst = createCompatibleDestImage(src, null);
152                    dstCM = srcCM;
153                } else {
154                    if (width != dst.getWidth()) {
155                        throw new IllegalArgumentException("Src width ("
156                                + width + ") not equal to dst width ("
157                                + dst.getWidth() + ")");
158                    }
159                    if (height != dst.getHeight()) {
160                        throw new IllegalArgumentException("Src height ("
161                                + height + ") not equal to dst height ("
162                                + dst.getHeight() + ")");
163                    }
164
165                    dstCM = dst.getColorModel();
166                    if (srcCM.getColorSpace().getType() != dstCM
167                            .getColorSpace().getType()) {
168                        needToConvert = true;
169                        dst = createCompatibleDestImage(src, null);
170                    }
171
172                }
173
174                BufferedImage origDst = dst;
175
176                if (ImagingLib.filter(this , src, dst) == null) {
177                    // Do it the slow way
178                    WritableRaster srcRaster = src.getRaster();
179                    WritableRaster dstRaster = dst.getRaster();
180
181                    if (srcCM.hasAlpha()) {
182                        if (numBands - 1 == numComponents || numComponents == 1) {
183                            int minx = srcRaster.getMinX();
184                            int miny = srcRaster.getMinY();
185                            int[] bands = new int[numBands - 1];
186                            for (int i = 0; i < numBands - 1; i++) {
187                                bands[i] = i;
188                            }
189                            srcRaster = srcRaster.createWritableChild(minx,
190                                    miny, srcRaster.getWidth(), srcRaster
191                                            .getHeight(), minx, miny, bands);
192                        }
193                    }
194                    if (dstCM.hasAlpha()) {
195                        int dstNumBands = dstRaster.getNumBands();
196                        if (dstNumBands - 1 == numComponents
197                                || numComponents == 1) {
198                            int minx = dstRaster.getMinX();
199                            int miny = dstRaster.getMinY();
200                            int[] bands = new int[numBands - 1];
201                            for (int i = 0; i < numBands - 1; i++) {
202                                bands[i] = i;
203                            }
204                            dstRaster = dstRaster.createWritableChild(minx,
205                                    miny, dstRaster.getWidth(), dstRaster
206                                            .getHeight(), minx, miny, bands);
207                        }
208                    }
209
210                    filter(srcRaster, dstRaster);
211                }
212
213                if (needToConvert) {
214                    // ColorModels are not the same
215                    ColorConvertOp ccop = new ColorConvertOp(hints);
216                    ccop.filter(dst, origDst);
217                }
218
219                return origDst;
220            }
221
222            /**
223             * Performs a lookup operation on a <code>Raster</code>.  
224             * If the destination <code>Raster</code> is <code>null</code>, 
225             * a new <code>Raster</code> will be created.
226             * The <code>IllegalArgumentException</code> might be thrown 
227             * if the source <code>Raster</code> and the destination 
228             * <code>Raster</code> do not have the same
229             * number of bands or if the number of arrays in the 
230             * <code>LookupTable</code> does not meet the
231             * restrictions stated in the class comment above.
232             * @param src the source <code>Raster</code> to filter
233             * @param dst the destination <code>WritableRaster</code> for the
234             *            filtered <code>src</code>
235             * @return the filtered <code>WritableRaster</code>.
236             * @throws IllegalArgumentException if the source and destinations 
237             *         rasters do not have the same number of bands, or the
238             *         number of arrays in the <code>LookupTable</code> does 
239             *         not meet the restrictions described in the class comments.
240             *         
241             */
242            public final WritableRaster filter(Raster src, WritableRaster dst) {
243                int numBands = src.getNumBands();
244                int dstLength = dst.getNumBands();
245                int height = src.getHeight();
246                int width = src.getWidth();
247                int srcPix[] = new int[numBands];
248
249                // Create a new destination Raster, if needed
250
251                if (dst == null) {
252                    dst = createCompatibleDestRaster(src);
253                } else if (height != dst.getHeight() || width != dst.getWidth()) {
254                    throw new IllegalArgumentException(
255                            "Width or height of Rasters do not " + "match");
256                }
257                dstLength = dst.getNumBands();
258
259                if (numBands != dstLength) {
260                    throw new IllegalArgumentException(
261                            "Number of channels in the src (" + numBands
262                                    + ") does not match number of channels"
263                                    + " in the destination (" + dstLength + ")");
264                }
265                int numComponents = ltable.getNumComponents();
266                if (numComponents != 1 && numComponents != src.getNumBands()) {
267                    throw new IllegalArgumentException(
268                            "Number of arrays in the " + " lookup table ("
269                                    + numComponents
270                                    + " is not compatible with the "
271                                    + " src Raster: " + src);
272                }
273
274                if (ImagingLib.filter(this , src, dst) != null) {
275                    return dst;
276                }
277
278                // Optimize for cases we know about
279                if (ltable instanceof  ByteLookupTable) {
280                    byteFilter((ByteLookupTable) ltable, src, dst, width,
281                            height, numBands);
282                } else if (ltable instanceof  ShortLookupTable) {
283                    shortFilter((ShortLookupTable) ltable, src, dst, width,
284                            height, numBands);
285                } else {
286                    // Not one we recognize so do it slowly
287                    int sminX = src.getMinX();
288                    int sY = src.getMinY();
289                    int dminX = dst.getMinX();
290                    int dY = dst.getMinY();
291                    for (int y = 0; y < height; y++, sY++, dY++) {
292                        int sX = sminX;
293                        int dX = dminX;
294                        for (int x = 0; x < width; x++, sX++, dX++) {
295                            // Find data for all bands at this x,y position
296                            src.getPixel(sX, sY, srcPix);
297
298                            // Lookup the data for all bands at this x,y position
299                            ltable.lookupPixel(srcPix, srcPix);
300
301                            // Put it back for all bands
302                            dst.setPixel(dX, dY, srcPix);
303                        }
304                    }
305                }
306
307                return dst;
308            }
309
310            /**
311             * Returns the bounding box of the filtered destination image.  Since
312             * this is not a geometric operation, the bounding box does not
313             * change.
314             * @param src the <code>BufferedImage</code> to be filtered
315             * @return the bounds of the filtered definition image.
316             */
317            public final Rectangle2D getBounds2D(BufferedImage src) {
318                return getBounds2D(src.getRaster());
319            }
320
321            /**
322             * Returns the bounding box of the filtered destination Raster.  Since
323             * this is not a geometric operation, the bounding box does not
324             * change.
325             * @param src the <code>Raster</code> to be filtered
326             * @return the bounds of the filtered definition <code>Raster</code>.
327             */
328            public final Rectangle2D getBounds2D(Raster src) {
329                return src.getBounds();
330
331            }
332
333            /**
334             * Creates a zeroed destination image with the correct size and number of
335             * bands.  If destCM is <code>null</code>, an appropriate 
336             * <code>ColorModel</code> will be used.
337             * @param src       Source image for the filter operation.
338             * @param destCM    the destination's <code>ColorModel</code>, which 
339             *                  can be <code>null</code>.
340             * @return a filtered destination <code>BufferedImage</code>.
341             */
342            public BufferedImage createCompatibleDestImage(BufferedImage src,
343                    ColorModel destCM) {
344                BufferedImage image;
345                int w = src.getWidth();
346                int h = src.getHeight();
347                int transferType = DataBuffer.TYPE_BYTE;
348                if (destCM == null) {
349                    ColorModel cm = src.getColorModel();
350                    Raster raster = src.getRaster();
351                    if (cm instanceof  ComponentColorModel) {
352                        DataBuffer db = raster.getDataBuffer();
353                        boolean hasAlpha = cm.hasAlpha();
354                        boolean isPre = cm.isAlphaPremultiplied();
355                        int trans = cm.getTransparency();
356                        int[] nbits = null;
357                        if (ltable instanceof  ByteLookupTable) {
358                            if (db.getDataType() == db.TYPE_USHORT) {
359                                // Dst raster should be of type byte
360                                if (hasAlpha) {
361                                    nbits = new int[2];
362                                    if (trans == cm.BITMASK) {
363                                        nbits[1] = 1;
364                                    } else {
365                                        nbits[1] = 8;
366                                    }
367                                } else {
368                                    nbits = new int[1];
369                                }
370                                nbits[0] = 8;
371                            }
372                            // For byte, no need to change the cm
373                        } else if (ltable instanceof  ShortLookupTable) {
374                            transferType = DataBuffer.TYPE_USHORT;
375                            if (db.getDataType() == db.TYPE_BYTE) {
376                                if (hasAlpha) {
377                                    nbits = new int[2];
378                                    if (trans == cm.BITMASK) {
379                                        nbits[1] = 1;
380                                    } else {
381                                        nbits[1] = 16;
382                                    }
383                                } else {
384                                    nbits = new int[1];
385                                }
386                                nbits[0] = 16;
387                            }
388                        }
389                        if (nbits != null) {
390                            cm = new ComponentColorModel(cm.getColorSpace(),
391                                    nbits, hasAlpha, isPre, trans, transferType);
392                        }
393                    }
394                    image = new BufferedImage(cm, cm
395                            .createCompatibleWritableRaster(w, h), cm
396                            .isAlphaPremultiplied(), null);
397                } else {
398                    image = new BufferedImage(destCM, destCM
399                            .createCompatibleWritableRaster(w, h), destCM
400                            .isAlphaPremultiplied(), null);
401                }
402
403                return image;
404            }
405
406            /**
407             * Creates a zeroed-destination <code>Raster</code> with the 
408             * correct size and number of bands, given this source.
409             * @param src the <code>Raster</code> to be transformed
410             * @return the zeroed-destination <code>Raster</code>.
411             */
412            public WritableRaster createCompatibleDestRaster(Raster src) {
413                return src.createCompatibleWritableRaster();
414            }
415
416            /**
417             * Returns the location of the destination point given a
418             * point in the source.  If <code>dstPt</code> is not 
419             * <code>null</code>, it will be used to hold the return value.  
420             * Since this is not a geometric operation, the <code>srcPt</code>
421             * will equal the <code>dstPt</code>.
422             * @param srcPt a <code>Point2D</code> that represents a point
423             *        in the source image
424             * @param dstPt a <code>Point2D</code>that represents the location
425             *        in the destination
426             * @return the <code>Point2D</code> in the destination that 
427             *         corresponds to the specified point in the source.
428             */
429            public final Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
430                if (dstPt == null) {
431                    dstPt = new Point2D.Float();
432                }
433                dstPt.setLocation(srcPt.getX(), srcPt.getY());
434
435                return dstPt;
436            }
437
438            /**
439             * Returns the rendering hints for this op.
440             * @return the <code>RenderingHints</code> object associated
441             *         with this op.
442             */
443            public final RenderingHints getRenderingHints() {
444                return hints;
445            }
446
447            private final void byteFilter(ByteLookupTable lookup, Raster src,
448                    WritableRaster dst, int width, int height, int numBands) {
449                int[] srcPix = null;
450
451                // Find the ref to the table and the offset
452                byte[][] table = lookup.getTable();
453                int offset = lookup.getOffset();
454                int tidx;
455                int step = 1;
456
457                // Check if it is one lookup applied to all bands
458                if (table.length == 1) {
459                    step = 0;
460                }
461
462                int x;
463                int y;
464                int band;
465                int len = table[0].length;
466
467                // Loop through the data
468                for (y = 0; y < height; y++) {
469                    tidx = 0;
470                    for (band = 0; band < numBands; band++, tidx += step) {
471                        // Find data for this band, scanline
472                        srcPix = src.getSamples(0, y, width, 1, band, srcPix);
473
474                        for (x = 0; x < width; x++) {
475                            int index = srcPix[x] - offset;
476                            if (index < 0 || index > len) {
477                                throw new IllegalArgumentException("index ("
478                                        + index + "(out of range: "
479                                        + " srcPix[" + x + "]=" + srcPix[x]
480                                        + " offset=" + offset);
481                            }
482                            // Do the lookup
483                            srcPix[x] = table[tidx][index];
484                        }
485                        // Put it back
486                        dst.setSamples(0, y, width, 1, band, srcPix);
487                    }
488                }
489            }
490
491            private final void shortFilter(ShortLookupTable lookup, Raster src,
492                    WritableRaster dst, int width, int height, int numBands) {
493                int band;
494                int[] srcPix = null;
495
496                // Find the ref to the table and the offset
497                short[][] table = lookup.getTable();
498                int offset = lookup.getOffset();
499                int tidx;
500                int step = 1;
501
502                // Check if it is one lookup applied to all bands
503                if (table.length == 1) {
504                    step = 0;
505                }
506
507                int x = 0;
508                int y = 0;
509                int index;
510                int maxShort = (1 << 16) - 1;
511                // Loop through the data
512                for (y = 0; y < height; y++) {
513                    tidx = 0;
514                    for (band = 0; band < numBands; band++, tidx += step) {
515                        // Find data for this band, scanline
516                        srcPix = src.getSamples(0, y, width, 1, band, srcPix);
517
518                        for (x = 0; x < width; x++) {
519                            index = srcPix[x] - offset;
520                            if (index < 0 || index > maxShort) {
521                                throw new IllegalArgumentException(
522                                        "index out of range " + index
523                                                + " x is " + x + "srcPix[x]="
524                                                + srcPix[x] + " offset="
525                                                + offset);
526                            }
527                            // Do the lookup
528                            srcPix[x] = table[tidx][index];
529                        }
530                        // Put it back
531                        dst.setSamples(0, y, width, 1, band, srcPix);
532                    }
533                }
534            }
535        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.