Source Code Cross Referenced for PngEncoder.java in  » Graphic-Library » jcommon-components » com » keypoint » 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 » Graphic Library » jcommon components » com.keypoint 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.keypoint;
002:
003:        import java.awt.Image;
004:        import java.awt.image.ImageObserver;
005:        import java.awt.image.PixelGrabber;
006:        import java.io.ByteArrayOutputStream;
007:        import java.io.IOException;
008:        import java.util.zip.CRC32;
009:        import java.util.zip.Deflater;
010:        import java.util.zip.DeflaterOutputStream;
011:
012:        /**
013:         * PngEncoder takes a Java Image object and creates a byte string which can be 
014:         * saved as a PNG file.  The Image is presumed to use the DirectColorModel.
015:         *
016:         * <p>Thanks to Jay Denny at KeyPoint Software
017:         *    http://www.keypoint.com/
018:         * who let me develop this code on company time.</p>
019:         *
020:         * <p>You may contact me with (probably very-much-needed) improvements,
021:         * comments, and bug fixes at:</p>
022:         *
023:         *   <p><code>david@catcode.com</code></p>
024:         *
025:         * <p>This library is free software; you can redistribute it and/or
026:         * modify it under the terms of the GNU Lesser General Public
027:         * License as published by the Free Software Foundation; either
028:         * version 2.1 of the License, or (at your option) any later version.</p>
029:         *
030:         * <p>This library is distributed in the hope that it will be useful,
031:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
032:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
033:         * Lesser General Public License for more details.</p>
034:         *
035:         * <p>You should have received a copy of the GNU Lesser General Public
036:         * License along with this library; if not, write to the Free Software
037:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
038:         * USA. A copy of the GNU LGPL may be found at
039:         * <code>http://www.gnu.org/copyleft/lesser.html</code></p>
040:         *
041:         * @author J. David Eisenberg
042:         * @version 1.5, 19 Oct 2003
043:         *
044:         * CHANGES:
045:         * --------
046:         * 19-Nov-2002 : CODING STYLE CHANGES ONLY (by David Gilbert for Object 
047:         *               Refinery Limited);
048:         * 19-Sep-2003 : Fix for platforms using EBCDIC (contributed by Paulo Soares);
049:         * 19-Oct-2003 : Change private fields to protected fields so that
050:         *               PngEncoderB can inherit them (JDE)
051:         *               Fixed bug with calculation of nRows
052:         */
053:
054:        public class PngEncoder {
055:
056:            /** Constant specifying that alpha channel should be encoded. */
057:            public static final boolean ENCODE_ALPHA = true;
058:
059:            /** Constant specifying that alpha channel should not be encoded. */
060:            public static final boolean NO_ALPHA = false;
061:
062:            /** Constants for filter (NONE). */
063:            public static final int FILTER_NONE = 0;
064:
065:            /** Constants for filter (SUB). */
066:            public static final int FILTER_SUB = 1;
067:
068:            /** Constants for filter (UP). */
069:            public static final int FILTER_UP = 2;
070:
071:            /** Constants for filter (LAST). */
072:            public static final int FILTER_LAST = 2;
073:
074:            /** IHDR tag. */
075:            protected static final byte[] IHDR = { 73, 72, 68, 82 };
076:
077:            /** IDAT tag. */
078:            protected static final byte[] IDAT = { 73, 68, 65, 84 };
079:
080:            /** IEND tag. */
081:            protected static final byte[] IEND = { 73, 69, 78, 68 };
082:
083:            protected static final byte[] PHYS = { (byte) 'p', (byte) 'H',
084:                    (byte) 'Y', (byte) 's' };
085:
086:            /** The png bytes. */
087:            protected byte[] pngBytes;
088:
089:            /** The prior row. */
090:            protected byte[] priorRow;
091:
092:            /** The left bytes. */
093:            protected byte[] leftBytes;
094:
095:            /** The image. */
096:            protected Image image;
097:
098:            /** The width. */
099:            protected int width;
100:
101:            /** The height. */
102:            protected int height;
103:
104:            /** The byte position. */
105:            protected int bytePos;
106:
107:            /** The maximum position. */
108:            protected int maxPos;
109:
110:            /** CRC. */
111:            protected CRC32 crc = new CRC32();
112:
113:            /** The CRC value. */
114:            protected long crcValue;
115:
116:            /** Encode alpha? */
117:            protected boolean encodeAlpha;
118:
119:            /** The filter type. */
120:            protected int filter;
121:
122:            /** The bytes-per-pixel. */
123:            protected int bytesPerPixel;
124:
125:            /** The physical pixel dimension : number of pixels per inch on the X axis. */
126:            private int xDpi = 0;
127:
128:            /** The physical pixel dimension : number of pixels per inch on the Y axis. */
129:            private int yDpi = 0;
130:
131:            /** Used for conversion of DPI to Pixels per Meter. */
132:            static private float INCH_IN_METER_UNIT = 0.0254f;
133:
134:            /** 
135:             * The compression level (1 = best speed, 9 = best compression, 
136:             * 0 = no compression). 
137:             */
138:            protected int compressionLevel;
139:
140:            /**
141:             * Class constructor.
142:             */
143:            public PngEncoder() {
144:                this (null, false, FILTER_NONE, 0);
145:            }
146:
147:            /**
148:             * Class constructor specifying Image to encode, with no alpha channel 
149:             * encoding.
150:             *
151:             * @param image A Java Image object which uses the DirectColorModel
152:             * @see java.awt.Image
153:             */
154:            public PngEncoder(Image image) {
155:                this (image, false, FILTER_NONE, 0);
156:            }
157:
158:            /**
159:             * Class constructor specifying Image to encode, and whether to encode 
160:             * alpha.
161:             *
162:             * @param image A Java Image object which uses the DirectColorModel
163:             * @param encodeAlpha Encode the alpha channel? false=no; true=yes
164:             * @see java.awt.Image
165:             */
166:            public PngEncoder(Image image, boolean encodeAlpha) {
167:                this (image, encodeAlpha, FILTER_NONE, 0);
168:            }
169:
170:            /**
171:             * Class constructor specifying Image to encode, whether to encode alpha, 
172:             * and filter to use.
173:             *
174:             * @param image A Java Image object which uses the DirectColorModel
175:             * @param encodeAlpha Encode the alpha channel? false=no; true=yes
176:             * @param whichFilter 0=none, 1=sub, 2=up
177:             * @see java.awt.Image
178:             */
179:            public PngEncoder(Image image, boolean encodeAlpha, int whichFilter) {
180:                this (image, encodeAlpha, whichFilter, 0);
181:            }
182:
183:            /**
184:             * Class constructor specifying Image source to encode, whether to encode 
185:             * alpha, filter to use, and compression level.
186:             *
187:             * @param image A Java Image object
188:             * @param encodeAlpha Encode the alpha channel? false=no; true=yes
189:             * @param whichFilter 0=none, 1=sub, 2=up
190:             * @param compLevel 0..9 (1 = best speed, 9 = best compression, 0 = no 
191:             *        compression)
192:             * @see java.awt.Image
193:             */
194:            public PngEncoder(Image image, boolean encodeAlpha,
195:                    int whichFilter, int compLevel) {
196:                this .image = image;
197:                this .encodeAlpha = encodeAlpha;
198:                setFilter(whichFilter);
199:                if (compLevel >= 0 && compLevel <= 9) {
200:                    this .compressionLevel = compLevel;
201:                }
202:            }
203:
204:            /**
205:             * Set the image to be encoded.
206:             *
207:             * @param image A Java Image object which uses the DirectColorModel
208:             * @see java.awt.Image
209:             * @see java.awt.image.DirectColorModel
210:             */
211:            public void setImage(Image image) {
212:                this .image = image;
213:                this .pngBytes = null;
214:            }
215:
216:            /**
217:             * Returns the image to be encoded.
218:             */
219:            public Image getImage() {
220:                return image;
221:            }
222:
223:            /**
224:             * Creates an array of bytes that is the PNG equivalent of the current 
225:             * image, specifying whether to encode alpha or not.
226:             *
227:             * @param encodeAlpha boolean false=no alpha, true=encode alpha
228:             * @return an array of bytes, or null if there was a problem
229:             */
230:            public byte[] pngEncode(boolean encodeAlpha) {
231:                byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 };
232:
233:                if (this .image == null) {
234:                    return null;
235:                }
236:                this .width = this .image.getWidth(null);
237:                this .height = this .image.getHeight(null);
238:
239:                /*
240:                 * start with an array that is big enough to hold all the pixels
241:                 * (plus filter bytes), and an extra 200 bytes for header info
242:                 */
243:                this .pngBytes = new byte[((this .width + 1) * this .height * 3) + 200];
244:
245:                /*
246:                 * keep track of largest byte written to the array
247:                 */
248:                this .maxPos = 0;
249:
250:                this .bytePos = writeBytes(pngIdBytes, 0);
251:                //hdrPos = bytePos;
252:                writeHeader();
253:                writeResolution();
254:                //dataPos = bytePos;
255:                if (writeImageData()) {
256:                    writeEnd();
257:                    this .pngBytes = resizeByteArray(this .pngBytes, this .maxPos);
258:                } else {
259:                    this .pngBytes = null;
260:                }
261:                return this .pngBytes;
262:            }
263:
264:            /**
265:             * Creates an array of bytes that is the PNG equivalent of the current 
266:             * image.  Alpha encoding is determined by its setting in the constructor.
267:             *
268:             * @return an array of bytes, or null if there was a problem
269:             */
270:            public byte[] pngEncode() {
271:                return pngEncode(this .encodeAlpha);
272:            }
273:
274:            /**
275:             * Set the alpha encoding on or off.
276:             *
277:             * @param encodeAlpha  false=no, true=yes
278:             */
279:            public void setEncodeAlpha(boolean encodeAlpha) {
280:                this .encodeAlpha = encodeAlpha;
281:            }
282:
283:            /**
284:             * Retrieve alpha encoding status.
285:             *
286:             * @return boolean false=no, true=yes
287:             */
288:            public boolean getEncodeAlpha() {
289:                return this .encodeAlpha;
290:            }
291:
292:            /**
293:             * Set the filter to use.
294:             *
295:             * @param whichFilter from constant list
296:             */
297:            public void setFilter(int whichFilter) {
298:                this .filter = FILTER_NONE;
299:                if (whichFilter <= FILTER_LAST) {
300:                    this .filter = whichFilter;
301:                }
302:            }
303:
304:            /**
305:             * Retrieve filtering scheme.
306:             *
307:             * @return int (see constant list)
308:             */
309:            public int getFilter() {
310:                return this .filter;
311:            }
312:
313:            /**
314:             * Set the compression level to use.
315:             *
316:             * @param level the compression level (1 = best speed, 9 = best compression,
317:             *        0 = no compression)
318:             */
319:            public void setCompressionLevel(int level) {
320:                if (level >= 0 && level <= 9) {
321:                    this .compressionLevel = level;
322:                }
323:            }
324:
325:            /**
326:             * Retrieve compression level.
327:             *
328:             * @return int (1 = best speed, 9 = best compression, 0 = no compression)
329:             */
330:            public int getCompressionLevel() {
331:                return this .compressionLevel;
332:            }
333:
334:            /**
335:             * Increase or decrease the length of a byte array.
336:             *
337:             * @param array The original array.
338:             * @param newLength The length you wish the new array to have.
339:             * @return Array of newly desired length. If shorter than the
340:             *         original, the trailing elements are truncated.
341:             */
342:            protected byte[] resizeByteArray(byte[] array, int newLength) {
343:                byte[] newArray = new byte[newLength];
344:                int oldLength = array.length;
345:
346:                System.arraycopy(array, 0, newArray, 0, Math.min(oldLength,
347:                        newLength));
348:                return newArray;
349:            }
350:
351:            /**
352:             * Write an array of bytes into the pngBytes array.
353:             * Note: This routine has the side effect of updating
354:             * maxPos, the largest element written in the array.
355:             * The array is resized by 1000 bytes or the length
356:             * of the data to be written, whichever is larger.
357:             *
358:             * @param data The data to be written into pngBytes.
359:             * @param offset The starting point to write to.
360:             * @return The next place to be written to in the pngBytes array.
361:             */
362:            protected int writeBytes(byte[] data, int offset) {
363:                this .maxPos = Math.max(this .maxPos, offset + data.length);
364:                if (data.length + offset > this .pngBytes.length) {
365:                    this .pngBytes = resizeByteArray(this .pngBytes,
366:                            this .pngBytes.length + Math.max(1000, data.length));
367:                }
368:                System.arraycopy(data, 0, this .pngBytes, offset, data.length);
369:                return offset + data.length;
370:            }
371:
372:            /**
373:             * Write an array of bytes into the pngBytes array, specifying number of 
374:             * bytes to write. Note: This routine has the side effect of updating
375:             * maxPos, the largest element written in the array.
376:             * The array is resized by 1000 bytes or the length
377:             * of the data to be written, whichever is larger.
378:             *
379:             * @param data The data to be written into pngBytes.
380:             * @param nBytes The number of bytes to be written.
381:             * @param offset The starting point to write to.
382:             * @return The next place to be written to in the pngBytes array.
383:             */
384:            protected int writeBytes(byte[] data, int nBytes, int offset) {
385:                this .maxPos = Math.max(this .maxPos, offset + nBytes);
386:                if (nBytes + offset > this .pngBytes.length) {
387:                    this .pngBytes = resizeByteArray(this .pngBytes,
388:                            this .pngBytes.length + Math.max(1000, nBytes));
389:                }
390:                System.arraycopy(data, 0, this .pngBytes, offset, nBytes);
391:                return offset + nBytes;
392:            }
393:
394:            /**
395:             * Write a two-byte integer into the pngBytes array at a given position.
396:             *
397:             * @param n The integer to be written into pngBytes.
398:             * @param offset The starting point to write to.
399:             * @return The next place to be written to in the pngBytes array.
400:             */
401:            protected int writeInt2(int n, int offset) {
402:                byte[] temp = { (byte) ((n >> 8) & 0xff), (byte) (n & 0xff) };
403:                return writeBytes(temp, offset);
404:            }
405:
406:            /**
407:             * Write a four-byte integer into the pngBytes array at a given position.
408:             *
409:             * @param n The integer to be written into pngBytes.
410:             * @param offset The starting point to write to.
411:             * @return The next place to be written to in the pngBytes array.
412:             */
413:            protected int writeInt4(int n, int offset) {
414:                byte[] temp = { (byte) ((n >> 24) & 0xff),
415:                        (byte) ((n >> 16) & 0xff), (byte) ((n >> 8) & 0xff),
416:                        (byte) (n & 0xff) };
417:                return writeBytes(temp, offset);
418:            }
419:
420:            /**
421:             * Write a single byte into the pngBytes array at a given position.
422:             *
423:             * @param b The integer to be written into pngBytes.
424:             * @param offset The starting point to write to.
425:             * @return The next place to be written to in the pngBytes array.
426:             */
427:            protected int writeByte(int b, int offset) {
428:                byte[] temp = { (byte) b };
429:                return writeBytes(temp, offset);
430:            }
431:
432:            /**
433:             * Write a PNG "IHDR" chunk into the pngBytes array.
434:             */
435:            protected void writeHeader() {
436:
437:                int startPos = this .bytePos = writeInt4(13, this .bytePos);
438:                this .bytePos = writeBytes(IHDR, this .bytePos);
439:                this .width = this .image.getWidth(null);
440:                this .height = this .image.getHeight(null);
441:                this .bytePos = writeInt4(this .width, this .bytePos);
442:                this .bytePos = writeInt4(this .height, this .bytePos);
443:                this .bytePos = writeByte(8, this .bytePos); // bit depth
444:                this .bytePos = writeByte((this .encodeAlpha) ? 6 : 2,
445:                        this .bytePos);
446:                // direct model
447:                this .bytePos = writeByte(0, this .bytePos); // compression method
448:                this .bytePos = writeByte(0, this .bytePos); // filter method
449:                this .bytePos = writeByte(0, this .bytePos); // no interlace
450:                this .crc.reset();
451:                this .crc.update(this .pngBytes, startPos, this .bytePos
452:                        - startPos);
453:                this .crcValue = this .crc.getValue();
454:                this .bytePos = writeInt4((int) this .crcValue, this .bytePos);
455:            }
456:
457:            /**
458:             * Perform "sub" filtering on the given row.
459:             * Uses temporary array leftBytes to store the original values
460:             * of the previous pixels.  The array is 16 bytes long, which
461:             * will easily hold two-byte samples plus two-byte alpha.
462:             *
463:             * @param pixels The array holding the scan lines being built
464:             * @param startPos Starting position within pixels of bytes to be filtered.
465:             * @param width Width of a scanline in pixels.
466:             */
467:            protected void filterSub(byte[] pixels, int startPos, int width) {
468:                int offset = this .bytesPerPixel;
469:                int actualStart = startPos + offset;
470:                int nBytes = width * this .bytesPerPixel;
471:                int leftInsert = offset;
472:                int leftExtract = 0;
473:
474:                for (int i = actualStart; i < startPos + nBytes; i++) {
475:                    this .leftBytes[leftInsert] = pixels[i];
476:                    pixels[i] = (byte) ((pixels[i] - this .leftBytes[leftExtract]) % 256);
477:                    leftInsert = (leftInsert + 1) % 0x0f;
478:                    leftExtract = (leftExtract + 1) % 0x0f;
479:                }
480:            }
481:
482:            /**
483:             * Perform "up" filtering on the given row.
484:             * Side effect: refills the prior row with current row
485:             *
486:             * @param pixels The array holding the scan lines being built
487:             * @param startPos Starting position within pixels of bytes to be filtered.
488:             * @param width Width of a scanline in pixels.
489:             */
490:            protected void filterUp(byte[] pixels, int startPos, int width) {
491:
492:                final int nBytes = width * this .bytesPerPixel;
493:
494:                for (int i = 0; i < nBytes; i++) {
495:                    final byte currentByte = pixels[startPos + i];
496:                    pixels[startPos + i] = (byte) ((pixels[startPos + i] - this .priorRow[i]) % 256);
497:                    this .priorRow[i] = currentByte;
498:                }
499:            }
500:
501:            /**
502:             * Write the image data into the pngBytes array.
503:             * This will write one or more PNG "IDAT" chunks. In order
504:             * to conserve memory, this method grabs as many rows as will
505:             * fit into 32K bytes, or the whole image; whichever is less.
506:             *
507:             *
508:             * @return true if no errors; false if error grabbing pixels
509:             */
510:            protected boolean writeImageData() {
511:                int rowsLeft = this .height; // number of rows remaining to write
512:                int startRow = 0; // starting row to process this time through
513:                int nRows; // how many rows to grab at a time
514:
515:                byte[] scanLines; // the scan lines to be compressed
516:                int scanPos; // where we are in the scan lines
517:                int startPos; // where this line's actual pixels start (used
518:                // for filtering)
519:
520:                byte[] compressedLines; // the resultant compressed lines
521:                int nCompressed; // how big is the compressed area?
522:
523:                //int depth;              // color depth ( handle only 8 or 32 )
524:
525:                PixelGrabber pg;
526:
527:                this .bytesPerPixel = (this .encodeAlpha) ? 4 : 3;
528:
529:                Deflater scrunch = new Deflater(this .compressionLevel);
530:                ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
531:
532:                DeflaterOutputStream compBytes = new DeflaterOutputStream(
533:                        outBytes, scrunch);
534:                try {
535:                    while (rowsLeft > 0) {
536:                        nRows = Math
537:                                .min(
538:                                        32767 / (this .width * (this .bytesPerPixel + 1)),
539:                                        rowsLeft);
540:                        nRows = Math.max(nRows, 1);
541:
542:                        int[] pixels = new int[this .width * nRows];
543:
544:                        pg = new PixelGrabber(this .image, 0, startRow,
545:                                this .width, nRows, pixels, 0, this .width);
546:                        try {
547:                            pg.grabPixels();
548:                        } catch (Exception e) {
549:                            System.err
550:                                    .println("interrupted waiting for pixels!");
551:                            return false;
552:                        }
553:                        if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
554:                            System.err
555:                                    .println("image fetch aborted or errored");
556:                            return false;
557:                        }
558:
559:                        /*
560:                         * Create a data chunk. scanLines adds "nRows" for
561:                         * the filter bytes.
562:                         */
563:                        scanLines = new byte[this .width * nRows
564:                                * this .bytesPerPixel + nRows];
565:
566:                        if (this .filter == FILTER_SUB) {
567:                            this .leftBytes = new byte[16];
568:                        }
569:                        if (this .filter == FILTER_UP) {
570:                            this .priorRow = new byte[this .width
571:                                    * this .bytesPerPixel];
572:                        }
573:
574:                        scanPos = 0;
575:                        startPos = 1;
576:                        for (int i = 0; i < this .width * nRows; i++) {
577:                            if (i % this .width == 0) {
578:                                scanLines[scanPos++] = (byte) this .filter;
579:                                startPos = scanPos;
580:                            }
581:                            scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
582:                            scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff);
583:                            scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff);
584:                            if (this .encodeAlpha) {
585:                                scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff);
586:                            }
587:                            if ((i % this .width == this .width - 1)
588:                                    && (this .filter != FILTER_NONE)) {
589:                                if (this .filter == FILTER_SUB) {
590:                                    filterSub(scanLines, startPos, this .width);
591:                                }
592:                                if (this .filter == FILTER_UP) {
593:                                    filterUp(scanLines, startPos, this .width);
594:                                }
595:                            }
596:                        }
597:
598:                        /*
599:                         * Write these lines to the output area
600:                         */
601:                        compBytes.write(scanLines, 0, scanPos);
602:
603:                        startRow += nRows;
604:                        rowsLeft -= nRows;
605:                    }
606:                    compBytes.close();
607:
608:                    /*
609:                     * Write the compressed bytes
610:                     */
611:                    compressedLines = outBytes.toByteArray();
612:                    nCompressed = compressedLines.length;
613:
614:                    this .crc.reset();
615:                    this .bytePos = writeInt4(nCompressed, this .bytePos);
616:                    this .bytePos = writeBytes(IDAT, this .bytePos);
617:                    this .crc.update(IDAT);
618:                    this .bytePos = writeBytes(compressedLines, nCompressed,
619:                            this .bytePos);
620:                    this .crc.update(compressedLines, 0, nCompressed);
621:
622:                    this .crcValue = this .crc.getValue();
623:                    this .bytePos = writeInt4((int) this .crcValue, this .bytePos);
624:                    scrunch.finish();
625:                    return true;
626:                } catch (IOException e) {
627:                    System.err.println(e.toString());
628:                    return false;
629:                }
630:            }
631:
632:            /**
633:             * Write a PNG "IEND" chunk into the pngBytes array.
634:             */
635:            protected void writeEnd() {
636:                this .bytePos = writeInt4(0, this .bytePos);
637:                this .bytePos = writeBytes(IEND, this .bytePos);
638:                this .crc.reset();
639:                this .crc.update(IEND);
640:                this .crcValue = this .crc.getValue();
641:                this .bytePos = writeInt4((int) this .crcValue, this .bytePos);
642:            }
643:
644:            /**
645:             * Set the DPI for the X axis.
646:             *
647:             * @param xDpi  The number of dots per inch
648:             */
649:            public void setXDpi(int xDpi) {
650:                this .xDpi = Math.round(xDpi / INCH_IN_METER_UNIT);
651:
652:            }
653:
654:            /**
655:             * Get the DPI for the X axis.
656:             *
657:             * @return The number of dots per inch
658:             */
659:            public int getXDpi() {
660:                return Math.round(xDpi * INCH_IN_METER_UNIT);
661:            }
662:
663:            /**
664:             * Set the DPI for the Y axis.
665:             *
666:             * @param yDpi  The number of dots per inch
667:             */
668:            public void setYDpi(int yDpi) {
669:                this .yDpi = Math.round(yDpi / INCH_IN_METER_UNIT);
670:            }
671:
672:            /**
673:             * Get the DPI for the Y axis.
674:             *
675:             * @return The number of dots per inch
676:             */
677:            public int getYDpi() {
678:                return Math.round(yDpi * INCH_IN_METER_UNIT);
679:            }
680:
681:            /**
682:             * Set the DPI resolution.
683:             *
684:             * @param xDpi  The number of dots per inch for the X axis.
685:             * @param yDpi  The number of dots per inch for the Y axis.
686:             */
687:            public void setDpi(int xDpi, int yDpi) {
688:                this .xDpi = Math.round(xDpi / INCH_IN_METER_UNIT);
689:                this .yDpi = Math.round(yDpi / INCH_IN_METER_UNIT);
690:            }
691:
692:            /**
693:             * Write a PNG "pHYs" chunk into the pngBytes array.
694:             */
695:            protected void writeResolution() {
696:                if (xDpi > 0 && yDpi > 0) {
697:
698:                    final int startPos = bytePos = writeInt4(9, bytePos);
699:                    bytePos = writeBytes(PHYS, bytePos);
700:                    bytePos = writeInt4(xDpi, bytePos);
701:                    bytePos = writeInt4(yDpi, bytePos);
702:                    bytePos = writeByte(1, bytePos); // unit is the meter.
703:
704:                    crc.reset();
705:                    crc.update(pngBytes, startPos, bytePos - startPos);
706:                    crcValue = crc.getValue();
707:                    bytePos = writeInt4((int) crcValue, bytePos);
708:                }
709:            }
710:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.