Skip to main content
added 12 characters in body
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332
xkcdStyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{str_, {x1_, y1_}, {xo_, yo_}}] := Module[{x2, y2}, x2 = x1 + xo; y2 = y1 + yo; {Inset[ Style[str, xkcdStyle], {x2, y2}, {1.2 Sign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}], Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdRules = {EdgeForm[ef_]EdgeForm[ef:Except[None]] :> EdgeForm[Flatten@{ef, Thick, Black}], Style[x_, st_] :> Style[x, xkcdStyle], Pane[s_String] :> Pane[Style[s, xkcdStyle]], {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}, Grid[{{g_Graphics, s_String}}] :> Grid[{{g, Style[s, xkcdStyle]}}], Rule[PlotLabel, lab_] :> Rule[PlotLabel, Style[lab, xkcdStyle]]}; xkcdShow[p_] := Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle] /. xkcdRules xkcdShow[Labeled[p_, rest__]] := Labeled[Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle], rest] /. xkcdRules xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~ GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r, # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -5]]; xkcdConvert[x_] := xkcdDistort[xkcdShow[x]] 
xkcdStyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{str_, {x1_, y1_}, {xo_, yo_}}] := Module[{x2, y2}, x2 = x1 + xo; y2 = y1 + yo; {Inset[ Style[str, xkcdStyle], {x2, y2}, {1.2 Sign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}], Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdRules = {EdgeForm[ef_] :> EdgeForm[Flatten@{ef, Thick, Black}], Style[x_, st_] :> Style[x, xkcdStyle], Pane[s_String] :> Pane[Style[s, xkcdStyle]], {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}, Grid[{{g_Graphics, s_String}}] :> Grid[{{g, Style[s, xkcdStyle]}}], Rule[PlotLabel, lab_] :> Rule[PlotLabel, Style[lab, xkcdStyle]]}; xkcdShow[p_] := Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle] /. xkcdRules xkcdShow[Labeled[p_, rest__]] := Labeled[Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle], rest] /. xkcdRules xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~ GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r, # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -5]]; xkcdConvert[x_] := xkcdDistort[xkcdShow[x]] 
xkcdStyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{str_, {x1_, y1_}, {xo_, yo_}}] := Module[{x2, y2}, x2 = x1 + xo; y2 = y1 + yo; {Inset[ Style[str, xkcdStyle], {x2, y2}, {1.2 Sign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}], Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdRules = {EdgeForm[ef:Except[None]] :> EdgeForm[Flatten@{ef, Thick, Black}], Style[x_, st_] :> Style[x, xkcdStyle], Pane[s_String] :> Pane[Style[s, xkcdStyle]], {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}, Grid[{{g_Graphics, s_String}}] :> Grid[{{g, Style[s, xkcdStyle]}}], Rule[PlotLabel, lab_] :> Rule[PlotLabel, Style[lab, xkcdStyle]]}; xkcdShow[p_] := Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle] /. xkcdRules xkcdShow[Labeled[p_, rest__]] := Labeled[Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle], rest] /. xkcdRules xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~ GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r, # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -5]]; xkcdConvert[x_] := xkcdDistort[xkcdShow[x]] 
major edit to include various different plot types
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332

This method is based on creatingThe code below attempts to apply the XKCD style to a standardvariety of plots and charts. The idea is to first apply cartoon-like styles to the graphics objects Plot(thick lines, silly font etc), and then distorting itto apply a distortion using image processing. Plot

The final function is xkcdConvert which is simply applied to a standard plot or chart.

The font style and size are set by xkcdStyle which can be changed to your preference. I've used the dreaded Comic Sans font, as the text will get distorted along with everything else and I thought that starting with the Humor Sans font might lead to unreadable text.

