我們希望通過裝載SDL_Image圖像,以創建一個SDL表面,如果尺寸超過限制調整表面。SDL2調整表面
我們需要這樣做的原因是Raspbian SDL從表面創建紋理時引發錯誤('紋理尺寸限制爲2048x2048')。雖然這是一個非常大的圖像,我們不希望用戶關心圖像大小,但我們希望爲它們調整大小。儘管我們沒有在Windows上遇到這種限制,但我們正試圖在Windows上開發解決方案,並在調整紋理大小時遇到問題。
尋找一個解決方案也出現了類似的問題...:
- 2008 not SDL2 custom blitting
- 2010 use SDL_gfx
- 2008 can't be done use SDL_gfx, 2015 use SDL_BlitScaled, 2015 use SDL_RenderCopyEx
是一個自定義的阻擊器或必要SDL_gfx當前SDL2(那些回答SDL2 2013年發佈之前的版本)? SDLRenderCopyEx沒有幫助,因爲您需要生成出現問題的紋理。
所以我們嘗試了一些像SDL_BlitScaled可用塊傳輸功能,下面是一個簡單的程序來呈現2500x2500 PNG與不結垢:
#include <SDL.h>
#include <SDL_image.h>
#include <sstream>
#include <string>
SDL_Texture * get_texture(
SDL_Renderer * pRenderer,
std::string image_filename) {
SDL_Texture * result = NULL;
SDL_Surface * pSurface = IMG_Load(image_filename.c_str());
if (pSurface == NULL) {
printf("Error image load: %s\n", IMG_GetError());
}
else {
SDL_Texture * pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
if (pTexture == NULL) {
printf("Error image load: %s\n", SDL_GetError());
}
else {
SDL_SetTextureBlendMode(
pTexture,
SDL_BLENDMODE_BLEND);
result = pTexture;
}
SDL_FreeSurface(pSurface);
pSurface = NULL;
}
return result;
}
int main(int argc, char* args[]) {
SDL_Window * pWindow = NULL;
SDL_Renderer * pRenderer = NULL;
// set up
SDL_Init(SDL_INIT_VIDEO);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
SDL_Rect screenDimensions;
screenDimensions.x = 0;
screenDimensions.y = 0;
screenDimensions.w = 640;
screenDimensions.h = 480;
pWindow = SDL_CreateWindow("Resize Test",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
screenDimensions.w,
screenDimensions.h,
SDL_WINDOW_SHOWN);
pRenderer = SDL_CreateRenderer(pWindow,
-1,
SDL_RENDERER_ACCELERATED);
IMG_Init(IMG_INIT_PNG);
// render
SDL_SetRenderDrawColor(
pRenderer,
0,
0,
0,
0);
SDL_RenderClear(pRenderer);
SDL_Texture * pTexture = get_texture(
pRenderer,
"2500x2500.png");
if (pTexture != NULL) {
SDL_RenderCopy(
pRenderer,
pTexture,
NULL,
&screenDimensions);
SDL_DestroyTexture(pTexture);
pTexture = NULL;
}
SDL_RenderPresent(pRenderer);
// wait for quit
bool quit = false;
while (!quit)
{
// poll input for quit
SDL_Event inputEvent;
while (SDL_PollEvent(&inputEvent) != 0) {
if ((inputEvent.type == SDL_KEYDOWN) &&
(inputEvent.key.keysym.sym == 113)) {
quit = true;
}
}
}
IMG_Quit();
SDL_DestroyRenderer(pRenderer);
pRenderer = NULL;
SDL_DestroyWindow(pWindow);
pWindow = NULL;
return 0;
}
更改get_texture功能,所以它標識的限制,並試圖創造一種新的表面:
SDL_Texture * get_texture(
SDL_Renderer * pRenderer,
std::string image_filename) {
SDL_Texture * result = NULL;
SDL_Surface * pSurface = IMG_Load(image_filename.c_str());
if (pSurface == NULL) {
printf("Error image load: %s\n", IMG_GetError());
}
else {
const int limit = 1024;
int width = pSurface->w;
int height = pSurface->h;
if ((width > limit) ||
(height > limit)) {
SDL_Rect sourceDimensions;
sourceDimensions.x = 0;
sourceDimensions.y = 0;
sourceDimensions.w = width;
sourceDimensions.h = height;
float scale = (float)limit/(float)width;
float scaleH = (float)limit/(float)height;
if (scaleH < scale) {
scale = scaleH;
}
SDL_Rect targetDimensions;
targetDimensions.x = 0;
targetDimensions.y = 0;
targetDimensions.w = (int)(width * scale);
targetDimensions.h = (int)(height * scale);
SDL_Surface *pScaleSurface = SDL_CreateRGBSurface(
pSurface->flags,
targetDimensions.w,
targetDimensions.h,
pSurface->format->BitsPerPixel,
pSurface->format->Rmask,
pSurface->format->Gmask,
pSurface->format->Bmask,
pSurface->format->Amask);
if (SDL_BlitScaled(pSurface, NULL, pScaleSurface, &targetDimensions) < 0) {
printf("Error did not scale surface: %s\n", SDL_GetError());
SDL_FreeSurface(pScaleSurface);
pScaleSurface = NULL;
}
else {
SDL_FreeSurface(pSurface);
pSurface = pScaleSurface;
width = pSurface->w;
height = pSurface->h;
}
}
SDL_Texture * pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
if (pTexture == NULL) {
printf("Error image load: %s\n", SDL_GetError());
}
else {
SDL_SetTextureBlendMode(
pTexture,
SDL_BLENDMODE_BLEND);
result = pTexture;
}
SDL_FreeSurface(pSurface);
pSurface = NULL;
}
return result;
}
SDL_BlitScaled失敗,「BLIT組合不支持」其它變型具有相似的誤差的誤差:
SDL_BlitScaled(pSurface, NULL, pScaleSurface, NULL)
SDL_BlitScaled(pSurface, &sourceDimensions, pScaleSurface, &targetDimensions)
SDL_LowerBlitScaled(pSurface, &sourceDimensions, pScaleSurface, &targetDimensions) // from the wiki this is the call SDL_BlitScaled makes internally
然後我們嘗試了一個非縮放blit ...它沒有拋出一個錯誤,但只顯示白色(不清晰的顏色或圖像中的顏色)。
SDL_BlitSurface(pSurface, &targetDimensions, pScaleSurface, &targetDimensions)
隨着該位圖傳輸功能不能正常工作,我們再與相同的圖像作爲位圖(僅僅出口巴紐爲.BMP),還是加載與SDL_Image和這兩個功能的文件,SDL_BlitScaled比例爲工作試過預計
不知道發生了什麼事情錯在這裏(我們期望和需要像png格式的主要圖像文件格式的支持),或者如果這是推薦的方法,任何幫助表示讚賞!
爲了使用blit功能,您的硬件必須支持GL_EXT_framebuffer_blit--集成顯卡和一些工作站GPU通常不支持的功能。 –
什麼是源圖像的像素格式(每像素和掩模的位數)?所述錯誤在源和目標表面格式的組合沒有blitting實現時產生;我建議爲每個通道的目標表面(RGB爲24位,RGBA爲32)創建「正常」8位,並將其傳送至其中。 – keltar
@ bruno-ferreira謝謝,你是對的,擴展不支持,所以我安裝了顯卡的驅動程序,並得到它,但不幸的是,如果沒有解決這個問題 – Paddy