【问题标题】:Write BMP image写入 BMP 图像
【发布时间】:2021-04-26 15:00:29
【问题描述】:

我现在正在学习C,我开始写一个BMP图像读取器和写入器,对基本图像进行一些操作。

我正在读取 BMP 图像并将其保存到结构中,然后只需编写一个副本以确保流程正常工作,但是,当我编写图像时,我得到以下结果

左侧是原件,右侧是副本,我不知道是我没有节省足够的内存还是我没有以正确的方式写入数据。

我有头文件和实现,我写了两个函数readImagewriteImage,都接收头文件中描述的文件名和Image结构。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdbool.h>

typedef uint16_t ImageType;

typedef struct
{
    uint32_t size;
    uint16_t additionalFeature;
    uint16_t copy;
    uint32_t offset;

} ImageHeader;

typedef struct
{
    uint32_t headerSize;
    int width;
    int height;
    uint16_t colorSpaces;
    uint16_t bitsPerPixel;
    uint32_t compression;
    uint32_t size;
    int verticalResolution;
    int horizontalResolution;
    uint32_t totalColors;
    uint32_t importantColors;
} ImageMetadata;

typedef struct {
    int red; 
    int green; 
    int blue;
    int reserved;
} ImageColors;

typedef unsigned char *ImagePixels;

typedef struct {
    ImageType type;
    ImageHeader header;
    ImageMetadata metadata;
    ImagePixels pixels;
} Image;

ImageType BMP_IMAGE_TYPE = 0x4D42;

void readImage(char *filename, Image *image);
void writeImage(char *filename, Image *image);
void fragmentImage(Image *image);
#include "bmp.h"

void readImage(char *filename, Image *image)
{
    FILE *imageFile = fopen(filename, "r");
    if (!imageFile)
    {
        perror("ReadImageFileException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    fread(&(image->type), sizeof(ImageType), 1, imageFile);
    if (image->type != BMP_IMAGE_TYPE)
    {
        fprintf(stderr, "%hu", image->type);
        perror("ReadImageTypeException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    fread(&(image->header), sizeof(ImageHeader), 1, imageFile);
    fread(&(image->metadata), sizeof(ImageMetadata), 1, imageFile);

    image->pixels = (unsigned char *)malloc(image->metadata.width * image->metadata.height);
    if (!image->pixels)
    {
        perror("ReadImagePixelsException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    fseek(imageFile, image->header.offset, SEEK_SET);
    fread(image->pixels, sizeof(char) * image->metadata.width * image->metadata.height, 1, imageFile);

    fclose(imageFile);
}

void writeImage(char *filename, Image *image)
{
    FILE *imageFile = fopen(filename, "w+");
    if (!imageFile)
    {
        perror("WriteImageFileException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    int typeWritten = fwrite(&(image->type), sizeof(image->type), 1, imageFile);
    if (typeWritten == 0)
    {
        perror("WriteImageTypeException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    int headerWritten = fwrite(&(image->header), sizeof(image->header), 1, imageFile);
    if (headerWritten == 0)
    {
        perror("WriteImageHeaderException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    int metadataWritten = fwrite(&(image->metadata), sizeof(image->metadata), 1, imageFile);
    if (metadataWritten == 0)
    {
        perror("WriteImageMetadataException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    fseek(imageFile, image->header.offset, SEEK_SET);
    int pixelsWritten = fwrite(image->pixels, sizeof(char) * image->metadata.width * image->metadata.height, 1, imageFile);
    if (pixelsWritten == 0)
    {
        perror("WriteImagePixelsException");
        fclose(imageFile);
        exit(EXIT_FAILURE);
    }

    fclose(imageFile);
}

在主文件中,我声明了图像数据结构并将其传递给两个函数

#include "bmp.c"

int main() {
    Image image;
    readImage("image.bmp", &image);
    writeImage("image-copy.bmp", &image);
    return 0;
} 

¿有人可以帮助确定我做错了什么?我已经尝试分配更多内存或计算保存像素的数据结构的大小以及保存图像大小的标题,但它没有工作。

【问题讨论】:

  • 每个像素有 3 个值吗?
  • 不,所有的图像数据/像素都保存在一个字符指针中。
  • 您似乎只写了图片的 1/3?可能是一些尺寸问题,你需要乘以 3? (AKA 它是彩色图像而不是灰度图像)
  • @Mikhail - 不错。 288 像素高,目前有 96 个。这里可能值得一提的是,图像(虽然这个没有)也可能在每条扫描线的末尾填充。当一个人第一次遇到它时,这有点粗鲁。
  • @enhzflep:“当你第一次遇到它时,这有点粗鲁的惊喜”:我完全支持你!

标签: c image image-processing


【解决方案1】:

24 bpp 格式的图像每个像素占用三个字节。如有必要,行会用虚拟字节填充到下一个大小,即四的倍数。

【讨论】:

    【解决方案2】:
    fread(image->pixels, sizeof(char) * image->metadata.width * image->metadata.height, 1, imageFile);
    
    fwrite(image->pixels, sizeof(char) * image->metadata.width * image->metadata.height, 1, imageFile);
    

    也许您的原始 bmp 文件的每个像素大小超过 8 位?图像似乎只有原始图像的三分之一,因此原始图像可能具有 24 位格式。

    试试3 * sizeof(char)怎么样?

    【讨论】:

    • 尝试在 ImageMetadata 中打印 bitsPerPixel。这可能证明了这一点。
    • 是的,现在我乘以所需的字节数,基于 BPP,但其他图像仍然很奇怪。黑白图像和灰度图像,唯一可以正常工作的是彩色图像。我应该打开其他问题吗?
    • @DanielAlessandroAguilar 它的行为有多奇怪?如果问题与每像素位数有关,您可以查看image-&gt;metadata-&gt;bitsPerPixel。如果 bmp 文件是 24bit 格式,则值为 24,如果是 8,则值为 8,依此类推。然后您可以相应地调整 fwrite 函数的 size 参数。如果问题不同,请说明。
    猜你喜欢
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2022-08-21
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多