2011-02-17 45 views
7

¿Hay alguna forma de conocer el ancho y la altura originales de un archivo swf con java?¿Cómo saber el tamaño original (ancho y alto) de un archivo swf con java?

int width, height; 

// my stream contains an image or a swf file 
InputStream stream = file.getInputStream(); 

// mediaType has been set with the help of file extension 
switch (mediaType) 
{ 
    case IMAGE: 
     BufferedImage img = ImageIO.read(stream); 
     width = img.getWidth(); 
     height = img.getHeight(); 
     break; 
    case FLASH: 
     // what is the code here ? 
     break; 
} 

Respuesta

5

Miré a la fuente brooksandrus, y estaba un poco decepcionados, así que escribí mi propia solución "una clase de nivel superior". Me doy cuenta de que esto hace una publicación larga, pero no sabía cómo publicarla de otra manera.

 
package resnbl.android.swfview; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.util.Arrays; 
import java.util.zip.DataFormatException; 
import java.util.zip.Inflater; 

/** 
* This class will read just enough of a SWF file's header to glean the essential 
* meta-data about the animation. 
* 
* This is based on <a href="http://www.adobe.com/devnet/swf.html"> 
* SWF File Format Specification (version 10)</a>. 
* 
* @author Resnbl Software 
* @since Mar 22, 2011 
*/ 
public class SWFInfo 
{ 
    static final int UNCOMP_HDR_LEN = 8;  // portion of header that is never compressed 

    public boolean  isCompressed; 
    public int   version; 
    public long   size; 
    public int   width, height; 
    public float  fps; 
    public int   frameCount; 

    // Instantiate through getInfo() methods 
    private SWFInfo() 
    { } 

    /** 
    * Get the header info for a (potential) SWF file specified by a file path String. 
    * 
    * @param path String containing path to file. 
    * 
    * @return  {@link SWFinfo} object or null if file not found or not SWF. 
    */ 
    public static SWFInfo getInfo(String path) 
    { 
     return getInfo(new File(path)); 
    } 

    /** 
    * Get the header info for a (potential) SWF file specified by a {@link File} object. 
    * 
    * @param path {@link File} pointing to the desired SWF file. 
    * 
    * @return  {@link SWFinfo} object or null if file not found or not SWF. 
    */ 
    public static SWFInfo getInfo(File file) 
    { 
     SWFInfo  info = new SWFInfo(); 
     byte[]  hdr = getBytes(file); 

     if (hdr == null) 
      return null; 
     info.isCompressed = hdr[0] == 'C'; 
     info.version = hdr[3]; 
     info.size = hdr[4]&0xFF | (hdr[5]&0xFF)<<8 | (hdr[6]&0xFF)<<16 | hdr[7]<<24; 

     BitReader rdr = new BitReader(hdr, UNCOMP_HDR_LEN); 

     int[] dims = decodeRect(rdr); 
     info.width = (dims[1] - dims[0])/20; // convert twips to pixels 
     info.height = (dims[3] - dims[2])/20; 

     info.fps = (float) rdr.uI16()/256f; // 8.8 fixed-point format 
     info.frameCount = rdr.uI16(); 

     return info; 
    } 

    /* 
    * Read just enough of the file for our purposes 
    */ 
    private static byte[] getBytes(File file) 
    { 
     if (file == null || !file.exists() || file.isDirectory()) 
      return null; 

     byte[] bytes = new byte[128]; // should be enough... 
     FileInputStream fis = null; 

     try 
     { 
      fis = new FileInputStream(file); 

      if (fis.read(bytes) < bytes.length) 
       bytes = null;  // too few bytes to be a SWF 
      else if (bytes[0] == 'C' && bytes[1] == 'W' && bytes[2] == 'S') 
       bytes = expand(bytes, UNCOMP_HDR_LEN); // compressed SWF 
      else if (bytes[0] != 'F' || bytes[1] != 'W' || bytes[2] != 'S') 
       bytes = null;  // not a SWF 
      // else uncompressed SWF 
     } 
     catch (IOException e) 
     { } 
     finally 
     { 
      if (fis != null) 
       try { fis.close(); } 
       catch (IOException ee) { } 
     } 

     return bytes; 
    } 

    /* 
    * All of the file past the initial {@link UNCOMP_HDR_LEN} bytes are compressed. 
    * Decompress as much as is in the buffer already read and return them, 
    * overlaying the original uncompressed data. 
    * 
    * Fortunately, the compression algorithm used by Flash is the ZLIB standard, 
    * i.e., the same algorithms used to compress .jar files 
    */ 
    private static byte[] expand(byte[] bytes, int skip) 
    { 
     byte[] newBytes = new byte[bytes.length - skip]; 
     Inflater inflater = new Inflater(); 

     inflater.setInput(bytes, skip, newBytes.length); 
     try 
     { 
      int outCount = inflater.inflate(newBytes); 
      System.arraycopy(newBytes, 0, bytes, skip, outCount); 
      Arrays.fill(bytes, skip + outCount, bytes.length, (byte) 0); 
      return bytes; 
     } 
     catch (DataFormatException e) 
     { } 

     return null; 
    } 

