Source Code Cross Referenced for PDFImage.java in  » PDF » PDF-Renderer » com » sun » pdfview » 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 » PDF » PDF Renderer » com.sun.pdfview 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: PDFImage.java,v 1.2 2007/12/20 18:17:41 rbair Exp $
003:         *
004:         * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005:         * Santa Clara, California 95054, U.S.A. All rights reserved.
006:         *
007:         * This library is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU Lesser General Public
009:         * License as published by the Free Software Foundation; either
010:         * version 2.1 of the License, or (at your option) any later version.
011:         * 
012:         * This library is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         * Lesser General Public License for more details.
016:         * 
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this library; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020:         */
021:
022:        package com.sun.pdfview;
023:
024:        import java.awt.Color;
025:        import java.awt.Point;
026:        import java.awt.Transparency;
027:        import java.awt.color.ColorSpace;
028:        import java.awt.color.ICC_ColorSpace;
029:        import java.awt.image.BufferedImage;
030:        import java.awt.image.ColorConvertOp;
031:        import java.awt.image.ColorModel;
032:        import java.awt.image.ComponentColorModel;
033:        import java.awt.image.DataBuffer;
034:        import java.awt.image.DataBufferByte;
035:        import java.awt.image.IndexColorModel;
036:        import java.awt.image.MultiPixelPackedSampleModel;
037:        import java.awt.image.Raster;
038:        import java.awt.image.SampleModel;
039:        import java.awt.image.WritableRaster;
040:        import java.io.IOException;
041:        import java.util.Map;
042:
043:        import com.sun.pdfview.colorspace.IndexedColor;
044:        import com.sun.pdfview.colorspace.PDFColorSpace;
045:        import com.sun.pdfview.function.FunctionType0;
046:
047:        /**
048:         * Encapsulates a PDF Image
049:         */
050:        public class PDFImage {
051:            /** the width of this image in pixels */
052:            private int width;
053:
054:            /** the height of this image in pixels */
055:            private int height;
056:
057:            /** the colorspace to interpret the samples in */
058:            private PDFColorSpace colorSpace;
059:
060:            /** the number of bits per sample component */
061:            private int bpc;
062:
063:            /** whether this image is a mask or not */
064:            private boolean imageMask = false;
065:
066:            /** the SMask image, if any */
067:            private PDFImage sMask;
068:
069:            /** the decode array */
070:            private float[] decode;
071:
072:            /** the actual image data */
073:            private PDFObject imageObj;
074:
075:            /** 
076:             * Create an instance of a PDFImage
077:             */
078:            protected PDFImage(PDFObject imageObj) {
079:                this .imageObj = imageObj;
080:            }
081:
082:            /**
083:             * Read a PDFImage from an image dictionary and stream
084:             *
085:             * @param obj the PDFObject containing the image's dictionary and stream
086:             * @param resources the current resources
087:             */
088:            public static PDFImage createImage(PDFObject obj, Map resources)
089:                    throws IOException {
090:                // create the image
091:                PDFImage image = new PDFImage(obj);
092:
093:                // get the width (required)
094:                PDFObject widthObj = obj.getDictRef("Width");
095:                if (widthObj == null) {
096:                    throw new PDFParseException("Unable to read image width: "
097:                            + obj);
098:                }
099:                image.setWidth(widthObj.getIntValue());
100:
101:                // get the height (required)
102:                PDFObject heightObj = obj.getDictRef("Height");
103:                if (heightObj == null) {
104:                    throw new PDFParseException("Unable to get image height: "
105:                            + obj);
106:                }
107:                image.setHeight(heightObj.getIntValue());
108:
109:                // figure out if we are an image mask (optional)
110:                PDFObject imageMaskObj = obj.getDictRef("ImageMask");
111:                if (imageMaskObj != null) {
112:                    image.setImageMask(imageMaskObj.getBooleanValue());
113:                }
114:
115:                // read the bpc and colorspace (required except for masks) 
116:                if (image.isImageMask()) {
117:                    image.setBitsPerComponent(1);
118:
119:                    // create the indexed color space for the mask
120:                    Color[] colors = { Color.WHITE, Color.BLACK };
121:                    image.setColorSpace(new IndexedColor(colors));
122:                } else {
123:                    // get the bits per component (required)
124:                    PDFObject bpcObj = obj.getDictRef("BitsPerComponent");
125:                    if (bpcObj == null) {
126:                        throw new PDFParseException(
127:                                "Unable to get bits per component: " + obj);
128:                    }
129:                    image.setBitsPerComponent(bpcObj.getIntValue());
130:
131:                    // get the color space (required)
132:                    PDFObject csObj = obj.getDictRef("ColorSpace");
133:                    if (csObj == null) {
134:                        throw new PDFParseException("No ColorSpace for image: "
135:                                + obj);
136:                    }
137:
138:                    PDFColorSpace cs = PDFColorSpace.getColorSpace(csObj,
139:                            resources);
140:                    image.setColorSpace(cs);
141:                }
142:
143:                // read the decode array
144:                PDFObject decodeObj = obj.getDictRef("Decode");
145:                if (decodeObj != null) {
146:                    PDFObject[] decodeArray = decodeObj.getArray();
147:
148:                    float[] decode = new float[decodeArray.length];
149:                    for (int i = 0; i < decodeArray.length; i++) {
150:                        decode[i] = decodeArray[i].getFloatValue();
151:                    }
152:
153:                    image.setDecode(decode);
154:                }
155:
156:                // read the soft mask
157:                PDFObject sMaskObj = obj.getDictRef("SMask");
158:                if (sMaskObj == null) {
159:                    // try the explicit mask, if there is no SoftMask
160:                    sMaskObj = obj.getDictRef("Mask");
161:                }
162:
163:                if (sMaskObj != null) {
164:                    PDFImage sMaskImage = PDFImage.createImage(sMaskObj,
165:                            resources);
166:                    image.setSMask(sMaskImage);
167:                }
168:
169:                return image;
170:            }
171:
172:            /**
173:             * Get the image that this PDFImage generates.
174:             *
175:             * @return a buffered image containing the decoded image data
176:             */
177:            public BufferedImage getImage() {
178:                try {
179:                    BufferedImage bi = (BufferedImage) imageObj.getCache();
180:
181:                    if (bi == null) {
182:                        // parse the stream data into an actual image
183:                        bi = parseData(imageObj.getStream());
184:                        imageObj.setCache(bi);
185:                    }
186:
187:                    return bi;
188:                } catch (IOException ioe) {
189:                    System.out.println("Error reading image");
190:                    ioe.printStackTrace();
191:                    return null;
192:                }
193:            }
194:
195:            /**
196:             * Parse the image stream into a buffered image.  Note that this is
197:             * guaranteed to be called after all the other setXXX methods have been 
198:             * called.
199:             */
200:            protected BufferedImage parseData(byte[] data) {
201:                // create the data buffer
202:                DataBuffer db = new DataBufferByte(data, data.length);
203:
204:                // pick a color model, based on the number of components and
205:                // bits per component
206:                ColorModel cm = getColorModel();
207:
208:                // create a compatible raster
209:                SampleModel sm = cm.createCompatibleSampleModel(getWidth(),
210:                        getHeight());
211:                WritableRaster raster = Raster.createWritableRaster(sm, db,
212:                        new Point(0, 0));
213:
214:                /* 
215:                 * Workaround for a bug on the Mac -- a class cast exception in
216:                 * drawImage() due to the wrong data buffer type (?)
217:                 */
218:                BufferedImage bi = null;
219:                if (cm instanceof  IndexColorModel) {
220:                    IndexColorModel icm = (IndexColorModel) cm;
221:
222:                    // choose the image type based on the size
223:                    int type = BufferedImage.TYPE_BYTE_BINARY;
224:                    if (getBitsPerComponent() == 8) {
225:                        type = BufferedImage.TYPE_BYTE_INDEXED;
226:                    }
227:
228:                    // create the image with an explicit indexed color model.
229:                    bi = new BufferedImage(getWidth(), getHeight(), type, icm);
230:
231:                    // set the data explicitly as well
232:                    bi.setData(raster);
233:                } else {
234:                    bi = new BufferedImage(cm, raster, true, null);
235:                }
236:
237:                // hack to avoid *very* slow conversion
238:                ColorSpace cs = cm.getColorSpace();
239:                ColorSpace rgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB);
240:                if (!isImageMask() && cs instanceof  ICC_ColorSpace
241:                        && !cs.equals(rgbCS)) {
242:                    ColorConvertOp op = new ColorConvertOp(cs, rgbCS, null);
243:
244:                    BufferedImage converted = new BufferedImage(getWidth(),
245:                            getHeight(), BufferedImage.TYPE_INT_ARGB);
246:
247:                    bi = op.filter(bi, converted);
248:                }
249:
250:                // add in the alpha data supplied by the SMask, if any
251:                PDFImage sMaskImage = getSMask();
252:                if (sMaskImage != null) {
253:                    BufferedImage si = sMaskImage.getImage();
254:
255:                    BufferedImage outImage = new BufferedImage(getWidth(),
256:                            getHeight(), BufferedImage.TYPE_INT_ARGB);
257:
258:                    int[] srcArray = new int[width];
259:                    int[] maskArray = new int[width];
260:
261:                    for (int i = 0; i < height; i++) {
262:                        bi.getRGB(0, i, width, 1, srcArray, 0, width);
263:                        si.getRGB(0, i, width, 1, maskArray, 0, width);
264:
265:                        for (int j = 0; j < width; j++) {
266:                            int ac = 0xff000000;
267:
268:                            maskArray[j] = ((maskArray[j] & 0xff) << 24)
269:                                    | (srcArray[j] & ~ac);
270:                        }
271:
272:                        outImage.setRGB(0, i, width, 1, maskArray, 0, width);
273:                    }
274:
275:                    bi = outImage;
276:                }
277:
278:                return (bi);
279:            }
280:
281:            /**
282:             * Get the image's width
283:             */
284:            public int getWidth() {
285:                return width;
286:            }
287:
288:            /**
289:             * Set the image's width
290:             */
291:            protected void setWidth(int width) {
292:                this .width = width;
293:            }
294:
295:            /**
296:             * Get the image's height
297:             */
298:            public int getHeight() {
299:                return height;
300:            }
301:
302:            /**
303:             * Set the image's height
304:             */
305:            protected void setHeight(int height) {
306:                this .height = height;
307:            }
308:
309:            /**
310:             * Get the colorspace associated with this image, or null if there
311:             * isn't one
312:             */
313:            protected PDFColorSpace getColorSpace() {
314:                return colorSpace;
315:            }
316:
317:            /**
318:             * Set the colorspace associated with this image
319:             */
320:            protected void setColorSpace(PDFColorSpace colorSpace) {
321:                this .colorSpace = colorSpace;
322:            }
323:
324:            /**
325:             * Get the number of bits per component sample
326:             */
327:            protected int getBitsPerComponent() {
328:                return bpc;
329:            }
330:
331:            /**
332:             * Set the number of bits per component sample
333:             */
334:            protected void setBitsPerComponent(int bpc) {
335:                this .bpc = bpc;
336:            }
337:
338:            /**
339:             * Return whether or not this is an image mask
340:             */
341:            public boolean isImageMask() {
342:                return imageMask;
343:            }
344:
345:            /**
346:             * Set whether or not this is an image mask
347:             */
348:            public void setImageMask(boolean imageMask) {
349:                this .imageMask = imageMask;
350:            }
351:
352:            /** 
353:             * Return the soft mask associated with this image
354:             */
355:            public PDFImage getSMask() {
356:                return sMask;
357:            }
358:
359:            /**
360:             * Set the soft mask image
361:             */
362:            protected void setSMask(PDFImage sMask) {
363:                this .sMask = sMask;
364:            }
365:
366:            /**
367:             * Get the decode array
368:             */
369:            protected float[] getDecode() {
370:                return decode;
371:            }
372:
373:            /**
374:             * Set the decode array
375:             */
376:            protected void setDecode(float[] decode) {
377:                this .decode = decode;
378:            }
379:
380:            /**
381:             * get a Java ColorModel consistent with the current color space,
382:             * number of bits per component and decode array
383:             * 
384:             * @param bpc the number of bits per component
385:             */
386:            private ColorModel getColorModel() {
387:                PDFColorSpace cs = getColorSpace();
388:
389:                if (cs instanceof  IndexedColor) {
390:                    IndexedColor ics = (IndexedColor) cs;
391:
392:                    byte[] components = ics.getColorComponents();
393:                    int num = ics.getCount();
394:
395:                    // process the decode array
396:                    if (decode != null) {
397:                        byte[] normComps = new byte[components.length];
398:
399:                        // move the components array around
400:                        for (int i = 0; i < num; i++) {
401:                            byte[] orig = new byte[1];
402:                            orig[0] = (byte) i;
403:
404:                            float[] res = normalize(orig, null, 0);
405:                            int idx = (int) res[0];
406:
407:                            normComps[i * 3] = components[idx * 3];
408:                            normComps[(i * 3) + 1] = components[(idx * 3) + 1];
409:                            normComps[(i * 3) + 2] = components[(idx * 3) + 2];
410:                        }
411:
412:                        components = normComps;
413:                    }
414:
415:                    // make sure the size of the components array is 2 ^ numBits
416:                    // since if it's not, Java will complain
417:                    int correctCount = 1 << getBitsPerComponent();
418:                    if (correctCount < num) {
419:                        byte[] fewerComps = new byte[correctCount * 3];
420:
421:                        System.arraycopy(components, 0, fewerComps, 0,
422:                                correctCount * 3);
423:
424:                        components = fewerComps;
425:                        num = correctCount;
426:                    }
427:
428:                    return new IndexColorModel(getBitsPerComponent(), num,
429:                            components, 0, false);
430:                } else {
431:                    int[] bits = new int[cs.getNumComponents()];
432:                    for (int i = 0; i < bits.length; i++) {
433:                        bits[i] = getBitsPerComponent();
434:                    }
435:
436:                    return new DecodeComponentColorModel(cs.getColorSpace(),
437:                            bits);
438:                }
439:            }
440:
441:            /**
442:             * Normalize an array of values to match the decode array
443:             */
444:            private float[] normalize(byte[] pixels, float[] normComponents,
445:                    int normOffset) {
446:                if (normComponents == null) {
447:                    normComponents = new float[normOffset + pixels.length];
448:                }
449:
450:                float[] decodeArray = getDecode();
451:
452:                for (int i = 0; i < pixels.length; i++) {
453:                    int val = pixels[i] & 0xff;
454:                    int pow = ((int) Math.pow(2, getBitsPerComponent())) - 1;
455:                    float ymin = decodeArray[i * 2];
456:                    float ymax = decodeArray[(i * 2) + 1];
457:
458:                    normComponents[normOffset + i] = FunctionType0.interpolate(
459:                            val, 0, pow, ymin, ymax);
460:                }
461:
462:                return normComponents;
463:            }
464:
465:            /**
466:             * A wrapper for ComponentColorSpace which normalizes based on the 
467:             * decode array.
468:             */
469:            class DecodeComponentColorModel extends ComponentColorModel {
470:                public DecodeComponentColorModel(ColorSpace cs, int[] bpc) {
471:                    super (cs, bpc, false, false, Transparency.OPAQUE,
472:                            DataBuffer.TYPE_BYTE);
473:
474:                    if (bpc != null) {
475:                        pixel_bits = bpc.length * bpc[0];
476:                    }
477:                }
478:
479:                @Override
480:                public SampleModel createCompatibleSampleModel(int width,
481:                        int height) {
482:                    // workaround -- create a MultiPixelPackedSample models for 
483:                    // single-sample, less than 8bpp color models
484:                    if (getNumComponents() == 1 && getPixelSize() < 8) {
485:                        return new MultiPixelPackedSampleModel(
486:                                getTransferType(), width, height,
487:                                getPixelSize());
488:                    }
489:
490:                    return super .createCompatibleSampleModel(width, height);
491:                }
492:
493:                @Override
494:                public boolean isCompatibleRaster(Raster raster) {
495:                    if (getNumComponents() == 1 && getPixelSize() < 8) {
496:                        SampleModel sm = raster.getSampleModel();
497:
498:                        if (sm instanceof  MultiPixelPackedSampleModel) {
499:                            return (sm.getSampleSize(0) == getPixelSize());
500:                        } else {
501:                            return false;
502:                        }
503:                    }
504:
505:                    return super .isCompatibleRaster(raster);
506:                }
507:
508:                @Override
509:                public float[] getNormalizedComponents(Object pixel,
510:                        float[] normComponents, int normOffset) {
511:                    if (getDecode() == null) {
512:                        return super .getNormalizedComponents(pixel,
513:                                normComponents, normOffset);
514:                    }
515:
516:                    return normalize((byte[]) pixel, normComponents, normOffset);
517:                }
518:            }
519:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.