2016-05-25 50 views
5

voglio leggere un file di testo utilizzando del C Language.Here il file: -Lettura modello da file e creare un'immagine bmp di quella in C

enter image description here

È lì che vedi è qualche modello nel testo contenuto sul file. 0 significa niente. 9 significa nero. quindi c'è lo schema di colorazione da 0 a 9.

Devo creare un'immagine bitmap di questo e il colore è secondo i valori nel modello. Devi regolarlo con lo schema di colori 0-256. E il risultato finale di questo è mostrato sotto

enter image description here

Ora vedere il modello del contenuto del file di testo si trova di fronte al file di output bitmap finale (non necessario). L'oscurità dei colori nell'immagine bitmap è in base ai valori nel modello del contenuto del testo.

Chiunque mi dirà come ottengo questo in linguaggio C.

Sono in grado di creare un file BMP ma non in base al modello nel file di testo.

#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; 
} 
+6

Tanti magici ... Per il bene della vostra proprio sanità mentale, usa costanti con nome! – Lundin

+2

Utilizzare * 'unsigned' *' char bitmap [1900] '. –

+2

Perché hai creato una bitmap 4x1 quando ne hai bisogno 24x15? Avrai bisogno di scrivere 3 byte (ciascuno uguale per una scala di grigi) di dati di pixel in ogni posizione nell'array, che (efficacemente) è 'array [height] [width] [3]'. –

risposta

4

Questo è un codice funzionante. Non controllo alcun caso di errore (file di input formattato male, ad esempio). Ho inserito alcuni commenti, sebbene il codice stesso non sia difficile da capire.

#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; 
} 
+0

Non penso che il codice funzioni. Perché prima ci sono errori di trasmissione da void a uint32 o altro. 2 dopo aver rimosso questi errori il file non viene generato. Puoi controllarlo. ? –

+1

Funziona perfettamente con 'gcc -std = c11 -Wall -Wextra -pedantic' sul mio Debian (con' gcc-5' e 'gcc-6'). Quindi dovrebbe andare bene con altri compilatori standard. Si prega di essere più specifici sugli errori. – Boiethios

+1

Ti interessa ancora? Non hai risposto alla mia domanda: che tipo di errore hai riscontrato? Non posso aiutare senza dettagli. – Boiethios

2

Metodo greggio per ottenere la funzionalità richiesta sarebbe: (Non proprio C, ma poi è il tuo non compiti a casa mia) numeri

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)