user2028342
user2028342

Reputation:

How to create in ascii square, triangle, rectangle or circle with C++ and save it to portable bitmap file?

I don't know how to save in lines 0 and 1 to create a figure. This is my code, which generates lines with zeros. I need to create a square or trianlge, or rectangle (doesn't matter). Just need to know how to do that properly and save to pbm (portable bitmap) as monochromatic image.

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

using namespace std;

int main()
{
ofstream file;

int width=5;
int height=5;
int tab [10][10];

file.open("graphics.pbm");
if(file.good() == true)
{
    file << "P1" << endl;
    file << "# comment" << endl;
    file << "10 10" << endl;

    for (int  i=0; i<width; i++)
    {
        for (int j=0; j<height; j++)
        {
            tab[i][j]=0;
        }
    }

    for (int  i=0; i<width; i++)
    {
        for (int j=0; j<height; j++)
        {
            file << tab[i][j] << " ";
        }
    }

file.close();
}

return 0;
}

Upvotes: 3

Views: 1619

Answers (1)

coincoin
coincoin

Reputation: 4685

Well you have some work to do... You need to specify a function for each geometry form which would fill your image.

Here an example which is more C++ like where a class Image handle the methods to compute the geometric forms such as makeFillCircle(). Image class also handles the PBM output. Remark how easy it is now to save it using std::ostream operator<< !

#include <vector>
#include <iostream>
#include <algorithm>

struct Point { 
    Point(int xx, int yy) : x(xx), y(yy) {} 
    int x; 
    int y; 
};

struct Image {
    int width;
    int height;
    std::vector<int> data; // your 2D array of pixels in a linear/flatten storage

    Image(size_t w, size_t h) : width(w), height(h), data(w * h, 0) {} // we fill data with 0s

    void makeFillCircle(const Point& p, int radius) {
        // we do not have to test every points (using bounding box)
        for (int i = std::max(0, p.x - radius); i < std::min(width-1, p.x + radius) ; i ++) {
            for (int j = std::max(0,p.y - radius); j < std::min(height-1, p.y + radius); j ++) {
                // test if pixel (i,j) is inside the circle
                if ( (p.x - i) * (p.x - i) + (p.y - j) * (p.y - j) < radius * radius ) {
                    data[i * width + j] = 1;  //If yes set pixel on 1 !
                }
            }
        }
    }
};

std::ostream& operator<<(std::ostream& os, const Image& img) {
    os << "P1\n" << img.width << " " << img.height << "\n";
    for (auto el : img.data) { os << el << " "; }
    return os;
}

int main() {
    Image img(100,100);
    img.makeFillCircle(Point(60,40), 30); // first big circle
    img.makeFillCircle(Point(20,80), 10); // second big circle
    std::cout << img << std::endl; // the output is the PBM file
}

Live Code

Result is :

two circles

And voilà... I let you the fun to create your own functions makeRectangle(), makeTriangle() for your needs ! That requires some little maths !

Edit BONUS

As asked in the comment, here a little member function which would save the image in a file. Add it in the Image class (you can also if you prefer have a free function outside the class). Since we have a ostream operator<< this is straightforward :

void save(const std::string& filename) {
    std::ofstream ofs;
    ofs.open(filename, std::ios::out);
    ofs << (*this);
    ofs.close();
}

An other way without modifying the code would be to catch the output of the program in a file with something like this on your terminal :

./main >> file.pgm

Upvotes: 1

Related Questions