jaytea's big text

By jaytea on Aug 17, 2011

Image

/*
{

A new take on the whole 'big text' idea.

This one lets you select your own fonts as
well as add control codes to format text,
then generates the ASCII required to display
the big text on the fly.

To use:

  • Use the popup to launch the dialog.
  • Enter text in the embedded window at the top.
  • Click 'Go!' to generate the ASCII 'art'.

    From there, you can click 'Preview' to see
    how it would look as an IRC message, or click
    '/clipboard' to copy the necessary code to
    your clipboard so you can then paste it
    wherever you like.

    Note:

    Some fonts use a variety of colours in order
    to make characters look smooth, a technique
    called 'anti-aliasing'. These colours are
    not necessarily found in the 4-bit colour
    palette you use in IRC messages, but this
    script will attempt to approximate and choose
    the best fitting colours in these cases.

    For any questions or suggestions feel free
    to swing by #mSL on irc.swiftirc.net and drop
    me a message.

}
*/

/*
{

  /bt_convert <width> <height>

  Takes data from a picwin, formats it, and adds it to a
  hidden window.

  So far, all it does is maps coloured pixels in the picwin
  onto their corresponding mIRC colour in hex format, with
  an approximation using Euclidean distance if one doesn't
  exist. In the future, this could be expanded to allow for
  more interesting designs, such as big letters composed of
  smaller versions of themselves, etc.

}
*/

alias bt_convert {
  if ($window(@bt_text)) window -c $v1
  if ($hget(bt_convert)) hfree bt_convert
  window -h @bt_text
  hmake bt_convert

  var %i, %j, %colours, %fg, %bg, %line, %dot, %approx, %tmp

  %j = 0

  ; Set %fg and %bg to the RGB integer values of the foreground (normal text) colour
  ; and window background colour

  %fg = $colour($colour(normal))
  %bg = $colour($colour(background))

  ; Fill %colours with a list of RGB integers values for all colours 0 to 15

  while (%j < 16) {
    %colours = %colours $colour(%j)
    inc %j
  }

  %j = 0

  ; $2 = height
  ; Loop through each row of pixels of the picture in @bt_pic

  while (%j < $2) {

    %i = 0
    %line =

    ; $1 = width
    ; Loop through each column of pixels

    while (%i < $1) {

      ; Get the RGB integer value of the pixel at (%i, %j)

      %dot = $getdot(@bt_pic, %i, %j)

      ; Try to determine if that pixel is normal text (fg), part of the
      ; background (bg) or otherwise try to fit it onto one of the other
      ; colours in the colour palette.

      :findDot

      ; See if the current pixel's colour is exactly equal to bg.
      ; Use 'I' (invisible) as its placeholder in %line. 
      if (%dot == %bg) {
        %line = %line $+ I
      }

      ; See if the current pixel's colour is equal to fg.
      ; Use 'N' (normal) as its placeholder.
      elseif (%dot == %fg) {
        %line = %line $+ N
      }

      ; Otherwise, see if the current pixel is somewhere in our
      ; colour palette. 
      ; If so, its placeholder will be a single hex digit from
      ; 0-F depending on its position in %colours (which is its
      ; position in the palette)
      elseif ($findtok(%colours, %dot, 32)) {
        %line = %line $+ $base($calc($v1 - 1), 10, 16)
      }

      ; If the current pixel is not in the colour palette, as a
      ; background/foreground colour or otherwise, then we must
      ; try to find the closest match to it in the palette.

      ; Save approximations in a hash table named 'bt_convert'

      else {

        ; Check if the approximation has been saved before

        if ($hget(bt_convert, %dot) != $null) %dot = $v1
        else {

          ; Otherwise, calculate it and save it.

          %tmp = $bt_approx(%dot, %colours)
          hadd bt_convert %dot %tmp
          %dot = %tmp
        }

        ; Now that we have our approximation in %dot, go back
        ; up and test again.

        goto findDot
      }
      inc %i

    }

    aline @bt_text $iif(%line == $null, $str(I, $1), %line)
    inc %j

  }

  ; Remove empty lines. An empty line should be detected when the
  ; whole line is the same colour whilst ignoring trailing invisible
  ; ('I') colours.

  while ($regex($line(@bt_text, 1), /^([^N])\1*I*$/)) dline @bt_text 1

  %i = 1
  %j = $line(@bt_text, 0) - 1

  ; Now remove empty lines from the end (save for one).

  while (%j) && ($regex($line(@bt_text, %j), /^([^N])\1*I*$/)) {
    dline @bt_text %j
    dec %j
  }

}

