C ++ с использованием трехмерных динамических массивов и векторов - PullRequest
1 голос
/ 11 октября 2010

Я новичок в C ++ и немного разочарован этим.Ниже в pixVector я сохраняю значение каждого пикселя RGB в формате Pixel и хочу вывести все значения в байтовый массив с помощью pixArray, чтобы я мог вывести его в файл изображения.ВЫСОТА и ШИРИНА относятся к размерам изображения.Приведенный ниже код работает нормально, но мне нужно указать размеры пикселя массива во время выполнения, потому что он не всегда может быть изображением 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выше я получаю ошибку, так как они не являются постоянными значениями.Теперь использование трехмерного вектора действительно работает, но fwrite не будет принимать вектор в качестве первого аргумента.Я попытался использовать массив из трех указателей, но он, похоже, не работает вообще - возможно, я использовал его неправильно.Здесь используется трехмерный вектор для пикселов. Массив:

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);

Предложения?

Ответы [ 2 ]

1 голос
/ 11 октября 2010

Из последнего фрагмента кода:

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

Используя имена переменных в верхнем регистре, вы рискуете столкнуться с макросами. В C ++ все прописные имена условно зарезервированы для макросов.

...

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

Предположительно, этот вектор такой же, как называется pixels ниже?

Если это так, то стандартный совет заключается в том, что это помогает опубликовать реальный код.

В любом случае, чтобы вывести эти байты за одну эффективную операцию, необходимо, чтобы байты непрерывно сохранялись в памяти. Таким образом, вектор векторов векторов отсутствует. Используйте один вектор (C ++ гарантирует непрерывное хранение для буфера 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) что вы хотите в своем файле?

В любом случае, надеюсь, это поможет,

- Альф

1 голос
/ 11 октября 2010

Вы можете использовать Boost.MultiArray, не содержащее векторов, чтобы получить доступ к основной памяти с помощью метода .data ().

Похоже, вы пытаетесь манипулировать изображениями, поэтому вы можете рассмотреть возможность использования Boost.Gil .

...