0

I am making a little game in WPF, and I want to make my character's movement continuous by using a spritesheet that I extracted from another game's installation folder.

I do not know how to cut out the required portion of the spritesheet image without the 'separating' black background.

Here's the spritesheet showing my character's various movements

I can only use classes for visualization that are inherited from the classes System.Windows.Media.Drawing OR System.Windows.Media.Visual

(it's for an assignment at the uni and they make us choose from one of these)

L.Z.
  • 11
  • 1
  • In WPF, you can generate a transparency mask. This mask should be everything you want to be invisible. – Gusdor Dec 28 '17 at 19:31
  • The easiest thing to do would be to make the black background transparent in the source image. – Bradley Uffner Dec 28 '17 at 20:51
  • If it is the "certain part" of the sprite sheet you are having problems with, you can use an [`ImageBrush`](https://msdn.microsoft.com/en-us/library/system.windows.media.imagebrush(v=vs.110).aspx) with [`Viewbox`](https://msdn.microsoft.com/en-us/library/system.windows.media.tilebrush.viewbox(v=vs.110).aspx) property set to the bounds of the frame you want to display. You can then use that `ImageBrush` as the `Fill` of something like a `Rectangle`. – Bradley Uffner Dec 28 '17 at 21:05

1 Answers1

0

If not required to solve this in code, a quick solution is to use an image editing application:

  1. Ensure the background has an alpha channel.
  2. Use the magic wand tool to select each isolated background part.
  3. delete the selection.

To convert the background to transparency. I did this to your image with the magic wand tolerance set to 0 using paint.net in just a few seconds.

Otherwise use an opacity mask.

Though not meeting your assignment's criteria, another solution is to replace all background pixels at runtime. If you do this, save the result to disk so you only incur the cost once. This is essentially a DIY of the first solution I described. i.e.

// someBitmap is the bitmap you want to manipulate.

// Ensure we're reading from a bitmap in Bgra32 format.
var srcBitmap = someBitmap.Format == PixelFormats.Bgra32 ?
    (BitmapSource)someBitmap : new FormatConvertedBitmap(someBitmap, PixelFormats.Bgra32, null, 0);

// Copy the pixels of the source image to a buffer we can use.
var width = srcBitmap.PixelWidth;
var height = srcBitmap.PixelHeight;
var stride = width * 4;
var byteCount = height * stride;
var srcData= new byte[byteCount];
srcBitmap.CopyPixels(srcData, stride, 0);

var destBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
var destData = new byte[byteCount];

// The channel offsets for PixelFormats.Bgra32.
const int BlueOffset = 0;
const int GreenOffset = 1;
const int RedOffset = 2;
const int AlphaOffset = 3;

// Copy the image, filtering out the background.
for (var y = 0; y < height; y++) { // Each column.
    for (var x = 0; x < width; x++) { // Each row.
        var i = (y * width + x) * 4; // The offset of this pixel in both srcBytes and destBytes.
        var b = srcData[i + BlueOffset];
        var g = srcData[i + GreenOffset];
        var r = srcData[i + RedOffset];
        var a = srcData[i + AlphaOffset];

        // The "filter".
        if (b == 0 && g == 0 && r == 0 && a == 255) {
            // The pixel is solid black(the background color), set to transparent.
            a = 0;
        }

        destData[i + BlueOffset] = b;
        destData[i + GreenOffset] = g;
        destData[i + RedOffset] = r;
        destData[i + AlphaOffset] = a;
    }
}
// Update the final image with the filtered buffer.
destBitmap.WritePixels(new Int32Rect(0, 0, width, height), destData, stride, 0);

// Finally, convert destBitmap to a BitmapImage and use that in place of someBitmap.

See this answer for converting destBitmap to a BitmapImage.

Koby Duck
  • 1,118
  • 7
  • 15
  • I tried your first suggestion (using paint.net) and I could delete the black parts of the image. The problem is whenever I save the modified image, it saves it with white background instead of a fully transparent background. Tried to display it in WPF, it shows my character in a white rectangle. So the original problem still remains unsolved (it's just that I now have white background instead of black). Any advice on this one? I also tried using Opacity Mask, but I don't really understand how it works yet. (Though I will keep trying to understand it.) – L.Z. Dec 29 '17 at 06:14
  • Did you save it as bmp or jpg? paint.net doesn't save transparency with bmp or jpg. Save as png instead. – Koby Duck Dec 29 '17 at 06:22
  • That was the problem. Saving as .png works. Thank you. – L.Z. Dec 29 '17 at 06:35