图像处理--字模放大

news/2024/7/21 6:48:45 标签: 图像处理, 音视频

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、 插值处理之后的效果:
在这里插入图片描述


http://www.niftyadmin.cn/n/1721668.html

相关文章

Linux配置本地yum源

在无法联网的情况下&#xff0c;yum 可以考虑用本地光盘&#xff08;或安装映像文件&#xff09;作为 yum 源。 Linux 系统安装映像文件中就含有常用的 RPM 包&#xff0c;我们可以使用压缩文件打开映像文件&#xff08;iso文件&#xff09;&#xff0c;进入其 Packages 子目录…

数学基础--旋转矩阵的推导

1、简介 旋转矩阵的应用范围比较广&#xff0c;是姿态变换&#xff0c;坐标变换等的基础&#xff0c;由于考虑到IMU的融合需要用到旋转矩阵。因此&#xff0c;本文介绍一下旋转矩阵的推导过程。 2、推导过程 在介绍旋转矩阵之前&#xff0c;先介绍一下两个矩阵相乘的示意图如…

zabbix-自定义报警媒介

自定义告警&#xff0c;我的理解是&#xff1a;当出现告警的时候&#xff0c;触发执行脚本&#xff0c;并将告警的信息传递给脚本&#xff0c;在脚本中将信息发送给相关人员 告警的信息的3个变量 {ALERT.SENDTO} 接收人 {ALERT.SUBJECT} 主题 {ALERT.MESSAGE} 消息体 1、进入…

PCB设计--PCB设计基本注意事项

1、简介 最近为了好玩&#xff0c;准备画几个板子玩玩&#xff0c;因此查阅可一些PCB设计需要注意的事项&#xff1b; 2、布局 布局&#xff1a;在综合考虑信号质量、EMC、热设计、DFM、DFT、结构、安规等方面要求的基础上&#xff0c;将器件合理的放置到板面上。 PCB布局设…

音频基础--PCM音频

1、PCM定义 PCM 全称 Pulse-Code Modulation,就是脉冲调制编码&#xff0c;是用于将波形表示的模拟音频信号转换为数字1和0表示的数字音频信号&#xff0c;而不压缩也不丢失信息的处理技术。简单来说就是一种用数字表示采样模拟信号的方法。 如下是使用Audacity音频处理软件截取…

C基础--内存对齐问题(结构体对齐)

问题现象 在调试一个软件功能时&#xff0c;发现一个结构体对齐的问题&#xff0c;以前没有太关注&#xff0c;现在把它总结出来。先看示例&#xff1a; 结构体1&#xff1a; typedef struct {char magic[4];uint32_t crc32;uint32_t lenght;uint16_t ver;uint16_t IFrameCnt…

oracle-impdp导入数据

第一&#xff1a;dmp文件上传到/picclife/app/oracle/admin/xcalcpro/dpdump目录下 第二&#xff1a;创建directory路径 sqlplus / as sysdba create or replace directory PATH as /picclife/app/oracle/admin/xcalcpro/dpdump; grant read,write on directory PATH to basi…

自制触摸屏电话

几个周末前闲着无聊做了个触摸屏电话&#xff0c;功能是简单了点&#xff0c;只能打电话、接电话、挂断、接听。而且个子还大了点&#xff0c;但是总归还算是做出了点东西&#xff0c;就晒晒。喷吧&#xff0c;哈哈。 小触摸屏是这样的&#xff08;按钮左上角的编号实际显示时是…