个人作品

合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下

图片转化为 ASCII 图,就是很多字符组成图片的那种(by Geodesic)

本程序实现将图片转换为 ascii 字符的效果。

使用说明:

支持 bmp / jpg / gif / emf / wmf / ico 类型的图片。gif 类型的图片仅加载第一帧,不支持透明。我只测试过jpg格式。

请把要转换的图片复制到 exe 程序所在的文件夹,并确保图片名中没有中文等无法输入的字符。

运行 exe 文件即可转换。

因为 txt 文件的行距,字符间距等原因,为了达到最好效果,请先把图片的高度压缩到原来的 1/2(宽度不变)。

转换根据图片的实际大小操作,如果图片过大,请修改图片尺寸,或者手工修改 txt 中字符的尺寸,以便能够完全显示。

这仅仅是一个 demo,里边存在不少问题,比如 ASCII 灰度实际上是按照 8*16 像素扫描的;实际使用的 ASCII 灰度值我修改过,并非原来的灰度等等。

为了更精确的控制字体的尺寸,间距,行距,html 文件是个不错的选择,如果你愿意的话,你可以选择完善这个 demo,做成一个很实用的小小的软件,但是让一个东西变得更加精致,并不是我的兴趣所在,所以估计今后我也不会再修改这个程序了。

为了方便你的完善,我给你写了一段灰度扫描的程序,有自己的 main(),可以独立的运行。

如果在本程序的基础上修改完善,请保留文件头部的作者信息

玩的开心o(∩_∩)o

执行效果如图:

以下是完整源代码:

/////////////////////////////////////////////////////
// 程序名称:图片转ASCII点阵demo
// 编译环境:Visual C++ 6.0,EasyX 2012-5-1测试版 
// 作  者:Geodesic <Geodesicwl-cpro@yahoo.cn> 
// 最后修改:2012-5-16 
///////////////////////////////////////////////////// 
//若提示缺少graphics.h(Easyx)头文件,请到这里下载:
//www.easyx.cn
/////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>

/***********************宏定义***********************/
#define ASC_HEIGHT 8
#define ASC_WIDTH 8
#define ASCII_NUM 32

/*********************结构体定义*********************/
struct ascii
{
	char asc[ASCII_NUM];
	int gray[ASCII_NUM];
}as = {' ', '`', '.', '^', ',', ':', '~', '"', '<', '!', 'c', 't', '+', '{', 'i', '7', '?',
		'u', '3', '0', 'p', 'w', '4', 'A', '8', 'D', 'X', '%', '#', 'H', 'W', 'M',
		0, 5, 7, 9, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
		45, 47, 49, 51, 53, 55, 59, 61, 63, 66, 68, 70};

/**********************函数声明***********************/
char SearchAsc(struct ascii as, int gray);
void Pic2Asc(struct ascii as, char filename[]);

/***********************主函数***********************/
int main(void)
{
	char filename[256];

	system("title, 图片转化为ASCII图画demo");

	printf("请输入文件名(含扩展名)\n\n");
	gets(filename);
	system("cls");
	Pic2Asc(as, filename);

	printf("转换完成,任意键退出\n\n");
	system("pause");

	return 0;
}

/***********************函数体***********************/

//图片转化为ASCII点阵,并保存到txt和html文件中
void Pic2Asc(struct ascii as, char filename[])
{
	int height, width, gray;
	IMAGE img;
	FILE *fpAscPicText;

	//图像设备初始化
	loadimage(&img, filename);
	SetWorkingImage(&img);

	height = getheight() / ASC_HEIGHT;
	width = getwidth() / ASC_WIDTH;

	if((fpAscPicText = fopen("ASC_PIC.txt", "w")) == NULL)
	{
		printf("文件打开失败\n");
		exit(0);
	}

	//开始转化并保存结果
	for(int i = 0; i < height; i++)
	{
		for(int j = 0; j < width; j++)
		{
			gray = 0;

			//扫描每一小块的灰度,并计算出平均灰度
			for(int h = 0; h < ASC_HEIGHT; h++)
				for(int w = 0; w < ASC_WIDTH; w++)
				{
					gray += GetRValue(RGBtoGRAY(getpixel(j * ASC_WIDTH + w, i * ASC_HEIGHT + h))); 
				}
			gray /= (ASC_HEIGHT * ASC_WIDTH);
			gray = (255- gray) * 90 / 255; 
			
			fputc(SearchAsc(as, gray), fpAscPicText);
		}
		fputc('\n', fpAscPicText);
	}
	fclose(fpAscPicText);
}

//二分法查找ASCII字符,就低不就高
char SearchAsc(struct ascii as, int gray)
{
	int lower = 0;
	int higher = ASCII_NUM;
	int mid;

	if(gray <= as.gray[0])
	{
		return as.asc[0];
	}
	else if (gray >= as.gray[ASCII_NUM - 1])
	{
		return as.asc[ASCII_NUM - 1];
	}
	else
	{
		while((higher - lower) > 1)
		{
			mid = (lower + higher) >> 1;
			if(gray > as.gray[mid])
			{
				lower = mid;
			}
			else
			{
				higher = mid;
			}
		}
		return as.asc[lower];
	}
}
作者:Geodesic
邮箱:geodesicwl-cpro@yahoo.cn

添加评论