mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-25 20:34:13 +08:00
(WBM): image compression variations.
This commit is contained in:
parent
1cf89e33b6
commit
da15b1f31f
@ -2,7 +2,7 @@
|
|||||||
//! \date Thu Jul 09 20:59:09 2015
|
//! \date Thu Jul 09 20:59:09 2015
|
||||||
//! \brief Wild Bug's image format.
|
//! \brief Wild Bug's image format.
|
||||||
//
|
//
|
||||||
// Copyright (C) 2015 by morkt
|
// Copyright (C) 2015-2016 by morkt
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to
|
// of this software and associated documentation files (the "Software"), to
|
||||||
@ -136,6 +136,10 @@ namespace GameRes.Formats.WildBug
|
|||||||
format = PixelFormats.Bgr555;
|
format = PixelFormats.Bgr555;
|
||||||
pixel_size = 2;
|
pixel_size = 2;
|
||||||
break;
|
break;
|
||||||
|
case 8:
|
||||||
|
format = PixelFormats.Indexed8;
|
||||||
|
pixel_size = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException ("Not supported WBM bitdepth");
|
throw new NotSupportedException ("Not supported WBM bitdepth");
|
||||||
}
|
}
|
||||||
@ -144,6 +148,18 @@ namespace GameRes.Formats.WildBug
|
|||||||
var pixels = reader.Unpack (stride, pixel_size, section.DataFormat);
|
var pixels = reader.Unpack (stride, pixel_size, section.DataFormat);
|
||||||
if (null == pixels)
|
if (null == pixels)
|
||||||
throw new InvalidFormatException();
|
throw new InvalidFormatException();
|
||||||
|
|
||||||
|
if (8 == meta.BPP)
|
||||||
|
{
|
||||||
|
section = WpxSection.Find (meta.Header, 0x12, meta.EntryCount, meta.EntrySize);
|
||||||
|
if (null == section)
|
||||||
|
return ImageData.Create (info, PixelFormats.Gray8, null, pixels, stride);
|
||||||
|
reader = new WbmReader (stream, section);
|
||||||
|
var palette_data = reader.Unpack (48, 3, section.DataFormat);
|
||||||
|
var palette = CreatePalette (palette_data);
|
||||||
|
return ImageData.Create (info, PixelFormats.Indexed8, palette, pixels, stride);
|
||||||
|
}
|
||||||
|
|
||||||
if (meta.BPP < 24)
|
if (meta.BPP < 24)
|
||||||
return ImageData.Create (info, format, null, pixels, stride);
|
return ImageData.Create (info, format, null, pixels, stride);
|
||||||
section = WpxSection.Find (meta.Header, 0x13, meta.EntryCount, meta.EntrySize);
|
section = WpxSection.Find (meta.Header, 0x13, meta.EntryCount, meta.EntrySize);
|
||||||
@ -183,6 +199,18 @@ namespace GameRes.Formats.WildBug
|
|||||||
{
|
{
|
||||||
throw new System.NotImplementedException ("WbmFormat.Write not implemented");
|
throw new System.NotImplementedException ("WbmFormat.Write not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BitmapPalette CreatePalette (byte[] palette_data)
|
||||||
|
{
|
||||||
|
int colors = Math.Min (palette_data.Length/3, 0x100);
|
||||||
|
var palette = new Color[0x100];
|
||||||
|
for (int i = 0; i < colors; ++i)
|
||||||
|
{
|
||||||
|
int c = i * 3;
|
||||||
|
palette[i] = Color.FromRgb (palette_data[c], palette_data[c+1], palette_data[c+2]);
|
||||||
|
}
|
||||||
|
return new BitmapPalette (palette);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class WbmReader : WpxDecoder
|
internal class WbmReader : WpxDecoder
|
||||||
@ -237,14 +265,16 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int m_version;
|
||||||
int m_condition;
|
int m_condition;
|
||||||
|
|
||||||
public byte[] Unpack (int stride, int pixel_size, int flags) // sub_40919C
|
public byte[] Unpack (int stride, int pixel_size, int flags) // sub_40919C
|
||||||
{
|
{
|
||||||
int[] offset_table = new int[8];
|
int[] offset_table = new int[8];
|
||||||
GenerateOffsetTableV2 (offset_table, stride, pixel_size);
|
GenerateOffsetTableV2 (offset_table, stride, pixel_size);
|
||||||
for (m_condition = 1; m_condition >= 0; --m_condition)
|
for (m_version = 2; m_version >= 0; --m_version)
|
||||||
{
|
{
|
||||||
|
m_condition = m_version > 0 ? 1 : 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ResetInput();
|
ResetInput();
|
||||||
@ -281,16 +311,16 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
if (0 == m_condition)
|
if (0 == m_version)
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
if (1 == m_version)
|
||||||
GenerateOffsetTableV1 (offset_table, stride, pixel_size);
|
GenerateOffsetTableV1 (offset_table, stride, pixel_size);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackVD (byte[] a4, int[] offset_table, int pixel_size) // 0x0F format
|
byte[] UnpackVD (byte[] a4, int[] offset_table, int pixel_size) // 0x0F format
|
||||||
// int sub_460470(void *dst, const void *src, unsigned __int8 *ref_table, unsigned int packed_size, int *offset_table, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
byte[] v47 = BuildTable(); //sub_46C26C();
|
byte[] v47 = BuildTable(); //sub_46C26C();
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
@ -448,11 +478,60 @@ namespace GameRes.Formats.WildBug
|
|||||||
|
|
||||||
byte[] UnpackV9 (int[] offset_table, int pixel_size) // 0x09 format
|
byte[] UnpackV9 (int[] offset_table, int pixel_size) // 0x09 format
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
|
m_available = FillBuffer();
|
||||||
|
if (0 == m_available)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int step = (pixel_size + 3) & -4;
|
||||||
|
if (m_available < step)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Buffer.BlockCopy (m_buffer, 0, m_output, 0, pixel_size);
|
||||||
|
int dst = pixel_size;
|
||||||
|
int remaining = m_output.Length - pixel_size;
|
||||||
|
m_current = pixel_size + (-pixel_size & 3);
|
||||||
|
|
||||||
|
m_bits = m_buffer[m_current++];
|
||||||
|
m_bit_count = 8;
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
while (0 == (GetNextBit() ^ m_condition))
|
||||||
|
{
|
||||||
|
m_output[dst++] = ReadNext();
|
||||||
|
--remaining;
|
||||||
|
if (0 == remaining)
|
||||||
|
return m_output;
|
||||||
|
}
|
||||||
|
int count, src_offset;
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
src_offset = dst - 1 - ReadNext();
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = min_count;
|
||||||
|
int v35 = GetNextBit();
|
||||||
|
v35 += v35 + GetNextBit();
|
||||||
|
v35 += v35 + GetNextBit();
|
||||||
|
src_offset = dst - offset_table[v35];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetNextBit() == 0)
|
||||||
|
{
|
||||||
|
count += ReadCount();
|
||||||
|
}
|
||||||
|
if (remaining < count)
|
||||||
|
return null;
|
||||||
|
Binary.CopyOverlapped (m_output, src_offset, dst, count);
|
||||||
|
dst += count;
|
||||||
|
remaining -= count;
|
||||||
|
}
|
||||||
|
return m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV5 (byte[] a4, int[] offset_table, int pixel_size) // 0x07 format
|
byte[] UnpackV5 (byte[] a4, int[] offset_table, int pixel_size) // 0x07 format
|
||||||
// int sub_409AF4 (void *a1, FILE *stream, void *ptr, void *a4, unsigned int m_packed_size, int *offset_table, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
byte[] v46 = BuildTable();
|
byte[] v46 = BuildTable();
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
@ -506,8 +585,36 @@ namespace GameRes.Formats.WildBug
|
|||||||
if (0 == remaining)
|
if (0 == remaining)
|
||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
int src_offset;
|
int count, src_offset;
|
||||||
int count;
|
if (m_version > 1)
|
||||||
|
{
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
int v35;
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
v35 = ReadNext();
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v35 = ReadNext();
|
||||||
|
v35 |= ReadNext() << 8;
|
||||||
|
count = 3;
|
||||||
|
}
|
||||||
|
src_offset = dst - 1 - v35;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = min_count;
|
||||||
|
int v35 = GetNextBit();
|
||||||
|
v35 += v35 + GetNextBit();
|
||||||
|
v35 += v35 + GetNextBit();
|
||||||
|
src_offset = dst - offset_table[v35];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (GetNextBit() != 0)
|
if (GetNextBit() != 0)
|
||||||
{
|
{
|
||||||
count = min_count;
|
count = min_count;
|
||||||
@ -522,6 +629,7 @@ namespace GameRes.Formats.WildBug
|
|||||||
count = 2;
|
count = 2;
|
||||||
src_offset = dst - 1 - v35;
|
src_offset = dst - 1 - v35;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (0 == GetNextBit())
|
if (0 == GetNextBit())
|
||||||
{
|
{
|
||||||
count += ReadCount();
|
count += ReadCount();
|
||||||
@ -536,7 +644,6 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV4 (byte[] a4, int[] offset_table, int pixel_size) // 0x06 format
|
byte[] UnpackV4 (byte[] a4, int[] offset_table, int pixel_size) // 0x06 format
|
||||||
// signed int __cdecl sub_40B044(void *a1, FILE *stream, void *ptr, void *a4, unsigned int packed_size, int *offset_table, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
byte[] v48 = BuildTable();
|
byte[] v48 = BuildTable();
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
@ -615,7 +722,6 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV3 (byte[] a4, int[] offset_table, int pixel_size) // 0x03 format
|
byte[] UnpackV3 (byte[] a4, int[] offset_table, int pixel_size) // 0x03 format
|
||||||
// int sub_409F70(void *a1, FILE *stream, void *ptr, void *a4, unsigned int packed_size, int *offset_table, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
|
|
||||||
@ -660,6 +766,34 @@ namespace GameRes.Formats.WildBug
|
|||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
int count, src_offset;
|
int count, src_offset;
|
||||||
|
if (m_version > 1)
|
||||||
|
{
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
count = 2;
|
||||||
|
src_offset = ReadNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = 3;
|
||||||
|
src_offset = ReadNext();
|
||||||
|
src_offset |= ReadNext() << 8;
|
||||||
|
}
|
||||||
|
src_offset = dst - 1 - src_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = min_count;
|
||||||
|
int v28 = GetNextBit();
|
||||||
|
v28 += v28 + GetNextBit();
|
||||||
|
v28 += v28 + GetNextBit();
|
||||||
|
src_offset = dst - offset_table[v28];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (GetNextBit() != 0)
|
if (GetNextBit() != 0)
|
||||||
{
|
{
|
||||||
count = min_count;
|
count = min_count;
|
||||||
@ -674,6 +808,7 @@ namespace GameRes.Formats.WildBug
|
|||||||
count = 2;
|
count = 2;
|
||||||
src_offset = dst - 1 - ReadNext();
|
src_offset = dst - 1 - ReadNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (GetNextBit() == 0)
|
if (GetNextBit() == 0)
|
||||||
{
|
{
|
||||||
count += ReadCount();
|
count += ReadCount();
|
||||||
@ -688,9 +823,7 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV2 (byte[] a4, int[] offset_table, int pixel_size) // 0x02 format
|
byte[] UnpackV2 (byte[] a4, int[] offset_table, int pixel_size) // 0x02 format
|
||||||
// int sub_40B458(void *a1, FILE *stream, unsigned __int8 *ptr, void *a4, unsigned int packed_size, int *offset_table, int unpacked_size, unsigned int a8)
|
|
||||||
{
|
{
|
||||||
byte[] v48 = BuildTable();
|
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
m_available = FillBuffer();
|
m_available = FillBuffer();
|
||||||
if (0 == m_available)
|
if (0 == m_available)
|
||||||
@ -756,7 +889,6 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV1 (int[] offset_table, int pixel_size) // 0x01 format
|
byte[] UnpackV1 (int[] offset_table, int pixel_size) // 0x01 format
|
||||||
//int sub_40A3C4(void *a1, FILE *stream, const void *ptr, unsigned int packed_size, int *offset_table, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
m_available = FillBuffer();
|
m_available = FillBuffer();
|
||||||
@ -784,6 +916,34 @@ namespace GameRes.Formats.WildBug
|
|||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
int count, src_offset;
|
int count, src_offset;
|
||||||
|
if (m_version > 1)
|
||||||
|
{
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
if (GetNextBit() != 0)
|
||||||
|
{
|
||||||
|
src_offset = ReadNext();
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
src_offset = ReadNext();
|
||||||
|
src_offset |= ReadNext() << 8;
|
||||||
|
count = 3;
|
||||||
|
}
|
||||||
|
src_offset = dst - 1 - src_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = min_count;
|
||||||
|
int v20 = GetNextBit();
|
||||||
|
v20 += v20 + GetNextBit();
|
||||||
|
v20 += v20 + GetNextBit();
|
||||||
|
src_offset = dst - offset_table[v20];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (GetNextBit() != 0)
|
if (GetNextBit() != 0)
|
||||||
{
|
{
|
||||||
count = min_count;
|
count = min_count;
|
||||||
@ -797,6 +957,7 @@ namespace GameRes.Formats.WildBug
|
|||||||
count = 2;
|
count = 2;
|
||||||
src_offset = dst - 1 - ReadNext();
|
src_offset = dst - 1 - ReadNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (GetNextBit() == 0)
|
if (GetNextBit() == 0)
|
||||||
{
|
{
|
||||||
count += ReadCount();
|
count += ReadCount();
|
||||||
@ -811,7 +972,6 @@ namespace GameRes.Formats.WildBug
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] UnpackV0 (int[] offset_table, int pixel_size) // 0x00 format
|
byte[] UnpackV0 (int[] offset_table, int pixel_size) // 0x00 format
|
||||||
// int sub_40B83C(void *a1, FILE *stream, const void *ptr, unsigned int packed_size, int *a5, int unpacked_size, unsigned int pixel_size)
|
|
||||||
{
|
{
|
||||||
int min_count = 1 == pixel_size ? 2 : 1;
|
int min_count = 1 == pixel_size ? 2 : 1;
|
||||||
m_available = FillBuffer();
|
m_available = FillBuffer();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user