图像处理--字模放大

1、简介

在嵌入式设备开发过程中,我们可能需要用到各种大小的字体,由于嵌入式设备的Flash限制,我们不能把各种大小的字体放入到设备的Flash中。因此,在某些场景下,考虑软件对字体放大的方式,达到我们的需求。比如我们可以在Flash中放入font16的字体,然后对这个字体进行正数倍放大(比如放大到font48);

2、处理流程

字模处理流程:
  • 将字模转换成二值图像;
    注意所用的字模参数为:字模采用阴码,列行式,取模顺序逆向
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>


#define BASE_FONTS_SIZE			16

//char in[BASE_FONTS_SIZE*BASE_FONTS_SIZE/8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
//char in[BASE_FONTS_SIZE*BASE_FONTS_SIZE/8] = {0x04,0xD4,0x54,0x5F,0x54,0xD4,0x04,0x00,0x04,0xD4,0x54,0x5F,0x54,0xD4,0x04,0x00,0x04,0xF5,0x57,0x55,0x57,0xF5,0x04,0x00,0x04,0xF5,0x57,0x55,0x57,0xF5,0x04,0x00};									
char in[BASE_FONTS_SIZE*BASE_FONTS_SIZE/8] = {0xFC,0x84,0x84,0xFC,0x00,0x22,0xAA,0xAB,0xAA,0xBE,0x2A,0xAB,0x2A,0xA2,0x00,0x00,0x3F,0x10,0x10,0x3F,0x00,0x0A,0x56,0x9F,0x72,0x06,0x0A,0x4F,0x32,0x5A,0xE3,0x00};									
char out[BASE_FONTS_SIZE*BASE_FONTS_SIZE] = {0,};

// 获取函数
uint32_t get_line(uint32_t len)
{
	uint32_t fonts;
	
	fonts = sqrt(len*8);
	
	return fonts/8;
}


// 获取字体大小
uint32_t get_fonts(uint32_t len)
{
	uint32_t fonts;
	
	fonts = sqrt(len*8);
	
	return fonts;
}

// 字模转化为二值图像,比如16*16的字模,可以转成16*16的数组,字模采用阴码,列行式,取模顺序逆向
int ch_to_arr(const char *pIn, int inLen, char *pOut)
{
	char ch;
	int i, j, k;
	int line, fonts;
	
	
	if (!pIn || !pOut)
	{
		return -1;
	}
	
	line = get_line(inLen);
	fonts = get_fonts(inLen);
	
	for(i=0; i<line; i++)
	{
		for(j=0; j<fonts; j++)
		{
			ch = pIn[i*fonts+j];
			for(k=0; k<8; k++)
			{
				if ((ch>>k)&0x01)
				{
					pOut[(k+i*8)*fonts+j] = 1;
				}
				else
				{
					pOut[(k+i*8)*fonts+j] = 0;
				}
			}
		}
	}

	return 0;
}
  • 将二值图像等比例放大;
