获取SDL_Texture中单个像素的SDL_Color

时间:2014-04-29 14:09:35

标签: c++ sdl-2

我在查找如何在SDL_Texture上检索像素的特定颜色的解决方案时遇到了一些问题... 更具体一点:我试图计算给定纹理中使用的平均颜色数量。后来我想以像素总量为例来划分红色像素的数量。对于这个任务,我需要一个方法,它将获得每个像素颜色......

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

你有解决方案吗?

2 个答案:

答案 0 :(得分:4)

要访问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具体涉及该问题。

如果您有任何问题或某些事情不清楚,请与我们联系。

祝你好运!

答案 1 :(得分:0)

对于SDL 2,您可以使用它从表面复制像素。一旦有了像素,就可以从中提取颜色(请参见下面的示例)。

const string msg = "<RESULTS><ROW><COLUMN NAME=\"OM_USER\"><![CDATA[TEXT]]></COLUMN><COLUMN NAME=\"LASTNAME\"><![CDATA[TEXT]]></COLUMN><COLUMN NAME=\"FIRSTNAME\"><![CDATA[TEXT]]></COLUMN><COLUMN NAME=\"PHONE\"><![CDATA[TEXT]]></COLUMN></ROW></RESULTS>";

XDocument xmlDocument = XDocument.Parse(msg);

//get the first element named ROW from the xdocument.
var xElement = xmlDocument.Descendants().First(x => x.Name == "ROW");

if (xElement != null)
{
   //Loop through the childs of ROW
   foreach (var child in xElement.Elements())
   {
      //Find the first attribute in the child element which is named NAME.
      var childAttrName = child.Attributes().First(x => x.Name == "NAME");
      //Print the value of the attribute called name and the value of the element.
      System.Console.WriteLine(childAttrName.Value + " : " + child.Value);
   }
}

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

/*
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;
}