一转眼又到了毕业季,大学里相伴四年之人也将各奔东西,这其中不乏你的好兄弟,好闺蜜,也有你暗恋许久的人,不如就趁这最后的时间,勇敢一次,用我们的专业技术做一张表白图片送给她(他)吧!
这是博主的青梅竹马大美女的原图:
这是经过代码后,自动设计构造的图:当然现在只会发现变暗了之外,好像也没什么区别。
但是当你经过放大只会就知道其中的奥秘了,这是放大121%的效果:
已经能够看出一些端倪了,那我们在放大到459%呢:
没错,我们这次的代码就是实现了用想要的文字构成想要的图,完整源代码放到后面了。
构成一张图片的基本单位是像素,而每一个像素点在同一时刻只能表示一种颜色,如果我们把构成这张图片的每一像素点的颜色依次取出,再把这一个像素点改为我们想要的文字,并且把取出的颜色又依次赋给我们的文字,那么这么一张图是不是就被我们用文字构成了呢?没错原理不难,明白之后就是如何用代码去实现了。
安装好EasyX图形库后。我们就可以开始分析图片了,要记得包含EasyX图形库的头文件
第一步,我们要把用到的图片先加入到内存,然后用EasyX图形库中的getpixe()函数依次得到每一个像素点的颜色值,存放到一个数组里面等待使用。
//1.把图片加载到内存
IMAGE img;
loadimage(&img, "marry.jpg");
int w = img.getwidth();
int h = img.getheight();
int* data = (int *)malloc(sizeof(int) * w * h);
if (data == NULL) return -1;
//设置工作区,对指定图像进行操作
SetWorkingImage(&img);
int k = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
data[k] = getpixel(j, i);
k++;
}
}
SetWorkingImage(); //把工作区恢复到默认工作区
我们会通过scanf()函数输入我们想要构成图片的文字,但为了能够一个字一个字的循环出现在图片上,我们需要将这串字符串分割位一个个的字符数组。
//提示输入文本
char str[124];
printf("请输入文字(用来构成构图):");
scanf_s("%s", str, sizeof(str));
//二 把字符串转为字符串数组
//计算汉字个数
int count = strlen(str) / 2;
char** ss = (char**)malloc(sizeof(char*) * count);
for (int i = 0; i < count; i++)
{
ss[i] = (char*)malloc(sizeof(char) * 3);
strncpy(ss[i], &str[i * 2], 2);
ss[i][2] = '\0';
}
我们还要设置一下字体的格式,否则就会使用默认字体,那样的话会很拥挤,设置合适的字体格式将会使效果更好。
//设置字体
//定义一个字体变量
LOGFONT font;
//获取当前字体
gettextstyle(&font);
font.lfHeight = 12;
font.lfWeight = 0; //默认值
strcpy(font.lfFaceName, "黑体");
font.lfQuality = ANTIALIASED_QUALITY; //抗锯齿
setbkmode(TRANSPARENT); //背景透明
//设置字体
settextstyle(&font);
有了上面这些条件后,我们就只需要开始绘制图片就可以了,即把每一个文字依次填充上数组里面对应的颜色值就可以了,需要用到settexcolor()函数来设置颜色。
//创建一张空白图片
IMAGE imgDest;
//设置图片大小
imgDest.Resize(w * 12, h * 12);
//开始画图,设置图片工作区
SetWorkingImage(&imgDest);
//设置字体
//定义一个字体变量
int index = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
int x = j * 12;
int y = i * 12;
int color = data[i * w + j];
settextcolor(color);
outtextxy(x, y, ss[index]);
index = (index + 1) % count;
}
printf("已转换 %d%%\n",(i + 1) * 100 / h);
}
整合一下前面的代码后,在添加一些自动打开图片的功能后,最终代码来了!我将用我小伙伴的婚纱照作为演示,并且在此再一次祝愿她们新婚快乐!
#include
#include
#include
int main(void)
{
initgraph(1, 1, 1); //在easyx图形库中创建窗口
//提示输入文本
char str[124];
printf("请输入文字(用来构成构图):");
scanf_s("%s", str, sizeof(str));
//一 图片——》数组(存储各个像素的颜色值)
//1.把图片加载到内存
IMAGE img;
loadimage(&img, "marry.jpg");
int w = img.getwidth();
int h = img.getheight();
int* data = (int *)malloc(sizeof(int) * w * h); //用malloc动态分配空间
if (data == NULL) return -1;
//设置工作区,对指定图像进行操作
SetWorkingImage(&img);
int k = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
data[k] = getpixel(j, i);
k++;
}
}
SetWorkingImage(); //把工作区恢复到默认工作区
//二 把字符串转为字符串数组
//计算汉字个数
int count = strlen(str) / 2; //因为每个中文字占两个字节
char** ss = (char**)malloc(sizeof(char*) * count);
for (int i = 0; i < count; i++)
{
ss[i] = (char*)malloc(sizeof(char) * 3);
strncpy(ss[i], &str[i * 2], 2);
ss[i][2] = '\0';
}
//三 绘制图片
//创建一张空白图片
IMAGE imgDest;
//设置图片大小
imgDest.Resize(w * 12, h * 12);
//开始画图,设置图片工作区
SetWorkingImage(&imgDest);
//设置字体
//定义一个字体变量
LOGFONT font;
//获取当前字体
gettextstyle(&font);
font.lfHeight = 12;
font.lfWeight = 0; //默认值
strcpy(font.lfFaceName, "黑体");
font.lfQuality = ANTIALIASED_QUALITY; //抗锯齿
setbkmode(TRANSPARENT); //背景透明
//设置字体
settextstyle(&font);
int index = 0;
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
int x = j * 12;
int y = i * 12;
int color = data[i * w + j];
settextcolor(color);
outtextxy(x, y, ss[index]); //在横坐标为x,纵坐标为y的位置输出字体
index = (index + 1) % count;
}
printf("已转换 %d%%\n",(i + 1) * 100 / h); //添加一个进度提示
}
//保存文件
saveimage("D:/biaobai/Biaobai/Biaobai/img/new.jpg", &imgDest);
//释放内存
free(ss);
free(data);
//把生成的图片自动打开
//方案一:使用Windows的“画图”,但是太大的图打不开
//方案二:使用Windows的图片查看器
system("rundll32.exe c:\\windows\\system32\\shimgvw.dll,ImageView_Fullscreen D:\\biaobai\\Biaobai\\Biaobai\\img\\new.jpg");
closegraph(); //关闭窗口
system("pause");
return 0;
}