New Tutorial / Example File

I spent a little time working up a MATLAB tutorial file that does a little more explanation.  It talks about open source code licensing and creative commons copyright.  It shows some basic MATLAB drawing examples, it emulates a specific work, shows how to parameterize and randomize the code, then shows one way to re-create a single image from a set of parameters.  

I tested it in Octave Online and most seems to work.  Octave Online Link

Images for tutorial from / inspired by Claisse.

Tutorial file download:   tutorial.m




% Open Source Art Project Tutorial
% 2022 Ed Gatzke (1/20/2022) epg@sc.edu
%
% This tutorial is organized as follows:
%  1.  Licensing.  The source code is open source
%  2.  MATLAB drawing basics
%  3.  Emulating a type of art example
%  4.  Making the code randomize the output
%  5.  Parameterizing the code for reproducibilty
%  6.  User-defined functions 
%
% HOW TO USE THIS TUTORIAL
%  Start MATLAB and type edit at the >> prompt then hit return/enter
%  Open the file (tutorial.m) in the editor using the open button
%  Read throught the file, hitting the Run button or F5 to execute code
%  At some points there are lines with the command return to stop code
%  You can delete the return funtion or comment out the return to run more
%
%
%% Code Licensing Section
%
% Code licensed under GPL v3.0
% https://www.gnu.org/licenses/gpl-3.0.en.html
%
% Simple explanation:  Software code based on these works must remain free! 
%
% The GPL grants open-source permissions for users including:
% The right to download and run the software freely
% The right to make changes to the software as desired
% The right to redistribute (or even sell!) copies of the software
% The right to modify and distribute copies of new versions of the software

% Open-source code requires that the source code remain available to users
% so that folks can improve and fix things.  Imagine a company makes a
% product and sells it but then goes out of business.  The software product
% could never be developed further!  With open-source code, others can fix
% bugs and make improvements.  
%
% One catch is that you are required to release changes in the code if you
% sell it.  Some companies will take open-source code, make lots of
% modifications and improvements, but never sell a product so they never
% have to release the code back to the community.  Their software product
% is just used internally, never sold so they never have to release code.
%
%
% This code can be used to make art. Art released from epg is released with
% a creative commons license but other users with derivative works can 
% select any license they want.  The creative commons license is very close 
% being a "public domain" license but iit does require folks to give credit
%
% Art licensed under Creative Commons Attribution 3.0 Unported
% https://creativecommons.org/licenses/by/3.0/
% Simple explanation:  This is not "public domain!" You are free to:
% Share — copy and redistribute the material in any medium or format
% Adapt — remix, transform, and build upon the material for any purpose,
% even selling the works commercially.
% The licensor cannot revoke freedoms as long as you follow the terms.
% Under the following terms:
% Attribution — You must give appropriate credit, provide a link to the 
% license, and indicate if changes were made. You may do so in any 
% reasonable manner, but not in any way that suggests the licensor endorses 
% you or your use.
% No additional restrictions — You may not apply legal terms or 
% technological measures that legally restrict others from doing anything 
% the license permits.
%
%
% This work inspired by Genvive Classie
% https://en.wikipedia.org/wiki/Genevi%C3%A8ve_Claisse
%% 2.  MATLAB Drawing Basics
% Matlab draws to a figure window.  This turns off some menu stuff
close all  % This closes all the open figures
figure('Name','Art','NumberTitle','off') % New fig with window title
set(gcf, 'MenuBar', 'none');  % Clear out some of the stuff in a figure
set(gcf, 'ToolBar', 'none');  % Remove the toolbar too!
% gcf is the current figure data object.
get(gcf) % You can see what data is available for an object
pos=get(gcf,'Position');  % You can get a specific set of data
pos(1)=1200;   % Move the x value over to 1200
set(gcf,'Position',pos);  % Change the vector that describes position
% MATLAB will erase the whole figure when you draw to it a second time.  To
% avoid this, you have to turn on the hold feature
hold on
% We are going to draw to a grid, from 0 to xmax and 0 to ymax.  (0,0) is
% in the bottom left corner, (xmax,ymax is top right)
xmax=10;
ymax=10;
% fill can be used to specify a shape by the corners of the shape for x & y
% The last argument is a vector for red, green, blue ranging 0 to 1
fa=fill([0 xmax xmax 0],[0 0 ymax ymax],[1 0 0]);  % Big red box
fb=fill([1 2 1],[ 1 1  2],[0 1 0]);  % Tiny green triangle
fc=fill([4 5 6 5 4 3],[ 4 4 5 6 6 5],[0 0 1]);  % blue hexagon
fd=fill([4 5 6 5 4 3],[ 4 4 5 6 6 5]+3,[0 0 1]);  % blue hexagon shifted up
% The output value of fill is the data object.  Look in the command window
% to see all the various attributes that can be modified.
get(fd)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 % return function stops the code at that point!!!
 
