Yahoo! Logo ASCII Animation in 462 bytes of C
Last week I put together another obfuscated C program and have been urged by my coworkers to post it publicly. I've made some refinements since posting it to our internal list, so here is the final version (to those who had seen it already: it's one line shorter now, and the angles are less screwy, and the animation is 2 seconds instead of 3). Go ahead, try it:
$ cat >yanim.c
c,p,i,j,n,F=40,k,m;float a,x,y,S=0,V=0;main(){for(;F--;usleep(50000),F?puts(
"\x1b[25A"):0)for(S+=V+=(1-S)/10-V/4,j=0;j<72;j+=3,putchar(10))for(i=0;x=S*(
i-27),i++<73;putchar(c[" ''\".$u$"]))for(c=0,n=3;n--;)for(y=S*(j+n-36),k=0,c
^=(136*x*x+84*y*y<92033)<<n,p=6,m=0;m<8;k++["<[\\]O=IKNAL;KNRbF8EbGEROQ@BSX"
"XtG!#t3!^"]/1.16-68>x*cos(a)+y*sin(a)?k=p,p="<AFJPTX"[m++]-50:k==p?c^=1<<n,
m=8:0)a=(k["O:85!fI,wfO8!yZfO8!f*hXK3&fO;:O;#hP;\"i[by asloane"]-79)/14.64;}
^D
$ gcc -o yanim yanim.c -lm
[warnings which real programmers ignore]
$ ./yanim
[you'll see - show the animation]
...uuuu$$$$$uuuu... $$$$$$$uuuuuu
..u$$$$$$$$$$$$$$$$$$$$$$$u.. $$$$$$$$$$$$'
.u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u. $$$$$$$$$$$$
.$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$. $$$$$$$$$$$"
.$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$. $$$$$$$$$$$
u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u $$$$$$$$$$$
.$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$. $$$$$$$$$$'
$$$$$$$$$$$$$u. uu$$$$$''''''''''''''$$$$$$$ $$$$$$$$$$
$$$$$$$$$$$$$$$$. $$$$$$.. ..$$$$$$$$$ $$$$$$$$$"
$$$$$$$$$$$$$$$$$u "$$$$$$"' u$$$$$$$$$$$$$ $$$$$$$$$
u$$$$$$$$$$$$$$$$$$$ '$$$"' u$$$$$$$$$$$$$$$u $$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$. '"' u$$$$$$$$$$$$$$$$$$ $$$$$$$$
$$$$$$$$$$$$$$$$$$$$$u .u$$$$$$$$$$$$$$$$$$$ $$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$u u$$$$$$$$$$$$$$$$$$$$$ $$$$$$$"
'$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$' $$$$$$$
"$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$" ""$$$$$
'$$$$$$$$$$$$$$$""""" """""$$$$$$$$$$$$$$'
"$$$$$$$$$$$$$................$$$$$$$$$$$$" ..
'"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"' $$$$$$$u
'"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"' $$$$$$$'
'""$$$$$$$$$$$$$$$$$$$$$$$$$""' .$$$$$$$
''"""$$$$$$$$$$$$$"""'' '"""""$$
'''''
It's a 20fps, antialiased ASCII art animation of the Yahoo! logo. If you want to figure out how it works on your own, you're welcome to. Otherwise, read on.
I encourage you to play with the constants in the code: S+=V+=(1-S)/10-V/5 is the underdamped control system for the animation -- S is scale (=1/zoom), V is velocity, and 1/10 and 1/5 are the PD constants. S=0 corresponds to infinite zoom on the first frame. S<0 is funny. F is the frame counter. The 1.16 controls the scale of the polygon rendering (68 is an approximation of 79/1.16 so you have to adjust that too), and 136/84/92033 define the ellipse. The 14.64 is not a tunable parameter, though (it's 46/π, and for a good reason).
The antialiasing is simple: each character consists of three vertically-arranged samples and an 8-character lookup table for each arrangement of three on/off pixels. Each frame consists of 73x24 characters, or 73x72 pixels. The 73 horizontal choice was somewhat arbitrary; I suppose I could have gone up to 79.
The logo is rendered as an ellipse and eight convex polygons using a fairly neat method (I thought) with sub-pixel precision and no frame buffer. It required some design tradeoffs to fit into two printable-character arrays, but it's much less code than rendering triangles to a framebuffer, which is the typical way polygon rasterization is done.
To produce this, first I had to vectorize the "Y!" logo. I did this by taking some measurements of a reference image and writing coordinates down on graph paper. Then I wrote a utility program which takes the points and polygon definitions and turns them into angles and offsets as defined below. [I put the generator code on pastebin until I get can some code highlighting stuff set up for my blog].
The ellipse is fairly standard high-school math: x2/a2 + y2/b2 < 1. Each point is tested and if it's inside the ellipse, the pixel is plotted. (136x2 + 84y2 < 92033 was a trivial rearrangement of terms with a and b being the radii of the two axes of the ellipse measured from my source image, scaled to the pixel grid).
Each polygon is made up of a set of separating half-planes (a half-plane being all points on one side of an infinitely long line). If a given point is "inside" all of the half-planes, it's inside the polygon (which only works as long as the polygon is convex) and the pixel is toggled with the XOR operator ^ (thus it handles the "inverse" part inside the ellipse as well as the uninverted exclamation mark without any special cases). Each side of a polygon is defined by the equation ax + by > c. To represent both a and b I use an angle θ so that a = cos(θ) and b = sin(θ) and quantize the angle in π/46 increments — my angles are thus represented from -π to +π as ASCII 33 to 125 — '!' to '}' — with 'O' (ASCII 79) as zero. Then I solve for c, also quantized in scaled increments from -47 to +47, so that the midpoint of the side is considered inside the polygon.
Here's an extremely crude diagram: (I'm writing this on a plane and none of my drawing programs are working. Sorry.)

The shaded area is ax + by < c, implying it's outside the polygon, and the dashed line is ax + by = c.
(a,b) form a vector orthogonal to the line segment they represent pointing towards the inside of the polygon, so we can get them directly from the points defining the line segment by taking the vector defining the side — (x1 - x0, y1 - y0) — and rotating it 90 degrees, resulting in (a, b) = (y1 - y0, x0 - x1). Then we normalize (a, b) as the actual magnitude doesn't matter, but it will be 1 when we decode the angle and we can compensate with our choice of c later (if ax+by>c, then sax+sby>sc for some scale s>0). Then compute θ = atan2(a,b), quantize to one of our 94 angles, and get our new (a,b) = (cos(θ), sin(θ)).
c is easy to get by directly substituting any of the points making up the line on the side of the polygon into c = ax+by. I use the midpoint of the line segment on the side, (xt, yt) = ((x0 +x1)/2, (y0 + y1)/2), because the angle of the side can be slightly off after we quantize θ, and this evens the errors out across the length of the side.
You'll notice on the first couple frames (you can pause with ^S, resume with ^Q -- xon/xoff) that the bottom section of the 'Y' has little bites taken out of it due to the quantization error in the separating half-plane equations.
It could probably be made somewhat more efficient CPU-wise by careful reordering of the separating plane arrays so that most of the drawing area is rejected first. I didn't get to that in my generator code.
The animation is done by the <ESC>[25A sequence — it moves the cursor up 25 lines in just about any terminal emulation mode. I technically only need to move up 24 lines, but puts is shorter than printf and it implicitly adds a newline. If your terminal isn't at least 26 lines high, though, it does funky things to your scrollback. And usleep is there to limit it to 20fps, which is the only non-ANSI Cism about it.
And then I shrunk the code down by arranging it into clever for loops and taking unorthodox advantage of commas, conditionals, and globals being ints by default in C (which is all par for the course in obfuscated C code). And that pretty much reveals all the secrets as to how it was done.
It would be fairly easy to enhance this with a different movement sequence, or rotation (or any kind of 3D transform, as it's basically just ray-tracing the logo). I just animated the scale to prove the point that it was being rendered dynamically and not just a compressed logo, and kept the animation short and sweet.
I apologize in advance for the various sign errors I'm sure to have made when typing this up, but you get the idea.
Yahoo! Logo ASCII Animation in 462 bytes of C的更多相关文章
- booting logo & booting animation
開機第一張圖片: 圖片位置: linux_repo/vendor/mediatek/proprietary/bootable/bootloader/lk/dev/logo 因為 project 選用 ...
- 【C语言编程学习笔记】利用462字节代码实现雅虎logo ACSII 动画!
ACSII 动画演示: 不过本文介绍的是另一个作品:c 代码实现雅虎 logo ACSII 动图. 运行后,你将会看到: 它是一个 20fps.抗锯齿的 Yahoo! logo ASCII 动 ...
- 异常空格,ASCII (194,160)问题
今天运营的同学反映有一些店铺的名称后面带空格,我下意识的说不可能啊,我已经处理过了啊.然后就找出来看. 其中有个店铺的名称是“安踏 ”,第一眼看上去好像是带了个空格.然后我就仔细的看了下. pry(m ...
- 二进制;16进制; Byte , Python的bytes类; Base64数据编码; Bae64模块;
参考:中文维基 二进制 位操作(wiki) Byte字节 互联网数据处理:Base64数据编码 Python的模块Base64 16进制简介 python: bytes对象 字符集介绍:ascii 二 ...
- Python3中的bytes和str类型
Python 3最重要的新特性之一是对字符串和二进制数据流做了明确的区分.文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示.Python 3不会以任意隐式的方式混用str和b ...
- Transact-SQL 数据类型转换
Syntax Syntax for CAST: CAST ( expression AS data_type [ ( length ) ] ) Syntax for CONVERT: CO ...
- python基础知识(四)
摘要:主要涉及lambda表达式.python内置函数(open文件重点).冒泡排序 一.lambda表达式 适用于创建简单函数,也叫匿名函数, 函数名 = lambda 参数 : 返回值 funct ...
- Python3使用urllib访问网页
介绍 改教程翻译自python官网的一篇文档. urllib.request是一个用于访问URL(统一资源定位符)的Python模块.它以urlopen函数的形式提供了一个非常简单的接口,可以访问使用 ...
- 初始python第三天(三)
全局变量与局部变量 1.什么是全局变量 在globals中的变量,都是全局变量,全局变量的作用域就是整个程序 NAME = 'alex' def global_test(): name = 'alex ...
随机推荐
- javascript/jquery给动态加载的元素添加click事件
/** 这种写法:在重新加载数据后事件依然有效*/$(document).on('click', '#district_layer ul li', function () { });
- nodejs错误:ld: library not found for -lgcc_s.10.5 clang: error: linker command failed with exit code 1 (use -v to see invocation)
解决方案: $ cd /usr/local/lib $ sudo ln -s ../../lib/libSystem.B.dylib libgcc_s.10.5.dylib 参考链接
- 简单学JAVA之---接口的定义与实现
为了巩固自己学习的知识,可能会对自己以后所学的知识做一个小结,今天就来一篇接口的定义与实现. 在java中,我们可以通过继承得到另一个类中的方法,但是这个仅仅满足继承一个方法,那有办法可以多个继承不, ...
- 浅谈用java解析xml文档(二)
上一文中总结了dom解析xml文档的方式,本文开始总结使用SAX解析xml 的方式及它的优缺点! SAX(Simple API for XML),是指一种接口,或者一个软件包. 首先我们应该知道SAX ...
- C#学习笔记6:各种字符串问题
1.字符串 逐字字符串字面量:字符串前加@,不仅将反斜杠当做普通字符来处理,而且还会逐字解释所有空白字符. 如: Class Triangle { Static void Main() { Syste ...
- 我踩过的Alwayson的坑!(上集)
最近被sql server Alwayson高可用组和读写分离,弄得神魂颠倒,身心俱疲.遇到了下面一些问题,提醒自己也给后来人做些记录. EntityFramework支不支持Alwayson? 起因 ...
- Switch的表达式的要求
在java中switch后的表达式的类型只能为以下几种:byte.short.char.int(在Java1.6中是这样),在java1.7后支持了对string的判断.
- 解决某些手机RadioGroup中的RadioButton不居中的问题
问题:RadioButton中使用android:gravity="center"使其图片文字居中,在我的华为荣耀7手机上居中显示了,但在HUAWEI G606-T00却显示在右侧 ...
- 敌情篇 ——DDoS攻击原理
敌情篇 ——DDoS攻击原理 DDoS攻击基础 DDoS(Distributed Denial of Service,分布式拒绝服务)攻击的主要目的是让指定目标无法提供正常服务,甚至从互联网上消失,是 ...
- MVC (M-V-C启动程序调用关系)
在网上有很多mvc程序启动,调用之间的关系与顺序.而且还有很多很不错的网站.推荐一个 http://www.cnblogs.com/QLeelulu/archive/2008/09/30/1 ...