    /** 
    * Return Stage frame rectangle as 4 <code>int</code>s: LRTB 
    * 
    * Note the values are in TWIPS (= 1/20th of a pixel) 
    * 
    * I do this to avoid a loading the <code>Rect</code> class which is an 
    * <code>android.graphics</code> class, and not available if you want to 
    * test this with desktop Java. 
    * 
    * @param rdr 
    * @return 
    */ 
    public static int[] decodeRect(BitReader rdr) 
    { 
     int[] dims = new int[4]; 
     int nBits = rdr.uBits(5); 

     dims[0] = rdr.sBits(nBits);  // X min = left  always 0 
     dims[1] = rdr.sBits(nBits);  // X max = right 
     dims[2] = rdr.sBits(nBits);  // Y min = top  always 0 
     dims[3] = rdr.sBits(nBits);  // Y max = bottom 

     return dims; 
    } 

    /** 
    * This can be run from a desktop command line sitting at the .../bin directory as: 
    * 
    * java resnbl.android.swfview.SWFInfo swf_file 
    * 
    * @param args path to swf_file to parse 
    */ 
// commented out to prevent Eclipse from thinkg this is a standard Java app when used for Android! 
// public static void main(String[] args) 
// { 
//  if (args.length == 0) 
//   throw new IllegalArgumentException("No swf_file parameter given"); 
// 
//  File file = new File(args[0]); 
//  SWFInfo info = SWFInfo.getInfo(file); 
// 
//  if (info != null) 
//  { 
//   System.out.println("File: " + file); 
//   System.out.println("Flash ver: " + info.version + " FPS: " + info.fps + " Frames: " + info.frameCount); 
//   System.out.println("File size: " + file.length() + " Compressed: " + info.isCompressed + " Uncompressed size: " + info.size); 
//   System.out.println("Dimensions: " + info.width + "x" + info.height); 
//  } 
//  else 
//   System.out.println("File not a .SWF: " + file); 
// } 

    /** 
    * Read an arbitrary number of bits from a byte[]. 
    * 
    * This should be turned into a full-featured independant class (someday...). 
    */ 
    static class BitReader 
    { 
     private byte[]  bytes; 
     private int   byteIdx; 
     private int   bitIdx = 0; 

     /** 
     * Start reading from the beginning of the supplied array. 
     * @param bytes byte[] to process 
     */ 
     public BitReader(byte[] bytes) 
     { 
      this(bytes, 0); 
     } 

     /** 
     * Start reading from an arbitrary index into the array. 
     * @param bytes   byte[] to process 
     * @param startIndex byte # to start at 
     */ 
     public BitReader(byte[] bytes, int startIndex) 
     { 
      this.bytes = bytes; 
      byteIdx = startIndex; 
     } 

     /** 
     * Fetch the next <code>bitCount</code> bits as an unsigned int. 
     * @param bitCount # bits to read 
     * @return int 
     */ 
     public int uBits(int bitCount) 
     { 
      int value = 0; 

      while (--bitCount >= 0) 
       value = value << 1 | getBit(); 
      return value; 
     } 

     /** 
     * Fetch the next <code>bitCount</code> bits as a <em>signed</em> int. 
     * @param bitCount # bits to read 
     * @return int 
     */ 
     public int sBits(int bitCount) 
     { 
      // First bit is the "sign" bit 
      int value = getBit() == 0 ? 0 : -1; 
      --bitCount; 

      while (--bitCount >= 0) 
       value = value << 1 | getBit(); 
      return value; 
     } 

     // Get the next bit in the array 
     private int getBit() 
     { 
      int value = (bytes[byteIdx] >> (7 - bitIdx)) & 0x01; 

      if (++bitIdx == 8) 
      { 
       bitIdx = 0; 
       ++byteIdx; 
      } 

      return value; 
     } 

     /** 
     * Fetch the next 2 "whole" bytes as an unsigned int (little-endian). 
     * @return int 
     */ 
     public int uI16() 
     { 
      sync();  // back to "byte-aligned" mode 
      return (bytes[byteIdx++] & 0xff) | (bytes[byteIdx++] & 0xff) << 8; 
     } 

     /** 
     * Bump indexes to the next byte boundary. 
     */ 
     public void sync() 
     { 
      if (bitIdx > 0) 
      { 
       ++byteIdx; 
       bitIdx = 0; 
      } 
     } 
    } 
} 

Nota: Hice un reemplazo global de corchetes angulares con sus equivalentes HTML para que esto se muestre correctamente. Si lo corta y pega, ojalá no tenga que revertir ese cambio.

+0

gracias, creo que este es un buen comienzo. Voy a darle una oportunidad. –

1

Bueno, obtener el ancho y la altura de un archivo flash también es interesante para mí. No he encontrado una manera fácil de hacer esto hasta ahora, sin embargo.

Después de una breve búsqueda en Google me encontré con este:

http://www.brooksandrus.com/blog/2006/08/11/lightweight-swf-header-reader-java-ii/

Es una biblioteca que le permite analizar un encabezado del archivo flash, pero es varios años y los comentarios sugieren que se produce un error para el flash 7 hacia arriba (lo que lo haría casi inútil ahora). Pero quizás con un poco de ajuste funcionaría.

Debo decir, sin embargo, que no probé esa biblioteca.

Espero que ayude

Cuestiones relacionadas