KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > common > util > FlashInfo


1 /**
2  * FlashInfo is (c) 2006 Paul Brooks Andrus and is released under the MIT
3  * License: http://www.opensource.org/licenses/mit-license.php
4  */

5 package org.riotfamily.common.util;
6
7 import java.io.*;
8 import java.util.zip.*;
9
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12
13 /**
14  * @author brooks
15  */

16 public class FlashInfo {
17
18     protected Log log = LogFactory.getLog(getClass());
19
20     public static String JavaDoc COMPRESSED = "compressed";
21
22     public static String JavaDoc UNCOMPRESSED = "uncompressed";
23
24     private String JavaDoc signature;
25
26     private String JavaDoc compressionType;
27
28     private int version;
29
30     private long size;
31
32     private int nbits;
33
34     private int xmax;
35
36     private int ymax;
37
38     private int width;
39
40     private int height;
41
42     private int frameRate;
43
44     private int frameCount;
45
46     private boolean valid = false;
47
48     public FlashInfo(File file) throws IOException {
49         valid = parseHeader(file);
50     }
51
52     public boolean parseHeader(File file) throws IOException {
53         log.debug("Parsing file '" + file + "'...");
54
55         FileInputStream fis = null;
56         byte[] temp = new byte[(int) file.length()];
57         byte[] swf = null;
58
59         fis = new FileInputStream(file);
60         fis.read(temp);
61         fis.close();
62
63         if (!isSWF(temp)) {
64             log.debug("The file does not appear to be a swf - incorrect file signature");
65             return false;
66         }
67         else {
68             signature = "" + (char) temp[0] + (char) temp[1] + (char) temp[2];
69         }
70
71         if (isCompressed(temp[0])) {
72             try {
73                 swf = decompress(temp);
74             }
75             catch (DataFormatException dfe) {
76                 log.warn("The file appears to be compressed, but decompression failed: "
77                         + dfe.getMessage());
78
79                 return false;
80             }
81             compressionType = FlashInfo.COMPRESSED;
82         }
83         else {
84             swf = temp;
85             compressionType = FlashInfo.UNCOMPRESSED;
86         }
87
88         // version is the 4th byte of a swf;
89
version = swf[3];
90
91         // bytes 5 - 8 represent the size in bytes of a swf
92
size = readSize(swf);
93
94         // Stage dimensions are stored in a rect
95

96         nbits = ((swf[8] & 0xff) >> 3);
97
98         PackedBitObj pbo = readPackedBits(swf, 8, 5, nbits);
99
100         PackedBitObj pbo2 = readPackedBits(swf, pbo.nextByteIndex, pbo.nextBitIndex, nbits);
101
102         PackedBitObj pbo3 = readPackedBits(swf, pbo2.nextByteIndex, pbo2.nextBitIndex, nbits);
103
104         PackedBitObj pbo4 = readPackedBits(swf, pbo3.nextByteIndex, pbo3.nextBitIndex, nbits);
105
106         xmax = pbo2.value;
107         ymax = pbo4.value;
108
109         width = convertTwipsToPixels(xmax);
110         height = convertTwipsToPixels(ymax);
111
112         int bytePointer = pbo4.nextByteIndex + 2;
113
114         frameRate = swf[bytePointer];
115         bytePointer++;
116
117         int fc1 = swf[bytePointer] & 0xFF;
118         bytePointer++;
119
120         int fc2 = swf[bytePointer] & 0xFF;
121         bytePointer++;
122
123         frameCount = (fc2 << 8) + fc1;
124
125         log.debug("signature: " + getSignature());
126         log.debug("version: " + getVersion());
127         log.debug("compression: " + getCompressionType());
128         log.debug("size: " + getSize());
129         log.debug("nbits: " + getNbits());
130         log.debug("xmax: " + getXmax());
131         log.debug("ymax: " + getYmax());
132         log.debug("width: " + getWidth());
133         log.debug("height: " + getHeight());
134         log.debug("frameRate: " + getFrameRate());
135         log.debug("frameCount: " + getFrameCount());
136
137         return true;
138     }
139
140     public void read(byte[] output, byte[] input, int offset) {
141         System.arraycopy(input, offset, output, 0, output.length - offset);
142     }
143
144     public int readSize(byte[] bytes) {
145         int size = 0;
146         for (int i = 0; i < 4; i++) {
147             size = (size << 8) + bytes[i + 4];
148         }
149
150         size = Integer.reverseBytes(size);
151
152         return size;
153     }
154
155     public PackedBitObj readPackedBits(byte[] bytes, int byteMarker, int bitMarker, int length) {
156         int total = 0;
157         int shift = 7 - bitMarker;
158         int counter = 0;
159         int bitIndex = bitMarker;
160         int byteIndex = byteMarker;
161
162         while (counter < length) {
163
164             for (int i = bitMarker; i < 8; i++) {
165                 int bit = ((bytes[byteMarker] & 0xff) >> shift) & 1;
166                 total = (total << 1) + bit;
167                 bitIndex = i;
168                 shift--;
169                 counter++;
170                 if (counter == length) {
171                     break;
172                 }
173             }
174             byteIndex = byteMarker;
175             byteMarker++;
176             bitMarker = 0;
177             shift = 7;
178         }
179         return new PackedBitObj(bitIndex, byteIndex, total);
180     }
181
182     public int convertTwipsToPixels(int twips) {
183         return twips / 20;
184     }
185
186     public int convertPixelsToTwips(int pixels) {
187         return pixels * 20;
188     }
189
190     public boolean isSWF(byte[] signature) {
191         String JavaDoc sig = "" + (char) signature[0] + (char) signature[1] + (char) signature[2];
192
193         if (sig.equals("FWS") || sig.equals("CWS")) {
194             return true;
195         }
196         else {
197             return false;
198         }
199     }
200
201     public boolean isCompressed(int firstByte) {
202         if (firstByte == 67) {
203             return true;
204         }
205         else {
206             return false;
207         }
208     }
209
210     public byte[] compress(byte[] bytes, int length) {
211
212         byte[] compressed = null;
213         byte[] temp = new byte[length];
214
215         Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
216         deflater.setInput(bytes, 8, length - 8);
217         deflater.finish();
218
219         int compressedLength = deflater.deflate(temp);
220
221         compressed = new byte[compressedLength + 8];
222
223         // the first 8 bytes of the header are uncompressed
224
System.arraycopy(bytes, 0, compressed, 0, 8);
225
226         // copy the compressed data from the temporary byte array to its new
227
// byte array
228
System.arraycopy(temp, 0, compressed, 8, compressedLength);
229
230         // the first byte of the swf indicates the swf is compressed
231
temp[0] = 67;
232
233         // make sure the swf size structure represents the uncompressed size of
234
// the swf
235
int bl = bytes.length;
236         temp[4] = (byte) (bl & 0x000000FF);
237         temp[5] = (byte) ((bl & 0x0000FF00) >> 8);
238         temp[6] = (byte) ((bl & 0x00FF0000) >> 16);
239         temp[7] = (byte) ((bl & 0xFF000000) >> 24);
240
241         return compressed;
242     }
243
244     public byte[] decompress(byte[] bytes) throws DataFormatException {
245         int size = readSize(bytes);
246
247         byte[] uncompressed = new byte[size];
248         System.arraycopy(bytes, 0, uncompressed, 0, 8);
249
250         Inflater inflater = new Inflater();
251         inflater.setInput(bytes, 8, bytes.length - 8);
252         inflater.inflate(uncompressed, 8, size - 8);
253         inflater.finished();
254
255         // the first byte of the swf indicates the swf is uncompressed
256
uncompressed[0] = 70;
257
258         return uncompressed;
259     }
260
261
262     /**
263      * @return the frameCount
264      */

265     public int getFrameCount() {
266         return frameCount;
267     }
268
269     /**
270      * @return the frameRate
271      */

272     public int getFrameRate() {
273         return frameRate;
274     }
275
276     /**
277      * @return the nbits
278      */

279     public int getNbits() {
280         return nbits;
281     }
282
283     /**
284      * @return the signature
285      */

286     public String JavaDoc getSignature() {
287         return signature;
288     }
289
290     /**
291      * @return the size
292      */

293     public long getSize() {
294         return size;
295     }
296
297     /**
298      * @return the version
299      */

300     public int getVersion() {
301         return version;
302     }
303
304     /**
305      * @return the xmax
306      */

307     public int getXmax() {
308         return xmax;
309     }
310
311     /**
312      * @return the ymax
313      */

314     public int getYmax() {
315         return ymax;
316     }
317
318     /**
319      * @return the compressionType
320      */

321     public String JavaDoc getCompressionType() {
322         return compressionType;
323     }
324
325     /**
326      * @return the height
327      */

328     public int getHeight() {
329         return height;
330     }
331
332     /**
333      * @return the width
334      */

335     public int getWidth() {
336         return width;
337     }
338
339     /**
340      * @return true if no exception occured during parsing
341      */

342     public boolean isValid() {
343         return valid;
344     }
345
346
347     /**
348      * @author brooks
349      */

350     public class PackedBitObj {
351
352         public int bitIndex = 0;
353
354         public int byteIndex = 0;
355
356         public int value = 0;
357
358         public int nextBitIndex = 0;
359
360         public int nextByteIndex = 0;
361
362         public int nextByteBoundary = 0;
363
364         /**
365          * @param bitIndex The index of the last bit read
366          * @param byteMarker The index of the last byte read
367          * @param decimalValue The decimal value of the packed bit sequence
368          * @param binaryString
369          */

370         public PackedBitObj(int bitMarker, int byteMarker, int decimalValue) {
371             bitIndex = bitMarker;
372             byteIndex = byteMarker;
373             value = decimalValue;
374             nextBitIndex = bitMarker;
375
376             if (bitMarker < 7) {
377                 nextBitIndex++;
378                 nextByteIndex = byteMarker;
379                 nextByteBoundary = byteMarker++;
380             }
381             else {
382                 nextBitIndex = 0;
383                 nextByteIndex++;
384                 nextByteBoundary = nextByteIndex;
385             }
386         }
387
388     }
389
390 }
Popular Tags