Изменение размера длины и ширины файла тома в C

#c #image-processing

#c #обработка изображений

Вопрос:

У меня есть файл тома с переменной длиной фрагмента, высотой изображения 640 и шириной изображения 512. Я хочу преобразовать его в файл высотой 620 и шириной 420 и записать его в новый файл. Я хочу убрать 20 пикселей от верхней части высоты и снять 46 с каждой стороны ширины, чтобы выполнить это изменение размера. Каждый пиксель имеет 16 бит без знака. Я не уверен, как выполнить фактические манипуляции.

Это то, что у меня есть в моем основном:

 FILE* pfile = NULL;
FILE* pfile2 = NULL;

pFile = fopen("test.vol", "rb");
fseek (pFile , 0 , SEEK_END);

int fileData = ftell(pFile);
rewind(pFile);

char* FileBuffer = new char[fileData];
fread(FileBuffer, fileData, 1, pFile);

int height = 640;
int width = 512;
int slizeSize = height * width * 2;
int sliceCount = fileData / sliceSize;
uint16_t pixels;

int newHeight = height - 20;
int newWidth = width - 92;
int newSliceSize = newHeight * newWidth * 2;
int newImageSize = newSliceSize * sliceCount;

char* NewFileBuffer = new char[newImageSize];

for (int i = 0; i < newHeight; i  ) {

    for (int i = 0; i < newWidth; i  ) {

    }
   // need help in these for loops and after

}

fclose (pFile);
free (FileBuffer);

pFile2 = fopen("test2.vol", "wb");
fwrite(NewFileBuffer, NewImageSize, 1, pFile2);
  

Ответ №1:

Если вы программируете на C , используйте C : get rid of FILE* и другие C-вещи.

Вы выделяете массив char with new , но вызываете free , чтобы освободить память: вы должны вызвать delete[] или, что еще лучше, использовать std::vector и позволить ему управлять памятью для вас.

Вы имеете дело с 16-битными значениями, так почему бы не читать / записывать / обрабатывать 16-битные значения?

Сначала прочитайте файл:

 #include <fstream>
#include <iterator>
#include <vector>

int main()
{
    using data_type = uint16_t;

    std::basic_ifstream<data_type> file_in{
        "test.vol",
        std::ifstream::binary
    };
    std::vector<data_type> FileBuffer{
        std::istreambuf_iterator<data_type>(file_in), 
        std::istreambuf_iterator<data_type>() // end of stream iterator
    };
  

Теперь FileBuffer это массив uint16_t , заполненный содержимым "test.vol" , с управляемым распределением и освобождением памяти.

Следующая часть, измените размер тома. Я предполагаю, что ваши данные упакованы в следующем порядке: столбцы, строки, фрагменты. Неясно, являются ли верхние строки первыми или последними строками фрагмента. Вот мое предложение с использованием итераторов и std::copy :

     size_t height = 640, width = 512;
    size_t sliceSize = height * width;
    size_t sliceCount = FileBuffer.size() / sliceSize;

    size_t newHeight = height - 20, newWidth = width - 92;
    size_t newSliceSize = newHeight * newWidth;
    size_t newImageSize = newSliceSize * sliceCount;

    std::vector<data_type> NewFileBuffer(newImageSize);

    auto it_buffer = FileBuffer.begin();
    auto it_new_buffer = NewFileBuffer.begin();

    for (size_t i = 0; i < sliceCount;   i)
    {
        // skip 20 first lines, remove and uncomment the next line
        // if you want to skip the last ones
        auto it_line = it_buffer   20*width;
        //auto it_line = it_buffer;

        for (size_t j = 0; j < newHeight;   j)
        {
            auto it_column = it_line   46;

            it_new_buffer = std::copy(
                it_column,
                it_column   newWidth,
                it_new_buffer
            );

            it_line  = width; // go to next line
        }

        it_buffer  = sliceSize; // go to next slice
    }
  

Наконец, запишите файл:

     std::basic_ofstream<data_type> file_out{
        "test2.vol",
        std::ofstream::binary
    };
    std::copy(
        NewFileBuffer.begin(),
        NewFileBuffer.end(),
        std::ostreambuf_iterator<data_type>(file_out)
    );
}
  

Комментарии:

1. Спасибо, но при компиляции я получаю кучу ошибок. ошибка: ожидаемый спецификатор вложенного имени перед ‘data_type’, похоже, вызвал цепную реакцию ошибок

2. Я попытался выполнить дополнение в c 11 и 98 и все равно получил ошибки

3. Хорошо, я исправил эту ошибку. Теперь я получаю сообщение «завершение вызывается после создания экземпляра ‘std:: bad_cast’ what (): std:: bad_cast прерван (сброс ядра)»

4. Код действительно c 11. Как вы исправили ошибки? Какой вызов вызывает вызов?

5. Я изменил using data_type uint16_t; на using data_type = uint16_t;. Я попытался использовать gdb для отладки программы, но это не дает мне понятия о том, где у него проблемы