2017-11-04 113 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