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


001:        /*
002:         * $Id: FunctionType0.java,v 1.3 2007/12/20 18:33:35 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.function;
023:
024:        import java.io.IOException;
025:        import java.nio.ByteBuffer;
026:
027:        import com.sun.pdfview.PDFObject;
028:        import com.sun.pdfview.PDFParseException;
029:
030:        /**
031:         * A sampled function maps input values to output values by interpolating
032:         * along a line or cubic between two known values.
033:         */
034:        public class FunctionType0 extends PDFFunction {
035:            /** the valid interpolation methods */
036:            protected static final int LINEAR_INTERPOLATION = 1;
037:            protected static final int CUBIC_INTERPOLATION = 3;
038:
039:            /** the size of each input dimension, as an array of <i>m</i> integers */
040:            private int[] size;
041:
042:            /** the number of bits in each sample */
043:            private int bitsPerSample;
044:
045:            /** the interpolation type, from the list above */
046:            private int order = 1;
047:
048:            /** the optional encoding array, tells how to map input parameters to values */
049:            private float[] encode;
050:
051:            /** the optional decoding array, tells how to map output parameters to values */
052:            private float[] decode;
053:
054:            /** 
055:             * the actual samples, converted to integers.  The first index is
056:             * input values (from 0 to size[m - 1] * size[m - 2] * ... * size[0]), 
057:             * and the second is the output dimension within the sample (from 0 to n)
058:             */
059:            private int[][] samples;
060:
061:            /** Creates a new instance of FunctionType0 */
062:            protected FunctionType0() {
063:                super (TYPE_0);
064:            }
065:
066:            /** Read the function information from a PDF Object */
067:            protected void parse(PDFObject obj) throws IOException {
068:                // read the size array (required)
069:                PDFObject sizeObj = obj.getDictRef("Size");
070:                if (sizeObj == null) {
071:                    throw new PDFParseException(
072:                            "Size required for function type 0!");
073:                }
074:                PDFObject[] sizeAry = sizeObj.getArray();
075:                int[] size = new int[sizeAry.length];
076:                for (int i = 0; i < sizeAry.length; i++) {
077:                    size[i] = sizeAry[i].getIntValue();
078:                }
079:                setSize(size);
080:
081:                // read the # bits per sample (required)
082:                PDFObject bpsObj = obj.getDictRef("BitsPerSample");
083:                if (bpsObj == null) {
084:                    throw new PDFParseException(
085:                            "BitsPerSample required for function type 0!");
086:                }
087:                setBitsPerSample(bpsObj.getIntValue());
088:
089:                // read the order (optional)
090:                PDFObject orderObj = obj.getDictRef("Order");
091:                if (orderObj != null) {
092:                    setOrder(orderObj.getIntValue());
093:                }
094:
095:                // read the encode array (optional)
096:                PDFObject encodeObj = obj.getDictRef("Encode");
097:                if (encodeObj != null) {
098:                    PDFObject[] encodeAry = encodeObj.getArray();
099:                    float[] encode = new float[encodeAry.length];
100:                    for (int i = 0; i < encodeAry.length; i++) {
101:                        encode[i] = encodeAry[i].getFloatValue();
102:                    }
103:                    setEncode(encode);
104:                }
105:
106:                // read the decode array (optional)
107:                PDFObject decodeObj = obj.getDictRef("Decode");
108:                if (decodeObj != null) {
109:                    PDFObject[] decodeAry = decodeObj.getArray();
110:                    float[] decode = new float[decodeAry.length];
111:                    for (int i = 0; i < decodeAry.length; i++) {
112:                        decode[i] = decodeAry[i].getFloatValue();
113:                    }
114:                    setDecode(decode);
115:                }
116:
117:                // finally, read the samples
118:                setSamples(readSamples(obj.getStreamBuffer()));
119:            }
120:
121:            /**
122:             * Map from <i>m</i> input values to <i>n</i> output values.
123:             * The number of inputs <i>m</i> must be exactly one half the size of the
124:             * domain.  The number of outputs should match one half the size of the
125:             * range.
126:             *
127:             * @param inputs an array of <i>m</i> input values
128:             * @param outputs an array of size <i>n</i> which will be filled
129:             *                with the output values, or null to return a new array
130:             */
131:            protected void doFunction(float[] inputs, int inputOffset,
132:                    float[] outputs, int outputOffset) {
133:                // calculate the encoded values for each input
134:                float[] encoded = new float[getNumInputs()];
135:                for (int i = 0; i < getNumInputs(); i++) {
136:                    // encode -- interpolate(x<i>, domain<2i>, domain<2i + 1>,
137:                    //                       encode<2i>, encode<2i + 1>)
138:                    encoded[i] = interpolate(inputs[i + inputOffset],
139:                            getDomain(2 * i), getDomain((2 * i) + 1),
140:                            getEncode(2 * i), getEncode((2 * i) + 1));
141:
142:                    // clip to size of sample table -- min(max(e<i>, 0), size<i> - 1)
143:                    encoded[i] = Math.max(encoded[i], 0);
144:                    encoded[i] = Math.min(encoded[i], size[i] - 1);
145:                }
146:
147:                // do some magic
148:                for (int i = 0; i < getNumOutputs(); i++) {
149:                    if (getOrder() == 1) {
150:                        outputs[i + outputOffset] = multilinearInterpolate(
151:                                encoded, i);
152:                    } else {
153:                        outputs[i + outputOffset] = multicubicInterpolate(
154:                                encoded, i);
155:                    }
156:                }
157:
158:                // now adjust the output to be within range
159:                for (int i = 0; i < outputs.length; i++) {
160:                    // decode -- interpolate(r<i>, 0, 2^bps - 1, 
161:                    //                       decode<2i>, decode<2i + 1>)
162:                    outputs[i + outputOffset] = interpolate(outputs[i
163:                            + outputOffset], 0, (float) Math.pow(2,
164:                            getBitsPerSample()) - 1, getDecode(2 * i),
165:                            getDecode((2 * i) + 1));
166:                }
167:            }
168:
169:            /**
170:             * Get the size of a given input dimension
171:             *
172:             * @param dimension the input dimension to get the size of
173:             * @return the number of samples in the given dimension
174:             */
175:            protected int getSize(int dimension) {
176:                return size[dimension];
177:            }
178:
179:            /** 
180:             * Set the size of all input dimensions
181:             */
182:            protected void setSize(int[] size) {
183:                this .size = size;
184:            }
185:
186:            /** 
187:             * Get the number of bits per sample
188:             */
189:            protected int getBitsPerSample() {
190:                return bitsPerSample;
191:            }
192:
193:            /**
194:             * Set the number of bits per sample
195:             */
196:            protected void setBitsPerSample(int bits) {
197:                this .bitsPerSample = bits;
198:            }
199:
200:            /**
201:             * Get the interpolation type
202:             */
203:            protected int getOrder() {
204:                return order;
205:            }
206:
207:            /**
208:             * Set the interpolation type
209:             */
210:            protected void setOrder(int order) {
211:                this .order = order;
212:            }
213:
214:            /**
215:             * Get the encoding for a particular input parameter
216:             *
217:             * @param i the index into the encoding array, which has size 2 * <i>m</i>.
218:             *          the <i>i</i>th entry in the array has index 2<i>i</i>, 
219:             *           2<i>i</i> + 1
220:             * @return the encoding value if the encoding array is set, or the default 
221:             */
222:            protected float getEncode(int i) {
223:                if (encode != null) {
224:                    return encode[i];
225:                } else if ((i % 2) == 0) {
226:                    return 0f;
227:                } else {
228:                    return (getSize(i / 2) - 1);
229:                }
230:            }
231:
232:            /**
233:             * Set the encode array
234:             */
235:            protected void setEncode(float[] encode) {
236:                this .encode = encode;
237:            }
238:
239:            /**
240:             * Get the decoding for a particular input parameter
241:             *
242:             * @param i the index into the decoding array, which has size 2 * <i>n</i>.
243:             *          the <i>i</i>th entry in the array has index 2<i>i</i>, 
244:             *           2<i>i</i> + 1
245:             * @return the decoding value if the decoding array is set, or the default 
246:             */
247:            protected float getDecode(int i) {
248:                if (decode != null) {
249:                    return decode[i];
250:                } else {
251:                    return getRange(i);
252:                }
253:            }
254:
255:            /**
256:             * Set the decode array
257:             */
258:            protected void setDecode(float[] decode) {
259:                this .decode = decode;
260:            }
261:
262:            /**
263:             * Get a component for a sample given <i>m</i> indices and output
264:             * dimension. 
265:             *
266:             * @param values an array of <i>m</i> values determining which sample
267:             *               to select
268:             * @param od the output dimension (0 - <i>n</i>) to get the sample in
269:             * @return the sample for the given values and index
270:             */
271:            protected int getSample(int[] values, int od) {
272:                int mult = 1;
273:                int index = 0;
274:                for (int i = 0; i < values.length; i++) {
275:                    index += mult * values[i];
276:                    mult *= getSize(i);
277:                }
278:
279:                return samples[index][od];
280:            }
281:
282:            /**
283:             * Set the table of samples
284:             */
285:            protected void setSamples(int[][] samples) {
286:                this .samples = samples;
287:            }
288:
289:            /**
290:             * Read the samples from the input stream.  Each sample is made up
291:             * of <i>n</i> components, each of which has length <i>bitsPerSample</i>
292:             * bits.  The samples are arranged by dimension, then range
293:             */
294:            private int[][] readSamples(ByteBuffer buf) {
295:                // calculate the number of samples in the table
296:                int size = 1;
297:                for (int i = 0; i < getNumInputs(); i++) {
298:                    size *= getSize(i);
299:                }
300:
301:                // create the samples table
302:                int[][] samples = new int[size][getNumOutputs()];
303:
304:                // the current location in the buffer, in bits from byteLoc
305:                int bitLoc = 0;
306:
307:                // the current location in the buffer, in bytes
308:                int byteLoc = 0;
309:
310:                // the current index in the samples array
311:                int index = 0;
312:
313:                for (int i = 0; i < getNumInputs(); i++) {
314:                    for (int j = 0; j < getSize(i); j++) {
315:                        for (int k = 0; k < getNumOutputs(); k++) {
316:                            /** [JK FIXME one bit at a time is really inefficient */
317:                            int value = 0;
318:
319:                            int toRead = getBitsPerSample();
320:                            byte curByte = buf.get(byteLoc);
321:
322:                            while (toRead > 0) {
323:                                int nextBit = ((curByte >> (7 - bitLoc)) & 0x1);
324:                                value |= nextBit << (toRead - 1);
325:
326:                                if (++bitLoc == 8) {
327:                                    bitLoc = 0;
328:                                    byteLoc++;
329:
330:                                    if (toRead > 1) {
331:                                        curByte = buf.get(byteLoc);
332:                                    }
333:                                }
334:
335:                                toRead--;
336:                            }
337:
338:                            samples[index][k] = value;
339:                        }
340:
341:                        index++;
342:                    }
343:                }
344:
345:                return samples;
346:            }
347:
348:            /**
349:             * Perform a piecewise multilinear interpolation.  The provides a
350:             * close approximation to the standard linear interpolation, at
351:             * a far lower cost, since every element is not evaluated at every
352:             * iteration.  Instead, a walk of the most significant axes is performed,
353:             * following the algorithm desribed at:
354:             *     http://osl.iu.edu/~tveldhui/papers/MAScThesis/node33.html
355:             *
356:             * @param encoded the encoded input values
357:             * @param od the output dimension
358:             */
359:            private float multilinearInterpolate(float[] encoded, int od) {
360:                // first calculate the distances -- the differences between
361:                // each encoded value and the integer below it.
362:                float[] dists = new float[encoded.length];
363:
364:                for (int i = 0; i < dists.length; i++) {
365:                    dists[i] = (float) (encoded[i] - Math.floor(encoded[i]));
366:                }
367:
368:                // initialize the map of axes.  Each bit in this map represents
369:                // whether the control value in that dimension should be the integer
370:                // above or below encoded[i]
371:                int map = 0;
372:
373:                // the initial values
374:                float val = getSample(encoded, map, od);
375:                float prev = val;
376:
377:                // walk the axes
378:                for (int i = 0; i < dists.length; i++) {
379:                    // find the largest value of dist remaining
380:                    int idx = 0;
381:                    float largest = -1;
382:                    for (int c = 0; c < dists.length; c++) {
383:                        if (dists[c] > largest) {
384:                            largest = dists[c];
385:                            idx = c;
386:                        }
387:                    }
388:
389:                    // now find the sample with that axis set to 1
390:                    map |= (0x1 << idx);
391:                    float cur = getSample(encoded, map, od);
392:
393:                    // calculate the value and remember it
394:                    val += dists[idx] * (cur - prev);
395:                    prev = val;
396:
397:                    // make sure we won't find this distance again
398:                    dists[idx] = -1;
399:                }
400:
401:                // voila
402:                return val;
403:            }
404:
405:            /**
406:             * Perform a multicubic interpolation
407:             *
408:             * @param encoded the encoded input values
409:             * @param od the output dimension
410:             */
411:            private float multicubicInterpolate(float[] encoded, int od) {
412:                System.out.println("Cubic interpolation not supported!");
413:                return multilinearInterpolate(encoded, od);
414:            }
415:
416:            /**
417:             * Perform a linear interpolation.  Given a value x, and two points,
418:             * (xmin, ymin), (xmax, ymax), where xmin <= x <= xmax, calculate a value
419:             * y on the line from (xmin, ymin) to (xmax, ymax).
420:             *
421:             * @param x the x value of the input
422:             * @param xmin the minimum x value
423:             * @param ymin the minimum y value
424:             * @param xmax the maximum x value
425:             * @param ymax the maximum y value
426:             * @return the y value interpolated from the given x
427:             */
428:            public static float interpolate(float x, float xmin, float xmax,
429:                    float ymin, float ymax) {
430:                float value = (ymax - ymin) / (xmax - xmin);
431:                value *= x - xmin;
432:                value += ymin;
433:
434:                return value;
435:            }
436:
437:            /**
438:             * Get a sample based on an array of encoded values and a control
439:             * map.  For each bit in the map, if that bit is 0 the integer below 
440:             * the encoded value is selected, or if the bit is 1, the interger
441:             * above is selected.
442:             * 
443:             * @param encoded the encoded values
444:             * @param map the bit map of control values
445:             * @param od the output dimension to read the sample for
446:             */
447:            private float getSample(float[] encoded, int map, int od) {
448:                int[] controls = new int[encoded.length];
449:
450:                // fill in the controls array with appropriate ints
451:                for (int i = 0; i < controls.length; i++) {
452:                    if ((map & (0x1 << i)) == 0) {
453:                        controls[i] = (int) Math.floor(encoded[i]);
454:                    } else {
455:                        controls[i] = (int) Math.ceil(encoded[i]);
456:                    }
457:                }
458:
459:                // now return the actual sample
460:                return getSample(controls, od);
461:            }
462:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.