return % Add a comment symbol % before return to continue on!!!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% You can use the object value to change attributes for an object
set(fd,'FaceAlpha',.4) % Reducing alpha makes the object more transparent
% The fill command objects all include a different edge color.  The edge
% can be removed by change the attribute.
set(fa,'edgecolor','none')
set(fb,'edgecolor','none')
set(fc,'edgecolor','none')
set(fd,'edgecolor','none')

% There is a user-defined function to make nice circles.  The following
% makes a circle centered at 7,3 with radius 2 that is white and alpha
% value of 0.8, so partially transparent.  User-defined functions can be at
% the bottom of a .m script file or in their own .m file
circles(7,3,2,[1 1 1],.8);
% Another user-defined function (at bottom of the file) can easily make a
% rectangle.  This makes a rectangle with the bottom left corner at (1,3)
% that is .5 wide, 4 high, black, and no transparency (alpha = 1)
rectangle(1,3,.5,4,[0 0 0],1);
% Another user-defined function at the bottom will rotate a list of points
% by a given number of degrees.  Consider a triangle with vertices at the
% points (3,1) (4,1) & (3,2) that rotates CCW by 20 degrees:
[xx,yy]=rotate([3 4 3],[ 1 1  2],20);
fe=fill(xx,yy,[0 1 0],'edgecolor','none');  % Tiny green rotated triangle
% Now make a skinny rectangle and rotate it clockwise (CW) by 20
[xx,yy]=rotate([7 7.5 7.5 7],[ 6 6 9 9],-20); % Rotate clockwise 20
ff=fill(xx,yy,[1 1 1],'edgecolor','none');    % Rotated white rectangle 
% How about a star?
x=[-1 -.1 0 .1 1 .1 0 -.1]+3;  % Make points then shift over and up
y=[0 .1 1 .1 0 -.1 -1 -.1]+3;
[xx,yy]=rotate(x,y,-45); % Rotate clockwise 45
fg=fill(x,y,[1 1 0],'edgecolor','none');   % Yellow star
fh=fill(xx,yy,[1 1 0],'edgecolor','none'); % Yellow star rotated


