Запись bmp файла на C дает неверный результат - PullRequest
0 голосов
/ 23 июня 2018

Я пытаюсь написать функцию, которая читает файл bmp, а затем делает его копию. Я, как обычно, читаю заголовок изображения в структуру и копирую значения пикселей в матрицы RGB.

Функция, которую я создаю для записи файла BMP, дает правильную ширину / высоту и размер изображения, но изображение все черное, а когда значения пикселей неверны (я сравниваю его с исходным изображением BMP). сделав шестнадцатеричный дамп с xxd).

Вот функция для записи файла BMP:

void writeBMP(BMPFILEHEADER *headerData,BMPINFOHEADER *headerInfo, int values[headerInfo->width*headerInfo->height]) {

        FILE *out;
        out = fopen("example.bmp", "wb");
        fwrite(headerData, sizeof(char), sizeof(BMPFILEHEADER), out);
        fseek(out, 14, SEEK_SET);
        fwrite(headerInfo, sizeof(char), sizeof(BMPINFOHEADER), out);
        fseek(out, 54, SEEK_SET);
        fwrite(values, sizeof(char), headerInfo->imagesize, out);
        fclose(out);
    }

Я проверил values (там я и сохранил данные пикселей), используя printf, и значения пикселей совпадают с пикселями исходного изображения. Но похоже, что строка fwrite(values, sizeof(char), headerInfo->imagesize, out) записывает неверные данные в файл.

РЕДАКТИРОВАТЬ: я добавляю другие детали о коде

Функция для чтения данных пикселей:

RGBmatrix readPixels(char *fileName, BMPFILEHEADER *header, BMPINFOHEADER *info) {
    FILE *fp;
    int **matR, **matG, **matB;
    int RGBvalues[info->width][info->height];

    RGBmatrix values;

    matR = allocateRGB(matR, info->width, info->height);
    matG = allocateRGB(matG, info->width, info->height);
    matB = allocateRGB(matB, info->width, info->height);

    fp = fopen(fileName, "rb");
    if(fp==NULL) {
        printf("Can't open file\n");
    }

    fseek(fp, header->offset, SEEK_SET);

    for(int i = 0; i<info->width; i++) {
        for(int j=0; j<info->height;j++) {
            fread(&RGBvalues[i][j], 3, 1, fp);
        }
    }

    for(int i=0; i<info->width; i++) {
        for(int j=0; j<info->height; j++) {
            matB[i][j] =  RGBvalues[i][j] & 0xff;
            matG[i][j] = (RGBvalues[i][j]>>8) & 0xff;
            matR[i][j] = (RGBvalues[i][j]>>16) & 0xff; 
        }
    }

    values.R = matR;
    values.G = matG;
    values.B = matB;

    return values;
}

Структуры для хранения данных BMP:

typedef struct RGBmatrix {
    int **R, **G, **B;
}RGBmatrix;

typedef struct BMPFILEHEADER {
    short int magicNumber;
    int bmpfSize;
    short int reserved1;
    short int reserverd2;
    int offset;
}BMPFILEHEADER;

typedef struct BMPINFOHEADER {
    unsigned int size;
    int width, height;
    unsigned short int planes;
    unsigned short int bits;
    unsigned int compression;
    unsigned int imagesize;
    int xresolution, yresolution;
    unsigned int ncolours;
    unsigned int importantcolours;
}BMPINFOHEADER;

Моя основная функция:

int main(int argc, char *argv[]) {
    BMPFILEHEADER headerData;
    BMPINFOHEADER headerInfo;
    FILE *fp;
    char fileName[20];

    strcpy(fileName, argv[1]); // command line argument to bmp file

    readBMPHeader(fileName, &headerData, &headerInfo); // read header data
    RGBmatrix values = readPixels(fileName, &headerData, &headerInfo); // read pixels

    int rgbModifiedValues[headerInfo.width*headerInfo.height];

    // do stuff with RGB values and store them into rgbModified Values

    writeBMP(&headerData, &headerInfo, rgbModifiedValues);

    return 0;
}

1 Ответ

0 голосов
/ 23 июня 2018

Я ожидаю, что вы пишете 256-цветный (8-битный) файл BMP.

Если это так, возможно, что, используя int значения, вы записываете неверные записи в файле:

  these are not 8-bit in size
  |
  v
  int values[headerInfo->width*headerInfo->height])


  fwrite(values, sizeof(char), headerInfo->imagesize, out);
                 ^
                 |
                 but here you seem to treat them as if they are

Вы должны использовать unsigned char или uint8_t, если доступно.

Если я прав, то теперь вы должны видеть изображение, которое в основном черное (или в основном одноцветное), с вертикальными или диагональными полосами, и в шестнадцатеричном дампе должны отображаться ненулевые значения, чередующиеся с одним или тремя нулями; ненулевые значения сами по себе являются правильными:

Expected pixel values
12  17  4B

Integer values in memory, read as bytes:

12 0 0 0 17 0 0 0 4B 0 0 0
...