Source Code Cross Referenced for GIFHelper.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » iv » flash » util » 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 » Ajax » Laszlo 4.0.10 » org.openlaszlo.iv.flash.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: GIFHelper.java,v 1.2 2002/02/15 23:44:28 skavish Exp $
003:         *
004:         * ===========================================================================
005:         *
006:         * The JGenerator Software License, Version 1.0
007:         *
008:         * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
009:         *
010:         * Redistribution and use in source and binary forms, with or without
011:         * modification, are permitted provided that the following conditions are met:
012:         *
013:         * 1. Redistributions of source code must retain the above copyright
014:         *    notice, this list of conditions and the following disclaimer.
015:         *
016:         * 2. Redistributions in binary form must reproduce the above copyright
017:         *    notice, this list of conditions and the following disclaimer in
018:         *    the documentation and/or other materials provided with the
019:         *    distribution.
020:         *
021:         * 3. The end-user documentation included with the redistribution, if
022:         *    any, must include the following acknowlegement:
023:         *    "This product includes software developed by Dmitry Skavish
024:         *     (skavish@usa.net, http://www.flashgap.com/)."
025:         *    Alternately, this acknowlegement may appear in the software itself,
026:         *    if and wherever such third-party acknowlegements normally appear.
027:         *
028:         * 4. The name "The JGenerator" must not be used to endorse or promote
029:         *    products derived from this software without prior written permission.
030:         *    For written permission, please contact skavish@usa.net.
031:         *
032:         * 5. Products derived from this software may not be called "The JGenerator"
033:         *    nor may "The JGenerator" appear in their names without prior written
034:         *    permission of Dmitry Skavish.
035:         *
036:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039:         * DISCLAIMED.  IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
040:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047:         * SUCH DAMAGE.
048:         *
049:         */
050:
051:        package org.openlaszlo.iv.flash.util;
052:
053:        import java.io.*;
054:        import java.util.zip.Deflater;
055:        import org.openlaszlo.iv.flash.parser.DataMarker;
056:
057:        /**
058:         * GIF Reader utility class
059:         * Parse GIF code from an inputStream without using java.awt
060:         * (to avoid the need of a display on a server)
061:         *
062:         * Use a modified version of the GIFDecoder part the PJA Toolkit
063:         * Part of the implementation has been commented because we didn't need it
064:         * Basically everything that was dealing with GIF comments output
065:         * and the creation of an RGB image
066:         *
067:         * With kind permission of Emmanuel PUYBARET from eteks
068:         * Lots of contributions here, but the code is reliable and approved
069:         *
070:         * Following is the initial copyright notice (which for this project is Apache style)
071:         *
072:         * ****************************************************************************
073:         *
074:         * Copyright (c) 2000 Emmanuel PUYBARET / eTeks <info@eteks.com>. All Rights Reserved.
075:         *
076:         * Raster over-run errors fixed by Alan Dix (alan@hcibook.com www.hiraeth.com/alan)
077:         *
078:         * Visit eTeks web site for up-to-date versions of the original file and other
079:         * Java tools and tutorials : http://www.eteks.com/
080:         *
081:         * ****************************************************************************
082:         *
083:         * This file is based and translated from the following C source file :
084:         *
085:         * xvgif.c  -  GIF loading code for 'xv'.  Based strongly on...
086:         *
087:         * gif2ras.c - Converts from a Compuserve GIF (tm) image to a Sun raster image.
088:         *
089:         * Copyright (c) 1988, 1989 by Patrick J. Naughton
090:         *
091:         * Author: Patrick J. Naughton
092:         * naughton@wind.sun.com
093:         *
094:         * Permission to use, copy, modify, and distribute this software and its
095:         * documentation for any purpose and without fee is hereby granted,
096:         * provided that the above copyright notice appear in all copies and that
097:         * both that copyright notice and this permission notice appear in
098:         * supporting documentation.
099:         *
100:         * This file is provided AS IS with no warranties of any kind.  The author
101:         * shall have no liability with respect to the infringement of copyrights,
102:         * trade secrets or any patents by this file or any part thereof.  In no
103:         * event will the author be liable for any lost revenue or profits or
104:         * other special, indirect and consequential damages.
105:         *
106:         * ****************************************************************************
107:         *
108:         */
109:
110:        public class GIFHelper {
111:
112:            private byte bytePixels[]; // image data in index model
113:            private int width; // image width
114:            private int height; // image height
115:            private int bitMask; // size of the colormap - 1;
116:            private int colorMapSize; // actual size of the colormap
117:
118:            private InputStream input; // the GIF ByteArrayInputStream
119:            private byte data[]; // the compressed (zlib) byte array
120:
121:            /******************************************************************************
122:             * The following methods are the getters needed for JGen to process
123:             * a new LBitmap object to insert into the Script
124:             * Added to the original GIFReader especially for JGen
125:             ******************************************************************************/
126:
127:            public int getColorTableSize() {
128:                return bitMask;
129:            }
130:
131:            public int getWidth() {
132:                return width;
133:            }
134:
135:            public int getHeight() {
136:                return height;
137:            }
138:
139:            public DataMarker getZlibData() throws IOException {
140:                int deflatedSize = deflate(); // compress the data
141:                return new DataMarker(data, 0, deflatedSize);
142:            }
143:
144:            public boolean isAlpha() {
145:                return (transparentIndex > -1);
146:            }
147:
148:            /**
149:             * Launch the loadGIF routine
150:             *
151:             * @param buffer
152:             * @exception IOException
153:             */
154:            public void doRead(byte[] buffer) throws IOException {
155:                doRead(new ByteArrayInputStream(buffer, 0, buffer.length));
156:            }
157:
158:            public void doRead(FlashBuffer fob) throws IOException {
159:                doRead(fob.getInputStream());
160:            }
161:
162:            public void doRead(InputStream input) throws IOException {
163:                this .input = input;
164:                try {
165:                    loadGIF(input);
166:                } finally {
167:                    try {
168:                        input.close();
169:                    } catch (IOException ioe) {
170:                    }
171:                }
172:            }
173:
174:            /**
175:             * Performs the ZLib compression.<br>
176:             *
177:             * <p>Everything from here is the private implementation of the reader
178:             * But we don't want to disturb other classes with that stuff, do we ?
179:             *
180:             * @return
181:             * @exception IOException
182:             */
183:            private int deflate() throws IOException {
184:                int retour = 0;
185:                int plus = 0;
186:                if (transparentIndex > -1)
187:                    plus++;
188:                int maxpixels = bytePixels.length;
189:                int falsewidth = width;
190:                int added = 0;
191:                if (width % 4 > 0) {
192:                    while (falsewidth % 4 > 0) {
193:                        falsewidth++;
194:                        added++;
195:                    }
196:                    maxpixels = falsewidth * height;
197:                }
198:                byte[] map = new byte[colorMapSize * (3 + plus) + maxpixels];
199:                for (int i = 0; i < colorMapSize; i++) {
200:                    if (transparentIndex > -1) {
201:                        if (transparentIndex == i) {
202:                            map[i * (3 + plus)] = 0;
203:                            map[(i * (3 + plus)) + 1] = 0;
204:                            map[(i * (3 + plus)) + 2] = 0;
205:                            map[(i * (3 + plus)) + 3] = 0;
206:                        } else {
207:                            map[i * (3 + plus)] = r[i];
208:                            map[(i * (3 + plus)) + 1] = g[i];
209:                            map[(i * (3 + plus)) + 2] = b[i];
210:                            map[(i * (3 + plus)) + 3] = (byte) 255;
211:                        }
212:                    } else {
213:                        map[i * (3 + plus)] = r[i];
214:                        map[(i * (3 + plus)) + 1] = g[i];
215:                        map[(i * (3 + plus)) + 2] = b[i];
216:                    }
217:                }
218:                if (width % 4 > 0) {
219:                    byte[] tempPixels = new byte[maxpixels];
220:                    int idTemp = 0;
221:                    int idByte = 0;
222:                    for (int h = 0; h < height; h++) {
223:                        for (int w = 0; w < width; w++)
224:                            tempPixels[idTemp++] = bytePixels[idByte++];
225:                        for (int i = 0; i < added; i++)
226:                            tempPixels[idTemp++] = 0x00;
227:                    }
228:                    bytePixels = tempPixels;
229:                }
230:                System.arraycopy(bytePixels, 0, map,
231:                        (colorMapSize * (3 + plus)), bytePixels.length);
232:                Deflater def = new Deflater();
233:                def.setInput(map);
234:                data = new byte[(colorMapSize * (3 + plus)) + bytePixels.length];
235:                def.finish();
236:                retour = def.deflate(data);
237:                return retour;
238:            }
239:
240:            /******************************************************************************
241:             * This is where the original GIFReader from PJA starts
242:             * A few things had been commented out because it wasn't needed
243:             ******************************************************************************/
244:
245:            // Where the xvgif.c translation starts
246:            private int bitOffset = 0; // Bit Offset of next code
247:            private int XC = 0; // Output X coords of current pixel
248:            private int YC = 0; // Output Y coords of curent pixel
249:            private int pass = 0; // Used by output routine if interlaced pixels
250:            private int ptr = 0; // Just an index
251:            private int oldYC = -1; // Here to remember YC
252:
253:            private byte r[] = new byte[256]; // red colormap value
254:            private byte g[] = new byte[256]; // green colormap value
255:            private byte b[] = new byte[256]; // blue colormap, value
256:            private int transparentIndex = -1; // index of the transparent color in the index array
257:
258:            // private int            intPixels [];       // image data in RGB model
259:            // we don't really need this one, since we only compute the bytePixels Array
260:
261:            // private String     fullInfo;              // Format: field in info box
262:            // private String     shortInfo;             // short format info
263:            // private String     comment;               // comment text
264:
265:            private final static String id87 = "GIF87a";
266:            private final static String id89 = "GIF89a";
267:
268:            private final static short EGA_PALETTE[][] = { { 0, 0, 0 },
269:                    { 0, 0, 128 }, { 0, 128, 0 }, { 0, 128, 128 },
270:                    { 128, 0, 0 }, { 128, 0, 128 }, { 128, 128, 0 },
271:                    { 200, 200, 200 }, { 100, 100, 100 }, { 100, 100, 255 },
272:                    { 100, 255, 100 }, { 100, 255, 255 }, { 255, 100, 100 },
273:                    { 255, 100, 255 }, { 255, 255, 100 }, { 255, 255, 255 } };
274:
275:            private final static byte EXTENSION = 0x21;
276:            private final static byte IMAGESEP = 0x2c;
277:            private final static byte TRAILER = 0x3b;
278:            private final static byte INTERLACEMASK = 0x40;
279:            private final static byte COLORMAPMASK = (byte) 0x80;
280:
281:            private void loadGIF(InputStream input) throws IOException {
282:                if (!(input instanceof  BufferedInputStream))
283:                    input = new BufferedInputStream(input);
284:
285:                // Use a DataInputStream to have EOFException if file  is corrupted
286:                DataInputStream dataInput = new DataInputStream(input);
287:
288:                // initialize variables
289:                bitOffset = XC = YC = pass = 0;
290:                boolean gotimage = false;
291:                boolean gif89 = false;
292:
293:                byte[] idBytes = new byte[6];
294:                for (int i = 0; i < 6; i++)
295:                    idBytes[i] = dataInput.readByte();
296:
297:                String id = new String(idBytes);
298:                if (id.equals(id87))
299:                    gif89 = false;
300:                else if (id.equals(id89))
301:                    gif89 = true;
302:                else
303:                    warning(input, "not a GIF file");
304:
305:                // Get variables from the GIF screen descriptor
306:                byte aByte = dataInput.readByte();
307:                int screenWidth = ((int) aByte & 0xFF) + 0x100
308:                        * (dataInput.readByte() & 0xFF); // screen dimensions... not used.
309:                aByte = dataInput.readByte();
310:                int screenHeight = ((int) aByte & 0xFF) + 0x100
311:                        * (dataInput.readByte() & 0xFF);
312:
313:                aByte = dataInput.readByte();
314:                boolean hasColormap = (aByte & COLORMAPMASK) != 0;
315:
316:                // Bits per pixel, read from GIF header
317:                int bitsPerPixel = (aByte & 7) + 1;
318:                // Number of colors
319:                colorMapSize = 1 << bitsPerPixel;
320:                // AND mask for data size
321:                bitMask = colorMapSize - 1;
322:
323:                int background = dataInput.readByte() & 0xFF; // background color... not used.
324:
325:                int aspect = dataInput.readByte() & 0xFF;
326:                if (aspect != 0)
327:                    if (!gif89)
328:                        warning(input, "corrupt GIF file (screen descriptor)");
329:
330:                // Read in global colormap.
331:                if (hasColormap)
332:                    for (int i = 0; i < colorMapSize; i++) {
333:                        r[i] = dataInput.readByte();
334:                        g[i] = dataInput.readByte();
335:                        b[i] = dataInput.readByte();
336:                    }
337:                else {
338:                    colorMapSize = 256;
339:                    bitMask = 255;
340:                    // no colormap in GIF file
341:                    // put std EGA palette (repeated 16 times) into colormap, for lack of
342:                    // anything better to do
343:                    for (int i = 0; i < 256; i++) {
344:                        r[i] = (byte) EGA_PALETTE[i & 15][0];
345:                        g[i] = (byte) EGA_PALETTE[i & 15][1];
346:                        b[i] = (byte) EGA_PALETTE[i & 15][2];
347:                    }
348:                }
349:
350:                for (int block = 0; (block = dataInput.readByte() & 0xFF) != TRAILER;)
351:                    if (block == EXTENSION) {
352:                        // possible things at this point are:
353:                        //   an application extension block
354:                        //   a comment extension block
355:                        //   an (optional) graphic control extension block
356:                        //       followed by either an image
357:                        //     or a plaintext extension
358:
359:                        // parse extension blocks
360:                        int fn, blocksize, aspnum, aspden;
361:
362:                        // read extension block
363:                        fn = dataInput.readByte() & 0xFF;
364:
365:                        if (fn == 'R') {
366:                            // GIF87 aspect extension
367:                            int blockSize;
368:
369:                            blocksize = dataInput.readByte() & 0xFF;
370:                            if (blocksize == 2) {
371:                                aspnum = dataInput.readByte();
372:                                aspden = dataInput.readByte();
373:                                if (aspden <= 0 || aspnum <= 0) {
374:                                    aspnum = aspden = 1;
375:                                }
376:                            } else
377:                                dataInput.skipBytes(blocksize);
378:
379:                            while ((blockSize = dataInput.readByte() & 0xFF) > 0)
380:                                // eat any following data subblocks
381:                                dataInput.skipBytes(blockSize);
382:                        } else if (fn == 0xFE) {
383:                            // Comment Extension
384:                            // We don't really need them, so let's eat that too :
385:                            int blockSize;
386:                            while ((blockSize = dataInput.readByte() & 0xFF) > 0)
387:                                dataInput.skipBytes(blockSize);
388:
389:                            /* This part was in the original GIFReader but we don't use the GIF comments
390:                            // to read the comments :
391:                            for (int blockSize = 0; (blockSize = dataInput.readByte () & 0xFF) != 0; )
392:                            {
393:                                byte commentBytes [] = new byte [blockSize];
394:                                for (int i = 0; i < blockSize; i++)
395:                                    commentBytes [i] = dataInput.readByte ();
396:
397:                                if (comment != null)
398:                                    comment += "\n" + new String (commentBytes);
399:                                else
400:                                    comment = new String (commentBytes);
401:                            }
402:                             */
403:                        } else if (fn == 0x01) {
404:                            // PlainText Extension
405:                            int blockSize = dataInput.readByte() & 0xFF;
406:                            int tgLeft = dataInput.readByte() & 0xFF;
407:                            tgLeft += (dataInput.readByte() & 0xFF) << 8;
408:                            int tgTop = dataInput.readByte() & 0xFF;
409:                            tgTop += (dataInput.readByte() & 0xFF) << 8;
410:                            int tgWidth = dataInput.readByte() & 0xFF;
411:                            tgWidth += (dataInput.readByte() & 0xFF) << 8;
412:                            int tgHeight = dataInput.readByte() & 0xFF;
413:                            tgHeight += (dataInput.readByte() & 0xFF) << 8;
414:                            int cWidth = dataInput.readByte() & 0xFF;
415:                            int cHeight = dataInput.readByte() & 0xFF;
416:                            int fg = dataInput.readByte() & 0xFF;
417:                            int bg = dataInput.readByte() & 0xFF;
418:
419:                            dataInput.skipBytes(blockSize - 12); // read rest of first subblock
420:
421:                            // read (and ignore) data sub-blocks
422:                            while ((blockSize = dataInput.readByte() & 0xFF) != 0)
423:                                dataInput.skipBytes(blockSize);
424:                        } else if (fn == 0xF9) {
425:                            // Graphic Control Extension
426:                            for (int blockSize = 0; (blockSize = dataInput
427:                                    .readByte() & 0xFF) != 0;)
428:                                // Added transparent GIF management here
429:                                if (blockSize == 4) {
430:                                    int ext1 = (dataInput.readByte() & 0xFF);
431:                                    int ext2 = (dataInput.readByte() & 0xFF);
432:                                    int ext3 = (dataInput.readByte() & 0xFF);
433:                                    int ext4 = (dataInput.readByte() & 0xFF);
434:
435:                                    // v2.1.1 Changed condition for transparent GIFs
436:                                    if ((ext1 & 0x01) != 0)
437:                                        transparentIndex = ext4;
438:                                } else
439:                                    dataInput.skipBytes(blockSize);
440:                        } else if (fn == 0xFF) {
441:                            // Application Extension
442:                            // read (and ignore) data sub-blocks
443:                            for (int blockSize = 0; (blockSize = dataInput
444:                                    .readByte() & 0xFF) != 0;)
445:                                dataInput.skipBytes(blockSize);
446:                        } else {
447:                            // unknown extension
448:                            // read (and ignore) data sub-blocks
449:                            for (int blockSize = 0; (blockSize = dataInput
450:                                    .readByte() & 0xFF) != 0;)
451:                                dataInput.skipBytes(blockSize);
452:                        }
453:                    } else if (block == IMAGESEP) {
454:                        if (gotimage) {
455:                            // just skip over remaining images
456:                            dataInput.skipBytes(8); // left position
457:                            // top position
458:                            // width
459:                            // height
460:                            int misc = dataInput.readByte() & 0xFF; // misc. bits
461:
462:                            if ((misc & 0x80) != 0)
463:                                // image has local colormap.  skip it
464:                                for (int i = 0; i < 1 << ((misc & 7) + 1); i++)
465:                                    dataInput.skipBytes(3);
466:
467:                            dataInput.skipBytes(1); // minimum code size
468:
469:                            // skip image data sub-blocks
470:                            for (int blockSize = 0; (blockSize = dataInput
471:                                    .readByte() & 0xFF) != 0;)
472:                                dataInput.skipBytes(blockSize);
473:                        } else {
474:                            readImage(dataInput, bitsPerPixel, bitMask,
475:                                    hasColormap, gif89);
476:                            gotimage = true;
477:                        }
478:                    } else {
479:                        // unknown block type
480:                        // don't mention bad block if file was trunc'd, as it's all bogus
481:                        String str = "Unknown block type (0x"
482:                                + Integer.toString(block, 16) + ")";
483:                        warning(input, str);
484:                        break;
485:                    }
486:
487:                if (!gotimage)
488:                    warning(input, "no image data found in GIF file");
489:            }
490:
491:            private void readImage(DataInputStream dataInput, int bitsPerPixel,
492:                    int bitMask, boolean hasColormap, boolean gif89)
493:                    throws IOException {
494:                int npixels = 0;
495:                int maxpixels = 0;
496:
497:                // read in values from the image descriptor
498:                byte aByte = dataInput.readByte();
499:                int leftOffset = (aByte & 0xFF) + 0x100
500:                        * (dataInput.readByte() & 0xFF);
501:                aByte = dataInput.readByte();
502:                int topOffset = (aByte & 0xFF) + 0x100
503:                        * (dataInput.readByte() & 0xFF);
504:                aByte = dataInput.readByte();
505:                width = (aByte & 0xFF) + 0x100 * (dataInput.readByte() & 0xFF);
506:                aByte = dataInput.readByte();
507:                height = (aByte & 0xFF) + 0x100 * (dataInput.readByte() & 0xFF);
508:
509:                int misc = dataInput.readByte(); // miscellaneous bits (interlace, local cmap)
510:                boolean interlace = (misc & INTERLACEMASK) != 0;
511:
512:                if ((misc & 0x80) != 0)
513:                    for (int i = 0; i < 1 << ((misc & 7) + 1); i++) {
514:                        r[i] = dataInput.readByte();
515:                        g[i] = dataInput.readByte();
516:                        b[i] = dataInput.readByte();
517:                    }
518:
519:                if (!hasColormap && (misc & 0x80) == 0) {
520:                    // no global or local colormap
521:                }
522:
523:                // Start reading the raster data. First we get the intial code size
524:                // and compute decompressor constant values, based on this code size.
525:
526:                // Code size, read from GIF header
527:                int codeSize = dataInput.readByte() & 0xFF;
528:
529:                int clearCode = (1 << codeSize); // GIF clear code
530:                int EOFCode = clearCode + 1; // GIF end-of-information code
531:                int firstFree = clearCode + 2; // First free code, generated per GIF spec
532:                int freeCode = firstFree; // Decompressor,next free slot in hash table
533:
534:                // The GIF spec has it that the code size is the code size used to
535:                // compute the above values is the code size given in the file, but the
536:                // code size used in compression/decompression is the code size given in
537:                // the file plus one. (thus the ++).
538:                codeSize++;
539:                int initCodeSize = codeSize; // Starting code size, used during Clear
540:                int maxCode = (1 << codeSize); // limiting value for current code size
541:                int readMask = maxCode - 1; // Code AND mask for current code size
542:
543:                // UNBLOCK:
544:                // Read the raster data.  Here we just transpose it from the GIF array
545:                // to the raster array, turning it from a series of blocks into one long
546:                // data stream, which makes life much easier for readCode ().
547:                ByteArrayOutputStream bos = new ByteArrayOutputStream(10000);
548:                byte[] raster = null;
549:                for (int blockSize = 0; (blockSize = dataInput.readByte() & 0xFF) != 0;) {
550:                    while (blockSize-- > 0) {
551:                        bos.write(dataInput.readByte());
552:                    }
553:                }
554:                raster = bos.toByteArray();
555:
556:                // Allocate the 'pixels'
557:                maxpixels = width * height;
558:                bytePixels = new byte[maxpixels];
559:                int picptr = 0;
560:
561:                // The hash table used by the decompressor
562:                int prefix[] = new int[4096];
563:                int suffix[] = new int[4096];
564:                // An output array used by the decompressor
565:                int outCode[] = new int[4097];
566:                int outCount = 0; // Decompressor output 'stack count'
567:
568:                int currentCode; // Decompressor variables
569:                int oldCode = 0;
570:                int inCode;
571:                int finChar = 0;
572:                // Decompress the file, continuing until you see the GIF EOF code.
573:                // One obvious enhancement is to add checking for corrupt files here.
574:                int code = readCode(dataInput, raster, codeSize, readMask);
575:                while (code != EOFCode) {
576:                    // Clear code sets everything back to its initial value, then reads the
577:                    // immediately subsequent code as uncompressed data.
578:                    if (code == clearCode) {
579:                        codeSize = initCodeSize;
580:                        maxCode = (1 << codeSize);
581:                        readMask = maxCode - 1;
582:                        freeCode = firstFree;
583:                        code = readCode(dataInput, raster, codeSize, readMask);
584:                        currentCode = oldCode = code;
585:                        finChar = currentCode & bitMask;
586:                        if (!interlace)
587:                            bytePixels[picptr++] = (byte) finChar;
588:                        else
589:                            doInterlace(finChar);
590:                        npixels++;
591:                    } else {
592:                        // If not a clear code, must be data: save same as currentCode and inCode
593:
594:                        // if we're at maxcode and didn't get a clear, stop loading
595:                        if (freeCode >= 4096)
596:                            break;
597:
598:                        currentCode = inCode = code;
599:
600:                        // If greater or equal to freeCode, not in the hash table yet;
601:                        // repeat the last character decoded
602:                        if (currentCode >= freeCode) {
603:                            currentCode = oldCode;
604:                            if (outCount > 4096)
605:                                break;
606:                            outCode[outCount++] = finChar;
607:                        }
608:
609:                        // Unless this code is raw data, pursue the chain pointed to by currentCode
610:                        // through the hash table to its end; each code in the chain puts its
611:                        // associated output code on the output queue.
612:                        while (currentCode > bitMask) {
613:                            if (outCount > 4096)
614:                                break; // corrupt file
615:                            outCode[outCount++] = suffix[currentCode];
616:                            currentCode = prefix[currentCode];
617:                        }
618:
619:                        if (outCount > 4096)
620:                            break;
621:
622:                        // The last code in the chain is treated as raw data.
623:                        finChar = currentCode & bitMask;
624:                        outCode[outCount++] = finChar;
625:
626:                        // Now we put the data out to the Output routine.
627:                        // It's been stacked LIFO, so deal with it that way...
628:
629:                        // safety thing:  prevent exceeding range of 'bytePixels'
630:                        if (npixels + outCount > maxpixels)
631:                            outCount = maxpixels - npixels;
632:
633:                        npixels += outCount;
634:                        if (!interlace)
635:                            for (int i = outCount - 1; i >= 0; i--)
636:                                bytePixels[picptr++] = (byte) outCode[i];
637:                        else
638:                            for (int i = outCount - 1; i >= 0; i--)
639:                                doInterlace(outCode[i]);
640:                        outCount = 0;
641:
642:                        // Build the hash table on-the-fly. No table is stored in the file.
643:                        prefix[freeCode] = oldCode;
644:                        suffix[freeCode] = finChar;
645:                        oldCode = inCode;
646:
647:                        // Point to the next slot in the table.  If we exceed the current
648:                        // maxCode value, increment the code size unless it's already 12.  If it
649:                        // is, do nothing: the next code decompressed better be CLEAR
650:
651:                        freeCode++;
652:                        if (freeCode >= maxCode) {
653:                            if (codeSize < 12) {
654:                                codeSize++;
655:                                maxCode *= 2;
656:                                readMask = (1 << codeSize) - 1;
657:                            }
658:                        }
659:                    }
660:
661:                    code = readCode(dataInput, raster, codeSize, readMask);
662:                    if (npixels >= maxpixels)
663:                        break;
664:                }
665:
666:                if (npixels != maxpixels) {
667:                    if (!interlace) // clear.EOBuffer
668:                        for (int i = 0; i < maxpixels - npixels; i++)
669:                            bytePixels[npixels + i] = 0;
670:                }
671:
672:                /* This was part of the original GIFReader, used to make an RGB Image
673:                // But we don't need the following since we only compute the bytePixels Array
674:                // fill in the GifImage structure
675:
676:                intPixels = new int [bytePixels.length];
677:                for (int i = 0; i < bytePixels.length; i++)
678:                    intPixels [i] =      transparentIndex > 0
679:                            && ((bytePixels [i] & 0xFF) == transparentIndex)
680:                            ? 0
681:                            :   0xFF000000
682:                              | ((r [bytePixels [i]] & 0xFF) << 16)
683:                              | ((g [bytePixels [i]] & 0xFF) << 8)
684:                              |  (b [bytePixels [i]] & 0xFF);
685:                 */
686:
687:                // We don't need any info or comments, really, so let's get rid of this
688:                /*
689:                fullInfo =   "GIF" +  ((gif89) ? "89" : "87")
690:                                   + ", " + bitsPerPixel + " bit" + ((bitsPerPixel == 1) ? "" : "s") + "per pixel, "
691:                                   + (interlace ? "" : "non-") + "interlaced.";
692:
693:                shortInfo = width + "x" + height + " GIF" + ((gif89) ? "89" : "87");
694:                 */
695:
696:                // comment gets handled in main LoadGIF() block-reader
697:            }
698:
699:            /**
700:             * Fetch the next code from the raster data stream.  The codes can be
701:             * any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
702:             * maintain our location in the raster array as a BIT Offset.  We compute
703:             * the byte Offset into the raster array by dividing this by 8, pick up
704:             * three bytes, compute the bit Offset into our 24-bit chunk, shift to
705:             * bring the desired code to the bottom, then mask it off and return it.
706:             */
707:            private int readCode(DataInputStream input, byte raster[],
708:                    int codeSize, int readMask) throws IOException {
709:                int byteOffset = bitOffset / 8;
710:                int inWordOffset = bitOffset % 8;
711:                // Alan Dix modification to fix raster over-run errors
712:                // int rawCode =   (raster [byteOffset] & 0xFF)
713:                //              + ((raster [byteOffset + 1] & 0xFF) << 8);
714:                int rawCode = (raster[byteOffset] & 0xFF);
715:                if (byteOffset + 1 < raster.length)
716:                    rawCode += ((raster[byteOffset + 1] & 0xFF) << 8);
717:                else if (codeSize + inWordOffset > 8)
718:                    warning(input, "short raster ?  raster.length = "
719:                            + raster.length + ", codeSize = " + codeSize
720:                            + ", readMask = " + readMask);
721:                // end of modification
722:
723:                if (codeSize >= 8 && byteOffset + 2 < raster.length)
724:                    rawCode += (raster[byteOffset + 2] & 0xFF) << 16;
725:                rawCode >>= (bitOffset % 8);
726:                bitOffset += codeSize;
727:                return rawCode & readMask;
728:            }
729:
730:            private void doInterlace(int index) {
731:                if (oldYC != YC) {
732:                    ptr = YC * width;
733:                    oldYC = YC;
734:                }
735:
736:                if (YC < height)
737:                    bytePixels[ptr++] = (byte) index;
738:
739:                // Update the X-coordinate, and if it overflows, update the Y-coordinate
740:                if (++XC == width) {
741:                    // deal with the interlace as described in the GIF
742:                    // spec.  Put the decoded scan line out to the screen if we haven't gone
743:                    // past the bottom of it
744:                    XC = 0;
745:
746:                    switch (pass) {
747:                    case 0:
748:                        YC += 8;
749:                        if (YC >= height) {
750:                            pass++;
751:                            YC = 4;
752:                        }
753:                        break;
754:
755:                    case 1:
756:                        YC += 8;
757:                        if (YC >= height) {
758:                            pass++;
759:                            YC = 2;
760:                        }
761:                        break;
762:
763:                    case 2:
764:                        YC += 4;
765:                        if (YC >= height) {
766:                            pass++;
767:                            YC = 1;
768:                        }
769:                        break;
770:
771:                    case 3:
772:                        YC += 2;
773:                        break;
774:
775:                    default:
776:                        break;
777:                    }
778:                }
779:            }
780:
781:            private void warning(InputStream input, String st)
782:                    throws IOException {
783:                throw new IOException("Warning ! " + input + " : " + st);
784:            }
785:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.