Search code examples
c#monogame

How to get the "edges" of a single dimensional array


Explanation

I'm generating textures for UI elements that have a single pixel outline on the edge of the texture.

The method of setting the color data in the texture is limited to passing a one dimensional array of color values.

These textures are 2D, so they are basically rectangles. I need to be able to identify when the current pixel is at an edge. This is how I currently do it:

Color[] colorData = new Color[width * height];
        for (int p = 0; p < colorData.Length; p++) {

            //Top
            if (p < width - 1) {

                colorData[p] = DefaultOutlineColor;
            }    
            //Left
            else if(p % width == 0) {
                colorData[p] = DefaultOutlineColor;
            }
            //Right
            else if(p % height == height - outlineWidth) {
                colorData[p] = DefaultOutlineColor;
            }
            //Bottom
            else if(p >= width * (height - outlineWidth)) {
                colorData[p] = DefaultOutlineColor;
            }
            //Fill
            else {
                colorData[p] = DefaultBaseColor;
            }
        }

The Problem

Some Modulo math and what not. The problem I am having is with the Right side of the Texture. More specifically calculating the right side edge. A picture is worth a thousand words:

UI Texture

I know it is just a miss calculation in the Right edge part. But I have no idea how to make it work. Any help would be highly appreciated.

EDIT: Figured it out. Here is the working code:

        //Fill
        for (int p = 0; p < colorData.Length; p++) {

            colorData[p] = DefaultBaseColor;
        }

        //Top
        for (int p = 0; width * outlineWidth > p; p++) {

            colorData[p] = DefaultOutlineColor;
        }

        //Left and Right
        for (int p = 1; height > p; p++) {

            for (int i = 0; i < outlineWidth; i++) {

                colorData[(p * width) + i] = DefaultOutlineColor; //Left
                colorData[((p * width) - i) - 1] = DefaultOutlineColor; //Right
            }

        }

        //Bottom
        for (int p = width * height - (width * outlineWidth); colorData.Length > p; p++) {

           colorData[p] = DefaultOutlineColor;
        }

Solution

  • Why not do it in three loops? One for the top, one for the left and right and then one for the bottom? That way you can skip all the items that don't need to be touched at all.

    for(int ndx = 0; Width > ndx; ++ndx)
    {
      colorData[ndx] = DefaultOutlineColor;
    }
    
    for(int ndx = 1; Height > ndx; ++ndx)
    {
      colorDatandx * Widthp] = DefaultOutlineColor;
      colorData[ndx*Width + Width] = DefaultOutlineColor;}
    }
    
    for(int ndx = Width * Height - Width; Length > ndx; ++ndx)
    {
      colorDatandxp] = DefaultOutlineColor;
    }