Skip to content

Instantly share code, notes, and snippets.

@james4k
Created September 7, 2012 20:17
Show Gist options
  • Save james4k/3669270 to your computer and use it in GitHub Desktop.
Save james4k/3669270 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
namespace Limpleaf.Phorm.Content.Pipeline
{
enum SpriteSheetProcessorSpriteSize
{
x32 = 32,
x64 = 64,
x128 = 128,
x256 = 256,
x512 = 512,
}
[ContentProcessor(DisplayName = "Sprite sheet - Phorm")]
class SpriteSheetProcessor : TextureProcessor
{
[Browsable(false)]
public override bool ColorKeyEnabled { get { return false; } set { } }
[Browsable(false)]
public override Color ColorKeyColor { get; set; }
[DisplayName("Sprite Size")]
[Description("The size of each sprite in this sprite sheet.")]
[DefaultValue(SpriteSheetProcessorSpriteSize.x128)]
public SpriteSheetProcessorSpriteSize SpriteSize { get; set; }
public SpriteSheetProcessor()
{
SpriteSize = SpriteSheetProcessorSpriteSize.x128;
}
// Summary:
// Processes a texture.
//
// Parameters:
// input:
// The texture content to process.
//
// context:
// Context for the specified processor.
public override TextureContent Process(TextureContent input, ContentProcessorContext context)
{
foreach (var face in input.Faces)
for (int i = 0; i < face.Count; i += 1)
face[i] = ProcessBitmap(face[i]);
return base.Process(input, context);
}
BitmapContent ProcessBitmap(BitmapContent bitmap)
{
byte[] data = bitmap.GetPixelData();
// TODO: check the actual format
if (data.Length != bitmap.Width * bitmap.Height * 4)
{
throw new InvalidContentException("Unexpected bitmap format", bitmap.Identity);
}
int newWidth, newHeight;
byte[] newData = CreateNewBitmap(bitmap, data, out newWidth, out newHeight);
var newBitmap = new PixelBitmapContent<Byte4>(newWidth, newHeight);
newBitmap.SetPixelData(newData);
return newBitmap;
}
byte[] CreateNewBitmap(BitmapContent bitmap, byte[] oldData, out int width, out int height)
{
int spriteSize = (int)SpriteSize;
if (spriteSize == 0)
throw new Exception(String.Format("{0} is not a valid SpriteSize value.", SpriteSize));
if (bitmap.Width % spriteSize != 0 || bitmap.Height % spriteSize != 0)
throw new InvalidContentException(String.Format("Bitmap does not break evenly into x{0} sprites", spriteSize), bitmap.Identity);
int xsprites = bitmap.Width / spriteSize;
int ysprites = bitmap.Height / spriteSize;
width = xsprites * spriteSize + xsprites * 2;
height = ysprites * spriteSize + ysprites * 2;
byte[] data = new byte[width * height * 4];
for (int y = 0; y < bitmap.Height; y += 1)
{
int yoffsetOld = y * 4 * bitmap.Width;
int yoffset = y * 4 * width;
for (int x = 0; x < bitmap.Width; x += 1)
{
int oldOffset = x * 4 + yoffsetOld;
int offset = x * 4 + yoffset + (x / spriteSize + (x + spriteSize) / spriteSize) * 4 +
(y / spriteSize + (y + spriteSize) / spriteSize) * 4 * width;
CopyPixel(data, offset, oldData, oldOffset);
}
}
return data;
}
void CopyPixel(byte[] destBuf, int destOffset, byte[] srcBuf, int srcOffset)
{
destBuf[destOffset] = srcBuf[srcOffset];
destBuf[destOffset + 1] = srcBuf[srcOffset + 1];
destBuf[destOffset + 2] = srcBuf[srcOffset + 2];
destBuf[destOffset + 3] = srcBuf[srcOffset + 3];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment