1

我有一个管理灰度图像的类。我想用 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是非常量,所以我必须const_cast在某个时候使用,如果我希望成员函数GrayscaleImage::SavePNGconst. 我想知道,这样做安全吗?

4

3 回答 3

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。

于 2015-11-22T00:54:56.930 回答
0

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

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

于 2012-07-06T13:11:14.660 回答
0

这不安全。png_set_rows()如果没有declare的第三个参数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;
}
于 2012-07-06T19:20:28.723 回答