Question

I am building my first ever program in C++ over and over again.

The program is intended to create a picture, a gradient - with parameters of height h, width l, in pixels, and 4 parameters of density Da, Db, Dc, Dd. This gradient is produced by '1 bit' pixels: they are black or white - and by the simplest error-diffusion algorithm (so-called "naive" sometimes),

>> push the error on the next pixel of the line.

After having performed an optimization (deque instead of vector allows bigger images to be created for ex.), I am stuck with a problem that I cannot solve for now:

My pixel values being stored in a deque, how do I transport them into a bitmap file?

I tried to understand the EasyBMP library but I couldn't find the solution.

In my code, you can see line 33 that I tried (unsuccessfully) to make a .PBM header (Portable Bit Map)

Actually, I'd like to copy the values of my deque <int> dequeA; (line 30) to a .BMP file or any other raster file-format, instead of in a .txt file like it happens line 72!

Here's my code, and a nice picture of what it makes :

#include <iostream>
#include <fstream>
#include <vector>
#include <deque>
#include <iterator>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;

// constant values

double   Da=1;          //densities
double   Db=0.5;
double   Dc=0.5;
double   Dd=0;

double      l = 999;    //width & height => L = l+1  ///  999 = 1000 pixels
double      h = 999;

//double      u = 1;    // UNIT

double      D = 0;      // GAMMA
double      E = 0;      // ERROR LOCAL
vector <double> F;      // ERROR DYNAMIC

int main ()
{
    // vector
    deque <int> dequeA;
    F.push_back (0);

    //dequeA.push_back (2);     //FAKE PBM header (old)
    //dequeA.push_back (l+1);
    //dequeA.push_back (h+1);
    //dequeA.push_back (1);

    float a = 0;
    float b = 0;                // Local variables
    double IO = 0;              // variable I/O

    while (a<l+1, b<h+1){

        //values for given a & b
        double DL = Da-Da*(b/h)+Dc*(b/h);
        double DR = Db-Db*(b/h)+Dd*(b/h);
        double D  = DL-DL*(a/l)+DR*(a/l); //GAMMA

        if (E+0-D<=-0.5) {
            dequeA.push_back(1);
            IO = 1;
        }

        else {
            dequeA.push_back(0);
            IO = 0;
        }

        E = E+IO-D;
        F.push_back(E);

        // next pixel & next line
        a++;
        if (a>l) {
            a = 0;
            b = b++;
            E = 0;
            F.clear();
        }
    }
    //export values to .txt file
    ofstream output_file("./test.txt");
    ostream_iterator<int> output_iterator(output_file, "\n");
    copy(dequeA.begin(), dequeA.end(), output_iterator);
    dequeA.clear();
}

simplest error-diffusion with 4 corner-located density parameters

Was it helpful?

Solution

PBM files are very easy to create and should suffice for your purpose. No need to use an external library.

A problem in your original code was that you were storing both the PBM metadata and the actual image data in the same dequeA. Don't do that. Mixing data like this makes your program hard to understand and maintain.

You can create a valid PBM file by slightly adjusting the code writing the file:

ofstream output_file("./test.ppm");

// write file header
output_file << "P1\n" << (l+1) << " " << (h+1) << "\n";
//write image data
ostream_iterator<int> output_iterator(output_file, "\n");
copy(dequeA.begin(), dequeA.end(), output_iterator);

The resulting PPM file works fine with Gimp.

Writing to a BMP or TGA file works basically the same - you first write a header, followed by the actual data. The main difference is that those file formats are binary files, so the file I/O looks a bit different, and the header and image data formats are slightly more complicated. But still, both formats are quite simple and easy to write even without using a library.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top