; $bt_approx(<colour>, <list of colours>)
alias -l bt_approx {
  var %i, %in, %distance, %closest, %list

  %i = 1
  %in = $rgb($1)
  %list = $2

  ; Loop through each member of %list checking calculating the distance
  ; between them and the given colour.

  while ($rgb($gettok(%list, %i, 32))) {

    ; Suppose %in = A,B,C and $v1 = X,Y,Z 

    tokenize 44 %in $+ , $+ $v1

    ; The distance between %in and $v1 (given colour and current list member
    ; is then sqrt((A - X)^2 + (B - Y)^2 + (C - Z)^2)

    ; This is an equivalent calculation to determining the distance between
    ; two points in 3d.

    ; !>= %distance could be < %distance if not for the fact that %distance
    ; begins at $null, and (N < $null) is false for all numerical N.

    if ($calc(($1 - $4) ^ 2 + ($2 - $5) ^ 2 + ($3 - $6) ^ 2) !>= %distance) {
      %distance = $v1
      %closest = %i
    }
    inc %i
  }

  return $gettok(%list, %closest, 32)
}

/*
{

  /bt_prepare

  Prepares the lines added by /bt_convert for use on IRC.

  It is expected that each line of @bt_text is comprised of
  characters denoting either normal (N) or invisible (I) text
  as well as hex characters 0 to F for each of the 16 colours
  presently supported by mIRC.

  This alias is also subject to change in the future, but it is 
  not worth implementing anything more abstract at this time.

}
*/

alias bt_prepare {
  if ($window(@bt_text)) {
    var %i = 1, %line, %n = $line(@bt_text, 0)

    ; Delete the last line if it's 'empty' (see /bt_convert)

    if ($regex($line(@bt_text, %n), /^([^N])\1*I*$/)) dline @bt_text %n

    while ($line(@bt_text, %i)) {

      ; With each line, replace the longest contiguous series of the same character
      ; with a block of coloured text.

      ; The nature of this block is defined by $format().

      %line = $regsubex($v1, /(?!^)I+$|((.)\2*)/g, $format(\2, $len(\1)))

      ; potential future optimizations

      rline @bt_text %i %line
      inc %i

    }
  } 
}

alias -l format {

  ; R is for reverse (highlighted) text.

  if ($1 == R) return $+($chr(22), $str($chr(160), $2), $chr(22))

  ; For everything else, map the symbol ('N' = normal, etc.) onto
  ; the correct colour code.

  ; Then return a series of spaces (chr160) with foreground and background
  ; colour corresponding to the given symbol.

  if ($2) && ($map($1) >= 0) return $+($chr(3), $v1, $chr(44), $v1, $str($chr(160), $2))

}

alias -l map {
  var %n = $1 I
  goto %n

  :N
  return $colour(normal)

  :I
  return $colour(background)

  :%n
  return $base($1, 16, 10)
}

menu channel,status,menubar,query {
  jaytea's big text:{ dialog $iif($dialog(bt), -v, -m) bt bt_main }
}

dialog bt_main {
  title "jaytea's big text"
  size -1 -1 296 346

  text "Font:", 1, 42 100 35 12
  text "<font>", 2, 85 100 72 12
  text "Size:", 3, 42 120 35 12
  text "<size>", 4, 85 120 72 12
  button "Go!", 5, 128 158 84 30
  button "Choose font...", 6, 170 106 108 24
  edit "", 7, 10 200 280 100, multi read autovs
  button "Preview", 8, 10 308 58 24
  button "/clipboard", 9, 72 308 58 24
  button "Exit", 10, 236 308 50 24, ok
  check "3D text", 11, 42 146 110 12
}

on *:dialog:bt:init:*:{
  window -aoBedw0j1 +bL @bt_edit 0 0 280 75
  echo @bt_edit type here!
  ; dialog -v bt
  bt_fontdetails
  did -c bt 11
  .timerbt_checkpos -om 0 25 bt_checkpos
  .timerbt_checkpos -e
}

on *:dialog:bt:active:*:{
  if ($dialog(bt).active) {
    if ($window(@bt_edit).state == hidden) {
      bt_showEdit
    }
  }
  elseif ($active != @bt_edit) {
    bt_hideEdit
  }
}

; "Choose font"
on *:dialog:bt:sclick:6:{
  .timerfont 1 0 bt_font
}

; "Go!"
on *:dialog:bt:sclick:5:{
  bt_convert $bt_drawtext($did(2), $did(4), $$editbox(@bt_edit))
  window -c @bt_pic

  if ($did(11).state) bt_3d

  bt_prepare
  filter -cwo @bt_text bt 7
}

; "Preview"
on *:dialog:bt:sclick:8:{
  if ($window(@bt_text)) {
    window -aedCw0 @bt_preview -1 -1 $calc($window(-1).w - 100) 500

    var %i = 1, %stamp = $+(<, $me, >)

    while ($line(@bt_text, %i)) {
      echo -t @bt_preview %stamp $v1
      inc %i
    }
  }
}

; "/clipboard"
on *:dialog:bt:sclick:9:{
  clipboard $line(@bt_text, 1)

  var %i = 2

  while ($line(@bt_text, %i)) {
    clipboard -a $crlf $+ $v1
    inc %i
  }
}

; $bt_drawtext(<font>, <fontsize>, <text>)
alias bt_drawtext {
  if ($window(@bt_pic)) window -c @bt_pic

  window -Bphd @bt_pic
  drawtext -p @bt_pic $colour(normal) $qt($1) $2 0 0 $3

  return $width($3, $1, $2, 1) $height($3, $1, $2)
}

alias -l bt_font {
  window -aj1 @bt_edit
  font
  dialog -v bt
  bt_fontdetails
}

alias -l bt_fontdetails {
  did -ra bt 2 $window(@bt_edit).font
  did -ra bt 4 $window(@bt_edit).fontsize
}

on *:appactive:{
  if (!$appactive) && ($window(@bt_edit)) {
    bt_hideEdit
  }
}

alias -l bt_hideEdit {
  window -hj1 @bt_edit
  .timerbt_checkpos -p
}

alias -l bt_showEdit {
  window -ow0j1 @bt_edit
  .timerbt_checkpos -r
}

on *:dialog:bt:close:*:{
  while ($window(@bt_*, 1)) window -c $v1
  .timerbt_checkpos off
}

alias -l bt_checkpos {
  if ($$window(@bt_edit).x $window(@bt_edit).y != $calc($dialog(bt).x + 10) $calc($dialog(bt).y + 30)) {
    window -j1 @bt_edit $v2
  }
}

on *:keydown:@bt_edit:*:{
  .timer 1 0 if ($replace($editbox($active),$chr(32),$chr(160)) = $!null) dline @bt_edit 1 $(|) aline @bt_edit $!$v1
}

; --------------------------- FUN STUFF ---------------------------

/*
{

  /bt_3d

  This command should follow /bt_convert.

  It reformats the encoded picture in @bt_text
  and creates a 3d effect.

  Might optimize this in the future.

}
*/

alias bt_3d {

  if ($hget(bt_3d)) hfree bt_3d
  hmake bt_3d

  hadd bt_3d 0 F
  hadd bt_3d 1 E
  hadd bt_3d 2 C
  hadd bt_3d 3 9
  hadd bt_3d 4 5
  hadd bt_3d 5 4
  hadd bt_3d 6 D
  hadd bt_3d 7 8
  hadd bt_3d 8 7
  hadd bt_3d 9 3
  hadd bt_3d A B
  hadd bt_3d B A
  hadd bt_3d C 2
  hadd bt_3d D 6
  hadd bt_3d E F
  hadd bt_3d F E
  hadd bt_3d N E

  var %i = 1, %line, %j, %width, %coord, %n

  while ($line(@bt_text, %i)) {
    hadd bt_3d line $+ %i $v1 
    inc %i
  }

  %n = %i - 1
  dec %i 2
  %width = $len($hget(bt_3d, line1)) - 2

  while (%i) {

    %j = %width

    while (%j) {
      if ($coord(%i, %j) != I) {
        %coord = $v1
        if ($coord(%i + 1, %j + 1) == I) $coord(%i + 1, %j + 1, $hget(bt_3d, %coord))

        ; Extra shadow pixel, looks better without it but you may uncomment it and
        ; decide for yourself:

        ; if ($coord(%i + 1, %j + 2) == I) $coord(%i + 1, %j + 2, $hget(bt_3d, %coord))
      }
      dec %j
    }
    dec %i
  }

  while (%n) {
    rline @bt_text %n $hget(bt_3d, line $+ %n)
    dec %n
  }

  hfree bt_3d
}

alias -l coord {
  var %1 = $calc($1), %2 = $calc($2), %line = $hget(bt_3d, line $+ %1)
  if ($0 == 2) return $mid(%line, %2, 1)
  hadd bt_3d line $+ %1 $+($mid(a %line, 2, %2), $3, $right(%line, - $+ %2))
}

Comments

Sign in to comment.
dma   -  Dec 30, 2015

outragous

 Respond  
PackardBell   -  Jun 12, 2013

super script!
but can someone add a !bigtext command?

 Respond  
eyiezinc   -  May 09, 2012

'Definitely a 10!

 Respond  
troll   -  Sep 10, 2011

nice 3d text

hi im nasa wanna job?

 Respond  
jaytea   -  Sep 10, 2011

finally added comments!

also added a new 3d text option (see new screenshot)

 Respond  
troll   -  Sep 07, 2011

advanced as fuck

 Respond  
jaytea   -  Aug 20, 2011

In your description why didn't you use the img tags an add the image instead of a link?

i tried, but i must have used the wrong format since i was just able to embed the image.

the preview was not a 'sneak preview', it was just a way to permanently host a screenshot of the script.

Mind commenting the 2 aliases? I'm very interested in how it works

sure, i'll do that at some point today :P

I've just realized this snippet has a potential to be utilized for malicious purposes, disrupting the chat and all that.

spammers gonna spam. i don't expect this script will convert anyone from being a contributing member of a channel to someone who floods it with malicious intent.

 Respond  
Jethro   -  Aug 20, 2011

:P maybe it was the other way around. But what do we expect? jaytea's avatar is Hannibal Lecter...

 Respond  
napa182   -  Aug 20, 2011

lol @ big spoiler

 Respond  
Jethro   -  Aug 20, 2011

napa182, it was a sneak preview, but then jaytea posted the snippet not long after, which was sort of a big spoiler.

 Respond  
napa182   -  Aug 19, 2011

Nice snippet jaytea. 9/10 +Like
In your description why didn't you use the img tags an add the image instead of a link?

 Respond  
FelicianoX   -  Aug 19, 2011

@Dani, I don't understand how this works either :S

 Respond  
Jethro   -  Aug 18, 2011

I've just realized this snippet has a potential to be utilized for malicious purposes, disrupting the chat and all that.

 Respond  
syrusmx   -  Aug 18, 2011

Brilliant. Now I have an entirely new way to annoy people in spam channels. <3

 Respond  
Dani_l11   -  Aug 18, 2011

Mind commenting the 2 aliases? I'm very interested in how it works

 Respond  
Jordyk19   -  Aug 18, 2011

Holly mIRC That's nice!
'Definitely a 10!

 Respond  
Veritas   -  Aug 18, 2011

Damn Jaytea, very nice work, 10+Like O

 Respond  
ProIcons   -  Aug 17, 2011

well a pretty well coded snippet as always...
of course 10...
i didn't expect something not cool from you ;)

 Respond  
Jethro   -  Aug 17, 2011

:P awwwww jaytea has let his funky side run rampant finally! No doubt, 10 from me as well.

 Respond  
GrimReaper   -  Aug 17, 2011

Very nice code Jaytea.. I saw it when you had finished it and was wondering what the code would look like..

to me it's well coded.. Also I love the way that the Preview button works. :)

Get's a like and 10 from me!

dma  -  Apr 21, 2015
Sign in to comment

Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.