我试图将IMG_Load
(SDL_image)创建的曲面blit到通过SDL_CreateRGBSurface
创建的曲面上。当两个曲面都加载IMG_Load
时,这样可以正常工作,但不能在使用SDL_CreateRGBSurface
创建目标曲面时使用。
通过实验,我发现如果我在源表面上调用SDL_SetAlpha
,它会突然正常工作。文档有点缺乏,但我如何理解它,我在下面调用它的方式应该清除SDL_SRCALPHA
标志,可能由IMG_Load
设置。看起来像 source 表面的alpha标志是blitting时最重要的,所以我想这会完全关闭alpha混合。
最大的问题是:为什么这个SDL_SetAlpha
首先是必要的?这真的是正确的方法吗?
以下代码重现了这一点:
#include <SDL/SDL.h>
#include <SDL_image/SDL_image.h>
SDL_Surface* copy_surface(SDL_Surface* source)
{
SDL_Surface *target;
target = SDL_CreateRGBSurface(0, source->w, source->h,
source->format->BitsPerPixel,
source->format->Rmask, source->format->Gmask,
source->format->Bmask, source->format->Amask);
/*
* I really don't understand why this is necessary. This is supposed to
* clear the SDL_SRCALPHA flag presumably set by IMG_Load. But why wouldn't
* blitting work otherwise?
*/
SDL_SetAlpha(source, 0, 0);
SDL_BlitSurface(source, 0, target, 0);
return target;
}
int main(int argc, char* argv[])
{
SDL_Event event;
SDL_Surface *copy, *screen, *source;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(800, 600, 0, 0);
SDL_FillRect(screen, 0, SDL_MapRGB(screen->format, 0xff, 0xff, 0xff));
source = IMG_Load("source.png");
if (!source) {
fprintf(stderr, "Unable to load source image\n");
return 1;
}
copy = copy_surface(source);
SDL_BlitSurface(copy, 0, screen, 0);
SDL_Flip(screen);
while (SDL_WaitEvent(&event))
if (event.type == SDL_QUIT
|| (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE))
break;
SDL_Quit();
return 0;
}
你需要source.png。我使用400x400透明PNG和一些黑色涂鸦。
答案 0 :(得分:1)
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsetalpha.html描述了每种可能的像素格式组合的blitting。
执行Alpha混合时,标准公式为SRC_COLOUR * SRC_ALPHA + DST_COLOUR * (1 - SRC_ALPHA)
。目的地alpha不在此处使用。
如果启用了Alpha混合,并且为源曲面启用了SRCALPHA标记,则源alpha将用于重新计算(混合)更新的目标颜色,但目标的Alpha通道保持不变。下次这个&#39; dst&#39;用作blitting的来源,将使用它的alpha。
为了避免您的问题,有几种可能的方法:
memcpy
就足够了。这将覆盖目的地的内容,而不是混合它。它也会明显快于混合。如果尺寸不匹配 - 取决于pitch
参数,您可能需要number_of_rows memcpy
&#39; s。如果像素格式不匹配 - 复制有问题,则需要从源像素格式解码每个像素并将其编码为目标像素格式。SDL_ConvertSurface(source, source->format, 0)
。它会创建具有相同内容的新曲面。我认为这种方式是首选。不要忘记稍后释放新曲面。SDL_ConvertSurface
几乎相同,但将表面转换为显示格式,而不是源表面格式。它已不再可用于SDL2。另请注意,(4),(5)和(6)只是我看到的方式,允许您保持源alpha。所有blitting操作都会丢弃源alpha,使目标保留其自己的alpha值 - 因为blitting永远不会更新目标alpha。