Let's draw Mona Lisa

In 2014, demoscener Jakub 'Ilmenit' Debski released a 250-byte(1) procedural graphics demo for the Atari XL called Mona. It's drawing the following picture(2):

(1) Breakdown: 136 bytes of data + 114 bytes of code.
(2) The original picture is 128x96. The above version was magnified to 256x192. A few pixels differ from the original, but this is the expected output with the pseudo-code described in this challenge.

How?

This is . Although you're authorized to use any method, best results will most probably be achieved by using the original algorithm which is described below.

NB: This paragraph is not a specification but rather a general description. Please refer to the pseudo-code and the reference implementation for the details of the algorithm.

The image is made of 64 pseudo-random brush strokes (see this video), cycling through the following colors (in RRGGBB hexadecimal format):

COLOR = [ 0xFFE289, 0xE99E45, 0xA55A00, 0x000000 ]


The background is initially filled with the 4th color (black). Each stroke is shorter than the previous one.

The pseudo-random generator is using a Linear-Feedback Shift Register (LFSR) on a 32-bit integer initially set to 0x7EC80000 and XOR'ed with 0x04C11DB7.

Each stroke is initialized with a 16-bit value which overwrites the lowest bytes of the seed:

BRUSH = [
0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B,
0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2,
0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347,
0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051,
0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C,
0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7,
0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B,
0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139
];


These values are also used to set the new position (bx, by) of the brush at the beginning of the stroke: bx is given by the least significant byte and by is given by the most significant byte.

The direction of the stroke is given by bits #1 and #7 of the seed. (See the SWITCH statement in the pseudo-code.)

Pseudo-code

Below is the algorithm in pseudo-code, assuming 0-indexed arrays, where AND, OR and XOR mean bitwise operations.

seed = 0x7EC80000
dir = 0x00

FOR part = 0 TO 63
word = BRUSH[part]
seed = (seed AND 0xFFFF0000) OR word
bx = word AND 0xFF
by = (word >> 8) AND 0xFF

FOR len = 0 TO (64 - part) * 32 - 1
carry = seed AND 0x80000000
seed = (seed << 1) AND 0xFFFFFFFF

IF carry
seed = seed XOR 0x04C11DB7
dir = seed AND 0xFF
ENDIF

SWITCH dir AND 0x82
CASE 0x00:
by = (by + 1) AND 0x7F
ENDCASE
CASE 0x02:
bx = (bx + 1) AND 0x7F
ENDCASE
CASE 0x80:
by = (by - 1) AND 0x7F
ENDCASE
CASE 0x82:
bx = (bx - 1) AND 0x7F
ENDCASE
ENDSWITCH

drawPixel(bx, by, COLOR[part AND 3])
ENDFOR
ENDFOR


Reference implementation

Below is an ungolfed reference implementation in JavaScript.

const SEED    = 0x7EC80000,
XOR_MSK = 0x04C11DB7,
COLOR   = [
'#FFE289', '#E99E45', '#A55A00', '#000000'
],
BRUSH   = [
0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B,
0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2,
0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347,
0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051,
0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C,
0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7,
0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B,
0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139
];

var ctx = document.getElementById('output').getContext('2d'),
seed = SEED,
bx, by, word, len, carry,
dir = 0,
part;

ctx.fillStyle = COLOR[3];
ctx.fillRect(0, 0, 128 * 2, 128 * 2);

for(part = 0; part < 64; part++) {
word = BRUSH[part];
seed = (seed & 0xffff0000) | word;
bx = word & 0xff;
by = (word >> 8) & 0xff;

ctx.fillStyle = COLOR[part & 3];

for(len = 0; len < (64 - part) * 32; len++) {
carry = seed & 0x80000000;
seed <<= 1;

if(carry) {
seed ^= XOR_MSK;
dir = seed & 0xff;
}

switch(dir & 0x82) {
case 0x00:
by = (by + 1) & 0x7f;
break;

case 0x02:
bx = (bx + 1) & 0x7f;
break;

case 0x80:
by = (by - 1) & 0x7f;
break;

case 0x82:
bx = (bx - 1) & 0x7f;
break;
}
ctx.fillRect(bx * 2, by * 2, 2, 2);
}
}
<canvas id="output" width=256 height=192></canvas>

You can also see an animated version here.

Clarification and rules

• The output must be cropped to 128x96, even though the algorithm draws outside this area.
• If your language/platform is not able to output the exact colors described above, you must use colors that are as close as possible.
• Should you decide to use an alternate method, you still must generate the exact same output.
• Just in case: submitting the original 6502 assembly code or any slightly edited version is not allowed.
• Can you beat 250 bytes? Happy drawing!
• The "you're encouraged to" is problematic, because if doing so conflicts with saving bytes, should someone do so or not? It should either be "you must" (do it even if it costs bytes), or "you may" (do it only if it saves bytes). – user62131 Jun 16 '17 at 2:19
• Usually I think it's better to split the ascii option into another challenge, otherwise there are kind of 2 sub-challenges anyway. – FryAmTheEggman Jun 16 '17 at 2:33
• @FryAmTheEggman It was originally meant to be graphical output only and adding this ASCII option was probably a bad idea indeed. Hopefully I'm not ruining some WIP answer by removing it... – Arnauld Jun 16 '17 at 2:47
• @ATaco Paint Starry Nigh was a code-challenge with a different goal (reproducing the image as closely as possible). This one is plain kolmogorov-complexity with a constant output. – Arnauld Jun 16 '17 at 2:57
• That's understandable, Redacting my close vote. – ATaco Jun 16 '17 at 3:10

x86 opcode, 227224 223 Bytes

0000h: 68 20 A8 07 B8 13 00 CD 10 66 BF 40 00 C8 7E 5A
0010h: 89 FD BE 5B 01 AD 89 C7 89 E9 C1 E1 05 66 D1 E7
0020h: 73 09 66 81 F7 B7 1D C1 04 89 FA 80 E2 82 74 09
0030h: 7A 04 78 08 40 40 05 7F 7F 80 C4 02 FE CC 25 7F
0040h: 7F 89 EB 83 E3 03 8A B7 DB 01 88 E3 6B DB 40 01
0050h: C3 26 88 37 E2 C7 4D 75 BC EB FE 0A 03 BE 37 9B
0060h: 2F 2B 07 3C 0E 9B F5 91 8A 0B 1B BD 0E 78 93 3E
0070h: B8 5A B0 B5 70 80 02 B1 D0 D2 9C 93 20 9C 20 11
0080h: 3D D6 26 19 DF F5 97 A3 90 47 A3 F7 8A 59 08 AD
0090h: 29 2C A3 FC 7D 7D 0D 7A D5 51 30 31 D4 2B 54 42
00a0h: B2 14 B1 96 8A 14 29 F1 B0 2C 53 13 04 09 0A BB
00b0h: 3E 16 E9 77 18 E2 B8 72 AC C7 80 40 52 3C 8D AF
00c0h: 3E 63 AD 14 1E 3D B2 8F 23 7B C0 9D AF 2E 31 CE
00d0h: 96 A7 25 37 9E 44 2C B9 2B 39 21 43 00 06 42

0100 6820A8                 push A820
0103 07                     pop es
0104 B81300                 mov ax, 0013
0107 CD10                   int 10
0109 66BF4000C87E           mov edi, 7EC80040
010F 5A                     pop dx
0110 89FD                   mov bp, di
0112 BE5B01                 mov si, 015B
0116 89C7                   mov di, ax
0118 89E9                   mov cx, bp
011A C1E105                 shl cx, 05
011D 66D1E7                 shl edi, 01
0120 7309                   jnb 012B
0122 6681F7B71DC104         xor edi, 04C11DB7
0129 89FA                   mov dx, di
012B 80E282                 and dl, 82
012E 7409                   je 0139
0130 7A04                   jpe 0136
0132 7808                   js 013C
0134 40                     inc ax
0135 40                     inc ax
013C FECC                   dec ah
013E 257F7F                 and ax, 7F7F
0141 89EB                   mov bx, bp
0143 83E303                 and bx, 0003
0146 8AB7DB01               mov dh, [bx+01DB]
014A 88E3                   mov bl , ah
014C 6BDB40                 imul bx, 0040
0151 268837                 mov es:[bx], dh
0154 E2C7                   loop 011D
0156 4D                     dec bp
0157 75BC                   jne 0115
0159 EBFE                   jmp 0159
015B 0A03BE37...3921        brush_dw
01DB 43000642               color_db


Image:

• Would you mind including an explanation of this and a screenshot of the output - as it is it is not self explanatory – Taylor Scott Dec 28 '17 at 19:42
• Should I use a camera or a virtual environment, as I run it on full screen and no screen capture anymore – l4m2 Dec 29 '17 at 3:20
• – l4m2 Dec 29 '17 at 3:34
• 0122 6681F7B71DC104 xor edi, 00001DB7 bug found in W32Dasm – l4m2 Mar 9 '18 at 17:03

8086 Assembly - NASM (MBR) - 248 245 bytes

[org 0x7C00]
[bits 16]
push 0xA000
pop es
mov si, $brush xor cx, cx mov ax, 0x0013 int 0x10 mov ebx, 0x7EC80000 part_loop: lodsw mov bx, ax mov bp, 64 sub bp, cx shl bp, 5 mov sp, bp len_loop: shl ebx, 1 jnc not_carry xor ebx, 0x04C11DB7 mov dh, bl not_carry: and dh, 0x82 je dir_00 jpe dir_82 js dir_80 dir_02: inc al jmp dir_end dir_82: dec al jmp dir_end dir_00: inc ah jmp dir_end dir_80: dec ah dir_end: and ax, 0x7F7F cmp ah, 96 jae skip movzx di, ah movzx bp, al imul di, 320 add di, bp mov bp, cx and bp, 3 mov dl, byte[bp + color] mov [es:di], dl skip: dec sp jnz len_loop inc cx cmp cx, 64 jl part_loop jmp$

color:
db 0x43, 0x42, 0x06, 0x00

brush:
dw  0x030A, 0x37BE, 0x2F9B, 0x072B, 0x0E3C, 0xF59B, 0x8A91, 0x1B0B
dw  0x0EBD, 0x9378, 0xB83E, 0xB05A, 0x70B5, 0x0280, 0xD0B1, 0x9CD2
dw  0x2093, 0x209C, 0x3D11, 0x26D6, 0xDF19, 0x97F5, 0x90A3, 0xA347
dw  0x8AF7, 0x0859, 0x29AD, 0xA32C, 0x7DFC, 0x0D7D, 0xD57A, 0x3051
dw  0xD431, 0x542B, 0xB242, 0xB114, 0x8A96, 0x2914, 0xB0F1, 0x532C
dw  0x0413, 0x0A09, 0x3EBB, 0xE916, 0x1877, 0xB8E2, 0xAC72, 0x80C7
dw  0x5240, 0x8D3C, 0x3EAF, 0xAD63, 0x1E14, 0xB23D, 0x238F, 0xC07B
dw  0xAF9D, 0x312E, 0x96CE, 0x25A7, 0x9E37, 0x2C44, 0x2BB9, 0x2139

times 510 - (-) db 0 DB 0x55 DB 0xAA  • Oh hey, an answer that beats the score in the question (assuming an accurate byte count). Nice! – Draco18s Jun 21 '17 at 20:48 • Welcome to PPCG! wonderful first post. – Taylor Scott Jun 22 '17 at 18:50 • You can reduce to 245 bytes if you remove useless xor dx,dx and change mov bp,0xa000; mov es,bp to push 0xa000; pop es. – Ruslan Jun 23 '17 at 12:43 • It's not 8086. 8086 has no PUSH imm – l4m2 Dec 28 '17 at 16:15 • Basic optimize to 240 paste.ubuntu.com/26272648 – l4m2 Dec 28 '17 at 16:52 Excel VBA 32-Bit, 1011 720 Bytes Revision 49; ΔScore=291 Bytes Golfed Full Subroutine that takes no input and outputs the Mona Lisa to the ActiveSheet object on the range [A1:DX96]. There was a lot of black magic involved in golfing this down to its current state, - of note, some of the tricks involved are pixel art prep, bit shifting colors implicit type conversion, and base64 compression compressing bytes as a String. Sub M h Cells,0 t="5¼-™) :ó™ˆ"+vbTab+" »‘v¶<®Xn³"+chr(0)+"~Î¯šÐ ‘ š;ÔÝ•óŽ¡¡EˆõW'«¡*{ú {Óx.OÒ/R)°@¯ˆ”'®ïQ*<¹çu¶àªp~ÅP>‹:<­«a °;!¾y­›/,”Ì#¥œ5*B)· 7 s=4057*2^19 j=127 For p=0To 63 w=(Asc(Mid(t,2*p+1))+2)*256&+Asc(Mid(t,2*p+2))+2 s=s And-4^8Or w x=255And w y=255And w/2^8-.5 For l=1To(64-p)*32 c=s And-2^31 z=2^30And s s=(1073741823And s)*2 s=IIf(z,s Or-2^31,s)And-1 If c Then:s=79764919Xor s:d=255And s d=130And d y=IIf(d,IIf(d=128,y-1And j,y),y+1And j) x=IIf(d=2,x+1And j,IIf(d=130,x-1And j,x)) h[B2].Cells(y,x),Array(9036543,4562665,23205,0)(3And p) Next l,p h[97:999,DY:ZZ],0 End Sub Sub h(r,c) r.Interior.Color=c r.RowHeight=48 End Sub  Note: This solution has been restricted to 32-Bit versions of Excel VBA as ^ is the LongLong type literal in 64-Bit versions Note, The Second: The string is line 3 is not a comment as ” is not equivalent to " Output Gif showing ouput to the ActiveSheet when M is called in the VBE immediate window. Note that due to file size limitations this fig gif has fewer frames than actually produced. Ungolfed Ungolfed full subroutine that takes no input and produces the mona lisa using the method described above on the ActiveSheet object Option Private Module Option Compare Text Option Explicit Option Base 0 Public Sub MonaLisa() On Error GoTo 0 Dim part As Integer, _ length As Integer, _ M As Long, _ seed As Long, _ dir As Long, _ word As Long, _ carry As Long, _ bx As Byte, _ by As Byte, _ BRUSH, _ COLOR Let COLOR = Array(&H89E2FF, &H459EE9, &H5AA5, 0) Let BRUSH = Array( _ 778, 14270, 12187, 1835, 3644, 62875, 35473, 6923, _ 3773, 37752, 47166, 45146, 28853, 640, 53425, 40146, _ 8339, 8348, 15633, 9942, 57113, 38901, 37027, 41799, _ 35575, 2137, 10669, 41772, 32252, 3453, 54650, 12369, _ 54321, 21547, 45634, 45332, 35478, 10516, 45297, 21292, _ 1043, 2569, 16059, 59670, 6263, 47330, 44146, 32967, _ 21056, 36156, 16047, 44387, 7700, 45629, 9103, 49275, _ 44957, 12590, 38606, 9639, 40503, 11332, 11193, 8505) Let dir = 0 Let carry = 0 Let seed = &H7EC80000 Let Cells.Interior.Color = 0 Let Cells.ColumnWidth = 2 Call Range("A1:DX96").Select Let ActiveWindow.Zoom = True Call Range("A1").Select For part = 0 To 63 Step 1 Call VBA.DoEvents Let word = BRUSH(part) Let seed = (seed And &HFFFF0000) Or word Let bx = word And 255 Let by = Int(word / (2 ^ 8)) And 255 For length = 0 To (64 - part) * 32 - 1 Step 1 Let carry = seed And &H80000000 Let M = seed And &H40000000 Let seed = (seed And &H3FFFFFFF) * 2 If M <> 0 Then Let seed = seed Or &H80000000 Let seed = seed And &HFFFFFFFF If carry Then Let seed = seed Xor 79764919 Let dir = Int(seed And 255) End If Select Case dir And 130 Case 0: Let by = Int(by + 1) And 127 Case 2: Let bx = Int(bx + 1) And 127 Case 128: Let by = Int(by - 1) And 127 Case 130: Let bx = Int(bx - 1) And 127 End Select Let Cells(by + 1, bx + 1).Interior.Color = COLOR(part And 3) Next length Next part Let Range("97:999,DY:ZZ").Interior.Color=0 End Sub  • Hey, nice animation! – Arnauld Jun 20 '17 at 20:27 • @Arnauld, thanks :P it took more work than it should have – Taylor Scott Jun 21 '17 at 0:45 HTML + CSS + JavaScript (ES6), 499 bytes • HTML: 33 bytes • CSS: 17 bytes • JS: 678 ... 478 475 473 465 459 455 451 447 449 bytes It's nowhere near 250 bytes, but I'll definitely settle for under 500 bytes! Huge thanks to @Arnauld and @Firefly for helping me golf this monster down. with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x,y,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x=x+D&127:y=y+D&127 *{background:#000 <canvas id=C width=128 height=96> For a bigger scale, replace the CSS with the following: canvas { background: #000; image-rendering: pixelated; zoom: 3 }  Annotated History! I had a blast golfing Arnauld's reference code, and you can get some of that here. Enjoy! // One pass through Closure Compiler ADVANCED mode // Added with statement, golfed switch statement, golfed color array // I was surprised Closure Compiler didn't touch the switch statement, like, at least convert it into a bunch of conditional statements. with(C.getContext("2d")){e=2127036416;m=0;fillRect(0,0,256,256);for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e<<=1,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);} // Background moved to CSS with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e<<=1,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);} // e<<=1 same as e*=2 with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1);} // Semicolon with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=[778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505][n],e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // Failed to golf those colors down ;-; a=n=>["FFE289","E99E45","A55A00","000"][n&3] b=n=>"FFE289E99E45A55A00000".substr(n%4*6,6) c=n=>btoaQ6óÑ=ôN9@ÓM4ÓM4.substr(n%4*6,6) // <-- there are 2 unprintables somewhere in there A = [0,1,2,3] console.log(A.map(n=>a(n))) console.log(A.map(n=>b(n))) console.log(A.map(n=>c(n))) d=n=>FFE289 E99E45 A55A00 000.split [n&3] // Let's compress that hunky array of numbers... [778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505].map(n=>String.fromCharCode(n)).join ̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n) // And the char at n=20 became 65533 instead of 57113?? with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n),e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // Maybe try replacing that char with \u000? (Nope, editor doesn't like that at all) with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n)||57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // Okay, just check if n is 20 and make an exception. with(C.getContext("2d")){e=2127036416;m=0;for(n=0;n<64;n++)for(h=n-20?̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n):57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // Also, this could work too... (how to do byte comparison properly? Not so knowledgeable about encodings) +('0x'+btoaÓ}ß°DØ_AÓ½ÐMÂAðuÔÐ@C÷~üÍÄN@ï@yÓo4@uô öÛOwÛOBÜ=uÛ ú]}÷±y÷@7~;ð{ÓÎ}ÛÐ}ì1BÐ>ÃÀßNuõçn6]xðzÛÝxAuç}ÓwÐ =Ü@AÝz×ÎûÁ6.öó@»çn4ð=ÂÜ@>·ÔMxmÃÛNÁ_Cß]÷ Û;ôMûØ.8Ø}Û]ý.substr(n*4,4)) // ES6 template string syntax, easy-peasy. with(C.getContext2d){e=2127036416;m=0;for(n=0;n<64;n++)for(h=n-20?̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n):57113,e=e&4294901760|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&2147483648,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // 0x80000000 = 2147483648 = 2**31 = 1<<31 // 0x4C11DB7 = 2127036416 = 4057<<19 // 0xffff0000 = 4294901760 with(C.getContext2d){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n):57113,e=e&0xffff0000|h,p=[h>>8&255,,h&255],fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?p[i]--:p[i]++,fillRect(p[2]&127,p[0]&127,1,1)} // Turns out individual x and y vars were better with(C.getContext2d){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=0;k<32*(64-n);k++)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)} // Reverse loop k with(C.getContext2d){e=4057<<19;m=0;for(n=0;n<64;n++)for(h=n-20?̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖�韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","E99E45","A55A00","000"][n&3],k=32*(64-n);k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)} // Reverse loop n (wow!) // Side effects: string is reversed, 20th character becomes 43rd character, color array is reversed, and we must add 1 to n when used in the k loop with(C.getContext2d){e=4057<<19;m=0;for(n=64;n--;)for(h=n-43?ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1)} // Everything in the for loop to eliminate "with" brackets with(C.getContext2d)for(e=4057<<19,m=0,n=64;n--;)for(h=n-43?ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;)l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++,fillRect(x&127,y&127,1,1) // Use third argument of "for" with(C.getContext2d)for(e=4057<<19,m=0,n=64;n--;)for(h=n-43?ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["000","A55A00","E99E45","FFE289"][n&3],k=32*-~n;k--;fillRect(x&127,y&127,1,1))l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // Iterate 65 to 1 instead of 64 to 0; removes need to add 1 with -~ at cost of increasing string length by 1 with(C.getContext2d)for(e=4057<<19,m=0,n=65;n--;)for(h=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,e=e&0xffff0000|h,x=h&255,y=h>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=e&1<<31,e*=2,l&&(e^=79764919,m=e&255),j=m&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // Rename variables to be more aligned with original names // s = seed, d = direction, w = word with(C.getContext2d)for(s=4057<<19,d=0,n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&0xffff0000|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // s&0xffff0000|w same as s>>16<<16|w (@Arnauld) with(C.getContext2d)for(s=4057<<19,d=0,n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // d can be initialized to 65 (@Arnauld) with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // Much shorter way to calculate direction (@Arnauld) // j=d&130,i=j%4,2<j?i?x--:y--:i?x++:y++ // d&128?d&2?x--:y--:d&2?x++:y++ with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(s^=79764919,d=s&255),d&128?d&2?x--:y--:d&2?x++:y++ // "&255" of "d=s&255" isn't necessary now (@Arnauld) // s^=79764919,d=s&255 // d=s^=79764919 with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s>>16<<16|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),d&128?d&2?x--:y--:d&2?x++:y++ // s>>16<<16 same as s&~65535 (@FireFly) with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),d&128?d&2?x--:y--:d&2?x++:y++ // Even shorter way to calculate direction (@FireFly) // d&128?d&2?x--:y--:d&2?x++:y++ // D=d&128?-1:1,d&2?x+=D:y+=D with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))l=s&1<<31,s*=2,l&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D // Get rid of l (@Arnauld) // l=s&1<<31,s*=2,l&& // (s*=2)/2>>31&& with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8&255,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D // "&255" isn't necessary y=w>>8&255 (@Arnauld) with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x&127,y&127,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x+=D:y+=D // x and y are constrained within 255 only upon direction change, making the drawing invalid; constraining every time fixes it. (@Arnauld) // x+=D:y+=D // fillRect(x&127,y&127,1,1) // x=x+D&127:y=y+D&127 // fillRect(x,y,1,1) with(C.getContext2d)for(s=4057<<19,d=n=65;n--;)for(w=n-44? ℹ⮹ⱄ鸷▧雎ㄮ꾝쁻⎏눽Ḕ굣㺯贼剀胇걲룢ᡷ㺻ਉГ匬냱⤔誖넔뉂含퐱け핺ൽ緼ꌬ⦭࡙諷ꍇ那韵�⛖㴑ₜₓ鳒킱ʀ炵끚렾鍸ຽᬋ誑฼ܫ⾛㞾̊.charCodeAt(n):57113,s=s&~65535|w,x=w&255,y=w>>8,fillStyle="#"+["FFE289","000","A55A00","E99E45"][n&3],k=32*n;k--;fillRect(x,y,1,1))(s*=2)/2>>31&&(d=s^=79764919),D=d&128?-1:1,d&2?x=x+D&127:y=y+D&127 • Nice job and thanks for sharing the history! – Arnauld Jun 16 '17 at 14:49 • @Arnauld Glad to take the challenge! – darrylyeo Jun 16 '17 at 15:56 Befunge, 1131 1052 bytes "Dq~"1+00g"Ot"0"-R"0003"7/"727*"E1"5*\2*39*27*"\1"3*\2*:8-"ph"2*2\"N"2*" =&~a"v v *83+"k~>"*524\*2"XS)"*2"E"-1:*2"YT"*2"j0"\+94*3"G}"+"%~)"8*2\+"%~E"-7:+" w"+< >"V\"2*\2*"@"2*"R/"3*">~/"+56*"Y"2*"##"2*\5*"1K"2*"%O"2*",+!_"2*25*\"{ "+"+<{"v v"/~Y"+"y~G"+"%~"*5"1"*55*2"k"+98+9:*3"1"*2\*3";i"*2\+"7~@Z>x"*3"?"+92+" q"+" "< >+",~"2*"}zQ1+BK"2*45*\45*",~s"+\25*9+9"~="+29+2*"wq"2*"r~I"+"@<c#"5*\45*"=o "+v v_,#!>#:<"P3 128 96 127"_v+" k":p39+1:%*:*82<<0<<<\*5"%9D7"+")~"*2"g."+" }{"< #@_:63p"@d~"03p2*13p043p0v^_:"@"%\"@"/p93g28*:*+^>\04>1-:93p3g2*+:v>g+\%:v>:"_" _3*55+,:2g.:1+2g.2+2g.1+v_:48**\1-:83p\83g:1g:23p\0v |:g39\0p3g39<3v4\+4<^+1< v0:\%4g++77/"@"\%"@":::<^!:$_\73g>0#p0#33g#:#g^#< _$!#v_28*:*::0^>/2%8*-03p:v
">\:88vv%"@":\g38:\<_\73p\1-:!^v4:%\+g32::p31-*2+%2\*"@"% 4/"@":\++"C~":%\+g31:<
~v<\%*<>\"@"/77++p\0^!-g36:%**<>5*9++\:4/8%4*\2%+2*-23p:3 3g+\%:"="3*+\033g28*v
">88*/7v>g!+53g2-!-153g2%+28*8^v2\0\%2/2+*:*82:g34+*:*82<p34p33:-*2++%8\*+88< 8
^-1p++7<^35+*:*28\%**8*28-%2g35>#<*#2+#-:#!5#-3#3p#g1#3-#5!#+< >8+#:/#\4#*%#*^#<


There are a number of issues that make this a challenging problem in Befunge:

1. Befunge has only got 2000 bytes of memory to work with (and that includes the source code), so there is no way we can render the entire image into memory before outputting it. The way I work around this is by repeatedly running the algorithm 96 times, once for each line. Each run stores just the pixels that are needed for the current line, which are then output at the end of the run. This allows us to get by with a pixel buffer of just 128 bytes.

2. Befunge has no bit operations whatsoever. Many of the AND operations can simply be emulated with a modulo operator (e.g. a AND 0x7F can be replaced with a % 0x80). However, the XOR requires some rather complicated bit manipulation, which we have to deal with one byte at a time, using a set of custom formulas hardcoded to handle the four bytes we need. For example, to calculate a XOR 0xC1, we use the formula: a + 0xC1 - (a/64%4*64 + a%2)*2

3. While not a limitation of Befunge per se, the interface on TIO is incapable of handling extended ASCII characters in the source, which would have been the easiest way to store the brush and colour tables. I work around this by generating those tables as a list of numbers on the stack, then have a little initialisation loop that copies the values from the stack to memory. A significant chunk of my time was spent golfing this table, which takes up the first five and half lines of code.

Unfortunately, despite all my effort to make the code compatible with TIO, and my choice of a file format that could be extracted from TIO (PPM), it's just too slow to complete within the 60 second time limit (running the algorithm 96 times probably doesn't help). But since it generates the image line by line, you should still get enough of the output to recover nearly half the image.

