Array problem between 2 class

Hello there !

I am trying to write values into arrays with a method add_general_noise() which generates an int random value and writes it into arrays.

The arrays are in a first class ppm_file. I am trying to put numbers into these arrays in a class general_noise.

When I do something in general_noise and I try to return in ppm_file, it does not work.

For instance, I try to write random values on my arrays. I create a noise object and I apply a method to this object which writes random values on arrays. This method works and the arrays are full in general_noise but in ppm_file, arrays are still empty.



Where are the usefull lines :
ppm_file.h :
1
2
3
4
5
6
7
8
9
  class ppm_file
        : public ofstream
{

    int R[100][100];
    int G[100][100];
    int B[100][100];

};


ppm_file.cpp :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
             R[i][j] = 0;
             G[i][j] = 0;
             B[i][j] = 0;
        }
    }
    cout << "Initialisation des valeurs terminee" << endl;

    //Creating a general_noise object
    general_noise noise;
    cout << "Generation terminee !" << endl;

    //Writing the file

    cout << "Ecriture du fichier en cours ..." << endl;
    for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
            //R
            *this << R[i][j] << endl;
            //G
            *this << G[i][j] << endl;
            //B
            *this << B[i][j] << endl;
        }
    }



general_noise.h :
1
2
3
4
5
6
7
8
9
10
11
12

class general_noise : public ppm_file
{
public:
    general_noise();

    void add_general_noise(unsigned int width, unsigned int height);
    int get_int_value(unsigned int gain);

};




general_noise.cpp :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cout << "Ajout de valeurs de bruit a l'image..." << endl;
    for(unsigned int i=0; i<width; i++)
    {
        for(unsigned int j=0; j<height; j++)
        {
            int test = get_int_value(100);
            //cout << test << endl;
            R[i][j] = test;
            G[i][j] = test;
            B[i][j] = test;
            cout << R[i][j] << endl;
        }
    }

    cout << "Ajout des valeurs terminee !" << endl;


I hope you'll understand me. Thank you !
Please post the entire functions not just parts of it.

But I guess that the problem is line 13. The object noise may contain the generated values, but there is no magic that transports those values to the R/G/B values which are previously set to 0 within the loop on line 1 in ppm_file.cpp.

Your inheritance is a bit off. It is certainly not recommended to inherite from ofstream. Further more: general_noise sounds like a function, not like a class...
I, thank you. I thought that arrays were writable in every inherited class.
The project is to make a software which generates sky images with stars, galaxies or others things... so I make a .ppm file and I write values inside. general_noise has to add noise to the image. In the future, I would like to make one class by sky object or by function.

For instance :
class stars
class galaxie
class noise
class chromatic aberation
...

Have I to rename my class general_noise into "noise" and create a function general_noise() ?

ppm_file.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef PPM_FILE_H
#define PPM_FILE_H
#include<fstream>
#include<string>
#include<random>


using namespace std;

class ppm_file
        : public ofstream
{
public:
    ppm_file();
    //Constructor with name, size and max level parameters
    ppm_file(const string& name, unsigned int width, unsigned int height, unsigned int max_level);

    void ppm_image(unsigned int width, unsigned int height, unsigned int max_level);
    void ppm_close();

    string name;

    unsigned int width; //largeur
    unsigned int height; //hauteur
    unsigned int max_level;

    //Three colors arrays

    /* For futur implementation
    vector<vector<int>> R;
    vector<vector<int>> G;
    vector<vector<int>> B;
    */

    int R[100][100];
    int G[100][100];
    int B[100][100];


};

#endif // PPM_FILE_H 


ppm_file.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include<iostream>
#include<vector>
#include<random>
#include<chrono>
#include<new>
#include "ppm_file.h"
#include "general_noise.h"

using namespace std;
//ppm_file file;


/*
//seed creation, based on date
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);*/

/* The random generator seems to works only with double or float
 *
 * To get unsigned int, we just take the round(abs()) value of this float number
 * *
normal_distribution<float> distri(0.0, 0.15);
*/

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


/**
 * @brief ppm_file::ppm_file
 * This constructor creates a ppm file with its header and run a body function. This is the default image : 100*100, max value = 255
 * Be careful ! If the file already exists, he's deleted.
 * @date 04-16-2019
 * @author Alexandre Bouton
 */
