Wolfram Archive
Wolfram Programming Lab is a legacy product.
All the same functionality and features, including access to Programming Lab Explorations, are available with Wolfram|One.
Start programming now. »
Try it now »
(no sign-in required)

Picture Patterns

Make patterns by repeatedly reflecting pictures.

Get a picture of something. Give it the name pic:

Hint: try a common type of animal, or a famous person.

SHOW/HIDE DETAILS

There are lots of ways to get pictures in the Wolfram Language.

On the desktop, you can take a picture with your computers camera using CurrentImage.

You can use the Wolfram Knowledgebase (the same one that powers Wolfram|Alpha) to ask for a picture of something. Hold down the key and press = to get a natural language input field ():

\!\(\* NamespaceBox["LinguisticAssistant", DynamicModuleBox[{WolframAlphaClient`Private`query$$ = "picture of einstein", WolframAlphaClient`Private`boxes$$ = RowBox[{"EntityValue", "[", RowBox[{ TemplateBox[{"\"Albert Einstein\"", RowBox[{"Entity", "[", RowBox[{"\"Person\"", ",", "\"AlbertEinstein::6tb7g\""}], "]"}], "\"Entity[\\\"Person\\\", \\\"AlbertEinstein::6tb7g\\\"]\"", "\"person\""}, "Entity"], ",", TemplateBox[{"\"image\"", RowBox[{"EntityProperty", "[", RowBox[{"\"Person\"", ",", "\"Image\""}], "]"}], "\"EntityProperty[\\\"Person\\\", \\\"Image\\\"]\""}, "EntityProperty"]}], "]"}], WolframAlphaClient`Private`allassumptions$$ = {{ "type" -> "Clash", "word" -> "einstein", "template" -> "Assuming \"${word}\" is ${desc1}. Use as \ ${desc2} instead", "count" -> "3", "Values" -> {{ "name" -> "Person", "desc" -> "a person", "input" -> "*C.einstein-_*Person-"}, { "name" -> "Book", "desc" -> "a book", "input" -> "*C.einstein-_*Book-"}, { "name" -> "Satellite", "desc" -> "a spacecraft", "input" -> "*C.einstein-_*Satellite-"}}}}, WolframAlphaClient`Private`assumptions$$ = {}, WolframAlphaClient`Private`open$$ = {1}}, DynamicBox[ToBoxes[ AlphaIntegration`LinguisticAssistantBoxes["", 1, Dynamic[WolframAlphaClient`Private`query$$], Dynamic[WolframAlphaClient`Private`boxes$$], Dynamic[WolframAlphaClient`Private`allassumptions$$], Dynamic[WolframAlphaClient`Private`assumptions$$], Dynamic[WolframAlphaClient`Private`open$$]], StandardForm], ImageSizeCache->{114., {7., 16.}}, TrackedSymbols:>{ WolframAlphaClient`Private`query$$, WolframAlphaClient`Private`boxes$$, WolframAlphaClient`Private`allassumptions$$, WolframAlphaClient`Private`assumptions$$, WolframAlphaClient`Private`open$$}], DynamicModuleValues:>{}, UndoTrackedVariables:>{WolframAlphaClient`Private`open$$}], BaseStyle->{"Deploy"}, DeleteWithContents->True, Editable->False, SelectWithContents->True]\)

You can also drag images from most websites and drop them directly into the code.

Give your picture the name pic so you can refer to it later:

pic = \!\(\* NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "picture of a bird", Typeset`boxes$$ = RowBox[{"EntityValue", "[", RowBox[{ TemplateBox[{"\"birds\"", RowBox[{"Entity", "[", RowBox[{"\"Species\"", ",", "\"Class:Aves\""}], "]"}], "\"Entity[\\\"Species\\\", \\\"Class:Aves\\\"]\"", "\"species specification\""}, "Entity"], ",", TemplateBox[{"\"image\"", RowBox[{"EntityProperty", "[", RowBox[{"\"Species\"", ",", "\"Image\""}], "]"}], "\"EntityProperty[\\\"Species\\\", \\\"Image\\\"]\""}, "EntityProperty"]}], "]"}], Typeset`allassumptions$$ = {{ "type" -> "MultiClash", "word" -> "", "template" -> "Assuming ${word1} is referring to ${desc1}. Use \ \"${word2}\" as ${desc2}. Use \"${word3}\" as ${desc3}. Use \ \"${word4}\" as ${desc4}. Use \"${word5}\" as ${desc5}.", "count" -> "5", "Values" -> {{ "name" -> "Species", "word" -> "bird", "desc" -> "a species specification", "input" -> "*MC.%7E-_*Species-"}, { "name" -> "Movie", "word" -> "bird", "desc" -> "a movie", "input" -> "*MC.%7E-_*Movie-"}, { "name" -> "PopularCurve", "word" -> "bird", "desc" -> "a popular curve", "input" -> "*MC.%7E-_*PopularCurve-"}, { "name" -> "Person", "word" -> "a bird", "desc" -> "a person", "input" -> "*MC.%7E-_*Person-"}, { "name" -> "WordData", "word" -> "", "desc" -> " referring to English words", "input" -> "*MC.%7E-_*WordData-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1}, Typeset`querystate$$ = { "Online" -> True, "Allowed" -> True, "mparse.jsp" -> 1.282299`6.5595342970793595, "Messages" -> {}}}, DynamicBox[ToBoxes[ AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache->{103., {7., 16.}}, TrackedSymbols:>{ Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues:>{}, UndoTrackedVariables:>{Typeset`open$$}], BaseStyle->{"Deploy"}, DeleteWithContents->True, Editable->False, SelectWithContents->True]\)

HIDE DETAILS
pic = \!\(\* NamespaceBox["LinguisticAssistant", DynamicModuleBox[{Typeset`query$$ = "picture of a bird", Typeset`boxes$$ = RowBox[{"EntityValue", "[", RowBox[{ TemplateBox[{"\"birds\"", RowBox[{"Entity", "[", RowBox[{"\"Species\"", ",", "\"Class:Aves\""}], "]"}], "\"Entity[\\\"Species\\\", \\\"Class:Aves\\\"]\"", "\"species specification\""}, "Entity"], ",", TemplateBox[{"\"image\"", RowBox[{"EntityProperty", "[", RowBox[{"\"Species\"", ",", "\"Image\""}], "]"}], "\"EntityProperty[\\\"Species\\\", \\\"Image\\\"]\""}, "EntityProperty"]}], "]"}], Typeset`allassumptions$$ = {{ "type" -> "MultiClash", "word" -> "", "template" -> "Assuming ${word1} is referring to ${desc1}. Use \ \"${word2}\" as ${desc2}. Use \"${word3}\" as ${desc3}. Use \ \"${word4}\" as ${desc4}. Use \"${word5}\" as ${desc5}.", "count" -> "5", "Values" -> {{ "name" -> "Species", "word" -> "bird", "desc" -> "a species specification", "input" -> "*MC.%7E-_*Species-"}, { "name" -> "Movie", "word" -> "bird", "desc" -> "a movie", "input" -> "*MC.%7E-_*Movie-"}, { "name" -> "PopularCurve", "word" -> "bird", "desc" -> "a popular curve", "input" -> "*MC.%7E-_*PopularCurve-"}, { "name" -> "Person", "word" -> "a bird", "desc" -> "a person", "input" -> "*MC.%7E-_*Person-"}, { "name" -> "WordData", "word" -> "", "desc" -> " referring to English words", "input" -> "*MC.%7E-_*WordData-"}}}}, Typeset`assumptions$$ = {}, Typeset`open$$ = {1}, Typeset`querystate$$ = { "Online" -> True, "Allowed" -> True, "mparse.jsp" -> 3.073973`6.939245042085039, "Messages" -> {}}}, DynamicBox[ToBoxes[ AlphaIntegration`LinguisticAssistantBoxes["", 4, Automatic, Dynamic[Typeset`query$$], Dynamic[Typeset`boxes$$], Dynamic[Typeset`allassumptions$$], Dynamic[Typeset`assumptions$$], Dynamic[Typeset`open$$], Dynamic[Typeset`querystate$$]], StandardForm], ImageSizeCache->{112., {7., 16.}}, TrackedSymbols:>{ Typeset`query$$, Typeset`boxes$$, Typeset`allassumptions$$, Typeset`assumptions$$, Typeset`open$$, Typeset`querystate$$}], DynamicModuleValues:>{}, UndoTrackedVariables:>{Typeset`open$$}], BaseStyle->{"Deploy"}, DeleteWithContents->True, Editable->False, SelectWithContents->True]\)

Reflect the picture top-to-bottom. Try other reflections, like LeftRight:

Note: run the previous step first to define pic.

SHOW/HIDE DETAILS

Reflect a picture top-to-bottom:

ImageReflect[pic, Top -> Bottom]

Reflect the same picture left-to-right:

ImageReflect[pic, Left -> Right]

HIDE DETAILS
ImageReflect[pic, Top -> Bottom]

Join the picture and its reflection:

SHOW/HIDE DETAILS

ImageAssemble assembles grids of images.

This assembles an image from one image repeated in two rows, three copies per row:

ImageAssemble[{ {pic, pic, pic}, {pic, pic, pic} }]

Use ImageAssemble to join an image with its reflection:

ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]} }]

HIDE DETAILS
ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]} }]

Reflect again vertically. Try making other patterns with different combinations of reflections:

Note: reflections other than Left->Right and Top->Bottom will give different-size images that cant be assembled.

SHOW/HIDE DETAILS

Heres the picture joined with its horizontal reflection:

ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]} }]

Add a second row just like the first one:

ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]}, {pic, ImageReflect[pic, Left -> Right]} }]

Reflect the pictures in the second row top-to-bottom by wrapping them with ImageReflect[,Top->Bottom]:

ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]}, {ImageReflect[pic, Top -> Bottom], ImageReflect[ImageReflect[pic, Left -> Right], Top -> Bottom]} }]

HIDE DETAILS
ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]}, {ImageReflect[pic, Top -> Bottom], ImageReflect[ImageReflect[pic, Left -> Right], Top -> Bottom]} }]

Repeat two times. Try more times:

Note: it may take a long time to run the code if you repeat more than 4 times.

SHOW/HIDE DETAILS

Well want to repeat the reflect-and-assemble step several times. Thats most easy to do if the code is rewritten as a pure function.

Heres the ImageAssemble expression:

ImageAssemble[{ {pic, ImageReflect[pic, Left -> Right]}, {ImageReflect[pic, Top -> Bottom], ImageReflect[ImageReflect[pic, Left -> Right], Top -> Bottom]} }]

Heres the same expression rewritten as a pure function applied to the picture. Wherever # occurs in the function, its replaced by pic:

ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &[pic]

Apply the reflect-and-assemble function to the picture repeatedly using Nest.

This applies the function f to 0 three times:

Nest[f, 0, 3]

This is a pure function that adds 1 to a number:

(# + 1) &

Applying the function to 0 gives 1:

(# + 1) &[0]

Applying the function three times gives 3:

Nest[(# + 1) &, 0, 3]

Apply the reflect-and-assemble function to the picture two times:

Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, pic, 2]

HIDE DETAILS
Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, pic, 2]

Resize the picture to keep it from getting too large. Try sizes other than 400:

SHOW/HIDE DETAILS

The picture gets larger the more times you nest:

Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, pic, 3]

Reduce the size of the result with ImageResize:

ImageResize[Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, pic, 3], 400]

HIDE DETAILS
ImageResize[Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, pic, 3], 400]

Share Itmake a picture pattern website:

SHOW/HIDE DETAILS

Deploy a website that makes patterns from a picture that you upload:

CloudDeploy[ FormFunction[{"pic" -> "Image"}, ImageResize[Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, #pic, 3], 400] &, "PNG"], "Permissions" -> "Public" ]

Click the link in the output to visit the site.

Tell the world about your creation by sharing the link via email, tweet or other message.

HIDE DETAILS
CloudDeploy[ FormFunction[{"pic" -> "Image"}, ImageResize[Nest[ImageAssemble[{ {#, ImageReflect[#, Left -> Right]}, {ImageReflect[#, Top -> Bottom], ImageReflect[ImageReflect[#, Left -> Right], Top -> Bottom]} }] &, #pic, 3], 400] &, "PNG"], "Permissions" -> "Public" ]