Try it online!

If you don't have a local PPM file viewer, you can easily convert to another format using one of the many online converters. One example being Convertio.

• Probably not the easiest tool for the job. Well done! – Arnauld Dec 25 '17 at 11:56

Python 3, 544536523519 518 bytes

from tkinter import*
s=32456<<16
d=0
b="#000"
a=Canvas(Tk(),w=128,he=96,bg=b)
a.pack()
for p in range(64):w=ord("̊㞾⾛ܫ฼誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖\udf19韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ㺻ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝ㄮ雎▧鸷ⱄ⮹ℹ"[p]);s=s&~65535|w;*e,=divmod(w,256)[::-1];exec("c=s&8<<28>0;s=s*2^79764919*c;d=[d,s&255][c];e[d&2<1]=e[d&2<1]+(d&128<1)*2-1&127;a.create_line(*e,e[0]+1,e[1]+1,f=['#FFE289','#E99E45','#A55A00',b][p&3]);"*(64-p)*32)


This is a further golfed-down version of CCB60's Python translation of the reference implementation. I originally used a large hex number to represent the brush of the algorithm, but I later realized that my unfounded assumption that a Unicode string representation wouldn't work in Python was false.

I originally thought my byte count was significantly lower, but as ASCII-only pointed out, I didn't remember to count the Unicode characters as more than one byte.

