Files
2013-04-25 13:36:51 -07:00

158 lines
3.9 KiB
Java

// Copyright (c) 2013 Adobe Systems Inc
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package flascc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
class SWFHeader
{
public final byte version;
public final byte[] rect;
public final short frameRate;
public final short frameCount;
public final int length;
public static byte[] readRect(InputStream is) throws IOException
{
int b0 = is.read();
if(b0 < 0)
return null;
int bpc = b0 >> 3; // high 5 bits indicate bits per component for xMin, xMax, yMin, yMax
int bitCount = 5 + bpc * 4; // total bitcount for the rect (including component width bits)
int byteCount = (bitCount + 7) / 8; // round up for total byte count
byte[] result = new byte[byteCount];
result[0] = (byte)b0;
if(is.read(result, 1, result.length-1) != result.length-1)
return null;
return result;
}
public static class SWFHeaderAndInputStream
{
public final SWFHeader swfHeader;
public final InputStream inputStream;
public SWFHeaderAndInputStream(SWFHeader swfHeader, InputStream inputStream)
{
this.swfHeader = swfHeader;
this.inputStream = inputStream;
}
}
public static SWFHeaderAndInputStream read(InputStream is) throws IOException
{
// header
boolean compressed;
switch(is.read())
{
default:
return null;
case 'F':
compressed = false;
break;
case 'C':
compressed = true;
break;
}
if(is.read() != 'W')
return null;
if(is.read() != 'S')
return null;
// version
int ver = is.read();
if(ver < 0)
return null;
// file size (ignored)
if(is.skip(4) != 4)
return null;
if(compressed)
is = new InflaterInputStream(is);
byte[] rect = readRect(is);
if(rect == null)
return null;
int frameRate = is.read() | (is.read() << 8);
if(frameRate < 0)
return null;
int frameCount = is.read() | (is.read() << 8);
if(frameCount < 0)
return null;
return new SWFHeaderAndInputStream(new SWFHeader((byte)ver, rect, (short)frameRate, (short)frameCount), is);
}
public OutputStream write(OutputStream os, int swfLength, boolean compress) throws IOException
{
compress &= (version >= 6);
os.write(compress ? 'C' : 'F');
os.write('W');
os.write('S');
os.write(version);
os.write(swfLength);
os.write(swfLength >> 8);
os.write(swfLength >> 16);
os.write(swfLength >> 24);
if(compress)
{
os.flush();
os = new DeflaterOutputStream(os);
}
os.write(rect);
os.write(frameRate);
os.write(frameRate >> 8);
os.write(frameCount);
os.write(frameCount >> 8);
return os;
}
public SWFHeader(byte version, byte[] rect, short frameRate, short frameCount)
{
this.version = version;
this.rect = rect;
this.frameRate = frameRate;
this.frameCount = frameCount;
length = 4 + 4 + rect.length + 2 + 2;
}
}