Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

c - Write BMP image

I'm currently learning C and I started to write a BMP image reader and writer, to make some operations with basic images.

I'm reading the BMP image and saving it into a struct, then just write a copy to ensure that the flow is working, but, when I write the image I get the following result

BMP write result

Where the left one is the original and the right one the copy, I don't know if I'm not saving enough memory or if I'm not writing in the right way the data.

I have the header file and the implementation, where I wrote two functions readImage and writeImage, both receive the filename and the Image struct described in the header file.

#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);
}

In the main file, I declare the image data structure and pass it to both functions

#include "bmp.c"

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

?Someone could help to identify what I'm doing wrong? I already try to allocate more memory or calculate the size of the data structure that saves the pixels with the header that saves the image size, but it didn't work.

question from:https://stackoverflow.com/questions/65840161/write-bmp-image

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
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);

Maybe your original bmp file has each pixel size more than 8 bit? Image seems to only have one third part of original image so original image might have 24bit format.

How about trying 3 * sizeof(char)?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...