23
\$\begingroup\$

Good Afternoon,

Your goal is to, in the least amount of source code bytes, recreate any of Piet Mondrian's 'Composition' paintings (for instance, Composition #10).

The recreation can either use the actual colors, or replace it with the appropriate colours from the Windows Default 16 Color Palette.

Your recreation can be outputted in PNG, BMP or NetPBM, either to a file or to STDOUT, or directly to the screen.

Your recreation must be a resolution of 512x512 or higher.

Your recreation must not access the internet. If your program requires data files, then their size will be added to the size of your source.

Your score will be the size of your source file in bytes.

Please state with your entry which painting you're recreating, and provide a link to the original and a picture of your recreation.

Good Luck.

\$\endgroup\$
  • \$\begingroup\$ Step one: find a language with a built-in PNG, BMP or NetPBM encoder. \$\endgroup\$ – John Dvorak Sep 21 '13 at 5:02
  • 6
    \$\begingroup\$ Relevant: Piet \$\endgroup\$ – Griffin Sep 21 '13 at 10:56
  • 4
    \$\begingroup\$ It's a difficult language to work in... every now and then I attempt to do a Quine outputting NetPBM... but yeah. I'll be very impressed if anybody can recreate Piet Mondrian in Piet! \$\endgroup\$ – lochok Sep 21 '13 at 14:56
  • 2
    \$\begingroup\$ Can we output character art using terminal color escapes and block drawing characters? (eg. ▃▃▌) Or is this best posed as a different challenge? \$\endgroup\$ – Tobia Feb 2 '14 at 15:13
  • 2
    \$\begingroup\$ @lochok I would offer a bounty for a Piet answer if anybody was seriously interested in trying. \$\endgroup\$ – Jerry Jeremiah Feb 10 '17 at 3:08
14
\$\begingroup\$

Tikz, 175 bytes

Composition III in Black and White, 175 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz{\def\b{;\draw[line width=}\def\a{)--(}\clip(1,1\a1,5\a5,5\a5,1)\b2mm](0,4\a6,4\a6,3\a4,3)\b1mm](4,0\a4,5);}\end{document}

Verify it in the Blogosphere

This is perhaps one of Mondrian's most minimalistic works and I am surprised no one has found it yet. It is not however particularly interesting so I have included several other paintings in my answer.

Explanation

There is a bit of a wrapper that is associated with every tikz answer. The wrapper is:

\documentclass[tikz]{standalone}\begin{document}\tikz{
}\end{document}

Once you get past the wrapper there are a few \def statements that save bytes but unfortunately obfuscate the code:

\def\b{;\draw[line width=}\def\a{)--(}

If we make all the proper substitutions our code comes out looking like:

\clip(1,1)--(1,5)--(5,5)--(5,1);
\draw[line width=2mm](0,4)--(6,4)--(6,3)--(4,3);
\draw[line width=1mm](4,0)--(4,5);

The first bit is a \clip and is very important, but we will skip over it for the time being.

Now we draw the first line on the blank canvas, This line is rather thick so we use [line width=2mm] to set the thickness to 2mm:

\draw[line width=2mm](0,4)--(6,4)--(6,3)--(4,3);

This connects a couple of nodes and produces this shape:

Next we \draw a second stroke, however this stroke is thinner so we have to set the line thickness to 1mm:

\draw[line width=1mm](4,0)--(4,5);

Now our painting looks like:

This is close to the original but not quite, so here is where the \clip comes into play. We use the \clip to remove all the extra lines from our canvas and set the canvas to the correct size. With the canvas resized we get the image:

Composition III in Black and White


Composition With Yellow Patch, 214 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz[line width=2mm]{\clip(1,1)rectangle(7,7);\draw(0,8)rectangle(4,3.5)rectangle(6.5,1.2)rectangle(4,0);\draw[fill=yellow](6.5,3.5)rectangle(8,2.5);}\end{document}

Evaluate it in CyberSpace

Explanation to come


Composition II in Blue and Yellow, 225 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz[line width=2mm]{\clip(1,1)rectangle(7,10);\draw(8,9)rectangle(3,6)rectangle(0,0);\draw[fill=yellow](0,0)rectangle(3,2);\draw[fill=blue](0,11)rectangle(3,9);}\end{document}

Assess it over the Webbernetz!

Explanation to come


Composition B (No. 2) in Red, 232 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz[line width=2mm]{\clip(1,1)rectangle(10,13);\draw[line width=1mm](1.2,5)--(1.2,9);\draw[fill=red](0,14)rectangle(5,9);\draw(0,9)rectangle(11,5)(7,0)rectangle(5,14);}\end{document}

Attempt it within the Internet!

Explanation

First here is the code with line breaks inserted to make it more readable:

\documentclass[tikz]{standalone}
\begin{document}
\tikz[line width=2mm]{
\clip(1,1)rectangle(10,13);
\draw[line width=1mm](1.2,5)--(1.2,9);
\draw[fill=red](0,14)rectangle(5,9);
\draw(0,9)rectangle(11,5)(7,0)rectangle(5,14);
}
\end{document}

The first command of interest is

\draw[fill=red](0,14)rectangle(5,9);

This draws a red rectangle with a black outline. For the upper left hand corner of the painting.

We then draw two more rectangles with white interiors and black outlines to create the grid pattern on the painting

\draw(0,9)rectangle(11,5)(7,0)rectangle(5,14);

We then draw in a thin line

\draw[line width=1mm](1.2,5)--(1.2,9);

And crop the image to the proper size

\clip(1,1)rectangle(10,13);


Composition II in Red, Blue and Yellow, 251 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz[line width=1mm]{\clip(1,1)rectangle(9,9);\draw[fill=yellow](8.5,6)--(0,6)--(8.5,6)--(8.5,2)rectangle(10,0);\draw[fill=red](3,3)rectangle(10,10);\draw[fill=blue](0,0)rectangle(3,3);}\end{document}

Test it upon the World Wide Web!

Explanation

First I will insert some line breaks to make my code readable

\documentclass[tikz]{standalone}
\begin{document}
\tikz[line width=1mm]{
\clip(1,1)rectangle(9,9);
\draw[fill=yellow](8.5,6)--(0,6)--(8.5,6)--(8.5,2)rectangle(10,0);
\draw[fill=red](3,3)rectangle(10,10);
\draw[fill=blue](0,0)rectangle(3,3);
}
\end{document}

The first line of importance is:

\draw[fill=yellow](8.5,6)--(0,6)--(8.5,6)--(8.5,2)rectangle(10,0);

This draws the following shape:

This strange shape is the yellow rectangle in the lower right corner and the two lines that are no the edge of a colored rectangle. Next we insert the red square and cover up the extra lines made by the last shape:

\draw[fill=red](3,3)rectangle(10,10);

This comes out looking like:

Now we insert our blue square:

\draw[fill=blue](0,0)rectangle(3,3);

Now all that is left is to crop out all the unnecessary parts of the image using a \clip

\clip(1,1)rectangle(10,10);

Composition II in Red, Blue and Yellow


Composition II, 308 bytes

\documentclass[tikz]{standalone}\begin{document}\tikz[line width=2mm]{\clip(1,1)rectangle(12.6,13);\draw(0,0)rectangle(10,4)rectangle(2,12)--(0,12);\draw[fill=red](10,1.6)rectangle(14,0);\draw[fill=yellow](6,12)rectangle(10,14);\draw[fill=blue](0,4)rectangle(2,8);\fill(10,10)rectangle(14,14);}\end{document}

Check it out on the Information-Super-Highway

Explanation to come

\$\endgroup\$
12
\$\begingroup\$

Mathematica 202 287 bytes.

Just For Fun! 330 bytes: Mondrian with "Boogie Woogie" in Its Title

Column[{"Boogie Woogie", Grid[{{"",i["",b->Red],\[SpanFromLeft]},{"",\[SpanFromAbove],\[SpanFromBoth]},{i["",b->Blue],"",""},{\[SpanFromAbove],\[SpanFromAbove],i["",b -> Yellow]}},Dividers->{{2->t@5,3->t@6},{2->t@9,3->t@7,4->t@6}},ItemSize->{{1->3,2->9,3->1},{1->6,2->6,3->2,4->2}}]},Alignment->Center]

enter image description here


Actual Submission [287 bytes]

\[SpanFromLeft] and similar expressions take up roughly 85 bytes. In mathematica each such expression has its dedicated one character symbol.

t=Thickness;b=Background;i=Item;
Grid[{{"",i["",b->Red], \[SpanFromLeft]},{"",\[SpanFromAbove],\[SpanFromBoth]},{i["",b->Blue],"",""},{\[SpanFromAbove],\[SpanFromAbove],i[ "",b->Yellow]}},
Dividers->{{2->t@5, 3->t@6},{2->t@9,3->t@7,4->t@6}},ItemSize->{{1->3, 2->9, 3->1},
{1->6, 2->6, 3->2, 4->2}}] 

side by side

Output on left; photo of Piet Mondrian, Red Blue Yellow Composition on right.

\$\endgroup\$
  • 3
    \$\begingroup\$ Nice try. You're not getting the bounty that easily. \$\endgroup\$ – Wheat Wizard Feb 15 '17 at 1:33
11
\$\begingroup\$

Ruby, 112 (111) characters

Piet Mondrian - composition in B (No.II) with Red

b="0 "*9
w="2 "*9
puts"P3 609 771 2",["1 0 0 "*267,w*8+b*2+w*79,w*89].map{|x|(x+b*3+w*42+b*3+w*66)*249}*(b*2436)

my production on the left, the upscaled reference on the right.

enter image description here

The colors can be tweaked slightly - up to a precision of 1/9 - without loss of score by tweaking the max-value in PPM. I've chosen the "suitable Win16 color" approach. 8/9 white is probably closer to the canvas original color, but 9/9 is closer to the author's intention.

One character can be saved if we replace "1 0 0 " with (w+b+b) (#F00 red). I believe that counts as "close enough"

file ouptut version (not golfed)

File.open "tmp.ppm", ?w do |f|
    b="0 "
    w="2 "
    s=b*27+w*378+b*27+w*594
    f.puts"P3 609 771 2",["1 0 0 "*267,w*72+b*18+w*711,w*801].map{|x|(x+s)*249}*(b*21924)
end
\$\endgroup\$
  • \$\begingroup\$ An easy one: "0 " -> b \$\endgroup\$ – Howard Sep 21 '13 at 7:58
  • \$\begingroup\$ @Howard damn. Missed this one while minifying. Thanks \$\endgroup\$ – John Dvorak Sep 21 '13 at 8:00
  • \$\begingroup\$ And some more if you change w="2 " to w="2 "*9 and b also. \$\endgroup\$ – Howard Sep 21 '13 at 8:09
  • \$\begingroup\$ umm... I get this (it goes on forever) \$\endgroup\$ – Doorknob Sep 22 '13 at 19:27
  • \$\begingroup\$ @Doorknob save that as a ppm file and open in an image editor \$\endgroup\$ – John Dvorak Sep 22 '13 at 19:34
9
+150
\$\begingroup\$

SmileBASIC, 2774 1892 bytes

Broadway Boogie Woogie

GCLS-920851D$="w$BȜąr:BȂąr7?Ƣǘy1SƑǘb<?ŵǘw-/ƶvyFMƮeb<<ŶIr:,ėǭy:Sėǘw-LŒƄw7;ėƎrkLćƄrBMĜey26ğ¸bKBē²y,Bć²w<Dđïw+DüïyDÒïw--çvyU8Òpw.1±syBM¨eb;<Iy28¥żrJNůbwN{ůr?@Ǣb3>Sǭw.Fb¤w24D­rMF5¤w,7Nnr[75ny1X=e
FOR I=1TO 36G A(),A(),A(),A(),A()NEXT
D$=" w*+r6,r1+b<*w1+b/+b++r(+w*+w,Br )b+*b()w0,w=+b,,r5+b1+r ,w24-Ȃ  w  w#.r-#-Ǥ  w*+r4,b3+r6*w2+b,-r-,b++r*+b**r(*b(*r*+b<-w@+b -w ,r4+b1+b%-w,5-ǔ  w +r)+w?#-ƹǘ w +r%-b,#-ƭ +w *r +w/,b2,r1-b;-w7+b*.w5+r1+r +-ƒ> w +r'-b*#-ž *r+)w +r?+b:+b1-b2+w:+w*+w3-b4-r4-b6,w2+r--w3+b1+r )w52-ş  w*+r )w ,b>+r7+b :w -b,+r:+w*+w7,r 6w ,r7-r0.w/+bM+b1+b ,w24-ľ *w +r)+r *w5+r9,b7.w++w ,r.+w*+w6*b Dw *r06w -r5+b *w8+w +r1+b ,w *r(7-ü  w*+w )b +w*+r*+bD-rC/r7+b*+r5+bD-r,.b/.w.+b *w8+r +w1+b'+r,4-Ò  w*+b )w+*r+*w +b )w<0wX-w +r*+b /wd-w/.b/*w+-r 7w)+bC+r,3-p *w+)w +b*+w*+b )w@2wU*w+*w++wx-wQ-w.,bT+b,.-* +w +r++r5,w6+w %|üŭ w3+r1*w(+r0+r7*b (w )r3*w+*w,+r-*w +b5+r )w6+w.,r1+w *b*-w +b *w(,r()w ,r+*r :| ȋ+w7*b 1w4)w +r %|şǷ+r,*w)+w.*w*)w ?r -w+'|pǷ)w,)w +b*#| Ƿ+r/+b()w ?r -w+*w),r(*w *b +w *r +| Ǣ w+(w +b1*w(+r0+b7)b *w *r2)w +b *w,+r7+b5+r )w6+b/+b )w1,r7+b.*b9*w +b*8| Ǎ w3+w )b0*w +r4)w +r/+w**w**b +w6+w )r1*b3+w /|üň+b-*w1+w%*r(-w +r *w.+w')r (w5*| ň w3+w )r0*w +b )r5*b/+w3+w *r +w *r,+w9+r3+w-*b (w +r,+b2,w /r3+b0)r *b+-w+*r :| ij w3+b )w)*r 'w +b (w+)w *r1+b0*w.+r6+b )w0)w,)w +b4+w +b0)w'*r1*b))w+*b.*b1(w+*r ;| 3w +b )w*)b 'w +b.)r 'w )b0+r <b,+b6+b.,b=+r 3w ,b +w *b 6w *r);b)+b7+b 1w=9| Z w3+r (w.-w +b1+w +r0+r )w +r (w,+r6+b *w),r8+b?+bJ*w:)w+)w.*r1)w+*r 7| >+r )w6+r2*b1+r6*b1*w +b*(| ,
FOR Q=1TO 27S=A()T=A()R=A()L=A()FOR I=1TO L
R A(),89R A(),A()NEXT
NEXT
DEF A()RETURN-32+ASC(POP(D$))END
DEF R L,C
IF L THEN IF R-13THEN G C,L,11,T,S:T=T+L ELSE G C,11,L,T,S:S=S+L
END
DEF G C,H,W,Y,X
GFILL X,Y,X+W-1,Y+H-1,-1716698*(C>88)-2302505*(C==87)-6080725*(C==82)-14597488*(C<67)END

screenshot

Each of the "lines" in the image is stored in this format:

x,y,direction,numberOfSegments,
yellowLength,nextColor,colorLength,
yellowLength,nextColor,colorLength,...

All the numbers are stored as CHR$(number+32), colors are stored as one character; w,y,r, or b, and direction is stored as | or -

The extra rectangles are just stored as:

x,y,width,height,color,
x,y,width,height,color,...

In the same way.

\$\endgroup\$
  • \$\begingroup\$ Nice! I was thinking about doing QBasic, but there isn't a 512x512 screen mode. \$\endgroup\$ – DLosc Feb 10 '17 at 19:23
  • \$\begingroup\$ I got very lucky; SmileBASIC's graphics pages are exactly 512x512 pixels \$\endgroup\$ – 12Me21 Feb 15 '17 at 1:19
7
\$\begingroup\$

SVG - 455 480 - Mondrian Composition II in Red, Blue, and Yellow

If you can embed Javascript into SVG and make it dynamic, its a programming language. Ergo, this is a program. Turns out if an x or y coord is missing in SVG it defaults to 0. Also red is shorter than #f00!

<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg"><rect x="145" fill="red" width="455" height="440"/><rect y="432" fill="#00F" width="150" height="168"/><rect x="550" y="517" fill="#FF0" width="50" height="83"/><rect x="140" width="16" height="600"/><rect y="430" width="600" height="16"/><rect y="180" width="140" height="25"/><rect x="550" y="430" width="15" height="170"/><rect x="550" y="515" width="50" height="16"/></svg>

Pretty Printed:

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
  <rect x="145" fill="red" width="455" height="440"/>
  <rect y="432" fill="#00F" width="150" height="168"/>
  <rect x="550" y="517" fill="#FF0" width="50" height="83"/>
  <rect x="140" width="16" height="600"/>
  <rect y="430" width="600" height="16"/>
  <rect y="180" width="140" height="25"/>
  <rect x="550" y="430" width="15" height="170"/>
  <rect x="550" y="515" width="50" height="16"/>
</svg>
\$\endgroup\$
  • \$\begingroup\$ Wait, I thought Composition B (No.II) with Red 1935 was #2 \$\endgroup\$ – John Dvorak Sep 21 '13 at 5:42
  • 4
    \$\begingroup\$ @JanDvorak I don't know, I just looked him up on Wikipedia. Honestly, Piet was a pretty lazy painter. They all look the same. \$\endgroup\$ – user8777 Sep 21 '13 at 6:11
  • \$\begingroup\$ I think you can avoid most of the double quotes and still work in most browsers. Not sure about compliance, though. \$\endgroup\$ – John Dvorak Sep 21 '13 at 8:02
  • \$\begingroup\$ @LegoStormtroopr Lazy? That's pretty rich, coming from a guy who hangs out on a website devoted to writing short programs. \$\endgroup\$ – boothby Sep 22 '13 at 0:49
  • 1
    \$\begingroup\$ @boothby Touche. I was going to argue that I've learned a lot from code golf due to its hyperminimalist approach. But... the same could be argued of Piet's work too. \$\endgroup\$ – user8777 Sep 22 '13 at 4:54
3
\$\begingroup\$

SmileBASIC, 67 bytes

GCLS-1GFILL 353,0,367,#R,0GFILL.,121,#R,156,0GFILL 367,266,#R,293,0

I picked an easy one: Composition III in Black and White

Luckily SB's graphics page is exactly 512x512 pixels, but it won't all fit on the 400x240 screen so I can't get a screenshot easily.

Explained:

GCLS -1 'fill screen with &HFFFFFFFF (white)
GFILL 353,0,367,511,0 'draw vertical line in &H00000000 (black)
GFILL 0,121,#R,156,0 'draw horizontal line
GFILL 367,266,#R,293,0 'draw small horizontal line
\$\endgroup\$
3
\$\begingroup\$

Processing, 15,447 15,441 15,439 bytes

String i="data:image/jpeg;base64,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";PImage x=loadImage(i);void draw(){image(x);}

Brute force, and I haven't managed to find a way to remove the draw function.

It errors in the main processing engine, I think because it's too big of a b64. You can test it here.

JS fiddles does crop it though, to 100*100px. My base64 works, but the online environment doesn't. :(

\$\endgroup\$
  • \$\begingroup\$ You can golf this by using PImage x=loadImage(i); instead \$\endgroup\$ – Kritixi Lithos Feb 10 '17 at 11:16
  • 1
    \$\begingroup\$ The question demands a resolution of 512x512 or higher, but the canvas in your fiddle is only 100x100. Is this a quirk of JSFiddle? \$\endgroup\$ – Dennis Feb 10 '17 at 18:09
  • \$\begingroup\$ @Dennis It's not only the canvas size. The image is cut off on both the right and the bottom, making the result incorrect. \$\endgroup\$ – mbomb007 Feb 10 '17 at 22:34
  • \$\begingroup\$ @Dennis Yeah, it is. Manually setting it to 512*512 px still crops it to the same size. It's just JS fiddle, and the b64 I used is greater than 512. \$\endgroup\$ – Rɪᴋᴇʀ Feb 10 '17 at 22:35
  • \$\begingroup\$ data:;base64 works just as well \$\endgroup\$ – Kritixi Lithos Feb 11 '17 at 15:38
2
\$\begingroup\$

Love2D, 4956 + 395 + 1 = 5351 bytes

f=io.open("d","rb")s=f:read("*a"):gsub("(.)(.)",function(a,b)return a:rep(b:byte())end)o=love.image.newImageData(512,512)c={{244,243,248},{173,24,0},{250,209,5},{30,64,164}}o:mapPixel(function(x,y)i=math.floor((x+math.floor(y/4)*512)/4)O=3-i%4 n=s:sub(math.floor(i/4)+1,math.floor(i/4)+1)if n and#n>0 then b=math.floor(n:byte()/(4^O))%4 else b=0 end return unpack(c[b+1])end)o:encode("png","o") 

The Data file is stored HERE

Output:

Output

Original:

Original

Explanation

f = io.open("d","rb")                                                   -- Open the image in raw format.
s = f:read("*a"):gsub("(.)(.)",function(a,b)return a:rep(b:byte())end)  -- And read it's contents. 
o=love.image.newImageData(512,512)                                      -- Make the output image
c = {{244,243,248},{173,24,0},{250,209,5},{30,64,164}}                  -- Build the Pallet
o:mapPixel(function(x,y)                                                -- Fill the image, based on a function
    i = (x+y*512)                                   -- The position this pixel exists on the string, 0 indexed.
    O = 3-i%4                                       -- The offset. The byte stores 4 pixels, so this is the id among a group of 4.
    n = s:sub(math.floor(i/4)+1,math.floor(i/4)+1)  -- And this gets the byte itself.
    if n and #n > 0 then                            -- Sometimes this is null and I don't like it.
        b = math.floor(n:byte()/(4^O))%4            -- /4^offset % 4 gives us the value of the index on the pallet.
    else
        b = 0                                       -- Fallback plan.
    end
    return unpack(c[b+1])                           -- Set the pixel to the colour required.
end)
o:encode("png","o") -- Store it in Appdata as "o", which is a png file.

The Encoder.

This is just the script I used to encode the image. Gif worked out more compressed, but I wasn't challenged to display a gif.

img = love.image.newImageData("mondrian.jpg")
-- white    0
-- blue     3
-- yellow   2
-- red      1

cols = {{244,243,248},{173,24,0},{250,209,5},{30,64,164}}

local s = ""
for y = 0, 511 do
    for x = 0, 511 do
        local r,g,b = img:getPixel(x,y)
        local n = 0
        local D = math.huge
        for k,v in pairs(cols) do
            local d = (v[1]-r)^2 + (v[2]-g)^2 + (v[3]-b)^2
            if d < D then
                n = k-1
                D = d
            end
        end
        s = s .. n
    end
end
-- Convert base 4 to base 256
-- How many digits do we need- Every 4 digits
encd = ""
for str in s:gmatch"...." do
    local n = str:sub(1,1) * 4^3 +
              str:sub(2,2) * 4^2 +
              str:sub(3,3) * 4^1 +
              str:sub(4,4) * 4^0
    encd = encd .. string.char(n)
end

f = io.open("stored.dat","wb")

smlr = ""
lst = ""
c = 0
for s in encd:gmatch"." do
    if s == lst then
        c = c + 1
        while c > 255 do
            smlr = smlr .. lst .. string.char(255)
            c = c - 255
        end
    else
        if c > 0 then
            smlr = smlr .. lst .. string.char(c)
        end
        lst = s
        c = 1
    end
end

f:write(smlr)

Mostly competing for the bounty. There are likely better ways to do this, but I thought it would be interesting to try to use a simple pallet and run length decoding.

EDIT: Input image was simplified, slightly less accurate, but a magnitude less bytes.

\$\endgroup\$
  • 2
    \$\begingroup\$ Why do parts of your output look like they're made of puzzle pieces? Is that what you meant by "slightly less accurate, but a magnitude less bytes"? It seems to me that the resulting gaps in the color strips make this not a valid recreation. \$\endgroup\$ – DLosc Feb 15 '17 at 6:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.