[Question]
  [
I think the ASCII art questions on PPCG are fun to do, but personally I think it can be pretty hard, especially when the question is tagged as [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'").
I wonder if anyone here might have some tips that will be useful for producing ASCII art.
Simply arranging characters is easy, but with (short) algorithms, things will become more complicated.
I'm talking about ASCII art like: 
* Text to ASCII art (characters)
* Images (logos or icons)
I'm just looking for general tips, but language-specific is allowed since most of them can be translated anyhow.
  
[Answer]
## Compression algorithms
You can apply LZMA compression to the string.  
Many languages support it.
## Run-length encoding
You can use processing instructions such as `[char][number]` (e.g. `b12`).  
This compression algorithm is used here: <https://codegolf.stackexchange.com/a/20589/10920>
Further reading: <http://en.wikipedia.org/wiki/Run-length_encoding>
## Integer packing
You can use arrays of integers to store small shapes such as:
```
// This is an invader!
// (SE line height makes it looks awful)
// ~158 characters
    ##          ##    
      ##      ##      
    ##############    
  ####  ######  ####  
######################
##  ##############  ##
##  ##          ##  ##
      ####  ####       
```
Each space will be translated into a `0`.  
Each sharp will be translated into a `1`.
```
// ~58 characters
// Saved ~100 bytes!
[
  196656,  49344,   262128,  999228,
  4194303, 3407859, 3342387, 62400
]
```
Each bit is then read using bitwise operator `&`.
The above algorithm could be improved by using a bigger integer base:
```
// ~44 characters
// Integers are in base 36.
// Use `_` as a separator (or a line break).
"47qo_122o_5m9c_lf0c_2hwcf_211ir_1zn03_1c5c"
```
[Answer]
## Look for symmetry
Sometimes the required ASCII art is symmetric at some point. For example, [Argyle ASCII Art](https://codegolf.stackexchange.com/questions/56032/argyle-ascii-art) requires an output similar to this:
```
    /\        /\
   /  \  /\  /  \
/\/    \/  \/    \/\
\/\    /\  /\    /\/
   \  /  \/  \  /
    \/        \/
```
One could just print this normally, but depending on the language, the code required can be shortened by only generating the top half of the result, reversing it and swapping `/` and `\`.
## Try transposing
In [ASCII Art Archery Arrows](https://codegolf.stackexchange.com/questions/54682/ascii-art-archery-arrows) the result to print is this, scaled to a given `n`:
```
     /\
    /  \
   /    \
  /      \
  \      /
   \____/
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
    |  |
   /|  |\
  / |  | \
 /  |  |  \
/   |  |   \
/   |  |   \
/   |__|   \
/  /    \  \
/ /      \ \
//        \\
/          \
```
If we take a look at the arrow, we can see there's 8 kinds of lines:
```
/ \
\ /
\_/
| |
/ | | \
/ |_| \
/ / \ \
/ \
```
Let's try the same for its transpose.
```
                         ///////
                        /     / 
   /\                  /     /  
  /  \                /     /   
 /   _||||||||||||||||||||||    
/    _                     _    
\    _                     _    
 \   _||||||||||||||||||||||    
  \  /                \     \   
   \/                  \     \  
                        \     \ 
                         \\\\\\\
```
Here, there are 10 kinds of lines.
```
/
/ /
/ \ / /
/ _|
/ _ _
\ _ _
\ _|
\ / \ \
\ \
\
```
But here's the catch: the bottom 5 are identical to the top 5, except for swapping `/` and `\`. As per the previous rule, you can first generate the first 5, copy, do the swap, and finally transpose to get the arrow. This can save a lot of code.
[Answer]
# Control characters, escape sequences and console codes
Unless the question forbids them, [the current consensus on Meta](http://meta.codegolf.stackexchange.com/a/5515) is that ASCII art challenges do not require a specific byte stream, but output that looks correct.
This means that we can use [ASCII control characters](https://en.wikipedia.org/wiki/Control_character#In_ASCII), [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code) and [Linux console codes](http://man7.org/linux/man-pages/man4/console_codes.4.html) in our answers, assuming a supporting terminal.
Unless specified otherwise, the rest of this answer will explain the behavior of Linux terminals, which is what I have available for testing right now.
### ASCII control characters
Support/interpretation varies from terminal to terminal and character to character. The most portable one ought to be the linefeed (`\n`, `\x0a`), which moves the character to the beginning of the next line.
Other useful characters include:
* The vertical tab (`\v`, `\x0b`) moves the cursor one position to the right, then one position down.
```
$ echo -e 'a\vb'
a
 b
```
* The carriage return (`\r`, `\x0d`) moves the cursor to the beginning of the *current* line. Any subsequent printable character will overwrite the first character of the current line.
```
$ echo -e 'ab\rc'
cb
```
* The backspace (`\b`, `\x08`) moves the cursor one position to the left. Any subsequent printable character will overwrite the character before the backspace.
```
$ echo -e 'ab\bc'
ac
```
* The escape (`\e`, `\x1b`) does nothing on its own, but forms part of ANSI escape sequences (optionally) and Linux console codes.
Many languages permit actual control characters in the source code.
### ANSI escape sequences
(yet to come)
### Linux console codes
While there are many more, the most useful console codes for ASCII art are probably these:
* The sequence `\ec` will *reset* the terminal. This clears the screen, moes the cursor the upper left corner and sets fore- and background color, cursor blinking rate, etc. to their default values.
* The sequence `\eM` causes a *reverse linefeed*, i.e., the cursor will move one position up.
```
$ echo -e '\na\eMb\n'
 b
a
```
* The sequence `\eH` sets the *tab stop* at the current column.
```
$ echo -e '   \eHa\n\tb'
   a
   b
```
[Answer]
## Look for patterns
This one might be a bit obvious, but... look for patterns, similarities and repetitions in the output. For instance, when I saw the [Transform number into 7-segment display pattern](https://codegolf.stackexchange.com/questions/19196/transform-number-into-7-segment-display-pattern) task I started thinking about how one could golf it, and started looking for similarities. Due to the way the horizontal segments go between the vertical ones in the character matrix it'd probably be easiest to deal with three segments at a time, grouped together as such (adding two "always empty" segments for the first, topmost one):
![segments groping](https://i.stack.imgur.com/06X47.png)
Thus, you could do something like `lc + " "*N + rc + "\n"` N-1 times and then `lc + bc*N + rc` once, for every three segments (`lc`, `bc`, `rc` being the left-, bottom-, and right-segment characters, i.e. one of `|`, `_` or ).
[Answer]
# Use base conversion
[This answer](https://codegolf.stackexchange.com/a/53432/20080) was to a question which wanted ASCII art which consisted of the characters `+ |-` and newlines. Since there are only 5 possible characters, these can be treated as a base 5 number and converted to bytes, packing 3.45 characters per byte.
# Exploit regularities
Often, the data will have some regularities, even if those regularities aren't strong enough to employ specific tools such as mirroring. For instance, in the above question, the desired output had newlines roughly evenly spaced throughout the test, since the text was roughly rectangular. I exploited this to shorten my code, by using Pyth's split into n pieces function, then joining on newlines.
# Know your tools, and choose the right one for the job.
The most powerful and efficient text processing tools I know are:
Regex engines: `///`, Retina, Perl, in order of power/conciseness tradeoff.
Use if the thing you want to do can be conscisely described in regex substitutions, such as [this answer](https://codegolf.stackexchange.com/a/57195/20080)
Obscure text-processing tools: gema, etc. (I'm sure there are others, but they're too obscure)
Use if they have a feature that is exactly what you need, that nothing else has. Such as in [this question](https://codegolf.stackexchange.com/a/52977/20080), with gema's recursive matching.
General code golfing languages: CJam, Pyth, etc.
Use if you're exploiting some subtlety complex enough that no other tool will do the job or it just does the job shorter.
# Try many approaches
This applies in every code-golf question, but especially here. You're not going to know whether a regularity is exploitable until you try it out. Possibly in multiple languages.
]