function photoToDots( src_file, dst_file, diameter )
% Load image and convert to gray scale
src_img = rgb2gray(im2double(imread(src_file)));
% Calculate the dimensions of the output image
rows = round(size(src_img, 1) / diameter);
cols = round(size(src_img, 2) / diameter);
% Resize, normalize and invert the source image
src_img = imresize(src_img, [rows cols], 'bicubic');
src_img = (src_img - min(src_img(:))) / (max(src_img(:) - min(src_img(:))));
src_img = 1 - src_img;
% Create an empty destination image
dst_img = zeros((rows+1)*diameter, (cols+1)*diameter);
% Draw the dots
for i = 1:cols
for j = 1:rows
x = i * diameter;
y = j * diameter;
% The size of the dot is determined by the darkness of the original pixel
r = sqrt(src_img(j, i) * diameter^2 / pi);
dst_img = addDot(dst_img, x, y, r);
end
end
% If the output image is a png, store a transparent image.
if strcmpi(dst_file(end-3:end), '.png')
imwrite(zeros(size(dst_img)), dst_file, 'Alpha', dst_img);
% Otherwise, just store a grayscale image.
else
dst_img = 1 - dst_img;
imwrite(dst_img, dst_file);
end
end
function I = addDot(I, x, y, r)
% Determine the dimensions of the dot
w = ceil(r) + (x - floor(x)) - 1;
h = ceil(r) + (y - floor(y)) - 1;
% Create a meshgrid
[X,Y] = meshgrid(-h:h,-w:w);
% Create the dot (the division by 2 is to smooth the edge)
D = r-sqrt(X.^2+Y.^2);
C = min(max(D/2, 0), 1);
% Calculate the position of the patch in the destination image image
X = x+X;
Y = y+Y;
% Calculate the indexes in the destination image
idx = (X-1) * size(I,1) + Y;
% Add the dot to the original image
I(idx) = max(I(idx), C);
end