SDL2调整表面大小
SDL2 resize a surface
我们想通过加载带有sdl_image的图像来创建SDL表面,如果尺寸超过限制,则调整了表面的大小。
我们需要这样做的原因是在Raspbian SDL上引发了一个错误,从表面创建纹理('纹理尺寸限制为2048x2048 ')。尽管这是一个非常大的图像,但我们不希望用户关注图像大小,但我们希望为他们调整它。尽管我们尚未在Windows上遇到此限制,但我们正在尝试在Windows上开发解决方案,并在调整纹理的问题上遇到问题。
寻找解决方案也有类似的问题...
- 2008不是SDL2自定义爆炸
- 2010使用SDL_GFX
- 2008无法完成使用SDL_GFX,2015年使用SDL_BLITSCALED,2015使用SDL_RenderCopyEx
当前SDL2是否需要自定义的blitter或SDL_GFX(这些答案Pre-pate 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: %sn", IMG_GetError());
}
else {
SDL_Texture * pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
if (pTexture == NULL) {
printf("Error image load: %sn", 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: %sn", 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: %sn", 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: %sn", SDL_GetError());
}
else {
SDL_SetTextureBlendMode(
pTexture,
SDL_BLENDMODE_BLEND);
result = pTexture;
}
SDL_FreeSurface(pSurface);
pSurface = NULL;
}
return result;
}
SDL_BLITSCALITSCALED失败,错误'闪电组合不支持'其他变体具有类似的错误:
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
然后,我们尝试了一个非刻度打击...没有丢失错误,而只是显示白色(不是图像中的透明颜色或颜色)。
SDL_BlitSurface(pSurface, &targetDimensions, pScaleSurface, &targetDimensions)
使用该漏油功能不起作用,我们然后使用与位图相同的映像(只需导出.png as .bmp),仍使用SDL_IMAGE加载文件,并且这两个功能都与SDL_BLITSCALCALED缩放量一起使用,符合预期的量表。P>
不确定这里出了什么问题(我们期望和需要支持。
tl; dr @kelter的评论将我指向正确的方向,另一个堆栈溢出问题为我提供了解决方案:如果您首先闪电到一个32BPP表面,然后将其粘贴到另一个32BPP表面。它适用于8和24位深度PNG,32位再次被看不见另一个堆栈溢出问题,建议在爆炸之前首先填充表面。
更新的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: %sn", 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);
// create a 32 bits per pixel surface to Blit the image to first, before BlitScaled
// https://stackoverflow.com/questions/33850453/sdl2-blit-scaled-from-a-palettized-8bpp-surface-gives-error-blit-combination/33944312
SDL_Surface *p32BPPSurface = SDL_CreateRGBSurface(
pSurface->flags,
sourceDimensions.w,
sourceDimensions.h,
32,
pSurface->format->Rmask,
pSurface->format->Gmask,
pSurface->format->Bmask,
pSurface->format->Amask);
if (SDL_BlitSurface(pSurface, NULL, p32BPPSurface, NULL) < 0) {
printf("Error did not blit surface: %sn", SDL_GetError());
}
else {
// create another 32 bits per pixel surface are the desired scale
SDL_Surface *pScaleSurface = SDL_CreateRGBSurface(
p32BPPSurface->flags,
targetDimensions.w,
targetDimensions.h,
p32BPPSurface->format->BitsPerPixel,
p32BPPSurface->format->Rmask,
p32BPPSurface->format->Gmask,
p32BPPSurface->format->Bmask,
p32BPPSurface->format->Amask);
// 32 bit per pixel surfaces (loaded from the original file) won't scale down with BlitScaled, suggestion to first fill the surface
// 8 and 24 bit depth pngs did not require this
// https://stackoverflow.com/questions/20587999/sdl-blitscaled-doesnt-work
SDL_FillRect(pScaleSurface, &targetDimensions, SDL_MapRGBA(pScaleSurface->format, 255, 0, 0, 255));
if (SDL_BlitScaled(p32BPPSurface, NULL, pScaleSurface, NULL) < 0) {
printf("Error did not scale surface: %sn", SDL_GetError());
SDL_FreeSurface(pScaleSurface);
pScaleSurface = NULL;
}
else {
SDL_FreeSurface(pSurface);
pSurface = pScaleSurface;
width = pSurface->w;
height = pSurface->h;
}
}
SDL_FreeSurface(p32BPPSurface);
p32BPPSurface = NULL;
}
SDL_Texture * pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
if (pTexture == NULL) {
printf("Error image load: %sn", SDL_GetError());
}
else {
SDL_SetTextureBlendMode(
pTexture,
SDL_BLENDMODE_BLEND);
result = pTexture;
}
SDL_FreeSurface(pSurface);
pSurface = NULL;
}
return result;
}
@kelter的评论让我更仔细地看待表面像素格式,位图在24BPP上工作,PNG在8BPP上加载而不起作用。尝试将目标表面更改为24或32 BPP,但这无济于事。我们已经在自动检测的位深度生成了PNG,将其设置为8或24,并在表面上执行蓝色的表面,尽管它不适用于32。@petruza的问答。
update 有点快地写下此答案,原始解决方案处理的BMP和8和24位PNG,但32位PNG没有渲染。@retired的忍者回答有关blit_scaled的另一个问题的回答建议在调用功能之前填充表面并对其进行整理,还有另一个问题与在新表面上设置alpha有关,可能与此相关(特别是如果您需要透明度),但请填充固体颜色对我来说已经足够了...
- 为char数组调整zlib-zpipe
- 调整大小后指向元素值的指针unordered_map有效?
- 在C++中调整向量中的索引
- 哪些库可以通过Opencv调整曝光率
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- Alt+Enter 在 Win32 应用中,管理大小调整和分辨率
- 在容量内调整矢量大小时的性能影响
- 将 boost::odeint 与向量类一起使用,而无需调整向量的大小
- 将摄像机调整到俯视图
- Qt 图表条形图调整大小崩溃
- 除非重新绘制大小,否则SDL_Texture在调整大小后呈现黑色
- 如何在C++中为表面制作邻接矩阵
- 调整布局上的 QGraphicsView 小部件的大小
- 如何在构建链接列表时调整头、尾指针
- 如何将旧的 C 样式 #define 映射与现代C++进行调整?
- 当您在此单词中搜索单词时调整字符数组的大小?
- SDL2 调整窗口大小后如何缩放鼠标坐标?
- 如何按另一个向量的方向调整一个向量?
- 使用大小调整大小调整 wxListView 的大小
- SDL2调整表面大小