我们希望通过装载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