打造你的专属印章(c语言)

2023-11-07

制作原理

我们看到屏幕上显示的汉字的字型有两种表达方式:一种称为矢量方式,一种称为点阵方式。其中的点阵方式较为简单,其原理就是好比:铺地砖。有的铺为白色,有的铺为黑色,只要精心安排,就会组成我们希望的图案,当然也可以是汉字。

瓷砖越多,铺出的图案效果越细腻,这就是点阵的规模。56点阵汉字用56 x 56 = 3136个像素点来描绘。

当我们需要记录一个汉字信息的时候,当然不是存储汉字的字型,而是存储它的编码。汉字可以有多种编码的规则,其中GB2312的编码规则是:一个汉字用两个字节表示,前一个字节表示区号,后一个表示区中的偏移序号

在本博客资源里面有隶书和行楷的两种56点阵字体下载

事先准备:

在这里插入图片描述
准备好代码生成的.exe程序(源码在下面),一个空的bmp文件(这里可以新建一个txt文本,改成bmp的扩展名就可以了),并且和字体的txt文件放在同一个目录下。

启动终端:

在这里插入图片描述
为了支持中文的显示,我们改为中文的编码,输入chcp 936回车即可:
在这里插入图片描述
接下来进入我们刚才文件及程序所在的目录,这里的话当前目录就是文件所在目录,输入demo.exe 56.bmp LiShu56.txt回车,格式为程序名+bmp文件名+txt文档名
在这里插入图片描述
汉字自行输入:
在这里插入图片描述
完成:
在这里插入图片描述
查看:
在这里插入图片描述
在这里插入图片描述
用另一种字体:
在这里插入图片描述

源码附录:

/*********************************************************************************
 ****  FileName:  demo.c
 ****  Function:  印章的打印          
 ****  Usage:     demo.exe  xxxx.bmp  xxx.txt 
 ****  Author:    linshuheng 
 ****  Date:      2020-06-03        
 *********************************************************************************/
//#include <CONIO.H>    
#include <stdlib.h>    
#include <stdio.h>    
#include <math.h>   
#include <malloc.h> 
#include <string.h>
char strk[4];
char stri[120];   
typedef unsigned char BYTE;   
typedef unsigned short WORD;   
typedef unsigned long DWORD;   
   
/****  The file header of bmp file 位图文件头*****/
#include <pshpack2.h> 
typedef struct tagBITMAPFILEHEADER {   
    WORD bfType;   
    DWORD bfSize;   
    WORD bfReserved1;   
    WORD bfReserved2;
    DWORD bfoffBits;                                                
} BITMAPFILEHEADER; 
#include <poppack.h> 
   
/****  The information header of bmp file 位图信息头*****/
typedef struct tagBITMAPINFOHEADER {   
    DWORD biSize;   
    DWORD biWidth;   
    DWORD biHeight;   
    WORD  biPlanes;   
    WORD  biBitCount;      
    DWORD biCompress;
    DWORD biSizeImage;   
    DWORD biXPeIsPerMeter;   
    DWORD biYPeIsPerMeter;   
    DWORD biCIrUsed;   
    DWORD biClrImprotant;   
} BITMAPINFOHEADER;   
   