Output (128 x 96)

Identical to CCB60's output.

• This is 518 bytes, not 396 – ASCII-only Jun 20 '17 at 2:17
• @ASCII-only I forgot to count the Unicode characters as more than one byte. Oof. No wonder the byte count seemed so low... – notjagan Jun 20 '17 at 2:43

Java 7, 681677675626612 610 bytes

Object l(){BufferedImage g=new BufferedImage(128,96,1);String b="̊㞾⾛
ܫ\u0E3C\uF59B誑ᬋຽ鍸렾끚炵ʀ킱鳒ₓₜ㴑⛖\udf19韵那ꍇ諷࡙⦭ꌬ緼ൽ핺け퐱含뉂넔誖⤔냱匬Гਉ
㺻\uE916ᡷ룢걲胇剀贼㺯굣Ḕ눽⎏쁻꾝\u312E雎▧鸷ⱄ\u2BB9ℹ";for(int
s=0x7EC80000,d=0,x,y,z=130,u,w,c,r=255,t=127,p=0,o;p<64;p++)
{w=b.charAt(p);s=s&0xFFFF0000|w;x=w&r;y=(w>>8)&r;for(o=0;o<(64-p)*32;o++)
{c=s&0x80000000;s<<=1;if(c!=0){s^=0x4C11DB7;d=s&r;}x=(u=d&z)==2?x+1&t:u==z?
x-1&t:x;y=u==0?y+1&t:u==128?y-1&t:y;if(x<128&y<96)g.setRGB(x,y,new int[]
{0xFFE289,0xE99E45,0xA55A00,0}[p&3]);}}return g;}


