【问题标题】:SDL2 messed up image with manipulating pixels and SDL_UpdateTexture()SDL2 通过操作像素和 SDL_UpdateTexture() 搞砸了图像
【发布时间】:2015-11-25 00:21:11
【问题描述】:

我正在尝试制作一个简单的图像查看器。我基本上将图像加载到表面中,然后从中创建纹理。

最后,我按照migration guide 执行通常的SDL_RenderClear()SDL_RenderCopy()SDL_RenderPresent()

这很好用,除了如果我在上面的 3 个渲染调用之前调用 SDL_UpdateTexture(),我会得到一个混乱的图像:

我这样调用 SDL_UpdateTexture():

SDL_UpdateTexture(texture, NULL, image->pixels, image->pitch)

image 是我为图像加载的表面,texture 是我从中创建的纹理。尝试改变音高会导致不同程度的混乱图像。我也尝试使用矩形作为第二个参数,但如果矩形与图像具有相同的尺寸,结果是相同的。如果尺寸较大(例如与窗口相同),则不会发生更新,但不会出现错误。

full code 可用。

我想直接通过image->pixels 操作表面的像素,然后调用SDL_UpdateTexture(),但只要调用SDL_UpdateTexture() 而不进行任何篡改就足以搞砸了。

【问题讨论】:

    标签: c image sdl sdl-2


    【解决方案1】:

    我认为音高或SDL_Rect 参数有问题, 但还有另一个 SDL 函数可能会有所帮助:

    SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
                                          SDL_Surface*  surface)
    

    【讨论】:

      【解决方案2】:

      您可以尝试以下方法。它应该将任何粉红色 (r=255,g=0,b=255) 像素替换为透明的。您只需更改 pixel32 操作即可满足您的需求。

      SDL_Surface* image = IMG_Load(filename);
      
      SDL_Surface* imageFomatted = SDL_ConvertSurfaceFormat(image, 
                                                            SDL_PIXELFORMAT_RGBA8888, 
                                                            NULL);
      
      texture = SDL_CreateTexture(renderer,
                                  SDL_PIXELFORMAT_RGBA8888,
                                  SDL_TEXTUREACCESS_STREAMING,
                                  imageFomatted->w, imageFomatted->h);
      
      void* pixels = NULL;
      int pitch = 0;
      
      SDL_LockTexture(texture, &imageFomatted->clip_rect, &pixels, &pitch);
      
      memcpy(pixels, imageFomatted->pixels, (imageFomatted->pitch * imageFomatted->h));
      
      int width   = imageFomatted->w;
      int height  = imageFomatted->h;
      
      Uint32* pixels32    = (Uint32*)pixels;
      int     pixelCount  = (pitch / 4) * height;
      
      Uint32 colorKey     = SDL_MapRGB(imageFomatted->format, 0xFF, 0x00, 0xFF);
      Uint32 transparent  = SDL_MapRGBA(imageFomatted->format, 0xFF, 0x00, 0xFF, 0x00);
      
      for (int i = 0; i < pixelCount; i++) {
        if (pixels32[i] == colorKey) {
          pixels32[i] = transparent;
        }
      }
      
      SDL_UnlockTexture(texture);
      
      SDL_FreeSurface(imageFormatted);
      SDL_FreeSurface(image);
      
      pixels = NULL;
      pitch = 0;
      width = 0;
      height = 0;
      

      【讨论】:

      • 感谢您的回答。它在 memcpy 上会变得疯狂,但如果你只用 pitch 替换 image->pitch 就会运行。我从 colorKey 行注释掉,直到 for 循环结束,因为 formattedSurf 没有在任何地方定义。我似乎无法在程序不崩溃的情况下使用像素。
      • @Gigi 抱歉,我在调整代码以适应您的代码时犯了几个错误,所以错过了几个变量名。你能再试一次完整的代码(包括内存复制)吗?我认为这可能是因为在创建纹理之前没有转换表面格式而搞砸了,所以我添加了这个。
      • 您错过了纹理声明,并且在 imageFormatted 中也有错字(缺少 'r') - 所以 SDL_FreeSurface(imageFormatted) 不一致。修复这些后,我仍然会在 memcpy 上崩溃。您可以在发布之前尝试测试代码吗?
      • @Gigi 这段代码已经过测试并且可以正常工作,因为我使用了相同的方法。很抱歉有可变错别字的错误,但这些很容易纠正。您在 memcpy 上遇到的实际崩溃是什么,因为这是主要问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-14
      • 2016-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      相关资源
      最近更新 更多