mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 03:44:13 +08:00
(WebPDecoder): use IBinaryStream instead of BinaryReader.
This commit is contained in:
parent
e2ec6423d1
commit
0b12c7bcef
@ -44,9 +44,9 @@ using GameRes.Utility;
|
|||||||
|
|
||||||
namespace GameRes.Formats.Google
|
namespace GameRes.Formats.Google
|
||||||
{
|
{
|
||||||
internal sealed class WebPDecoder : IDisposable
|
internal sealed class WebPDecoder
|
||||||
{
|
{
|
||||||
BinaryReader m_input;
|
IBinaryStream m_input;
|
||||||
byte[] m_output;
|
byte[] m_output;
|
||||||
byte[] m_alpha_data; // compressed alpha data (if present)
|
byte[] m_alpha_data; // compressed alpha data (if present)
|
||||||
byte[] m_alpha_plane; // output. Persistent, contains the whole data.
|
byte[] m_alpha_plane; // output. Persistent, contains the whole data.
|
||||||
@ -60,16 +60,16 @@ namespace GameRes.Formats.Google
|
|||||||
public byte[] Cache { get { return m_cache; } }
|
public byte[] Cache { get { return m_cache; } }
|
||||||
public byte[] AlphaPlane { get { return m_alpha_plane; } }
|
public byte[] AlphaPlane { get { return m_alpha_plane; } }
|
||||||
|
|
||||||
public WebPDecoder (Stream input, WebPMetaData info)
|
public WebPDecoder (IBinaryStream input, WebPMetaData info)
|
||||||
{
|
{
|
||||||
m_input = new ArcView.Reader (input);
|
m_input = input;
|
||||||
m_info = info;
|
m_info = info;
|
||||||
m_stride = (int)info.Width * 4;
|
m_stride = (int)info.Width * 4;
|
||||||
m_output = new byte[m_stride * (int)info.Height];
|
m_output = new byte[m_stride * (int)info.Height];
|
||||||
m_io = new VP8Io();
|
m_io = new VP8Io();
|
||||||
if (0 != m_info.AlphaOffset)
|
if (0 != m_info.AlphaOffset)
|
||||||
{
|
{
|
||||||
m_input.BaseStream.Position = m_info.AlphaOffset;
|
m_input.Position = m_info.AlphaOffset;
|
||||||
m_alpha_data = m_input.ReadBytes (m_info.AlphaSize);
|
m_alpha_data = m_input.ReadBytes (m_info.AlphaSize);
|
||||||
m_alpha_plane = new byte[info.Width * info.Height];
|
m_alpha_plane = new byte[info.Width * info.Height];
|
||||||
Format = PixelFormats.Bgra32;
|
Format = PixelFormats.Bgra32;
|
||||||
@ -94,7 +94,7 @@ namespace GameRes.Formats.Google
|
|||||||
|
|
||||||
public void Decode ()
|
public void Decode ()
|
||||||
{
|
{
|
||||||
m_input.BaseStream.Position = m_info.DataOffset;
|
m_input.Position = m_info.DataOffset;
|
||||||
if (m_info.IsLossless)
|
if (m_info.IsLossless)
|
||||||
{
|
{
|
||||||
m_io.opaque = m_output;
|
m_io.opaque = m_output;
|
||||||
@ -112,14 +112,6 @@ namespace GameRes.Formats.Google
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadInt24 ()
|
|
||||||
{
|
|
||||||
int v = m_input.ReadByte();
|
|
||||||
v |= m_input.ReadByte() << 8;
|
|
||||||
v |= m_input.ReadByte() << 16;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class FrameHeader
|
internal class FrameHeader
|
||||||
{
|
{
|
||||||
public bool KeyFrame;
|
public bool KeyFrame;
|
||||||
@ -230,7 +222,7 @@ namespace GameRes.Formats.Google
|
|||||||
{
|
{
|
||||||
int chunk_size = m_info.DataSize;
|
int chunk_size = m_info.DataSize;
|
||||||
|
|
||||||
int bits = ReadInt24();
|
int bits = m_input.ReadInt24();
|
||||||
chunk_size -= 3;
|
chunk_size -= 3;
|
||||||
m_frame_header.KeyFrame = 0 == (bits & 1);
|
m_frame_header.KeyFrame = 0 == (bits & 1);
|
||||||
m_frame_header.Profile = (bits >> 1) & 7;
|
m_frame_header.Profile = (bits >> 1) & 7;
|
||||||
@ -372,26 +364,26 @@ namespace GameRes.Formats.Google
|
|||||||
|
|
||||||
bool ParsePartitions (BitReader br, int size)
|
bool ParsePartitions (BitReader br, int size)
|
||||||
{
|
{
|
||||||
long part_end = m_input.BaseStream.Position + size;
|
long part_end = m_input.Position + size;
|
||||||
int size_left = size;
|
int size_left = size;
|
||||||
m_num_parts = 1 << br.GetBits (2);
|
m_num_parts = 1 << br.GetBits (2);
|
||||||
int last_part = m_num_parts - 1;
|
int last_part = m_num_parts - 1;
|
||||||
if (size < 3 * last_part)
|
if (size < 3 * last_part)
|
||||||
return false;
|
return false;
|
||||||
long part_start = m_input.BaseStream.Position + last_part * 3;
|
long part_start = m_input.Position + last_part * 3;
|
||||||
size_left -= last_part * 3;
|
size_left -= last_part * 3;
|
||||||
for (int p = 0; p < last_part; ++p)
|
for (int p = 0; p < last_part; ++p)
|
||||||
{
|
{
|
||||||
int psize = ReadInt24();
|
int psize = m_input.ReadInt24();
|
||||||
var sz_pos = m_input.BaseStream.Position;
|
var sz_pos = m_input.Position;
|
||||||
if (psize > size_left) psize = size_left;
|
if (psize > size_left) psize = size_left;
|
||||||
m_input.BaseStream.Position = part_start;
|
m_input.Position = part_start;
|
||||||
m_parts[p] = new BitReader (m_input, psize);
|
m_parts[p] = new BitReader (m_input, psize);
|
||||||
part_start += psize;
|
part_start += psize;
|
||||||
size_left -= psize;
|
size_left -= psize;
|
||||||
m_input.BaseStream.Position = sz_pos;
|
m_input.Position = sz_pos;
|
||||||
}
|
}
|
||||||
m_input.BaseStream.Position = part_start;
|
m_input.Position = part_start;
|
||||||
m_parts[last_part] = new BitReader (m_input, size_left);
|
m_parts[last_part] = new BitReader (m_input, size_left);
|
||||||
return part_start < part_end;
|
return part_start < part_end;
|
||||||
}
|
}
|
||||||
@ -2063,12 +2055,12 @@ namespace GameRes.Formats.Google
|
|||||||
|
|
||||||
public bool Eof { get { return m_eof; } }
|
public bool Eof { get { return m_eof; } }
|
||||||
|
|
||||||
public BitReader (BinaryReader input, int length)
|
public BitReader (IBinaryStream input, int length)
|
||||||
{
|
{
|
||||||
Init (input, length);
|
Init (input, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init (BinaryReader input, int length)
|
public void Init (IBinaryStream input, int length)
|
||||||
{
|
{
|
||||||
if (null == m_buf || m_buf.Length < length)
|
if (null == m_buf || m_buf.Length < length)
|
||||||
m_buf = new byte[length];
|
m_buf = new byte[length];
|
||||||
@ -2285,19 +2277,6 @@ namespace GameRes.Formats.Google
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable Members
|
|
||||||
bool _disposed = false;
|
|
||||||
public void Dispose ()
|
|
||||||
{
|
|
||||||
if (!_disposed)
|
|
||||||
{
|
|
||||||
m_input.Dispose();
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
GC.SuppressFinalize (this);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
static readonly byte[,,,] CoeffsProba0 = new byte[,,,] {
|
static readonly byte[,,,] CoeffsProba0 = new byte[,,,] {
|
||||||
{ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{ { { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
|
||||||
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
|
{ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128 },
|
||||||
|
@ -86,8 +86,8 @@ namespace GameRes.Formats.Google
|
|||||||
if (chunk_size != stream.Read (header, 0, chunk_size))
|
if (chunk_size != stream.Read (header, 0, chunk_size))
|
||||||
return null;
|
return null;
|
||||||
info.Flags = (WebPFeature)LittleEndian.ToUInt32 (header, 0);
|
info.Flags = (WebPFeature)LittleEndian.ToUInt32 (header, 0);
|
||||||
info.Width = 1 + GetUInt24 (header, 4);
|
info.Width = 1 + (uint)header.ToInt24 (4);
|
||||||
info.Height = 1 + GetUInt24 (header, 7);
|
info.Height = 1 + (uint)header.ToInt24 (7);
|
||||||
if ((long)info.Width * info.Height >= (1L << 32))
|
if ((long)info.Width * info.Height >= (1L << 32))
|
||||||
return null;
|
return null;
|
||||||
continue;
|
continue;
|
||||||
@ -96,7 +96,7 @@ namespace GameRes.Formats.Google
|
|||||||
{
|
{
|
||||||
info.IsLossless = header[3] == 'L';
|
info.IsLossless = header[3] == 'L';
|
||||||
info.DataOffset = stream.Position;
|
info.DataOffset = stream.Position;
|
||||||
info.DataSize = chunk_size;
|
info.DataSize = aligned_size;
|
||||||
if (!found_vp8x)
|
if (!found_vp8x)
|
||||||
{
|
{
|
||||||
if (chunk_size < 10 || 10 != stream.Read (header, 0, 10))
|
if (chunk_size < 10 || 10 != stream.Read (header, 0, 10))
|
||||||
@ -134,18 +134,11 @@ namespace GameRes.Formats.Google
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint GetUInt24 (byte[] src, int offset)
|
|
||||||
{
|
|
||||||
return (uint)(src[offset] | src[offset+1] << 8 | src[offset+2] << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
public override ImageData Read (IBinaryStream stream, ImageMetaData info)
|
||||||
{
|
{
|
||||||
using (var reader = new WebPDecoder (stream.AsStream, (WebPMetaData)info))
|
var reader = new WebPDecoder (stream, (WebPMetaData)info);
|
||||||
{
|
reader.Decode();
|
||||||
reader.Decode();
|
return ImageData.Create (info, reader.Format, null, reader.Output);
|
||||||
return ImageData.Create (info, reader.Format, null, reader.Output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Write (Stream file, ImageData image)
|
public override void Write (Stream file, ImageData image)
|
||||||
|
@ -599,7 +599,7 @@ namespace GameRes.Formats.Google
|
|||||||
br_.Init (data, data_i, (uint)data_size);
|
br_.Init (data, data_i, (uint)data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init (BinaryReader input, int length, VP8Io io)
|
public void Init (IBinaryStream input, int length, VP8Io io)
|
||||||
{
|
{
|
||||||
io_ = io;
|
io_ = io;
|
||||||
br_.Init (input, (uint)length);
|
br_.Init (input, (uint)length);
|
||||||
@ -1614,7 +1614,7 @@ namespace GameRes.Formats.Google
|
|||||||
{
|
{
|
||||||
ulong val_; // pre-fetched bits
|
ulong val_; // pre-fetched bits
|
||||||
byte[] buf_; // input byte buffer
|
byte[] buf_; // input byte buffer
|
||||||
uint end_pos_; // buffer length
|
uint end_pos_; // buffer length
|
||||||
uint pos_; // byte position in buf_
|
uint pos_; // byte position in buf_
|
||||||
int bit_pos_; // current bit-reading position in val_
|
int bit_pos_; // current bit-reading position in val_
|
||||||
bool eos_; // true if a bit was read past the end of buffer
|
bool eos_; // true if a bit was read past the end of buffer
|
||||||
@ -1653,7 +1653,7 @@ namespace GameRes.Formats.Google
|
|||||||
buf_ = input;
|
buf_ = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init (BinaryReader input, uint length)
|
public void Init (IBinaryStream input, uint length)
|
||||||
{
|
{
|
||||||
var buf = input.ReadBytes ((int)length);
|
var buf = input.ReadBytes ((int)length);
|
||||||
if (buf.Length != length)
|
if (buf.Length != length)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user