1

私は C++ が初めてで、少しイライラしています。以下の pixelVector では、各ピクセルの RGB 浮動小数点値を Pixel に格納しています。すべての値を、pixelsArray を使用してバイト配列にダンプして、画像ファイルに出力できるようにします。HEIGHT と WIDTH は画像の寸法を表します。以下のコードは問題なく動作しますが、実行時に pixelArray のサイズを指定する必要があります。これは、常に 500x500 の画像であるとは限らないためです。

// WIDTH and HEIGHT specified at run-time
vector<vector<Pixel>> pixelsVector (WIDTH, vector<Pixel> (HEIGHT));

...

unsigned char pixelsArray[500][500][3];

for (int i = 0; i < 500; i++)
{
    for (int j = 0; j < 500; j++)
    {
        // Returns RGB components
        vector<float> pixelColors = pixelArray[i][j].getColor();

        for (int k = 0; k < 3; k++)
        {
            pixels[i][j][k] = pixelColors.at(k);
        }
    }
}

// write to image file
fwrite(pixelsArray, 1, 500*500*3, file);

上記の 500 と 500 の代わりに HEIGHT と WIDTH を入力すると、定数値ではないためエラーが発生します。現在、3D ベクトルの使用は機能しているように見えますが、fwrite は最初の引数にベクトルを取りません。トリプルポインター配列を使用してみましたが、まったく機能していないようです - 間違った使い方をしていたのかもしれません。ここでは、pixelsArray に 3D ベクトルを使用しています。

vector<vector<Pixel>> pixelsVector (WIDTH, vector<Pixel> (HEIGHT));

...

vector< vector< vector<unsigned char> > > pixelsArray;

for (int i = 0; i < HEIGHT; i++)
{
    pixels.push_back(vector< vector<unsigned char> >());

    for (int j = 0; j < WIDTH; j++)
    {
        pixels[i].push_back(vector<unsigned char>());

        vector<float> pixelColors;
        pixelColors = pixelArray[i][j].getColor();

        for (int k = 0; k < 3; k++)
        {
            pixels[i][j][k] = pixelColors.at(k);
        }
    }
}

// Error
fwrite(pixelsArray, 1, 500*500*3, file);

提案?

4

2 に答える 2

1

最後のコード スニペットから:

vector<vector<Pixel>> pixelsVector (WIDTH, vector<Pixel> (HEIGHT));

変数に大文字の名前を使用すると、名前がマクロと衝突する危険があります。C++ では、慣習的にすべての大文字の名前がマクロ用に予約されています。

...

vector< vector< vector<unsigned char> > > pixelsArray;

pixelsおそらく、このベクトルは以下で呼ばれるものと同じですか?

もしそうなら、標準的なアドバイスは、実際のコードを投稿するのに役立つということです.

とにかく、これらのバイトを 1 回の効率的な操作で出力するには、バイトをメモリに連続して格納する必要があります。したがって、ベクトルのベクトルのベクトルが出力されます。単一のベクトルを使用します (C++ は a のバッファーに連続したストレージを保証しますstd::vector)。

for (int i = 0; i < HEIGHT; i++)
{
    pixels.push_back(vector< vector<unsigned char> >());

    for (int j = 0; j < WIDTH; j++)
    {
        pixels[i].push_back(vector<unsigned char>());

この時点で、内部ベクトルがありますが、空で、サイズは 0 です。

        vector<float> pixelColors;
        pixelColors = pixelArray[i][j].getColor();

おそらくpixelArray、定義したクラスのインスタンスですか?

        for (int k = 0; k < 3; k++)
        {
            pixels[i][j][k] = pixelColors.at(k);
        }

ここでは、空の最も内側のベクトルの存在しない要素に代入しようとしています。事前に適切なサイズにすることも、push_back各値に対してメソッドを使用することもできます。

さらに、float値が 0 から 255 (またはより一般的には 0 から UCHAR_MAX) の範囲の整数であり、たとえば 0 から 1 の範囲ではないことを確認しますか?

おそらく、これらの値をスケーリングする必要があります。

    }
}

// Error
fwrite(pixelsArray, 1, 500*500*3, file);

pixelsArrayが (空でない) バイトのベクトルであった場合、最初のバイトへのポインターを取得するために使用できます&pixelsArray[0]

さて、私は知っていますが、上記は何が間違っているかを分析しているだけで、何が正しいかを直接伝えていません. :-)

ただし、これを行うためのコード例を示すには、(1)float値は何か、(2) ファイルに何が必要かなど、さらに情報が必要です。

とにかく、これが役に立てば幸いです。

– アルフ

于 2010-10-10T23:48:25.440 に答える
1

ベクトルのベクトルの代わりに Boost.MultiArray を使用できます。これにより、.data() メソッドを使用して基になるメモリにアクセスできます。

画像を操作しようとしているように見えるので、Boost.Gilの使用を検討することをお勧めします。

于 2010-10-10T22:54:41.240 に答える