【问题标题】:Saving image with libpng - const object使用 libpng - const 对象保存图像
【发布时间】:2012-07-06 12:03:37
【问题描述】:

我有一个管理灰度图像的类。我想用 libpng 保存它。为此,我想使用这样的const 成员函数:

void GrayscaleImage::SavePNG(std::string filename) const
{
    // ...
    png_bytep* row_pointers = new png_bytep[m_height];
    for (int i = 0; i < height_; i++) {
        row_pointers[i] = const_cast<png_bytep>(m_data.data()) +  i * m_width * sizeof(uint8_t);
    }
    png_set_rows(png_ptr, info_ptr, row_pointers);
    // ...
}

问题是png_set_rows 的第三个参数是非常量,所以如果我希望成员函数GrayscaleImage::SavePNGconst,我必须在某些时候使用const_cast。我想知道,这样做安全吗?

【问题讨论】:

  • png_ptrinfo_ptr 是什么?
  • @japreiss 它们是指向 libpng 使用的某些结构的不透明指针。

标签: c++ constants libpng


【解决方案1】:

libpng 提供了一个 API 来释放 row_pointers 和它们指向的东西; png_data_freer。这是读取时的默认设置(当前可以调用 png_set_rows 但该调用会被忽略)。

只要你不调用 png_data_freer,你所做的就是安全的。没有写入 API 修改输入数据。

问题存在于png_write_image,API png_write_png调用,同样存在于png_write_rows。它曾经存在于 png_write_row 中,这是最低级别的 API,但在 libpng 1.5 中已修复;这是一个安静的 API 更改,因为它不会更改参数的类型兼容性。将其更改得更高会导致现有应用程序由于类型错误而无法编译。

您不太可能很快看到变化;在我看来,直到 libpng 2.0 才能以需要应用程序重写现有代码的方式更改 API。

【讨论】:

    【解决方案2】:

    这不安全。没有png_set_rows()的第三个参数声明const,你不能保证它不会修改输入数据。

    您将始终不得不处理不声明参数const 的库,即使它们可以。这就是const_cast 存在的原因。你应该非常小心地使用它。但从描述来看,png_set_rows() 不太可能修改你的数据。

    编辑:这里是源代码。你可以看到它没有修改row_pointers。 (但它肯定会修改其他两个参数!)

    void PNGAPI
    png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
    {
       png_debug1(1, "in %s storage function", "rows");
    
       if (png_ptr == NULL || info_ptr == NULL)
          return;
    
       if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
          png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
    
       info_ptr->row_pointers = row_pointers;
    
       if (row_pointers)
          info_ptr->valid |= PNG_INFO_IDAT;
    }
    

    【讨论】:

    • 谢谢。我可能会看一下 libpng 源代码,看看它是否会修改数据,尽管这可能有点难。
    • 我刚刚添加了源代码。它不会修改row_pointers
    【解决方案3】:

    你的函数定义中的const 只是说你的实例不应该改变。保存到文件不应更改您的实例,所以没关系。 当然png_set_rows 的第三个参数不是const,因为它被设置了。

    在 const 函数中创建、销毁或更改内容都没有关系,只要它们不属于您的类即可。您的代码不会更改 GrayscaleImage 的任何实例。

    【讨论】:

    • 我认为这是被写入的第二个参数 (refspecs.linuxbase.org/LSB_3.1.0/LSB-Desktop-generic/…)
    • 问题是我将指向类数据的指针存储在row_pointers 数组中。当我将该数组传递给png_set_rows 时,libpng 将存储指向我的班级数据的指针。然后它将使用这些指针,我想知道这是否安全。不知道libpng会不会修改他们指向的数据。
    猜你喜欢
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 2012-01-11
    • 2015-03-25
    • 2011-06-15
    • 2019-05-22
    • 2018-07-23
    • 1970-01-01
    相关资源
    最近更新 更多