Bài viết mới

Wednesday, March 23, 2016

Funny code 2 - Bmp picture

Đọc và xử lý file hình ảnh BMP

Tập tin Bitmap Tập tin Bitmap (hay còn gọi là BMP) là một định dạng tập tin dùng để lưu trữ dữ liệu hình ảnh rất phổ biến trên môi trường Windows. Xuất hiện lần đầu tiên trong phiên bản Windows 1.0, định dạng BMP vẫn tồn tại và phát triển cho đến ngày nay. 
Sỡ dĩ có thời gian tồn tại lâu như vậy là do tập tin BMP có cấu trúc rất đơn giản, dữ liệu màu của từng điểm ảnh được lưu trực tiếp, không áp dụng giải thuật nén và bảo toàn được chất lượng ảnh sau khi lưu trữ.

Cấu trúc tập tin Bitmap


Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <stdlib.h>
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdint.h>
const char source[]="E:\\testi.bmp";
const char path[]="E:\\testo.bmp";
#pragma pack(1)

////////////////////////////////////////////////

typedef struct bmp_color
{
    unsigned char R;
    unsigned char G;
    unsigned char B;
} color;
typedef struct bmp_header
{
    char isbmp[2];
    uint32_t sizeof_bmp;
    uint16_t other_1;
    uint16_t other_2;
    uint32_t place_data;
} header;
typedef struct bmp_dib
{
    uint32_t sizeof_dib;
    uint32_t picture_width;
    uint32_t picture_height;
    uint16_t color_layers;
    uint16_t color_deep;
    uint32_t impress_method;
    uint32_t picture_size;
    uint32_t resolution_row;
    uint32_t resolution_column;
    uint32_t colors_used;
    uint32_t main_colors;
    char *thirt_part;
} dib;
typedef struct bmp_data
{
    color **c;
    char padding;
} data;
typedef struct bmp_file
{
    header h;
    dib d;
    data a;
} file;

////////////////////////////////////////////////

file bmp;
color before, after;
FILE *fi=fopen(source,"rb");
FILE *fo=fopen(path,"wb");

////////////////////////////////////////////////

void scan_bmp_file()
{
    if (fi==NULL) return;
    fread(&bmp.h,sizeof(header),1,fi);
    fread(&bmp.d,sizeof(dib),1,fi);
    bmp.a.padding=(4-(bmp.d.picture_size/8)%4)%4;
    bmp.d.thirt_part=new char[bmp.h.place_data-sizeof(header)-sizeof(dib)];
    fread(bmp.d.thirt_part,bmp.h.place_data-sizeof(header)-sizeof(dib),1,fi);
    bmp.a.c = new color*[bmp.d.picture_height];
    for (int i=0; i<bmp.d.picture_height;i++)
    {
        bmp.a.c[i]=new color[bmp.d.picture_width];
        for (int j=0;j<bmp.d.picture_width;j++)
            fread(bmp.a.c[i]+j,sizeof(color),1,fi);
    }
}
void change_bmp_color()
{
    printf("Input color need to chang (RGB): ");
    scanf("%d%d%d",&before.R,&before.G,&before.B);
    printf("Input color to replace (RGB): ");
    scanf("%d%d%d",&after.R,&after.G,&after.B);
    for (int i=0;i<bmp.d.picture_height;i++)
        for (int j=0;j<bmp.d.picture_width;j++)
            if (bmp.a.c[i][j].R==before.R && bmp.a.c[i][j].G==before.G && bmp.a.c[i][j].B==before.B)
            {
                bmp.a.c[i][j].R=after.R;
                bmp.a.c[i][j].G=after.G;
                bmp.a.c[i][j].B=after.B;
            }
}
void print_bmp_console()
{
    HWND console=GetConsoleWindow();
    HDC  hdc=GetDC(console);
    for (int i=bmp.d.picture_height-1;i>=0;i--)
        for (int j=0;j<bmp.d.picture_width;j++)
            SetPixel(hdc,j,bmp.d.picture_height-i-1,RGB(bmp.a.c[i][j].R,bmp.a.c[i][j].G,bmp.a.c[i][j].B));
    ReleaseDC(console, hdc);
}
void print_bmp_file()
{
    if (fo==NULL) return;
    fwrite(&bmp.h,sizeof(header),1,fo);
    fwrite(&bmp.d,sizeof(dib),1,fo);
    fwrite(bmp.d.thirt_part,bmp.h.place_data-sizeof(header)-sizeof(dib),1,fo);
    for (int i=0;i<bmp.d.picture_height;i++)
    {
        for (int j=0;j<bmp.d.picture_width;j++)
            fwrite(bmp.a.c[i]+j,sizeof(color),1,fo);
        for (int j=0;j<bmp.a.padding;j++) fprintf(fo,"0");
    }
}

////////////////////////////////////////////////

int main()
{
    if (fi==NULL || fo==NULL)
    {
        printf("Input error");
        return 0;
    }
    scan_bmp_file();
    change_bmp_color();
    print_bmp_console();
    print_bmp_file();
    fclose(fi);
    fclose(fo);
    return 0;
}


Hình ảnh test:









Vẫn còn update...

No comments:

Post a Comment