[XNA] Texture2D Crop

Started by
5 comments, last by Ghost Clock 11 years, 8 months ago
I need some kind of formula to crop down a Texture2D. The textures are not loading as assets nor saved to jpeg or png at any point, they're created on the fly by the game.
ex1q.png
to
ex2f.png

Not all of the white needs to be removed, just minimized down until the black shape is touched by the edges.

I'm thinking it would look something like (but not necessarily exact)

Texture2D Crop(Color excess)
{
// Forumula for cropping
return resultingTexture;
}

I was thinking maybe something with a Color[] but I couldn't think of way to make that work.
Advertisement
So XNA will let you load the color[] data from a texture2D object with Texture2D.GetData(), and through the Width and Height properties of the object, you have the dimensions handy. It's not the most efficient algorithm, but you could loop through rows first, then columns, determining at what index in the row/column the color shifts over the "culling" threshold (i.e. coming form the left, which index is the first to switch from white to black, and then what's the index from black back to white). Store the biggest index ranges across all rows and columns (which will give you the smallest dimensions that still contain your 'good' pixels), and then copy in the relevant data to a new, smaller color[] with the dimensions you just calculated. (System.Array has handy methods for copying select ranges of data).

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

You can use Texture2D.GetData to get a Color[] representation of the texture. Are you generating these images on the GPU? Because if the images are created on the CPU, you don't have to get the data in the first place.


Texture2D Crop(Color[] data, int width, int height, Color excess)
{
int x1 = width, x2 = 0, y1 = height, y2 = 0;
for (int i = 0; i < width * height; i++)
{
if (data != excess)
{
int y = i / width;
int x = i % width;
x1 = Math.Min(x, x1);
x2 = Math.Max(x, x2);
y1 = Math.Min(y, y1);
y2 = Math.Max(y, y2);
}
}
Rectangle cropped = new Rectangle(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
Color[] newData = new Color[cropped.Width * cropped.Height];
for (int y = 0; y < cropped.Height; y++)
{
for (int x = 0; x < cropped.Width; x++)
{
int newIndex = y * cropped.Width + x;
int oldIndex = (y + cropped.Y) * width + (x + cropped.X);
newData[newIndex] = data[oldIndex];
}
}
Texture2D texture = new Texture2D(this.GraphicsDevice, cropped.Width, cropped.Height);
texture.SetData(newData);
return texture;
}

current project: Roa


You can use Texture2D.GetData to get a Color[] representation of the texture. Are you generating these images on the GPU? Because if the images are created on the CPU, you don't have to get the data in the first place.


//some slick stuff here



Yes, like that! What I meant, only much cleaner and more efficient :) Describing algorithms is much easier if you just show someone the actual code...

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

[quote name='lwm' timestamp='1346164394' post='4974124'][/quote]
First off, thank you. This is definitely a good start. Here's the issues. Trying your code directly in a new project (1 update call, crop, exit, save as), my first image in the first post results in this.
ex3vc.png
This happens to be the most dramatic example so far. Other examples show me getting the bottom and right edges cut off 1 row too much. I'm going to look at the math and see if I can't pin this down, if anyone else would take a look I'd appreciate it too.

Thanks again, I think this is really really close to what I need.
Ha, I knew I shouldn't have used the Rectangle. smile.png I fixed the code in my previous post.

current project: Roa


Ha, I knew I shouldn't have used the Rectangle. smile.png I fixed the code in my previous post.

Dead on accurate. Thank you, this method will get plenty of usage.

This topic is closed to new replies.

Advertisement