bad apple项目试制

前言

之前就一直很羡慕大佬能制作出用字符跑bad apple的项目,一直很想试试。最近突然想到了,于是动手自己实操了一番。
项目里的很多代码都是借鉴了大佬们的,也感谢很多大佬的博客讲的很详细。
主要借鉴了以下几个大佬的博客:

       https://blog.csdn.net/clauyiye/article/details/78995219?spm=1001.2014.3001.5501
        https://www.cnblogs.com/CodeMIRACLE/p/5508236.html

我的大部分操作是借鉴大佬的,有一些操作是找到了一些更快捷的方式替代了。
下面将介绍具体的操作:

1.下载视频

视频可以自备,如果不知道怎么下,可以点

https://www.bilibili.com/video/BV1xx411c79H?from=search&seid=6687738456694002600&spm_id_from=333.337.0.0

然后在www.后面加个i就可以跳转下载了,它会要求下个下载器,觉得麻烦的可以通过其他方式获得视频。

2.截图成帧

我看几个大佬推荐的是用OpenCV来将视频处理成一帧帧的图片的,我觉得太麻烦了,安装个OpenCV就花了我许多时间,还不会用。另一个大佬用的是kmplayer或者potplayer,potplayer我电脑上有,但我打开的时候要更新就想让它更新了,我担心截到的帧的格式不对,又去下了个格式工厂,发现里面直接就可以将图片截成帧。
在这里插入图片描述
我立刻就将视频导了进去,帧的间隔建议设为0.1s,如果太小了,截下来的会非常多,特别占空间,即使如此,我也截了两千多张,好像有1.2g,空间不足就别逞强了。在这里插入图片描述
然后截好就存在一个新项目文档里,建议在项目文档里建个文件夹命名为p(为啥叫这个,因为代码里引用的是这个,为了有些同学看不懂代码又想自己实现一遍,你只要按步操作就行),如图所示
在这里插入图片描述

3.用代码生成文档

上代码!!!
下面代码,你需要改一些地方,具体看注释

#include <cstdio>
 #include <cstring>
 #include <stdint.h>
 #include <windows.h>
 using namespace std;
 int32_t width,height;
 RGBQUAD *pixels;
 bool OpenBitmap(char const *filename)
 {
    
    
     FILE *file = fopen(filename, "rb");
     if (file)
     {
    
    
         width=0;
         height=0;
         BITMAPFILEHEADER bf;
         BITMAPINFOHEADER bi;
         fread(&bf, sizeof(bf), 1, file);
         fread(&bi, sizeof(bi), 1, file);
         if(bi.biBitCount!=24)
             return false;
         if(bi.biCompression!=BI_RGB)
             return false;
         width=bi.biWidth;
         height=bi.biHeight;
         pixels=new RGBQUAD[width*height];
         uint32_t rowSize = (bi.biBitCount * width + 31) / 32 * 4;
         uint8_t *line = new uint8_t[rowSize];
         for (int y = 0; y < height; y++)
         {
    
    
             fread(line, rowSize, 1, file);
             for (int x = 0; x < width; x++)
             {
    
    
                 uint8_t *color = line + x * 3;
                 RGBQUAD *pixel = &pixels[(height-y-1) * width+x];
                 pixel->rgbBlue  = color[0];
                 pixel->rgbGreen = color[1];
                 pixel->rgbRed   = color[2];
             }
         }
         delete[] line;
         fclose(file);
         return true;
     }
     return false;
 }
 RGBQUAD GetColor(int x, int y, int w, int h)
 {
    
    
     int r = 0, g = 0, b = 0;
     for (int i = 0; i < w; i++)
     {
    
    
         if (i + x >= width) continue;
         for (int j = 0; j < h; j++)
         {
    
    
             if (j + y >= height) continue;
             RGBQUAD const& color = pixels[(y + j) * width + (x + i)];
             r += color.rgbRed;
             g += color.rgbGreen;
             b += color.rgbBlue;
         }
     }
     return RGBQUAD{
    
    r / (w * h), g / (w * h),b / (w * h)};
 }
 char ColorToCharacter(RGBQUAD const& color)
 {
    
    
     int brightness = (color.rgbRed + color.rgbGreen + color.rgbBlue) / 3;
     static char const *characters = "Qdogc*;:-. ";
     int len = strlen(characters);
     int span = 0xFF / len;
     int cidx = brightness / span;
     if (cidx == len)
         cidx--;
     return characters[cidx];
 }
 void OutputAscii(const char* filename, int w, int h)
 {
    
    
     FILE *file=fopen(filename,"a+");
     int x = width  / w;
     int y = height / h;
     for (int i = 0; i < height; i += y)
     {
    
    
         for (int j = 0; j < width; j += x)
         {
    
    
             RGBQUAD color = GetColor(j, i, x, y);
             fprintf(file, "%c", ColorToCharacter(color));
            
         }
         fprintf(file, "\n");
   
     }
     delete [] pixels;
     fclose(file);
 }
 int main()
 {
    
    
     char filename[1024];
     printf("转换中.....");
     for(int i=1;i<=2173;i++)//将这里的i改为你p文件夹下图片的数量
     {
    
    
         sprintf(filename,"p/image%d.bmp",i);//这里是读入图片,如果图片的命名不是image+数字,那就自己根据具体命名改下
         if(OpenBitmap(filename));
             OutputAscii("badapple.txt",width/6,height/12);//输出字符文档
     }
     printf("转换完成!");
 }

该程序的存放位置要和p文件夹在同一个文件夹下。

4.播放

接下来有了txt文档,我们就可以播放了

#include <cstdio>
#include <windows.h>
struct fps_limit {
    
    
 
	int previous_time;
	int tpf_limit;
	int tpf;
	fps_limit(int fps = 60) : previous_time(GetTickCount()), tpf(0) {
    
    
		limit_fps(fps);
	}
	void reset() {
    
    
		previous_time = GetTickCount(), 
			tpf = 0;
		tpf_limit = 60;
	}
	void limit_fps(int fps) {
    
    
		tpf_limit = (int)(1000.0f / (float)fps);
	}
	void delay() {
    
    
		tpf = GetTickCount() - previous_time; 
 
		if (tpf < tpf_limit)
			Sleep(tpf_limit - tpf - 1);
 
		previous_time = GetTickCount();
	}
};
int main()
{
    
    
	FILE* fp = fopen("badapple.txt", "r");
	char buf[2048];
	fps_limit fps(20);//画面刷新帧率,不同设备最适不同,需要慢慢试
	while (!feof(fp))
	{
    
    
		HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
														
		COORD pos;//定义光标起始点
		pos.X = 0;
		pos.Y = 10;
		SetConsoleCursorPosition(hConsoleOutput, pos);
		for (int i = 0; i<32; i++) //这里调整的是整个画面的刷新频率,具体啥值播放最流畅需要自己慢慢试
		{
    
    
			fgets(buf, 2048, fp);
			printf("%s", buf);
		}
		fps.delay();
	}
	return 0;
}

该程序也要和txt文档放在同一个文件夹下,播放时如果不流畅,需要自己慢慢挑最适的fps还有刷新频率。
在这里插入图片描述
整个程序,如果有人想要的话,可以私信我,我发给你。

另外,再次感谢大佬们的博客,让我能自己对着博客实现了这样一个有趣的项目。

猜你喜欢

转载自blog.csdn.net/qq_57109165/article/details/121760092