/****  The RGB data of bmp file 图像RGB数据*****/
typedef struct tagRGBDATA{   
    BYTE rgbBlue;       
    BYTE rgbGreen; 
	BYTE rgbRed;   
} RGBDATA; 
int main(int argc, char *argv[])
{
	
	RGBDATA *bmpData=NULL;	//图像数据指针
	FILE *fp;				//BMP文件指针
	FILE *fq;
//	long i,j,k;
	long width=120;			//图像宽度
	long height=120;		//图像高度
	long dataSize=width*height;
	BITMAPFILEHEADER bmfHeader;   
	BITMAPINFOHEADER bmiHeader; 
	int  i, len; 
    unsigned char  BM[100];
    char  str[200];
	if(argc<2)
	{
		printf("\n    请指定您要生成的BMP文件名!\n");
		printf("\n    方法1:在cmd窗口输入: demo.exe  xxxx.bmp  xxx.txt 后回车执行!\n");
		printf("\n    方法2:在VC的工程设置中添加参数: xxxx.bmp xxx.txt后编译运行!\n");
		printf("\n    功能: 根据文字生成指定印章\n\n");
		exit(0);
	}		

	printf("\n    ********************************************************************************\n");
	printf("\n         感谢您使用txt文件制作印章程序                 \n");
	printf("\n             作者:林舒恒                \n");
	printf("\n             日期:2020年6月03日                 \n");
	printf("\n             目的:印章生成程序       \n");
	printf("\n             功能:根据不同的字体,输入对应的四个文字即可打印\n\n");
	printf("\n    ********************************************************************************\n\n");

    //第一步:用命令行中给出的文件名新建一BMP文件,此时还是一个空文件
	if((fp=fopen(argv[1],"wb+"))==NULL)
	{
		printf("Cannot open BMP file!");
		exit(0);
	}
	if((fq=fopen(argv[2],"r"))==NULL)
	{
		printf("Cannot open TXT file!");
		exit(0);
 	}
 	 printf("请输入四个汉字:");
    scanf("%s",BM);
    for(len=0;BM[len]!='\0';len++);
    for(i=0;i<len;i++)
	printf("BM[%d]=%x\n",i,BM[i]); //输入"向",则其编码为CF  F2

    printf("将编码转换成字符并显示:");
//	fread(&txt,sizeof(TXT),1,fq);

	//第二步:置文件头数据并写入BMP文件
	bmfHeader.bfType=0x4d42;
	bmfHeader.bfSize=14+40+width*height*3;
	bmfHeader.bfReserved1=0;
	bmfHeader.bfReserved2=0;
	bmfHeader.bfoffBits=0x36;
    fwrite(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, fp);

	//第三步:置信息头数据并写入BMP文件
	bmiHeader.biSize=40;
	bmiHeader.biWidth=width;
	bmiHeader.biHeight=height;
	bmiHeader.biPlanes=1;
	bmiHeader.biBitCount=24;
	bmiHeader.biCompress=0;
	bmiHeader.biSizeImage=width*height*3;
	bmiHeader.biXPeIsPerMeter=0;
	bmiHeader.biYPeIsPerMeter=0;
	bmiHeader.biCIrUsed=0;
	bmiHeader.biClrImprotant=0;
    fwrite(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);

	//第四步:置图像RGB数据并写入BMP文件
	//分配足够内存,让bmpData指向这块内存,用于存放图像各象素点的RGB分量值
	if((bmpData=(RGBDATA*)malloc(width*height*3))==NULL)
	{
		printf("bmpData memory malloc error!");
	}	
	for(int i=0;i<len;i++)
		sprintf(str+2*i,"%x",BM[i]); //编码->字符,并存入str数组
	for(int i=0;i<height;i++)
		{
		
		for( int j=0;j<width;j++)
		{
		int k=(height-i-1)*width + j;//计算bmp图片中第i行第j列图像数据在bmpData[]数组中的位置
			
		if(i==0||i==1||i==2||i==3||j==3||j==1||j==2||j==0||i==116||i==117||i==118||i==119||j==118||j==119||j==117||j==116)//设置红色边框 
		{
			bmpData[k].rgbBlue=0;
			bmpData[k].rgbGreen=0;
			bmpData[k].rgbRed=255;//红色分量值
		}
		else 
		{
			bmpData[k].rgbBlue=255;//白色分量值为:255
			bmpData[k].rgbGreen=255;
			bmpData[k].rgbRed=255;	
		} 
	}
}
    int count=1;
    int dx[4]={4,56,4,56};//为了安排四个字的位置,采用每个字做不同的偏移 
    int dy[4]={56,56,4,4};
		for(int i=0;i<16;i+=4)
		{
			strncpy(strk,str+i,4);
			rewind(fq);//从头开始一行行寻找 
			while(!feof(fq))
			{
				fgets(stri,sizeof(stri)-1,fq);//一行行往下寻找 
				if(strstr(stri,strk))//找到了对应编码 
				{
					
						for(int w=0;w<56;w++)//往下56行的内容转化为对应的红白色块 
						{	
							fgets(stri,sizeof(stri)-1,fq);
							int flag=0;
							for(int j=0;j<63;j++)
							{	
								int k=(height-w-1-dx[i/4])*width + j+dy[i/4]-flag;//flag的解释如下 : 
								if(stri[j]==',')//如果遇到逗号,要忽略,采用的策略为色块向左移动flag个单位 
								{
									flag++;
									continue;
								}
								if(stri[j]=='X')
								{
								bmpData[k].rgbBlue=0;
								bmpData[k].rgbGreen=0;
								bmpData[k].rgbRed=255;//红色分量值为:255
								}
								else
								{
								bmpData[k].rgbBlue=255;//白色分量值为:255
								bmpData[k].rgbGreen=255;
								bmpData[k].rgbRed=255;	
								} 
							}
						}
						break; //找到了一个字,得跳出循环重新从第一行找起,省时间 
				}
				
			}
		}
		
	fwrite(bmpData,sizeof(RGBDATA),dataSize,fp);//将bmpData所指内存中的RGB数据一次性写入BMP文件

	printf("\n    恭喜您!BMP文件已经成功生成!\n");
	printf("\n    请在当前目录下查看生成的BMP文件%s\n\n",argv[1]);

	free(bmpData);	//释放bmpData所指的内存空间
	bmpData=NULL;	//置bmpData为空指针
	fclose(fp);		//关闭fp所指文件
	fclose(fq);

}

