Escher Code For Mathmap

########################################

## Droste Effect code for Mathmap ##

## Original Code by Breic (Ben) ##

## Adapted by Pisco Bandito (Josh) ##

## Version 4.0 ##

## This version for Windows and Linux ##

########################################

#You may need to alter the values of the following 9 variables to suit your image.

r1=.4; # r1 is the inner radius. r1 is greater than zero and less than r2

r2=1; # r2 is the outer radius. r2 is greater than r1 and less than 1

p1=1; # periodicity - the number of times the image will repeat per cycle

p2=1; # number of strands - the number of "arms" the spiral will have

  1. procedural scaling and rotation

zoom=.1; #Between .1 and 10

rotate=-30; #Between -360 and 360

  1. Procedural Shifting

xShift=.2; #Between -1 and 1

yShift=0; #Between -1 and 1

##

  1. To avoid framing problems on the largest annulus when tiling based on transparency, look
  1. outside (levelsToLookOut) levels to see if something farther out should cover up this pixel
  1. Try setting to 0 to see framing errors; 1 should be sufficient unless you have three or more
  1. image layers contributing to some pixel (in which case set it to 2 or more). Larger values
  1. slow the code down, and may lead to floating point errors.

##

levelsToLookOut=3;

############################################################

############################################################

## You should not have to change anything below this line ##

############################################################

############################################################

imageX=W; # image size, in pixels

imageY=H;

minDimension=min(imageX, imageY);

## User Variables, set these on the User Settings Tab ##

retwist=user_bool("Do Not Retwist (Leave Unchecked for Droste Effect)");

retwist=!retwist;

##

  1. Tiling can be based on transparency (if the input image is a tiff), or simply based on the
  1. radius. Using transparency, there can be protrusions between different annular layers.
  1. Tiling based on transparency, you can decide whether you want to look inward or
  1. outward from a transparent pixel. For example, with a frame you'll want to look inward,
  1. while for a flower you'll want to look outward.

##

tileBasedOnTransparency=user_bool("Tile Based on Transparency?");

transparentPointsIn=user_bool("Transparency Points In?");

  1. Miscellaneous variables

true=1;

false=0;

epsilon=.01;

##Correct the Rotation Variable

rotate=pi/180*rotate;

##

  1. Droste-effect code starts here
  1. Set Droste effect parameters

##

alpha=atan(p2/p1*log(r2/r1)/(2*pi));

f=cos(alpha);

beta=f*exp(I*alpha);

  1. the angle of rotation between adjacent annular levels

if (p2 > 0)

then angle = 2*pi*p1;

else

angle =-2*pi*p1;

end;

##

  1. Code to set up the viewport properly

##

if (retwist) then

xbounds=[-r2,r2];

ybounds=[-r2,r2];

else

ybounds=[0,2.1*pi];

xbounds=[-log(r2/r1), log(r2/r1)];

end;

xymiddle=ri:[0.5*(xbounds[0]+xbounds[1]),0.5*(ybounds[0]+ybounds[1])];

xyrange=xy:[xbounds[1]-xbounds[0], ybounds[1]-ybounds[0]];

aspectRatio=W/H;

xyrange[0]=xyrange[1]*aspectRatio;

xbounds=[xymiddle[0]-0.5*xyrange[0],xymiddle[0]+0.5*xyrange[0]];

z=ri:[(xbounds[0]+(xbounds[1]-xbounds[0])*(x+W/2)/W)+xShift,(ybounds[0]+(ybounds[1]-ybounds[0

])*(y+H/2)/H)+yShift];

if (retwist) then # only allow for procedural zooming/scaling in the standard coordinates

zinitial=z;

z=xymiddle+(z-xymiddle)/zoom*exp(-I*rotate);

else

zinitial=r1*exp(z); # save these coordinates for drawing a frame later

zinitial=zinitial*zoom*exp(I*rotate);

end;

##

  1. The Droste effect math all takes place over the next six lines.
  1. All the rest of the code is for niceties.

##

if (retwist) then

z2=log(z/r1);

else

z2 = z;

end;

logz=z2; # save these coordinates for drawing a grid later

z=p1*z2/beta;

rotatedscaledlogz=z; # save these coordinates for drawing a grid later

z=r1*exp(z);

## End Droste effect math

## Tiling

if (tileBasedOnTransparency && levelsToLookOut > 0) then

if ( transparentPointsIn) then ratio=r1/r2*exp(-I*angle); end;

if (!transparentPointsIn) then ratio=r2/r1*exp( I*angle); end;

z=z*exp(levelsToLookOut*log(ratio));

end;

##

  1. When tiling based on transparency, color is accumulated into the colorSoFar variable,
  1. while alphaRemaining tells how much remains for lower layers to contribute (initially 1,
  1. finally 0).

##

colorSoFar=rgba:[0,0,0,0];

alphaRemaining=1;

ix=minDimension/2*z[0];

iy=minDimension/2*z[1];

color=origValXY(ix,iy);

colorSoFar = colorSoFar + (color*(alpha(color)*alphaRemaining));

alphaRemaining=alphaRemaining*(1-alpha(color));

  1. do we need to look inward from the current point, or outward?

sign=0;

if (tileBasedOnTransparency) then

if ( transparentPointsIn && alphaRemaining > epsilon) then sign=-1; end;

if (!transparentPointsIn && alphaRemaining > epsilon) then sign= 1; end;

else

radius=sqrt(z[0]*z[0]+z[1]*z[1]);

if (radius < r1) then sign=-1; end;

if (radius > r2) then sign= 1; end;

end;

if (sign < 0) then ratio=r2/r1*exp( I*angle); end;

if (sign > 0) then ratio=r1/r2*exp(-I*angle); end;

##

  1. Iteratively move inward or outward, until
  1. the point has radius r in [r1, r2), if tileBasedOnTransparency=false
  1. or until alphaRemaining=0, if tileBasedOnTransparency=true
  1. In the latter case, we accumulate color at each step

##

iteration=0; maxiteration=10;

while (sign != 0 && iteration < maxiteration) do

z2=z*ratio;

z=z2;

rotatedscaledlogz=rotatedscaledlogz+ri:[0,-sign*angle];

ix=minDimension/2*(z[0]);

iy=minDimension/2*(z[1]);

color=origValXY(ix,iy);

colorSoFar = colorSoFar + (color*(alpha(color)*alphaRemaining));

alphaRemaining=alphaRemaining*(1-alpha(color));

radius=sqrt(z[0]*z[0]+z[1]*z[1]);

sign=0;

if (tileBasedOnTransparency) then

if ( transparentPointsIn && alphaRemaining > epsilon) then sign=-1; end;

if (!transparentPointsIn && alphaRemaining > epsilon) then sign= 1; end;

else

radius=sqrt(z[0]*z[0]+z[1]*z[1]);

if (radius < r1) then sign=-1; end;

if (radius > r2) then sign= 1; end;

end;

iteration=iteration+1;

end;

color=colorSoFar;

color=rgba:[color[0], color[1], color[2], 1]; # set the alpha value to 1 (it could be <1 if the loop terminated at # iteration maxiteration)

#This last line is important, it returns the pixel value for the current pixel

color

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.