【问题标题】:Explore the memory with only a void pointer仅使用 void 指针探索内存
【发布时间】:2014-10-27 16:04:31
【问题描述】:

我从 C 语言开始(我通常使用 Java 或 PHP),但我遇到了 void* 指针类型的问题。

在我的程序中,我从一个外部 API 获取一个像素缓冲区,该缓冲区包含在结构 f 中。 (void*) f -> pixbuf

此指针指向以 BGR24 编码的像素缓冲区。 3 个字节对应一个像素(每种颜色 1 个字节)。

我只想按像素保留 1 个八位字节(像素 = 3 个字节)。但我真的不知道该怎么做。我只是拥有所有这些八位字节的地址(f -> pixbuf)。是否可以通过逐个读取每个八位字节来填充字符选项卡?

PS:f -> pixelbuf的大小是5292000字节

【问题讨论】:

  • 我不确定您的确切意思,您是说要将图像转换为 8 位颜色吗?
  • 您可以将其转换为例如unsigned char* 这样您就可以一个接一个地读取八位字节。但这听起来像你的图书馆不打算让你这样做,如果它给你一个空余。
  • 您是说要将颜色从 24 位 BGR 重新编码为 8 位 rgb,其中 3 位用于红色和绿色,2 位用于蓝色?
  • 是的,我想将图像从 24 位转换为 8 位。图像是灰色的,所以我不需要 3 像素。但我只有指向像素缓冲区的指针,一个 void* 指针。
  • @LaurentJerber 等等,再澄清一次,你想把它变成一个 8 位灰度图吗?丢失颜色数据并因此将图像缩小三分之二?

标签: c pointers pixel void


【解决方案1】:

要通过void-指针访问特定数据类型,您需要将void-指针转换为您要访问的类型的指针,在您的情况下为char

struct pic
{
  void * pixbuf;
  size_t pixbuflen;
  ...
}

...

struct pic f = ...;
struct pic grey = {0};

grey->pixbuflen = f->pixbuflen/3;
grey->pixbuf = malloc(grey->pixbuflen); /* Allocate the target buffer begin sized a 
                                          3rd of the destination buffer. */
if (NULL == grey->pixbuf) /* Test for failure. */
{
   /* Failure to allocate the buffer. */
   grey->pixbuflen = 0;
   exit(1);
}

for (size_t i = 0, j = 0; i < grey->pixbuflen; ++i, j += 3)
{
  ((char *) grey->pixbuf)[i] = ((char *) f->pixbuf)[j]; /* Copy every 3rd byte from 
                                                           source to destination. */
}

如果您可以确保指针指向有效内存,则可以像数组一样对其进行索引。

【讨论】:

    【解决方案2】:

    你需要这样的东西:

    int length =  f->pixbuflen;
    unsigned char* sourcepixels = (unsigned char*)f->pixbuf;
    unsigned char* destpixels = malloc(length / 3); // length being the number of
                                                    // RGB pixels of the original image
    for (int i = 0; i < length/3; i++)
      destpixels[i] = sourcepixels[i*3];
    

    这是未经优化、未经测试、非错误检查的代码。

    【讨论】:

    • 我不知道我们可以像数组一样探索无符号字符指针。我明天试试(我现在不在工作)因为我知道变量 f 的长度 -> pixbuflen
    • @LaurentJerber 数组在 C 中并不存在。x[i] 实际上是 *(x + i) 的简写。
    • "数组在 C 中并不真正存在" 什么?
    • @MichaelWalz 数组确实存在,它们与指针不同,尽管一个可以转换为另一个 :)
    • @MichaelWalz 这不仅仅是语法糖,例如数组的大小和指针有非常不同的规则,但无论如何你似乎已经知道了,所以这个讨论没有多大意义,除了也许对于一些随机的互联网人来说,阅读这个 cmets 并得到一个“啊哈!”时刻。
    【解决方案3】:
    typedef struct pixel
    {
      char b;
      char g;
      char r;
    }              pixel_t;
    

    然后您可以像这样访问任何像素的任何颜色:

    pixel_t*  pixels = f->pixbuf;
    
    pixels[42].r = 0x0F;
    pixels[42].g = 0xA0;
    pixels[42].b = 0xB4;
    

    【讨论】:

    • 这不会受到(理论上的)填充问题的影响吗?使用数组数组可能会更好。 (char[N][3])
    • @Vality 没有问题 issue,char 是最小的变量,所以它会被尽可能地缩小,任何重载都将在数组或打包的 attr 声明中
    • 它将创建一个像素数组(结构)。每个结构包含 3 个字节?
    • @LaurentJerber 是的,那么您可以使用任何算法将这 3 个字节转换为 1。
    • 感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 2015-11-27
    • 2018-03-03
    • 1970-01-01
    • 2014-05-30
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    相关资源
    最近更新 更多