如果一张图片值 1000 个字,那么 140 个字符可以容纳多少张图片?
注意:就是这样,伙计们!赏金截止日期到了,经过深思熟虑后,我决定Boojum 的参赛作品勉强超过了Sam Hocevar 的参赛作品。一旦我有机会写出来,我会发布更详细的笔记。当然,每个人都应该随时继续提交解决方案并改进解决方案供人们投票。感谢所有提交和参赛的人;我很喜欢他们所有人。这对我来说很有趣,我希望对参赛者和观众来说都很有趣。
我遇到了一篇关于尝试将图像压缩到 Twitter 评论中的有趣帖子,该帖子中的很多人(以及Reddit 上的一个帖子)都对不同的方法提出了建议。所以,我认为这将是一个很好的编码挑战;让人们把钱放在嘴边,并展示他们关于编码的想法如何在您可用的有限空间中带来更多细节。
我挑战你想出一个通用系统,将图像编码为 140 个字符的 Twitter 消息,然后再次将它们解码为图像。您可以使用 Unicode 字符,因此每个字符可以获得超过 8 位。但是,即使允许使用 Unicode 字符,您也需要将图像压缩到非常小的空间中;这肯定是有损压缩,因此必须对每个结果看起来有多好进行主观判断。
以下是原作者Quasimondo从他的编码中得到的结果(图像是在知识共享署名-非商业性许可下获得许可的):
你能做得更好吗?
规则
- 你的程序必须有两种模式:编码和解码。
- 编码时:
- 您的程序必须将您选择的任何合理光栅图形格式的图形作为输入。我们会说ImageMagick支持的任何光栅格式都是合理的。
- 您的程序必须输出一条可以用 140 个或更少的 Unicode 代码点表示的消息;–<code>U+10FFFF范围内的 140 个代码点
U+0000
,不包括非字符 (U+FFFE
,U+FFFF
,U+
nFFFE
,U+
nFFFF
其中n是1
–<code>10 十六进制,范围U+FDD0
–<code>U+FDEF) 和代理代码点 (U+D800
–<代码>U+DFFF)。它可以以您选择的任何合理编码输出;GNUiconv
支持的任何编码都将被认为是合理的,您的平台本机编码或语言环境编码可能是一个不错的选择。有关更多详细信息,请参阅下面的Unicode 注释。
- 解码时:
- 您的程序应将编码模式的输出作为输入。
- 您的程序必须以您选择的任何合理格式输出图像,如上所述,尽管输出矢量格式也可以。
- 图像输出应该是输入图像的近似值;离输入图像越近越好。
- 除了上面指定的输出之外,解码过程可能无法访问编码过程的任何其他输出;也就是说,您不能将图像上传到某处并输出 URL 以供解码过程下载,或者任何类似的愚蠢行为。
为了用户界面的一致性,您的程序必须表现如下:
- 您的程序必须是可以在具有适当解释器的平台上设置为可执行的脚本,或者是可以编译为可执行文件的程序。
- 您的程序必须将
encode
或decode
设置模式作为其第一个参数。 您的程序必须通过以下一种或多种方式获取输入(如果您实现了获取文件名的方式,如果缺少文件名,您也可以从 stdin 和 stdout 读取和写入):
从标准输入获取输入并在标准输出上产生输出。
my-program encode <input.png >output.txt my-program decode <output.txt >output.png
从第二个参数命名的文件中获取输入,并在第三个参数命名的文件中产生输出。
my-program encode input.png output.txt my-program decode output.txt output.png
- 对于您的解决方案,请发布:
- 您的完整代码和/或在其他地方托管的指向它的链接(如果它很长,或者需要很多文件来编译,或其他)。
- 如果代码不是很明显,或者代码很长并且人们会对摘要感兴趣,则说明它是如何工作的。
- 示例图像,包含原始图像、压缩后的文本和解码图像。
- 如果您正在建立其他人的想法,请归因于他们。尝试对别人的想法进行提炼是可以的,但你必须归因于他们。
指导方针
这些基本上是可能被打破的规则、建议或评分标准:
- 审美很重要。我将根据以下内容进行判断,并建议其他人进行判断:
- 输出图像看起来有多好,它看起来与原始图像有多少相似之处。
- 文字看起来多好。如果你有一个非常聪明的压缩方案,完全随机的 gobbledigook 是可以的,但我也希望看到将图像变成多语言诗歌的答案,或者类似的聪明东西。请注意,原始解决方案的作者决定只使用汉字,因为这样看起来更好。
- 有趣的代码和聪明的算法总是好的。我喜欢简短、中肯、清晰的代码,但真正聪明的复杂算法也可以,只要它们能产生好的结果。
- 速度也很重要,尽管不如压缩图像的工作好坏重要。我宁愿有一个可以在十分之一秒内转换图像的程序,而不是可以连续几天运行遗传算法的程序。
- 我会更喜欢较短的解决方案而不是较长的解决方案,只要它们在质量上相当可比;简洁是一种美德。
- 你的程序应该以一种可以在 Mac OS X、Linux 或 Windows 上免费使用的语言来实现。我希望能够运行这些程序,但如果你有一个很好的解决方案,只能在MATLAB或其他东西下运行,那很好。
- 你的程序应该尽可能的通用;它应该适用于尽可能多的不同图像,尽管有些图像可能会产生比其他图像更好的结果。尤其:
- 将一些图像内置到程序中进行匹配并写入引用,然后在解码时生成匹配图像,这是相当蹩脚的,并且只会覆盖少数图像。
- 一个可以拍摄简单、平面、几何形状的图像并将它们分解为一些矢量基元的程序非常漂亮,但如果它在超过一定复杂度的图像上失败,它可能不够通用。
- 一个只能拍摄特定固定纵横比的图像但可以很好地处理它们的程序也可以,但并不理想。
- 您可能会发现,与彩色图像相比,黑白图像可以在更小的空间中获取更多信息。另一方面,这可能会限制它适用的图像类型;黑白相间的面孔效果很好,但抽象设计可能不太好。
- 如果输出图像小于输入图像,但比例大致相同,则完全没问题。如果您必须将图像放大以将其与原始图像进行比较,那也没关系;重要的是它的外观。
- 你的程序应该产生实际上可以通过 Twitter 并且毫发无损的输出。这只是一个指导而不是规则,因为我找不到任何关于支持的精确字符集的文档,但你应该避免控制字符、时髦的不可见组合字符、私人使用字符等。
评分标准
作为在选择我接受的解决方案时我将如何对解决方案进行排名的一般指南,假设我可能会以 25 分来评估解决方案(这非常粗略,我不会直接评分任何东西,只是使用这是一个基本准则):
- 编码方案再现各种输入图像的能力为15 分。这是一种主观的、审美的判断
- 0 表示它根本不起作用,它每次都返回相同的图像,或者什么
- 5 意味着它可以编码一些图像,尽管解码后的版本看起来很难看,并且它可能根本无法处理更复杂的图像
- 10 表示它适用于广泛的图像,并产生令人愉悦的图像,有时可能可以区分
- 15 意味着它可以生成某些图像的完美复制品,甚至对于更大、更复杂的图像,也能提供可识别的东西。或者,也许它不会制作出非常容易辨认的图像,但会产生清晰地源自原始图像的精美图像。
- 3分巧妙使用Unicode字符集
- 0 分用于简单地使用整个允许的字符集
- 使用一组有限的字符可安全通过 Twitter 或在更广泛的情况下传输 1 分
- 使用主题字符子集 2 分,例如仅汉字或仅从右到左的字符
- 做一些非常整洁的事情得 3 分,比如生成可读的文本或使用看起来像相关图像的字符
- 聪明的算法方法和代码风格
3 分
- 1000 行代码的 0 点仅用于缩小图像,将其视为每像素 1 位,然后 base64 对其进行编码
- 使用标准编码技术且写得好且简短的东西得 1 分
- 引入相对新颖的编码技术,或者令人惊讶的短而干净的东西,得 2 分
- 实际产生良好结果或在图形编码中开辟新天地的单行线 3 分(如果这似乎是开辟新天地的低分,请记住,这种好结果可能会在美学方面获得高分以及)
- 速度2分。在其他条件相同的情况下,越快越好,但以上标准都比速度更重要
- 在免费(开源)软件上运行得1 分,因为我更喜欢免费软件(请注意,只要 C# 在 Mono 上运行,它仍然有资格获得这一点,同样,如果 MATLAB 代码在 GNU Octave 上运行,它也有资格)
- 实际遵守所有规则得1 分。这些规则变得有点大和复杂,所以我可能会接受其他好的答案,但会错误地回答一个小细节,但我会为任何确实遵循所有规则的解决方案加分
参考图像
有些人要求提供一些参考图像。以下是一些您可以尝试的参考图像;此处嵌入了较小的版本,如果您需要,它们都链接到图像的较大版本:
奖
根据上述标准,我为我最喜欢的解决方案提供500 个代表赏金(加上 StackOverflow 启动的 50 个)。当然,我鼓励其他人也在这里投票选出他们最喜欢的解决方案。
截止日期注意事项
这场比赛将一直持续到赏金用完,大约在 5 月 30 日星期六下午 6 点左右。我不能说它结束的确切时间;它可能是下午 5 点到 7 点之间的任何时间。我保证我会查看下午 2 点之前提交的所有参赛作品,我会尽力查看所有下午 4 点之前提交的参赛作品;如果在那之后提交了解决方案,我可能没有机会在做出决定之前给他们一个公平的审视。此外,您越早提交,您就越有机会投票以帮助我选择最佳解决方案,因此请尝试尽早提交,而不是在截止日期前提交。
Unicode 注释
对于究竟允许使用哪些 Unicode 字符,也存在一些混淆。可能的 Unicode 代码点的范围U+0000
是U+10FFFF
. 在任何开放的数据交换中,有些代码点永远不能用作 Unicode 字符;这些是非字符和代理代码点。非字符在Unidode 标准 5.1.0 第 16.7 节中定义为值U+FFFE
, U+FFFF
, U+
nFFFE
, U+
nFFFF
其中n是1
–<code>10 十六进制,范围U+FDD0
–<代码>U+FDEF。这些值旨在用于特定于应用程序的内部使用,并且符合标准的应用程序可能会从它们处理的文本中去除这些字符。代理代码点,在Unicode 标准 5.1.0 第 3.8 节中定义为U+D800
–<code>U+DFFF,用于对 UTF-16 中基本多语言平面之外的字符进行编码;因此,不可能直接用 UTF-16 编码来表示这些代码点,并且用任何其他编码对它们进行编码都是无效的。因此,出于本次竞赛的目的,我将允许任何程序将图像编码为不超过 140 个 Unicode 代码点的序列,范围为U+0000
–<code>U+10FFFF,不包括上面定义的所有非字符和代理对。
我会更喜欢只使用指定字符的解决方案,甚至更喜欢使用指定字符的聪明子集或使用他们使用的字符集做一些有趣的事情的更好的解决方案。有关分配字符的列表,请参阅Unicode 字符数据库;请注意,有些字符是直接列出的,而有些字符仅作为范围的开始和结束列出。另请注意,代理代码点已在数据库中列出,但如上所述是禁止的。如果您想利用字符的某些属性使输出的文本更有趣,可以使用各种字符信息数据库,例如命名代码块列表和各种字符属性.
由于 Twitter 没有指定它们支持的确切字符集,因此我将对实际上不适用于 Twitter 的解决方案宽容,因为某些字符会额外计数或某些字符会被删除。最好但不要求所有编码输出都应该能够通过 Twitter 或其他微博服务(如identi.ca )不受损害地传输。我看过一些文档说明 Twitter 实体编码 <、> 和 &,因此分别将它们计为 4、4 和 5 个字符,但我自己没有测试过,他们的 JavaScript 字符计数器似乎没有以这种方式计算它们。
提示和链接
- 规则中有效 Unicode 字符的定义有点复杂。选择单个字符块,例如 CJK 统一表意文字 (U+4E00–U+9FCF) 可能更容易。
- 您可以使用现有的图像库,例如ImageMagick或Python Imaging Library来进行图像处理。
- 如果您在理解 Unicode 字符集及其各种编码方面需要帮助,请参阅此快速指南或有关 Linux 和 Unix 中的 UTF-8 的详细常见问题解答。
- 你越早得到你的解决方案,我(和其他投票的人)就会有越多的时间来研究它。如果您改进它,您可以编辑您的解决方案;当我最后一次浏览这些解决方案时,我会以最新版本为基础。
- 如果您想要一种简单的图像格式来解析和写入(并且不想只使用现有格式),我建议使用PPM 格式。它是一种基于文本的格式,非常易于使用,您可以使用ImageMagick进行转换。