Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/anotherbigidea/flash/movie/ImageUtil.java


1   /****************************************************************
2    * Copyright (c) 2001, David N. Main, All rights reserved.
3    * 
4    * Redistribution and use in source and binary forms, with or
5    * without modification, are permitted provided that the 
6    * following conditions are met:
7    *
8    * 1. Redistributions of source code must retain the above 
9    * copyright notice, this list of conditions and the following 
10   * disclaimer. 
11   * 
12   * 2. Redistributions in binary form must reproduce the above 
13   * copyright notice, this list of conditions and the following 
14   * disclaimer in the documentation and/or other materials 
15   * provided with the distribution.
16   * 
17   * 3. The name of the author may not be used to endorse or 
18   * promote products derived from this software without specific 
19   * prior written permission. 
20   * 
21   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 
22   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
23   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
24   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25   * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
27   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
29   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
30   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
31   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
32   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   ****************************************************************/
34  package com.anotherbigidea.flash.movie;
35  
36  import java.util.*;
37  import java.io.*;
38  import java.awt.*;
39  import java.awt.image.*;
40  import com.sun.image.codec.jpeg.*;
41  import com.anotherbigidea.flash.SWFConstants;
42  
43  /**
44   * Utilities for dealing with images
45   */
46  public class ImageUtil
47  {
48      /**
49       * Normalize a JPEG to ensure that it is "Baseline" rather than
50       * "Progressive".  The Flash player doesn't like "Progressive".
51       * 
52       * @param size null or an int[2] to receive the (width,height) of the image
53       * @return the image data - with the necessary header for SWF
54       */
55      public static byte[] normalizeJPEG( InputStream jpegImage, int[] size )
56          throws IOException 
57      {
58          JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder( jpegImage );
59          BufferedImage buff = decoder.decodeAsBufferedImage();
60          
61          if( size != null && size.length >= 2 )
62          {
63              size[0] = decoder.getJPEGDecodeParam().getWidth();
64              size[1] = decoder.getJPEGDecodeParam().getHeight();
65          }
66          
67          ByteArrayOutputStream out = new ByteArrayOutputStream();
68          
69          //--write stream headers/terminators
70          out.write( 0xff );
71          out.write( 0xd9 );
72          out.write( 0xff );
73          out.write( 0xd8 );
74          
75          JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder( out );
76          
77          encoder.encode( buff );
78          out.flush();
79          
80          return out.toByteArray();
81      }
82      
83      /**
84       * Create a Shape for the image.  The resulting shape uses the image as
85       * a clipped image fill.  The shape is a rectangle just the right size
86       * to show the entire image and its origin is at the top left.
87       * 
88       * Additional geometry vectors may be added to the shape if required.
89       * 
90       * @param size null or an int[2] to receive the (width,height) of the image
91       */
92      public static Shape shapeForImage( InputStream jpegImage, int[] size )
93          throws IOException 
94      {
95          if( size == null || size.length < 2 ) size = new int[2];
96          byte[] data = normalizeJPEG( jpegImage, size );
97          
98          int width = size[0];
99          int height = size[1];
100         
101         Image img = new Image.JPEG( data );
102         
103         return shapeForImage( img, (double)width, (double)height );
104     }
105 
106     /**
107      * Create a Shape for the image.  The resulting shape uses the image as
108      * a clipped image fill.  The shape is a rectangle just the right size
109      * to show the entire image and its origin is at the top left.
110      * 
111      * Additional geometry vectors may be added to the shape if required.
112      */
113     public static Shape shapeForImage( Image image, double width, double height )
114         //throws IOException 
115     {
116         Shape s = new Shape();
117 
118         Transform matrix = new Transform( SWFConstants.TWIPS,
119                                           SWFConstants.TWIPS,
120                                           0.0, 0.0 );
121         
122         s.defineFillStyle( image, matrix, true );
123         s.setRightFillStyle(1);  //use image fill
124         s.setLineStyle(0);       //no line
125         s.line(width,0);
126         s.line(width,height);
127         s.line(0,height);
128         s.line(0,0);
129         
130         return s;
131     }
132         
133     /**
134      * Create a lossless Image object from an AWT Image - the awt image
135      * must be fully loaded and ready.
136      * 
137      * @param format one of: SWFConstants.BITMAP_FORMAT_8_BIT,
138      *                       SWFConstants.BITMAP_FORMAT_16_BIT,
139      *                       SWFConstants.BITMAP_FORMAT_32_BIT
140      */
141     public static Image.Lossless createLosslessImage( 
142                                      java.awt.Image image,
143                                      int format,
144                                      boolean hasAlpha )
145     {
146         int width  = image.getWidth(null);
147         int height = image.getHeight(null);
148               
149         PixelGrabber grabber = new PixelGrabber( image, 0, 0, width, height, true );
150         grabber.startGrabbing();
151         
152         try{ grabber.grabPixels(); } catch( InterruptedException ie ) {}
153         
154         int[] pixelData = (int[])grabber.getPixels();
155         
156         int size = 0;
157         switch( format )
158         {
159             case SWFConstants.BITMAP_FORMAT_8_BIT:  size = 1; break;
160             case SWFConstants.BITMAP_FORMAT_16_BIT: size = 2; break;
161             case SWFConstants.BITMAP_FORMAT_32_BIT: 
162             default:                                size = 4; break;
163         }  
164         
165         int rowBytes = width * size;
166         int modulo = rowBytes % 4;
167         if( modulo > 0 ) rowBytes += 4 - modulo; //pad up to next 32 bits
168         //>>>Padding bug spotted by Joachim Sauer        
169         
170         byte[] imageData = new byte[ height * rowBytes ];
171         
172         //--color lookup table
173         Map table = ( format == SWFConstants.BITMAP_FORMAT_32_BIT ) ? null :
174                         new HashMap();
175         
176         for( int y = 0; y < height; y++ )
177         {
178             int rowStart = y * width;
179             int rowByte  = y * rowBytes;
180             
181             for( int x = 0; x < width; x++ )
182             {
183                 int pix = pixelData[ rowStart + x ];
184                 int bite = rowByte + ( x * size );
185                 
186                 if( format == SWFConstants.BITMAP_FORMAT_32_BIT )
187                 {                    
188                     imageData[ bite   ] = hasAlpha ? (byte)( pix >> 24 ) : -1;
189                     imageData[ bite+1 ] = (byte)((pix >> 16) & 0xff );
190                     imageData[ bite+2 ] = (byte)((pix >> 8 ) & 0xff  );
191                     imageData[ bite+3 ] = (byte)( pix & 0xff );
192                 }                
193                 else
194                 {
195                     //--find the pixel color in the lookup table
196                     Integer pixI  = new Integer( pix );
197                     Integer index = (Integer)table.get( pixI );
198                     
199                     if( index == null )
200                     {
201                         index = new Integer( table.size() );
202                         table.put( pixI, index );
203                     }
204                     
205                     int idx = index.intValue();
206 
207                     if( format == SWFConstants.BITMAP_FORMAT_8_BIT )
208                     {
209                         imageData[ bite ] = (byte)idx;
210                     }
211                     else
212                     {
213                         imageData[bite  ] = (byte)(( idx >> 8 )& 0xff);
214                         imageData[bite+1] = (byte)( idx & 0xff );
215                     }
216                 }
217             }        
218         }
219         
220         com.anotherbigidea.flash.structs.Color[] colors = 
221             ( format == SWFConstants.BITMAP_FORMAT_32_BIT ) ? null :
222                 new com.anotherbigidea.flash.structs.Color[ table.size() ];
223         
224         if( colors != null )
225         {
226             for( Iterator it = table.keySet().iterator(); it.hasNext(); )
227             {              
228                 Integer key = (Integer)it.next();
229                 int argb = key.intValue();
230                 
231                 int index = ((Integer)table.get(key)).intValue();
232                 
233                 int alpha = (argb >> 24) & 0xff;
234                 int red   = (argb >> 16) & 0xff;
235                 int green = (argb >> 8 ) & 0xff;
236                 int blue  = argb & 0xff;
237                 
238                 com.anotherbigidea.flash.structs.Color color = hasAlpha ? 
239                     new com.anotherbigidea.flash.structs.AlphaColor(red,green,blue,alpha):
240                     new com.anotherbigidea.flash.structs.Color(red,green,blue);
241                 
242                 colors[index] = color;
243                 
244                 System.out.println( "Color " + index + " = " + color );
245             }
246         }
247 
248         return new Image.Lossless( colors, imageData,
249                                    (double)width, (double)height,
250                                    hasAlpha, format );
251     }                                
252 }