Outputs the following image in resolution 128x96:

I know it is not even near 250 bytes but hey it's java

-2 bytes thanks to Zacharý

• Well hey, it appears that no-one has welcomed you to PPCG, so hi, and welcome to PPCG! Nice post, I only have two formatting recommendations for you 1, the header is, for the sake of having leaderboards supposed to be of the format #Language, <s>Old Scores</s> Score Bytes and 2 you can make your code a bit more readable by adding in a language flag of the form <!-- language-all: lang-java --> before your code block – Taylor Scott Jun 18 '17 at 15:14
• Hey thank you for welcoming me :)! I've now edited my post with the improvements you proposed. – Twometer Jun 18 '17 at 15:17
• No problem @Twometer,it looks great and hope you enjoy your golfing – Taylor Scott Jun 18 '17 at 15:18
• Two bytes can be shaved: 0x04C11DB7 => 0x4C11DB7 and 0x7f => 127. Don't go hex crazy when it's not needed. – Zacharý Jul 18 '17 at 13:02
• I love that “but hey it’s Java” – Jack Sep 15 '17 at 18:35

C#, 960 850 bytes

using System.Drawing;_=>{var m = new Bitmap(128,96);Graphics.FromImage(m).FillRectangle(Brushes.Black,0,0,128,96);for(int s=0x7EC80000,d=0,p=0,w,x,y,l,c,t,n=127;p<64;++p){w=new[]{778,14270,12187,1835,3644,62875,35473,6923,3773,37752,47166,45146,28853,640,53425,40146,8339,8348,15633,9942,57113,38901,37027,41799,35575,2137,10669,41772,32252,3453,54650,12369,54321,21547,45634,45332,35478,10516,45297,21292,1043,2569,16059,59670,6263,47330,44146,32967,21056,36156,16047,44387,7700,45629,9103,49275,44957,12590,38606,9639,40503,11332,11193,8505}[p];s=s>>16<<16|w;x=w&255;y=w>>8&255;for(l=0;l++<(64-p)*32;){c=(int)(s&0x80000000);s*=2;if(c!=0){s^=79764919;d=s&255;}t=d&130;x=t==2?(x+1)&n:t==130?(x-1)&n:x;y=t<1?(y+1)&n:t==128?(y-1)&n:y;if(x<=n&y<96)m.SetPixel(x,y,Color.FromArgb((int)new[]{0xFFFFE289,0xFFE99E45,0xFFA55A00,0xFF000000}[p&3]));}}return m;}


A straight forward copy of the pseudo code with some golfing added in. There is still a lot that can be golfed but I wanted to post my answer to get the ball rolling.

Full/Formatted version:

using System.Drawing;

class P
{
static void Main()
{
System.Func<object, Bitmap> f = _ =>
{
var m = new Bitmap(128, 96);
Graphics.FromImage(m).FillRectangle(Brushes.Black, 0, 0, 128, 96);

for (int s = 0x7EC80000, d = 0, p = 0, w, x, y, l, c, t, n = 127; p < 64; ++p)
{
w = new[] { 778, 14270, 12187, 1835, 3644, 62875, 35473, 6923, 3773, 37752, 47166, 45146, 28853, 640, 53425, 40146, 8339, 8348, 15633, 9942, 57113, 38901, 37027, 41799, 35575, 2137, 10669, 41772, 32252, 3453, 54650, 12369, 54321, 21547, 45634, 45332, 35478, 10516, 45297, 21292, 1043, 2569, 16059, 59670, 6263, 47330, 44146, 32967, 21056, 36156, 16047, 44387, 7700, 45629, 9103, 49275, 44957, 12590, 38606, 9639, 40503, 11332, 11193, 8505 }[p];
s = s >> 16 << 16 | w;
x = w & 255;
y = w >> 8 & 255;

for (l = 0; l++ < (64 - p) * 32;)
{
c = (int)(s & 0x80000000);
s *= 2;

if (c != 0)
{
s ^= 79764919;
d = s & 255;
}

t = d & 130;

x = t == 2 ? (x + 1) & n : t == 130 ? (x - 1) & n : x;
y = t < 1 ? (y + 1) & n : t == 128 ? (y - 1) & n : y;

if (x <= n & y < 96)
m.SetPixel(x, y, Color.FromArgb((int)new[] { 0xFFFFE289, 0xFFE99E45, 0xFFA55A00, 0xFF000000 }[p & 3]));
}
}

return m;
};

f(null).Save("monaLisa.jpg");
}
}

• var m = new Bitmap(128,96) AE IU WAUGH WY – CalculatorFeline Jun 18 '17 at 2:59
• @CalculatorFeline I don't understand? – TheLethalCoder Jun 18 '17 at 14:38
• Possible because of the unneeded spaces? – Zacharý Jun 18 '17 at 19:30

Python 2.7; 880 876 bytes total (including data)

-4 bytes to 876 thanks to ZacharyT. (My python interpreter did not like his suggestion to drop the spaces between the 80s and else).

Taylor Scott's suggestion to put the brush into Base 10 is excellent, but notjagan (in a comment) took his suggestion one step further, using python's extended integer format in hex. notjagan's answer is in Python 3, and is such an improvement from what I did that he deserves credit. I hope he'll post it as a separate answer.

Output into a Tkinter window. Without scaling, the image is very small, but scaling adds about a dozen bytes to the count.

B=[0x030A,0x37BE,0x2F9B,0x072B,0x0E3C,0xF59B,0x8A91,0x1B0B,
0x0EBD,0x9378,0xB83E,0xB05A,0x70B5,0x0280,0xD0B1,0x9CD2,
0x2093,0x209C,0x3D11,0x26D6,0xDF19,0x97F5,0x90A3,0xA347,
0xD431,0x542B,0xB242,0xB114,0x8A96,0x2914,0xB0F1,0x532C,
0x0413,0x0A09,0x3EBB,0xE916,0x1877,0xB8E2,0xAC72,0x80C7,
0xAF9D,0x312E,0x96CE,0x25A7,0x9E37,0x2C44,0x2BB9,0x2139]
s=0x7EC80000
d=0x00
from Tkinter import *
m=Tk()
a=Canvas(m,w=128,he=96,bg='black')
a.pack()
for p in range(64):
w=B[p];s=(s&0xFFFF0000)|w;x=w%256;y=w/256
for t in range((64-p)*32):
c=s&0x80000000;s=(s<<1)&0xFFFFFFFF;
if c:s=s^0x04C11DB7;d=s&0xFF
if d&2:x=(x+(-1if d&0x80 else 1))&0x7f
else:y=(y+(-1if d&0x80 else 1))&0x7f
a.create_line(x,y,x+1,y+1,f=['#FFE289','#E99E45','#A55A00','#000000'][p&3])
mainloop()


