diff --git a/src/Syroot.Worms.Armageddon/Team.cs b/src/Syroot.Worms.Armageddon/Team.cs
index 7d6576c..6df6595 100644
--- a/src/Syroot.Worms.Armageddon/Team.cs
+++ b/src/Syroot.Worms.Armageddon/Team.cs
@@ -81,7 +81,7 @@ namespace Syroot.Worms.Armageddon
///
/// Gets or sets the team grave bitmap if it uses a custom one.
///
- public RawBitmapData Grave { get; set; }
+ public RawBitmap Grave { get; set; }
///
/// Gets or sets the team's special weapon.
@@ -151,7 +151,7 @@ namespace Syroot.Worms.Armageddon
///
/// Gets or sets the bitmap of the team flag.
///
- public RawBitmapData Flag { get; set; }
+ public RawBitmap Flag { get; set; }
///
/// Gets or sets the deathmatch rank this team reached.
@@ -210,7 +210,7 @@ namespace Syroot.Worms.Armageddon
if (GraveSprite < 0)
{
GraveFileName = reader.ReadString(0x20);
- Grave = new RawBitmapData()
+ Grave = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(24, 32),
@@ -233,7 +233,7 @@ namespace Syroot.Worms.Armageddon
MissionStatuses = reader.ReadStructs(_missionCount);
FlagFileName = reader.ReadString(0x20);
- Flag = new RawBitmapData()
+ Flag = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(20, 17),
diff --git a/src/Syroot.Worms.Mgame/Igd.cs b/src/Syroot.Worms.Mgame/Igd.cs
index 0574aaa..656ec5a 100644
--- a/src/Syroot.Worms.Mgame/Igd.cs
+++ b/src/Syroot.Worms.Mgame/Igd.cs
@@ -2,7 +2,7 @@
using System.Drawing;
using System.IO;
using Syroot.BinaryData;
-using Syroot.Worms.Core.Graphics;
+using Syroot.Worms.Core;
namespace Syroot.Worms.Mgame
{
@@ -93,11 +93,12 @@ namespace Syroot.Worms.Mgame
// Decompress the data.
int dataSize = stream.ReadInt32();
int dataSizeCompressed = stream.ReadInt32();
- byte[] data = Decompress(stream, dataSizeCompressed, dataSize);
- // The actual image width is a multiple of 4.
- image.Bitmap = BitmapTools.CreateIndexed(new Size((image.Size.Width + 4 - 1) / 4 * 4, image.Size.Height),
- palette, data);
-
+ image.RawBitmap = new RawBitmap
+ {
+ Size = new Size(Algebra.NextMultiple(image.Size.Width, 4), image.Size.Height),
+ Palette = palette,
+ Data = Decompress(stream, dataSizeCompressed, dataSize)
+ };
Images.Add(image);
}
}
diff --git a/src/Syroot.Worms.Mgame/IgdImage.cs b/src/Syroot.Worms.Mgame/IgdImage.cs
index 6839a4a..f452794 100644
--- a/src/Syroot.Worms.Mgame/IgdImage.cs
+++ b/src/Syroot.Worms.Mgame/IgdImage.cs
@@ -14,6 +14,6 @@ namespace Syroot.Worms.Mgame
public int UnknownC { get; set; }
public Size Size { get; set; }
public Point Center { get; set; }
- public Bitmap Bitmap { get; set; }
+ public RawBitmap RawBitmap { get; set; }
}
}
diff --git a/src/Syroot.Worms.Mgame/Ksf.cs b/src/Syroot.Worms.Mgame/Ksf.cs
index 4f604ea..98b2636 100644
--- a/src/Syroot.Worms.Mgame/Ksf.cs
+++ b/src/Syroot.Worms.Mgame/Ksf.cs
@@ -2,7 +2,6 @@
using System.Drawing;
using System.IO;
using Syroot.BinaryData;
-using Syroot.Worms.Core.Graphics;
namespace Syroot.Worms.Mgame
{
@@ -95,7 +94,14 @@ namespace Syroot.Worms.Mgame
int dataLength = offsets[i + 1] - offset;
Size size = sizes[i];
if (!size.IsEmpty)
- images[i].Bitmap = BitmapTools.CreateIndexed(size, palette.Colors, stream.ReadBytes(dataLength));
+ {
+ images[i].RawBitmap = new RawBitmap
+ {
+ Size = size,
+ Palette = palette.Colors,
+ Data = stream.ReadBytes(dataLength)
+ };
+ }
Images.Add(images[i]);
}
diff --git a/src/Syroot.Worms.Mgame/KsfImage.cs b/src/Syroot.Worms.Mgame/KsfImage.cs
index 8b6aec6..c844ea7 100644
--- a/src/Syroot.Worms.Mgame/KsfImage.cs
+++ b/src/Syroot.Worms.Mgame/KsfImage.cs
@@ -10,6 +10,6 @@ namespace Syroot.Worms.Mgame
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
public Point Center { get; set; }
- public Bitmap Bitmap { get; set; }
+ public RawBitmap RawBitmap { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Syroot.Worms.Scratchpad/Program.cs b/src/Syroot.Worms.Scratchpad/Program.cs
index e437577..0657864 100644
--- a/src/Syroot.Worms.Scratchpad/Program.cs
+++ b/src/Syroot.Worms.Scratchpad/Program.cs
@@ -36,7 +36,7 @@ namespace Syroot.Worms.Scratchpad
{
string pngFileName = Path.ChangeExtension(i.ToString(), "png");
IgdImage image = igd.Images[i];
- image.Bitmap.Save(Path.Combine(pngIgdFolder, pngFileName), ImageFormat.Png);
+ image.RawBitmap.ToBitmap().Save(Path.Combine(pngIgdFolder, pngFileName), ImageFormat.Png);
}
}
}
@@ -65,7 +65,7 @@ namespace Syroot.Worms.Scratchpad
for (int i = 0; i < ksf.Images.Count; i++)
{
string pngFileName = Path.ChangeExtension(i.ToString(), "png");
- ksf.Images[i].Bitmap?.Save(Path.Combine(pngKsfFolder, pngFileName), ImageFormat.Png);
+ ksf.Images[i].RawBitmap?.ToBitmap().Save(Path.Combine(pngKsfFolder, pngFileName), ImageFormat.Png);
}
}
}
diff --git a/src/Syroot.Worms.WorldParty/Team.cs b/src/Syroot.Worms.WorldParty/Team.cs
index 5fd01be..ffad627 100644
--- a/src/Syroot.Worms.WorldParty/Team.cs
+++ b/src/Syroot.Worms.WorldParty/Team.cs
@@ -79,7 +79,7 @@ namespace Syroot.Worms.WorldParty
///
/// Gets or sets the team grave bitmap if it uses a custom one.
///
- public RawBitmapData Grave { get; set; }
+ public RawBitmap Grave { get; set; }
///
/// Gets or sets the team's special weapon.
@@ -149,7 +149,7 @@ namespace Syroot.Worms.WorldParty
///
/// Gets or sets the bitmap of the team flag.
///
- public RawBitmapData Flag { get; set; }
+ public RawBitmap Flag { get; set; }
///
/// Gets or sets an unknown value.
@@ -209,7 +209,7 @@ namespace Syroot.Worms.WorldParty
if (GraveSprite < 0)
{
GraveFileName = reader.ReadString(0x20);
- Grave = new RawBitmapData()
+ Grave = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(24, 32),
@@ -232,7 +232,7 @@ namespace Syroot.Worms.WorldParty
MissionStatuses = reader.ReadStructs(_missionCount);
FlagFileName = reader.ReadString(0x20);
- Flag = new RawBitmapData()
+ Flag = new RawBitmap()
{
BitsPerPixel = 8,
Size = new Size(20, 17),
diff --git a/src/Syroot.Worms/Core/Algebra.cs b/src/Syroot.Worms/Core/Algebra.cs
new file mode 100644
index 0000000..68c9a76
--- /dev/null
+++ b/src/Syroot.Worms/Core/Algebra.cs
@@ -0,0 +1,16 @@
+namespace Syroot.Worms.Core
+{
+ ///
+ /// Represents mathemtical helper utilities.
+ ///
+ public static class Algebra
+ {
+ ///
+ /// Gets the nearest, bigger of the given .
+ ///
+ /// The value whose nearest, bigger multiple will be returned of.
+ /// The multiple to return.
+ /// The nearest, bigger multiple.
+ public static int NextMultiple(int value, int multiple) => (value + multiple - 1) / multiple * multiple;
+ }
+}
diff --git a/src/Syroot.Worms/Core/ByteExtensions.cs b/src/Syroot.Worms/Core/ByteExtensions.cs
index b18ee47..1ef38c9 100644
--- a/src/Syroot.Worms/Core/ByteExtensions.cs
+++ b/src/Syroot.Worms/Core/ByteExtensions.cs
@@ -15,10 +15,7 @@ namespace Syroot.Worms.Core
/// The extended instance.
/// The 0-based index of the bit to enable.
/// The current byte with the bit enabled.
- public static byte EnableBit(this byte self, int index)
- {
- return (byte)(self | (1 << index));
- }
+ public static byte EnableBit(this byte self, int index) => (byte)(self | (1 << index));
///
/// Returns the current byte with the bit at the cleared (being 0).
@@ -26,10 +23,7 @@ namespace Syroot.Worms.Core
/// The extended instance.
/// The 0-based index of the bit to disable.
/// The current byte with the bit disabled.
- public static byte DisableBit(this byte self, int index)
- {
- return (byte)(self & ~(1 << index));
- }
+ public static byte DisableBit(this byte self, int index) => (byte)(self & ~(1 << index));
///
/// Returns a value indicating whether the bit at the in the current byte is enabled
@@ -38,10 +32,7 @@ namespace Syroot.Worms.Core
/// The extended instance.
/// The 0-based index of the bit to check.
/// true when the bit is set; otherwise false.
- public static bool GetBit(this byte self, int index)
- {
- return (self & (1 << index)) != 0;
- }
+ public static bool GetBit(this byte self, int index) => (self & (1 << index)) != 0;
///
/// Returns the current byte with all bits rotated in the given , where positive
@@ -97,10 +88,7 @@ namespace Syroot.Worms.Core
/// The number of least significant bits which are used to store the
/// value.
/// The decoded .
- public static byte DecodeByte(this byte self, int bits)
- {
- return DecodeByte(self, bits, 0);
- }
+ public static byte DecodeByte(this byte self, int bits) => DecodeByte(self, bits, 0);
///
/// Returns an instance represented by the given number of , starting
@@ -124,10 +112,7 @@ namespace Syroot.Worms.Core
/// The number of least significant bits which are used to store the
/// value.
/// The decoded .
- public static sbyte DecodeSByte(this byte self, int bits)
- {
- return DecodeSByte(self, bits, 0);
- }
+ public static sbyte DecodeSByte(this byte self, int bits) => DecodeSByte(self, bits, 0);
///
/// Returns an instance represented by the given number of , starting
@@ -154,10 +139,7 @@ namespace Syroot.Worms.Core
/// The value to encode.
/// The number of bits which are used to store the value.
/// The current byte with the value encoded into it.
- public static byte Encode(this byte self, byte value, int bits)
- {
- return Encode(self, value, bits, 0);
- }
+ public static byte Encode(this byte self, byte value, int bits) => Encode(self, value, bits, 0);
///
/// Returns the current byte with the given set into the given number of
@@ -187,10 +169,7 @@ namespace Syroot.Worms.Core
/// The value to encode.
/// The number of bits which are used to store the value.
/// The current byte with the value encoded into it.
- public static byte Encode(this byte self, sbyte value, int bits)
- {
- return Encode(self, value, bits, 0);
- }
+ public static byte Encode(this byte self, sbyte value, int bits) => Encode(self, value, bits, 0);
///
/// Returns the current byte with the given set into the given number of
diff --git a/src/Syroot.Worms/Core/Graphics/RawBitmap.cs b/src/Syroot.Worms/Core/Graphics/RawBitmap.cs
new file mode 100644
index 0000000..0747852
--- /dev/null
+++ b/src/Syroot.Worms/Core/Graphics/RawBitmap.cs
@@ -0,0 +1,64 @@
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using Syroot.Worms.Core;
+
+namespace Syroot.Worms
+{
+ ///
+ /// Represents a pixel-based 2D image in different color formats.
+ ///
+ public class RawBitmap
+ {
+ // ---- PROPERTIES ---------------------------------------------------------------------------------------------
+
+ ///
+ /// Gets or sets the number of bits required to describe a color per pixel.
+ ///
+ public byte BitsPerPixel { get; set; }
+
+ ///
+ /// Gets or sets the colors in the palette of the bitmap, if it has one.
+ ///
+ public IList Palette { get; set; }
+
+ ///
+ /// Gets or sets the size of the image in pixels.
+ ///
+ public Size Size { get; set; }
+
+ ///
+ /// Gets or sets the data of the image pixels.
+ ///
+ public byte[] Data { get; set; }
+
+ // ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
+
+ ///
+ /// Creates a from the raw data.
+ ///
+ /// The created from the raw data.
+ public Bitmap ToBitmap()
+ {
+ using (DisposableGCHandle dataPin = new DisposableGCHandle(Data, GCHandleType.Pinned))
+ {
+ // Transfer the pixel data, respecting power-of-2 strides.
+ Bitmap bitmap = new Bitmap(Size.Width, Size.Height, PixelFormat.Format8bppIndexed);
+ BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
+ ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
+ for (int y = 0; y < Size.Height; y++)
+ Marshal.Copy(Data, y * Size.Width, bitmapData.Scan0 + y * bitmapData.Stride, Size.Width);
+ bitmap.UnlockBits(bitmapData);
+
+ // Transfer the palette.
+ ColorPalette bitmapPalette = bitmap.Palette;
+ for (int i = 0; i < Palette.Count; i++)
+ bitmapPalette.Entries[i] = Palette[i];
+ bitmap.Palette = bitmapPalette;
+
+ return bitmap;
+ }
+ }
+ }
+}
diff --git a/src/Syroot.Worms/Img.cs b/src/Syroot.Worms/Img.cs
index a6fb4a6..ea2645d 100644
--- a/src/Syroot.Worms/Img.cs
+++ b/src/Syroot.Worms/Img.cs
@@ -12,7 +12,7 @@ namespace Syroot.Worms
/// Represents a (palettized) graphical image stored in an IMG file, possibly compressed.
/// Used by W2, WA and WWP. S. https://worms2d.info/Image_file.
///
- public class Img : RawBitmapData, ILoadableFile, ISaveableFile
+ public class Img : RawBitmap, ILoadableFile, ISaveableFile
{
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
@@ -203,8 +203,8 @@ namespace Syroot.Worms
// Write the image palette if available. The first color of the palette is implicitly black.
if (Palette != null)
{
- writer.Write((short)(Palette.Length - 1));
- for (int i = 1; i < Palette.Length; i++)
+ writer.Write((short)(Palette.Count - 1));
+ for (int i = 1; i < Palette.Count; i++)
{
Color color = Palette[i];
writer.Write(color.R);
diff --git a/src/Syroot.Worms/RawBitmapData.cs b/src/Syroot.Worms/RawBitmapData.cs
deleted file mode 100644
index 4432352..0000000
--- a/src/Syroot.Worms/RawBitmapData.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Drawing;
-
-namespace Syroot.Worms
-{
- ///
- /// Represents a pixel-based 2D image in different color formats.
- ///
- public class RawBitmapData
- {
- // ---- PROPERTIES ---------------------------------------------------------------------------------------------
-
- ///
- /// Gets or sets the number of bits required to describe a color per pixel.
- ///
- public byte BitsPerPixel { get; set; }
-
- ///
- /// Gets or sets the colors in the palette of the bitmap, if it has one.
- ///
- public Color[] Palette { get; set; }
-
- ///
- /// Gets or sets the size of the image in pixels.
- ///
- public Size Size { get; set; }
-
- ///
- /// Gets or sets the data of the image pixels.
- ///
- public byte[] Data { get; set; }
- }
-}