基本概念
BPP:bits per pixel,每个像素的比特数。
场景
- 打印机打印二维码/图片:热敏打印机只可打印点阵图;
- 对图片质量要求低,降低内存消耗。
C语言实现
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* BMP file signature */
#define BMP_SIGNATURE 0x4D42
#define BMP_SIG_BYTES 2
/* BITMAPFILEHEADER */
#define BFH_WTYPE 0 /* WORD bfType; */
#define BFH_DSIZE 2 /* DWORD bfSize; */
#define BFH_WRESERVED1 6 /* WORD bfReserved1; */
#define BFH_WRESERVED2 8 /* WORD bfReserved2; */
#define BFH_DOFFBITS 10 /* DWORD bfOffBits; */
#define BFH_DBIHSIZE 14 /* DWORD biSize; */
#define FILEHED_SIZE 14 /* sizeof(BITMAPFILEHEADER) */
#define BIHSIZE_SIZE 4 /* sizeof(biSize) */
/* BITMAPINFOHEADER, BITMAPV4HEADER, BITMAPV5HEADER */
#define BIH_DSIZE 0 /* DWORD biSize; */
#define BIH_LWIDTH 4 /* LONG biWidth; */
#define BIH_LHEIGHT 8 /* LONG biHeight; */
#define BIH_WPLANES 12 /* WORD biPlanes; */
#define BIH_WBITCOUNT 14 /* WORD biBitCount; */
#define BIH_DCOMPRESSION 16 /* DWORD biCompression; */
#define BIH_DSIZEIMAGE 20 /* DWORD biSizeImage; */
#define BIH_LXPELSPERMETER 24 /* LONG biXPelsPerMeter; */
#define BIH_LYPELSPERMETER 28 /* LONG biYPelsPerMeter; */
#define BIH_DCLRUSED 32 /* DWORD biClrUsed; */
#define BIH_DCLRIMPORANT 36 /* DWORD biClrImportant; */
#define B4H_DREDMASK 40 /* DWORD bV4RedMask; */
#define B4H_DGREENMASK 44 /* DWORD bV4GreenMask; */
#define B4H_DBLUEMASK 48 /* DWORD bV4BlueMask; */
#define B4H_DALPHAMASK 52 /* DWORD bV4AlphaMask; */
#define B4H_DCSTYPE 56 /* DWORD bV4CSType; */
#define B4H_XENDPOINTS 60 /* CIEXYZTRIPLE bV4Endpoints; */
#define B4H_DGAMMARED 96 /* DWORD bV4GammaRed; */
#define B4H_DGAMMAGREEN 100 /* DWORD bV4GammaGreen; */
#define B4H_DGAMMABLUE 104 /* DWORD bV4GammaBlue; */
#define B5H_DINTENT 108 /* DWORD bV5Intent; */
#define B5H_DPROFILEDATA 112 /* DWORD bV5ProfileData; */
#define B5H_DPROFILESIZE 116 /* DWORD bV5ProfileSize; */
#define B5H_DRESERVED 120 /* DWORD bV5Reserved; */
#define INFOHED_SIZE 40 /* sizeof(BITMAPINFOHEADER) */
#define BMPV4HED_SIZE 108 /* sizeof(BITMAPV4HEADER) */
#define BMPV5HED_SIZE 124 /* sizeof(BITMAPV5HEADER) */
/* BITMAPCOREHEADER */
#define BCH_DSIZE 0 /* DWORD bcSize; */
#define BCH_WWIDTH 4 /* WORD bcWidth; */
#define BCH_WHEIGHT 6 /* WORD bcHeight; */
#define BCH_WPLANES 8 /* WORD bcPlanes; */
#define BCH_WBITCOUNT 10 /* WORD bcBitCount; */
#define COREHED_SIZE 12 /* sizeof(BITMAPCOREHEADER) */
/* RGBQUAD */
#define RGBQ_BLUE 0 /* BYTE rgbBlue; */
#define RGBQ_GREEN 1 /* BYTE rgbGreen; */
#define RGBQ_RED 2 /* BYTE rgbRed; */
#define RGBQ_RESERVED 3 /* BYTE rgbReserved; */
#define RGBQUAD_SIZE 4 /* sizeof(RGBQUAD) */
/* RGBTRIPLE */
#define RGBT_BLUE 0 /* BYTE rgbtBlue; */
#define RGBT_GREEN 1 /* BYTE rgbtGreen; */
#define RGBT_RED 2 /* BYTE rgbtRed; */
#define RGBTRIPLE_SIZE 3 /* sizeof(RGBTRIPLE) */
//#define BYTES_BITS 8
#define MAX_BMP_WIDTH 384
#define MAX_BMP_HEIGHT 1024
typedef struct __BITMAP_HEAD
{
unsigned char file_tar[2];
unsigned int file_size;
unsigned int reserve1;
unsigned int data_offset;
}BITMAP_HEAD;
typedef BITMAP_HEAD* PBITMAP_HEAD;
typedef struct __BITMAP_INFO
{
unsigned int info_bytes;
unsigned int width;
unsigned int height;
unsigned short plane;
unsigned short p_bits;
unsigned int compress_type;
unsigned int bmp_data_bytes;
unsigned int h_dpm;
unsigned int v_dpm;
unsigned int clr_used;
unsigned int clr_important;
}BITMAP_INFO;
typedef BITMAP_INFO* PBITMAP_INFO;
typedef struct __BITMAP_PANEL
{
unsigned char panel[8];
}BITMAP_PANEL;
typedef BITMAP_PANEL* PBITMAP_PANEL;
static unsigned int IntG(unsigned char *pp)
{
unsigned int ret = 0;
ret = pp[0];
ret += pp[1] * 256;
ret += pp[2] * 65536;
ret += pp[3] * 16777216;
return ret;
}
static unsigned short ShortG(unsigned char *pp)
{
unsigned short ret = 0;
ret = pp[0];
ret += pp[1] * 256;
return ret;
}
static void IntS(unsigned char *pp, unsigned int set)
{
pp[0] = set & 0xFF;
pp[1] = ((set>>8) & 0xFF);
pp[2] = ((set>>16) & 0xFF);
pp[3] = ((set>>24) & 0xFF);
}
static void ShortS(unsigned char *pp, unsigned short set)
{
pp[0] = set & 0xFF;
pp[1] = ((set>>8) & 0xFF);
}
static const unsigned char fix_panel[8] = {0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00};
static void mputdwl(void *ptr, unsigned long val)
{
unsigned char *p = (unsigned char *)ptr;
p[0] = (unsigned char)(val & 0xFF);
p[1] = (unsigned char)(val >> 8 & 0xFF);
p[2] = (unsigned char)(val >> 16 & 0xFF);
p[3] = (unsigned char)(val >> 24 & 0xFF);
}
static void mputwl(void *ptr, unsigned int val)
{
unsigned char *p = (unsigned char *)ptr;
p[0] = (unsigned char)(val & 0xFF);
p[1] = (unsigned char)(val >> 8 & 0xFF);
}
int bmp24bppto1bpp(unsigned char *psrc, unsigned char *pdest)
{
int i, j, k;
int SrcWidth, SrcHeight;
unsigned char *ppbitmap;
unsigned char *pdesrudedata;
BITMAP_HEAD msrcbitmap_head;
BITMAP_INFO msrcbitmap_info;
unsigned char desHead[14];
unsigned char desInfo[40];
BITMAP_PANEL mbitmap_panel;
int pitch;
int pitchcount;
int desCount = 0;
ppbitmap = psrc;
msrcbitmap_head.file_tar[0] = *(ppbitmap++);
msrcbitmap_head.file_tar[1] = *(ppbitmap++);
msrcbitmap_head.file_size = IntG(ppbitmap);
ppbitmap += 4;
ppbitmap += 4;
msrcbitmap_head.data_offset = IntG(ppbitmap);
ppbitmap += 4;
if((msrcbitmap_head.file_tar[0] != 'B') && (msrcbitmap_head.file_tar[1] != 'M'))
{
return -1;
}
msrcbitmap_info.info_bytes = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.width = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.height = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.plane = ShortG(ppbitmap);ppbitmap += 2;
msrcbitmap_info.p_bits = ShortG(ppbitmap);ppbitmap += 2;
msrcbitmap_info.compress_type = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.bmp_data_bytes = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.h_dpm = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.v_dpm = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.clr_used = IntG(ppbitmap);ppbitmap += 4;
msrcbitmap_info.clr_important = IntG(ppbitmap);ppbitmap += 4;
if((msrcbitmap_info.width > MAX_BMP_WIDTH)||(msrcbitmap_info.height > MAX_BMP_HEIGHT))
{
return -2;
}
if(msrcbitmap_info.p_bits == 1)
{
memcpy(pdest, psrc, msrcbitmap_head.file_size);
return msrcbitmap_head.file_size;
}
else if(msrcbitmap_info.p_bits != 24)
{
return -3;
}
pdesrudedata = pdest + 62;
SrcWidth = msrcbitmap_info.width;
SrcHeight = msrcbitmap_info.height;
pitch = SrcWidth%4;
for(i=0; i<(int)msrcbitmap_info.height; i++)
{
int y;
unsigned char writein = 0;
pitchcount = 0;
k=0;
int realPitch = i*pitch;
for(j=0; j<(int)msrcbitmap_info.width; j++)
{
unsigned char b = ppbitmap[(i*SrcWidth+j)*3+realPitch];
unsigned char g = ppbitmap[(i*SrcWidth+j)*3+1+realPitch];
unsigned char r = ppbitmap[(i*SrcWidth+j)*3+2+realPitch];
writein<<=1;
if ((r+g+b)/3>127)
writein|=1;
/*
y = (int)(r * 0.299 + g * 0.587 + b * 0.114);
if(y > 190)
writein|=1;
*/
if (++k==8)
{
pitchcount++;
pdesrudedata[desCount++] = writein;
writein = 0;
k=0;
}
}
if (k != 0)
{
writein<<=(8-k);
pdesrudedata[desCount++] = writein;
pitchcount++;
}
if (pitchcount%4 != 0)
{
writein = 0;
for (j=0; j<4-pitchcount%4; j++)
{
pdesrudedata[desCount++] = writein;
}
}
}
memset(desHead, 0, sizeof(desHead));
memset(desInfo, 0, sizeof(desInfo));
mputwl( desHead + BFH_WTYPE , BMP_SIGNATURE);
mputdwl(desHead + BFH_DSIZE , desCount + 62);
mputdwl(desHead + BFH_DOFFBITS, 62);
mputdwl(desInfo + BIH_DSIZE , msrcbitmap_info.info_bytes);
mputdwl(desInfo + BIH_LWIDTH , msrcbitmap_info.width);
mputdwl(desInfo + BIH_LHEIGHT , msrcbitmap_info.height);
mputwl( desInfo + BIH_WPLANES , 1);
mputwl( desInfo + BIH_WBITCOUNT , 1);
mputdwl(desInfo + BIH_DSIZEIMAGE, desCount);
memcpy((void *)(mbitmap_panel.panel),fix_panel,8);
memcpy(pdest, desHead, sizeof(desHead));
memcpy(pdest+sizeof(desHead), desInfo, sizeof(desInfo));
memcpy(pdest+sizeof(desHead)+sizeof(desInfo), &mbitmap_panel, sizeof(mbitmap_panel));
return desCount + 62;
}