从 NSString 创建 UIImage / NSImage 实例,通过结合 ASCII 艺术和幼儿园技能。
原始博客帖子解释了 ASCIImage 的起源,但它可能仍然令人困惑:为什么有人会使用它,以及用于什么样的目的。它的主要优势是结合了两件事:(1)直接在代码中拥有图像,并且(2)看到图像。代码就是图像,图像就是代码。实际上,它只能以这种方式工作对于由几行和/或简单形状组成的简单图像。任何更复杂的东西都会破坏第(2)点,并且可能根本无法使用 ASWIImage 故意限制的选项来实现。
虽然最初它是基于位图开发的,而 ASCII 表示看起来像像素,但由于数字连接的方法,它实际上是一个向量绘图工具,具有强制像素对齐。这可能有点令人困惑。即使我没有意识到这一点,我也感到困惑:在我的原始博客帖子中,我一次也没有使用过“向量”一词。只有当第一个编辑器被开发出来(ASWIImage Super Studio)时,我才意识到它可以绘制非常大的图像,并以我从未想象过的方式输出东西。这是因为背后,形状首先被制作成 NSBezierPath。当然,最后,屏幕上的所有内容最终都会变成像素。
这个想法和初始实现基本上是一个一天的临时解决方案。但在我之后的一年里,我对一些细节进行了微调,并于2015年3月最终公开。由于这些小改动,它真的满足了我用它所需的所有需求。我可能还会向基于块的API中的绘图“上下文”添加更多选项,特别是为了更好地利用矢量方面,增加缩放和平滑选项。我也很想知道其他人会如何使用它。但我认为我想要尽可能地保持简单,并将其限制在原始精神:代码和图像在一个地方,实现即得满足。对于更复杂的事物,应该使用设计师、真正的图像编辑器和真正的格式。
如果您在发布的应用程序中使用了 ASCIImage,请让我知道,并将它添加到这里的列表中。
目前,我只知道 Findings (免责声明:作为 ASCIImage 的作者,我通过 Findings 谋生)。
唉。
ASCIImage 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中
pod "ASCIImage"
图像由字符串数组定义,其中每个字符串表示一行。这里有一个例子
NSArray *asciiRepresentation =
@[
@"· · · 1 2 · · · · · ",
@"· · · A # # · · · · ",
@"· · · · # # # · · · ",
@"· · · · · # # # · · ",
@"· · · · · · 9 # 3 · ",
@"· · · · · · 8 # 4 · ",
@"· · · · · # # # · · ",
@"· · · · # # # · · · ",
@"· · · 7 # # · · · · ",
@"· · · 6 5 · · · · · ",
];
在这个文档中,我将只以如下方式表示
· · · 1 2 · · · · ·
· · · A # # · · · ·
· · · · # # # · · ·
· · · · · # # # · ·
· · · · · · 9 # 3 ·
· · · · · · 8 # 4 ·
· · · · · # # # · ·
· · · · # # # · · ·
· · · 7 # # · · · ·
· · · 6 5 · · · · ·
空格被忽略。以下两种表示方法是等价的。很明显,为什么使用额外的空格是建议的:它确实有助于使内容以正确的宽高比显示。
· · · 1 2 · · · · · ···12·····
· · · A # # · · · · ···A##····
· · · · # # # · · · ····###···
· · · · · # # # · · ·····###··
· · · · · · 9 # 3 · ······9#3·
· · · · · · 8 # 4 · ······8#4·
· · · · · # # # · · ·····###··
· · · · # # # · · · ····###···
· · · 7 # # · · · · ···7##····
· · · 6 5 · · · · · ···65·····
每一行应该有相同数量的非空白字符,否则您只能看到神秘的控制台日志。以下表示方法是不合法的
! ! I N V A L I D ! N O # G O O D !
· ····1 2 · · · · · 1 2
· · · A # # · · · · A # #
· · · · # # # · · · # # #
· · · · · # # # · · # # #
· · · · · · 9 # 3 · 9 # 3
· · · · · · 8 # 4 · 8 # 4
· · · · · # # # · · # # #
· · · · # # # · · · # # #
· · · 7 # # · · · · 7 # #
· · · 6 5 · · · · · 6 5
虽然所有非空白字符都被视为像素网格的一部分,但大多数字符都是被动的。只有以下字符被视为形状的一部分
1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P
Q R S T U V W X Y Z a b c d e f g h i j k l m n p
q r s t u v w x y z
请注意,O(零)和o(小写字母O)被忽略。当前的实现不会忽略大写字母O。这三个中的任何一个都可能被认为是错误,但我认为这是最好的做法。可能我会后悔。很可能不会。
所有其他字符在从字符网格中提取形状时都会被忽略。
以下所有表示方法都是等价的。以下例子中的 '#' 标志对眼睛很有指导作用,我经常使用它们('@' 工作得很好)。但它们也可以被用来恶意隐藏信息!不好!
· 1 2 · · · · · · 1 2 · · · · · · 1 2 · · · · · # 1 2 # # # # #
· A # # · · · · · A @ @ · · · · · A · · · · · · # A # # # # # #
· · # # # · · · · · @ @ @ · · · · · · · · · · · # # # # # # # #
· · · # # # · · · · · @ @ @ · · · · · · · · · · # # # # # # # #
· · · · 9 # 3 · · · · · 9 @ 3 · · · · · 9 · 3 · # # # # 9 # 3 #
· · · · 8 # 4 · · · · · 8 @ 4 · · · · · 8 · 4 · # # # # 8 # 4 #
· · · # # # · · · · · @ @ @ · · · · · · · · · · # # # # # # # #
· · # # # · · · · · @ @ @ · · · · · · · · · · · # # # # # # # #
· 7 # # · · · · · 7 @ @ · · · · · 7 · · · · · · # 7 # # # # # #
· 6 5 · · · · · · 6 5 · · · · · · 6 5 · · · · · # 6 5 # # # # #
在渲染成 NSImage 之前,ASCII网格被转换成一系列的 NSBezierPath。下面的几节将描述可能创建的不同类型的贝塞尔路径。
上述字符的最简单用途是使用著名的“连接数字”技术来绘制多边形。每个多边形由一系列连续的字符定义,每当您在上面的列表中跳过一个字符时,就开始新一个多边形。因此,第一个多边形可能由系列 '123456' 定义,下一个形状由 '89ABCDEF' 定义,下一个由 'HIJKLMNOP' 定义等。对于多边形,每个字符只能使用一次(或根本不使用)。如果您用完了字符,您可能正在滥用 ASCIImage!
这里是包含3个多边形的示例,这些多边形使用序列[1,2,3,4,5,6,7,8,9,A]定义,然后是[C,D,E],最后是[G,H,I,J,K,L]。请注意,字符B和F被跳过以区分这三个多边形。旁边的第二个示例与之等价,但最后一个多边形使用序列[a,b,c,d,e,f],没有很好的理由(但也没有坏的理由)。
· · · · · · · · C · · E · · · · · · · · C · · E
· · · 1 2 · · · · · · · · · · 1 2 · · · · · · ·
· · · A · · · · · · · · · · · A · · · · · · · ·
· · · · · · · · · · · D · · · · · · · · · · · D
G · H · · · · · · · · · a · b · · · · · · · · ·
· · · · · · 9 · 3 · · · · · · · · · 9 · 3 · · ·
· · I J · · 8 · 4 · · · · · c d · · 8 · 4 · · ·
L · · K · · · · · · · · f · · e · · · · · · · ·
· · · · · · · · · · · · · · · · · · · · · · · ·
· · · 7 · · · · · · · · · · · 7 · · · · · · · ·
· · · 6 5 · · · · · · · · · · 6 5 · · · · · · ·
· · · · · · · · · · · · · · · · · · · · · · · ·
当一个多边形仅由一个字符组成时,它将形成一个填充相应点的正方形。以下表示包含了5个单独的点。
· · 1 · · · · · · 5 · T
· · · · 3 · · · · · · ·
· · · · · · · · · · 7 ·
· · · · · · · · · · · ·
当一个字符恰好被使用两次时,相应的形状将是连接两个点的线条(中心到中心,带有方形的端点,当使用1点宽加粗绘图时,将准确填充像素)。由于此类字符被多次使用,它们不能是多项式的一部分,并且不需要在线条与其他任何形状之间跳过字符。以下是一个包含3条线和三角形的示例。注意,我们没有跳过任何字符(尽管我们可以)。
· · 1 # # # # # # 1 6 ·
· · · · · · · · · · # ·
· · · · 2 · 3 · · · # ·
· · · · · 4 · · · · # ·
· · · · · · · · · · # ·
· · 5 # # # # # # 5 6 ·
当一个字符被使用三次或更多次时,相应的形状将是通过包含所有点的最大矩形定义的椭圆。以下所有表示都将产生相同直径为11点的圆。
· · · 1 1 1 1 1 · · · · · · · · 1 · · · · · · · · · · 1 · · · · ·
· · 1 · · · · · 1 · · · · · · · · · · · · · · · · · · · · · · · ·
· 1 · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · · ·
1 · · · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · ·
1 · · · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · ·
1 · · · · · · · · · 1 1 · · · · · · · · · 1 · · · · · · · · · · ·
1 · · · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · ·
1 · · · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · ·
· 1 · · · · · · · 1 · · · · · · · · · · · · · · · · · · · · · · ·
· · 1 · · · · · 1 · · · · · · · · · · · · · · · · · · · · · · · ·
· · · 1 1 1 1 1 · · · · · · · · 1 · · · · · 1 · · · · · · · · · 1
'API'这个词对于ASCIImage来说有点夸张。它只是一个NSImage
类别,包含两个类方法。
我99%的时间使用最简单的方法
+ (PARImage *)imageWithASCIIRepresentation:(NSArray *)rep
color:(PARColor *)color
shouldAntialias:(BOOL)shouldAntialias;
使用这种简单形式,单个点、多边形和椭圆将以颜色填充,而线条将以该颜色'加粗'。简单。
第二种方法提供了更高级的选项,可以使用contextHandler
块分别设置在每个"形状"上。由块传递的可变字典可以使用以下常量中列出的键进行修改。该字典最初包含ASCIIContextShapeIndex
键以指示上下文将应用于哪个形状。
+ (PARImage *)imageWithASCIIRepresentation:(NSArray *)rep
contextHandler:(void(^)(NSMutableDictionary *ctx))handler;
以下是字典上下文的键
extern NSString * const ASCIIContextShapeIndex;
extern NSString * const ASCIIContextFillColor;
extern NSString * const ASCIIContextStrokeColor;
extern NSString * const ASCIIContextLineWidth;
extern NSString * const ASCIIContextShouldClose;
extern NSString * const ASCIIContextShouldAntialias;
请注意,这些选项中的某些实际上应用于Bezier路径(线宽、应关闭),而其他一些则应用于实际的图形上下文。反走样选项可以影响两者。ASCIImage在幕后做了一些事情来保持幻象。
cparnot, [email protected]
ASCIImage可在MIT许可证下使用。更多信息请参阅LICENSE文件。