There's not much going on here except translation into Python and some basic golfing. Sometimes bit-wise manipulations are shorter, sometimes integer math. I could not find a way to pack more of the logic into lists or arrays. The basic algorithm is already pretty dense.

• Just a formatting tip, you can make your code be a bit more readable by adding language specific highlighting using prettify.js . For python this flag, which should be added before you code block(s), looks like <!-- language-all: lang-py --> – Taylor Scott Jun 18 '17 at 15:16
• You don't need the space between the 80's and the else's. And, 0x00 is the same as 0, right? – Zacharý Jun 18 '17 at 19:26
• And you can remove the space between import and *. – Zacharý Jun 18 '17 at 19:30
• Got it down to 641 bytes by switching to Python 3 and making some general golfing improvements. – notjagan Jun 18 '17 at 21:57
• Shaved off one more byte to 640. – notjagan Jun 18 '17 at 22:04

808815816819826839840843

Still the loser, but I had to do it! may be I can golf it more later!

Not the loser now!

rename set S
rename expr E
pack [canvas .c -w 130 -he 98 -bg #000]
.c cr i 67 51 -i [S I [image c photo -w 128 -h 96]]
S s 0x7EC80000
S d 0
time {S s [E $s&0xFFFF0000|[S w 0x[lindex {. 30A 37BE 2F9B 72B E3C F59B 8A91 1B0B EBD 9378 B83E B05A 70B5 280 D0B1 9CD2 2093 209C 3D11 26D6 DF19 97F5 90A3 A347 8AF7 859 29AD A32C 7DFC D7D D57A 3051 D431 542B B242 B114 8A96 2914 B0F1 532C 413 A09 3EBB E916 1877 B8E2 AC72 80C7 5240 8D3C 3EAF AD63 1E14 B23D 238F C07B AF9D 312E 96CE 25A7 9E37 2C44 2BB9 2139} [incr p]]]] S x [E$w&255]
S y [E $w>>8] time {S c [E$s&1<<31]
S s [E $s<<1] if $c {S s [E s^79764919] S d [E s&255]} switch [E d&130] {0 {S y [E y+[S h 1&127]]} 2 {S x [E x+h]} 128 {S y [E y-h]} 130 {S x [E x-h]}} I p #[lindex {FFE289 E99E45 A55A00 000} [E p-1&3]] -t x y} [E (65-p)*32]} 64  Tcl/Tk, 1370 Very ungolfed transliteration of the Pseudo-code before the golfing spree began! The update line makes possible to view the drawing being done progressively! pack [canvas .c -w 130 -he 98 -bg #000] .c create i 67 51 -i [set p [image create photo -w 128 -h 96]] set COLOR {FFE289 E99E45 A55A00 000000} set BRUSH { 0x030A 0x37BE 0x2F9B 0x072B 0x0E3C 0xF59B 0x8A91 0x1B0B 0x0EBD 0x9378 0xB83E 0xB05A 0x70B5 0x0280 0xD0B1 0x9CD2 0x2093 0x209C 0x3D11 0x26D6 0xDF19 0x97F5 0x90A3 0xA347 0x8AF7 0x0859 0x29AD 0xA32C 0x7DFC 0x0D7D 0xD57A 0x3051 0xD431 0x542B 0xB242 0xB114 0x8A96 0x2914 0xB0F1 0x532C 0x0413 0x0A09 0x3EBB 0xE916 0x1877 0xB8E2 0xAC72 0x80C7 0x5240 0x8D3C 0x3EAF 0xAD63 0x1E14 0xB23D 0x238F 0xC07B 0xAF9D 0x312E 0x96CE 0x25A7 0x9E37 0x2C44 0x2BB9 0x2139} set seed 0x7EC80000 set dir 0x00 set part 0 while {part<64} { set word [lindex BRUSH part] set seed [expr (seed&0xFFFF0000)|word] set bx [expr word&0xFF] set by [expr word>>8] set len 0 while {len<[expr (64-part)*32]} { set carry [expr seed&0x80000000] set seed [expr seed<<1] if$carry { set seed [expr$seed^0x04C11DB7]
set dir [expr $seed&0xFF] } switch [expr$dir&0x82] {
0 {
set by [expr $by+1&0x7F] } 2 { set bx [expr$bx+1&0x7F]
}
128 {
set by [expr $by-1&0x7F] } 130 { set bx [expr$bx-1&0x7F]
}
}

$p put #[lindex$COLOR [expr $part&3]] -to$bx $by incr len update } incr part }  Python 3 + matplotlib, 541 from pylab import* B='ਃ븷鬯⬇㰎鯵醊ଛ봎碓㺸媰땰耂뇐튜錠鰠ᄽ혦᧟ꎐ䞣夈괩ⲣﱽ納竕儰㇔⭔䊲ᒱ隊ᐩⱓጄऊ묾ᛩ眘犬잀䁒㲍꼾掭ᐞ㶲輣節鶯⸱캖ꜥ㞞䐬뤫㤡' s=32456<<16 d=0 i=zeros((256,256),'I') for p in range(64): W=ord(B[p]);w=W>>8|W%256<<8;s=s&65535<<16|w;x=[w>>8,w&255] for l in range((64-p)*32): s*=2 if s>>32:s=d=s^4374732215 a=(-1)**(d>>7);b=d>>1&1;x[b]=x[b]+a&127;i[(*x,)]=[9036543,4562665,23205,0][p&3] imsave('i',i.view('4B')[:96,:128,:3])  This saves the image as a png file "i". To display the image you can replace the imsave with an imshow and a show for 545 bytes. SmileBASIC, 454447 444 bytes DIM C[5]C[1]=-7543C[2]=-1466811C[3]=-5940736S=32456<<16FOR P=-63TO.W=ASC("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"[-P])S=W+(S>>16<<16)C[4]=127AND W C[0]=W>>8FOR L=0TO 31-P*32O=S S=S<<1IF O<0THEN S=79764919XOR S:D=130AND S T=D*2AND 4C[T]=127AND C[T]-(D>>6)+1GPSET C[4],C[0]+144,C[3AND P]NEXT NEXT  The string of "x"s had some invalid unicode characters, so I'm not able to post it here. Here are the character codes in decimal (just the BRUSH array in reverse): 8505, 11193, 11332, 40503, 9639, 38606, 12590, 44957, 49275, 9103, 45629, 7700, 44387, 16047, 36156, 21056, 32967, 44146, 47330, 6263, 59670, 16059, 2569, 1043, 21292, 45297, 10516, 35478, 45332, 45634, 21547, 54321, 12369, 54650, 3453, 32252, 41772, 10669, 2137, 35575, 41799, 37027, 38901, 57113, 9942, 15633, 8348, 8339, 40146, 53425, 640, 28853, 45146, 47166, 37752, 3773, 6923, 35473, 62875, 3644, 1835, 12187, 14270, 778 • You posted an image of the output, would it be possible to post an image of the contents of the "xx...xx" string? – Taylor Scott Mar 16 '18 at 3:41 • Most of the characters don't actually have symbols defined for them, so it really does look like "xxxxxxxxxxx". I can get a list of the character codes though. – 12Me21 Mar 16 '18 at 15:19 • That actually might be helpful - I think I may be able to use a similar method with yabasic - oh, you already did it - coolio – Taylor Scott Mar 16 '18 at 17:07 • It's not very space efficient since (at least in UTF-8) most of those are saved as 3 or more bytes. But it's still better than hex and you might be able to shorten the decoder too. – 12Me21 Mar 16 '18 at 17:19 :r4, 764 bytes the source for run in :r4 github ^r4/lib/gui.txt #c$FFE289 $E99E45$A55A00 $000000 #b$37BE030A $072B2F9B$F59B0E3C $1B0B8A91$93780EBD $B05AB83E$028070B5 $9CD2D0B1$209C2093 $26D63D11$97F5DF19 $A34790A3$08598AF7 $A32C29AD$0D7D7DFC $3051D57A$542BD431 $B114B242$29148A96 $532CB0F1$0A090413 $E9163EBB$B8E21877 $80C7AC72$8D3C5240 $AD633EAF$B23D1E14 $C07B238F$312EAF9D $25A796CE$2C449E37 $21392BB9 :m pick2 +$7f7f and dup $7f and over 8 >> 96 >? ( 2drop ; ) setxy ink@ a! ; :s +? ( 2* ; ) 2*$4c11db7 xor rot drop dup 24 << 31 >> 1 or over $2 and 2 << 8 xor << rot rot ; :d$100 $7ec80000 0 ( 64 <? )( dup$3 and 2 << 'c + @ ink dup >r 2* 'b + w@ $ffff and swap$ffff0000 and over or 64 r@ - 5 << ( 1? )( >r s swap m swap r> 1- ) drop nip r> 1+ ) 3drop ;
: cls d show 'exit >esc< ;


I use a trick for make the move without conditionals, transform bit 8 in sign and shift with bit 2. version with stack names:

| PHREDA 2017
| https://codegolf.stackexchange.com/questions/126738/lets-draw-mona-lisa
^r4/lib/gui.txt

#color  $FFE289$E99E45 $A55A00$000000
#brush [
$030A$37BE $2F9B$072B $0E3C$F59B $8A91$1B0B
$0EBD$9378 $B83E$B05A $70B5$0280 $D0B1$9CD2
$2093$209C $3D11$26D6 $DF19$97F5 $90A3$A347
$8AF7$0859 $29AD$A32C $7DFC$0D7D $D57A$3051
$D431$542B $B242$B114 $8A96$2914 $B0F1$532C
$0413$0A09 $3EBB$E916 $1877$B8E2 $AC72$80C7
$5240$8D3C $3EAF$AD63 $1E14$B23D $238F$C07B
$AF9D$312E $96CE$25A7 $9E37$2C44 $2BB9$2139 ]

:movxy | dir seed bxy -- dir seed bxy
pick2 + $7f7f and dup$7f and
over 8 >>
96 >? ( 2drop ; )
setxy ink@ a! ;

:step | dir bxy seed -- dir bxy seed
+? ( 2* ; )
2* $4c11db7 xor rot drop dup 24 << 31 >> 1 or over$2 and 2 << 8 xor <<
rot rot ;

:draw
$100 | dir$7ec80000 | seed
0 ( 64 <? )(
dup $3 and 2 << 'color + @ ink dup >r 2* 'brush + w@$ffff and | dir seed brush
swap $ffff0000 and over or | dir bxy seed 64 r@ - 5 << ( 1? )( >r | dir bxy seed step swap movxy swap r> 1- ) drop nip r> 1+ ) 3drop ; : cls draw show 'exit >esc< ;  Yabasic, 790 779 bytes An answer that takes no input and outputs to a new graphics window. Open Window 128,96 j=127 s=4057*2^19 k=255 For p=-1To 63 Color Mid$("255,226,137233,158,069165,090,0000,0,0",1+And(3,p)*11,11)
If p<0Then Fill Circle 0,0,k:p=0Fi
s=Or(And(-4^8,s),w)
x=And(k,w)
y=And(w/2^8,k)
For l=1To(64-p)*32
c=And(-2^31,s)
z=And(2^30,s)
s=And(1073741823,s)*2
t=s
If z Then t=Or(s,-2^31)Fi
s=And(-1,t)
If c Then s=Xor(79764919,s):d=And(k,s)Fi
d=And(130,d)
If d=0Then y=And(y+1,j)Fi
If d=2Then x=And(x+1,j)Fi
If d=128Then y=And(y-1,j)Fi
If d=130Then x=And(x-1,j)Fi
Dot x,y
Next
Next


Output

The below is scaled by a factor of 8