使用 libpng - const 对象保存图像

Saving image with libpng - const object

本文关键字:保存 图像 对象 const libpng 使用      更新时间:2023-10-16

我有一个管理灰度图像的类。我想用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::SavePNG const,我必须在某个时候使用 const_cast。我想知道,这样做安全吗?

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

所做的是安全的,只要你不打电话给png_data_freer。 任何写入 API 都不会修改输入数据。

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

你不太可能很快看到变化;在我看来,在libpng 2.0之前,以要求应用程序重写现有代码的方式更改API不太可能发生。

这不安全。 如果没有声明const png_set_rows()第三个参数,则无法保证它不会修改输入数据。

您将始终必须处理不声明参数的库,即使它们可以声明参数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;
}
函数

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

在 const 函数中创建、销毁或更改内容并不重要,只要它们不属于您的类即可。您的代码不会更改灰度图像的任何实例。