Draw the Easter Bunny

This happy individual is known in folklore as the Easter Bunny.

Colours

It is created using 4 colours:

• Light pink
• Dark pink
• White
• Black

(I'm happy for these colours to be approximated in your answer. It does not need to be this precise shade)

Shapes

It is constructed of these shapes:

• Two tall ellipses in light pink (outer ears). They have the same height and width.
• Two tall ellipses in dark pink (inner ears). They are smaller than the outer ears and one is drawn on top of each of the outer ears. They are the same height and width.
• One large circle in light pink (head). It intersects with the bottom third of both outer ears (but no higher).
• Two circles in white (outer eyes). They are drawn on the head. Their diameter is less than the width of the outer ears. They have the same horizontal position as the outer ears.
• Two circles in black (inner eyes). They have a smaller diameter than the outer eyes. One is drawn on each of the outer eyes.
• One vertical line in black (upper mouth). It is drawn on the head and is lower than the bottom of the outer eyes. It is roughly equidistant from each eye.
• Two arcs in black (lower mouth). They are drawn on the head and arc downwards from a horizontal line. Both intersect with the bottom of the upper mouth, but one goes right and the other goes left.

The Rules

• Use any language and tools you like.
• Output can be an image, html, svg, or other markup.
• It's code golf, so aim to do it in the smallest number of bytes.
• Please include a screenshot of the result.
• Please feel free to approximate the colours defined.

Happy Easter!

• What size image would you like?
– Neil
Apr 21, 2019 at 10:46
• @Neil size doesn’t matter, Neil. As long as it meets the requirements for shape and colour. Apr 21, 2019 at 11:43
• I've got a desmos answer in the works. Is having no white in the eyes acceptable? Apr 21, 2019 at 15:47
• @BenjaminUrquhart not really. That considerably simplifies the process. You could make it a grey, if that helps. Apr 21, 2019 at 15:55
• @BenjaminUrquhart works for me Apr 21, 2019 at 16:07

T-SQL, 445 439 bytes

DECLARE @ GEOMETRY='MULTIPOINT((3 3),(7 3))',
@l GEOMETRY='CIRCULARSTRING(3 6,3.3 9,3 12,2.7 9,3 6)',@r GEOMETRY
SET @=@.STBuffer(.6)SET @r=@l.STUnion('CIRCULARSTRING(7 6,7.3 9,7 12,6.7 9,7 6)')
SELECT*FROM(VALUES(@),(@),(@),(@r.STBuffer(.3)),(@),(@),(@),(@),(@),(@),(@),(@),(@),
(@),(@),('CIRCULARSTRING(7 0,6 -1,5 0,5 1,5 1,5 0,5 0,4 -1,3 0)'),
(GEOMETRY::Point(5,1,0).STBuffer(5).STUnion(@r.STBuffer(1.3)).STDifference(@.STBuffer(.4)))
)a(g)


This site could use more T-SQL-based drawings!

Run on SQL 2017, but uses SQL geo-spatial storage features added back in SQL 2008. Line breaks are for readability only.

Output:

So, this was a pain to do in T-SQL, since spatial objects aren't exactly designed for drawing (no "ellipse" object, for example). Even more, getting the colors even close to right required a bit of trial and error.

Basically I'm constructing the following geometric objects:

1. The eyes (@), which are points expanded into disks using STBuffer(.6) (the set of all points within 0.6 of those starting points)
2. The ears (@r), which are generated as pointy curves, but are "puffed out" using STBuffer into either the inner or outer ears
3. The face, which is a disk plus the ears minus the eyes. I have to construct this and display it as a single object, or SQL would display it in different colors.
4. The mouth, which is a curve created using CIRCULARSTRING

To get the colors right, I have to SELECT these in the proper order. SSMS has a built-in sequence of colors for objects displayed in the spatial results pane, so the dark pink inner ears had to come 4th, and the light pink face had to come 16th. This required putting in a whole bunch of extra copies of the eyes, which is ok since we want them as close to black as possible (colors are somewhat transparent, so stacking them makes them darker).

Help and inspiration from the following resources:

EDIT: Moved the bunny down by 4 units, which changes some coordinates to a single digit, saving 6 bytes. No change in displayed output.

• Building a rabbit with geometry objects, brilliant! xD Apr 24, 2019 at 6:57

Red, 375340 329 bytes

Red[needs 'View]f: 'fill-pen p: 'pen e: 'ellipse c: 'circle
t:[5x5 0 180]view[base 200x200 #FFF draw
compose[(p)pink(f)pink(c)100x100 30(e)75x25
20x60(e)105x25 20x60(p)#E28(f)#E28(e)79x35 12x35(e)109x35
12x35(p)#FFF(f)#FFF(c)88x92 8(c)112x92 8(p)#000(f)#000(c)88x92
5(c)112x92 5 line 100x108 100x115 arc 95x115(t)arc 105x115(t)]]


Ruby with Shoes, 240 characters

Shoes.app{['fcc',[0,40,60],[5,0,20,50],[35,0,20,50],'f99',[t=10,t,t,h=30],[40,t,t,h],'fff',[t,55,15],[35,55,15],'000',[14,58,7],[38,58,7]].map{|v|stroke fill v rescue oval *v}
nofill
line h,75,h,80
arc 25,80,t,t,0,3.14
arc 35,80,t,t,0,3.14}


Sample output:

Python, 368 bytes

Using matplotlib.

from matplotlib import pyplot as l,patches as p,transforms as t;z=0,;[l.gca().add_patch(p.Wedge(z*2,R,s,360,width=w,color=(r,o,o),transform=t.Affine2D.from_values(X,0,0,9,350+x*n,y*9)))for R,s,w,r,o,X,x,y in zip([11,7,15,4,2,2,99],z*5+(180,359),[None]*5+[.2,.4],(1,)*4+z*3,(.8,.6,.8,1)+z*3,[4,4]+[9]*5,[7,7,0,6,6,2,98.8],[51,51,30,35,35,24,26])for n in[-9,9]];l.show()


Result:

Ungolfed:

from matplotlib import pyplot, patches, transforms
z = 0, # store zero as a tuple for later repetition
for radius, startAngle, width, red, other, xStretch, x, y in \
zip([11 ,7  ,15 ,4  ,2  ,2  ,99   ],  # radius
z * 5 +             (180,359  ),  # start angle
[None] * 5 +        [.2 ,.4   ],  # wedge width (None = full)
(1,) * 4        +z * 3         ,  # red channel
(.8 ,.6 ,.8 ,1) +z * 3         ,  # other color channels
[4]*2 + [9]*5                  ,  # x stretch factor
[ 7 ,7  ,0  ,6  ,6  ,2  ,98.8 ],  # x
[51 ,51 ,30 ,35 ,35 ,24 ,26   ]): # y
#        |   |   |   |   |   |   |
#        |   |   |   |   |   |   "straight" line for upper mouth
#        |   |   |   |   |   |   approximated by large radius arc
#        |   |   |   |   |   |
#        |   |   |   |   |   Arc for lower mouth
#        |   |   |   |   |
#        |   |   |   |   Inner eye circle
#        |   |   |   |
#        |   |   |   Outer eye circle
#        |   |   |
#        |   |   Circle for head
#        |   |
#        |   Inner ear ellipse
#        |
#        Outer ear ellipse

for n in [-9, 9]:        # draw left and right side mirrored
z*2,       # center = (0, 0), actual location set by the transform below
startAngle,
360,       # end angle
width = width,
color = (red, other, other), # only red channel varies from the others
transform = transforms.Affine2D.from_values( # affine transform matrix
xStretch,    # x stretch factor
0, 0,        # unused cross-axis coefficients for skew/rotation
9,           # y stretch factor
x * n + 350, # x value reflected by n, centered at 350
y * 9 )))    # y value

