从文件中读取模式并在C中创建一个bmp图像

时间:2016-05-25 05:20:24

标签: c image-processing bitmap

我想阅读使用C语言的文本文件。这是文件: -

enter image description here

您会看到文件中的文字内容中有一些模式。 0表示没有。 9表示黑色。所以有从0到9的着色方案。

我必须创建一个这样的位图图像,颜色根据图案中的值。您必须使用0-256颜色方案进行调整。 最终输出如下所示

enter image description here

现在看到文本文件内容中的模式与最终输出位图文件相反(不是必需的)。位图图像中颜色的暗度是根据文本内容的图案中的值。

  

任何人都会告诉我如何用C语言实现这一目标。

我能够创建一个BMP文件,但不能根据文本文件中的模式。

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

int main()
{

char bitmap[1900];

    // -- FILE HEADER -- //

    // bitmap signature
    bitmap[0] = 0x42;
    bitmap[1] = 0x4d;

    // file size
    bitmap[2] = 58; // 40 + 14 + 12
    bitmap[3] = 0;
    bitmap[4] = 0;
    bitmap[5] = 0;
    int i=0;
    // reserved field (in hex. 00 00 00 00)
    for(i = 6; i < 10; i++) bitmap[i] = 0;

    // offset of pixel data inside the image
    for(i = 10; i < 14; i++) bitmap[i] = 0;

    // -- BITMAP HEADER -- //

    // header size
    bitmap[14] = 40;
    for(i = 15; i < 18; i++) bitmap[i] = 0;

    // width of the image
    bitmap[18] = 4;
    for(i = 19; i < 22; i++) bitmap[i] = 0;

    // height of the image
    bitmap[22] = 1;
    for(i = 23; i < 26; i++) bitmap[i] = 0;

    // reserved field
    bitmap[26] = 1;
    bitmap[27] = 0;

    // number of bits per pixel
    bitmap[28] = 24; // 3 byte
    bitmap[29] = 0;

    // compression method (no compression here)
    for(i = 30; i < 34; i++) bitmap[i] = 0;

    // size of pixel data
    bitmap[34] = 12; // 12 bits => 4 pixels
    bitmap[35] = 0;
    bitmap[36] = 0;
    bitmap[37] = 0;

    // horizontal resolution of the image - pixels per meter (2835)
    bitmap[38] = 0;
    bitmap[39] = 0;
    bitmap[40] = 0b00110000;
    bitmap[41] = 0b10110001;

    // vertical resolution of the image - pixels per meter (2835)
    bitmap[42] = 0;
    bitmap[43] = 0;
    bitmap[44] = 0b00110000;
    bitmap[45] = 0b10110001;

    // color pallette information
    for(i = 46; i < 50; i++) bitmap[i] = 0;

    // number of important colors
    for(i = 50; i < 54; i++) bitmap[i] = 0;

    // -- PIXEL DATA -- //
    for(i = 54; i < 66; i++) bitmap[i] = 255;


    FILE *file;
    file = fopen("bitmap.bmp", "w+");
    for(i = 0; i < 66; i++)
    {
        fputc(bitmap[i], file);
    }
    fclose(file);
    return 0;
}

2 个答案:

答案 0 :(得分:4)

这是一个有效的代码。我没有检查一些错误的情况(输入文件格式错误,例如)。我写了一些评论,虽然代码本身并不难理解。

#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <ctype.h>

#define BMP_ASSERT(condition, message) \
    do { \
        if (! (condition)) { \
            fprintf(stderr, __FILE__ ":%d: %s: Assertion `" #condition \
                "` failed.\n\t: %s\n", __LINE__, __func__, message); \
            exit(EXIT_FAILURE); \
        } \
    } while (false)

#define BMP_COLORMAP_SIZE   10

////////////////////////////////////////////////////////////////////////////////
// STRUCTS

typedef struct __attribute__((__packed__))
bmp_color 
{
    uint8_t             r,
                        g,
                        b;
    uint8_t             :8;
}                       bmp_color_t;

typedef struct __attribute__((__packed__))
bmp_header_infos
{
    uint32_t const      info_size;
    uint32_t            width;
    uint32_t            height;
    uint16_t const      planes;
    uint16_t const      bpp;
    uint32_t const      compression;
    uint32_t            img_size;
    uint32_t const      horz_resolution;
    uint32_t const      vert_resolution;
    uint32_t const      n_colors;
    uint32_t const      n_important_colors;
}                       bmp_header_infos_t;

typedef struct __attribute__((__packed__))
bmp_header
{
    /* Header */
    char const          signature[2];
    uint32_t            file_size;
    uint32_t const      :32; // reserved
    uint32_t const      img_offset;
    /* Infos */
    bmp_header_infos_t  infos;
    /* Color map */
    bmp_color_t         colormap[BMP_COLORMAP_SIZE];
}                       bmp_header_t;

typedef struct          bmp_file_datas
{
    size_t              width;
    size_t              height;
    /* Bit map */
    uint8_t             *bitmap;
}                       bmp_file_datas_t;


////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS

