2
\$\begingroup\$

I have a texture created with SDL_TEXTUREACCESS_TARGET access and I want to get all its pixels with SDL_RenderReadPixels() function. One of the function parameters is pitch and I don't really know where can I can get it.

Texture is created with dimensions of a previously created surface, but function call with surface->pitch as pitch parameter generates EXC_BAD_ACCESS.

Texture and surface dimensions are 800x600, and surface->pitch returns 3200, which is strange for me, because I thought that pitch is the width of the texture in memory and expected surface->pitch to be something like 1024.

\$\endgroup\$
4
\$\begingroup\$

Pitch: the length of a row of pixels in bytes

Basically, if your texture/surface is 800px wide, and you have 4 bytes per pixel (32bit colour) then the pitch is 800x4 = 3200.

Use SDL_QueryTexture() to get texture format, the format can tell you how many bytes per pixel.


    SDL_QueryTexture(texture, &format, NULL, NULL, NULL);
    // Parse format with a switch
QueryTexture can also tell you the Access type, Width and Height.

SDL_PIXELFORMAT_RGB332 //8bit colour

...

SDL_PIXELFORMAT_RGB555 //15bit/16bit colour

...

SDL_PIXELFORMAT_ABGR8888 //32-bit colour

Note the last 3-4 numbers tell you how many bits are used for each colour, add them together to get the number of bits per pixel (bpp), then multiply bpp by width to get pitch.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Note, although not tested extensively, doing sizeof(SDL_PIXELFORMAT_ARGB8888) returns 4, which is what we need along with QueryTexture() to get the pitch (without having to hard code 4, 2, 1 for each macro) \$\endgroup\$ – jake Feb 12 '17 at 16:16
  • \$\begingroup\$ @jake That sizeof() is not doing what you think it's doing. It is returning the size of the SDL_PIXELFORMAT_ARGB8888 constant which is four bytes, not the size of the underlying pixel. Note that sizeof(SDL_PIXELFORMAT_RGB332) is also four. \$\endgroup\$ – janm Jul 10 '17 at 7:20
  • \$\begingroup\$ Interesting, I'll have to look into another solution :/ Any ideas? \$\endgroup\$ – jake Jul 11 '17 at 1:34
  • \$\begingroup\$ SDL_BYTESPERPIXEL macro, maybe? \$\endgroup\$ – Hydren Jul 21 at 22:23
2
\$\begingroup\$

You should use the pitch parameter of the surface, otherwise you're guessing. This is because the pitch can be padded on different systems or video cards (for extra data or optimization purposes -- any reason the vendor needs).

The only way to know for sure is to query the pitch value, otherwise you leave your program vulnerable to break on an unknown number of systems. It might be a large percentage or small percentage of systems, but either way it's a simple problem to avoid.

You stated that passing surface->pitch as a parameter causes an error. Possible causes are the surface being freed sooner in the program flow, the surface pointer not being assigned after initialization, or surface is pointing to an invalid/expired reference. You might also need to lock your surface before calling SDL_RenderReadPixels() as that might cause an access error as well.

Worst case, as a work-around, you can grab the pitch value early on (like right after you create the surface) and store it in a variable, and then pass that in as the pitch argument later.

  • It appears that there's some point in your code where calling surface->pitch doesn't cause an error -- since you stated that "surface->pitch returns 3200".
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.