{"id":992,"date":"2016-04-29T12:14:33","date_gmt":"2016-04-29T10:14:33","guid":{"rendered":"https:\/\/esimov.com\/blog\/?p=992"},"modified":"2016-11-21T09:21:14","modified_gmt":"2016-11-21T07:21:14","slug":"mandelbrot-renderer-in-go","status":"publish","type":"post","link":"https:\/\/esimov.com\/blog\/2016\/04\/29\/mandelbrot-renderer-in-go\/","title":{"rendered":"Mandelbrot renderer in Go"},"content":{"rendered":"<p>Lately i&#8217;ve been playing around a lot with the Go language, and wanted to put it something together which is somehow related to the graphics part of the language. Mandelbrot image set generator was a well suited candidate for this task, because of the calculation complexity and the iteration count used to generate the fractal image, Go being a language capable to communicate and share different pools of resources via channels and goroutines.<\/p>\n<p>The goroutine is used when i&#8217;m iterating over the two dimensional array, defined as a 2d system coordinate and applying the mathematical calculation prior to generate the mandelbrot set. The mandelbrot set is generated by applying a mathematical function to each complex number projected in the complex plane and determining for each whether they are bounded or escapes towards infinity.<\/p>\n<p>The mandelbrot is defined by the following formula: <kbd>z_{n+1} = z_n^2 + c.<\/kbd>. For example, letting <kbd>c = 1<\/kbd> gives the sequence <kbd>0, 1, 2, 5, 26,\u2026,<\/kbd> which tends to infinity. As this sequence is unbounded, <kbd>1<\/kbd> is not an element of the Mandelbrot set. On the other hand, <kbd>c = -1<\/kbd> gives the sequence <kbd>0, -1, 0, -1, 0,\u2026,<\/kbd> which is bounded, and so <kbd>-1<\/kbd> belongs to the Mandelbrot set.<\/p>\n<pre class=\" language-go\"><code class=\" language-go\">\r\n<span class=\"token keyword\">for<\/span> iy <span class=\"token operator\">:=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> iy <span class=\"token operator\">&lt;<\/span> height<span class=\"token punctuation\">;<\/span> iy<span class=\"token operator\">++<\/span> <span class=\"token punctuation\">{<\/span>\r\n\twaitGroup<span class=\"token punctuation\">.<\/span><span class=\"token function\">Add<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span>\r\n\t<span class=\"token keyword\">go<\/span> <span class=\"token keyword\">func<\/span><span class=\"token punctuation\">(<\/span>iy <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t<span class=\"token keyword\">defer<\/span> waitGroup<span class=\"token punctuation\">.<\/span><span class=\"token function\">Done<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span>\r\n\r\n\t\t<span class=\"token keyword\">for<\/span> ix <span class=\"token operator\">:=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> ix <span class=\"token operator\">&lt;<\/span> width<span class=\"token punctuation\">;<\/span> ix<span class=\"token operator\">++<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t\t<span class=\"token keyword\">var<\/span> x <span class=\"token builtin\">float64<\/span> <span class=\"token operator\">=<\/span> xmin <span class=\"token operator\">+<\/span> <span class=\"token punctuation\">(<\/span>xmax<span class=\"token operator\">-<\/span>xmin<span class=\"token punctuation\">)<\/span><span class=\"token operator\">*<\/span><span class=\"token function\">float64<\/span><span class=\"token punctuation\">(<\/span>ix<span class=\"token punctuation\">)<\/span><span class=\"token operator\">\/<\/span><span class=\"token function\">float64<\/span><span class=\"token punctuation\">(<\/span>width<span class=\"token number\">-1<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t\t<span class=\"token keyword\">var<\/span> y <span class=\"token builtin\">float64<\/span> <span class=\"token operator\">=<\/span> ymin <span class=\"token operator\">+<\/span> <span class=\"token punctuation\">(<\/span>ymax<span class=\"token operator\">-<\/span>ymin<span class=\"token punctuation\">)<\/span><span class=\"token operator\">*<\/span><span class=\"token function\">float64<\/span><span class=\"token punctuation\">(<\/span>iy<span class=\"token punctuation\">)<\/span><span class=\"token operator\">\/<\/span><span class=\"token function\">float64<\/span><span class=\"token punctuation\">(<\/span>height<span class=\"token number\">-1<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t\tnorm<span class=\"token punctuation\">,<\/span> it <span class=\"token operator\">:=<\/span> <span class=\"token function\">mandelIteration<\/span><span class=\"token punctuation\">(<\/span>x<span class=\"token punctuation\">,<\/span> y<span class=\"token punctuation\">,<\/span> maxIteration<span class=\"token punctuation\">)<\/span>\r\n\t\t\titeration <span class=\"token operator\">:=<\/span> <span class=\"token function\">float64<\/span><span class=\"token punctuation\">(<\/span>maxIteration<span class=\"token operator\">-<\/span>it<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">+<\/span> math<span class=\"token punctuation\">.<\/span><span class=\"token function\">Log<\/span><span class=\"token punctuation\">(<\/span>norm<span class=\"token punctuation\">)<\/span>\r\n\t\t\t\r\n\t\t\t<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token function\">int<\/span><span class=\"token punctuation\">(<\/span>math<span class=\"token punctuation\">.<\/span><span class=\"token function\">Abs<\/span><span class=\"token punctuation\">(<\/span>iteration<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;<\/span> <span class=\"token function\">len<\/span><span class=\"token punctuation\">(<\/span>colors<span class=\"token punctuation\">)<\/span><span class=\"token operator\">-<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t\t\tcolor1 <span class=\"token operator\">:=<\/span> colors<span class=\"token punctuation\">[<\/span><span class=\"token function\">int<\/span><span class=\"token punctuation\">(<\/span>math<span class=\"token punctuation\">.<\/span><span class=\"token function\">Abs<\/span><span class=\"token punctuation\">(<\/span>iteration<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span>\r\n\t\t\t\tcolor2 <span class=\"token operator\">:=<\/span> colors<span class=\"token punctuation\">[<\/span><span class=\"token function\">int<\/span><span class=\"token punctuation\">(<\/span>math<span class=\"token punctuation\">.<\/span><span class=\"token function\">Abs<\/span><span class=\"token punctuation\">(<\/span>iteration<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token operator\">+<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span>\r\n\t\t\t\tcolor <span class=\"token operator\">:=<\/span> <span class=\"token function\">linearInterpolation<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">RGBAToUint<\/span><span class=\"token punctuation\">(<\/span>color1<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">RGBAToUint<\/span><span class=\"token punctuation\">(<\/span>color2<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token function\">uint32<\/span><span class=\"token punctuation\">(<\/span>iteration<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>\r\n\r\n\t\t\t\timage<span class=\"token punctuation\">.<\/span><span class=\"token function\">Set<\/span><span class=\"token punctuation\">(<\/span>ix<span class=\"token punctuation\">,<\/span> iy<span class=\"token punctuation\">,<\/span> <span class=\"token function\">Uint32ToRGBA<\/span><span class=\"token punctuation\">(<\/span>color<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t\t<span class=\"token punctuation\">}<\/span>\r\n\t\t<span class=\"token punctuation\">}<\/span>\r\n\t<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">(<\/span>iy<span class=\"token punctuation\">)<\/span>\r\n<span class=\"token punctuation\">}<\/span>\r\n\r\n<\/code><\/pre>\n<p><\/p>\n<p>After applying the mathematical function to the same point projected in the complex plane infinite number of times we can check if its bounded or escapes towards infinity. If it&#8217;s bounded the iteration is restarted again.<\/p>\n<p>The mandelbrot function translated into Go code is looking like this:<\/p>\n<pre class=\" language-go\"><code class=\" language-go\">\r\n<span class=\"token keyword\">func<\/span> <span class=\"token function\">mandelIteration<\/span><span class=\"token punctuation\">(<\/span>cx<span class=\"token punctuation\">,<\/span> cy <span class=\"token builtin\">float64<\/span><span class=\"token punctuation\">,<\/span> maxIter <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token builtin\">float64<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t<span class=\"token keyword\">var<\/span> x<span class=\"token punctuation\">,<\/span> y<span class=\"token punctuation\">,<\/span> xx<span class=\"token punctuation\">,<\/span> yy <span class=\"token builtin\">float64<\/span> <span class=\"token operator\">=<\/span> <span class=\"token number\">0.0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0.0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0.0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0.0<\/span>\r\n\r\n\t<span class=\"token keyword\">for<\/span> i <span class=\"token operator\">:=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> i <span class=\"token operator\">&lt;<\/span> maxIter<span class=\"token punctuation\">;<\/span> i<span class=\"token operator\">++<\/span> <span class=\"token punctuation\">{<\/span> xy <span class=\"token operator\">:=<\/span> x <span class=\"token operator\">*<\/span> y xx <span class=\"token operator\">=<\/span> x <span class=\"token operator\">*<\/span> x yy <span class=\"token operator\">=<\/span> y <span class=\"token operator\">*<\/span> y <span class=\"token keyword\">if<\/span> xx<span class=\"token operator\">+<\/span>yy <span class=\"token operator\">&gt;<\/span> <span class=\"token number\">4<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t\t<span class=\"token keyword\">return<\/span> xx <span class=\"token operator\">+<\/span> yy<span class=\"token punctuation\">,<\/span> i\r\n\t\t<span class=\"token punctuation\">}<\/span>\r\n\t\tx <span class=\"token operator\">=<\/span> xx <span class=\"token operator\">-<\/span> yy <span class=\"token operator\">+<\/span> cx\r\n\t\ty <span class=\"token operator\">=<\/span> <span class=\"token number\">2<\/span><span class=\"token operator\">*<\/span>xy <span class=\"token operator\">+<\/span> cy\r\n\t<span class=\"token punctuation\">}<\/span>\r\n\r\n\tlog_zn <span class=\"token operator\">:=<\/span> <span class=\"token punctuation\">(<\/span>x<span class=\"token operator\">*<\/span>x <span class=\"token operator\">+<\/span> y<span class=\"token operator\">*<\/span>y<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token number\">2<\/span>\r\n\t<span class=\"token keyword\">return<\/span> log_zn<span class=\"token punctuation\">,<\/span> maxIter\r\n<span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p><\/p>\n<p>Treating the real and imaginary parts of each number as image coordinates, pixels are colored according to how rapidly the sequence diverges, if at all. For smooth color interpolation i&#8217;ve used <a href=\"http:\/\/paulbourke.net\/miscellaneous\/interpolation\/\">Paul Burke&#8217;s<\/a> <kbd>cosine interpolation<\/kbd> algorithm:<\/p>\n<pre class=\" language-go\"><code class=\" language-go\">\r\n<span class=\"token keyword\">func<\/span> <span class=\"token function\">cosineInterpolation<\/span><span class=\"token punctuation\">(<\/span>c1<span class=\"token punctuation\">,<\/span> c2<span class=\"token punctuation\">,<\/span> mu <span class=\"token builtin\">float64<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token builtin\">float64<\/span> <span class=\"token punctuation\">{<\/span>\r\n\tmu2 <span class=\"token operator\">:=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span> <span class=\"token operator\">-<\/span> math<span class=\"token punctuation\">.<\/span><span class=\"token function\">Cos<\/span><span class=\"token punctuation\">(<\/span>mu<span class=\"token operator\">*<\/span>math<span class=\"token punctuation\">.<\/span>Pi<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token number\">2.0<\/span>\r\n\t<span class=\"token keyword\">return<\/span> c1<span class=\"token operator\">*<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token operator\">-<\/span>mu2<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">+<\/span> c2<span class=\"token operator\">*<\/span>mu2\r\n<span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p><\/p>\n<p>The larger and scattered the color palette used the more intense and vivid the generated mandelbrot image is. By combining the following flag values: <kbd>-step<\/kbd>, <kbd>-palette<\/kbd> and <kbd>-iteration<\/kbd> you can obtain differently colorized mandelbrot sets, like in the screenshot below: <\/p>\n<p><a href=\"https:\/\/github.com\/esimov\/gobrot\"><img decoding=\"async\" src=\"https:\/\/esimov.com\/blog\/wp-content\/uploads\/2016\/04\/mandelbrot_sample-1024x576.jpg\" alt=\"mandelbrot_sample\" height=\"366\" class=\"aligncenter size-large wp-image-1013\" srcset=\"https:\/\/esimov.com\/blog\/wp-content\/uploads\/2016\/04\/mandelbrot_sample-1024x576.jpg 1024w, https:\/\/esimov.com\/blog\/wp-content\/uploads\/2016\/04\/mandelbrot_sample-768x432.jpg 768w, https:\/\/esimov.com\/blog\/wp-content\/uploads\/2016\/04\/mandelbrot_sample-650x366.jpg 650w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Because the rendering process could take some time, depending on the image resolution, the image smoothness and the iteration count, i thought that it would be a good idea to visualize the background process in terminal. For this purpose a good option was to use a different channel and signaling a tick on specified intervals. <kbd>time.Tick<\/kbd> is at rescue! On another channel i&#8217;m processing the image and when the rendering has been finished i&#8217;m sending a <kbd>done<\/kbd> signal to main goroutine, telling that the rendering process has been finished, which means i could stop the background indicator process.<\/p>\n<pre class=\"  language-go\"><code class=\"  language-go\">\r\ndone <span class=\"token operator\">:=<\/span> <span class=\"token function\">make<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">chan<\/span> <span class=\"token keyword\">struct<\/span><span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span>\r\nticker <span class=\"token operator\">:=<\/span> time<span class=\"token punctuation\">.<\/span><span class=\"token function\">NewTicker<\/span><span class=\"token punctuation\">(<\/span>time<span class=\"token punctuation\">.<\/span>Millisecond <span class=\"token operator\">*<\/span> <span class=\"token number\">100<\/span><span class=\"token punctuation\">)<\/span>\r\n\r\n<span class=\"token keyword\">go<\/span> <span class=\"token keyword\">func<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t<span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t<span class=\"token keyword\">select<\/span> <span class=\"token punctuation\">{<\/span>\r\n\t\t<span class=\"token keyword\">case<\/span> <span class=\"token operator\">&lt;-<\/span>ticker<span class=\"token punctuation\">.<\/span>C<span class=\"token punctuation\">:<\/span>\r\n\t\t\tfmt<span class=\"token punctuation\">.<\/span><span class=\"token function\">Print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">\".\"<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t<span class=\"token keyword\">case<\/span> <span class=\"token operator\">&lt;-<\/span>done<span class=\"token punctuation\">:<\/span>\r\n\t\t\tticker<span class=\"token punctuation\">.<\/span><span class=\"token function\">Stop<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t\tfmt<span class=\"token punctuation\">.<\/span><span class=\"token function\">Print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">\"Done!\"<\/span><span class=\"token punctuation\">)<\/span>\r\n\t\t\tfmt<span class=\"token punctuation\">.<\/span><span class=\"token function\">Printf<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">\"\\n\\nMandelbrot set rendered into `%s`\\n\"<\/span><span class=\"token punctuation\">,<\/span> outputFile<span class=\"token punctuation\">)<\/span>\r\n\t\t<span class=\"token punctuation\">}<\/span>\r\n\t<span class=\"token punctuation\">}<\/span>\r\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span>\r\n<\/code><\/pre>\n<h2>Install<\/h2>\n<p><strong>go get github.com\/esimov\/gobrot<\/strong><\/p>\n<p>Before to run the code you need to include the project into the GOPATH environment variable. See the documentation: <a href=\"https:\/\/golang.org\/doc\/code.html#GOPATH\">https:\/\/golang.org\/doc\/code.html#GOPATH<\/a><\/p>\n<h2>Run<\/h2>\n<p><strong>go run mandelbrot.go &#8211;help<\/strong><\/p>\n<p>Will give all the options supported by the renderer at the moment.<\/p>\n<p>Here are some options you can try out. (The attached images are generated using the below commands.)<\/p>\n<p style=\"font-family: monospace,serif;\">&#8211; go run mandelbrot.go -palette &#8220;Hippi&#8221; -xpos -0.0091275 -ypos 0.7899912 -radius .01401245 -file &#8220;test1.png&#8221;<\/p>\n<p style=\"font-family: monospace,serif;\">&#8211; go run mandelbrot.go -palette &#8220;Plan9&#8221; -xpos -0.0091275 -ypos 0.7899912 -radius .01401245 -file &#8220;test2.png&#8221; -iteration 600 -step 600<\/p>\n<p style=\"font-family: monospace,serif;\">&#8211; go run mandelbrot.go -palette &#8220;Hippi&#8221; -xpos -0.00275 -ypos 0.78912 -radius .1256789 -file &#8220;test3.png&#8221; -iteration 800 -step 6000 -smoothness 10 -width 1920 -height 1080<\/p>\n<p><\/p>\n<h2>TODO<\/h2>\n<ul>\n<li>\n<p>Generate various images with a single command<\/p>\n<\/li>\n<li>\n<p>Find dynamically the regions where a deep zoom will emerge new mandelbrot sets<\/p>\n<\/li>\n<ul>\n<h2>Resources<\/h2>\n<ul>\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Mandelbrot_set\">https:\/\/en.wikipedia.org\/wiki\/Mandelbrot_set<\/a><\/li>\n<li><a href=\"https:\/\/en.wikibooks.org\/wiki\/Fractals\/Iterations_in_the_complex_plane\/MandelbrotSetExterior\">https:\/\/en.wikibooks.org\/wiki\/Fractals\/Iterations_in_the_complex_plane\/MandelbrotSetExterior<\/a><\/li>\n<li><a href=\"http:\/\/linas.org\/art-gallery\/escape\/escape.html\">http:\/\/linas.org\/art-gallery\/escape\/escape.html<\/a><\/li>\n<li><a href=\"https:\/\/rosettacode.org\/wiki\/Mandelbrot_set\">https:\/\/rosettacode.org\/wiki\/Mandelbrot_set<\/a><\/li>\n<li><a href=\"https:\/\/youtu.be\/2AZYZ-L8m9Q\">https:\/\/youtu.be\/2AZYZ-L8m9Q<\/a><\/li>\n<\/ul>\n<p>Code on: <a href=\"https:\/\/github.com\/esimov\/gobrot\" class=\"github-link visible\"><span>Github<\/span><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mandelbrot image renderer written in Go. It&#8217;s using Go&#8217;s concurrent and parallel programming feature called goroutines. The output is highly customizable and the rendered mandelbrot set color palette is very adaptive due to the various color palettes (these can be extended easily) and the interpolation algorithm used to blend these colors together.<\/p>\n","protected":false},"author":1,"featured_media":1013,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[47,7,58,41,21],"tags":[69,59,60,71,70],"class_list":["post-992","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","category-experiments","category-go","category-programming","category-tutorials","tag-fractal","tag-go-2","tag-golang","tag-mandelbrot","tag-render"],"_links":{"self":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts\/992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/comments?post=992"}],"version-history":[{"count":0,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts\/992\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/media\/1013"}],"wp:attachment":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/media?parent=992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/categories?post=992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/tags?post=992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}