2017-11-04 175 views
1

我的代码会引发访问错误。这是代码:从SDL_Texture访问像素颜色

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; 

} 

回答

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

+2

从锁定的纹理中读取数据并不是真的有效(仅用于写入),如果已经解锁,则更是如此。我不知道为什么名为'getPixelColor'的函数会突然创建一个纹理,但它应该从源表面像素读取,而不是纹理。 – keltar

+0

我遵循SDL文档以及互联网上其他关于LazyFoo的其他来源之一的说明。根据文件中的说明,从Surface读取更糟且无法使用。 根据文档,对于像素访问发生在所有我必须锁定表面或纹理。 –

+2

@EmZee但是你已经从表面读取了,当你从表面上将像素的memcpy()从你的表面拖入你的锁定纹理时,所以我认为@keltar有一个观点:你没有理由打扰创建一个纹理(顺便说一句,你忘记了自由),只需从原始表面的像素中读取所需的像素值即可。 – TerraPass