pyplot.show()


JavaScript + P5.js, 291276 273 bytes

A lot of small changes this time around.. that don't change the byte size at all.

setup=_=>{createCanvas(u=400,u);(e=ellipse,f=fill)#fcc;e(u/=2,u,x=150,x);e(x+=10,z=99,50,z);e(w=240,z,50,z);f#f77;e(x,z,y=30,80);e(w,z,y,80);f;e(w,v=180,y,y);e(x,v,y,y);f(0);e(w,v,y=9,y);e(x,v,y,y);noFill(line(u,225,u,250));arc(195,...a=[245,y,y,0,PI]);arc(205,...a)}


Try it online!

Explanation:

setup = _ => {
createCanvas(u=400, u);                 // Create basic canvas.
(e = ellipse, f = fill)#fcc;          // Light pink
e(u /= 2, u, 150, 150);                 // These first few lines end up defining short-hand names for functions.
e(x += 10, z = 99, 50, z);              // Throughout the code, you will see
e(w = 240, z, 50, z);                   // lots of variable definitions.
f#f77;                                // Dark pink
e(x, z, y = 30, 80);                    // Another variable declaration
e(w, z, y, 80);
f;                                    // Empty fill argument = white, apparently? (Eyes start here)
e(w, v = 180, y, y);                    // I'll just stop commenting on declarations now
e(x, v, y, y);
f(0);                                   // fill(x) = fill(x, x, x)
e(w, v, y = 9, y);
e(x, v, y, y);
noFill(line(u, 225, u, 250));           // Last part of bunny starts here.
// Get rid of fill so the bunny doesn't look bad
arc(195, ...a= [245, y, y, 0, PI]);
arc(205, ...a)                          // arc() creates something similar to a semi-circle.
}

• You can use #fcc and #f77 for the colors.
– ovs
Apr 22, 2019 at 7:21
• Well... I haven't found any new bytes since then. Safe to say I've optimized this too much? Apr 27, 2019 at 18:32

Javascript, 381 326 bytes

Thanks Arnold and Epicness.

(d=document).body.appendChild(a=d.createElementcanvas);b=a.getContext2d;'A707|A7,/|Z707|Z7,/|MZAA|CR--|UR--|CR**|UR**|Id**|Nd**|La(+'.split|.map(x=>x.split.map(c=>c.charCodeAt()-40)).map((x,i)=>b[b.beginPath(b.fillStyle='#'+'fccf77fff000'.substr('030306699'[i],3)),b.ellipse(...x,0,0,3*-~(i<9)),i>8?'stroke':'fill']())

• 389 bytes Apr 22, 2019 at 12:38
• Recently submited an edit for -6. Apr 22, 2019 at 17:42
• If you are willing to change your answer HTML+JavaScript you can make the HTML part <canvas id=A> and the first part of the JS b=A.getContext... - I used this in my Flag of Iceland some time ago. This post just saved that that answer 2 bytes :) codegolf.stackexchange.com/a/176852/8340
– dana
Apr 23, 2019 at 10:05
• As a bonus you can embed a "stack snippet" :) stackoverflow.blog/2014/09/16/…
– dana
Apr 23, 2019 at 10:08
• You can save 3 more bytes with (D=document).body.appendChild(a=D.createElementcanvas). Apr 23, 2019 at 16:23

