【问题标题】:Access pixel color from SDL_Texture从 SDL_Texture 访问像素颜色
【发布时间】:2017-11-15 08:32:40
【问题描述】:

我的代码引发访问错误。这是代码:

SDL_Color *getPixelColor(SDL_Surface *loadingSurface, int x, int y) {

    SDL_Color getColor = {0,0,0};

    SDL_Texture *readingTexture = nullptr;
    readingTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, loadingSurface->w, loadingSurface->h);
    SDL_SetTextureBlendMode(readingTexture, SDL_BLENDMODE_BLEND);

    void * vPixels;

    SDL_LockTexture(readingTexture, &loadingSurface->clip_rect, &vPixels, &loadingSurface->pitch);

    memcpy(vPixels, loadingSurface->pixels, loadingSurface->w * loadingSurface->h);

    Uint32 *aPixels = (Uint32*)vPixels;

    SDL_UnlockTexture(readingTexture);

    //Get pixel at location.
    Uint32 getPixel = aPixels[y * loadingSurface->w + x];
    Uint8 *colors = (Uint8*)getPixel;

    //cout << colors[0] << " " << colors[1] << " " << colors[2] << endl;

    getColor.r = colors[0];
    getColor.g = colors[1];
    getColor.b = colors[2];

    SDL_Color *color = &getColor;
    return color;

}

抛出异常:读取访问冲突。 颜色为 0xFF00。

任何时候我都会尝试访问颜色。 SDL 文档中描述的方法都返回相同的错误,并且互联网上除了 LazyFoo 之外没有任何信息(此方法基于该方法,但它不起作用。)

感谢您的帮助。

编辑:

我通过重新编写代码来修复我的代码,并忽略了一些我用来理解 SDL 某些部分的错误来源。这是工作代码:

Uint32 getPixel(SDL_Surface *loadingSurface, int x, int y) {

    Uint32 *pixels = (Uint32*)loadingSurface->pixels;
    return pixels[(y * loadingSurface->pitch / 4) + x]; // I noticed that each y selection was off by 4 pixels in the y so I divided by 4. Why this is the case remains a mystery.

}

为什么我需要除以 4 是个谜,我花了一段时间才弄明白。任何想法为什么?

SDL_Color getPixelColor(SDL_Surface *loadingSurface, int x, int y) {

    SDL_Color getColor = {0,0,0};
    SDL_PixelFormat *format;
    Uint32 pixel, index;
    Uint8 red, green, blue, alpha;

    format = loadingSurface->format;
    SDL_LockSurface(loadingSurface);
    pixel = getPixel(loadingSurface, x, y);
    SDL_UnlockSurface(loadingSurface);

    index = pixel & format->Rmask;  
    index = index >> format->Rshift; 
    index = index << format->Rloss;  
    red = (Uint8)index;

    index = pixel & format->Gmask;   
    index = index >> format->Gshift; 
    index = index << format->Gloss;  
    green = (Uint8)index;

    index = pixel & format->Bmask;   
    index = index >> format->Bshift; 
    index = index << format->Bloss;  
    blue = (Uint8)index;

    index = pixel & format->Amask;
    index = index >> format->Ashift;
    index = index << format->Aloss;
    alpha = (Uint8)index;

    getColor.r = red;
    getColor.g = green;
    getColor.b = blue;
    getColor.a = alpha;

    return getColor;

}

【问题讨论】:

    标签: c++ sdl pixel sdl-2


    【解决方案1】:

    这一行:

    Uint8 *colors = (Uint8*)getPixel;
    

    据我所知,getPixel 是纹理中 (x,y) 位置的 32 位 RGBA 像素颜色值。然后出于某种原因将此值转换为 Uint8*

    所以现在colors 包含一个无意义的地址,等于像素颜色值,而不是您可能想要的getPixel 的地址。因此,当您执行colors[0] 并尝试通过此“地址”读取内存时,您会遇到访问冲突。

    您的意思是在投射之前先获取getPixel 的地址,以便访问各个颜色通道值吗?

    Uint8 *colors = (Uint8*)&getPixel; // Note the &
    

    与您的确切问题无关,但您的代码也存在问题:您正在返回一个指向局部变量的指针:

    SDL_Color getColor = {0,0,0};
    // etc.
    SDL_Color *color = &getColor;
    return color;
    

    getColor 将在函数返回时超出范围,函数的调用者将得到一个悬空指针。

    您应该重写您的函数以按值返回SDL_Color:只需return getColor; 并将返回类型更改为SDL_Color

    【讨论】:

    • 那,加上从锁定的纹理读取并不是真正有效的(它仅用于写入),如果它已经解锁则更是如此。我不知道为什么名为getPixelColor 的函数会突然创建纹理,但它应该从源表面像素读取,而不是纹理。
    • 我正在遵循 SDL 文档中的说明以及 Internet 上有关此问题的唯一其他来源之一,LazyFoo。根据文档中的说明,从 Surface 读取甚至更糟并且不起作用。根据文档,要进行像素访问,我必须锁定 Surface 或 Texture。
    • @EmZee 但是你已经从表面读取了,当你从表面读取像素memcpy() 到你的锁定纹理时,所以我认为@keltar 有一点:你没有理由当您可以简单地从原始表面的像素中读取所需的像素值时,根本不用费心创建纹理(顺便说一句,您忘记释放纹理)。
    • @EmZee LazyFoo 通常是不正确的。 SDL_LockTexture doc 明确表示它是只写的,因此从技术上讲,您无法从中读取(在大多数情况下,如果您只是将数据写入其中,则可以读取-但有什么意义呢?-但不能保证解锁后仍然存在),但是您首先将其解锁,然后尝试访问可能不再有效的指针(例如,SDL 可能为锁定的纹理分配 tmp 缓冲区,在解锁时释放它 - 您现在正在访问什么?垃圾甚至段错误)。对于表面不是很清楚,但除非 RLE,否则您可以访问 pixels 而无需锁定。为什么你需要纹理是未知的。
    • 感谢您的所有帮助。我忽略了 LazyFoo,而是只从 SDL 文档中工作。我仔细控制了我正在使用的位图图像类型并让它发挥作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 2021-09-06
    • 2014-08-05
    • 1970-01-01
    • 2013-07-21
    相关资源
    最近更新 更多