首页 > 解决方案 > 在 C 中编写 bmp 文件时得到模糊的结果

问题描述

我正在尝试将unsigned char我从相机中抓取的数组写入 bmp 文件。除了输出图像奇怪且模糊之外,它似乎运行良好。奇怪的是,当我保存为 png 格式时,我有一个很好的图像。当我使用 hexreader 检查文件时,我得到了好的标题和正确的数据大小。所以我想知道如果我只是向它写入像素,为什么图像会变得模糊。我想使用 bmp 格式,因为我从树莓派上的相机中抓取图片。我想要一个高帧率,所以 png 写在磁盘上太慢了。

bmp 文件的标题:

00000000: 424d 36bb 1700 0000 0000 3600 0000 2800  BM6.......6...(.
00000010: 0000 a005 0000 3804 0000 0100 0800 0000  ......8.........
00000020: 0000 00bb 1700 232e 0000 232e 0000 0000  ......#...#.....
00000030: 0000 0000 0000                           ......

后面是正确的长度:1555200 字节。

这是我编写 bmp 文件的函数:

#define BMP_HEADER_SIZE 14
#define BMP_INFO_HEADER_SIZE 40
#define BMP_NO_COMPRESSION 0
#define BMP_MAX_NUMBER_OF_COLORS 0
#define BMP_ALL_COLOR_REQUIRED 0

int saveImgToBmp(unsigned char *data, const char *path, int width, int height,
                 int bytesPerPixel) {
    FILE *fp = fopen(path, "wb");

    // Writing header
    const char *BM = "BM";
    fwrite(&BM[0], 1, 1, fp);
    fwrite(&BM[1], 1, 1, fp);

    int paddedRowSize = (int) (4 * ceil((float) width / 4.0f)) * bytesPerPixel;
    uint32_t fileSize = paddedRowSize * height + BMP_HEADER_SIZE + BMP_INFO_HEADER_SIZE;
    fwrite(&fileSize, 4, 1, fp);
    uint32_t reserved = 0x0000;
    fwrite(&reserved, 4, 1, fp);
    uint32_t dataOffset = BMP_HEADER_SIZE + BMP_INFO_HEADER_SIZE;
    fwrite(&dataOffset, 4, 1, fp);

    // Writing info header
    uint32_t infoHeaderSize= BMP_INFO_HEADER_SIZE;
    fwrite(&infoHeaderSize, 4, 1, fp);
    fwrite(&width, 4, 1, fp);
    fwrite(&height, 4 ,1, fp);
    uint16_t planes = 1;
    fwrite(&planes, 2, 1, fp);
    uint16_t bitsPerPixel =  bytesPerPixel * 8;
    fwrite(&bitsPerPixel, 2, 1, fp);
    uint32_t compression = BMP_NO_COMPRESSION;
    fwrite(&compression, 4, 1, fp);
    uint32_t imageSize = width * height * bytesPerPixel;
    fwrite(&imageSize, 4, 1, fp);
    uint32_t resolution = 11811;
    fwrite(&resolution, 4, 1, fp);
    fwrite(&resolution, 4, 1, fp);
    uint32_t colorsUsed = BMP_MAX_NUMBER_OF_COLORS;
    fwrite(&colorsUsed, 4, 1, fp);
    uint32_t importantColors = BMP_ALL_COLOR_REQUIRED;
    fwrite(&importantColors, 4, 1, fp);

    // Writing pixels
    int i = 0;
    int unpaddedRowSize = width * bytesPerPixel;
    for(i = 0; i < height; i++) {
        int pixelOffset = ((height - i) - 1) * unpaddedRowSize;
        fwrite(&data[pixelOffset], 1, paddedRowSize, fp);
    }

    fclose(fp);
    return 0;
}

以及调用此函数的代码:

if(grabResult.Status == Grabbed) {
    // Success
    getMinMax(imgBuf, grabResult.SizeX, grabResult.SizeY, &min, &max);
    printf("Acquisition de l'image #%2d. Valeur grise min = %3u, max = %3u\n",
        i + 1, min, max);
    char path[11];
    sprintf(path, "data/%d.bmp", i + 1);
    c = clock();
    saveImgToBmp(imgBuf, path, grabResult.SizeX, grabResult.SizeY, 1);
    c = clock() - c;
    double time_taken = ((double) c)/CLOCKS_PER_SEC;
    printf("Temps écoulé : %fs\n", time_taken);
} else if(grabResult.Status == Failed){
    fprintf(stderr, "L'image %d n'as pas pu être acquise avec succès. Code d'erreur : 0x%08X/\n", i + 1, grabResult.ErrorCode);
}

saveImgToPng 函数:

int saveImgToPng(unsigned char *data, const char * path, int width, int height){
    FILE *fp;
    int status;
    png_bytep row;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;

    fp = fopen(path, "wb");
    if(!fp) {
        goto fopen_failed;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(png_ptr == NULL) {
        goto png_create_write_struct_failed;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if(info_ptr == NULL) {
        goto png_create_info_struct_failed;
    }

    if (setjmp (png_jmpbuf (png_ptr))) {
        goto png_failure;
    }

    png_set_IHDR (png_ptr,
                  info_ptr,
                  width,
                  height,
                  8,
                  PNG_COLOR_TYPE_GRAY,
                  PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_DEFAULT,
                  PNG_FILTER_TYPE_DEFAULT);

    png_init_io(png_ptr, fp);

    png_write_info(png_ptr, info_ptr);

    row = (png_bytep) data;

    for(y = 0; y < height; y++) {
        png_write_row(png_ptr, row);
        row += width;
    }
    
    png_write_end(png_ptr, NULL);



    png_failure:
    png_create_info_struct_failed:
        png_destroy_write_struct (&png_ptr, &info_ptr);
    png_create_write_struct_failed:
        fclose (fp);
    fopen_failed:
        return status;

}

这是一个示例图片:

bmp图片

标签: cbmp

解决方案


推荐阅读