Проблема извлечения пиксельных данных из растрового изображения - PullRequest
0 голосов
/ 22 мая 2019

Я использую нативный C ++ без создания библиотеки обработки изображений с нуля, в настоящее время для растровых изображений.

Например, я использую следующее для извлечения пиксельных данных из растрового изображения после установки положения потока в правильное местоположение.

fread(pixelDataBuffer, sizeof(unsigned char), (height * width), streamIn);

Где высота и ширина - размеры в пикселях растрового изображения. Я думал, что это будет работать и имеет смысл для изображения с 8 битами на пиксель, но оно все еще не работает (функция возвращает 0). Это происходит даже при том, что высота и ширина имеют значения по 256 для каждого, а pixelDataBuffer инициализируется, как показано ниже:

unsigned char pixelDataBuffer[height * width]; 
// also tried:
unsigned char pixelDataBuffer[65536]; // which is 256*256

Спасибо!

Добавление кода для ясности:

bool isTrial = true;
FILE *streamIn;
FILE *outputFile;

int main(int argc, const char * argv[]) {

    if (isTrial) {
        streamIn = fopen("Images/cameraman.bmp", "rb");
        outputFile = fopen("Images/cameraman_copy.bmp", "wb");
    } else {
        streamIn = fopen("Images/flag.bmp", "rb");
        outputFile = fopen("Images/flag_copy.bmp", "wb");
    }

    unsigned char header[54];
    unsigned char colourTable[1024];

    if (streamIn == nullptr) {
        printf("null pointer");
    } else {

        for (int i = 0; i < 54; i++) {
            header[i] = getc(streamIn);
        }

        unsigned int width = *(int*)&header[18];
        cout << "width: " << width << "\n"; // = 256

        unsigned int height = *(int *)&header[22];
        cout << "height: " << height << "\n"; // = 256

        unsigned short bitDepth = *(short *)&header[28];
        cout << "bitDepth: " << bitDepth << "\n"; // = 8

        unsigned int fileSize = *(int *)&header[2];
        cout << "fileSize: " << fileSize << endl; // 66614

        if (1 < bitDepth && bitDepth <= 8) {
            short count = fread(colourTable, sizeof(unsigned char), 1024, streamIn); 
            if (count == 1024) {
                printf("colourTable read\n"); // colourTable gets read
            } else {
                printf("colourTable NOT read properly");
            }
        } else {
            printf("bitsPerPixel / bitDepth is more than 8");
        }


        { // getting pixelData, at this point I assumed that the stream's position starts where pixel data starts (i.e. after Headers & ColourTable)

            unsigned int pixelDataSize = height * width * (bitDepth/8); // = 65536
            cout << "pixelDataSize: " << pixelDataSize << endl;

            unsigned char pixelDataBuffer[pixelDataSize]; // also tried initializing like unsigned char pixelDataBuffer[height*width]

            short counter = fread(pixelDataBuffer, sizeof(unsigned char), pixelDataSize, streamIn);
            cout << "counter: " << counter << endl; // = 0 THIS IS THE ISSUE. Documentation says "If either size or count is zero, the function returns zero and both the stream state and the content pointed by ptr remain unchanged." But I think I have size and count >0 correctly?

        }


        { // writing our header onto the outputFile
            short count = fwrite(header, sizeof(unsigned char), 54, outputFile);
            if (count == 54) {
                printf("header written\n"); // Header gets written
            } else {
                printf("header not written");
            }
        }
    }
    return 0;
}

1 Ответ

3 голосов
/ 22 мая 2019

Ваша проблема объявляет результат фреда коротким.

Старайтесь всегда использовать авто как можно больше. Использование:

auto counter = fread(pixelDataBuffer, sizeof(unsigned char), pixelDataSize, streamIn);

заставляет это работать. Проблема в том, что 65536 не может быть представлено вкратце, фактически она переполняет ее настолько, что кажется, что результат будет 0.

Если вы используете более старую версию C ++ (до C ++ 11) и вы не можете использовать auto, используйте вместо этого size_t (который является фактическим возвращаемым типом fread).

Я бы также посоветовал вам научиться разбивать код на более мелкие функции и избегать написания огромных блоков if для удобства чтения и поддержки в будущем.

...