mirror of
https://github.com/crskycode/GARbro.git
synced 2025-01-11 20:39:29 +08:00
(DrgFormat): fixed stride calculation and tweaked decoder.
This commit is contained in:
parent
36ebffb010
commit
6831125278
@ -89,7 +89,7 @@ namespace GameRes.Formats.Ikura
|
|||||||
else
|
else
|
||||||
format = PixelFormats.Bgr565;
|
format = PixelFormats.Bgr565;
|
||||||
|
|
||||||
int stride = (int)info.Width*((info.BPP+7)/8);
|
int stride = ((int)info.Width * info.BPP / 8 + 3) & ~3;
|
||||||
var pixel_data = DecodeStream (file, stride*(int)info.Height);
|
var pixel_data = DecodeStream (file, stride*(int)info.Height);
|
||||||
if (null == pixel_data)
|
if (null == pixel_data)
|
||||||
throw new InvalidFormatException();
|
throw new InvalidFormatException();
|
||||||
@ -99,81 +99,64 @@ namespace GameRes.Formats.Ikura
|
|||||||
byte[] DecodeStream (Stream input, int pixel_count)
|
byte[] DecodeStream (Stream input, int pixel_count)
|
||||||
{
|
{
|
||||||
byte[] output = new byte[pixel_count];
|
byte[] output = new byte[pixel_count];
|
||||||
for (int out_pos = 0; pixel_count > 0; )
|
for (int out_pos = 0; out_pos < output.Length; )
|
||||||
{
|
{
|
||||||
int opcode = input.ReadByte ();
|
int opcode = input.ReadByte();
|
||||||
if (-1 == opcode)
|
if (-1 == opcode)
|
||||||
break;
|
break;
|
||||||
int count, src_offset;
|
int count, src_offset;
|
||||||
|
int remaining = output.Length - out_pos;
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
count = input.ReadByte ();
|
count = Math.Min (3 * input.ReadByte(), remaining);
|
||||||
src_offset = out_pos - 3;
|
src_offset = out_pos - 3;
|
||||||
if (count < 0 || count * 3 > pixel_count || src_offset < 0)
|
if (count < 0 || src_offset < 0)
|
||||||
return null;
|
return null;
|
||||||
for (int i = 0; i < count; ++i)
|
Binary.CopyOverlapped (output, src_offset, out_pos, count);
|
||||||
{
|
break;
|
||||||
Buffer.BlockCopy (output, src_offset, output, out_pos, 3);
|
case 1:
|
||||||
out_pos += 3;
|
count = Math.Min (3 * input.ReadByte(), remaining);
|
||||||
}
|
src_offset = out_pos - 3 * input.ReadByte();
|
||||||
pixel_count -= count * 3;
|
if (count < 0 || src_offset < 0 || src_offset == out_pos)
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
count = 3 * input.ReadByte ();
|
|
||||||
src_offset = out_pos - 3 * input.ReadByte ();
|
|
||||||
if (count < 0 || count > pixel_count || src_offset < 0 || src_offset == out_pos)
|
|
||||||
return null;
|
return null;
|
||||||
Binary.CopyOverlapped (output, src_offset, out_pos, count);
|
Binary.CopyOverlapped (output, src_offset, out_pos, count);
|
||||||
out_pos += count;
|
|
||||||
pixel_count -= count;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
count = 3 * input.ReadByte ();
|
count = Math.Min (3 * input.ReadByte(), remaining);
|
||||||
int off_lo = input.ReadByte ();
|
int off_lo = input.ReadByte();
|
||||||
int off_hi = input.ReadByte ();
|
int off_hi = input.ReadByte();
|
||||||
src_offset = out_pos - 3 * (off_hi << 8 | off_lo);
|
src_offset = out_pos - 3 * (off_hi << 8 | off_lo);
|
||||||
if (count < 0 || count > pixel_count || src_offset < 0 || src_offset == out_pos)
|
if (count < 0 || src_offset < 0 || src_offset == out_pos)
|
||||||
return null;
|
return null;
|
||||||
Binary.CopyOverlapped (output, src_offset, out_pos, count);
|
Binary.CopyOverlapped (output, src_offset, out_pos, count);
|
||||||
out_pos += count;
|
|
||||||
pixel_count -= count;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
count = 3;
|
count = Math.Min (3, remaining);
|
||||||
src_offset = out_pos - 3 * input.ReadByte ();
|
src_offset = out_pos - 3 * input.ReadByte();
|
||||||
if (count > pixel_count || src_offset < 0 || src_offset == out_pos)
|
if (src_offset < 0 || src_offset == out_pos)
|
||||||
return null;
|
return null;
|
||||||
Buffer.BlockCopy (output, src_offset, output, out_pos, count);
|
Buffer.BlockCopy (output, src_offset, output, out_pos, count);
|
||||||
out_pos += count;
|
|
||||||
pixel_count -= count;
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
{
|
{
|
||||||
count = 3;
|
count = Math.Min (3, remaining);
|
||||||
int off_lo = input.ReadByte ();
|
int off_lo = input.ReadByte();
|
||||||
int off_hi = input.ReadByte ();
|
int off_hi = input.ReadByte();
|
||||||
src_offset = out_pos - 3 * (off_hi << 8 | off_lo);
|
src_offset = out_pos - 3 * (off_hi << 8 | off_lo);
|
||||||
if (count > pixel_count || src_offset < 0 || src_offset == out_pos)
|
if (src_offset < 0 || src_offset == out_pos)
|
||||||
return null;
|
return null;
|
||||||
Buffer.BlockCopy (output, src_offset, output, out_pos, count);
|
Buffer.BlockCopy (output, src_offset, output, out_pos, count);
|
||||||
out_pos += count;
|
|
||||||
pixel_count -= count;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
count = 3*(opcode - 4);
|
count = Math.Min (3*(opcode - 4), remaining);
|
||||||
if (count > pixel_count)
|
input.Read (output, out_pos, count);
|
||||||
return null;
|
|
||||||
for (int i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
output[out_pos++] = (byte)input.ReadByte ();
|
|
||||||
}
|
|
||||||
pixel_count -= count;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
out_pos += count;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user