int font16_to_fontx(char *pArrFont16, uint32_t arrFont16Len, char *pOutFontx, uint32_t fontxLen, uint32_t zoom)
{
	int i, j;
	int m, n;
	char *pFont;
	uint32_t zoomx;
	uint32_t zoomy;
	uint32_t inFont;
	uint32_t outFontx;
	
	
	if(!pArrFont16 || !pOutFontx)
	{
		return -1;
	}
	
	if((fontxLen < arrFont16Len*zoom*zoom) || (zoom==0))
	{
		return -1;
	}
	
	pFont = malloc(fontxLen);
	if (!pFont)
	{
		return -1;
	}
	
	inFont = sqrt(arrFont16Len);
	outFontx = inFont * zoom;
	printf("outFontx:%d\n", outFontx);
	memset(pOutFontx, 0, fontxLen);
	
	// 将单点放大
	for(i=0; i<inFont; i++)
	{
		for(j=0; j<inFont; j++)
		{
			// 如果这个点为1,那么单点放大
			if (pArrFont16[i*inFont + j] == 1)
			{
				pFont[zoom*i*outFontx+zoom*j] = 1;
			}
		}
	}
	
	for(i=0; i<outFontx; i++)
	{
		for(j=0; j<outFontx; j++)
		{
			// 如果这个点为1,那么将1变成4个
			if (pFont[i*outFontx+j] == 1)
			{
				// 填充行
				if (outFontx-i > zoom)
				{
					zoomx = zoom;
				}
				else 
				{
					zoomx = outFontx-i;
				}
				
				// 填充行
				if(outFontx-j > zoom)
				{
					zoomy = zoom;
				}
				else 
				{
					zoomy = outFontx-i;
				}
				
				for(n=0; n<zoomx; n++)
				{
					for(m=0; m<zoomy; m++)
					{
						pOutFontx[(i+n)*outFontx + m + j] = 1;
					}
				}			
			}
		}
	}
	free(pFont);
	
	return 0;
}
  • 做插值处理,优化放大后的字体,使其更平滑;
int font_interpolation(char *pFontin, uint32_t fontLen)
{
	int i, j;
	int sum = 0;
	int cnt= 0;
	char *pFontmp;
	int fontSize = sqrt(fontLen);
	
	
	if (!pFontin)
	{
		return -1;
	}
	
	pFontmp = (char *)malloc(fontLen);
	if (!pFontmp)
	{
		return -1;
	}
	
	memcpy(pFontmp, pFontin, fontLen);

	for(i=0; i<fontSize; i++)
	{
		for(j=0; j<fontSize; j++)
		{
			if (pFontin[i*fontSize+j] == 0)
			{
				sum = 0;
				cnt = 0;
				// 左边
				if(j-1>=0) 
				{
					cnt ++;
					sum += pFontin[i*fontSize + j - 1];
				}
				
				// 右边
				if(j+1<fontSize) 
				{
					cnt ++;
					sum += pFontin[i*fontSize + j + 1];
				}
				
				// 下边
				if(i-1>=0)
				{
					cnt++;
					sum += pFontin[(i-1)*fontSize + j];
				}

				// 下边
				if(i+1<fontSize)
				{
					cnt++;
					sum += pFontin[(i+1)*fontSize + j];
				}
				
				if (sum * 2 >= cnt)
				{
					pFontmp[i*fontSize+j] = 1;
				}
			}
		}
	}	
	
	memcpy(pFontin, pFontmp, fontLen);
	
	return 0;
}

3、运行Demo

结合上述函数,可以用如下demo进行展示:

int main(void)
{
	char *pOut;
	uint32_t zoom = 4; 
	uint32_t pOutLen = 0;
	
	ch_to_arr(in, sizeof(in), out);
	print(out, BASE_FONTS_SIZE);
	
	printf("\n\n");
	
	pOutLen = BASE_FONTS_SIZE*BASE_FONTS_SIZE*zoom*zoom;
	pOut = malloc(pOutLen);
	if (!pOut)
	{
		return -1;
	}
	
	if (font16_to_fontx(out, sizeof(out), pOut, pOutLen, zoom))
	{
		free(pOut);
		return -1;
	}
	print(pOut, BASE_FONTS_SIZE*zoom);
	
	//printf("\n\n");
	//gray_print(pOut,pOutLen);
	printf("\n\n");
	
	if (zoom>2)
	{
		font_interpolation(pOut, pOutLen);
		print(pOut, BASE_FONTS_SIZE*zoom);
	}
	
	//printf("\n\n");
	//gray_print(pOut,pOutLen);
	//printf("\n\n");
	
	free(pOut);
	
	return 0;
}

“曦”字实际放大效果如下(从font16到font48):
1、原图:
在这里插入图片描述
2、等比例放大(放大三倍):
在这里插入图片描述
3、 插值处理之后的效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值