ppm_file::ppm_file()
{
    //Creating the file
    this->open("my_ppm_file.ppm", ofstream::trunc);

    //Put the default width and height values to 100 pixels
    width = height = 100;
    max_level = 255;

    /**************************
     * PPM file structure:
     *
     * P3               <- for the type of Netpbm format (P1 = PBM, P2 = PGM, P3 = PPM). "P3" means this is a RGB color image in ASCII
     * x y              <- x is the width and y is the height
     * max              <- maximum color level
     *
     * The part under this header is the image
     **************************/
    *this << "P3\n";
    *this << width;
    *this << " ";
    *this << height;
    *this << "\n";
    *this << max_level;
    *this << "\n";

    //Close the file
    //ppm_image(name...
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


/**
 * @brief ppm_file::ppm_file
 * This constructor creates a ppm file with its header and run a body function
 * Be careful ! If the file already exists, he's deleted.
 * @param name the name of the file
 * @param width
 * @param height
 * @param max_level the white level
 * @author Alexandre Bouton
 * @date 04-16-19
 */
ppm_file::ppm_file(const string& name, const unsigned int width, const unsigned int height, const unsigned int max_level)
{
    //Creating the file

    cout << "Creation du fichier..." << endl;
    cout << "Creationde l'en-tete..." << endl;
    this->open(name, ofstream::trunc);

    /**************************
     * PPM file structure:
     *
     * P3               <- for the type of Netpbm format (P1 = PBM, P2 = PGM, P3 = PPM). "P3" means this is a RGB color image in ASCII
     * x y              <- x is the width and y is the height
     * max              <- maximum color level
     *
     * The part under this header is the image
     **************************/
    *this << "P3\n";
    *this << width;
    *this << " ";
    *this << height;
    *this << "\n";
    *this << max_level;
    *this << "\n";


    cout << "En-tete cree !" << endl;
    ppm_image(width, height, max_level);
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


/**
 * @brief ppm_file::ppm_image
 * This function creates the body of the ppm file
 * @author Alexandre Bouton
 * @date 04-16-19
 */
void ppm_file::ppm_image(unsigned int width, unsigned int height, unsigned int max_level)
{
    //Creating empty arrays

    for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
             R[i][j] = 0;
             G[i][j] = 0;
             B[i][j] = 0;
        }
    }
    cout << "Initialisation des valeurs terminee" << endl;

    //Creating a general_noise object
    general_noise noise;
    cout << "Generation terminee !" << endl;

    //Writing the file

    cout << "Ecriture du fichier en cours ..." << endl;
    for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
            //R
            *this << R[i][j] << endl;
            //G
            *this << G[i][j] << endl;
            //B
            *this << B[i][j] << endl;
        }
    }

    close();
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


void ppm_file::ppm_close()
{
    close();
}
This message was too long si I have to post an other :


general_noise.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GENERAL_NOISE_H
#define GENERAL_NOISE_H
#include<random>
#include<iostream>
#include<chrono>
#include<vector>
#include"ppm_file.h"


class general_noise : public ppm_file
{
public:
    general_noise();

    void add_general_noise(unsigned int width, unsigned int height);
    int get_int_value(unsigned int gain);

};

#endif // GENERAL_NOISE_H




general_noise.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "general_noise.h"


using namespace std;
/**
 * @brief general_noise::general_noise
 * This class generates noise to add a real dimension to the image
 *
 * @author Alexandre Bouton
 * @date 04-24-2019
 */

//seed creation, based on date
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);

/* The random generator seems to works only with double or float
 *
 * To get unsigned int, we just take the round(abs()) value of this float number
 * */
normal_distribution<float> distri(0.0, 0.15);


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


/**
 * @brief general_noise::general_noise
 * While the method "add_general_noise" is not
 * called, nothing is added to the image
 */