Lua + LÖVE/Love2D, 328 bytes

l=love g=l.graphics c=g.setColor e=g.ellipse a=g.arc f="fill" k="line" o="open"function l.draw()c(1,.7,.7)e(f,50,82,40,40)e(f,30,28,10,25)e(f,70,28,10,25)c(1,.4,.4)e(f,30,28,5,18)e(f,70,28,5,18)c(1,1,1)e(f,35,73,8,8)e(f,65,73,8,8)c(0,0,0)g[k](49,90,49,99)a(k,o,45,96,5,.5,2.7)a(k,o,53,96,5,.5,2.7)e(f,35,73,4,4)e(f,65,73,4,4)end


Try it online!

Processing, 388343 319 chars/bytes

Not very elegant, but here it is. Saved bytes by making the image smaller.

int b=50,c=60,g=70;
noStroke();
//Face
fill(#FFCCCC);
ellipse(b,g,c,c);
//Outer ears
ellipse(40,25,15,b);
ellipse(c,25,15,b);
//Inner ears
fill(#FF9999);
ellipse(40,25,7,30);
ellipse(c,25,7,30);
//Outer eyes
fill(-1);
ellipse(40,g,10,10);
ellipse(c,g,10,10);
//Inner eyes
fill(0);
ellipse(40,g,5,5);
ellipse(c,g,5,5);
//Mouth
stroke(0);
line(b,80,b,85);
noFill();
arc(53,85,5,5,0,PI);
arc(48,85,5,5,0,PI);


• I saved a few bytes here and there: 332 bytes Apr 23, 2019 at 18:41
• 279 bytes Apr 23, 2019 at 18:49
• If strokes are allowed, 258 bytes Apr 23, 2019 at 19:02
• @Zylviij Used some of the ideas you had and got it down to 343 chars. I don't think you can assign functions to variables in Processing. Apr 23, 2019 at 21:15
• I haven't ever personally used or downloaded processing, but I did test my scripts here and they worked without producing errors in the image or console Apr 23, 2019 at 21:19

PostScript, 688484468439 359 bytes

Golfed version:

<</F{closepath fill}/C{0 360 arc}/c{curveto}/s{setrgbcolor}/M{moveto}/h{7 15 M 7 25 1 25 1 15 c 1 5 7 5 7 15 c F 1 .5 .5 s 6 15 M 6 22 2 22 2 15 c 2 8 6 8 6 15 c F 1 1 1 s 4 3 2 C F 0 0 0 s 4 3 1 C F 0 -3 M 0 -5 lineto stroke 1 -5 1 180 0 arc stroke}>>begin 80 60 translate 5 5 scale .2 setlinewidth 1 .7 .7 s 0 0 10 C F gsave h grestore -1 1 scale h showpage


Ungolfed version:

% define some short-named procedures for later use
<<
/F {closepath fill}
/C {0 360 arc}
/c {curveto}
/s {setrgbcolor}
/M {moveto}
/h {                           % procedure for drawing one half
7 15 M 7 25 1 25 1 15 c      % ellipse for outer ear
1  5 7  5 7 15 c F
1 .5 .5 s                    % dark pink
6 15 M 6 22 2 22 2 15 c      % ellipse for inner ear
2  8 6  8 6 15 c F
1 1 1 s                      % white
4 3 2 C F                    % circle for outer eye
0 0 0 s                      % black
4 3 1 C F                    % circle for inner eye
0 -3 M 0 -5 lineto stroke    % line for upper mouth
1 -5 1 180 0 arc stroke      % arc for lower mouth
}
>> begin

80 60 translate                  % over-all shift
5 5 scale                        % over-all scale
.2 setlinewidth
1 .7 .7 s                        % light pink
0 0 10 C F                       % large circle for head
gsave h grestore                 % right half
-1 1 scale h                     % left half
showpage


Result:

SVG (HTML5), 415 bytes

<svg width=48 height=80><g fill=#fdd><circle cx=24 cy=52 r=24 /><ellipse cx=12 cy=16 rx=8 ry=16 /><ellipse cx=36 cy=16 rx=8 ry=16 /></g><g fill=#f99><ellipse cx=12 cy=16 rx=4 ry=12 /><ellipse cx=36 cy=16 rx=4 ry=12 /></g><g fill=#fff><circle cx=16 cy=44 r=6 /><circle cx=32 cy=44 r=6 /></g><circle cx=16 cy=44 r=3 /><circle cx=32 cy=44 r=3 /><path stroke=#000 fill=none d=M18,60a3,3,180,0,0,6,0v-6v6a3,3,180,0,0,6,0

Keeping the height below 100 to help save precious bytes, but still the longest...

Java, 508 472 bytes

import java.awt.*;v->new Frame(){Graphics2D G;Color C;void d(int...d){G.fillOval(d[0],d[1],d[2],d[3]);}{add(new Panel(){public void paint(Graphics g){G=(Graphics2D)g;G.setPaint(C.PINK);d(0,65,99,99);d(22,0,24,75);d(58,0,24,75);G.setPaint(C.MAGENTA);d(27,5,14,65);d(63,5,14,65);G.setPaint(C.WHITE);d(24,85,20,20);d(60,85,20,20);G.setPaint(C.BLACK);d(30,91,8,8);d(66,91,8,8);G.drawArc(41,124,9,11,0,-180);G.drawArc(50,124,9,11,0,-180);G.drawLine(50,119,50,130);}});show();}}


This is the resulting bunny:

Explanation:

import java.awt.*;              // Required imports for almost everything
v->                             // Method with empty unused parameter and no return-type
new Frame(){                  //  Create a new Frame
Graphics2D G;               //   Graphics2D-object on class-level
Color C;                    //   Color variable to save bytes with static calls
void d(int...d){            //   Create an inner method with integer-varargs as parameter
G.fillOval(               //    Draw a circle/oval, filled with the current color:
d[0],d[1],              //     With the first two integers as starting x,y position
d[2],                   //     Third as width
d[3]));}                //     And fourth as height
{                           //   Then open an initializer-block inside the Frame-class
add(new Panel(){           //    And add a Panel to the Frame we can draw on
public void paint(Graphics g){
//     Override the Panel's paint-method
G=(Graphics2D)g;       //      Set the Graphics2D-object with the parameter
G.setPaint(C.PINK);    //      Set the color to pink (255,175,175)
d(0,65,99,99);         //      Draw the head circle
d(22,0,24,75);         //      Draw the left ear
d(58,0,24,75);         //      Draw the right ear
G.setPaint(C.MAGENTA); //      Change the color to magenta (255,0,255)
d(27,5,14,65);         //      Draw the inner part of the left ear
d(63,5,14,65);         //      Draw the inner part of the right ear
G.setPaint(C.WHITE);   //      Change the color to white (255,255,255)
d(24,85,20,20);        //      Draw the left eye
d(60,85,20,20);        //      Draw the right eye
G.setPaint(C.BLACK);   //      Change the color to black (0,0,0)
d(30,91,8,8);          //      Draw the left pupil
d(66,91,8,8);          //      Draw the right pupil
G.drawArc(41,124,9,11,0,-180);
//      Draw the left mouth elipse
G.drawArc(50,124,9,11,0,-180);
//      Draw the right mouth elipse
G.drawLine(50,119,50,130);}});
//      Draw the line of the mouth
show();}}                   //    And finally show the Frame on the screen


HTML, 280 278 bytes

a{color:#FFC8C8;}b{color:#FF7F7F;font-size:6px;margin-left:-10px;}m,n,j,d{display:block;}m{margin:-15px -3px;font-size:40px;}n{margin:-35px 5px;color:#FFF;font-size:15px;}j{margin:-14px 1px;color:#000;font-size:10px;}
<a>⬮<b>⬮</b><a>⬮<b>⬮</b><m>⬤<n>● ●<j>●‌‌ ‌‌ ‌‌ ●<d>‌‌ ‌‌ ‌‌ w

Here is a screenshot:

Citations