/* Give a header with the right magic values */
bmp_header_t *
bmp_get_header(void)
{
    static bmp_header_t _header = {
        {'B', 'M'},
        0u,
        sizeof(_header),
        {   // struct info
            sizeof(_header.infos),
            0u, 0u, // width, height
            1u,     // planes
            8u,     // bpp
            0u,     // no compression
            0u,     // img size
            0u, 0u, // resolution
            BMP_COLORMAP_SIZE,
            BMP_COLORMAP_SIZE,      // important colors
        },
        {{0u}}
    };
    bmp_header_t        *header = malloc(sizeof(_header));
    size_t              i,
                        color;

    assert(header != NULL);
    memcpy(header, &_header, sizeof(*header));
    // setting the scale of greys
    for (i = 0 ; i < BMP_COLORMAP_SIZE ; ++i)
    {
        color = (i * 255) / BMP_COLORMAP_SIZE;
        header->colormap[i] = (bmp_color_t){color, color, color};
    }
    return header;
}

/* Take all the file content and store it in a buffer */
char *
get_file_content(char const *filename)
{
    FILE        *file_handler = fopen(filename, "r");
    size_t      file_len;
    char        *buff;

    BMP_ASSERT(file_handler != NULL, strerror(errno));
    fseek(file_handler, 0, SEEK_END);
    file_len = ftell(file_handler);
    fseek(file_handler, 0, SEEK_SET);
    buff = malloc(file_len + 1);
    assert(buff != NULL);
    fread(buff, file_len, 1, file_handler);
    buff[file_len] = '\0';
    fclose(file_handler);
    return buff;
}

/* Get the greatest multiple of 4 that is >= size */
static inline size_t
multiple_of_four(size_t size)
{
    while (size % 4)
        ++size;
    return size;
}

/* Get the informations from buffer: size of line, number of lines */
void
get_file_infos(char *buff, bmp_header_t *header, bmp_file_datas_t *datas)
{
    /* width & height */
    header->infos.width =  strchr(buff, '\n') - buff;
    header->infos.height = strlen(buff) / (header->infos.width + 1);
                                            // + 1 for the terminating '\n'
    datas->width = multiple_of_four(header->infos.width);
    datas->height = header->infos.height;
printf("File size: %u, %u\n", header->infos.width, header->infos.height);
    /* image size & bitmap allocation */
    header->infos.img_size = datas->width * datas->height;
    datas->bitmap = malloc(header->infos.img_size * sizeof(*datas->bitmap));
    assert(datas->bitmap != NULL);
    header->file_size = header->img_offset + header->infos.img_size;
}

/* Take the informations from the buffer and store them in the bitmap */
void
write_bitmap(char *buff, bmp_file_datas_t *datas)
{
    size_t          ibuff,
                    iline = 0,
                    ibitmap = 0;

    for (ibuff = 0 ; buff[ibuff] ; ++ibuff)
    {
        if (isdigit(buff[ibuff]))
        {
            datas->bitmap[ibitmap] = BMP_COLORMAP_SIZE - 1 - (buff[ibuff] - '0');
            ++ibitmap;
        }
        else if (buff[ibuff] == '\n')
        {
            ++iline;
            ibitmap = iline * datas->width;
        }
    }
}

/* Write the datas in the file: the header and the bitmap */
void
write_in_file(bmp_header_t *header,
              bmp_file_datas_t *datas,
              char const *filename)
{
    FILE        *file_handler = fopen(filename, "w");

    BMP_ASSERT(file_handler != NULL, strerror(errno));
    fwrite(header, sizeof(*header), 1, file_handler);
    fwrite(datas->bitmap, header->infos.img_size, 1, file_handler);
    fclose(file_handler);
}


int main(int argc, char **argv)
{
    char                *buff;
    bmp_header_t        *header;
    bmp_file_datas_t    datas;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <input filename> <output filename>\n",
                                argv[0]);
        return EXIT_FAILURE;
    }
    buff = get_file_content(argv[1]);
    header = bmp_get_header();
    get_file_infos(buff, header, &datas);
    write_bitmap(buff, &datas);
    write_in_file(header, &datas, argv[2]);
    free(buff), free(header), free(datas.bitmap);
    return EXIT_SUCCESS;
}

答案 1 :(得分:2)

实现所需功能的原始方法是:(不是真的C,但那是你的作业而不是我的)

WIDTH = 0, HEIGHT = 0
if(LINE=READ_LINE(fin))
  WIDTH = strlen(LINE)
  ++HEIGHT
else
  ERROR!!!
PUSH(LINE)
while(LINE=READ_LINE(fin))
  if(WIDTH != strlen(LINE))
    ERROR!!!
  else
    ++HEIGHT
    PUSH(LINE)
WRITE_BMP_HEADER(WIDTH, HEIGHT)
for(h = 0; h < HEIGHT; ++h)
  LINE = POP()
  for(w = 0; w < WIDTH; ++w)
    COLOR = (LINE[w] - '0') * 255 / 9;
    WRITE_BMP_COLOR(COLOR)
  WRITE_BMP_PADDING(W)