2015-02-08 38 views
0

我在播放文件時遇到了一些麻煩。這是我想要完成的。我試圖通過取反藍色值(每第三個值)來過濾PPM圖像。我可以成功打開和寫入文件,但遇到了一些問題。在我的while(myfile.good())循環中,我認爲只有最後3個數字分配給變量r,g和b。我想要做的是每個第一個(分爲三個)值分配給變量r,每個第二個值分配給g,每個第三個值分配給b。但是,我想獲取255 - 當前的b值,並將其設置爲應用於過濾器的新b值。我是否必須製作3個單獨的文件(每個變量1個),然後將它們全部打開,將它們寫入4個文件中,作爲最終的副本?還是有辦法將它們全部複製並分配給一個變量?任何幫助深表感謝。我對C++很陌生,所以請原諒我。謝謝您的幫助。我試圖使用值如何編輯圖像的值

例子:http://imgur.com/H6EDFIq

#include <iostream> 
#include <cmath> 
#include <fstream> 
#include <cstdlib> 

using namespace std; 

int main() 
{ 
    char filename[50]; 
    ifstream myfile; 
    cin.getline(filename, 50); 
    myfile.open(filename); 

    if(!myfile.is_open()) 
    { 
     cout << "File cannot load."; 
    } 

    char r [50]; 
    char g [50]; 
    char b [50]; 
    myfile >> r >> g >> b; 

    while (myfile.good()) 
    { 
     myfile >> r >> g >> b; 
    } 

myfile.close(); 

ofstream myfile2; 
myfile2.open(filename); 


//this is just to test to see what gets written onto the file 
//for (int a=0; a<20; a++) 
//{ 
    // ** Is this even allowed?? int r = 255 - r; 
    //myfile2 << r << " " << g << " " << b; 
//} 

myfile2.close(); 

return 0; 
} 
+0

圖像文件只包含像素值嗎?沒有標題信息(關於圖像的大小等)? – 2015-02-08 09:27:34

+0

假設它是一個P3 ppm,肯定有一個標題需要處理。如果你想讀取值作爲你應該做的數字,現在你正在閱讀他們作爲一個字符串和循環的每個迭代覆蓋最後一個值。 – 2015-02-08 09:34:49

+0

如果你的目標純粹是爲了處理圖像,而不是學習C++,你可以使用ImageMagick(內置於大多數Linux發行版,可免費提供給Mac OSX和Windows),就像這樣:convert input.ppm-channel B -negate output.ppm – 2015-02-08 10:50:34

回答

0

你要檢查一個.ppm格式頭,其.ppm格式圖像的第一線。檢出.ppm幻數,P3或P6,你需要檢查。第二行是圖像的尺寸,所以您也需要考慮這一點。

這是我以前的工作,所以你可以得到一個想法。它可能無法立即工作,所以只要給它一個閱讀。

#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <exception> 

int main() { 
std::string filename = //whatever your file name is 
std::ifstream input(filename.c_str(), std::ios::in | std::ios::binary); 
if (input.is_open()) { 
    std::string line; 
    std::getline(input, line); 
    if (line != "P6" || line != "P3") { //you're going to want to check if you're using P3 or P6 
     //print out errors 
    } 

    std::stringstream image_dimensions(line); 

    try { 
     image_dimensions >> w //your width variable if you want to store it here 
     image_dimensions >> h //your height variable if you want to store it here 
    } catch (std::exception &e) { 
     std::cout << "Format error found in header " << e.what() << std::endl; 
     return; 
    } 

    int size = w*h; 

std::getline(input, line); 
std::stringstream max_value(line); //max colour value of the image 

//you can initialise the vectors here if you want 
std::vector<unsigned char> r; 
std::vector<unsigned char> g; 
std::vector<unsigned char> b; 

//we know it max capacity so reserve that size for the vectors 
r.reserve(size); 
g.reserve(size); 
b.reserve(size); 

    char read_rgb; 
    for (unsigned int i = 0; i < size; ++i) { 
     input.read(&read_rgb, 1); 
     r[i] = (unsigned char) read_rgb; 
     input.read(&read_rgb, 1); 
     g[i] = (unsigned char) read_rgb; 
     input.read(&read_rgb, 1); 
     b[i] = (unsigned char) read_rgb; 
    } 
} 
input.close(); 
} 

你會想要存儲r,g,b作爲你選擇的數組。完成之後,您可以遍歷B數組並將其編輯以應用您的過濾器,然後將其寫入ppm文件。

另外,對於錯誤處理,您可以隨時使用記事本或Notepad ++打開.ppm文件並讀取圖像。

+0

缺少'r','g','b'的聲明,並且沒有讀取最大顏色值。不適用於P3 ppm。 – 2015-02-08 10:09:51

+0

對不起,忘了那個。也可以以他想要的任何方式聲明'r','g','b',我不確定他希望如何存儲數據。 – 2015-02-08 10:16:35

+0

你好,感謝你的回覆。文件是P3,第二行是800 532.那麼我想爲每個r,g和b設置一個數組?這會成爲while(myfile.good())循環的一部分嗎? – Aaron 2015-02-08 23:38:32

0

除非您特別需要將數據存儲在內存中,否則在讀取數據時將數據寫入新文件會更簡單。

下面是一個用8位顏色條目讀取P3 ppm的示例,根據您的要求反轉藍色通道,然後用該數據寫入新文件。它不會進行大量的錯誤檢查,但我不想再花費更多的時間。你會想要添加你自己的文件名提示等。

#include <iostream> 
#include <string> 
#include <fstream> 

int main() 
{ 
    std::ifstream inFile("lena.ppm"); 
    if(!inFile) 
    { 
     std::cerr << "Could not open input file.\n"; 
     return -1; 
    } 

    std::string type; 
    std::string comment; 
    int width = 0, height = 0, colors = 0; 

    std::getline(inFile, type); 
    if(type != "P3") 
    { 
     std::cerr << "File is not a P3 format PPM.\n"; 
     return -1; 
    } 
    if(inFile.peek() == '#') 
    { 
     std::getline(inFile, comment); 
    } 
    inFile >> width >> height >> colors; 

    std::ofstream outFile("lena2.ppm"); 
    if(!outFile) 
    { 
     std::cerr << "Could not open output file.\n"; 
     return -1; 
    } 

    outFile << type << "\n"; 
    if(!comment.empty()) 
    { 
     outFile << comment << "\n"; 
    } 
    outFile << width << " " << height << "\n" << colors << "\n"; 
    for(int y = 0; y < height; ++y) 
    { 
     for(int x = 0; x < width; ++x) 
     { 
      int r = 0, g = 0, b = 0; 
      if(!(inFile >> r >> g >> b)) 
      { 
       std::cerr << "File ended early.\n"; 
       return -1; 
      } 
      b = (255 - b); 
      if(x != 0 && !(x % 5)) //Keep lines under 70 columns per spec. 
      { 
       outFile << "\n"; 
      } 
      outFile << r << " " << g << " " << b << " "; 
     } 
     outFile << "\n"; 
    } 
    return 0; 
}