【问题标题】:Getting the SDL_Color of a single pixel in a SDL_Texture获取 SDL_Texture 中单个像素的 SDL_Color
【发布时间】:2020-09-24 16:45:31
【问题描述】:

我在寻找有关如何检索 SDL_Texture 上像素的特定颜色的解决方案时遇到了一些问题... 更具体地说:我正在尝试计算给定纹理中使用的平均颜色量。稍后我想将红色像素的数量除以像素的总数。对于这个任务,我需要一个方法,它可以让我获得每个像素的颜色......

我试图搜索一些功能,但不幸的是我无法弄清楚.. 我看到了 SDL_RenderReadPixels 和 SDL_GetPixelFormatName 之类的方法,但这些方法都没有帮助我...

你有解决办法吗?

【问题讨论】:

  • 平均金额?你是说平均颜色吗?为什么SDL_RenderReadPixels() 不起作用?在我们提供帮助之前,您需要向我们展示您尝试过的一些实际代码以及出了什么问题。
  • 我的意思是“用特定颜色填充的像素总数”。
  • @olevegard:感谢您对SDL_RenderReadPixels 的引用!正是我想要的。

标签: c++ sdl-2


【解决方案1】:

要访问 SDL_Texture 的像素,您必须使用 SDL_CreateTexture() 创建一个空白纹理并为访问参数传入 SDL_TEXTUREACCESS_STREAMING,然后将表面的像素复制到其中。完成后,您可以使用 SDL_LockTexture() 函数检索指向像素数据的指针,然后可以访问和修改该像素数据。要保存您的更改,您需要调用 SDL_UnlockTexture()。试试这样的:

SDL_Texture *t;

int main()
{
    // Init SDL 

    SDL_Surface * img = IMG_Load("path/to/file");
    SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, img->w, img->h);

    void * pixels;

    SDL_LockTexture(t, &img->clip_rect, &pixels, img->pitch);

    memcpy(pixels, img->pixels, img->w * img->h);

    Uint32 * upixels = (Uint32 *) pixels;

    // get or modify pixels

    SDL_UnlockTexture(t);

    return 0;
}

Uint32 get_pixel_at(Uint32 * pixels, int x, int y, int w)
{
    return pixels[y * w + x];
}

您可以像这样从像素中获取颜色:

Uint32 pixel = get_pixel_at(pixels, x, y, img->w);
Uint8 * colors = (Uint8 *) pixel;

// colors[0] is red, 1 is green, 2 is blue, 3 is alpha (assuming you've set the blend mode on the texture to SDL_BLENDMODE_BLEND

如果您想了解更多信息,请查看以下 SDL 2.0 教程:http://lazyfoo.net/tutorials/SDL/index.php。教程 40 专门处理这个问题。

如果您有任何问题或不清楚的地方,请告诉我。

祝你好运!

【讨论】:

  • 这仍然准确吗?我注意到the SDL_LoadTexture documentation 今天声明:锁定纹理的一部分以进行只写像素访问,并且作为一种优化,可用于编辑的像素不要'不一定包含旧的纹理数据。这是一个只写操作,如果您需要保留纹理数据的副本,您应该在应用程序级别执行此操作。
  • user2437378,您正在将数据 memcpying 到一个空指针(像素)而不分配任何内存(提前)!你能解释一下吗?
  • @user1511417 是的,这是未定义的,不是吗?我只能猜测他们试图使其快速且如此不完整 - 假设 OP 会这样做。但这对我来说似乎很愚蠢,因为问题本身没有代码。这个答案让我想到了这个概念,但你仍然必须这样做。由于该问题没有提供任何代码,因此这可能足够公平,但如果答案指出了这一点,那就太好了。
  • wiki.libsdl.org/SDL_LockTexture 发现,之前的SDL_LockTexture-调用提供了对pixel 的只写访问。所以这应该没问题,假设 SDL 正在正确地完成有关内存等的工作。但是在此示例中,该调用的返回值肯定会被忽略。这也是lazyfoo.net 上的tutorial 40 中的情况。 :(
  • 我看不出这个答案有多安全;需要使用 malloc 或 calloc 将像素设置为内存的保留部分。否则,即使它编译,它也会一直写越界,并且具有难以追踪的副作用。
【解决方案2】:

对于 SDL 2,您可以使用它从表面复制像素。获得像素后,您可以从中提取颜色(参见下面的示例)。

/*
Copies the pixels from a SDL2 surface.
You should free() the returned pixels when you're done with it.
*/
Uint8* copySurfacePixels(
  SDL_Surface* surface,  // surface to take pixels from
  Uint32 pixelFormat,    // usually SDL_GetWindowPixelFormat(window)
  SDL_Renderer* renderer,// main SDL2 renderer
  int* width,            // stores result width
  int* height,           // stores result height
  int* pitch)            // stores result pitch
{
  Uint8* pixels = 0;
  SDL_Surface* tmpSurface = 0;
  SDL_Texture* texture = 0;
  int sizeInBytes = 0;
  void* tmpPixels = 0;
  int tmpPitch = 0;

  tmpSurface = SDL_ConvertSurfaceFormat(surface, pixelFormat, 0);
  if (tmpSurface) {
    texture = SDL_CreateTexture( renderer, pixelFormat,
                                 SDL_TEXTUREACCESS_STREAMING,
                                 tmpSurface->w, tmpSurface->h );
  }

  if (texture) {
    if (width) {
      *width = tmpSurface->w;
    }
    if (height) {
      *height = tmpSurface->h;
    }
    if (pitch) {
      *pitch = tmpSurface->pitch;
    }
    sizeInBytes = tmpSurface->pitch * tmpSurface->h;
    pixels = (Uint8*)malloc( sizeInBytes );
    SDL_LockTexture( texture, 0, &tmpPixels, &tmpPitch );
    memcpy( pixels, tmpSurface->pixels, sizeInBytes);
    SDL_UnlockTexture( texture );
  }

  // Cleanup
  if (texture) {
    SDL_DestroyTexture(texture);
  }
  if (tmpSurface) {
    SDL_FreeSurface(tmpSurface);
  }

  return pixels;
}

示例用法。加载位图并在 (1,1) 处打印 RGB 颜色

  SDL_Surface* surface = SDL_LoadBMP("..\\res\\test.bmp");
  Uint32 pf = SDL_GetWindowPixelFormat(window);
  int w=0, h=0, p=0;
  Uint8* pixels = copySurfacePixels(surface, pf, renderer, &w, &h, &p);
  if (pixels)
  {
    printf("width=%d, height=%d, pitch=%d\n", w, h, p);
    
    // Print color at (1,1)
    int x=1, y=1;

    // Assuming BGRA format
    int b = pixels[4 * (y * w + x) + 0]; // Blue
    int g = pixels[4 * (y * w + x) + 1]; // Green
    int r = pixels[4 * (y * w + x) + 2]; // Red
    int a = pixels[4 * (y * w + x) + 3]; // Alpha
    printf("Pixel at (%d,%d) has RGBA color (%d,%d,%d,%d)\n", x, y, r, g, b, a);
  }
  free(pixels);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    相关资源
    最近更新 更多