2015-11-06 50 views
-1

我嘗試讀取ppm文件並創建一個相同的新文件。但是當我用GIMP2打開它們時,圖像不一樣。如何讀寫ppm文件?

問題與我的代碼在哪裏?

int main() 
{ 
    FILE *in, *out; 
    in = fopen("parrots.ppm","r"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    unsigned char *buffer = NULL; 

    long size = 0; 
    fseek(in, 0, 2); 
    size = ftell(in); 
    fseek(in, 0, 0); 

    buffer = new unsigned char[size]; 
    if(buffer == NULL) 
    { 
     std::cout<<"Error\n"; 
     return 0; 
    } 

    if(fread(buffer, size, 1, in) < 0) 
    { 
      std::cout<<"Error.\n"; 
      return 0 ; 
    } 

    out = fopen("out.ppm","w"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    if(fwrite(buffer, size, 1, out) < 0) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    delete[] buffer; 

    fcloseall(); 

    return 0; 
} 

在此之前,我讀了結構的PPM文件,當我寫的,我得到了相同的圖像,但綠色是比原來的畫面更加激烈。然後我嘗試了這個簡單的閱讀和寫作,但是我得到了相同的結果。

+0

您是否嘗試過使用官方庫來達到這個目的? - http://netpbm.sourceforge.net/。僅供參考。 – Dummy00001

回答

1
int main() 

缺失包括。

FILE *in, *out; 

C++程序中的C風格I/O,爲什麼?此外,在初始化時聲明,接近第一次使用。

in = fopen("parrots.ppm","r"); 

這是打開在文本模式下,這肯定是不是你想要的文件。使用"rb"作爲模式。

unsigned char *buffer = NULL; 

在初始化時聲明,接近第一次使用。

fseek(in, 0, 2); 

你應該使用SEEK_END這是不能保證被定義爲2

fseek(in, 0, 0); 

上方見SEEK_SET不能保證被定義爲0

buffer = new unsigned char[size]; 
if(buffer == NULL) 

默認情況下,new不會返回一個指針NULL,而是拋出一個異常std::bad_alloc。 (對於大多數當前操作系統來說,過度配置是常態,檢查NULL不會保護您免受內存不足,即使使用malloc(),但很高興看到您養成了檢查習慣。)

C++ 11給我們帶來了smart pointers。使用它們。它們是避免內存泄漏的極好工具(C++的極少數弱點之一)。

if(fread(buffer, size, 1, in) < 0) 

成功使用的fread應該返回寫入的對象的數目,這應被檢查以等於所述第三參數(!= 1),不< 0

out = fopen("out.ppm","w"); 

文本模式下再次,你要在這裏"wb"

if(fwrite(buffer, size, 1, out) < 0) 

查看關於上述fread返回值的說明。這裏同樣適用。

fcloseall(); 

不是標準功能。使用fclose(in);fclose(out);


A C++ 11-指明分數溶液(省略了錯誤檢查簡潔)將看起來有點像這樣:

#include <iostream> 
#include <fstream> 
#include <memory> 

int main() 
{ 
    std::ifstream in("parrots.ppm", std::ios::binary); 
    std::ofstream out("out.ppm", std::ios::binary); 

    in.seekg(0, std::ios::end); 
    auto size = in.tellg(); 
    in.seekg(0); 

    std::unique_ptr<char[]> buffer(new char[ size ]); 

    in.read(buffer.get(), size); 
    out.write(buffer.get(), size); 

    in.close(); 
    out.close(); 

    return 0; 
} 

當然,一個智能解決方案會做一個實際的系統副本,通過Boost.Filesystemstandard functionality(本文寫作時的實驗)。