Source Code Cross Referenced for AnimGifEncoder.java in  » Search-Engine » yacy » de » anomic » ymage » 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 » Search Engine » yacy » de.anomic.ymage 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  (C)2000 by F. Jalvingh, Mumble Internet Services
0003:         *  For questions and the like: fjalvingh@bigfoot.com
0004:         *
0005:         *  Compression part (C)1996,1998 by Jef Poskanzer <jef@acme.com>. All rights reserved.
0006:         *
0007:         *  This software is placed in the public domain. You are free to use this
0008:         *  software for any means while respecting the above copyright.
0009:         *
0010:         *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0011:         *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0012:         *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0013:         *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0014:         *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0015:         *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0016:         *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0017:         *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0018:         *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0019:         *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0020:         *  SUCH DAMAGE.
0021:         *
0022:         *  Optimizations by Jal:
0023:         *  ---------------------
0024:         *  Initial:    Coded RLE code for building the 8-bit color table.
0025:         *  6dec00:     Changed code to remove extraneous if's and unrolled some calls.
0026:         *              Replaced color hashtable with local specialized variant.
0027:         *  7dec00:     Made specialized direct buffer access versions for BufferedImage
0028:         *              images..
0029:         *
0030:         */
0031:
0032:        // very slightly adopted by Michael Christen, 12.12.2007
0033:        // - removed unused variables
0034:        // - replaced old java classes by new one
0035:        package de.anomic.ymage;
0036:
0037:        import java.awt.Canvas;
0038:        import java.awt.Image;
0039:        import java.awt.MediaTracker;
0040:        import java.awt.image.BufferedImage;
0041:        import java.awt.image.ColorModel;
0042:        import java.awt.image.DataBuffer;
0043:        import java.awt.image.DataBufferByte;
0044:        import java.awt.image.DataBufferInt;
0045:        import java.awt.image.DataBufferShort;
0046:        import java.awt.image.IndexColorModel;
0047:        import java.awt.image.PixelGrabber;
0048:        import java.awt.image.PixelInterleavedSampleModel;
0049:        import java.awt.image.Raster;
0050:        import java.awt.image.SampleModel;
0051:        import java.awt.image.SinglePixelPackedSampleModel;
0052:        import java.io.File;
0053:        import java.io.FileNotFoundException;
0054:        import java.io.FileOutputStream;
0055:        import java.io.IOException;
0056:        import java.io.OutputStream;
0057:        import java.util.ArrayList;
0058:
0059:        /**
0060:         *  <p>This class can be used to write an animated GIF file by combining several
0061:         *  images. It is loosely based on the Acme GIF encoder.</p>
0062:         *
0063:         *  <p>The characteristics of the generated Gif 89a image are:
0064:         *  <ul>
0065:         *      <li>Only a single color table is used (no local tables). This table is
0066:         *          created by combining the colors from all other images.</li>
0067:         *  </ul>
0068:         *  </p>
0069:         *
0070:         *  @author F. Jalvingh
0071:         */
0072:        public class AnimGifEncoder {
0073:            /** The default interlacing indicator */
0074:            private boolean m_default_interlace = false;
0075:
0076:            /** The default delay time, */
0077:            private int m_default_delay = 100;
0078:
0079:            /** Set when looping the set is requested. */
0080:            private boolean m_loop = true;
0081:
0082:            /** The outputstream to write the image to. */
0083:            private OutputStream m_os;
0084:
0085:            /** The (current) list of images to embed in the GIF */
0086:            private ArrayList<AnIma> m_ima_ar;
0087:
0088:            /** The total width and height of all combined images */
0089:            private int m_w, m_h;
0090:
0091:            /** The canvas is used to proprly track images. */
0092:            private Canvas m_cv;
0093:
0094:            /** The index for the "transparant" color. -1 if no transparant found. */
0095:            private short m_transparant_ix = -1;
0096:
0097:            /** The index (palette table entry #) to use for the NEXT color encountered */
0098:            private short m_color_ix;
0099:
0100:            /** The #of bits to use (2log m_color_ix). */
0101:            private int m_color_bits;
0102:
0103:            /// Temp optimization inhibition.
0104:            public boolean m_no_opt;
0105:
0106:            /**
0107:             *  This constructor creates an empty default codec.
0108:             */
0109:            public AnimGifEncoder(OutputStream os) {
0110:                m_os = os;
0111:            }
0112:
0113:            /**
0114:             *  Creates a codec and specify interlace (not implemented yet).
0115:             */
0116:            public AnimGifEncoder(OutputStream os, boolean interlace) {
0117:                m_os = os;
0118:                m_default_interlace = interlace;
0119:            }
0120:
0121:            /**
0122:             *  <p>For animated GIF's the default is to LOOP all images in the GIF file.
0123:             *  This means that after displaying all images in the file the first image
0124:             *  is redisplayed ad infinitum.</p>
0125:             *  <p>To prevent the images from looping call setLoop(false) before calling
0126:             *  the encode() method.
0127:             *  </p>
0128:             *  <p>The current version does not allow the number of repetitions to be
0129:             *  specified.
0130:             *  </p>
0131:             */
0132:            public void setLoop(boolean loop) {
0133:                m_loop = loop;
0134:            }
0135:
0136:            /**
0137:             *  Releases ALL cached resources.
0138:             */
0139:            public void flush() {
0140:                //-- 1. The basic stuff
0141:                m_ccolor_ar = null;
0142:                m_cindex_ar = null;
0143:                m_cv = null;
0144:                m_ima_ar = null;
0145:
0146:                //-- 2. The compressor.
0147:                m_curr_pixels = null;
0148:                htab = null;
0149:                codetab = null;
0150:                accum = null;
0151:            }
0152:
0153:            /*------------------------------------------------------------------*/
0154:            /*  CODING: Adding images to combine into the animated GIF...       */
0155:            /*------------------------------------------------------------------*/
0156:            /**
0157:             *  Adds the specified image to the list of images. While adding, the
0158:             *  image is converted to pixels; each color is added to the color table
0159:             *  and the resulting 8-bit pixelset is saved. After this call the image
0160:             *  is released, and only the pixelset remains until the encode call is
0161:             *  made. Calling encode will release the pixelset.
0162:             */
0163:            public void add(Image ima, int delaytime, boolean interlace,
0164:                    int px, int py) throws IOException {
0165:                AnIma ai = new AnIma();
0166:                ai.m_delay = delaytime;
0167:                ai.m_interlace = interlace;
0168:                ai.m_x = px;
0169:                ai.m_y = py;
0170:
0171:                //-- Add to the list of images to embed,
0172:                if (m_ima_ar == null) // First call?
0173:                {
0174:                    m_ccolor_ar = new int[CHSIZE]; // New colors code table
0175:                    m_cindex_ar = new short[CHSIZE];
0176:                    m_ima_ar = new ArrayList<AnIma>(10); // Contains all component images,
0177:                    m_cv = new Canvas();
0178:                }
0179:                m_ima_ar.add(ai);
0180:
0181:                //-- Pre-scan the image!!
0182:                if (!m_no_opt)
0183:                    preCode(ai, ima); // Convert to 8bit and make palette
0184:                else
0185:                    precodeImage(ai, ima);
0186:            }
0187:
0188:            /**
0189:             *  Adds the specified image to the list of images.
0190:             */
0191:            public void add(Image ima) throws IOException {
0192:                add(ima, m_ima_ar == null ? 0 : m_default_delay,
0193:                        m_default_interlace, 0, 0);
0194:            }
0195:
0196:            /**
0197:             *  Adds the specified image to the list of images.
0198:             */
0199:            public void add(Image ima, int delay) throws IOException {
0200:                add(ima, delay, m_default_interlace, 0, 0);
0201:            }
0202:
0203:            /*------------------------------------------------------------------*/
0204:            /*  CODING: I/O to the file - helpers...                            */
0205:            /*------------------------------------------------------------------*/
0206:            /**
0207:             *  Writes a string as a #of bytes to the output stream.
0208:             */
0209:            private void utStr(String str) throws IOException {
0210:                byte[] buf = str.getBytes();
0211:                m_os.write(buf);
0212:            }
0213:
0214:            private void utWord(int val) throws IOException {
0215:                utByte((byte) (val & 0xff));
0216:                utByte((byte) ((val >> 8) & 0xff));
0217:            }
0218:
0219:            private void utByte(byte b) throws IOException {
0220:                m_os.write(b);
0221:            }
0222:
0223:            /*------------------------------------------------------------------*/
0224:            /*  CODING: Starting the encode process...                          */
0225:            /*------------------------------------------------------------------*/
0226:            /**
0227:             *  Creates the GIF file from all images added to the encoder.
0228:             */
0229:            public void encode() throws IOException {
0230:                //-- Check validity,
0231:                if (m_ima_ar == null || m_ima_ar.size() == 0)
0232:                    throw new IOException("No images added.");
0233:
0234:                //-- Init the compressor's tables
0235:                htab = new int[HSIZE];
0236:                codetab = new int[HSIZE];
0237:                accum = new byte[256];
0238:
0239:                //-- Write the GIF header now,
0240:                genHeader();
0241:
0242:                /*
0243:                 *  Traverse the data for each image. This determines the actual color
0244:                 *  table and the complete output size.
0245:                 */
0246:                for (int i = 0; i < m_ima_ar.size(); i++) {
0247:                    AnIma ai = (AnIma) m_ima_ar.get(i);
0248:                    genImage(ai);
0249:                    ai.m_rgb = null;
0250:                }
0251:                genTrailer();
0252:                flush();
0253:            }
0254:
0255:            /*--------------------------------------------------------------*/
0256:            /*  CODING: Color table code & specialized color hashtable.     */
0257:            /*--------------------------------------------------------------*/
0258:            /*
0259:             *  This is a hashtable mapping (int, byte). The first int is the actual
0260:             *  color as gotten from the image. The byte is the index color in the
0261:             *  colormap for the entry.
0262:             *  We need to find (byte) by indexing with (int) VERY quicky.
0263:             *  Furthermore we already know that the table will at max hold 256 entries.
0264:             *
0265:             *  Since all colors >= 0 are transparant, we use (int) = 0 as the empty
0266:             *  case.
0267:             *
0268:             *  This hashtable uses the same hash mechanism as the LZH compressor: a
0269:             *  double hash without chaining.
0270:             */
0271:            static private final int CHSIZE = 1023;
0272:
0273:            /// The color hashtable's COLOR table (int rcolors)
0274:            private int[] m_ccolor_ar;
0275:
0276:            /// The color hashtable's INDEX table (byte index)
0277:            private short[] m_cindex_ar;
0278:
0279:            /**
0280:             *  This retrieves the index for a color code from the color hash. If the
0281:             *  color doesn't exist it is added to the hash table. This uses the double
0282:             *  hash mechanism described above. If this call causes >255 colors to be
0283:             *  stored it throws a too many colors exception.
0284:             *  The function returns the index code for the color.
0285:             */
0286:            private short findColorIndex(int color) throws IOException {
0287:                //-- 1. Primary hash..
0288:                int i = (color & 0x7fffffff) % CHSIZE;
0289:
0290:                if (m_ccolor_ar[i] == color) // Bucket found?
0291:                    return m_cindex_ar[i];
0292:
0293:                //-- 2. No match. If the bucket is not empty do the 2nd hash,
0294:                if (m_ccolor_ar[i] != 0) // Bucket is full?
0295:                {
0296:                    //-- This was a clash. Locate a new bucket & look for another match!
0297:                    int disp = CHSIZE - i;
0298:                    do {
0299:                        i -= disp;
0300:                        if (i < 0)
0301:                            i += CHSIZE;
0302:                        if (m_ccolor_ar[i] == color) // Found in 2nd hash?
0303:                            return m_cindex_ar[i]; // Then return it.
0304:                    } while (m_ccolor_ar[i] != 0); // Loop till empty bucket.
0305:                }
0306:
0307:                //-- 3. Empty bucket found: add this there as a new index.
0308:                if (m_color_ix >= 256)
0309:                    throw new IOException(
0310:                            "More than 255 colors in this GIF are not allowed.");
0311:                m_ccolor_ar[i] = color;
0312:                m_cindex_ar[i] = (short) m_color_ix;
0313:                return m_color_ix++;
0314:            }
0315:
0316:            /*--------------------------------------------------------------*/
0317:            /*  CODING: Optimized pixel grabbers...                         */
0318:            /*--------------------------------------------------------------*/
0319:            /**
0320:             *  Checks if the image lies in the current complete image, else it extends
0321:             *  the source image.
0322:             */
0323:            private void checkTotalSize(AnIma ai) {
0324:                int t;
0325:
0326:                t = ai.m_w + ai.m_x; // Get end-X of image,
0327:                if (t > m_w)
0328:                    m_w = t; // Adjust complete GIF's size
0329:                t = ai.m_h + ai.m_y; // Get total height
0330:                if (t > m_h)
0331:                    m_h = t; // Adjust if higher,
0332:            }
0333:
0334:            /*--------------------------------------------------------------*/
0335:            /*  CODING: The precoder translates all to 8bit indexed...      */
0336:            /*--------------------------------------------------------------*/
0337:            /**
0338:             *  Traverse this image, and determine it's characteristics. It adds all
0339:             *  used colors to the color table and determines the completed size of
0340:             *  the thing. The image is converted to an 8-bit pixelmap where each pixel
0341:             *  indexes the generated color table.
0342:             *  This function tries to get the fastest access to the pixel data for
0343:             *  several types of BufferedImage. This should enhance the encoding speed
0344:             *  by preventing the loop thru the entire generalized Raster and ColorModel
0345:             *  method....
0346:             *  All precode methods build a color table containing all colors used in
0347:             *  the image, and an 8-bit "image" containing, for each pixel, the index
0348:             *  into that color table. They also set the transparant color to use.
0349:             */
0350:            private void preCode(AnIma ai, Image ima) throws IOException {
0351:                //-- Call the appropriate encoder depending on the image type.
0352:                if (ima instanceof  BufferedImage)
0353:                    precodeBuffered(ai, (BufferedImage) ima);
0354:                else
0355:                    precodeImage(ai, ima);
0356:            }
0357:
0358:            /**
0359:             *  Tries to decode a buffered image in an optimal way. It checks to see
0360:             *  if it knows the BufferedImage type and calls the appropriate quick
0361:             *  decoder. If the image is not implemented we fall back to the generic
0362:             *  method.
0363:             */
0364:            private void precodeBuffered(AnIma ai, BufferedImage bi)
0365:                    throws IOException {
0366:                //-- 1. Handle all shared tasks...
0367:                ai.m_w = bi.getWidth();
0368:                ai.m_h = bi.getHeight();
0369:                if (ai.m_h == 0 || ai.m_w == 0)
0370:                    return;
0371:                checkTotalSize(ai);
0372:
0373:                //-- 2. Optimize for known types...
0374:                boolean done = false;
0375:                int bt = bi.getType();
0376:                switch (bt) {
0377:                case BufferedImage.TYPE_BYTE_INDEXED:
0378:                    done = precodeByteIndexed(ai, bi);
0379:                    break;
0380:                case BufferedImage.TYPE_INT_BGR:
0381:                    done = precodeIntPacked(ai, bi);
0382:                    break;
0383:                case BufferedImage.TYPE_INT_ARGB:
0384:                    done = precodeIntPacked(ai, bi);
0385:                    break;
0386:                case BufferedImage.TYPE_USHORT_555_RGB:
0387:                    done = precodeShortPacked(ai, bi);
0388:                    break;
0389:                case BufferedImage.TYPE_USHORT_565_RGB:
0390:                    done = precodeShortPacked(ai, bi);
0391:                    break;
0392:                case BufferedImage.TYPE_INT_RGB:
0393:                    done = precodeIntPacked(ai, bi);
0394:                    break;
0395:                }
0396:
0397:                if (done)
0398:                    return;
0399:
0400:                precodeImage(ai, bi);
0401:            }
0402:
0403:            private int getBiOffset(Raster ras, PixelInterleavedSampleModel sm,
0404:                    int x, int y) {
0405:                return (y - ras.getSampleModelTranslateY())
0406:                        * sm.getScanlineStride() + x
0407:                        - ras.getSampleModelTranslateX();
0408:            }
0409:
0410:            private int getBiOffset(Raster ras,
0411:                    SinglePixelPackedSampleModel sm, int x, int y) {
0412:                return (y - ras.getSampleModelTranslateY())
0413:                        * sm.getScanlineStride() + x
0414:                        - ras.getSampleModelTranslateX();
0415:            }
0416:
0417:            /*--------------------------------------------------------------*/
0418:            /*  CODING: BufferedImage.TYPE_BYTE_INDEXED..                   */
0419:            /*--------------------------------------------------------------*/
0420:            /**
0421:             *  Encodes TYPE_BYTE_INDEXED images.
0422:             */
0423:            private boolean precodeByteIndexed(AnIma ai, BufferedImage bi)
0424:                    throws IOException {
0425:                //-- Get the colormodel, the raster, the databuffer and the samplemodel
0426:                ColorModel tcm = bi.getColorModel();
0427:                if (!(tcm instanceof  IndexColorModel))
0428:                    return false;
0429:                IndexColorModel cm = (IndexColorModel) tcm;
0430:
0431:                Raster ras = bi.getRaster();
0432:                SampleModel tsm = ras.getSampleModel();
0433:                if (!(tsm instanceof  PixelInterleavedSampleModel))
0434:                    return false;
0435:                PixelInterleavedSampleModel sm = (PixelInterleavedSampleModel) tsm;
0436:
0437:                DataBuffer dbt = ras.getDataBuffer();
0438:                if (dbt.getDataType() != DataBuffer.TYPE_BYTE)
0439:                    return false;
0440:                if (dbt.getNumBanks() != 1)
0441:                    return false;
0442:                DataBufferByte db = (DataBufferByte) dbt;
0443:
0444:                //-- Prepare the color mapping
0445:                short[] map = new short[256]; // Alternate lookup table
0446:                for (int i = 0; i < 256; i++)
0447:                    // Set all entries to unused,
0448:                    map[i] = -1;
0449:
0450:                /*
0451:                 *  Prepare the run: get all constants e.a. The mechanism runs thru
0452:                 *  all pixels by traversing each X scanline, then moving to the next
0453:                 *  one. One fun thing: we only have to COPY all pixels, since we're
0454:                 *  already byte-packed.
0455:                 */
0456:                int endoff = ai.m_w * ai.m_h; // Output image size,
0457:                byte[] par = new byte[endoff]; // Byte-indexed output array,
0458:                int doff = 0; // Destination offset,
0459:
0460:                //-- source
0461:                int soff = getBiOffset(ras, sm, 0, 0);
0462:                byte[] px = db.getData(0); // Get the pixelset,
0463:                int esoff = getBiOffset(ras, sm, ai.m_w - 1, ai.m_h - 1); // calc end offset,
0464:                int iw = sm.getScanlineStride(); // Increment width = databuf's width
0465:
0466:                while (soff < esoff) { // For all scan lines,
0467:
0468:                    int xe = soff + ai.m_w; // End for this line
0469:                    while (soff < xe) { // While within this line
0470:                        //-- (continue) collect a run,
0471:                        int rs = soff; // Save run start
0472:                        byte rcolor = px[soff++]; // First color
0473:                        while (soff < xe && px[soff] == rcolor)
0474:                            // Run till eoln or badclor
0475:                            soff++;
0476:
0477:                        //-- Run ended. Map the input index to the GIF's index,
0478:                        short ii = map[rcolor + 0x80];
0479:                        if (ii == -1) { // Unknown map?
0480:                            //-- New color. Get it's translated RGB value,
0481:                            int rix = (int) rcolor & 0xff; // Translate to unsigned
0482:                            int rgb = cm.getRGB(rix); // Get RGB value for this input index,
0483:                            if (rgb >= 0) { // Transparant color?
0484:                                //-- If there is a transparant color index use it...
0485:                                if (m_transparant_ix < 0) {
0486:                                    //-- First transparant color found- save it,
0487:                                    if (rgb == 0)
0488:                                        rgb = 1; // Zero color protection - req'd for hashtable implementation
0489:                                    m_transparant_ix = findColorIndex(rgb);
0490:                                }
0491:                                ii = m_transparant_ix; // Use trans color to fill
0492:                            } else {
0493:                                //-- Not transparant,
0494:                                ii = findColorIndex(rgb); // Add RGB value to the index,
0495:                            }
0496:                            map[rcolor + 0x80] = ii;
0497:                        }
0498:
0499:                        //-- Always write this run.
0500:                        int dep = doff + (soff - rs); // End output pos
0501:                        byte idx = (byte) ii;
0502:                        while (doff < dep)
0503:                            par[doff++] = idx; // Fill output.
0504:                    }
0505:
0506:                    //-- Prepare for a new line.
0507:                    soff += iw - ai.m_w; // Increment what's left to next line,
0508:                }
0509:
0510:                ai.m_rgb = par; // Save created thing
0511:                return true;
0512:            }
0513:
0514:            /*--------------------------------------------------------------*/
0515:            /*  CODING: BufferedImage.All int packed stuff..                */
0516:            /*--------------------------------------------------------------*/
0517:            /**
0518:             *  Encodes INT pixel-packed images.
0519:             */
0520:            private boolean precodeIntPacked(AnIma ai, BufferedImage bi)
0521:                    throws IOException {
0522:                //-- Get the colormodel, the raster, the databuffer and the samplemodel
0523:                ColorModel cm = bi.getColorModel();
0524:                Raster ras = bi.getRaster();
0525:                SampleModel tsm = ras.getSampleModel();
0526:                if (!(tsm instanceof  SinglePixelPackedSampleModel))
0527:                    return false;
0528:                SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) tsm;
0529:
0530:                DataBuffer dbt = ras.getDataBuffer();
0531:                if (dbt.getDataType() != DataBuffer.TYPE_INT)
0532:                    return false;
0533:                if (dbt.getNumBanks() != 1)
0534:                    return false;
0535:                DataBufferInt db = (DataBufferInt) dbt;
0536:
0537:                /*
0538:                 *  Prepare the run: get all constants e.a. The mechanism runs thru
0539:                 *  all pixels by traversing each X scanline, then moving to the next
0540:                 *  one. One fun thing: we only have to COPY all pixels, since we're
0541:                 *  already byte-packed.
0542:                 */
0543:                int endoff = ai.m_w * ai.m_h; // Output image size,
0544:                byte[] par = new byte[endoff]; // Byte-indexed output array,
0545:                int doff = 0; // Destination offset,
0546:                byte ii;
0547:
0548:                //-- source
0549:                int soff = getBiOffset(ras, sm, 0, 0);
0550:                int[] px = db.getData(0); // Get the pixelset,
0551:                int esoff = getBiOffset(ras, sm, ai.m_w - 1, ai.m_h - 1); // calc end offset,
0552:                int iw = sm.getScanlineStride(); // Increment width = databuf's width
0553:
0554:                while (soff < esoff) { // For all scan lines,
0555:
0556:                    int xe = soff + ai.m_w; // End for this line
0557:                    while (soff < xe) { // While within this line
0558:                        //-- (continue) collect a run,
0559:                        int rs = soff; // Save run start
0560:                        int rcolor = px[soff++]; // First color
0561:                        while (soff < xe && px[soff] == rcolor)
0562:                            // Run till eoln or badclor
0563:                            soff++;
0564:
0565:                        //-- Run ended. Map the input index to the GIF's index,
0566:                        int rgb = cm.getRGB(rcolor); // Get RGB value for this input index,
0567:                        if (rgb >= 0) { // Transparant color?
0568:                            //-- If there is a transparant color index use it...
0569:                            if (m_transparant_ix < 0) {
0570:                                //-- First transparant color found- save it,
0571:                                if (rgb == 0)
0572:                                    rgb = 1; // Zero color protection - req'd for hashtable implementation
0573:                                m_transparant_ix = findColorIndex(rgb);
0574:                            }
0575:                            ii = (byte) m_transparant_ix; // Use trans color to fill
0576:                        } else {
0577:                            //-- Not transparant,
0578:                            ii = (byte) findColorIndex(rgb); // Add RGB value to the index,
0579:                        }
0580:
0581:                        //-- Always write this run.
0582:                        int dep = doff + (soff - rs); // End output pos
0583:                        while (doff < dep)
0584:                            par[doff++] = ii; // Fill output.
0585:                    }
0586:
0587:                    //-- Prepare for a new line.
0588:                    soff += iw - ai.m_w; // Increment what's left to next line,
0589:
0590:                }
0591:
0592:                ai.m_rgb = par; // Save created thing
0593:                return true;
0594:            }
0595:
0596:            /*--------------------------------------------------------------*/
0597:            /*  CODING: BufferedImage- SHORT type stuff..                   */
0598:            /*--------------------------------------------------------------*/
0599:            /**
0600:             *  Encodes SHORT pixel-packed images.
0601:             */
0602:            private boolean precodeShortPacked(AnIma ai, BufferedImage bi)
0603:                    throws IOException {
0604:                //-- Get the colormodel, the raster, the databuffer and the samplemodel
0605:                ColorModel cm = bi.getColorModel();
0606:                Raster ras = bi.getRaster();
0607:                SampleModel tsm = ras.getSampleModel();
0608:                if (!(tsm instanceof  SinglePixelPackedSampleModel))
0609:                    return false;
0610:                SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel) tsm;
0611:
0612:                DataBuffer dbt = ras.getDataBuffer();
0613:                if (dbt.getDataType() != DataBuffer.TYPE_SHORT)
0614:                    return false;
0615:                if (dbt.getNumBanks() != 1)
0616:                    return false;
0617:                DataBufferShort db = (DataBufferShort) dbt;
0618:
0619:                /*
0620:                 *  Prepare the run: get all constants e.a. The mechanism runs thru
0621:                 *  all pixels by traversing each X scanline, then moving to the next
0622:                 *  one. One fun thing: we only have to COPY all pixels, since we're
0623:                 *  already byte-packed.
0624:                 */
0625:                int endoff = ai.m_w * ai.m_h; // Output image size,
0626:                byte[] par = new byte[endoff]; // Byte-indexed output array,
0627:                int doff = 0; // Destination offset,
0628:                byte ii;
0629:
0630:                //-- source
0631:                int soff = getBiOffset(ras, sm, 0, 0);
0632:                short[] px = db.getData(0); // Get the pixelset,
0633:                int esoff = getBiOffset(ras, sm, ai.m_w - 1, ai.m_h - 1); // calc end offset,
0634:                int iw = sm.getScanlineStride(); // Increment width = databuf's width
0635:
0636:                while (soff < esoff) // For all scan lines,
0637:                {
0638:                    int xe = soff + ai.m_w; // End for this line
0639:                    while (soff < xe) // While within this line
0640:                    {
0641:                        //-- (continue) collect a run,
0642:                        int rs = soff; // Save run start
0643:                        short rcolor = px[soff++]; // First color
0644:                        while (soff < xe && px[soff] == rcolor)
0645:                            // Run till eoln or badclor
0646:                            soff++;
0647:
0648:                        //-- Run ended. Map the input index to the GIF's index,
0649:                        int rgb = cm.getRGB(rcolor); // Get RGB value for this input index,
0650:                        if (rgb >= 0) // Transparant color?
0651:                        {
0652:                            //-- If there is a transparant color index use it...
0653:                            if (m_transparant_ix < 0) {
0654:                                //-- First transparant color found- save it,
0655:                                if (rgb == 0)
0656:                                    rgb = 1; // Zero color protection - req'd for hashtable implementation
0657:                                m_transparant_ix = findColorIndex(rgb);
0658:                            }
0659:                            ii = (byte) m_transparant_ix; // Use trans color to fill
0660:                        } else {
0661:                            //-- Not transparant,
0662:                            ii = (byte) findColorIndex(rgb); // Add RGB value to the index,
0663:                        }
0664:
0665:                        //-- Always write this run.
0666:                        int dep = doff + (soff - rs); // End output pos
0667:                        while (doff < dep)
0668:                            par[doff++] = ii; // Fill output.
0669:                    }
0670:
0671:                    //-- Prepare for a new line.
0672:                    soff += iw - ai.m_w; // Increment what's left to next line,
0673:
0674:                }
0675:
0676:                ai.m_rgb = par; // Save created thing
0677:                return true;
0678:            }
0679:
0680:            /*--------------------------------------------------------------*/
0681:            /*  CODING: The generic Image stuff to translate the GIF        */
0682:            /*--------------------------------------------------------------*/
0683:            /**
0684:             *  Using a generic Image, this uses a PixelGrabber to get an integer
0685:             *  pixel array.
0686:             */
0687:            private void precodeImage(AnIma ai, Image ima) throws IOException {
0688:                int[] px;
0689:
0690:                //-- Wait for the image to arrive,
0691:                MediaTracker mt = new MediaTracker(m_cv);
0692:                mt.addImage(ima, 0);
0693:                try {
0694:                    mt.waitForAll(); // Be use all are loaded,
0695:                } catch (InterruptedException x) {
0696:                    throw new IOException("Interrupted load of image");
0697:                }
0698:                mt.removeImage(ima, 0);
0699:                mt = null;
0700:
0701:                //-- Get the images' size & adjust the complete GIF's size,
0702:                ai.m_w = ima.getWidth(m_cv);
0703:                ai.m_h = ima.getHeight(m_cv);
0704:                if (ai.m_h == 0 || ai.m_w == 0)
0705:                    return;
0706:                checkTotalSize(ai);
0707:
0708:                //-- Grab pixels & convert to 8-bit pixelset.
0709:                PixelGrabber pg = new PixelGrabber(ima, 0, 0, ai.m_w, ai.m_h,
0710:                        true);
0711:                try {
0712:                    pg.grabPixels();
0713:                } catch (InterruptedException x) {
0714:                    throw new IOException("Interrupted load of image");
0715:                }
0716:                px = (int[]) pg.getPixels(); // Get the pixels,
0717:
0718:                translateColorsByArray(ai, px); // Run the translator
0719:            }
0720:
0721:            /**
0722:             *  For each pixel in the source image, the color is put into the palette
0723:             *  for the combined GIF. The index of the color is then used in the 8-bit
0724:             *  pixelset for this image.
0725:             */
0726:            private void translateColorsByArray(AnIma a, int[] px)
0727:                    throws IOException {
0728:                int off;
0729:                byte[] par;
0730:                int endoff = a.m_w * a.m_h; // Total #pixels in image
0731:                int rstart, rcolor; // Run data.
0732:                byte newc;
0733:
0734:                //-- Collect runs of pixels of the same color; then handle them;
0735:                par = new byte[endoff]; // Allocate output matrix
0736:                off = 0; // Output offset,
0737:                while (off < endoff) {
0738:                    //-- Collect the current run of pixels.
0739:                    rstart = off;
0740:                    rcolor = px[off++]; // Get 1st pixel of run,
0741:                    while (off < endoff && px[off] == rcolor)
0742:                        // Fast loop!
0743:                        off++;
0744:
0745:                    //-- Translate the color to an index, and handle transparency,
0746:                    if (rcolor >= 0) // Is this a TRANSPARANT color?
0747:                    {
0748:                        //-- If there is a transparant color index use it...
0749:                        if (m_transparant_ix < 0) {
0750:                            //-- First transparant color found- save it,
0751:                            if (rcolor == 0)
0752:                                rcolor = 1; // Zero color protection - req'd for hashtable implementation
0753:                            m_transparant_ix = findColorIndex(rcolor);
0754:                        }
0755:                        newc = (byte) m_transparant_ix; // Set color to fill run with
0756:                    } else {
0757:                        //-- Not transparant- is an index known for this color?
0758:                        int i = (rcolor & 0x7fffffff) % CHSIZE;
0759:
0760:                        if (m_ccolor_ar[i] == rcolor) // Bucket found?
0761:                            newc = (byte) m_cindex_ar[i];
0762:                        else
0763:                            newc = (byte) findColorIndex(rcolor); // Get color index,
0764:                    }
0765:
0766:                    //-- Always fill the run with the replaced color,
0767:                    while (rstart < off)
0768:                        par[rstart++] = newc;
0769:
0770:                    //-- This run has been done!!
0771:                }
0772:
0773:                a.m_rgb = par; // Save completed map;
0774:            }
0775:
0776:            /**
0777:             *  Generates the color map by using the color table and creating all
0778:             *  rgb tables. These are then written to the output. This gets called when
0779:             *  all images have been added and pre-traversed.
0780:             */
0781:            private void genColorTable() throws IOException {
0782:                // Turn colors into colormap entries.
0783:                int nelem = 1 << m_color_bits;
0784:                byte[] reds = new byte[nelem];
0785:                byte[] grns = new byte[nelem];
0786:                byte[] blus = new byte[nelem];
0787:
0788:                //-- Now enumerate the color table.
0789:                for (int i = CHSIZE; --i >= 0;) { // Count backwards (faster)
0790:                    if (m_ccolor_ar[i] != 0) { // A color was found?
0791:                        reds[m_cindex_ar[i]] = (byte) ((m_ccolor_ar[i] >> 16) & 0xff);
0792:                        grns[m_cindex_ar[i]] = (byte) ((m_ccolor_ar[i] >> 8) & 0xff);
0793:                        blus[m_cindex_ar[i]] = (byte) (m_ccolor_ar[i] & 0xff);
0794:                    }
0795:                }
0796:
0797:                //-- Write the map to the stream,
0798:                for (int i = 0; i < nelem; i++) { // Save all elements,
0799:                    utByte(reds[i]);
0800:                    utByte(grns[i]);
0801:                    utByte(blus[i]);
0802:                }
0803:            }
0804:
0805:            /**
0806:             *  Writes the GIF file header, containing all up to the first image data
0807:             *  structure: color table, option fields etc.
0808:             */
0809:            private void genHeader() throws IOException {
0810:                // Figure out how many bits to use.
0811:                if (m_color_ix <= 2)
0812:                    m_color_bits = 1;
0813:                else if (m_color_ix <= 4)
0814:                    m_color_bits = 2;
0815:                else if (m_color_ix <= 8)
0816:                    m_color_bits = 3;
0817:                else if (m_color_ix <= 16)
0818:                    m_color_bits = 4;
0819:                else
0820:                    m_color_bits = 8;
0821:
0822:                //-- Start with the headerm
0823:                utStr("GIF89a"); // Gif89a Header: signature & version
0824:
0825:                //-- Logical Screen Descriptor Block
0826:                utWord(m_w); // Collated width & height of all images
0827:                utWord(m_h);
0828:                byte b = (byte) (0xF0 | (m_color_bits - 1));// There IS a color map, 8 bits per color source resolution. not sorted,
0829:                utByte(b); // Packet fields,
0830:                utByte((byte) 0); // Background Color Index assumed 0.
0831:                utByte((byte) 0); // Pixel aspect ratio 1:1: zero always works...
0832:
0833:                //-- Now write the Global Color Map.
0834:                genColorTable();
0835:
0836:                if (m_loop && m_ima_ar.size() > 1) {
0837:                    //-- Generate a Netscape loop thing,
0838:                    utByte((byte) 0x21);
0839:                    utByte((byte) 0xff);
0840:                    utByte((byte) 0x0b);
0841:                    utStr("NETSCAPE2.0");
0842:                    utByte((byte) 0x03);
0843:                    utByte((byte) 1);
0844:                    utWord(0); // Repeat indefinitely
0845:                    utByte((byte) 0);
0846:                }
0847:            }
0848:
0849:            /**
0850:             *  Writes the GIF file trailer, terminating the GIF file.
0851:             */
0852:            private void genTrailer() throws IOException {
0853:                // Write the GIF file terminator
0854:                utByte((byte) ';');
0855:            }
0856:
0857:            /**
0858:             *  Writes a single image instance.
0859:             */
0860:            private void genImage(AnIma ai) throws IOException {
0861:                //-- Write out a Graphic Control Extension for transparent colour & repeat, if necessary,
0862:                if (m_transparant_ix != -1 || m_ima_ar.size() > 1) {
0863:                    byte transpar;
0864:
0865:                    utByte((byte) '!'); // 0x21 Extension Introducer
0866:                    utByte((byte) 0xf9); // Graphic Control Label
0867:                    utByte((byte) 4); // Block Size,
0868:                    if (m_transparant_ix >= 0) { // There IS transparancy?
0869:                        utByte((byte) 1); // TRANS flag SET
0870:                        transpar = (byte) m_transparant_ix;
0871:                    } else {
0872:                        utByte((byte) 0); // TRANS flag CLEAR
0873:                        transpar = 0;
0874:                    }
0875:                    utWord(ai.m_delay); // Delay time,
0876:                    utByte(transpar); // And save the index,
0877:                    utByte((byte) 0);
0878:                }
0879:
0880:                //-- Write the Image Descriptor
0881:                utByte((byte) ',');
0882:                utWord(ai.m_x); // Image left position,
0883:                utWord(ai.m_y); // Image right position
0884:                utWord(ai.m_w);
0885:                utWord(ai.m_h); // And it's size,
0886:                utByte((byte) (ai.m_interlace ? 0x40 : 0)); // Packed fields: interlaced Y/N, no local table no sort,
0887:
0888:                //-- The table-based image data...
0889:                int initcodesz = m_color_bits <= 1 ? 2 : m_color_bits;
0890:                utByte((byte) initcodesz); // Output initial LZH code size, min. 2 bits,
0891:                genCompressed(ai, initcodesz + 1); // Generate the compressed data,
0892:                utByte((byte) 0); // Zero-length packet (end series)
0893:            }
0894:
0895:            /*------------------------------------------------------------------*/
0896:            /*  CODING: Stuff to compress!!!                                    */
0897:            /*------------------------------------------------------------------*/
0898:            /*
0899:             *  Most of this compressor code has been reaped from the ACME GifEncoder
0900:             *  package. See there for more details.
0901:             *  This code will be revised for speed in the next release though.
0902:             */
0903:            /** Pixmap from ima currently compressed */
0904:            private byte[] m_curr_pixels;
0905:
0906:            /** Current pixel source index in above map */
0907:            private int m_px_ix;
0908:
0909:            /** End index within above index. */
0910:            private int m_px_endix;
0911:
0912:            private void genCompressed(AnIma a, int initcodesz)
0913:                    throws IOException {
0914:                //-- Set all globals to retrieve pixel data quickly. $$TODO: Interlaced
0915:                m_curr_pixels = a.m_rgb;
0916:                m_px_ix = 0;
0917:                m_px_endix = a.m_w * a.m_h; // Last index,
0918:
0919:                //-- Coder variables.
0920:                int i, c, ent, disp, hsize_reg, hshift, fcode;
0921:
0922:                //-- Init: the bit-code writer's variables,
0923:                cur_accum = 0;
0924:                cur_bits = 0;
0925:                free_ent = 0;
0926:                clear_flg = false;
0927:                maxbits = BITS; // user settable max # bits/code
0928:                maxmaxcode = 1 << BITS; // should NEVER generate this code
0929:                a_count = 0;
0930:                g_init_bits = initcodesz; // Initial #of bits
0931:
0932:                // Set up the necessary values
0933:                clear_flg = false;
0934:                n_bits = g_init_bits;
0935:                maxcode = MAXCODE(n_bits);
0936:                ClearCode = 1 << (initcodesz - 1);
0937:                EOFCode = ClearCode + 1;
0938:                free_ent = ClearCode + 2;
0939:                char_init();
0940:
0941:                hshift = 0;
0942:                for (fcode = hsize; fcode < 65536; fcode *= 2)
0943:                    ++hshift;
0944:                hshift = 8 - hshift; // set hash code range bound
0945:
0946:                hsize_reg = hsize;
0947:                cl_hash(hsize_reg); // clear hash table
0948:                output(ClearCode);
0949:
0950:                ent = m_curr_pixels[m_px_ix++]; // Get 1st pixel value,
0951:                outer_loop: while (m_px_ix < m_px_endix) // While not at end
0952:                {
0953:                    c = m_curr_pixels[m_px_ix++]; // Get next pixel value,
0954:                    fcode = (c << maxbits) + ent;
0955:                    i = (c << hshift) ^ ent; // xor hashing
0956:
0957:                    if (htab[i] == fcode) {
0958:                        ent = codetab[i];
0959:                        continue;
0960:                    } else if (htab[i] >= 0) // non-empty slot
0961:                    {
0962:                        disp = hsize_reg - i; // secondary hash (after G. Knott)
0963:                        if (i == 0) // ?? Should be inpossible?? JAL
0964:                            disp = 1;
0965:                        do {
0966:                            if ((i -= disp) < 0)
0967:                                i += hsize_reg;
0968:
0969:                            if (htab[i] == fcode) {
0970:                                ent = codetab[i];
0971:                                continue outer_loop;
0972:                            }
0973:                        } while (htab[i] >= 0);
0974:                    }
0975:                    output(ent);
0976:                    ent = c;
0977:                    if (free_ent < maxmaxcode) {
0978:                        codetab[i] = free_ent++; // code -> hashtable
0979:                        htab[i] = fcode;
0980:                    } else
0981:                        cl_block();
0982:                }
0983:                // Put out the final code.
0984:                output(ent);
0985:                outputEOF();
0986:            }
0987:
0988:            static final int EOF = -1;
0989:
0990:            // GIFCOMPR.C       - GIF Image compression routines
0991:            //
0992:            // Lempel-Ziv compression based on 'compress'.  GIF modifications by
0993:            // David Rowley (mgardi@watdcsu.waterloo.edu)
0994:
0995:            // General DEFINEs
0996:
0997:            static final int BITS = 12;
0998:            static final int HSIZE = 5003; // 80% occupancy
0999:
1000:            // GIF Image compression - modified 'compress'
1001:            //
1002:            // Based on: compress.c - File compression ala IEEE Computer, June 1984.
1003:            //
1004:            // By Authors:  Spencer W. Thomas      (decvax!harpo!utah-cs!utah-gr!thomas)
1005:            //              Jim McKie              (decvax!mcvax!jim)
1006:            //              Steve Davies           (decvax!vax135!petsd!peora!srd)
1007:            //              Ken Turkowski          (decvax!decwrl!turtlevax!ken)
1008:            //              James A. Woods         (decvax!ihnp4!ames!jaw)
1009:            //              Joe Orost              (decvax!vax135!petsd!joe)
1010:
1011:            int n_bits; // number of bits/code
1012:            int maxbits = BITS; // user settable max # bits/code
1013:            int maxcode; // maximum code, given n_bits
1014:            int maxmaxcode = 1 << BITS; // should NEVER generate this code
1015:
1016:            final int MAXCODE(int n_bits) {
1017:                return (1 << n_bits) - 1;
1018:            }
1019:
1020:            int[] htab;
1021:            int[] codetab;
1022:
1023:            int hsize = HSIZE; // for dynamic table sizing
1024:
1025:            int free_ent = 0; // first unused entry
1026:
1027:            // block compression parameters -- after all codes are used up,
1028:            // and compression rate changes, start over.
1029:            boolean clear_flg = false;
1030:
1031:            // Algorithm:  use open addressing double hashing (no chaining) on the
1032:            // prefix code / next character combination.  We do a variant of Knuth's
1033:            // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
1034:            // secondary probe.  Here, the modular division first probe is gives way
1035:            // to a faster exclusive-or manipulation.  Also do block compression with
1036:            // an adaptive reset, whereby the code table is cleared when the compression
1037:            // ratio decreases, but after the table fills.  The variable-length output
1038:            // codes are re-sized at this point, and a special CLEAR code is generated
1039:            // for the decompressor.  Late addition:  construct the table according to
1040:            // file size for noticeable speed improvement on small files.  Please direct
1041:            // questions about this implementation to ames!jaw.
1042:
1043:            int g_init_bits;
1044:            int ClearCode;
1045:            int EOFCode;
1046:
1047:            // Output the given code.
1048:            // Inputs:
1049:            //      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
1050:            //              that n_bits =< wordsize - 1.
1051:            // Outputs:
1052:            //      Outputs code to the file.
1053:            // Assumptions:
1054:            //      Chars are 8 bits long.
1055:            // Algorithm:
1056:            //      Maintain a BITS character long buffer (so that 8 codes will
1057:            // fit in it exactly).  Use the VAX insv instruction to insert each
1058:            // code in turn.  When the buffer fills up empty it and start over.
1059:
1060:            int cur_accum = 0;
1061:            int cur_bits = 0;
1062:
1063:            static int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
1064:                    0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
1065:                    0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1066:
1067:            void output(int code) throws IOException {
1068:                cur_accum |= (code << cur_bits);
1069:                cur_bits += n_bits;
1070:
1071:                while (cur_bits >= 8) {
1072:                    //-- Expanded char_out code
1073:                    accum[a_count++] = (byte) cur_accum;
1074:                    if (a_count >= 254)
1075:                        flush_char();
1076:                    //-- End of char_out expansion
1077:
1078:                    cur_accum >>= 8;
1079:                    cur_bits -= 8;
1080:                }
1081:
1082:                // If the next entry is going to be too big for the code size,
1083:                // then increase it, if possible.
1084:                // $$Rewrote if (JAL)
1085:                if (clear_flg) {
1086:                    maxcode = MAXCODE(n_bits = g_init_bits);
1087:                    clear_flg = false;
1088:                } else if (free_ent > maxcode) {
1089:                    ++n_bits;
1090:
1091:                    if (n_bits == maxbits)
1092:                        maxcode = maxmaxcode;
1093:                    else
1094:                        maxcode = MAXCODE(n_bits);
1095:                }
1096:            }
1097:
1098:            /**
1099:             *  Removed from output() above to skip an extra IF in the main loop. Must
1100:             *  be called instead of calling output(EOFCode).
1101:             */
1102:            private void outputEOF() throws IOException {
1103:                output(EOFCode); // Actually output the code
1104:
1105:                //-- At EOF, write the rest of the buffer.
1106:                while (cur_bits > 0) {
1107:                    //-- Expanded char_out.
1108:                    accum[a_count++] = (byte) cur_accum;
1109:                    if (a_count >= 254)
1110:                        flush_char();
1111:                    //-- End of char_out expansion
1112:                    cur_accum >>= 8;
1113:                    cur_bits -= 8;
1114:                }
1115:                flush_char();
1116:            }
1117:
1118:            // Clear out the hash table
1119:            // table clear for block compress
1120:            void cl_block() throws IOException {
1121:                cl_hash(hsize);
1122:                free_ent = ClearCode + 2;
1123:                clear_flg = true;
1124:
1125:                output(ClearCode);
1126:            }
1127:
1128:            // reset code table
1129:            void cl_hash(int hsize) {
1130:                for (int i = hsize; --i >= 0;)
1131:                    htab[i] = -1;
1132:            }
1133:
1134:            // GIF Specific routines
1135:
1136:            // Number of characters so far in this 'packet'
1137:            int a_count;
1138:
1139:            // Set up the 'byte output' routine
1140:            void char_init() {
1141:                a_count = 0;
1142:            }
1143:
1144:            // Define the storage for the packet accumulator
1145:            byte[] accum;
1146:
1147:            // Add a character to the end of the current packet, and if it is 254
1148:            // characters, flush the packet to disk.
1149:            void char_out(byte c) throws IOException {
1150:                accum[a_count++] = c;
1151:                if (a_count >= 254)
1152:                    flush_char();
1153:            }
1154:
1155:            // Flush the packet to disk, and reset the accumulator
1156:            void flush_char() throws IOException {
1157:                if (a_count > 0) {
1158:                    m_os.write(a_count);
1159:                    m_os.write(accum, 0, a_count);
1160:                    a_count = 0;
1161:                }
1162:            }
1163:
1164:            // test method for ymage classes
1165:            public static void main(String[] args) {
1166:                System.setProperty("java.awt.headless", "true");
1167:
1168:                ymageMatrix m = new ymageMatrix(200, 300, ymageMatrix.MODE_SUB,
1169:                        "FFFFFF");
1170:                ymageMatrix.demoPaint(m);
1171:                File file = new File("/Users/admin/Desktop/testimage.gif");
1172:
1173:                OutputStream os;
1174:                try {
1175:                    os = new FileOutputStream(file);
1176:                    AnimGifEncoder age = new AnimGifEncoder(os);
1177:                    age.add(m.getImage());
1178:                    age.add(m.getImage());
1179:                    age.encode();
1180:                    os.close();
1181:                } catch (FileNotFoundException e) {
1182:                    e.printStackTrace();
1183:                } catch (IOException e) {
1184:                    e.printStackTrace();
1185:                }
1186:            }
1187:        }
1188:
1189:        class GifColorEntry {
1190:            /** The actual RGB color for this entry */
1191:            public int m_color;
1192:
1193:            /** The colortable [palette] entry number for this color */
1194:            public int m_index;
1195:
1196:            public GifColorEntry(int col, int ix) {
1197:                m_color = col;
1198:                m_index = ix;
1199:            }
1200:        };
1201:
1202:        class AnIma {
1203:            /** This-image's interlace flag */
1204:            public boolean m_interlace;
1205:
1206:            /** This-image's delay factor */
1207:            public int m_delay;
1208:
1209:            /** This-image's source and destination within the completed image */
1210:            public int m_x, m_y;
1211:
1212:            /** This image's width and height */
1213:            public int m_w, m_h;
1214:
1215:            /** This-image's 8-bit pixelset. It indexes the m_color_ar table. */
1216:            public byte[] m_rgb;
1217:        };
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.