mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
(Rip007): implemented RGBA decoding.
This commit is contained in:
@@ -43,6 +43,8 @@ namespace GameRes.Formats.Rugp
|
|||||||
public override string Description { get { return "rUGP compressed image format"; } }
|
public override string Description { get { return "rUGP compressed image format"; } }
|
||||||
public override uint Signature { get { return 0; } }
|
public override uint Signature { get { return 0; } }
|
||||||
|
|
||||||
|
// signature set to 0 because all serialized rUGP objects have same signature.
|
||||||
|
|
||||||
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
public override ImageMetaData ReadMetaData (IBinaryStream file)
|
||||||
{
|
{
|
||||||
if (file.Signature != CRioArchive.ObjectSignature)
|
if (file.Signature != CRioArchive.ObjectSignature)
|
||||||
@@ -84,31 +86,34 @@ namespace GameRes.Formats.Rugp
|
|||||||
int Version;
|
int Version;
|
||||||
int m_width;
|
int m_width;
|
||||||
int m_height;
|
int m_height;
|
||||||
|
int m_x;
|
||||||
|
int m_y;
|
||||||
|
int m_w;
|
||||||
|
int m_h;
|
||||||
byte[] CompressInfo;
|
byte[] CompressInfo;
|
||||||
byte[] field_30;
|
int m_flags;
|
||||||
int field_38;
|
|
||||||
int field_3C;
|
|
||||||
CObject field_4C;
|
CObject field_4C;
|
||||||
byte[] m_pixels;
|
byte[] m_pixels;
|
||||||
|
|
||||||
public PixelFormat Format { get; private set; }
|
public PixelFormat Format { get; private set; }
|
||||||
public byte[] Pixels { get { return m_pixels; } }
|
public byte[] Pixels { get { return m_pixels; } }
|
||||||
public bool HasAlpha { get { return ((field_38 & 0xFF) - 2) == 1; } }
|
public bool HasAlpha { get { return ((m_flags & 0xFF) - 2) == 1; } }
|
||||||
|
|
||||||
public override void Deserialize (CRioArchive arc)
|
public override void Deserialize (CRioArchive arc)
|
||||||
{
|
{
|
||||||
Version = arc.ReadInt32();
|
Version = arc.ReadInt32();
|
||||||
m_width = arc.ReadUInt16();
|
m_width = arc.ReadUInt16();
|
||||||
m_height = arc.ReadUInt16();
|
m_height = arc.ReadUInt16();
|
||||||
field_30 = arc.ReadBytes (4);
|
m_x = arc.ReadUInt16();
|
||||||
arc.ReadUInt16();
|
m_y = arc.ReadUInt16();
|
||||||
arc.ReadUInt16();
|
m_w = arc.ReadUInt16();
|
||||||
field_38 = arc.ReadInt32();
|
m_h = arc.ReadUInt16();
|
||||||
|
m_flags = arc.ReadInt32();
|
||||||
CompressInfo = arc.ReadBytes (7);
|
CompressInfo = arc.ReadBytes (7);
|
||||||
if (arc.GetObjectSchema() >= 2)
|
if (arc.GetObjectSchema() >= 2)
|
||||||
field_4C = arc.ReadRioReference ("CSbm");
|
field_4C = arc.ReadRioReference ("CSbm");
|
||||||
int size = arc.ReadInt32();
|
int size = arc.ReadInt32();
|
||||||
field_3C = arc.ReadInt32();
|
arc.ReadInt32(); // field_3C
|
||||||
var data = arc.ReadBytes (size);
|
var data = arc.ReadBytes (size);
|
||||||
m_pixels = Uncompress (data);
|
m_pixels = Uncompress (data);
|
||||||
Format = HasAlpha ? PixelFormats.Bgra32 : PixelFormats.Bgr32;
|
Format = HasAlpha ? PixelFormats.Bgra32 : PixelFormats.Bgr32;
|
||||||
@@ -148,50 +153,31 @@ namespace GameRes.Formats.Rugp
|
|||||||
int x = 0;
|
int x = 0;
|
||||||
while (x < m_width)
|
while (x < m_width)
|
||||||
{
|
{
|
||||||
int count = 1;
|
int count = GetInt (input);
|
||||||
while (input.GetNextBit() > 0)
|
|
||||||
{
|
|
||||||
count <<= 1;
|
|
||||||
count |= input.GetNextBit();
|
|
||||||
}
|
|
||||||
x += count;
|
x += count;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (input.GetNextBit() > 0)
|
if (input.GetNextBit() > 0)
|
||||||
{
|
{
|
||||||
rgb = LittleEndian.ToInt32 (output, dst - stride);
|
rgb = LittleEndian.ToInt32 (output, dst - stride);
|
||||||
rgb_ = rgb;
|
|
||||||
if (rgb != 0)
|
if (rgb != 0)
|
||||||
{
|
{
|
||||||
rgb -= baseline;
|
rgb -= baseline;
|
||||||
rgb_ = rgb;
|
|
||||||
}
|
}
|
||||||
|
rgb_ = rgb;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int r = 0, g = 0, b = 0;
|
int r = 0, g = 0, b = 0;
|
||||||
if (input.GetNextBit() > 0)
|
if (input.GetNextBit() > 0)
|
||||||
{
|
{
|
||||||
g = 1;
|
g = GetSigned (input);
|
||||||
bool sign = input.GetNextBit() > 0;
|
|
||||||
while (input.GetNextBit() > 0)
|
|
||||||
{
|
|
||||||
g <<= 1;
|
|
||||||
g |= input.GetNextBit();
|
|
||||||
}
|
|
||||||
if (sign)
|
|
||||||
g = -g;
|
|
||||||
}
|
}
|
||||||
int b_inc = 0;
|
int b_inc = 0;
|
||||||
if (input.GetNextBit() > 0)
|
if (input.GetNextBit() > 0)
|
||||||
{
|
{
|
||||||
int v = 1;
|
|
||||||
bool sign = input.GetNextBit() > 0;
|
bool sign = input.GetNextBit() > 0;
|
||||||
while (input.GetNextBit() > 0)
|
int v = GetInt (input);
|
||||||
{
|
|
||||||
v <<= 1;
|
|
||||||
v |= input.GetNextBit();
|
|
||||||
}
|
|
||||||
b_inc = tblQuantTransfer[q, v];
|
b_inc = tblQuantTransfer[q, v];
|
||||||
if (sign)
|
if (sign)
|
||||||
b_inc = -b_inc;
|
b_inc = -b_inc;
|
||||||
@@ -199,13 +185,8 @@ namespace GameRes.Formats.Rugp
|
|||||||
int r_inc = 0;
|
int r_inc = 0;
|
||||||
if (input.GetNextBit() > 0)
|
if (input.GetNextBit() > 0)
|
||||||
{
|
{
|
||||||
int v = 1;
|
|
||||||
bool sign = input.GetNextBit() > 0;
|
bool sign = input.GetNextBit() > 0;
|
||||||
while (input.GetNextBit() > 0)
|
int v = GetInt (input);
|
||||||
{
|
|
||||||
v <<= 1;
|
|
||||||
v |= input.GetNextBit();
|
|
||||||
}
|
|
||||||
r_inc = tblQuantTransfer[q, v];
|
r_inc = tblQuantTransfer[q, v];
|
||||||
if (sign)
|
if (sign)
|
||||||
r_inc = -r_inc;
|
r_inc = -r_inc;
|
||||||
@@ -215,21 +196,21 @@ namespace GameRes.Formats.Rugp
|
|||||||
gg >>= 1;
|
gg >>= 1;
|
||||||
if (CompressInfo[3] != 0)
|
if (CompressInfo[3] != 0)
|
||||||
{
|
{
|
||||||
int c1 = (0xFF >> b_shift) & (rgb_ >> b_shift);
|
int c1 = (0xFF >> b_shift) & (int)((uint)rgb_ >> b_shift);
|
||||||
int c2 = (0xFF >> b_shift) - c1;
|
|
||||||
c1 = -c1;
|
c1 = -c1;
|
||||||
if (gg >= c1)
|
if (gg >= c1)
|
||||||
{
|
{
|
||||||
|
int c2 = (0xFF >> b_shift) + c1;
|
||||||
c1 = c2;
|
c1 = c2;
|
||||||
if (gg <= c2)
|
if (gg <= c2)
|
||||||
c1 = gg;
|
c1 = gg;
|
||||||
}
|
}
|
||||||
b = c1 + b_inc;
|
b = c1 + b_inc;
|
||||||
c1 = (0xFF0000 >> r_shift) & (rgb_ >> r_shift);
|
c1 = (0xFF0000 >> r_shift) & (int)((uint)rgb_ >> r_shift);
|
||||||
c2 = (0xFF0000 >> r_shift) - c1;
|
|
||||||
c1 = -c1;
|
c1 = -c1;
|
||||||
if (gg >= c1)
|
if (gg >= c1)
|
||||||
{
|
{
|
||||||
|
int c2 = (0xFF0000 >> r_shift) + c1;
|
||||||
c1 = c2;
|
c1 = c2;
|
||||||
if (gg <= c2)
|
if (gg <= c2)
|
||||||
c1 = gg;
|
c1 = gg;
|
||||||
@@ -254,12 +235,7 @@ namespace GameRes.Formats.Rugp
|
|||||||
if (x >= m_width)
|
if (x >= m_width)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
count = 1;
|
count = GetInt (input);
|
||||||
while (input.GetNextBit() > 0)
|
|
||||||
{
|
|
||||||
count <<= 1;
|
|
||||||
count |= input.GetNextBit();
|
|
||||||
}
|
|
||||||
x += count;
|
x += count;
|
||||||
while (count --> 0)
|
while (count --> 0)
|
||||||
{
|
{
|
||||||
@@ -273,7 +249,140 @@ namespace GameRes.Formats.Rugp
|
|||||||
|
|
||||||
void UncompressRgba (IBitStream input, byte[] output)
|
void UncompressRgba (IBitStream input, byte[] output)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
int stride = 4 * m_width;
|
||||||
|
int q = CompressInfo[0];
|
||||||
|
int b_bits = CompressInfo[4];
|
||||||
|
int g_bits = CompressInfo[5];
|
||||||
|
int r_bits = CompressInfo[6];
|
||||||
|
int b_shift = 8 - b_bits;
|
||||||
|
int g_shift = 16 - g_bits;
|
||||||
|
int r_shift = 24 - r_bits;
|
||||||
|
int dst_pos = m_y * stride + m_x * 4;
|
||||||
|
int baseline = 0xFF >> b_bits | (0xFF >> g_bits | (0xFF >> r_bits << 8)) << 8;
|
||||||
|
var line_buf = new int[m_w];
|
||||||
|
for (int y = 0; y < m_h; ++y)
|
||||||
|
{
|
||||||
|
int alpha = 0;
|
||||||
|
int rgb = 0;
|
||||||
|
int repeat_count = 0;
|
||||||
|
bool repeat = true;
|
||||||
|
int dst = dst_pos + y * stride;
|
||||||
|
int x = 0;
|
||||||
|
int chunk_size = 0;
|
||||||
|
while (x < m_w)
|
||||||
|
{
|
||||||
|
if (0 == chunk_size)
|
||||||
|
{
|
||||||
|
int alpha_inc = 0;
|
||||||
|
if (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
alpha_inc = GetSigned (input);
|
||||||
|
}
|
||||||
|
alpha += alpha_inc;
|
||||||
|
if (0 == alpha || 31 == alpha)
|
||||||
|
{
|
||||||
|
chunk_size = GetInt (input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alpha != 0)
|
||||||
|
{
|
||||||
|
if (31 == alpha)
|
||||||
|
--chunk_size;
|
||||||
|
if (0 == repeat_count)
|
||||||
|
{
|
||||||
|
repeat_count = GetInt (input);
|
||||||
|
repeat = !repeat;
|
||||||
|
}
|
||||||
|
--repeat_count;
|
||||||
|
if (!repeat)
|
||||||
|
{
|
||||||
|
if (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
rgb = line_buf[x];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int g = 0;
|
||||||
|
if (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
g = GetSigned (input);
|
||||||
|
}
|
||||||
|
int b_inc = 0;
|
||||||
|
if (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
bool sign = input.GetNextBit() > 0;
|
||||||
|
int v = GetInt (input);
|
||||||
|
b_inc = tblQuantTransfer[q, v];
|
||||||
|
if (sign)
|
||||||
|
b_inc = -b_inc;
|
||||||
|
}
|
||||||
|
int r_inc = 0;
|
||||||
|
if (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
bool sign = input.GetNextBit() > 0;
|
||||||
|
int v = GetInt (input);
|
||||||
|
r_inc = tblQuantTransfer[q, v];
|
||||||
|
if (sign)
|
||||||
|
r_inc = -r_inc;
|
||||||
|
}
|
||||||
|
int c1 = (0xFF >> b_shift) & (int)((uint)rgb >> b_shift);
|
||||||
|
c1 = -c1;
|
||||||
|
if (g >= c1)
|
||||||
|
{
|
||||||
|
int c2 = (0xFF >> b_shift) + c1;
|
||||||
|
c1 = g;
|
||||||
|
if (g > c2)
|
||||||
|
c1 = c2;
|
||||||
|
}
|
||||||
|
int b = c1 + b_inc;
|
||||||
|
c1 = (0xFF0000 >> r_shift) & (int)((uint)rgb >> r_shift);
|
||||||
|
c1 = -c1;
|
||||||
|
if (g >= c1)
|
||||||
|
{
|
||||||
|
int c2 = (0xFF0000 >> r_shift) + c1;
|
||||||
|
c1 = g;
|
||||||
|
if (g > c2)
|
||||||
|
c1 = c2;
|
||||||
|
}
|
||||||
|
int r = c1 + r_inc;
|
||||||
|
rgb += (b << b_shift) + (r << r_shift) + (g << g_shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint pixel = (uint)(baseline + rgb);
|
||||||
|
if (31 == alpha)
|
||||||
|
pixel |= 0xFF000000u;
|
||||||
|
else
|
||||||
|
pixel |= (uint)(alpha << 27);
|
||||||
|
LittleEndian.Pack (pixel, output, dst);
|
||||||
|
dst += 4;
|
||||||
|
line_buf[x++] = rgb;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst += 4 * chunk_size;
|
||||||
|
x += chunk_size;
|
||||||
|
chunk_size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetInt (IBitStream input)
|
||||||
|
{
|
||||||
|
int n = 1;
|
||||||
|
while (input.GetNextBit() > 0)
|
||||||
|
{
|
||||||
|
n <<= 1;
|
||||||
|
n |= input.GetNextBit();
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetSigned (IBitStream input)
|
||||||
|
{
|
||||||
|
bool sign = input.GetNextBit() > 0;
|
||||||
|
int n = GetInt (input);
|
||||||
|
return sign ? -n : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly byte[,] tblQuantTransfer = {
|
static readonly byte[,] tblQuantTransfer = {
|
||||||
|
|||||||
Reference in New Issue
Block a user