mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 11:54:13 +08:00
(SWF): support BitsJpeg2 chunks.
This commit is contained in:
parent
91390fb69c
commit
006004f170
@ -49,14 +49,14 @@ namespace GameRes.Formats.Macromedia
|
|||||||
public class SwfOpener : ArchiveFormat
|
public class SwfOpener : ArchiveFormat
|
||||||
{
|
{
|
||||||
public override string Tag { get { return "SWF"; } }
|
public override string Tag { get { return "SWF"; } }
|
||||||
public override string Description { get { return "Shockeave Flash presentation"; } }
|
public override string Description { get { return "Shockwave Flash presentation"; } }
|
||||||
public override uint Signature { get { return 0; } }
|
public override uint Signature { get { return 0; } }
|
||||||
public override bool IsHierarchic { get { return false; } }
|
public override bool IsHierarchic { get { return false; } }
|
||||||
public override bool CanWrite { get { return false; } }
|
public override bool CanWrite { get { return false; } }
|
||||||
|
|
||||||
public SwfOpener ()
|
public SwfOpener ()
|
||||||
{
|
{
|
||||||
Signatures = new uint[] { 0x08535743, 0 };
|
Signatures = new uint[] { 0x08535743, 0x08535746, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ArcFile TryOpen (ArcView file)
|
public override ArcFile TryOpen (ArcView file)
|
||||||
@ -173,14 +173,35 @@ namespace GameRes.Formats.Macromedia
|
|||||||
case Types.DefineBitsLossless2:
|
case Types.DefineBitsLossless2:
|
||||||
return new LosslessImageDecoder (swent.Chunk);
|
return new LosslessImageDecoder (swent.Chunk);
|
||||||
|
|
||||||
|
case Types.DefineBitsJpeg2:
|
||||||
|
return new SwfJpeg2Decoder (swent.Chunk);
|
||||||
|
|
||||||
case Types.DefineBitsJpeg3:
|
case Types.DefineBitsJpeg3:
|
||||||
return new SwfJpeg3Decoder (swent.Chunk);
|
return new SwfJpeg3Decoder (swent.Chunk);
|
||||||
|
|
||||||
|
case Types.DefineBitsJpeg:
|
||||||
|
return OpenBitsJpeg (swent.Chunk);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return base.OpenImage (arc, entry);
|
return base.OpenImage (arc, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IImageDecoder OpenBitsJpeg (SwfChunk chunk)
|
||||||
|
{
|
||||||
|
int jpeg_pos = 0;
|
||||||
|
for (int i = 0; i < chunk.Data.Length - 2; ++i)
|
||||||
|
{
|
||||||
|
if (chunk.Data[i] == 0xFF && chunk.Data[i+1] == 0xD8)
|
||||||
|
{
|
||||||
|
jpeg_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var input = new BinMemoryStream (chunk.Data, jpeg_pos, chunk.Data.Length - jpeg_pos);
|
||||||
|
return ImageFormatDecoder.Create (input);
|
||||||
|
}
|
||||||
|
|
||||||
delegate Stream Extractor (SwfEntry entry);
|
delegate Stream Extractor (SwfEntry entry);
|
||||||
|
|
||||||
static Dictionary<Types, Extractor> ExtractMap = new Dictionary<Types, Extractor> {
|
static Dictionary<Types, Extractor> ExtractMap = new Dictionary<Types, Extractor> {
|
||||||
@ -195,12 +216,20 @@ namespace GameRes.Formats.Macromedia
|
|||||||
|
|
||||||
static Dictionary<Types, string> TypeMap = new Dictionary<Types, string> {
|
static Dictionary<Types, string> TypeMap = new Dictionary<Types, string> {
|
||||||
{ Types.DefineBitsJpeg, "image" },
|
{ Types.DefineBitsJpeg, "image" },
|
||||||
{ Types.DefineBitsJpeg2, "DefineBitsJpeg2" },
|
{ Types.DefineBitsJpeg2, "image" },
|
||||||
{ Types.DefineBitsJpeg3, "image" },
|
{ Types.DefineBitsJpeg3, "image" },
|
||||||
{ Types.DefineBitsLossless, "image" },
|
{ Types.DefineBitsLossless, "image" },
|
||||||
{ Types.DefineBitsLossless2, "image" },
|
{ Types.DefineBitsLossless2, "image" },
|
||||||
{ Types.DefineSound, "audio" },
|
{ Types.DefineSound, "audio" },
|
||||||
{ Types.DoAction, "" },
|
{ Types.DoAction, "" },
|
||||||
|
|
||||||
|
{ Types.JpegTables, "JpegTables" },
|
||||||
|
/*
|
||||||
|
{ Types.DefineText, "Text" },
|
||||||
|
{ Types.DefineText2, "Text2" },
|
||||||
|
{ Types.DefineVideoStream, "VideoStream" },
|
||||||
|
{ Types.VideoFrame, "VideoFrame" },
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static bool IsSoundStream (SwfChunk chunk)
|
internal static bool IsSoundStream (SwfChunk chunk)
|
||||||
@ -217,17 +246,23 @@ namespace GameRes.Formats.Macromedia
|
|||||||
ShowFrame = 1,
|
ShowFrame = 1,
|
||||||
DefineShape = 2,
|
DefineShape = 2,
|
||||||
DefineBitsJpeg = 6,
|
DefineBitsJpeg = 6,
|
||||||
|
JpegTables = 8,
|
||||||
|
DefineText = 11,
|
||||||
DoAction = 12,
|
DoAction = 12,
|
||||||
DefineSound = 14,
|
DefineSound = 14,
|
||||||
SoundStreamHead = 18,
|
SoundStreamHead = 18,
|
||||||
SoundStreamBlock = 19,
|
SoundStreamBlock = 19,
|
||||||
DefineBitsLossless = 20,
|
DefineBitsLossless = 20,
|
||||||
DefineBitsJpeg2 = 21,
|
DefineBitsJpeg2 = 21,
|
||||||
|
DefineShape2 = 22,
|
||||||
|
DefineShape3 = 32,
|
||||||
|
DefineText2 = 33,
|
||||||
DefineBitsJpeg3 = 35,
|
DefineBitsJpeg3 = 35,
|
||||||
DefineBitsLossless2 = 36,
|
DefineBitsLossless2 = 36,
|
||||||
DefineSprite = 39,
|
DefineSprite = 39,
|
||||||
SoundStreamHead2 = 45,
|
SoundStreamHead2 = 45,
|
||||||
ExportAssets = 56,
|
ExportAssets = 56,
|
||||||
|
DefineVideoStream = 60,
|
||||||
VideoFrame = 61,
|
VideoFrame = 61,
|
||||||
FileAttributes = 69,
|
FileAttributes = 69,
|
||||||
Font3 = 75,
|
Font3 = 75,
|
||||||
@ -401,9 +436,12 @@ namespace GameRes.Formats.Macromedia
|
|||||||
for (int i = 0; i < pixels.Length; i += 4)
|
for (int i = 0; i < pixels.Length; i += 4)
|
||||||
{
|
{
|
||||||
byte a = pixels[i];
|
byte a = pixels[i];
|
||||||
pixels[i] = pixels[i+1];
|
byte r = pixels[i+1];
|
||||||
pixels[i+1] = pixels[i+2];
|
byte g = pixels[i+2];
|
||||||
pixels[i+2] = pixels[i+3];
|
byte b = pixels[i+3];
|
||||||
|
pixels[i] = b;
|
||||||
|
pixels[i+1] = g;
|
||||||
|
pixels[i+2] = r;
|
||||||
pixels[i+3] = a;
|
pixels[i+3] = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,6 +450,65 @@ namespace GameRes.Formats.Macromedia
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal sealed class SwfJpeg2Decoder : IImageDecoder
|
||||||
|
{
|
||||||
|
byte[] m_input;
|
||||||
|
ImageData m_image;
|
||||||
|
|
||||||
|
public Stream Source { get { return Stream.Null; } }
|
||||||
|
public ImageFormat SourceFormat { get { return null; } }
|
||||||
|
public ImageMetaData Info { get; private set; }
|
||||||
|
public ImageData Image { get { return m_image ?? (m_image = Unpack()); } }
|
||||||
|
|
||||||
|
public SwfJpeg2Decoder (SwfChunk chunk)
|
||||||
|
{
|
||||||
|
m_input = chunk.Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageData Unpack ()
|
||||||
|
{
|
||||||
|
int jpeg_pos = FindJpegSignature();
|
||||||
|
if (jpeg_pos < 0)
|
||||||
|
throw new InvalidFormatException();
|
||||||
|
using (var jpeg = new BinMemoryStream (m_input, jpeg_pos, m_input.Length-jpeg_pos))
|
||||||
|
{
|
||||||
|
var decoder = new JpegBitmapDecoder (jpeg, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
|
||||||
|
var frame = decoder.Frames[0];
|
||||||
|
Info = new ImageMetaData {
|
||||||
|
Width = (uint)frame.PixelWidth,
|
||||||
|
Height = (uint)frame.PixelHeight,
|
||||||
|
BPP = frame.Format.BitsPerPixel,
|
||||||
|
};
|
||||||
|
return new ImageData (frame, Info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int FindJpegSignature ()
|
||||||
|
{
|
||||||
|
int jpeg_pos = 2;
|
||||||
|
while (jpeg_pos < m_input.Length-4)
|
||||||
|
{
|
||||||
|
if (m_input[jpeg_pos] != 0xFF)
|
||||||
|
jpeg_pos++;
|
||||||
|
else if (m_input[jpeg_pos+1] == 0xD8)
|
||||||
|
return jpeg_pos;
|
||||||
|
else if (m_input[jpeg_pos+1] != 0xD9)
|
||||||
|
jpeg_pos++;
|
||||||
|
else if (m_input[jpeg_pos+2] != 0xFF)
|
||||||
|
jpeg_pos += 3;
|
||||||
|
else if (m_input[jpeg_pos+3] != 0xD8)
|
||||||
|
jpeg_pos += 2;
|
||||||
|
else
|
||||||
|
return jpeg_pos+4;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed class SwfJpeg3Decoder : IImageDecoder
|
internal sealed class SwfJpeg3Decoder : IImageDecoder
|
||||||
{
|
{
|
||||||
byte[] m_input;
|
byte[] m_input;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user