Click here to Skip to main content
16,020,459 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello! I'm making a simple game in C# and i'm trying to slice my UI images into 9 smaller rectangles, so
the image doesn't get stretched when drawing to different resolutions, but my current implementation does
not seems correct and i would like this method to look similar to the Unity3D sprite slicing editor.

I have the following method for slicing an image into rectangles:

C#
public class Sprite
{
	public Image texture;

	public PointF position;
	public SizeF size;
	public RectangleF rectangle;
	
	public RectangleF[] SliceRectangle(RectangleF rectangle, float left, float right, float top, float bottom)
	{
		float x = rectangle.X;
		float y = rectangle.Y;

		float left_width = (float) Math.Abs(Math.Sqrt(Math.Pow(left - rectangle.Left, 2)));
		float middle_width = (float) Math.Abs(Math.Sqrt(Math.Pow(left - right, 2)));
		float right_width = (float) Math.Abs(Math.Sqrt(Math.Pow(right - rectangle.Right, 2)));

		float top_height = (float) Math.Abs(Math.Sqrt(Math.Pow(top - rectangle.Top, 2)));
		float middle_height = (float) Math.Abs(Math.Sqrt(Math.Pow(top - bottom, 2)));
		float bottom_height = (float) Math.Abs(Math.Sqrt(Math.Pow(bottom - rectangle.Bottom, 2)));

		return new RectangleF[]
		{
			new RectangleF(x, y, left_width, top_height),			// top left
			new RectangleF(left, y, middle_width,  top_height),		// top center
			new RectangleF(right, y, right_width, top_height),		// top right

			new RectangleF(x, top, left_width, middle_height),		// middle left
			new RectangleF(left, top, middle_width, middle_height),		// middle center
			new RectangleF(right, top, right_width, middle_height),		// middle right

			new RectangleF(x, bottom, left_width, bottom_height),		// bottom left
			new RectangleF(left, bottom, middle_width, bottom_height),	// bottom center
			new RectangleF(right, bottom, right_width, bottom_height),	// bottom right
		};
	}
}


And then i draw the sliced image from the Sprite class like this:

C#
var sprite = new Sprite();

public void Render (Graphics graphics)
{
	sprite.rectangle = new RectangleF(0, 0, 512, 512);

	var destination_slices = sprite.SliceRectangle(rectangle: sprite.rectangle, left: 32, right: 480, top: 32, bottom: 480);
	var source_slices = sprite.SliceRectangle(rectangle: new RectangleF(0, 0, sprite.texture.Width, sprite.texture.Height), left: 32, right: 224, top: 16, bottom: 48);

	for (int i = 0; i < source_slices.Length; i++)
	{
		graphics.DrawImage(sprite.texture, destination_slices[i], source_slices[i], GraphicsUnit.Pixel);
		Debug.Log(source_slices[i]);
	}
}


Now, the problem with this method is:

. I also need to slice the main sprite rectangle, which makes no sense.
. If i set the padding of the main sprite rectangle wrong, it will mess with the whole drawing.
. If i make an simple editor for visually setting the paddings of a texture, i would also need to do it for the main rectangle.

Some specifications:

. I want the image to be sliced into smaller parts.
. The size of the image i'm drawing is 256 by 64 pixels.
. The area i want to draw the image is 512 by 512 pixels.
. The left/right/top/bottom values are basically lines that demarcates the bounds of each slice.

So, what can i do to fix these problems? Thanks in advance!

What I have tried:

I'm searching for a correct method to slice sprites since yesterday but did not found anything that solved my problem.
Posted
Updated 15-Sep-21 3:13am
v3
Comments
BillWoodruff 15-Sep-21 0:01am    
The size of your source image is 256x64 ? The only way you can fill an area 512x512 with that image is either stretch it (losing anamorphic scaling), use the source as tiles in 2 rows 8 columns.

Your calculations appear to calculate hypotenuses; why ?
strangerick 15-Sep-21 8:28am    
This seemed like the easiest way of doing it.

1 solution

See if this gives you some ideas:
// requires:
// using System.Collections.Generic;
// using System.Drawing;

// must be a top-level class: i.e., non-nested
public static class ShapeExtensions
{
    // rectangles returned in column-major order
    public static IEnumerable<RectangleF> RectFToRectsF(this RectangleF rectf, int nrows, int ncols)
    {
        float rh = rectf.Width / nrows;
        float cw = rectf.Width / ncols;

        for (int i = 0; i < ncols; i++)
        {
            for (int j = 0; j < nrows; j++)
            {
                yield return new RectangleF(cw * i, rh * j, rh, cw);
            }
        }
    }
}
Sample call:
// requires Linq
var cells = new RectangleF(0, 0, 512, 512).RectFToRectsF(3, 3);
Output
 ? cells.ToList()
Count = 9
    [0]: {X = 0 Y = 0 Width = 170.666672 Height = 170.666672}
    [1]: {X = 0 Y = 170.666672 Width = 170.666672 Height = 170.666672}
    [2]: {X = 0 Y = 341.333344 Width = 170.666672 Height = 170.666672}
    [3]: {X = 170.666672 Y = 0 Width = 170.666672 Height = 170.666672}
    [4]: {X = 170.666672 Y = 170.666672 Width = 170.666672 Height = 170.666672}
    [5]: {X = 170.666672 Y = 341.333344 Width = 170.666672 Height = 170.666672}
    [6]: {X = 341.333344 Y = 0 Width = 170.666672 Height = 170.666672}
    [7]: {X = 341.333344 Y = 170.666672 Width = 170.666672 Height = 170.666672}
    [8]: {X = 341.333344 Y = 341.333344 Width = 170.666672 Height = 170.666672}
 
Share this answer
 
Comments
strangerick 15-Sep-21 8:36am    
Hey, sorry for bothering, your method works but there is one part of the image missing and sometimes it just tiles the texture i don't know why, could you explain how to use it properly or improve it?

i'm drawing it like this:

var rect = new RectangleF(0, 0, 512, 512);
var cells = RectFToRectsF(rect, 3, 3);

foreach (var cell in cells)
{
e.Graphics.DrawImage(texture, rect, cell, GraphicsUnit.Pixel);
}

The image i'm drawing now is 190x49.
strangerick 15-Sep-21 9:12am    
This code seems to only tile the texture, not slice them into smaller textures the way i need. What can i do to accomplish this?
BillWoodruff 15-Sep-21 10:12am    
Don't worry, you are not bothering me :)

I think there's some aspect of what you are doing I can't, yet, understand: something to do with how you define textures ? or, use of sprites ? I would expect see textures in the context of 3-d rendering of object models ... sprites in WinForms are not something I've worked with.

See: https://www.codeproject.com/Articles/1085446/Using-Sprites-Inside-Windows-Forms

If you post links to pictures that show what you start with, and what you want to end up with, I'll take a look, as long as they can be accessed without registering on the site.

strangerick 15-Sep-21 10:42am    
Hey, thanks for the comment. I happened to fix the problem by changing some values and modifying the code a bit, so thanks for the answer, it works now.
BillWoodruff 15-Sep-21 11:11am    
great

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900