Select specific pixels of an image

ghz 8months ago ⋅ 87 views

I'm using C and stb_image, and image data is stored in an unsigned char* where a group of 4 elements represents a pixel, with r, g, b, and a channels respectively. I'm trying to get pixels of part of an image, for a sort of spritesheet loader. Currently I have this:

static void getGlyphTexture(unsigned char *dataOut, unsigned char *dataIn, size_t bitmapWidth, size_t glyphSize, size_t index) {
    for (size_t y = 0; y < glyphSize; y++) {
        for (size_t x = 0; x < glyphSize; x++) {
            dataOut[4 * (glyphSize * x + y) + 0] = dataIn[4 * (bitmapWidth * x + y) + 0];
            dataOut[4 * (glyphSize * x + y) + 1] = dataIn[4 * (bitmapWidth * x + y) + 1];
            dataOut[4 * (glyphSize * x + y) + 2] = dataIn[4 * (bitmapWidth * x + y) + 2];
            dataOut[4 * (glyphSize * x + y) + 3] = dataIn[4 * (bitmapWidth * x + y) + 3];
        }
    }
}

The above code takes in an image dataIn and outputs part of the image into dataOut. It works fine right now, copying the very first segment of the image, of glyphSize * glyphSize dimensions.

enter image description here

However, I cannot figure out the math to get the pixels offset from that starting point, say to get this part of the spritesheet.

enter image description here

I either get a buffer overflow error, or the data is not correct at all. Does anyone have any idea on the correct math to manipulate the array to select all the latter parts of the image?

Answers

To modify your code to extract a specific part of the image, you need to adjust the starting point from where you begin copying pixels. Here's how you can modify your getGlyphTexture function to achieve this:

static void getGlyphTexture(unsigned char *dataOut, unsigned char *dataIn, size_t bitmapWidth, size_t glyphSize, size_t indexX, size_t indexY) {
    for (size_t y = 0; y < glyphSize; y++) {
        for (size_t x = 0; x < glyphSize; x++) {
            size_t srcIndex = 4 * ((indexY * glyphSize + y) * bitmapWidth + (indexX * glyphSize + x));
            size_t destIndex = 4 * (glyphSize * y + x);
            dataOut[destIndex + 0] = dataIn[srcIndex + 0]; // Red channel
            dataOut[destIndex + 1] = dataIn[srcIndex + 1]; // Green channel
            dataOut[destIndex + 2] = dataIn[srcIndex + 2]; // Blue channel
            dataOut[destIndex + 3] = dataIn[srcIndex + 3]; // Alpha channel
        }
    }
}

Here's how the changes work:

  • indexX and indexY represent the starting indices of the region you want to copy.
  • Inside the nested loops, indexX * glyphSize and indexY * glyphSize determine the starting point in the dataIn array from where you begin copying.
  • The variable srcIndex calculates the index in the dataIn array corresponding to the current pixel being copied.
  • destIndex calculates the index in the dataOut array where the pixel will be copied.

With these changes, you should be able to specify the starting indices of the region you want to extract from the image. For example, to extract the region shown in the second image you provided, you would call the function like this:

getGlyphTexture(dataOut, dataIn, bitmapWidth, glyphSize, 1, 2);

This would copy the region starting from the second column and the third row of glyphs. Adjust the values of indexX and indexY accordingly to extract different regions of the image.