The function xkcdLabel is provided to allow labelling of plot lines using a little callout. The usage is now includedxkcdLabel[{str,{x1,y1},{xo,yo}] where str is the label (e.g. a string), {x1,y1} is the position of the callout line and {xo,yo} is the offset determining the relative position of the label. The first example demonstrates its usage.

xkcdstylexkcdStyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{func_, str_, {x1_, y1_}, {x2_xo_, y2_yo_}}] := Module[{y1x2, y2}, y1x2 = func[x1];x1 + xo; y2 = y1 + yo; {Inset[Style[strInset[ Style[str, xkcdstyle]xkcdStyle], {x2, y2}, {1.2 Sign[x1 - x2],  Sign[y1 - y2] Boole[x1 == x2]}],   Thick,    Thick,  BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdLabel[xkcdRules = {func_EdgeForm[ef_] :> EdgeForm[Flatten@{ef, Thick, Black}], Style[x_, st_] :> Style[x, xkcdStyle], Pane[s_String] :> Pane[Style[s, xkcdStyle]], {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}, Grid[{{g_Graphics, s_String}}] :> Grid[{{g, Style[s, xkcdStyle]}}], Rule[PlotLabel, lab_] :> Rule[PlotLabel, Style[lab, xkcdStyle]]}; xkcdShow[p_] := Null;Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle] /. xkcdRules  xkcdShow[Labeled[p_, rest__]] :=   Labeled[Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle], rest] /. xkcdRules xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} =  Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10]ImageDimensions@r]~ImageConvolve~ GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r,    # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -10]];5]]; SetAttributes[xkcdPlot,xkcdConvert[x_] HoldAll];:= xkcdDistort[xkcdShow[x]] 

Version 7 users will need to use this code for xkcdDistort:

