Source Code Cross Referenced for GifImageDecoder.java in  » 6.0-JDK-Modules » j2me » sun » awt » image » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » sun.awt.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * @(#)GifImageDecoder.java	1.55 06/10/24
003:         *
004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006:         * 
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License version
009:         * 2 only, as published by the Free Software Foundation. 
010:         * 
011:         * This program is distributed in the hope that it will be useful, but
012:         * WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014:         * General Public License version 2 for more details (a copy is
015:         * included at /legal/license.txt). 
016:         * 
017:         * You should have received a copy of the GNU General Public License
018:         * version 2 along with this work; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA 
021:         * 
022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023:         * Clara, CA 95054 or visit www.sun.com if you need additional
024:         * information or have any questions. 
025:         */
026:
027:        /*-
028:         *	Reads GIF images from an InputStream and reports the
029:         *	image data to an InputStreamImageSource object.
030:         */
031:        package sun.awt.image;
032:
033:        import java.util.Vector;
034:        import java.util.Hashtable;
035:        import java.io.InputStream;
036:        import java.io.IOException;
037:        import java.awt.image.*;
038:
039:        /**
040:         * Gif Image converter
041:         *
042:         * @version 1.41 01/05/01
043:         * @author Arthur van Hoff
044:         * @author Jim Graham
045:         */
046:        public class GifImageDecoder extends ImageDecoder {
047:            private static final boolean verbose = false;
048:
049:            private static final int IMAGESEP = 0x2c;
050:            private static final int EXBLOCK = 0x21;
051:            private static final int EX_GRAPHICS_CONTROL = 0xf9;
052:            private static final int EX_COMMENT = 0xfe;
053:            private static final int EX_APPLICATION = 0xff;
054:            private static final int TERMINATOR = 0x3b;
055:            private static final int TRANSPARENCYMASK = 0x01;
056:            private static final int INTERLACEMASK = 0x40;
057:            private static final int COLORMAPMASK = 0x80;
058:
059:            int num_global_colors;
060:            byte[] global_colormap;
061:            int trans_pixel = -1;
062:            IndexColorModel global_model;
063:
064:            Hashtable props = new Hashtable();
065:
066:            byte[] saved_image;
067:            IndexColorModel saved_model;
068:
069:            int global_width;
070:            int global_height;
071:            int global_bgpixel;
072:
073:            GifFrame curframe;
074:
075:            public GifImageDecoder(InputStreamImageSource src, InputStream is) {
076:                super (src, is);
077:            }
078:
079:            /**
080:             * An error has occurred. Throw an exception.
081:             */
082:            private static void error(String s1) throws ImageFormatException {
083:                throw new ImageFormatException(s1);
084:            }
085:
086:            /**
087:             * Read a number of bytes into a buffer.
088:             * @return number of bytes that were not read due to EOF or error
089:             */
090:            private int readBytes(byte buf[], int off, int len) {
091:                while (len > 0) {
092:                    try {
093:                        int n = input.read(buf, off, len);
094:                        if (n < 0) {
095:                            break;
096:                        }
097:                        off += n;
098:                        len -= n;
099:                    } catch (IOException e) {
100:                        break;
101:                    }
102:                }
103:                return len;
104:            }
105:
106:            private static final int ExtractByte(byte buf[], int off) {
107:                return (buf[off] & 0xFF);
108:            }
109:
110:            private static final int ExtractWord(byte buf[], int off) {
111:                return (buf[off] & 0xFF) | ((buf[off + 1] & 0xFF) << 8);
112:            }
113:
114:            /**
115:             * produce an image from the stream.
116:             */
117:            public void produceImage() throws IOException, ImageFormatException {
118:                try {
119:                    readHeader();
120:
121:                    int totalframes = 0;
122:                    int frameno = 0;
123:                    int nloops = -1;
124:                    int disposal_method = 0;
125:                    int delay = -1;
126:                    boolean loopsRead = false;
127:                    boolean isAnimation = false;
128:
129:                    while (!aborted) {
130:                        int code;
131:
132:                        if (!ImageProductionMonitor.allowsProduction()) {
133:                            abort();
134:                            break;
135:                        }
136:
137:                        switch (code = input.read()) {
138:                        case EXBLOCK:
139:                            switch (code = input.read()) {
140:                            case EX_GRAPHICS_CONTROL: {
141:                                byte buf[] = new byte[6];
142:                                if (readBytes(buf, 0, 6) != 0) {
143:                                    return;//error("corrupt GIF file");
144:                                }
145:                                if ((buf[0] != 4) || (buf[5] != 0)) {
146:                                    return;//error("corrupt GIF file (GCE size)");
147:                                }
148:                                // Get the index of the transparent color
149:                                delay = ExtractWord(buf, 2) * 10;
150:                                if (delay > 0 && !isAnimation) {
151:                                    isAnimation = true;
152:                                    ImageFetcher.startingAnimation();
153:                                }
154:                                disposal_method = (buf[1] >> 2) & 7;
155:                                if ((buf[1] & TRANSPARENCYMASK) != 0) {
156:                                    trans_pixel = ExtractByte(buf, 4);
157:                                } else {
158:                                    trans_pixel = -1;
159:                                }
160:                                break;
161:                            }
162:
163:                            case EX_COMMENT:
164:                            case EX_APPLICATION:
165:                            default:
166:                                boolean loop_tag = false;
167:                                String comment = "";
168:                                while (true) {
169:                                    int n = input.read();
170:                                    if (n <= 0) {
171:                                        break;
172:                                    }
173:                                    byte buf[] = new byte[n];
174:                                    if (readBytes(buf, 0, n) != 0) {
175:                                        return;//error("corrupt GIF file");
176:                                    }
177:                                    if (code == EX_COMMENT) {
178:                                        comment += new String(buf);
179:                                    } else if (code == EX_APPLICATION) {
180:                                        if (loop_tag) {
181:                                            if (n == 3 && buf[0] == 1) {
182:                                                if (loopsRead) {
183:                                                    ExtractWord(buf, 1);
184:                                                } else {
185:                                                    nloops = ExtractWord(buf, 1);
186:                                                    loopsRead = true;
187:                                                }
188:                                            } else {
189:                                                loop_tag = false;
190:                                            }
191:                                        }
192:                                        if ("NETSCAPE2.0"
193:                                                .equals(new String(buf))) {
194:                                            loop_tag = true;
195:                                        }
196:                                    }
197:                                }
198:                                if (code == EX_COMMENT) {
199:                                    props.put("comment", comment);
200:                                }
201:                                if (loop_tag && !isAnimation) {
202:                                    isAnimation = true;
203:                                    ImageFetcher.startingAnimation();
204:                                }
205:                                break;
206:
207:                            case -1:
208:                                return; //error("corrupt GIF file");
209:                            }
210:                            break;
211:
212:                        case IMAGESEP:
213:                            if (!isAnimation) {
214:                                input.mark(0); // we don't need the mark buffer
215:                            }
216:                            try {
217:                                if (!readImage(totalframes == 0,
218:                                        disposal_method, delay)) {
219:                                    return;
220:                                }
221:                            } catch (Exception e) {
222:                                if (verbose) {
223:                                    e.printStackTrace();
224:                                }
225:                                return;
226:                            }
227:                            frameno++;
228:                            totalframes++;
229:                            break;
230:
231:                        default:
232:                        case -1:
233:                            if (verbose) {
234:                                if (code == -1) {
235:                                    System.err
236:                                            .println("Premature EOF in GIF file,"
237:                                                    + " frame " + frameno);
238:                                } else {
239:                                    System.err
240:                                            .println("corrupt GIF file (parse) ["
241:                                                    + code + "].");
242:                                }
243:                            }
244:                            if (frameno == 0) {
245:                                return;
246:                            }
247:                            // NOBREAK
248:
249:                        case TERMINATOR:
250:                            if (nloops == 0 || nloops-- >= 0) {
251:                                try {
252:                                    if (curframe != null) {
253:                                        curframe.dispose();
254:                                        curframe = null;
255:                                    }
256:                                    input.reset();
257:                                    saved_image = null;
258:                                    saved_model = null;
259:                                    frameno = 0;
260:                                    break;
261:                                } catch (IOException e) {
262:                                    return; // Unable to reset input buffer
263:                                }
264:                            }
265:                            if (verbose && frameno != 1) {
266:                                System.out.println("processing GIF terminator,"
267:                                        + " frames: " + frameno + " total: "
268:                                        + totalframes);
269:                            }
270:                            imageComplete(ImageConsumer.STATICIMAGEDONE, true);
271:                            return;
272:                        }
273:                    }
274:                } finally {
275:                    close();
276:                }
277:            }
278:
279:            /**
280:             * Read Image header
281:             */
282:            private void readHeader() throws IOException, ImageFormatException {
283:                // Create a buffer
284:                byte buf[] = new byte[13];
285:
286:                // Read the header
287:                if (readBytes(buf, 0, 13) != 0) {
288:                    throw new IOException();
289:                }
290:
291:                // Check header
292:                if ((buf[0] != 'G') || (buf[1] != 'I') || (buf[2] != 'F')) {
293:                    error("not a GIF file.");
294:                }
295:
296:                // Global width&height
297:                global_width = ExtractWord(buf, 6);
298:                global_height = ExtractWord(buf, 8);
299:
300:                // colormap info
301:                int ch = ExtractByte(buf, 10);
302:                if ((ch & COLORMAPMASK) == 0) {
303:                    error("no global colormap in GIF file.");
304:                }
305:                num_global_colors = 1 << ((ch & 0x7) + 1);
306:
307:                global_bgpixel = ExtractByte(buf, 11);
308:
309:                if (buf[12] != 0) {
310:                    props.put("aspectratio", ""
311:                            + ((ExtractByte(buf, 12) + 15) / 64.0));
312:                }
313:
314:                // Read colors
315:                global_colormap = new byte[num_global_colors * 3];
316:                if (readBytes(global_colormap, 0, num_global_colors * 3) != 0) {
317:                    throw new IOException();
318:                }
319:
320:                input.mark(1000000); // set this mark in case this is an animated GIF
321:            }
322:
323:            /**
324:             * The ImageConsumer hints flag for a non-interlaced GIF image.
325:             */
326:            private static final int normalflags = ImageConsumer.TOPDOWNLEFTRIGHT
327:                    | ImageConsumer.COMPLETESCANLINES
328:                    | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME;
329:
330:            /**
331:             * The ImageConsumer hints flag for an interlaced GIF image.
332:             */
333:            private static final int interlaceflags = ImageConsumer.RANDOMPIXELORDER
334:                    | ImageConsumer.COMPLETESCANLINES
335:                    | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME;
336:
337:            private short prefix[] = new short[4096];
338:            private byte suffix[] = new byte[4096];
339:            private byte outCode[] = new byte[4097];
340:
341:            //private native boolean parseImage(int x, int y, int width, int height,
342:            //				      boolean interlace, int initCodeSize,
343:            //				      byte block[], byte rasline[],
344:            //				      IndexColorModel model);
345:
346:            /* 
347:             * This is converted from the native version. The java version is 
348:             * much faster when we have JIT.
349:             */
350:            private boolean parseImage(int relx, int rely, int width,
351:                    int height, boolean interlace, int initCodeSize,
352:                    byte block[], byte rasline[], IndexColorModel model) {
353:                int OUTCODELENGTH = 4097;
354:
355:                int clearCode = (1 << initCodeSize);
356:                int eofCode = clearCode + 1;
357:                int bitMask;
358:                int curCode;
359:                int outCount = OUTCODELENGTH;
360:
361:                /* Variables used to form reading data */
362:                boolean blockEnd = false;
363:                int remain = 0;
364:                int byteoff = 0;
365:                int accumbits = 0;
366:                int accumdata = 0;
367:
368:                /* Variables used to decompress the data */
369:                int codeSize = initCodeSize + 1;
370:                int maxCode = 1 << codeSize;
371:                int codeMask = maxCode - 1;
372:                int freeCode = clearCode + 2;
373:                int code = 0;
374:                int oldCode = 0;
375:                char prevChar = 0;
376:
377:                //int blockLength = 0;
378:                int blockLength = 0;
379:
380:                /* Variables used for writing pixels */
381:                int x = width;
382:                int y = 0;
383:                int off = 0;
384:                int passinc = interlace ? 8 : 1;
385:                int passht = passinc;
386:                int len;
387:
388:                bitMask = model.getMapSize() - 1;
389:
390:                /* Read codes until the eofCode is encountered */
391:                for (;;) {
392:                    if (accumbits < codeSize) {
393:                        boolean lastByte = false;
394:                        /* fill the buffer if needed */
395:                        while (remain < 2) {
396:                            if (blockEnd) {
397:                                /* Sometimes we have one last byte to process... */
398:                                if (remain == 1 && accumbits + 8 >= codeSize) {
399:                                    break;
400:                                }
401:
402:                                if (off > 0) {
403:                                    //                             sendPixels(relx, rely+y, width, passht, rasline, model);
404:                                    sendPixels(relx, rely + y, width, 1,
405:                                            rasline, model);
406:                                }
407:                                /* quietly accept truncated GIF images */
408:                                return false;
409:                            }
410:                            /* move remaining bytes to the beginning of the buffer */
411:                            block[0] = block[byteoff];
412:                            byteoff = 0;
413:
414:                            /* fill the block */
415:                            len = readBytes(block, remain, blockLength + 1);
416:
417:                            remain += blockLength;
418:                            if (len > 0) {
419:                                remain -= (len - 1);
420:                                blockLength = 0;
421:                            } else {
422:                                blockLength = (block[remain] & 0xff);
423:                            }
424:                            if (blockLength == 0) {
425:                                blockEnd = true;
426:                            }
427:                        }
428:
429:                        /* 2 bytes at a time saves checking for accumbits < codeSize.
430:                         * We know we'll get enough and also that we can't overflow
431:                         * since codeSize <= 12.
432:                         */
433:                        if (!lastByte) {
434:                            remain -= 2;
435:                            accumdata += (block[byteoff++] & 0xff) << accumbits;
436:                            accumbits += 8;
437:                            accumdata += (block[byteoff++] & 0xff) << accumbits;
438:                            accumbits += 8;
439:                        } else {
440:                            remain--;
441:                            accumdata += (block[byteoff++] & 0xff) << accumbits;
442:                            accumbits += 8;
443:                        }
444:                    }
445:
446:                    /* Compute the code */
447:                    code = accumdata & codeMask;
448:                    accumdata >>= codeSize;
449:                    accumbits -= codeSize;
450:
451:                    /*
452:                     * Interpret the code
453:                     */
454:                    if (code == clearCode) {
455:                        /* Clear code sets everything back to its initial value, then
456:                         * reads the immediately subsequent code as uncompressed data.
457:                         */
458:
459:                        /* Note that freeCode is one less than it is supposed to be,
460:                         * this is because it will be incremented next time round the 
461:                         * loop
462:                         */
463:                        freeCode = clearCode + 1;
464:                        codeSize = initCodeSize + 1;
465:                        maxCode = 1 << codeSize;
466:                        codeMask = maxCode - 1;
467:
468:                        /* Continue if we've NOT reached the end, some Gif images
469:                         * contain bogus codes after the last clear code.
470:                         */
471:                        if (y < height) {
472:                            continue;
473:                        }
474:
475:                        /* pretend we've reached the end of the data */
476:                        code = eofCode;
477:                    }
478:
479:                    if (code == eofCode) {
480:                        /* make sure we read the whole block of pixels. */
481:                        while (!blockEnd) {
482:                            if (readBytes(block, 0, blockLength + 1) != 0) {
483:                                /* quietly accept truncated GIF images */
484:                                return false;
485:                            }
486:                            blockLength = block[blockLength];
487:                            blockEnd = (blockLength == 0);
488:                        }
489:                        return true;
490:                    }
491:
492:                    /* It must be data: save code in CurCode */
493:                    curCode = code;
494:                    /* Whenever it gets here outCount is always equal to 
495:                       OUTCODELENGTH, so no need to reset outCount. */
496:                    //outCount = OUTCODELENGTH;
497:                    /* If greater or equal to freeCode, not in the hash table
498:                     * yet; repeat the last character decoded
499:                     */
500:                    if (curCode >= freeCode) {
501:                        if (curCode > freeCode) {
502:                            /*
503:                             * if we get a code too far outside our range, it
504:                             * could case the parser to start traversing parts
505:                             * of our data structure that are out of range...
506:                             */
507:                            /*In native version: goto flushit;*/
508:                            while (!blockEnd) {
509:                                if (readBytes(block, 0, blockLength + 1) != 0) {
510:                                    /* quietly accept truncated GIF images */
511:                                    return false;
512:                                }
513:                                blockLength = block[blockLength];
514:                                blockEnd = (blockLength == 0);
515:                            }
516:                            return true;
517:                        }
518:                        curCode = oldCode;
519:                        outCode[--outCount] = (byte) prevChar;
520:                    }
521:
522:                    /* Unless this code is raw data, pursue the chain pointed
523:                     * to by curCode through the hash table to its end; each
524:                     * code in the chain puts its associated output code on
525:                     * the output queue.
526:                     */
527:                    while (curCode > bitMask) {
528:                        outCode[--outCount] = suffix[curCode];
529:                        if (outCount == 0) {
530:                            /*
531:                             * In theory this should never happen since our
532:                             * prefix and suffix arrays are monotonically
533:                             * decreasing and so outCode will only be filled
534:                             * as much as those arrays, but I don't want to
535:                             * take that chance and the test is probably
536:                             * cheap compared to the read and write operations.
537:                             * If we ever do overflow the array, we will just
538:                             * flush the rest of the data and quietly accept
539:                             * the GIF as truncated here.
540:                             */
541:                            //In native version: goto flushit;
542:                            while (!blockEnd) {
543:                                if (readBytes(block, 0, blockLength + 1) != 0) {
544:                                    /* quietly accept truncated GIF images */
545:                                    return false;
546:                                }
547:                                blockLength = block[blockLength];
548:                                blockEnd = (blockLength == 0);
549:                            }
550:                            return true;
551:                        }
552:                        curCode = prefix[curCode];
553:                    }
554:
555:                    /* The last code in the chain is treated as raw data. */
556:                    prevChar = (char) curCode;
557:                    outCode[--outCount] = (byte) prevChar;
558:
559:                    /* Now we put the data out to the Output routine. It's
560:                     * been stacked LIFO, so deal with it that way...
561:                     */
562:                    len = OUTCODELENGTH - outCount; /* This is why I commented out
563:                                                                  the code that resets outCount. */
564:                    while (--len >= 0) {
565:                        rasline[off++] = outCode[outCount++];
566:
567:                        /* Update the X-coordinate, and if it overflows, update the
568:                         * Y-coordinate
569:                         */
570:                        if (--x == 0) {
571:                            int count;
572:
573:                            /* If a non-interlaced picture, just increment y to the next
574:                             * scan line.  If it's interlaced, deal with the interlace as
575:                             * described in the GIF spec.  Put the decoded scan line out
576:                             * to the screen if we haven't gone past the bottom of it
577:                             */
578:                            //                    count = sendPixels(relx, rely+y, width, passht, rasline, model);
579:                            count = sendPixels(relx, rely + y, width, 1,
580:                                    rasline, model);
581:
582:                            if (count <= 0) {
583:                                /* Nobody is listening any more. */
584:                                return false;
585:                            }
586:
587:                            x = width;
588:                            off = 0;
589:                            /*  pass        inc     ht      ystart */
590:                            /*   0           8      8          0   */
591:                            /*   1           8      4          4   */
592:                            /*   2           4      2          2   */
593:                            /*   3           2      1          1   */
594:                            y += passinc;
595:                            while (y >= height) {
596:                                passinc = passht;
597:                                passht >>= 1;
598:                                y = passht;
599:                                if (passht == 0) {
600:                                    //In native version: goto flushit;
601:                                    while (!blockEnd) {
602:                                        if (readBytes(block, 0, blockLength + 1) != 0) {
603:                                            /* quietly accept truncated GIF images */
604:                                            return false;
605:                                        }
606:                                        blockLength = block[blockLength] & 0xff;
607:                                        blockEnd = (blockLength == 0);
608:                                    }
609:                                    return true;
610:                                }
611:                            }
612:                        }
613:                    }
614:
615:                    /* Build the hash table on-the-fly. No table is stored in the file. */
616:                    prefix[freeCode] = (short) oldCode;
617:                    suffix[freeCode] = (byte) prevChar;
618:                    oldCode = code;
619:                    /* Point to the next slot in the table.  If we exceed the
620:                     * maxCode, increment the code size unless
621:                     * it's already 12.  If it is, do nothing: the next code
622:                     * decompressed better be CLEAR
623:                     */
624:                    if (++freeCode >= maxCode) {
625:                        if (codeSize < 12) {
626:                            codeSize++;
627:                            maxCode <<= 1;
628:                            codeMask = maxCode - 1;
629:                        } else {
630:                            /* Just in case */
631:                            freeCode = maxCode - 1;
632:                        }
633:                    }
634:                }
635:            }
636:
637:            private int sendPixels(int x, int y, int width, int height,
638:                    byte rasline[], ColorModel model) {
639:                int rasbeg, rasend, x2;
640:                if (y < 0) {
641:                    height += y;
642:                    y = 0;
643:                }
644:                if (y + height > global_height) {
645:                    height = global_height - y;
646:                }
647:                if (height <= 0) {
648:                    return 1;
649:                }
650:                // rasline[0]     == pixel at coordinate (x,y)
651:                // rasline[width] == pixel at coordinate (x+width, y)
652:                if (x < 0) {
653:                    rasbeg = -x;
654:                    width += x; // same as (width -= rasbeg)
655:                    x2 = 0; // same as (x2     = x + rasbeg)
656:                } else {
657:                    rasbeg = 0;
658:                    // width -= 0;	// same as (width -= rasbeg)
659:                    x2 = x; // same as (x2     = x + rasbeg)
660:                }
661:                // rasline[rasbeg]          == pixel at coordinate (x2,y)
662:                // rasline[width]           == pixel at coordinate (x+width, y)
663:                // rasline[rasbeg + width]  == pixel at coordinate (x2+width, y)
664:                if (x2 + width > global_width) {
665:                    width = global_width - x2;
666:                }
667:                if (width <= 0) {
668:                    return 1;
669:                }
670:                rasend = rasbeg + width;
671:                // rasline[rasbeg] == pixel at coordinate (x2,y)
672:                // rasline[rasend] == pixel at coordinate (x2+width, y)
673:                int off = y * global_width + x2;
674:                boolean save = (curframe.disposal_method == GifFrame.DISPOSAL_SAVE);
675:                if (trans_pixel >= 0 && !curframe.initialframe) {
676:                    if (saved_image != null && saved_model == model) {
677:                        for (int i = rasbeg; i < rasend; i++, off++) {
678:                            byte pixel = rasline[i];
679:                            if ((pixel & 0xff) == trans_pixel) {
680:                                rasline[i] = saved_image[off];
681:                            } else if (save) {
682:                                saved_image[off] = pixel;
683:                            }
684:                        }
685:                    } else {
686:                        // We have to do this the hard way - only transmit
687:                        // the non-transparent sections of the line...
688:                        int runstart = -1;
689:                        int count = 1;
690:                        for (int i = rasbeg; i < rasend; i++, off++) {
691:                            byte pixel = rasline[i];
692:                            if ((pixel & 0xff) == trans_pixel) {
693:                                if (runstart >= 0) {
694:                                    //			    count = setPixels(x + runstart, y, i - runstart, height, model, rasline, runstart, 0);
695:                                    count = setPixels(x + runstart, y, i
696:                                            - runstart, height, model, rasline,
697:                                            runstart, i - runstart);
698:                                    if (count == 0) {
699:                                        break;
700:                                    }
701:                                }
702:                                runstart = -1;
703:                            } else {
704:                                if (runstart < 0) {
705:                                    runstart = i;
706:                                }
707:                                if (save) {
708:                                    saved_image[off] = pixel;
709:                                }
710:                            }
711:                        }
712:                        if (runstart >= 0) {
713:                            //		    count = setPixels(x + runstart, y, rasend - runstart, height, model, rasline, runstart, 0);
714:                            count = setPixels(x + runstart, y, rasend
715:                                    - runstart, height, model, rasline,
716:                                    runstart, rasend - runstart);
717:                        }
718:                        // Since (saved_model != model), store must be null...
719:                        return count;
720:                    }
721:                } else if (save) {
722:                    System.arraycopy(rasline, rasbeg, saved_image, off, width);
723:                }
724:                //	int count = setPixels(x2, y, width, height, model, rasline, rasbeg, 0);
725:                int count = setPixels(x2, y, width, height, model, rasline,
726:                        rasbeg, width);
727:                return count;
728:            }
729:
730:            /**
731:             * Read Image data
732:             */
733:            private boolean readImage(boolean first, int disposal_method,
734:                    int delay) throws IOException {
735:                if (curframe != null && !curframe.dispose()) {
736:                    abort();
737:                    return false;
738:                }
739:
740:                long tm = 0;
741:
742:                if (verbose) {
743:                    tm = System.currentTimeMillis();
744:                }
745:
746:                // Allocate the buffer
747:                byte block[] = new byte[256 + 3];
748:
749:                // Read the image descriptor
750:                if (readBytes(block, 0, 10) != 0) {
751:                    throw new IOException();
752:                }
753:                int x = ExtractWord(block, 0);
754:                int y = ExtractWord(block, 2);
755:                int width = ExtractWord(block, 4);
756:                int height = ExtractWord(block, 6);
757:                boolean interlace = (block[8] & INTERLACEMASK) != 0;
758:
759:                IndexColorModel model = global_model;
760:
761:                if ((block[8] & COLORMAPMASK) != 0) {
762:                    // We read one extra byte above so now when we must
763:                    // transfer that byte as the first colormap byte
764:                    // and manually read the code size when we are done
765:                    int num_local_colors = 1 << ((block[8] & 0x7) + 1);
766:
767:                    // Read local colors
768:                    byte[] local_colormap = new byte[num_local_colors * 3];
769:                    local_colormap[0] = block[9];
770:                    if (readBytes(local_colormap, 1, num_local_colors * 3 - 1) != 0) {
771:                        throw new IOException();
772:                    }
773:
774:                    // Now read the "real" code size byte which follows
775:                    // the local color table
776:                    if (readBytes(block, 9, 1) != 0) {
777:                        throw new IOException();
778:                    }
779:                    model = new IndexColorModel(8, num_local_colors,
780:                            local_colormap, 0, false, trans_pixel);
781:                } else if (model == null
782:                        || trans_pixel != model.getTransparentPixel()) {
783:                    model = new IndexColorModel(8, num_global_colors,
784:                            global_colormap, 0, false, trans_pixel);
785:                    global_model = model;
786:                }
787:
788:                // Notify the consumers
789:                if (first) {
790:                    if (global_width == 0)
791:                        global_width = width;
792:                    if (global_height == 0)
793:                        global_height = height;
794:
795:                    setDimensions(global_width, global_height);
796:                    setProperties(props);
797:                    setColorModel(model);
798:                    headerComplete();
799:                }
800:
801:                if (disposal_method == GifFrame.DISPOSAL_SAVE
802:                        && saved_image == null) {
803:                    saved_image = new byte[global_width * global_height];
804:                }
805:
806:                int hints = (interlace ? interlaceflags : normalflags);
807:                setHints(hints);
808:
809:                curframe = new GifFrame(this , disposal_method, delay,
810:                        (curframe == null), model, x, y, width, height);
811:
812:                // allocate the raster data
813:                byte rasline[] = new byte[width];
814:
815:                if (verbose) {
816:                    System.out.print("Reading a " + width + " by " + height
817:                            + " " + (interlace ? "" : "non-")
818:                            + "interlaced image...");
819:                }
820:
821:                boolean ret = parseImage(x, y, width, height, interlace,
822:                        ExtractByte(block, 9), block, rasline, model);
823:
824:                if (!ret) {
825:                    abort();
826:                }
827:
828:                if (verbose) {
829:                    System.out.println("done in "
830:                            + (System.currentTimeMillis() - tm) + "ms");
831:                }
832:
833:                return ret;
834:            }
835:
836:            /* 
837:             * Since I translated the JNI version of parseImage() into Java,
838:             * we no longer need initIDs().
839:             */
840:            /* // if we're using JNI, we need to find the method and field IDs.
841:             * private static native void initIDs();
842:             * static {
843:             * 	 initIDs();
844:             * }
845:             */
846:        }
847:
848:        class GifFrame {
849:            private static final boolean verbose = false;
850:            private static IndexColorModel trans_model;
851:
852:            static final int DISPOSAL_NONE = 0x00;
853:            static final int DISPOSAL_SAVE = 0x01;
854:            static final int DISPOSAL_BGCOLOR = 0x02;
855:            static final int DISPOSAL_PREVIOUS = 0x03;
856:
857:            GifImageDecoder decoder;
858:
859:            int disposal_method;
860:            int delay;
861:
862:            IndexColorModel model;
863:
864:            int x;
865:            int y;
866:            int width;
867:            int height;
868:
869:            boolean initialframe;
870:
871:            public GifFrame(GifImageDecoder id, int dm, int dl, boolean init,
872:                    IndexColorModel cm, int x, int y, int w, int h) {
873:                this .decoder = id;
874:                this .disposal_method = dm;
875:                this .delay = dl;
876:                this .model = cm;
877:                this .initialframe = init;
878:                this .x = x;
879:                this .y = y;
880:                this .width = w;
881:                this .height = h;
882:            }
883:
884:            private void setPixels(int x, int y, int w, int h, ColorModel cm,
885:                    byte[] pix, int off, int scan) {
886:                decoder.setPixels(x, y, w, h, cm, pix, off, scan);
887:            }
888:
889:            public boolean dispose() {
890:                if (decoder.imageComplete(ImageConsumer.SINGLEFRAMEDONE, false) == 0) {
891:                    return false;
892:                } else {
893:                    if (delay > 0) {
894:                        try {
895:                            if (verbose) {
896:                                System.out.println("sleeping: " + delay);
897:                            }
898:                            Thread.sleep(delay);
899:                        } catch (InterruptedException e) {
900:                            return false;
901:                        }
902:                    } else {
903:                        Thread.yield();
904:                    }
905:
906:                    if (verbose && disposal_method != 0) {
907:                        System.out.println("disposal method: "
908:                                + disposal_method);
909:                    }
910:
911:                    int global_width = decoder.global_width;
912:                    int global_height = decoder.global_height;
913:
914:                    if (x < 0) {
915:                        width += x;
916:                        x = 0;
917:                    }
918:                    if (x + width > global_width) {
919:                        width = global_width - x;
920:                    }
921:                    if (width <= 0) {
922:                        disposal_method = DISPOSAL_NONE;
923:                    } else {
924:                        if (y < 0) {
925:                            height += y;
926:                            y = 0;
927:                        }
928:                        if (y + height > global_height) {
929:                            height = global_height - y;
930:                        }
931:                        if (height <= 0) {
932:                            disposal_method = DISPOSAL_NONE;
933:                        }
934:                    }
935:
936:                    switch (disposal_method) {
937:                    case DISPOSAL_PREVIOUS:
938:                        byte[] saved_image = decoder.saved_image;
939:                        IndexColorModel saved_model = decoder.saved_model;
940:                        if (saved_image != null) {
941:                            setPixels(x, y, width, height, saved_model,
942:                                    saved_image, y * global_width + x,
943:                                    global_width);
944:                        }
945:                        break;
946:                    case DISPOSAL_BGCOLOR:
947:                        byte tpix;
948:                        if (model.getTransparentPixel() < 0) {
949:                            model = trans_model;
950:                            if (model == null) {
951:                                model = new IndexColorModel(8, 1, new byte[4],
952:                                        0, true);
953:                                trans_model = model;
954:                            }
955:                            tpix = 0;
956:                        } else {
957:                            tpix = (byte) model.getTransparentPixel();
958:                        }
959:
960:                        int rassize = width * height;
961:                        byte[] rasfill = new byte[rassize];
962:                        if (tpix != 0) {
963:                            for (int i = 0; i < rassize; i++) {
964:                                rasfill[i] = tpix;
965:                            }
966:                        }
967:                        //		setPixels(x, y, width, height, model, rasfill, 0, 0);
968:                        setPixels(x, y, width, height, model, rasfill, 0, width);
969:                        break;
970:                    case DISPOSAL_SAVE:
971:                        decoder.saved_model = model;
972:                        break;
973:                    }
974:                }
975:                return true;
976:            }
977:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.