其中上面用到的的查找汉字的原理是通过汉字转编码再在txt文档中查找的,这里再附上单独查找的代码:

#include<stdio.h>
#include<string.h> 
int  main(int argc, char *argv[])
{
	int  i, len; 
    unsigned char  BM[100];
    char  str[200];
	FILE *fq=fopen(argv[1],"rb");
    printf("请输入一个或多个汉字:");
    scanf("%s",BM);

    for(len=0;BM[len]!='\0';len++);
    for(i=0;i<len;i++)
	printf("BM[%d]=%x\n",i,BM[i]); 

    printf("将编码转换成字符并显示:");
	
    for(i=0;i<len;i++)
		sprintf(str+2*i,"%x",BM[i]); //编码->字符,并存入str数组
		
		printf("%s",str); 
		
		fclose(fq);	
    return  0;

}

例如:
在这里插入图片描述
如果对bmp文件还有兴趣,请移步看其他博主写的bmp文件的详细格式,这里推荐:https://blog.csdn.net/aidem_brown/article/details/80500637
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打造你的专属印章(c语言) 的相关文章

  • 2.4.1 C# 和 F# 中的类型推断

    2 4 1 C 和 F 中的类型推断 大多数的类型有简称 例如 int 或 Random 只有很少一部分需要类型推断 因为手写类型名称并不困难 C 2 0 支持泛型 因此 可以构造更复杂的类型 在函数语言中的类型 像 F 是相当复杂的 尤其
  • R语言legend函数参数详解

    legend x y NULL legend fill NULL col par col border black lty lwd pch angle 45 density NULL bty o bg par bg box lwd par
  • Scala学习系列(二)——环境安装配置

    Scala下载地址 https www scala lang org download 一 安装JDK 首先 因为Scala是运行在JVM平台上的 所以安装Scala之前要安装JDK 二 二进制安装方式 我们可以直接用二进制安装Scala
  • 合并BPL包图文教程

    Delphi IDE 本身就是一个插件模式的工具 插件的好处不用多说 运行包的BPL 其实就是众多单元的集合 因此可以再次重新组合 只要你将各个BPL包用到的单元再组合一次 本文以 http code google com p tangra
  • libuv源码分析(1)事件循环分析

    前言 libuv总是报出一些让人难以理解的错误 作为一个C的项目 不具有Java JavaScript php那样的人气 很难百度到一些问题的答案 甚至google也不行 为了用好libuv 也为了学习吧 我开始看libuv的源码 不知道自
  • 【正点原子STM32连载】 第三十一章 睡眠模式实验 摘自【正点原子】APM32F407最小系统板使用指南

    1 实验平台 正点原子stm32f103战舰开发板V4 2 平台购买地址 https detail tmall com item htm id 609294757420 3 全套实验源码 手册 视频下载地址 http www openedv
  • 《机器学习》周志华(西瓜书)学习笔记 第二章 模型评估与选择

    机器学习 周志华 学习笔记 总目录 世上只有一种投资是只赚不赔的 那就是学习 当你的的能力还驾驭不了你的目标时 就应该沉下心来历练 当你的才华撑不起你的野心时 就应该静下心来学习 第二章 模型评估与选择 2 1 经验误差与过拟合 错误率 E
  • 11 【标准库之JSON对象 JSON5】

    13 JSON 对象 13 1 JSON 格式 JSON 格式 JavaScript Object Notation 的缩写 是一种用于数据交换的文本格式 2001年由 Douglas Crockford 提出 目的是取代繁琐笨重的 XML
  • 递归视角下

    def listSum numbers if not numbers return 0 else f rest numbers return f listSum rest myList 1 2 3 4 None total listSum
  • 在存储过程中IN传入参数无效的解决方法

    列 SELECT count COUNT sysid FROM Student WHERE Id IN Sysids 想要得到count 但是在in的时候 传入的参数无效 得到的结果只能为0 这时候可以将其转化成一条变量语句 然后去执行这条
  • websocket即时通讯

    目录 一 websocket简介 二 背景 三 优点 1 控制开销 2 实时性更强 3 保持连接状态 4 更好的二进制支持 5 支持扩展和更好的实现压缩效果 四 原理 1 客户端 服务器建立TCP连接 三次握手 2 TCP连接成功后 客户端
  • PANet[详解]

    一 Abstract摘要 Introduction介绍 Abstract 信息在神经网络中的传播方式非常重要 本文提出了一种基于提议的实例分割框架下的路径聚合网络Path Aggregation Network PANet 旨在促进信息的流
  • SQL Server 2019 Express的安装

    SQL Server 2019 Express的安装 下载安装程序 SQL Server 2019 Express 安装SQL Server 双击运行SQL2019 SSEI Expr exe 运行下载程序 选择自定义 点击安装 稍等几分钟
  • 小程序消息推送配置 Token校验失败,请检查确认

    一 小程序消息推送配置 Token校验失败 请检查确认 添加配置失败 原因 只要是没有echostr原样返回 就会报错 注意 返回的事echostr的内容 而不是key value格式 示例如下 return Content reqData
  • 大数据数据湖技术Hudi0.12.0版本源码编译

    0 介绍 Apache Hudi Hadoop Upserts Delete and Incremental 是下一代流数据湖平台 Apache Hudi将核心仓库和数据库功能直接引入数据湖 Hudi提供了表 事务 高效的upserts d
  • api的封装

    这是以 cnode中文社区的api 为例 值得一提的是有些请求可能要先进行url的编码 这是简易版的 use strict api 路径 get topics 主题首页 get topic id 主题详情 post accesstoken
  • 基于libevent, libuv和android Looper不断演进socket编程

    最近在做websocket porting的工作中 需要实现最底层socket读和写 基于同步读 libevent libuv和android Looper都写了一套 从中体会不少 1 同步阻塞读写 最开始采用同步阻塞读写 主要是为了快速实
  • 织梦网站搬迁后服务器错误,如何解决DEDECMS 5.7 将data目录迁移后网站地图无法打开和更新的问题...

    如何解决DEDECMS 5 7 将data目录迁移后网站地图无法打开和更新的问题 发布时间 2020 09 15 11 53 29 来源 亿速云 阅读 88 作者 小新 这篇文章主要介绍如何解决DEDECMS 5 7 将data目录迁移后网

