2015-02-08 37 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; 
}