Home > Software engineering >  Can you assign values to all elements in struct for a 2D array in C?
Can you assign values to all elements in struct for a 2D array in C?

Time:09-16

I want to make a grayscale filter so I have to assign the average of all 3 RGB values to each. I use a 2D array because this is a bitmap image and I'm filtering it by changing each pixel.

This is how the struct is defined (where BYTE is uint8_t):

typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

Do I need to assign the value to each element of struct separately, like I did below, or is there a way to assign that value to all elements of the struct (since they are the same type) in that specific location in the array at once?

This is the code for the filtering function.

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i  )
    {
        for (int j = 0 ; j < width; j  )
        {
            image[i][j].rgbtBlue = (image[i][j].rgbtBlue   image[i][j].rgbtRed   image[i][j].rgbtGreen)/3;
            image[i][j].rgbtGreen = (image[i][j].rgbtBlue   image[i][j].rgbtRed   image[i][j].rgbtGreen)/3;
            image[i][j].rgbtRed = (image[i][j].rgbtBlue   image[i][j].rgbtRed   image[i][j].rgbtGreen)/3;
        }
    }
    return;
}

CodePudding user response:

You can do it with a compound literal:

RGBTRIPLE x = image[i][j];  // Use temporary to reduce repetition.
BYTE t = (x.rgbtBlue   x.rgbtRed   x.rgbtGreen)/3;
image[i][j] = (RGBTRIPLE) { t, t, t };

CodePudding user response:

You can certainly avoid making the calculation three times on each loop. Two obvious ways to do this are:

(1) Chain the assignments (note that expressions like a = b = 3; are valid C and the = operator associates right-to-left);

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i  )
    {
        for (int j = 0; j < width; j  )
        {
            image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed =
                (image[i][j].rgbtBlue   image[i][j].rgbtRed   image[i][j].rgbtGreen) / 3;
        }
    }
    return;
}

(2) Calculate that 'gray' value and assign that to the array element (in one go) using a compound literal constructed from that calculated value:

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i  )
    {
        for (int j = 0; j < width; j  )
        {
            BYTE gray = (image[i][j].rgbtBlue   image[i][j].rgbtRed   image[i][j].rgbtGreen) / 3;
            image[i][j] = (RGBTRIPLE){ gray, gray, gray };
        }
    }
    return;
}

Whether or not either of the above actually constitutes an improvement is subjective (and a good compiler will likely generate the same code in both cases). However, for more complex situations, these techniques can make your code clearer and its purpose easier for a reader to understand.


Note also that, as pointed out in the comments, the above two examples will assign the same value to each of the three components of the image[i][j] element. In your posted code, the second and third recalculations use one or two values that will have been modified by the previous line(s).

  • Related