[Question]
  [
I'm not sure if this is the right place to ask, but I found this similar [question](https://codegolf.stackexchange.com/questions/145391/how-can-i-shorten-this-python-code) so I'll go ahead.
I'm *very* new to code golfing, so keep your smothered laughs and throw-up emoji's to yourselves please ;). Anyway, someone recently posted a challenge (that was shortly deleted) to draw a 16x16 pixel image of the Old Man from the original Legend of Zelda, who gives you the wooden sword.
This guy:[![](https://i.stack.imgur.com/zwneX.png)](https://i.stack.imgur.com/zwneX.png)
Here's my code (643 characters):
```
from PIL import Image,ImageColor
g=ImageColor.getrgb
r=range
l=[list('0000033333300000000023233232000000003313313300000000331331330000000042333324000000042222222240000044220000224400044224222242244034424422224424433444442222444443344404422440444304440444444044400444044444404440004044444444040000004444444400000004433443344000'[i*16:i*16+16])for i in r(16)]
i=Image.new('RGB',(16,16),color='black')
for j in r(16):
    for k in r(16):
        t=k,j
        v=l[j][k]
        if v=='2':
            i.putpixel(t,g('white'))
        if v=='3':
            i.putpixel(t,g('#FFC864'))
        if v=='4':
            i.putpixel(t,g('red'))
i.show()
```
It's bad, I know. Anyway, anyone care to share some tips on shortening it?
  
[Answer]
I'm proposing a slightly new strategy. Instead of `Image.putpixel`, we use `Image.frombytes`, which creates an image directly from an encoded string of `RGB` values. The logic is similar to the `putpixel` version, but when implemented, it turns out to be considerably shorter:
### 406 bytes
```
from PIL import Image
x=b'\0\0\0',b'\xff\xff\xff',b'\xff\xc8\x64',b'\xff\0\0'
D='0000022222200000000012122121000000002202202200000000220220220000000031222213000000031111111130000033110000113300033113111131133023313311113313322333331111333332233303311330333203330333333033300333033333303330003033333333030000003333333300000003322332233000'
Image.frombytes('RGB',(16,16),b''.join(x[int(c)]for c in D)).show()
```
However, the compressed string `D` takes up almost half of the program! We can use [@ovs's](https://codegolf.stackexchange.com/users/64121/ovs) idea to "compress" it by storing it in a higher base (such as base 36). Now the code is almost half as long:
### 267 bytes
```
from PIL import Image
x=b'\0\0\0',b'\xff\xff\xff',b'\xff\xc8\x64',b'\xff\0\0'
D=int('MG8FMXO3ZANJ48JRXWYBSK3DF0HDWGJ34QP4XXAYS0EMXW3OJUIPDTNGOJGZIQZEKKSTFNJB1XQIAVDYAS8S06VLJVICO4STFK',36)
Image.frombytes('RGB',(16,16),b''.join(x[D>>2*c&3]for c in range(256))).show()
```
Finally, notice that the image is vertically symmetric. Knowing this, we can cut the size of our compressed string in half, with some overhead from the added logic. Along with some general golfing tricks, we arrive at a messy 223-byte solution:
### 222 bytes
```
from PIL import Image
Image.frombytes('RGB',[16]*2,b''.join(b'\0\xff\xff\xff\0\xff\xc8\0\0\xffd\0'[int('5VJ6J7FF7GD34HSPDCBV1SHKVG80MFVR3VX2RKU7WMRHBW0XZ4',36)>>2*(c//16*8+(c^-(c%16>7))%8)&3::4]for c in range(256))).show()
```
[Answer]
Splitting the string into rows of 16 and then using two nested loops to go over each pixel is taking a lot of bytes to do. It would be easier to just loop over the original string and use `(index%16,index//16)` to point at a specific row and column.
Also, instead of specifying a background color you can just draw every single pixel, which is shorter when using [hyper-neutrino's advice to use a list of colors](https://codegolf.stackexchange.com/a/225556/62393). You can also use `#000` and `#FFF` instead of `black` and `white` (1 byte shorter each).
Bonus tip: `(16,16)` can become `[16]*2` (1 byte shorter)
Combining this with [knosmos huge save by using data compression](https://codegolf.stackexchange.com/a/225560/62393) and [makonede's suggestion to use as imports](https://codegolf.stackexchange.com/a/225561/62393) we can get this down to 353 bytes:
```
import base64,zlib
from PIL import Image,ImageColor as C
i=Image.new('RGB',[16]*2)
for j in range(256):i.putpixel((j%16,j//16),C.getrgb(['#000','#000','#FFF','#FFC864','red'][int(zlib.decompress(base64.a85decode(b"Garp%d1+#J#QrG=W9sOr.gFe$difq+:dD#Fi'\\kVYS/be9`DBVETlH%2Un>#OH/p!dpQBq?eAD\\o?Ok%[FUW>EJ8;cLZ6ZbI2XaB#r3e")).decode("u8")[j])]))
i.show()
```
[Answer]
Just removing some whitespace, we can get:
```
from PIL import Image,ImageColor
g=ImageColor.getrgb
r=range
l=[list('0000033333300000000023233232000000003313313300000000331331330000000042333324000000042222222240000044220000224400044224222242244034424422224424433444442222444443344404422440444304440444444044400444044444404440004044444444040000004444444400000004433443344000'[i*16:i*16+16])for i in r(16)]
i=Image.new('RGB',(16,16),color='black')
for j in r(16):
    for k in r(16):
        t=k,j;v=l[j][k]
        if v=='2':i.putpixel(t,g('white'))
        if v=='3':i.putpixel(t,g('#FFC864'))
        if v=='4':i.putpixel(t,g('red'))
i.show()
```
(since you can inline the if statements, and putting two statements on one line with `;` saves bytes when you're in a block)
Then, you can collapse the repetitive `i.putpixel` by using a ternary `if-else`. Alternatively, you can just use a list to select the appropriate value:
```
from PIL import Image,ImageColor
g=ImageColor.getrgb
r=range
l=[list('0000033333300000000023233232000000003313313300000000331331330000000042333324000000042222222240000044220000224400044224222242244034424422224424433444442222444443344404422440444304440444444044400444044444404440004044444444040000004444444400000004433443344000'[i*16:i*16+16])for i in r(16)]
i=Image.new('RGB',(16,16),color='black')
for j in r(16):
    for k in r(16):
        t=k,j;v=int(l[j][k])
        if v>1:i.putpixel(t,g(['white','#FFC864','red'][v-2]))
i.show()
```
Basically, for `2`, `3`, and `4`, what this does is it uses a list, `['white', '#FFC864', 'red']` and selects the `v-2`th element from it.
[Answer]
You use the literal `16` 8 times. In python 3.8+, you can write `c:=16` and then `c` the other times:
```
i=Image.new('RGB',(c:=16,c),color='black')
```
[Answer]
Shave off 97 bytes from hyper-neutrino's answer by encoding the data with base85 and zlib:
```
import base64,zlib
from PIL import Image,ImageColor
g=ImageColor.getrgb
r=range
l=[list(zlib.decompress(base64.a85decode(b"Garp%d1+#J#QrG=W9sOr.gFe$difq+:dD#Fi'\\kVYS/be9`DBVETlH%2Un>#OH/p!dpQBq?eAD\\o?Ok%[FUW>EJ8;cLZ6ZbI2XaB#r3e")).decode("u8")[i*16:i*16+16])for i in r(16)]
i=Image.new('RGB',(16,16),color='black')
for j in r(16):
 for k in r(16):
  t=k,j;v=int(l[j][k])
  if v>1:i.putpixel(t,g(['white','#FFC864','red'][v-2]))
i.show()
```
[Answer]
**EDIT:** Turns out Python 2 doesn't have `base64.a85decode`, so this won't work. But you can still combine a b-string with an r-string, and combine that with [Leo's amazing tip](https://codegolf.stackexchange.com/a/225562/94066), and you've saved \$292\$ bytes.
```
import base64,zlib
from PIL import Image,ImageColor as C
i=Image.new('RGB',[16]*2)
for j in range(256):i.putpixel((j%16,j//16),C.getrgb(['#000','#000','#FFF','#FFC864','red'][int(zlib.decompress(base64.a85decode(br"Garp%d1+#J#QrG=W9sOr.gFe$difq+:dD#Fi'\kVYS/be9`DBVETlH%2Un>#OH/p!dpQBq?eAD\o?Ok%[FUW>EJ8;cLZ6ZbI2XaB#r3e")).decode("u8")[j])]))
i.show()
```
[Answer]
# ~~215~~ ~~210~~ ~~216~~ ~~210~~ 216 bytes
By using literal characters in place of some of the Unicode escapes from [dingledooper's 222 byte solution](https://codegolf.stackexchange.com/a/225566/94066), we can save a byte. ~~But by encoding the program in Latin-1, we can save 7!~~
**EDIT:** Saved 5 bytes thanks to [Jakque](https://codegolf.stackexchange.com/users/103772/jakque)!
**EDIT:** Python by default parses programs as UTF-8, so this won't work. You would need a magic comment `#coding:l1` on the first line, so this would actually end up having to add 11 bytes.
**EDIT:** Just tested on TIO, turns out I was wrong. 6 bytes have been regained!
**EDIT:** After some more testing with Bash to try and get the raw bytes in, I was in fact correct the first time. Back to 216.
```
from PIL.Image import*;frombytes('RGB',[16]*2,b''.join(bytes('\0ÿÿÿ\0ÿÈ\0\0ÿd\0','l1')[int('5VJ6J7FF7GD34HSPDCBV1SHKVG80MFVR3VX2RKU7WMRHBW0XZ4',36)>>2*(c//16*8+(c^-(c%16>7))%8)&3::4]for c in range(256))).show()
```
[Answer]
```
import PIL.Image, base64, zlib
s = b'c$}?~T@Jt?2!nfA54&42e`bR~6Cc(PgZQCUfkXDR5YV!&&a9D%ndJ9|Ir)dDC5CqM!KF%g^YH~{$pjovNiD-9`RpnztxNF;#WPO6@aBt?_fv%3QW0r-!$ZTqrT#L(OW41F%c&RU*cng'
i = PIL.Image.frombytes("RGB", (16,16), zlib.decompress(base64.b85decode(s)))
```
[Answer]
Instead of making a bunch of zeros, you probably could have made something like 0x8 and then parse it to display as 8 zeros. However I am not sure if that's any shorter.
]