xkcdDistort[p_] :=  xkcdPlot[plotfuncs_, Module[{from_r, to_}id, opts___] :=  xkcdDistort[Plot[Through[plotfuncs[[Allix, 1]][x]]iy, {xsamplepoints, fromfuncs, tochannels},  r = ImagePad[Rasterize@p, LabelStyle10, Padding -> xkcdstyle,White]; AxesStyle   -> Thick,id Evaluated= ->Reverse@ImageDimensions[r];  True {ix,   iy} = Table[ListInterpolation[ImageData[  Epilog -> xkcdLabel /@Image@RandomReal[{-1, plotfuncs1}, opts]id]~ImageConvolve~GaussianMatrix[10]]], /.{2}];   samplepoints = Table[{h_Huex + 15 ix[x, l_Line}y], :>y {Thickness[0.02]+ 15 iy[x, Whitey]}, l{x, Thickid[[1]]}, h{y, lid[[2]]}];     funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r]; 

Each function to be plotted is given as a list:

{function, label channels = Apply[#, x1samplepoints, {x22}] & /@ funcs; ImagePad[ColorCombine[Image /@ channels], y2}}-10]] 

where function is a pure function defining the curve and label is a string (or graphic). x1, x2 and y2 define the start and end points of the little line attaching the label to the curve. The line attaches to the plotted curve atExamples

Standard {x1,y1}Plot including (y1xkcdLabel is calculated automatically) and attaches to the label atas an {x2,y2}Epilog. The label itself is positioned accordingly. An unlabeled plot can be made by specifying only the function.

Example:

plotfuncsf1[x_] := {  {5 + 50 (1 + Erf[#Erf[x - 5]); f2[x_] &,:= "Label20 1"+ 30 (1 - Erf[x - 5]); xkcdConvert[Plot[{f1[x], 7.5f2[x]}, {7.5x, 80}0, 10},   {20Epilog +-> 30   (1 - Erf[#xkcdLabel -/@ 5]){{"Label &1", "Label 2"{1, 4f1[1]}, {31, 60}30}}; , {"Label 2",  xkcdPlot[plotfuncs{8, f2[8]}, {0, 1030}}},    Ticks -> {{{3.5, "1st Event"}, {7, "2nd Event"}}, Automatic}, PlotLabel -> Style["XKCD Style Plot", 16]]]] 

enter image description hereenter image description here

Version 7 users will need to replace xkcdDistortBarChart with thiseither labels or legends:

xkcdDistort[p_]xkcdConvert[BarChart[{10, :=1},   ChartLabels Module[-> {r"XKCD", id"Others"},   ix, iyPlotLabel -> "Popularity of questions on MMA.SE",   samplepoints Ticks -> {None, funcs{{1, channels"Min"}, {10, "Max"}}}]] 

enter image description here

xkcdConvert[BarChart[{1, 10}, rChartLegends =-> ImagePad[Rasterize@p{"Others", 10"XKCD"},   Padding PlotLabel -> White];"Popularity of questions on MMA.SE", idChartStyle =-> Reverse@ImageDimensions[r];{Red, Green}]] 

enter image description here

Pie chart:

xkcdConvert[PieChart[{9, 1}, ChartLabels -> {ix"XKCD", iy"Others"},  = Table[ListInterpolation[ImageData[ PlotLabel -> "Popularity of questions on Image@RandomReal[{MMA.SE"]] 

enter image description here

ListPlot:

xkcdConvert[ ListLinePlot[RandomInteger[10, 15], PlotMarkers -1> Automatic]] 

enter image description here

3D plots:

xkcdConvert[BarChart3D[{3, 2, 1}, id]~ImageConvolve~GaussianMatrix[10]]]ChartStyle -> Red, {2}];FaceGrids -> None, samplepointsMethod =-> Table[{x"Canvas" +-> 15None}, ix[xViewPoint -> {-2, y]-4, y1},  + 15PlotLabel iy[x,-> y]}"This is just silly"]] 

enter image description here

xkcdConvert[ Plot3D[Exp[-10 (x^2 + y^2)^4], {x, id[[1]]-1, 1}, {y, id[[2]]-1, 1}];, funcs = ListInterpolation[ImageData@#] & /@MeshStyle ColorSeparate[r];-> Thick, channelsBoxed =-> Apply[#False, samplepoints,Lighting -> {2}]{"Ambient", &White}},  /@ funcs;PlotLabel   -> Framed@"This ImagePad[ColorCombine[Imageplot /@is channels],not\nparticularly -10]]useful"]] 

enter image description here

It should also work for various other plotting functions like ParametricPlot, LogPlot and so on.

This method is based on creating a standard Plot and then distorting it using image processing. Plot labelling is now included.

xkcdstyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{func_, str_, x1_, {x2_, y2_}}] := Module[{y1}, y1 = func[x1]; {Inset[Style[str, xkcdstyle], {x2, y2}, {1.2 Sign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}],   Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdLabel[{func_}] = Null; xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r, # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -10]]; SetAttributes[xkcdPlot, HoldAll]; xkcdPlot[plotfuncs_, {from_, to_}, opts___] :=  xkcdDistort[Plot[Through[plotfuncs[[All, 1]][x]], {x, from, to},  LabelStyle -> xkcdstyle, AxesStyle -> Thick, Evaluated -> True,    Epilog -> xkcdLabel /@ plotfuncs, opts] /.   {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}];   

Each function to be plotted is given as a list:

{function, label, x1, {x2, y2}} 

where function is a pure function defining the curve and label is a string (or graphic). x1, x2 and y2 define the start and end points of the little line attaching the label to the curve. The line attaches to the plotted curve at {x1,y1} (y1 is calculated automatically) and attaches to the label at {x2,y2}. The label itself is positioned accordingly. An unlabeled plot can be made by specifying only the function.

Example:

plotfuncs = {  {5 + 50 (1 + Erf[# - 5]) &, "Label 1", 7.5, {7.5, 80}},   {20 + 30 (1 - Erf[# - 5]) &, "Label 2", 4, {3, 60}}};   xkcdPlot[plotfuncs, {0, 10},  Ticks -> {{{3.5, "1st Event"}, {7, "2nd Event"}}, Automatic}, PlotLabel -> Style["XKCD Style Plot", 16]] 

enter image description here

Version 7 users will need to replace xkcdDistort with this:

xkcdDistort[p_] :=    Module[{r, id, ix, iy, samplepoints, funcs, channels}, r = ImagePad[Rasterize@p, 10, Padding -> White]; id = Reverse@ImageDimensions[r]; {ix, iy} = Table[ListInterpolation[ImageData[  Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]]], {2}]; samplepoints = Table[{x + 15 ix[x, y], y + 15 iy[x, y]}, {x, id[[1]]}, {y, id[[2]]}]; funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r]; channels = Apply[#, samplepoints, {2}] & /@ funcs;    ImagePad[ColorCombine[Image /@ channels], -10]] 

The code below attempts to apply the XKCD style to a variety of plots and charts. The idea is to first apply cartoon-like styles to the graphics objects (thick lines, silly font etc), and then to apply a distortion using image processing.

The final function is xkcdConvert which is simply applied to a standard plot or chart.

The font style and size are set by xkcdStyle which can be changed to your preference. I've used the dreaded Comic Sans font, as the text will get distorted along with everything else and I thought that starting with the Humor Sans font might lead to unreadable text.

The function xkcdLabel is provided to allow labelling of plot lines using a little callout. The usage is xkcdLabel[{str,{x1,y1},{xo,yo}] where str is the label (e.g. a string), {x1,y1} is the position of the callout line and {xo,yo} is the offset determining the relative position of the label. The first example demonstrates its usage.

xkcdStyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{str_, {x1_, y1_}, {xo_, yo_}}] := Module[{x2, y2}, x2 = x1 + xo; y2 = y1 + yo; {Inset[ Style[str, xkcdStyle], {x2, y2}, {1.2 Sign[x1 - x2],  Sign[y1 - y2] Boole[x1 == x2]}], Thick,      BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdRules = {EdgeForm[ef_] :> EdgeForm[Flatten@{ef, Thick, Black}], Style[x_, st_] :> Style[x, xkcdStyle], Pane[s_String] :> Pane[Style[s, xkcdStyle]], {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}, Grid[{{g_Graphics, s_String}}] :> Grid[{{g, Style[s, xkcdStyle]}}], Rule[PlotLabel, lab_] :> Rule[PlotLabel, Style[lab, xkcdStyle]]}; xkcdShow[p_] := Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle] /. xkcdRules  xkcdShow[Labeled[p_, rest__]] :=   Labeled[Show[p, AxesStyle -> Thick, LabelStyle -> xkcdStyle], rest] /. xkcdRules xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White]; {ix, iy} =  Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~ GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r,    # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -5]]; xkcdConvert[x_] := xkcdDistort[xkcdShow[x]] 

Version 7 users will need to use this code for xkcdDistort:

xkcdDistort[p_] :=  Module[{r, id, ix, iy, samplepoints, funcs, channels}, r = ImagePad[Rasterize@p, 10, Padding -> White];    id = Reverse@ImageDimensions[r];   {ix, iy} = Table[ListInterpolation[ImageData[  Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]]], {2}]; samplepoints = Table[{x + 15 ix[x, y], y + 15 iy[x, y]}, {x, id[[1]]}, {y, id[[2]]}];   funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r];  channels = Apply[#, samplepoints, {2}] & /@ funcs; ImagePad[ColorCombine[Image /@ channels], -10]] 

Examples

Standard Plot including xkcdLabel as an Epilog:

f1[x_] := 5 + 50 (1 + Erf[x - 5]); f2[x_] := 20 + 30 (1 - Erf[x - 5]); xkcdConvert[Plot[{f1[x], f2[x]}, {x, 0, 10}, Epilog ->    xkcdLabel /@ {{"Label 1", {1, f1[1]}, {1, 30}}, {"Label 2", {8, f2[8]}, {0, 30}}},   Ticks -> {{{3.5, "1st Event"}, {7, "2nd Event"}}, Automatic}]] 

enter image description here

BarChart with either labels or legends:

xkcdConvert[BarChart[{10, 1}, ChartLabels -> {"XKCD", "Others"},   PlotLabel -> "Popularity of questions on MMA.SE",    Ticks -> {None, {{1, "Min"}, {10, "Max"}}}]] 

enter image description here

xkcdConvert[BarChart[{1, 10}, ChartLegends -> {"Others", "XKCD"},   PlotLabel -> "Popularity of questions on MMA.SE", ChartStyle -> {Red, Green}]] 

enter image description here

Pie chart:

xkcdConvert[PieChart[{9, 1}, ChartLabels -> {"XKCD", "Others"},  PlotLabel -> "Popularity of questions on MMA.SE"]] 

enter image description here

ListPlot:

xkcdConvert[ ListLinePlot[RandomInteger[10, 15], PlotMarkers -> Automatic]] 

enter image description here

3D plots:

xkcdConvert[BarChart3D[{3, 2, 1}, ChartStyle -> Red, FaceGrids -> None, Method -> {"Canvas" -> None}, ViewPoint -> {-2, -4, 1},  PlotLabel -> "This is just silly"]] 

enter image description here

xkcdConvert[ Plot3D[Exp[-10 (x^2 + y^2)^4], {x, -1, 1}, {y, -1, 1}, MeshStyle -> Thick, Boxed -> False, Lighting -> {{"Ambient", White}},  PlotLabel -> Framed@"This plot is not\nparticularly useful"]] 

enter image description here

It should also work for various other plotting functions like ParametricPlot, LogPlot and so on.

major code overhaul to include plot labelling
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332

Here's a quick and dirtyThis method to distort a graphic.

First createis based on creating a plotstandard Plot and then distorting it using Mr Wizard's suggestion of a thick white line behind each coloured line:image processing. Plot labelling is now included.

pxkcdstyle = Plot[{Sin[x]FontFamily -> "Comic Sans MS", Cos[x]16}; xkcdLabel[{func_, str_, x1_, {xx2_, 0y2_}}] := Module[{y1}, y1 = func[x1]; {Inset[Style[str, xkcdstyle], {x2, y2}, {1.2 PiSign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}], Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdLabel[{func_}] = Null; xkcdDistort[p_] := Module[{r, ix, iy}, BaseStyler = ImagePad[Rasterize@p, 10, Padding -> White];  {FontFamilyix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r,  # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> "ComicFull], Sans-10]]; SetAttributes[xkcdPlot, MS"HoldAll]; xkcdPlot[plotfuncs_, 16{from_, to_}, opts___] := xkcdDistort[Plot[Through[plotfuncs[[All, 1]][x]], {x, from, to}, LabelStyle -> xkcdstyle, AxesStyle -> Thick]Thick, Evaluated -> True, Epilog -> xkcdLabel /@ plotfuncs, opts] /.   {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}];  

enter image description here Each function to be plotted is given as a list:

{function, label, x1, {x2, y2}} 

Now distort itwhere function is a pure function defining the curve and label is a string (or graphic). x1, x2 and y2 define the start and end points of the little line attaching the label to the curve. The line attaches to the plotted curve at {x1,y1} (y1 is calculated automatically) and attaches to the label at {x2,y2}. The label itself is positioned accordingly. An unlabeled plot can be made by specifying only the function.

Example:

rplotfuncs = ImagePad[Rasterize@p,{  10, Padding {5 + 50 (1 + Erf[# -> White]; i15]) =&, RandomImage["Label 1", 7.5, {-17.5, 180}}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10]; i2 = RandomImage[ {-20 + 30 (1 - Erf[# - 5]) &, 1}"Label 2", ImageDimensions@r]~ImageConvolve~GaussianMatrix[10];4, {3, 60}}};   ImagePad[ImageTransformation[rxkcdPlot[plotfuncs, #{0, +10}, 15 Ticks -> {ImageValue[i1{{3.5, #]"1st Event"}, ImageValue[i2{7, #]"2nd Event"}}, &Automatic},  DataRangePlotLabel -> Full]Style["XKCD Style Plot", -10]16]] 

enter image description here

Version 7 codeenter image description here

This replaces the second code block above, forVersion 7 users will need to replace xkcdDistort with version 7this:

xkcdDistort[p_] := Module[{r, id, ix, iy, samplepoints, funcs, channels}, r = ImagePad[Rasterize@p, 10, Padding -> White];  id = Reverse@ImageDimensions[r]; i1id = ListInterpolation[ImageData[Reverse@ImageDimensions[r];   Image@RandomReal[{-1ix, 1iy}, id]~ImageConvolve~GaussianMatrix[10]]]; i2 = ListInterpolation@ImageData[Table[ListInterpolation[ImageData[   Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]];id]~ImageConvolve~GaussianMatrix[10]]], {2}];   samplepoints = Table[{x + 15 i1[xix[x, y], y + 15 i2[xiy[x, y]}, {x, id[[1]]}, {y, id[[2]]}];   funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r];   channels = Apply[#, samplepoints, {2}] & /@ funcs;   ImagePad[ColorCombine[Image /@ channels], -10]10]] 

Here's a quick and dirty method to distort a graphic.

First create a plot using Mr Wizard's suggestion of a thick white line behind each coloured line:

p = Plot[{Sin[x], Cos[x]}, {x, 0, 2 Pi}, BaseStyle -> {FontFamily -> "Comic Sans MS", 16}, AxesStyle -> Thick] /. {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l} 

enter image description here

Now distort it:

r = ImagePad[Rasterize@p, 10, Padding -> White]; i1 = RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10]; i2 = RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10]; ImagePad[ImageTransformation[r, # + 15 {ImageValue[i1, #], ImageValue[i2, #]} &, DataRange -> Full], -10] 

enter image description here

Version 7 code

This replaces the second code block above, for users with version 7:

r = ImagePad[Rasterize@p, 10, Padding -> White]; id = Reverse@ImageDimensions[r]; i1 = ListInterpolation[ImageData[   Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]]]; i2 = ListInterpolation@ImageData[ Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]]; samplepoints = Table[{x + 15 i1[x, y], y + 15 i2[x, y]}, {x, id[[1]]}, {y, id[[2]]}]; funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r]; channels = Apply[#, samplepoints, {2}] & /@ funcs; ImagePad[ColorCombine[Image /@ channels], -10] 

This method is based on creating a standard Plot and then distorting it using image processing. Plot labelling is now included.

xkcdstyle = {FontFamily -> "Comic Sans MS", 16}; xkcdLabel[{func_, str_, x1_, {x2_, y2_}}] := Module[{y1}, y1 = func[x1]; {Inset[Style[str, xkcdstyle], {x2, y2}, {1.2 Sign[x1 - x2], Sign[y1 - y2] Boole[x1 == x2]}], Thick, BezierCurve[{{0.9 x1 + 0.1 x2, 0.9 y1 + 0.1 y2}, {x1, y2}, {x2, y2}}]}]; xkcdLabel[{func_}] = Null; xkcdDistort[p_] := Module[{r, ix, iy}, r = ImagePad[Rasterize@p, 10, Padding -> White];  {ix, iy} = Table[RandomImage[{-1, 1}, ImageDimensions@r]~ImageConvolve~GaussianMatrix[10], {2}]; ImagePad[ImageTransformation[r,  # + 15 {ImageValue[ix, #], ImageValue[iy, #]} &, DataRange -> Full], -10]]; SetAttributes[xkcdPlot, HoldAll]; xkcdPlot[plotfuncs_, {from_, to_}, opts___] := xkcdDistort[Plot[Through[plotfuncs[[All, 1]][x]], {x, from, to}, LabelStyle -> xkcdstyle, AxesStyle -> Thick, Evaluated -> True, Epilog -> xkcdLabel /@ plotfuncs, opts] /.   {h_Hue, l_Line} :> {Thickness[0.02], White, l, Thick, h, l}];  

Each function to be plotted is given as a list:

{function, label, x1, {x2, y2}} 

where function is a pure function defining the curve and label is a string (or graphic). x1, x2 and y2 define the start and end points of the little line attaching the label to the curve. The line attaches to the plotted curve at {x1,y1} (y1 is calculated automatically) and attaches to the label at {x2,y2}. The label itself is positioned accordingly. An unlabeled plot can be made by specifying only the function.

Example:

plotfuncs = {   {5 + 50 (1 + Erf[# - 5]) &, "Label 1", 7.5, {7.5, 80}},  {20 + 30 (1 - Erf[# - 5]) &, "Label 2", 4, {3, 60}}};   xkcdPlot[plotfuncs, {0, 10},  Ticks -> {{{3.5, "1st Event"}, {7, "2nd Event"}}, Automatic},  PlotLabel -> Style["XKCD Style Plot", 16]] 

enter image description here

Version 7 users will need to replace xkcdDistort with this:

xkcdDistort[p_] := Module[{r, id, ix, iy, samplepoints, funcs, channels}, r = ImagePad[Rasterize@p, 10, Padding -> White];  id = Reverse@ImageDimensions[r]; {ix, iy} = Table[ListInterpolation[ImageData[   Image@RandomReal[{-1, 1}, id]~ImageConvolve~GaussianMatrix[10]]], {2}];   samplepoints = Table[{x + 15 ix[x, y], y + 15 iy[x, y]}, {x, id[[1]]}, {y, id[[2]]}];   funcs = ListInterpolation[ImageData@#] & /@ ColorSeparate[r];   channels = Apply[#, samplepoints, {2}] & /@ funcs;   ImagePad[ColorCombine[Image /@ channels], -10]] 
added v7 code
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332
Loading
distortion now two dimensional
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332
Loading
Source Link
Simon Woods
  • 85.9k
  • 8
  • 183
  • 332
Loading