There's still a bug with the colors, please ignore it.
Don't wonder if the search takes some time. :-)
Code:
public partial class Form1 : Form
{
static Pattern startpattern = new Pattern(@"
9C 00 ?? ?? 00 ?? ?? ?? 00 00 00 00 00 00 00 00
00 ?? ?? ?? ?? ?? ?? 00 ?? ?? ?? ?? 00 00 00 ??
?? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00
");
public Form1()
{
InitializeComponent();
byte[] buffer = null;
int startposition = 0;
Pattern searchpattern = startpattern;
int width = 0;
int height = 0;
using (Stream s = new StreamReader("I:\\PathOfExile.DMP").BaseStream)
{
buffer = new byte[2013265920];
s.Read(buffer, 0, buffer.Length);
for (int i = 0; i < buffer.Length; i++)
{
bool equals = true;
for (int ii = 0; ii < searchpattern.Data.Length; ii++)
{
if (!searchpattern.Data[ii].Skip)
{
var pde = (PatternDefienedEntry)searchpattern.Data[ii];
if (buffer[i + ii] != pde.Byte)
{
equals = false;
break;
}
}
}
if (equals)
{
startposition = i;
break;
}
}
buffer = new byte[2];
s.Position = startposition + 31;
s.Read(buffer, 0, 2);
width = (buffer[0] << 8) | buffer[1];
buffer = new byte[2];
s.Position = startposition + 18;
s.Read(buffer, 0, 2);
height = ((buffer[0] << 8) | buffer[1]) / 2;
int length = width * height / 2;
buffer = new byte[length];
s.Position = startposition + 64;
s.Read(buffer, 0, (int)length);
}
var img = GenerateImage(buffer, width, height);
this.BackgroundImage = img;
}
class Pattern
{
public IPatternEntry[] Data
{
get;
protected set;
}
public Pattern(string value)
{
List<IPatternEntry> data = new List<IPatternEntry>();
value = value.Replace("\r", "").Replace("\n", "").Replace(" ", "").Replace("\t", "");
for (int i = 0; i < value.Length; i += 2)
{
string hex = value.Substring(i, 2);
if (hex == "??")
{
data.Add(new PatternUndefienedEntry());
}
else
{
data.Add(new PatternDefienedEntry(Convert.ToByte(hex, 16)));
}
}
this.Data = data.ToArray();
}
}
interface IPatternEntry
{
bool Skip { get; }
}
public class PatternDefienedEntry : IPatternEntry
{
public bool Skip { get { return false; } }
public byte Byte
{
get;
protected set;
}
public PatternDefienedEntry(byte value)
{
this.Byte = value;
}
}
public class PatternUndefienedEntry : IPatternEntry
{
public bool Skip { get { return true; } }
}
private Image GenerateImage(byte[] data, int width, int height)
{
Bitmap bmp = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.Yellow);
}
BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int bytes = Math.Abs(bmData.Stride) * height;
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
byte[] p = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(Scan0, p, 0, bytes);
int i = 0;
int nOffset = stride - width * 3;
int nPixel;
int y = 0;
int x = 0;
for (var ib = 0; ib < data.Length; ib += 8)
{
Color[] colors = new Color[4];
UInt16 color0 = (UInt16)(data[ib] << 8 | data[ib + 1]);
colors[0] = GetColor(color0);
UInt16 color1 = (UInt16)(data[ib + 2] << 8 | data[ib + 3]);
colors[1] = GetColor(color1);
if (color0 > color1)
{
colors[2] = GetColor((UInt16)((2 * color0 + color1) / 3));
colors[3] = GetColor((UInt16)((color0 + 2 * color1) / 3));
}
else
{
colors[2] = GetColor((UInt16)((color0 + color1)/ 2));
colors[3] = Color.Transparent;
}
if (x + 4 > width)
{
x = 0;
y += 4;
}
if (y >= height)
break;
for (int iy = 0; iy < 4; iy++)
{
byte value = data[ib + 4 + iy];
for (int ix = 0; ix < 4; ix++)
{
byte colorvalue = (byte)(value << ((3-ix) * 2));
colorvalue = (byte)(colorvalue >> 6);
Color color = colors[colorvalue];
p[(y + iy) * stride + (x + ix) * 4 + 3] = color.A;
p[(y + iy) * stride + (x + ix) * 4 + 2] = color.R;
p[(y + iy) * stride + (x + ix) * 4 + 1] = color.G;
p[(y + iy) * stride + (x + ix) * 4 + 0] = color.B;
}
}
x+=4;
}
System.Runtime.InteropServices.Marshal.Copy(p, 0, Scan0, bytes);
bmp.UnlockBits(bmData);
return bmp;
}
private Color GetColor(UInt16 value)
{
byte[] data = BitConverter.GetBytes(value);
byte red = (byte)(data[0] >> 3);
byte green1 = (byte)(data[0] << 5);
green1 = (byte)(green1 >> 2);
byte blue = (byte)(data[1] << 3);
blue = (byte)(blue >> 3);
byte green2 = (byte)(data[1] >> 5);
byte green = (byte)(green1 | green2);
return Color.FromArgb((byte)(red * (255 / 31)), (byte)(green * (255 / 63)), (byte)(blue * (255 / 31)));
}
}