如何编辑图像的值

时间:2015-02-08 09:25:45

标签: c++

我在玩文件时遇到了一些麻烦。这是我想要完成的。我试图通过取蓝色值的倒数(每三个值)来过滤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;
}

2 个答案:

答案 0 :(得分: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文件并读取图像。

答案 1 :(得分: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;
}