% % Thue_Morse_tiling( nOrder, strTileFileName, nNbrRule ) % ------------------------------------------------------------------------- % % Creates a a 2-D Thue_Morse tiled image from an input image of basis % tiling elements. % % USAGE: nimOut = Thue_Morse_tiling( 4, 'Flat_clr_tile.jpg', 2 ); % % INPUT: % % nOrder - [positive integer] Log2( size of image ). % % strTileFileName: - Filename of an image containing basis tiling % elements. % [NOTE: Currently the image must be either twice as wide as it is % high (4x2), or four times (for nNbrRule == 2) as high as it % is wide ((4x2)x4). Also, the dimensions must be even.] % % nNbrRule - [0,2] 0: B/W two symbol, strTileFileName is ignored. % 1: "simple" two tile. % 2: "octal" eight tile, considers near neighbor % configuration. % [Note: "octal" edge tiles are replaced with % black, as the neighbors are not defined.] % [Note: "octal" also accepts 32 tiles % shadings for each of four rotations of % each tile.] % % HARDCODED (immediately below function declaration): % % bShowResult: - [0, 1] Show progress, display final image in figure, % and output an image file. % bWriteResult: - [0, 1] Write final image to an image file. % % strOutFileName - Convention for output file name and format. % Default naming is: % TM[nNbrRule]_[nOrder]_[strTileFileName].tif % % OUTPUT: % % Returns an RGB image array, of the size 2^nOrder x 2^nOrder x 3. % If hardcoded bWriteResult == 1 creates an % image file called TM_[nOrder]_[strTileFileName].jpg, % and if bShowResult == 1 displays progress and a Matlab figure of the image. % % Mark Dow, January 1, 2007 % Mark Dow, modified January 6, 2007 (Conversion to 3-byte color tile elements.) % Mark Dow, modified January 30, 2007 % Mark Dow, modified February 7, 2007 % Mark Dow, modified February 15, 2007 % Mark Dow, modified March 8, 2007 (Integrate "simple" with neighborhood rules.) % function nimOut = Thue_Morse_tiling( nOrder, strTileFileName, nNbrRule ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % hardcoded parameters bShowResult = 1; % [0,1] bWriteResult = 1; % [0,1] strOutFilename = ['TM' num2str(nNbrRule) '_' num2str(nOrder) '_' strTileFileName(1:length(strTileFileName)-4) '.tif' ]; % Not functional: bThreeDimensional = 0; % [0,1] If true, strTileFileName isn't used. % hardcoded parameters %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% nSquare = 2^nOrder; % image size is a power of 2 szTiles = 0; fprintf( ['\n'] ); if nNbrRule > 0 imTiles = imread( strTileFileName ); % If the image is grayscale, convert to 3-byte color. dim = size( size(imTiles) ); if dim(2) == 2 imTiles(:,:,2) = imTiles(:,:,1); imTiles(:,:,3) = imTiles(:,:,1); end szTiles = size( imTiles ); % To Do: sanity check on size of input tile grid if bShowResult fprintf( [ 'Size of image: ' num2str( nSquare*szTiles(1) ) ' x ' num2str( nSquare*szTiles(1) ) ' px. \n' ] ); fprintf( [ 'Memory required (final image): ' num2str( nSquare^2 * szTiles(1)^2 *3/(2^20) ) ' MB \n' ] ); end else nimPattern = 255*ones( nSquare, nSquare, 'uint8' ); if bShowResult fprintf( [ 'Size of image: ' num2str( nSquare ) ' x ' num2str( nSquare ) 'px. \n' ] ); fprintf( [ 'Memory required (final image): ' num2str( nSquare^2 *3/(2^20) ) ' MB \n' ] ); end end % Form full 32 tile grid if only eight present in input. if nNbrRule == 2 & szTiles(1) == szTiles(2)/2 imTileARot = imTiles( 1 : szTiles(1), 1 : szTiles(2)/2, : ); imTileARot = flipdim( imTileARot, 1 ); imTileARot = permute( imTileARot, [2 1 3] ); imTiles( 1*szTiles(1) + 1 : 2*szTiles(1), 1 : szTiles(2)/2, : ) = imTileARot; imTileARot = flipdim( imTileARot, 1 ); imTileARot = permute( imTileARot, [2 1 3] ); imTiles( 2*szTiles(1) + 1 : 3*szTiles(1), 1 : szTiles(2)/2, : ) = imTileARot; imTileARot = flipdim( imTileARot, 1 ); imTileARot = permute( imTileARot, [2 1 3] ); imTiles( 3*szTiles(1) + 1 : 4*szTiles(1), 1 : szTiles(2)/2, : ) = imTileARot; imTileBRot = imTiles( 1 : szTiles(1), szTiles(2)/2 + 1 : szTiles(2), : ); imTileBRot = flipdim( imTileBRot, 1 ); imTileBRot = permute( imTileBRot, [2 1 3] ); imTiles( 1*szTiles(1) + 1 : 2*szTiles(1), szTiles(2)/2 + 1 : szTiles(2), : ) = imTileBRot; imTileBRot = flipdim( imTileBRot, 1 ); imTileBRot = permute( imTileBRot, [2 1 3] ); imTiles( 2*szTiles(1) + 1 : 3*szTiles(1), szTiles(2)/2 + 1 : szTiles(2), : ) = imTileBRot; imTileBRot = flipdim( imTileBRot, 1 ); imTileBRot = permute( imTileBRot, [2 1 3] ); imTiles( 3*szTiles(1) + 1 : 4*szTiles(1), szTiles(2)/2 + 1 : szTiles(2), : ) = imTileBRot; szTiles = size( imTiles ); end % Initialize output image. nimOut = 255*ones( nSquare*szTiles(1)/4, nSquare*szTiles(1)/4, 'uint8' ); length_msg = 0; % Construct Thue-Morse vector: vctTM = 0; for i = 1 : nOrder vctTM( length(vctTM) + 1 : 2*length(vctTM) ) = ~vctTM; end % Construct 2-D pattern from Thue-Morse vector: for i = 1:nSquare if bShowResult % Print current image column number that is being calculated. for k = 1:length_msg fprintf( '\b' ); end msg = [ 'Finding Thue-Morse tiling image column # ' num2str(i) ' of ' num2str(nSquare) ]; length_msg = length(msg); fprintf( msg ) end if vctTM(i) == 0 nimPattern( i, 1:nSquare ) = vctTM; else nimPattern( i, 1:nSquare ) = ~vctTM; end end if nNbrRule == 0 nimOut = 255*nimPattern; end if nNbrRule == 1 for i = 0 : nSquare - 1 for j = 0 : nSquare - 1 if nimPattern( i+1, j+1 ) == 0 nimOut( 1 + i*szTiles(1):(i+1)*szTiles(1), 1 + j*szTiles(1):(j+1)*szTiles(1), 1:3 )... = imTiles( 1 : szTiles(1), 1 : szTiles(2)/2, 1:3 ); else nimOut( 1 + i*szTiles(1):(i+1)*szTiles(1), 1 + j*szTiles(1):(j+1)*szTiles(1), 1:3 )... = imTiles( 1 : szTiles(1), szTiles(2)/2 + 1 : szTiles(2), 1:3 ); end end end end if nNbrRule == 2 imTileA_TR = imTiles( 1 : szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileA_BR = imTiles( szTiles(1)/8 + 1 : szTiles(1)/4, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileA_TL = imTiles( 1 : szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileA_BL = imTiles( szTiles(1)/8 + 1 : szTiles(1)/4, 1 : szTiles(2)/4, 1:3 ); imTileH_TR = imTiles( 1 : szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileH_BR = imTiles( szTiles(1)/8 + 1 : szTiles(1)/4, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileH_TL = imTiles( 1 : szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileH_BL = imTiles( szTiles(1)/8 + 1 : szTiles(1)/4, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileC_TR = imTiles( 2*szTiles(1)/8 + 1 : 3*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileC_BR = imTiles( 3*szTiles(1)/8 + 1 : 4*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileC_TL = imTiles( 2*szTiles(1)/8 + 1 : 3*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileC_BL = imTiles( 3*szTiles(1)/8 + 1 : 4*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileB_TR = imTiles( 2*szTiles(1)/8 + 1 : 3*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileB_BR = imTiles( 3*szTiles(1)/8 + 1 : 4*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileB_TL = imTiles( 2*szTiles(1)/8 + 1 : 3*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileB_BL = imTiles( 3*szTiles(1)/8 + 1 : 4*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileE_TR = imTiles( 4*szTiles(1)/8 + 1 : 5*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileE_BR = imTiles( 5*szTiles(1)/8 + 1 : 6*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileE_TL = imTiles( 4*szTiles(1)/8 + 1 : 5*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileE_BL = imTiles( 5*szTiles(1)/8 + 1 : 6*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileD_TR = imTiles( 4*szTiles(1)/8 + 1 : 5*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileD_BR = imTiles( 5*szTiles(1)/8 + 1 : 6*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileD_TL = imTiles( 4*szTiles(1)/8 + 1 : 5*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileD_BL = imTiles( 5*szTiles(1)/8 + 1 : 6*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileG_TR = imTiles( 6*szTiles(1)/8 + 1 : 7*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileG_BR = imTiles( 7*szTiles(1)/8 + 1 : 8*szTiles(1)/8, szTiles(2)/4 + 1 : szTiles(2)/2, 1:3 ); imTileG_TL = imTiles( 6*szTiles(1)/8 + 1 : 7*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileG_BL = imTiles( 7*szTiles(1)/8 + 1 : 8*szTiles(1)/8, 1 : szTiles(2)/4, 1:3 ); imTileF_TR = imTiles( 6*szTiles(1)/8 + 1 : 7*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileF_BR = imTiles( 7*szTiles(1)/8 + 1 : 8*szTiles(1)/8, 3*szTiles(2)/4 + 1 : szTiles(2), 1:3 ); imTileF_TL = imTiles( 6*szTiles(1)/8 + 1 : 7*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileF_BL = imTiles( 7*szTiles(1)/8 + 1 : 8*szTiles(1)/8, szTiles(2)/2 + 1 : 3*szTiles(2)/4, 1:3 ); imTileBlank( 1:szTiles(1)/8, 1:szTiles(2)/4, 1:3 ) = 0; % arbitrary initialization for i = 0 : nSquare - 1 for j = 0 : nSquare - 1 imTileTL = imTileBlank; imTileTR = imTileBlank; imTileBL = imTileBlank; imTileBR = imTileBlank; ip = i; jp = j; % On tileA if nimPattern( i+1, j+1 ) == 0 % Top left: % if tileB to left if jp > 0 & nimPattern(ip+1,jp) == 1 % if tileB above if ip > 0 if nimPattern(ip,jp+1) == 1 imTileTL = imTileE_TL; % else tileA above else imTileTL = imTileC_TL; end end end % if tileA to left if jp > 0 & nimPattern(ip+1,jp) == 0 % if tileB above if ip > 0 if nimPattern(ip,jp+1) == 1 imTileTL = imTileG_TL; % else tileA above else imTileTL = imTileA_TL; end end end % Top right: % if tileB above if ip > 0 & nimPattern(ip,jp+1) == 1 % if tileB to right if jp < nSquare - 1 if nimPattern(ip+1,jp+2) == 1 imTileTR = imTileG_TR; % else tileA to right else imTileTR = imTileE_TR; end end end % if tileA above if ip > 0 & nimPattern(ip,jp+1) == 0 % if tileB to right if jp < nSquare - 1 if nimPattern(ip+1,jp+2) == 1 imTileTR = imTileA_TR; % else tileA to right else imTileTR = imTileC_TR; end end end % Bottom left: % if tileB to left if jp > 0 & nimPattern(ip+1,jp) == 1 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBL = imTileC_BL; % else tileA below else imTileBL = imTileE_BL; end end end % if tileA to left if jp > 0 & nimPattern(ip+1,jp) == 0 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBL = imTileA_BL; % else tileA below else imTileBL = imTileG_BL; end end end % Bottom right: % if tileB to right if jp < nSquare - 1 & nimPattern(ip+1,jp+2) == 1 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBR = imTileA_BR; % else tileA below else imTileBR = imTileG_BR; end end end % if tileA to right if jp < nSquare - 1 & nimPattern(ip+1,jp+2) == 0 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBR = imTileC_BR; % else tileA below else imTileBR = imTileE_BR; end end end end % On tileB if nimPattern(i+1,j+1) == 1 % Top left: % if tileB to left if jp > 0 & nimPattern(ip+1,jp) == 1 % if tileB above if ip > 0 if nimPattern(ip,jp+1) == 1 imTileTL = imTileF_TL; % else tileA above else imTileTL = imTileD_TL; end end end % if tileA to left if jp > 0 & nimPattern(ip+1,jp) == 0 % if tileB above if ip > 0 if nimPattern(ip,jp+1) == 1 imTileTL = imTileH_TL; % else tileA above else imTileTL = imTileB_TL; end end end % Top right: % if tileB above if ip > 0 & nimPattern(ip,jp+1) == 1 % if tileB to right if jp < nSquare - 1 if nimPattern(ip+1,jp+2) == 1 imTileTR = imTileH_TR; % else tileA to right else imTileTR = imTileF_TR; end end end % if tileA above if ip > 0 & nimPattern(ip,jp+1) == 0 % if tileB to right if jp < nSquare - 1 if nimPattern(ip+1,jp+2) == 1 imTileTR = imTileB_TR; % else tileA to right else imTileTR = imTileD_TR; end end end % Bottom left: % if tileB to left if jp > 0 & nimPattern(ip+1,jp) == 1 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBL = imTileD_BL; % else tileA below else imTileBL = imTileF_BL; end end end % if tileA to left if jp > 0 & nimPattern(ip+1,jp) == 0 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBL = imTileB_BL; % else tileA below else imTileBL = imTileH_BL; end end end % Bottom right: % if tileB to right if jp < nSquare - 1 & nimPattern(ip+1,jp+2) == 1 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBR = imTileB_BR; % else tileA below else imTileBR = imTileH_BR; end end end % if tileA to right if jp < nSquare - 1 & nimPattern(ip+1,jp+2) == 0 % if tileB below if ip < nSquare - 1 if nimPattern(ip+2,jp+1) == 1 imTileBR = imTileD_BR; % else tileA below else imTileBR = imTileF_BR; end end end end nimOut( 1 + i*szTiles(1)/4:(i+1/2)*szTiles(1)/4,... 1 + j*szTiles(1)/4:(j+1/2)*szTiles(1)/4, 1:3 ) = imTileTL; nimOut( 1 + i*szTiles(1)/4:(i+1/2)*szTiles(1)/4,... 1 + (j+1/2)*szTiles(1)/4:(j+1) *szTiles(1)/4, 1:3 ) = imTileTR; nimOut( 1 + (i+1/2)*szTiles(1)/4:(i+1) *szTiles(1)/4,... 1 + j*szTiles(1)/4:(j+1/2)*szTiles(1)/4, 1:3 ) = imTileBL; nimOut( 1 + (i+1/2)*szTiles(1)/4:(i+1) *szTiles(1)/4,... 1 + (j+1/2)*szTiles(1)/4:(j+1) *szTiles(1)/4, 1:3 ) = imTileBR; end end end % 3-D: Not functional, except for B/W binary. % % Construct all planes from first plane: % if bThreeDimensional % for j = 1:nSquare % % % if bShowProgress % % Print current image plane number that is being calculated. % for k = 1:length_msg % fprintf( '\b' ); % end % msg = [ 'Finding Thue-Morse tiling image plane # ' num2str(j) ' of ' num2str(nSquare) ]; % length_msg = length(msg); % fprintf( msg ) % % end % % if vctTM(j) == 0 % nimOut( 1:nSquare, 1:nSquare, j ) = nimOut( :, :, 1 ); % else % nimOut( 1:nSquare, 1:nSquare, j ) = ~nimOut( :, :, 1 ); % end % end % end if bShowResult % Show tiling in a figure (only first plane if 3-D). figure; imshow( nimOut ); end if bWriteResult fprintf( [ '\nWriting image file to current directory,\n named ' strOutFilename '. \n' ] ); imwrite( nimOut, strOutFilename ); % imwrite( nimOut, strOutFilename, 'jpg',... % 'Quality', 100,... % 'Comment', 'Mark Dow, dow@uoregon.edu, http://lcni.uoregon.edu/~mark' ); end fprintf( ['\n'] );