2009年10月26日 星期一

簡易 BMP 讀檔


簡易 BMP 讀檔,只能讀舊式 BMP 版本的未壓縮格式。
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define RGB(r,g,b)  (((r)<<16)|((g)<<8)|(b))
typedef unsigned char uchar;
typedef unsigned short U2B;

struct Image {int w,h, *data;};
void release (Image* g) {free (g->data); g->data = 0;}

int open_bmp (Image* out, char* path)           
{
    static int c[256]; U2B *s;
    int   nc, w,h, W, n,i,j,t, b, *p;
    uchar *g, *bm = 0, hd[54], a;

    FILE* f = fopen (path, "rb");
    fread (hd,1,54,f);                              //讀入 header
    if (hd[30]) return 0;                           //只處理未壓縮格式

    b  = *(short*)(hd+28);                          //bits of a pixel
    i  = *(int*)  (hd+22);
    nc = *(int*)  (hd+46);                          //nc = 色盤的顏色數

    out->w = w = *(int*)(hd+18);  
    out->h = h = (i<0?-i:i);   
    out->data = p = (int*) malloc (w*h*sizeof(int));

    fread (c,1,(nc?nc:256)*4, f);

    i = int(float(b)/8*w); if(i<1) i=1;
    W = (i+3)&~3;                                   //8,16,24,32 的真實   
    g = bm = (uchar*) malloc (W*h);                 //列寬為 4 的倍數
    fseek (f,*(int*)(hd+10),0);
    fread (bm,1,W*h,f); 

    if (b<16) 
        for (n=8/b, t=n-1, a=(1<<b)-1, i=0; i<h; ++i, g+=W) 
            for (j=0; j<w; ++j)
                *p++ = c [ a & (g[j/n]>>(t-(j&t))*b) ];
    #define F(x) ((s[j]>>x)&63)<<3
    if (b==16) 
        for (i=0; i<h; ++i, g+=W)
            for (s=(U2B*)g, j=0; j<w; ++j)
                *p++ = RGB (F(10),F(5),F(0));
    #undef F
    if (b>=24)
        for (t=b/8, w*=t, i=0; i<h; ++i, g+=W)
            for (j=0; j<w; j+=t)
                *p++ = RGB (g[j+2],g[j+1],g[j]);
    free (bm);
    return 0 == fclose (f);     
}
秀圖測試:
#undef RGB
#include <windows.h>
extern"C"WINBASEAPI HWND WINAPI GetConsoleWindow();

void show (Image* g)
{
    BITMAPINFO info = {{40, g->w,g->h, 1,32,0,0,0,0,0,0},{{0}}};
    SetDIBitsToDevice (GetDC(GetConsoleWindow()), 0,0, g->w,g->h, 
        0,0,0, g->h, g->data, &info, DIB_RGB_COLORS);
}
int main()
{
    Image img;
    open_bmp (&img, "D:/test16.bmp");
    while(1) {show (&img); Sleep(2);}
}

沒有留言:

張貼留言