BMP位图转换:24bpp转1bpp — C实现

16 篇文章 0 订阅
3 篇文章 0 订阅

24位BMP位图转点阵图,即24bpp转1bpp

基本概念

BPP:bits per pixel,每个像素的比特数。

场景

  1. 打印机打印二维码/图片:热敏打印机只可打印点阵图
  2. 对图片质量要求低,降低内存消耗。

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;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值