% The following stuff cleans up the plot a bit.  MATLAB likes to treat most
% figures as a numeric plot, not a drawing canvas.
axis([0 max([xmax ymax]) 0 max([xmax ymax])]);  % make sure it is square
axis square;
set(gca,'XTickLabel',[],'YTickLabel',[]);  % Get rid of figure stuff
set(gca,'XTick',[],'YTick',[]);
set(gcf,'color',[1 1 1]);
set(gca,'XColor',[1 1 1],'YColor',[1 1 1]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
return  % Code will stop here if not commented out with % symbol!!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
% The previous code was to give examples of drawing simple objects using
% MATLAB functions and some user-defined functions that may help make
% simple shapes.
%

%% 3.  Emulating a type of art example
% Genevieve Claisse is a geometrical abstract painter.
% A simple image with yellow, black, white, and blue circles is here:
% https://alchetron.com/Genevi%C3%A8ve-Claisse
%
% Colors can be found using color picking web sites like:
% https://imagecolorpicker.com/
%
% The rectangle is rgba(249,193,24,255)
% White circle is rgba(230,224,210,255)
% Dark circle is rgba(17,18,13,255)
% Blue circle is rgba(44,53,108,255)
% Inner cirlce is rgba(232,161,11,255)
%
% Note these numbers run 0 to 255, not 0 to 1.
% Also note that the alpha value is given as well (all are high=1.0)
% Also realize the web site gives a nice color pallette for the image, a
% suite of related colors that should go nicely together based on the 
% colors found in the image.

% Create a background box rectangle using the first color
% Remember, using a figure size of 10x10
alph=1;
cr=[249,193,24]/255;   % Color for box converted to 0-1 range
f=fill([0 xmax xmax 0],[0 0 ymax ymax],cr);
set(f,'edgecolor','none','facealpha',alph);
% Now we need the circles.  Let's extract all their colors now:
cac=[230,224,210]/255; % White big
cbc=[17,18,13]/255;    % Dark big
ccc=[44,53,108]/255;   % Blueish medium
cdc=[232,161,11]/255;  % Inner yellow medium
% Now draw the circles.  I played around with the centers and radii until
% they matched the original pretty well.  I got one close then added
% another and another, I didn't try to do all at once.  For this one, each
% pair shares a center.
circles(5,5,4.5,cac,alph);
circles(5,5,3.75,cbc,alph);
circles(4.4,4.4,2.85,ccc,alph);
circles(4.4,4.4,2.4,cdc,alph);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
return  % Code will stop here if not commented out with % symbol!!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




%%  4.  Making the code randomize the output
% This is nice to almost exactly copy, but instead we would like to make a
% new work inspired by the original.  This type of artwork is often called
% a pastiche.
% This means the code will pick some values to randomize.  At the same
% time, we will collect all the random values so we could "save" the
% requisite numbers needed to regenerate the art later on.
% Set up some local variables to make parameters for the art.  Some of the
% parameter values will change each time the code is run.
% For this, we will just put randomly sized circles in random locations
ncirc=3;  % How many circles?
p=[ncirc xmax ymax];  % make parameter vector p to reproduce image
% Some things will be random.  Collecting all the values allows the image
% to be recreated given the parameter string
% MATLAB has multiple color maps with related colors.  The names are
% specified below in the cmaps list for  some of them
map=3;  % Which colormap to use, 1<map<13
% What are the names of all the color maps?
cmaps={'parula' 'jet' 'hsv' 'hot' 'cool' 'spring' 'summer' 'autumn' ...
    'winter'   'gray' 'bone' 'copper' 'pink'};
% Use the colormap function to get the color map
% The colormap name string length can change!  That is why it is a {} list 
% The number of related colors desired is nc
nc=10  % Number of colors to pull from colormap
% MATLAB can create an arbitrary function call then evaluate it internally
str=['cm=colormap(' cmaps{map} '(nc));']; % Make the MATLAB "command"
eval(str);  % This evaluates a string like you typed it
cmi=randperm(nc); % Pick a random order for the colors using randperm
cm=cm(cmi,:);     % Re-order the colors randomly, should be a matrix of nc 
% rows and 3 columns since we wanted nc different related colors
whos cm

% Create a background box rectangle using the first random color
alph=1;
f=fill([0 xmax xmax 0],[0 0 ymax ymax],cm(1,:));
set(f,'edgecolor','none','facealpha',alph);
p=[p cm(1,:) alph];  % Add background fill color to parameter
%Make some circles of decreasing size
% rand() gives a uniform distribution ranging 0 to 1
for i=(ncirc+1):-1:2  % This increments down instead of up!  For three 
    % circles, the counter i will be 4 then 3 then 2!
    alph=1;
    xc=3+rand()*4;  % This ranges from -1 to 7
    yc=3+rand()*4;  % This ranges from -1 to 7
    cr=(i/2)+(i/2)*rand(); % The radius probably is biggest first iteration
    % So the first radius will range from 2-4, second 1.5-3, third is 1-2
    
    circles(xc,yc,cr,cm(i,:),alph); % Draw the circle on top of others
    
    % Save the numbers needed to created this random circle!
    p=[p xc yc cr cm(i,:) alph];  % Add circle fill color to parameter list
    
end

% Clean up the figure nicely here:
axis([0 max([xmax ymax]) 0 max([xmax ymax])]);  % make sure it is square
axis square;
set(gca,'XTickLabel',[],'YTickLabel',[]);  % Get rid of figure stuff
set(gca,'XTick',[],'YTick',[]);
set(gcf,'color',[1 1 1]);
set(gca,'XColor',[1 1 1],'YColor',[1 1 1]);


% Instead of commenting out code to not run, you can use an IF statement.
% Using the variable named printimage, it can serve as a toggle.  Setting
% the variable to 0 will turn off saving the image, setting it to a value
% of 1 will allow the IF statement to run so the image is saved to file
printimage=0  % Set this value to 1 to save a jpg/png image file!  0 to not
 
if printimage>0  % Start image printing code here!
    
    % You can print the image to file.  Two image options are jpeg and png
    print testfile.jpg -djpeg
    print testfile.png -dpng
    
    % If you investigate these images, a png typically looks better than a
    % jpg when you zoom in.  However, they both are a bit "pixelated".  One
    % option in MATLAB to generate higher quality images is to expand the
    % figure before you save it.
    
    pos=get(gcf,'Position')
    posnew=[pos(1) pos(2) 20*pos(3) 20*pos(4)];
    set(gcf,'Position',posnew)
    print testfileBIG.png -dpng
    set(gcf,'Position',pos)  % The original window size needs to be set 
    % back because the giant window puts controls where you can't move it
    % JPG images use lossy image compression.  Depending on the amount of
    % compression, you can get blotchy colors near crisp color transitions.
    % PNG images do not use compression so you get fewer issues.
    
end  % End for image printing code here


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
return  % Code will stop here if not commented out with % symbol!!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%  5.  Parameterizing the code for reproducibilty

% After running the code a few times, I saw a nice looking random example 
% so I kept the parameter vector that should have all the numbers we need 
% to reproduce it.  The parameters for the image I liked were:
p=[ 3.0000 10.0000 10.0000 0.8000 0 1.0000 1.0000 4.0486 3.1778 3.5099 ...
0.8000 1.0000 0 1.0000 3.9711 4.7696 2.5317 0.2000 1.0000     0 1.0000 ...
4.4369 5.9454 1.3947 0.2000     0 1.0000 1.0000]
% What are these numbers we defined from above?  The were defined as:
% p=[ncirc xmax ymax]; % General parameters (3)
% p=[p cm(1,:) alph];  % Adds background fill color parameters (4)
% p=[p xc yc cr cm(i,:) alph];  % Adds circle fill info to parameter 3x(7)
%
% The 28 numbers in my p vector should be enough to reproduce my nice image
% Note this is generalized so that I could change the numer of circles
% above from 3 to something else and my code may still run.
ncirc=p(1);  % How many circles?
xmax=p(2);   % How big is my canvas in x direction?
ymax=p(3)    % How big is my canvas in the y direction?
bc=p(4:6)    % Get background color for canvas
bca=p(7);    % Background canvas alpha
f=fill([0 xmax xmax 0],[0 0 ymax ymax],bc,'facealpha',bca);
% Now use the rest of the parameters to draw the circles for the nice image
% I liked.  
for i=1:ncirc  % FOR each circle
    % Extract the seven parameters needed for the circle.  This is tricky
    % to index properly.  There are seven values for the first circle.  The
    % first circle starts at element 8 and ends at 14, second is 15 to 21,
    % third is 22 to 28.  The index variable i counts up 1, 2, 3:
    cdata=p(7+(i-1)*7+1:7+7*i); % grab all seven parameters for this circle
    xc=cdata(1);    % center for x
    yc=cdata(2);    % center for y
    cr=cdata(3);    % circle radius
    cc=cdata(4:6);  % circle color
    alph=cdata(7);  % circle alpha
    circles(xc,yc,cr,cc,alph);
end
% Now, every time the code is run, the exact same image will be produced
% based on the parameters in my vector p.  The vector p is basically the
% "fingerprint" for my image that should hold enough information to
% reproduce the original image.  Now I can run the random code until I find
% another nice image, save the corressponding vector p so that I can remake
% the image (or make minor modifications) any time I want.

% Nice sets of data can be saved using the save command.  The following
% will make a claisse_nice.mat data file with the vector p
% save claisse_nice p  % This will save the vector in the mat file
% load claisse_nice    % This loads the data file
% If you only have a single variable to save, you can save as an ASCII text
% file so that other applications could use the data.  Sometimes email
% systems will not let you email a MATLAB data file with a .mat extension
% because some .mat files are "dangerous" to PC systems.
% save -ascii claisse_nice.txt p

% Howver, when you load the text file, the variable is jsut the file name
% load claisse_nice.txt   % This will load the text file
% p=claisse_nice    % This will make a copy of the data into variable p


%% 6. User-defined functions
%
% These functions are provided to help do simple things like draw a
% rectangle, draw a circle, or rotate a set of points
%
% These functions can be called from inside this file.
% You can modify the functions if you want.


function [f,X,Y]=rectangle(x,y,dx,dy,c,alph)
% This function draws a rectangle with lower left corner at the point (x,y)
% of dx width and dy height with color c and alpha alph
X=[x x+dx x+dx x];
Y=[y y y+dy y+dy];
f=fill(X,Y,c);
set(f,'edgecolor','none','facealpha',alph);
end

function [f,x,y]=circles(xc,yc,r,c,alph)
% This function draws a circle of radius r and color c and alpha alph
% centered at the point (xc,yc).  f is the fill handle object, x and y are
% the sets of x,y points used.
a=[0:0.001:2*pi];
for i=1:length(a)
    x(i,1)=r*cos(a(i));
    y(i,1)=r*sin(a(i));
end
x=[x ; x(1)];
y=[y ; y(1)];
x=x+xc;
y=y+yc;
f=fill(x,y,c);
set(f,'edgecolor','none','facealpha',alph);

end

function [xx,yy]=rotate(x,y,theta)
% This function takes a list of x,y points, finds a center for them and
% rotates them by theta degrees around the center.
xc=min(x)+(max(x)-min(x))/2;
yc=min(y)+(max(y)-min(y))/2;
dx=x-xc;
dy=y-yc;
rad=theta*pi/180;
xx=cos(rad)*dx-sin(rad)*dy+xc;
yy=sin(rad)*dx+cos(rad)*dy+yc;
end


Comments

Popular posts from this blog

Inspired By Andy Goldsworthy

What is the Open Source Art Project?

Inspired by Piet Mondrian