general_noise::general_noise()
{
    cout << "Creation d'un general_noise..." << endl;
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


void general_noise::add_general_noise(unsigned int width, unsigned int height)
{
    cout << "Ajout de valeurs de bruit a l'image..." << endl;
    for(unsigned int i=0; i<width; i++)
    {
        for(unsigned int j=0; j<height; j++)
        {
            int test = get_int_value(100);
            //cout << test << endl;
            R[i][j] = test;
            G[i][j] = test;
            B[i][j] = test;
            cout << R[i][j] << endl;
        }
    }

    cout << "Ajout des valeurs terminee !" << endl;
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                                               */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */


int general_noise::get_int_value(unsigned int gain)
{
    float raw_random_number = distri(generator);
    if (raw_random_number > 1)
        raw_random_number = 1;
    else if(raw_random_number < -1)
        raw_random_number = -1;

    float normalized_random_number = raw_random_number * gain;

    int int_normalized_random_number = round(abs(normalized_random_number));
    //cout << int_normalized_random_number << endl;
    return int_normalized_random_number;
}


If you want, I put my QT project on github :
https://github.com/AlexandreBouton/image_du_ciel
Last edited on
I, thank you. I thought that arrays were writable in every inherited class.
Member variables of a base class are accessible by the inherited class when they are public or protected (not private).

That's not your problem here. You have different instances/objects of the classes. The objects do not share data unless the member variables are static. Thus the data of noise and the surrounding ppm_file are not shared.

I would like to make one class by sky object or by function.

For instance :
class stars
class galaxie
class noise
class chromatic aberation
I would suggest the following design:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class ppm // _file?
        : public ofstream
{
public:
    ppm(unsigned int w,  unsigned int h, unsigned int m_level) : width{w}, height{h}, max_level{m_level}
    {
    }
    //Constructor with name, size and max level parameters

    bool write_to_file(const string& name); // Not a constructor
{
    //Creating the file

    cout << "Creation du fichier..." << endl;
    cout << "Creationde l'en-tete..." << endl;
    ofstream ofs(name, ofstream::trunc); // Will close automatically at the end of the function

    /**************************
     * PPM file structure:
     *
     * P3               <- for the type of Netpbm format (P1 = PBM, P2 = PGM, P3 = PPM). "P3" means this is a RGB color image in ASCII
     * x y              <- x is the width and y is the height
     * max              <- maximum color level
     *
     * The part under this header is the image
     **************************/
    ofs << "P3\n";
    ofs << width;
    ofs << " ";
    ofs << height;
    ofs << "\n";
    ofs << max_level;
    ofs << "\n";


    cout << "En-tete cree !" << endl;
    ppm_image(ofs width, height, max_level);
}


    void ppm_image(ostream &os unsigned int width, unsigned int height, unsigned int max_level); // Called from write_to_file(...) / User membervariable instead of parameter
{
    //Creating empty arrays

    for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
             R[i][j] = 0;
             G[i][j] = 0;
             B[i][j] = 0;
        }
    }
    cout << "Initialisation des valeurs terminee" << endl;

    //Creating a general_noise object
    general_noise noise;
    generate(); // Now you can override this function which generates the data you want
    cout << "Generation terminee !" << endl;

    //Writing the file

    cout << "Ecriture du fichier en cours ..." << endl;
    for(unsigned int i=0; i<height; i++)
    {
        for(unsigned int j=0; j<width; j++)
        {
            //R
            os << R[i][j] << endl;
            //G
            os << G[i][j] << endl;
            //B
            os << B[i][j] << endl;
        }
    }

    close();
}
    virtual void generate() = 0;

    void ppm_close();

    string name;

    unsigned int width; //largeur
    unsigned int height; //hauteur
    unsigned int max_level;

    //Three colors arrays

    /* For futur implementation
    vector<vector<int>> R;
    vector<vector<int>> G;
    vector<vector<int>> B;
    */

    int R[100][100];
    int G[100][100];
    int B[100][100];


};

class noise : public ppm
{
    virtual void generate() override
{
    cout << "Ajout de valeurs de bruit a l'image..." << endl;
    for(unsigned int i=0; i<width; i++) // width -> use member variable
    {
        for(unsigned int j=0; j<height; j++) // height -> use member variable
        {
...
}
};
Not tested
Last edited on
Hey, I am trying to implement you code. What means override ? It does not work in my code.

Plus, the constructor of noise does not work.

1
2
3
4
noise::noise()
{

}


error : constructor for 'noise' must explicitely initialize the base class 'ppm_file' which does not have a default constructor
Last edited on
What means override ?
This:

https://en.cppreference.com/w/cpp/language/override

That means that you use an outdated compiler. You should really use a more recent one. You can actually omit override.

Plus, the constructor of noise does not work.
You need to provide the parameter to the base constructor:
1
2
3
4
5
6
7
8
class noise : public ppm_file
{
  noise(unsigned int w, unsigned int h, unsigned int m_level) : ppm_file(w,  h, m_level)
{
}

...
};
saxoalex, Qt has a tool to easily update all its components, compiler included: the Maintenance Tool.
If you cannot find it, search for MaintenanceTool.exe in your HD.

Topic archived. No new replies allowed.