从任意字符串生成图像

时间:2014-10-13 20:02:08

标签: javascript image-processing dynamic-image-generation

我已经看到了ascii艺术转换器的大量图像,但我需要的是更复杂一点。而不是从ascii字符创建的马赛克图像,我需要能够使用一组预定义的任意长度的字符串作为我的马赛克瓷砖。

我已经做了很多谷歌搜索,但我甚至不确定如何构建我的查询?有这样的事吗?如果它不会在图像生成中使用重复项,那就是奖金。

1 个答案:

答案 0 :(得分:3)

不太适合Stack Overflow,但仍然是一个有趣的项目。所以我有一点乐趣,看看我能走得多远。

我认为归结为:

  1. 计算一组ASCII字符的灰度值;
  2. 计算每个字符串的“最佳拟合度”;
  3. 重复2.直到完成。
  4. 我不认为“没有重复”是可行的,除非你有非常小的图像和很多候选字符串。这就是我想出来的,使用我的头像和我当前的徽章作为字符串列表。 (我排除了我的“c”徽章;不知怎的,我的程序决定对大补丁来说是“最适合”的,这不是很有吸引力。精神注释:不包括单字符串。)

    QuorumQuorumAutobiographerQuorumQuorumQuorumJongwareQuorumQuorumQuorumQuorumQuor
    umQuorumQuorumAutobiographerQuorumQuorumSupporterQuorumQuorumProofreaderQuorumQu
    orumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuorum
    QuorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuor
    umQuorumQuorumAutobiographerQuorumQuorumQuorumAutobiographerQuorumMortarboardQuo
    rumQuorumAutobiographerQuorumQuorumQuorumQuorumAutobiographerQuorumMortarboardQu
    orumQuorumAutobiographerQuorumQuorumQuorumQuorumJongwareQuorumQuorumCommentatorQ
    uorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuorumQuorumQuorumAutobiographe
    rQuorumQuorumAutobiographerQuorumQuorumProofreaderJongwareQuorumQuorumQuorumQuor
    umQuorumQuorumMortarboardJongwareQuorumProofreaderCommentatorSuffrageQuorumQuoru
    mQuorumQuorumJongwareQuorumAutobiographerSuffrageCommentatorCaucusCriticCleanupQ
    uorumQuorumMortarboardAutobiographerCommentatorQuorumConstituentCriticCriticQuor
    umQuorumQuorumQuorumAutobiographerJongwareCleanupSupporterInvestorCriticCleanupQ
    uorumQuorumQuorumQuorumAutobiographerFanaticCleanupFanaticInvestorCriticCleanupQ
    uorumQuorumQuorumQuorumAutobiographerCriticInformedSupporterCriticCriticInformed
    QuorumQuorumQuorumQuorumAutobiographerCriticQuorumSupporterInvestorFanaticQuorum
    QuorumQuorumQuorumQuorumAutobiographerCriticCleanupCommentatorQuorumDeputyQuorum
    QuorumQuorumQuorumQuorumAutobiographerCriticInvestorCaucusInformedDeputyQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorCriticCriticCitizen PatrolQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumAutobiographerCriticCriticCitizen PatrolQuorumQuorumQ
    uorumQuorumQuorumQuorumQuorumAutobiographerCriticCriticCitizen PatrolStewardQuor
    umQuorumQuorumQuorumQuorumAutobiographerConstituentCitizen PatrolCaucusQuorumQuo
    rumQuorumQuorumQuorumQuorumAutobiographerInvestorCriticConstituentQuorumQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorConstituentCleanupCaucusCleanupQuorumQuor
    umQuorumQuorumQuorumQuorumAutobiographerInvestorCleanupSupporterInformedQuorumQu
    orumQuorumQuorumAutobiographerCommentatorCriticInformedJongwareJongwareQuorumQuo
    rumQuorumQuorumAutobiographerCommentatorCriticInvestorJongwareJongwareQuorumQuor
    umQuorumQuorumAutobiographerFanaticInvestorCriticInformedCleanupQuorumQuorumQuor
    umQuorumQuorumQuorumDeputySupporterInvestorConstituentCaucusQuorumQuorumQuorumQu
    orumQuorumQuorumAutobiographerCriticInvestorCriticSupporterQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumAutobiographerInvestorInvestorCleanupQuorumQuorumQuorumQuor
    umQuorumQuorumQuorumQuorumCommentatorInvestorInvestorQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumCommentatorInvestorInvestorQuorumQuorumQuorumQuorumQu
    orumQuorumQuorumQuorumQuorumCommentatorInvestorCleanupStewardQuorumQuorumQuorumQ
    uorumQuorumQuorumQuorumQuorumCommentatorInvestorJongwareQuorumQuorumQuorumQuorum
    QuorumQuorumQuorumQuorumQuorumAutobiographerCleanupQuorumQuorumQuorumQuorumQuoru
    mQuorumQuorumQuorumQuorumQuorumAutobiographerSuffrageQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumAutobiographerDeputyQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumQuorumAutobiographerQuorumQuorumQuorumQuorumQuo
    rumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuorumQuoru
    

    你必须眯一点;在小尺寸看起来像这样:

    textvatar(tm)

    以下是我创建它的方式。

    第1步:找到合适的图像;

    第2步:转换为灰度;

    第3步:将灰色转换为极值。此步骤是为了确保输入范围(灰度值)使用0到255的整个范围。

    步骤4:调整图像大小以获得最佳效果。我选择了80x40,故意将图像压缩了一半。这是因为“文本”通常高于宽度。不同的字体需要不同的宽高比! 80将是每行的字符数,40是总行数。

    我使用Photoshop进行上述步骤,只是因为我不想为它编写代码。只要您可以访问原始图像数据,这并不困难或者其他什么,但这是一项很多工作而且并不有趣。

    中间步骤,放大400%,以便您可以看到像素:

    deformed grayscale image

    第5步:找到一个等宽的位图字体。我在网上的某个地方找到了一个不错的8x8。也许更大的可能更好,但只是非常小,因为限制因素是你的字符串,而不是字体。

    步骤6:计算每个ASCII字符的“灰色”值。这是黑色像素的数量除以总像素数。为了更好地传播,我将每个字符的结果除以找到的最大值,因此最低值为0(对于空格),最高值为1(恰好是M },但这取决于字体)。然后我将这些值乘以255,因此它模仿灰度值。最后,由于这些值与灰度图像中的值相反,我将其替换为255-value

    在我之间进行了大量测试,以确保我的初步想法仍然合理。这是使用简单的灰色到字符的翻译转储我的测试图像:

    0MMMMMM00000000000RDRRDDDDDDDDDDDDDDR#@RRRRR#00000RRR@RRRRR@RR@RRRRD&44&#00#0000
    MMMMMM000000000000RDRDDDDDDDDDDDDDDDR0####0R&&&&&&DR@RRR@#########RRDDD4@0000000
    MMM000#00000000000RDRRDDDDDDDDDDD&&&R00#000@&DR@####RR@#0000000##0#RD4PP&R@00000
    M000#0000000000000RDDDDDDDDDDD&D&&D&R###0000@#0000#@@##@@@@@##000000R&2FPP4R#000
    00###0000000000000RDDDDDDDDDDDDDD&&&D0000#@##@##00##@RDD&DRRRR#00000@R4FFP4PD@00
    00#000000000000000RDDDDDDDDDD&D&D&&&DRRRRDR@@@##00#R&4&44DDDRRR#0000##R&FPP4PRR@
    00##00#00000000000RDDDDDDDDDDD&&&&&&RDRRRRRRRR##@@RR&F4&RDDRR@@#0000000#&44&&4FD
    000000000000000000DDDDDDD&&&DD&&&D&&R##@RRRRRRRRRRRRD&DRD&44DD&RR@#00000RDDRR4F4
    000000000000000000RDDDDDDDRRDRDDD&DR@###@R&4&4444PP4DRRR&P22FF2FP&DRRRRRRRR@R4FD
    000000000000000000RRRRRRR@00@@R&&DRRRRRR@&P2$33*33*4RRRDP23$*33$$**333*$$2D#@4DR
    000000000000000000RRRRRRR@0000#DDRRRRRD&D4*$$%%ff3F&DRRR2$1%$$%11ff%ll1l;'IRDF&R
    000000000000000000RRR@#0#00000R4444DRRRR&3llf33$32PDRR&3Ii(i%fIlI1Il!ii/' .FF4DR
    0000000#0000000000#@@#0MM0M00#RP22*24DR4$l!!!I%*P4DDP31i===/lf1Illi((ii=;..*F4RR
    000000000000000000#@@##0M00000@F*$%*2PFflilllI1f3*2PF3fIi/=(lf$fIi/======;iF&P4R
    000000000000000000##@##00000000&3f$2F2*1i!ll1$2P4RD&4P*$$%!ii!I!ii/=/=;;;(*&R4FR
    000000000000000000#####00000000D%I3$$fflil!l1$3%3&RD2PP*$%1ll!lI1%f$3fI="1RRRRDR
    000000000000000000#####00000000Rf1f%II1IIl!l!!1%ff$*FFFF*%((lf**F4&D&PPFf2RRRRRR
    00000000000000000M#####0000000003!i11II11l!!!(ilIIl1f$f%I="=1FP4&@#R&DP22&RRR@#@
    0000000000000000000###0000000000#$i/iIIIl!!i=;"";===;""""";i12FFP4&4*4&*FRRRR@@R
    000000000000000000M000000000000000R4FF1l!i(=;"''"""""'...';/i$3$f$$33$$$4DRRRRRR
    000000000000000000000000000M00000000@21l(/ii/=;;=ilI;"'...'=;I%11f$$$ffP@@RR@R#0
    000000000000000000000000000M00000000&11!=/li(i!I%%Ii;... .";"!I!!I1ff$*R0#@#0000
    000000000000000000000000M0000M000000$lli=//=/i!lIi/l%I/""=//'=Iiiil%f$PR@#@00000
    000000000000000000000000M0M0M00000MRl!!!/=;;/l%fl!lI%3233$ff%11II%%f*2PP@##00000
    00000000000000000M000000M0MM00000003=illl!!iI%11%%f%f$32FF22$1%ff$f2DD4PR0000000
    00000000000000000M00M0#RRRRRRRRRRRPi/(lllI1I(=;=iI$2222FPFFP*$fff%FRR2322&R00000
    00000000000000000MM00#RRD&&&&&444*l/(i!ll!i!==/(il%$33*2FFF23$ff*4DDDF33*22&0000
    0000000000000000000000@R@@@@@#&f!((/i!!!lI!i=;;/!l1f32*3$$$ff$2&RR@###@##00##000
    0000000000000000#RRRR@@4F4R0R3!////(iii!!l%Ii=;"=l%f$333$ff%$4############00000#
    0000000000000000000000#@@@#0Di/ii(=/(i!!!lI%%1!(iI%$**$$fffF@0000000000000000000
    00000000000000000000000000000R3l((/((ii!lll!I%$3$f$$$$$3$f20M0000000000000000000
    000000000000000000000000000000#2l///((!!l!!i!!1%f%f$3$f%%fR000000000000000000000
    00000000000000#00000000000000000&l//(i!llllII1%%%1I1ff1I1&000000000000000000#00#
    M00000000000000000000000000000000R3l!!llII111%%%%%%f$$f%2000000000000000000RR00#
    0000#000000000000000000000000000000R*%1II111%%ffff$33fffR000000000000000000##00#
    0####000000000000000000000000000000M0RF3ff$$$fff$$33$ff&00000000000#000000##000R
    #00000000#00000000000000000000000000000R4FFFF22*****3fF00000000000000000000000@&
    00###000000000000000000000000000000000000@RRDD&&&4P*34#00000000000000000000000#R
    00000####000000000000000000000000000000000000##@RRDDR00000000000000M0000000000##
    00000000#000000000000000000000000000000000000000000000000000000000000000000000##
    

    这类似于您的平均图像到ASCII艺术转换器的输出。

    第7步:找到一个要使用的字符串列表。

    步骤8:从左上角开始,根据图像测试每个字符串的覆盖范围。打印最合适的,通过这个字符串的长度增加位置,重复直到完成。 (如果您不想重复,则此时从池中删除字符串。)

    第9步:获利!


    对于覆盖测试,我使用每个字符/像素的(source - dest)²之和除以字符串的长度:lower = better - 字符串和目标之间的最小差异。

    我在这里没有考虑漂亮的行结尾。如果一个单词完全填满一行,我尝试给出一个负面奖励,但输出的差异很小。它可能仍然适用于更大的字符串集。

    可能的改进是测试字符串的序列,即,而不是这里的贪婪方法,使用动态编程方法,就像Donald Knuth设计来决定自动换行文本中的最佳中断