2012-07-06 35 views
1

我有一個管理灰度圖像的類。我想用libpng保存它。要做到這一點我想用這樣的const成員函數:用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。我想知道,這樣做是否安全?

+0

什麼是'png_ptr'和'info_ptr'? – japreiss 2012-07-06 13:33:48

+0

@japreiss它們是libpng使用的某些結構的不透明指針。 – 2012-07-06 15:30:16

回答

0

這並不安全。如果沒有聲明constpng_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; 
} 
+0

謝謝。我可能會看看libpng源代碼,看看它是否修改了數據,儘管這可能有點難。 – 2012-07-06 21:18:30

+0

我剛添加了源代碼。它不會修改'row_pointers'。 – japreiss 2012-07-07 04:46:16

0

您的函數定義中的const只是說您的實例不應該改變。保存到一個文件不應該改變你的實例,所以它是沒問題的。 當然png_set_rows的第三個參數不是const,因爲它被設置。

只要不屬於你的類,你創建,銷燬或改變const函數中的東西並不重要。您的代碼不會更改任何GrayscaleImage實例。

+1

我認爲這是寫入的第二個參數(http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Desktop-generic/LSB-Desktop-generic/libpng12.png.set.rows.1。 html) – 2012-07-06 14:35:47

+0

問題是我在row_pointers數組中存儲指向類的數據的指針。當我將該數組傳遞給'png_set_rows'時,libpng將存儲指向我班的數據的指針。然後它會使用這些指針,我想知道這是否安全。我不知道libpng是否會修改它們指向的數據。 – 2012-07-06 15:36:12

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。