0

我是sdl的新手。这是我的问题:我使用 sdl_ttf.dll 创建了一个文本表面。像这样 TTF_Font* myFont = TTF_OpenFont(szFontPath, text.m_iFontSize); SDL_Surface *textSurface = TTF_RenderUNICODE_Blended(myFont, (const Uint16*)text.m_wstrFilePath.c_str(), textColor);

这很好用,如果我在用于播放视频的屏幕上闪烁,则文本表面也可以。 SDL_BlitSurface(textSurface , null, screen, offset); 但问题是屏幕上的文字每 3 /4 秒闪烁一次,即使我用 SDL_DOUBLEBUF 和 SDL_HWSURFACE 设置屏幕,也无济于事。所以它采用了另一种方式。我决定在显示之前在屏幕上对文本进行 blit。我使用这个功能:

blitSurface2YUV(text, vp->bmp, &rectOffset); //vp->bmp是sdl_overlay显示它:SDL_DisplayYUVOverlay(vp->bmp, &rcRView); //rcView 是到屏幕的偏移量

“blitSurface2YUV”在这里定义:

   int blitSurface2YUV(SDL_Surface *src, SDL_Overlay *dst, SDL_Rect *dstrect)
   {
  Uint8 r, g, b;
  int y1,u1,v1;
  int y,x;
  int height = src->h < dstrect->h ? src->h: dstrect->h;
  int width =  src->w < dstrect->w ? src->w: dstrect->w;
  int uv_off = 0;
  Uint32 pixel;

  if(dst->format != SDL_YV12_OVERLAY)
    return 1;

  for(y = 0; y < height; ++y)
  {
    for(x = 0; x < width; ++x)
    {
        switch(src->format->BitsPerPixel)
        {
        case 8:
            pixel = *((Uint8*)src->pixels + y*src->pitch + x);
            break;
        case 16:
            pixel = *((Uint16*)src->pixels + y*src->pitch/2 + x);
            break;
        case 32:
            pixel = *((Uint32*)src->pixels + y*src->pitch/4 + x);
            break;
        default:
            return -1;
        }
        SDL_GetRGB(pixel, src->format, &r, &g, &b);
        rgb2yuv(r, g, b, &y1, &u1, &v1);

        memset(dst->pixels[0] + (dstrect->y + y) * dst->pitches[0] + (dstrect->x + x), 
            (Uint8)y1, 1);

        if((x%2 == 0 ) && (y%2 == 0 ))
        {
            memset(dst->pixels[1] + (uv_off + dstrect->y /2) * dst->pitches[1] + (dstrect->x/2 + x/2), 
                (Uint8)v1, 1);
            memset(dst->pixels[2] + (uv_off + dstrect->y /2) * dst->pitches[2] + (dstrect->x/2 + x/2), 
                (Uint8)u1, 1);
        }
    }
    if(y%2 == 0)++uv_off;
}
return 0;
}

这可以解决眨眼问题。但屏幕上的文字有黑色背景,应该是空的。

所以有人可以告诉我有什么问题吗?

4

2 回答 2

0

这不是一个真正的答案,但对于评论来说肯定太长了。

我认为您正在尝试解决错误的问题。您最初的问题是您的文本是在屏幕表面上TTF_RenderUNICODE_Blended调用时使用“闪烁”生成的。SDL_BlitSurface应该有效,并且在我的所有SDL项目中都有效。

这意味着您的渲染循环或文本必须有问题,如果您可以发布更多有关此的代码,那将很有帮助!

于 2013-06-20T21:13:20.933 回答
0

您可以将其添加到循环中。并且黑色像素不会处理。

if(pixel == 0 )
    continue;

这是更正的功能。

int blitSurface2YUV(SDL_Surface *src, SDL_Overlay *dst, SDL_Rect *dstrect)
{
Uint8 r, g, b;
int y1,u1,v1;
int y,x;
int height = src->h < dstrect->h ? src->h: dstrect->h;
int width =  src->w < dstrect->w ? src->w: dstrect->w;
int uv_off = 0;
Uint32 pixel;

if(dst->format != SDL_YV12_OVERLAY)
    return 1;

for(y = 0; y < height; ++y)
{
    for(x = 0; x < width; ++x)
    {
        switch(src->format->BitsPerPixel)
        {
        case 8:
            pixel = *((Uint8*)src->pixels + y*src->pitch + x);
        break;
        case 16:
            pixel = *((Uint16*)src->pixels + y*src->pitch/2 + x);
        break;
        case 32:
            pixel = *((Uint32*)src->pixels + y*src->pitch/4 + x);
        break;
            default:
            return -1;
        }
        if(pixel == 0 )
            continue;
        SDL_GetRGB(pixel, src->format, &r, &g, &b);
        rgb2yuv(r, g, b, y1, u1, v1);

        memset(dst->pixels[0] + (dstrect->y + y) * dst->pitches[0] + (dstrect->x + x), 
            (Uint8)y1, 1);

        if((x%2 == 0 ) && (y%2 == 0 ))
        {
        memset(dst->pixels[1] + (uv_off + dstrect->y /2) * dst->pitches[1] + (dstrect->x/2 + x/2), 
            (Uint8)v1, 1);
        memset(dst->pixels[2] + (uv_off + dstrect->y /2) * dst->pitches[2] + (dstrect->x/2 + x/2), 
            (Uint8)u1, 1);
        }
    }
    if(y%2 == 0) ++uv_off;
}
return 0;
}
于 2013-07-09T09:44:35.597 回答