随机推荐

  • Firefox about:config设置

    以下内容来自于转载 原文 https www jianshu com p 6e6937a9574c 地址栏输入about config 打开 搜索 书签在新标签页中打开 browser tabs loadBookmarksInTabs 默认
  • 安卓开发日志捕获,错误日志捕获catch,崩溃日志捕获,抓取崩溃日志

    import android content Context import android content SharedPreferences import android content pm PackageInfo import and
  • 从街边小吃到网上爆款,螺蛳粉是如何逆袭走红的呢?

    要说现当下最火的食物是什么 那螺蛳粉肯定占有一席之地 喝奶茶已经不是当下年轻人的续命方式了 现在只有会嗦粉的才能称得上是整条街最靓的崽 在今年五花八门的热搜中 可以说螺蛳粉长在了热搜上 从西瓜微数热搜榜来看 关于螺蛳粉的热搜可是数不胜数 在
  • windows系统升级node

    直接去官网下载对应版本的安装包 覆盖到原来的下载路径就可以了 注意一定要下载稳定版本的下载 Node js nodejs org https nodejs org zh cn download 查看node下载路径where node 查看
  • 线程池基础入门

    文章目录 线程池的状态 ThreadPoolExecutor 构造方法 Executors 固定大小的线程池 Executors 定时线程池 Executors 带缓冲线程池 Executors 单线程线程池 线程池常用方法 线程池的状态
  • 对接阿里云弹性收缩小结

    1 垂直伸缩 执行垂直伸缩任务时 系统自动完成停止目标实例 调整实例规格 启动目标实例一系列操作 这个相对简单 直接增加实例配置 2 弹性伸缩 参考 阿里云弹性伸缩初体验 偶影独行的博客 CSDN博客 Sina Visitor System
  • Android电池信息

    Android中电池信息 Battery information 的取得 这里介绍电池信息的取得 Android content BroadcastReceiver类 Android os BatteryManager类 电池信息的取得 调
  • Jenkins连接k8s的多种姿势

    目录 1 概述 2 同集群 3 跨集群 3 1 端口有什么 3 2 网络策略打通 3 3 证书的生成和配置 3 4 配置连接外部的 k8s 集群 4 测试验证 4 1 配置 pod template 4 2 自由风格构建测试 4 3 流水线
  • Vue计算属性实现及简写

    计算属性 1 定义 要用的属性不存在 要通过已有的属性计算得来 2 原理 底层借助了Object defineproperty方法提供的getter和setter 3 get函数什么时候执行 1 初次读取时会执行一次 2 当依赖的数据发生改
  • 博客网址

    博客不在更新 转到www fulus wang 转载于 https my oschina net fuluS blog 713434
  • pandas整表写入excel指定位置_pandas处理excel的常用方法技巧(上)

    1 导库 import pandas as pd 2 读取excel文件 这里要注意的就是第二个参数header如果不设置 pandas会默认把excel的第一行当作columns header None的时候pandas会为我们新生成从0
  • 使用深度学习模型CNN进行实时情绪检测研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 使用深度学习模型CNN进行实时情绪检测是一
  • 字符串、字符数组的截取函数:strncpy、strsub

    字符数组的截取函数 字符串截取函数
  • 【材质和贴图】

    1 贴图坐标的换算公式 a1 a0 Offset 1 Tilling
  • C语言——每日一题

    1 倒置字符串 倒置字符串 要将每一个单词逆序输出 首先可以将整个字符串内容都逆序输出 然后再将字符串中的每一个单词再进行逆序 例如 逆序 i like beijing 先逆序成 gnijieb ekil i 再将每个单词逆序 beijin
  • 用ram实现寄存器堆_51单片机RAM数据存储区学习笔记

    1 RAM keil C语言编程 RAM是程序运行中存放随机变量的数据空间 在keil中编写程序 如果当前模式为small模式 如果总的变量大小未超过128B 则未初始化的变量的初值默认为0 如果所有的变量超过单片机small模式下的128
  • 基于Tensorflow来重现GPT v1模型

    OpenAI推出的ChatGPT模型让我们看到了通用人工智能的发展潜力 我也找了GPT的相关论文来进行研究 OpenAI在2017年的论文Improving Language Understanding by Generative Pre
  • 线程创建的三种方式

    1 Thread类实现多线程 步骤 1 创建一个Thread线程类的子类 重新run方法 2 创建该子类的实例 通过调用start方法启动线程 示例 class MyThread extends Thread public MyThread
  • c/c++语言的几个关键字

    1 register 中文意思为 寄存器 由来 在C语言中的register修饰的变量表示将此变量存储在CPU的寄存器中 由于CPU访问寄存器比访问内存快很多 可以大大提高运算速度 注意事项 1 用register修饰的变量只能是局部变量
  • 打造你的专属印章(c语言)

    制作原理 我们看到屏幕上显示的汉字的字型有两种表达方式 一种称为矢量方式 一种称为点阵方式 其中的点阵方式较为简单 其原理就是好比 铺地砖 有的铺为白色 有的铺为黑色 只要精心安排 就会组成我们希望的图案 当然也可以是汉字 瓷砖越多 铺出的