📄 bmp.c
字号:
/* *File: bmp.c *Author: Zhu Zhiqiang *Company: * */#include <mgdconfig.h>#ifdef ENABLE_BMP#include <stdio.h>#include <glib.h>#include <minigui/common.h>#include <minigui/gdi.h>#include "image.h"#include "web.h"#include "cache.h"#include "dicache.h"#define DEBUG_LEVEL 6#include "debug.h"typedef enum { DILLO_BMP_INIT, DILLO_BMP_STARTING, DILLO_BMP_READING, DILLO_BMP_DONE, DILLO_BMP_ERROR} DilloBmpState;typedef struct BITMAPFILEHEADER{ unsigned short bfType; unsigned long bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits;} BITMAPFILEHEADER;typedef struct BITMAPINFOHEADER{ unsigned long biSize; unsigned long biWidth; unsigned long biHeight; unsigned short biBitCount; unsigned long biCompression;} BITMAPINFOHEADER;typedef struct WINBMPINFOHEADER /* size: 40 */{ unsigned long biSize; unsigned long biWidth; unsigned long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; unsigned long biXPelsPerMeter; unsigned long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant;} WINBMPINFOHEADER;#define BI_RGB 0#define BI_RLE8 1#define BI_RLE4 2#define BI_BITFIELDS 3#define OS2INFOHEADERSIZE 12#define WININFOHEADERSIZE 40#define ReadGuchar(Buf) *((guchar *)Buf)#define ReadShortInt(Buf) *((guchar *)Buf)|*((guchar *)Buf+1)<<8#define ReadInt(Buf) *((guchar *)Buf)|*((guchar *)Buf+1)<<8|*((guchar *)Buf+2)<<16|*((guchar *)Buf+3)<<24#define PIX2BYTES(n) (((n)+7)/8)#define red 0#define green 2typedef struct _DilloBmp { DilloImage *Image; DilloUrl *url; gint version; BITMAPFILEHEADER fileheader; BITMAPINFOHEADER infoheader; guchar flag; gint pitch; gint effect_depth; gint size; gint line;//used by BI_RLE8 guint linerec;//how many line have received! guint lineout;//how many line have written to dicache! char *Data; gint bytessaved;//how many image data have be saved! gint bytesdelt;//how many image data have be delt! size_t Start_Ofs, Skip, NewStart; DilloBmpState state; guint rmask, gmask, bmask;} DilloBmp;/* * Forward declarations */static DilloBmp *Bmp_new(DilloImage *Image, DilloUrl *url, gint version);static void Bmp_callback(int Op, CacheClient_t *Client);static void Bmp_write(DilloBmp *bmp, void *Buf, guint BufSize);static void Bmp_close(DilloBmp *bmp, CacheClient_t *Client);static int read_bmfileheader(guchar *f, BITMAPFILEHEADER *fileheader);static int read_win_bminfoheader(guchar *f, BITMAPINFOHEADER *infoheader);static int bmpComputePitch (int bpp, Uint32 width, Uint32* pitch, BOOL does_round);static void image_4bit_save (DilloBmp *bmp,guchar *f, guint Bufsize);static void image_8bit_save (DilloBmp *bmp,guchar *f, guint Bufsize);static void image_16bit_save(DilloBmp *bmp,guchar *f, guint Bufsize);static void image_24bit_save(DilloBmp *bmp,guchar *f, guint Bufsize);/* exported function */DwWidget *a_Bmp_image(const char *Type, void *P, CA_Callback_t *Call, void **Data){ DilloWeb *web = P; DICacheEntry *DicEntry; if ( !web->Image ) web->Image = a_Image_new(0, 0, NULL, 0); /* Add an extra reference to the Image (for dicache usage) */ a_Image_ref(web->Image); DicEntry = a_Dicache_get_entry(web->url); if ( !DicEntry ) { /* Let's create an entry for this image... */ DicEntry = a_Dicache_add_entry(web->url); /* ... and let the decoder feed it! */ *Data = Bmp_new(web->Image, DicEntry->url, DicEntry->version); *Call = (CA_Callback_t) Bmp_callback; } else { /* Let's feed our client from the dicache */ a_Dicache_ref(DicEntry->url, DicEntry->version); *Data = web->Image; *Call = (CA_Callback_t) a_Dicache_callback; } return DW_WIDGET (web->Image->dw);}/* * Finish the decoding process */static void Bmp_close(DilloBmp *bmp, CacheClient_t *Client){ a_Dicache_close(bmp->url, bmp->version, Client); if(!bmp->Data) g_free(bmp->Data); g_free(bmp);}static DilloBmp *Bmp_new(DilloImage *Image, DilloUrl *url, gint version){ DilloBmp *bmp = g_malloc(sizeof(*bmp)); bmp->Image = Image; bmp->url = url; bmp->version = version; bmp->state = DILLO_BMP_INIT; bmp->Start_Ofs = 0; bmp->bytessaved=0; bmp->bytesdelt=0; bmp->linerec=0; bmp->lineout=0; return bmp;}static void Bmp_callback (int Op, CacheClient_t *Client){ DEBUG_MSG (5, "Bmp_callback is called\n"); if (Op) Bmp_close(Client->CbData, Client); else Bmp_write(Client->CbData, Client->Buf, Client->BufSize);}static void Bmp_write(DilloBmp *bmp, void *Buf, guint Bufsize){ DilloImgType type; gint i; unsigned long biSize; gint ncol; /*Save the received data to bmp->data*/ bmp-> rmask = 0x001f, bmp->gmask = 0x03e0, bmp->bmask = 0x7c00; if (bmp->state == DILLO_BMP_INIT) { if(Bufsize>54)/*Make sure the header of the bmp is got!*/ { if (read_bmfileheader (Buf, &bmp->fileheader) != 0) { bmp->state=DILLO_BMP_ERROR; return; } biSize =*((guchar *)Buf+14)|*((guchar *)Buf+15)<<8 ; ncol = (bmp->fileheader.bfOffBits - biSize - 14) / 4; if (biSize >= WININFOHEADERSIZE) { if (read_win_bminfoheader (Buf+14, &bmp->infoheader) != 0) { bmp->state=DILLO_BMP_ERROR; return; } } else if (biSize == OS2INFOHEADERSIZE) { bmp->state=DILLO_BMP_ERROR; return; } else { bmp->state=DILLO_BMP_ERROR; return; } bmp->effect_depth = bmp->infoheader.biBitCount; bmpComputePitch (bmp->effect_depth, bmp->infoheader.biWidth, (gint *)(&bmp->pitch), TRUE); // biSize =bmp->pitch*bmp->infoheader.biHeight; biSize =bmp->infoheader.biWidth*3*bmp->infoheader.biHeight; if( !(bmp->Data =g_malloc(biSize)) ) { bmp->state=DILLO_BMP_ERROR; return; } // bmp->Image->widget.RGBorBGR=0xaa; if (bmp->infoheader.biBitCount == 1) type = DILLO_IMG_TYPE_GRAY; else type = DILLO_IMG_TYPE_RGB; a_Dicache_set_parms(bmp->url, bmp->version, bmp->Image, (guint)bmp->infoheader.biWidth, (guint)bmp->infoheader.biHeight, type); bmp->state = DILLO_BMP_READING; } } if (bmp->state == DILLO_BMP_READING) { switch (bmp->infoheader.biCompression) { case BI_BITFIELDS: /* ignore the bit fileds */ bmp->rmask = ReadShortInt(Buf+14+bmp->infoheader.biSize); bmp->gmask = ReadShortInt(Buf+16+bmp->infoheader.biSize); bmp->bmask =ReadShortInt(Buf+18+bmp->infoheader.biSize); case BI_RGB: if (bmp->infoheader.biBitCount == 4) { printf("start to process 4 bits image\n"); image_4bit_save(bmp,Buf,Bufsize); } else if (bmp->infoheader.biBitCount == 8) { printf("start to process 8 bits image\n"); image_8bit_save(bmp,Buf,Bufsize); } else if (bmp->infoheader.biBitCount == 16) { printf("start to process 16 bits image\n"); image_16bit_save(bmp,Buf,Bufsize); } else if (bmp->infoheader.biBitCount == 24) { printf("start to process 24 bits image\n"); image_24bit_save(bmp,Buf,Bufsize); } else { bmp->state=DILLO_BMP_ERROR; return; } break; default: bmp->state=DILLO_BMP_ERROR; return; } for(i=bmp->lineout;i<bmp->linerec;i++) { a_Dicache_write (bmp->Image, bmp->url, bmp->version, bmp->Data+i*bmp->infoheader.biWidth*3, 0, bmp->infoheader.biHeight-1-i); bmp->lineout++; } if(bmp->lineout==bmp->infoheader.biHeight) { bmp->state = DILLO_BMP_DONE; } }}static int bmpComputePitch (int bpp, Uint32 width, Uint32* pitch, BOOL does_round){ Uint32 linesize; int bytespp = 1; if(bpp == 1) linesize = PIX2BYTES (width); else if(bpp <= 4) linesize = PIX2BYTES (width << 2); else if (bpp <= 8) linesize = width; else if(bpp <= 16) { linesize = width * 2; bytespp = 2; } else if(bpp <= 24) { linesize = width * 3; bytespp = 3; } else { linesize = width * 4; bytespp = 4; } /* rows are DWORD right aligned*/ if (does_round) *pitch = (linesize + 3) & -4; else *pitch = linesize; return bytespp;}static int read_win_bminfoheader(guchar *f, BITMAPINFOHEADER *infoheader){ WINBMPINFOHEADER win_infoheader; win_infoheader.biWidth = ReadInt(f); win_infoheader.biWidth = ReadInt(f+4); win_infoheader.biHeight = ReadInt(f+8); win_infoheader.biPlanes = ReadShortInt(f+12); win_infoheader.biBitCount =ReadShortInt(f+14) ; win_infoheader.biCompression =ReadInt(f+16) ; win_infoheader.biSizeImage = ReadInt(f+20); win_infoheader.biXPelsPerMeter = ReadInt(f+24); win_infoheader.biYPelsPerMeter = ReadInt(f+28); win_infoheader.biClrUsed = ReadInt(f+32); win_infoheader.biClrImportant =ReadInt(f+36) ; infoheader->biWidth = win_infoheader.biWidth; infoheader->biHeight = win_infoheader.biHeight; infoheader->biBitCount = win_infoheader.biBitCount; infoheader->biCompression = win_infoheader.biCompression; return 0;}static int read_bmfileheader(guchar *f, BITMAPFILEHEADER *fileheader){ fileheader->bfType =ReadShortInt(f) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -