File:Digital rain animation medium letters shine.gif

Digital_rain_animation_medium_letters_shine.gif (500 × 400 像素,檔案大小:6.49 MB,MIME 類型:image/gif、​循環、​150 畫格、​15秒)


The Matrix Boot Camp

摘要

描述
English: Animated interpretation of digital rain (or “Matrix code“ ,“digital rain“ or sometimes „green rain“ ) from the Matrix movie series.
日期
來源 自己的作品
作者 Jahobr
其他版本
GIF開發
InfoField
 
本GIF 點陣圖使用MATLAB創作Jahobr
原始碼
InfoField

MATLAB code

function digital_rain_animation
% Programmed in Matlab R2017a.
% You can have a glimpse of the original digital rain in the 
%   Matrix Movie at 1:04 (or youtube: /watch?v=3vAnuBtyEYE ).
% The original is far messier. Drops stop, start and shift rows
% additionally there are stuck letters, gaps and so on.
% This is not replicated because it makes the short loop time very obvious.
% Those features could be added in a longer video.
% The font is not correct.
% The code could be radically optimized, but hence it is intended for 
%   one-time use, there is no real need.

latinList = ['-><=*' char(124) '":АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ0123456789']; % the vertical bar is encrypted as char(124) to avoid template-errors on wikimedia commons
asianList = char(65393:65437); % Asian symbols; Half-width kana;
% Matlab can work with UTF-8 but M-Files are saved using ANSI. If letters are typed directly, they are lost while saving the file
charList = [latinList asianList asianList]; % aisan symbols twice as likely
nChar = numel(charList);
 
[pathstr,fname] = fileparts(which(mfilename)); % save files under the same name and at file location
 
for gifVersion = [1 2 3 4 5 6]%
    
    switch gifVersion
        case 1
            rng(1) % seed random generator to make results reproducible
            name = 'small_letters';
            nFrames = 250;
            sizeLetters = [25 42]; % [nLetterRows nLetterColumns]
            dropLength = 35; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 0.5; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/10; % in sec
            xLimits = [0 500]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        case 2
            rng(1) % seed random generator to make results reproducible
            name = 'medium_letters';
            nFrames = 150;
            sizeLetters = [12 21]; % [nLetterRows nLetterColumns]
            dropLength = 25; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 1; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/10; % in sec
            xLimits = [0 500]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        case 3
            rng(2) % seed random generator to make results reproducible
            name = 'medium_letters_2';
            nFrames = 191; % hight Least common multiple with 150; so combinations do no allign
            sizeLetters = [12 21]; % [nLetterRows nLetterColumns]
            dropLength = 25; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 1; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/10; % in sec
            xLimits = [0 500]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        case 4
            rng(3) % seed random generator to make results reproducible
            name = 'medium_letters_3';
            nFrames = 229;
            sizeLetters = [12 21]; % [nLetterRows nLetterColumns]
            dropLength = 25; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 1; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/10; % in sec
            xLimits = [0 500]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        case 5
            rng(4) % seed random generator to make results reproducible
            name = 'medium_letters_4';
            nFrames = 259;
            sizeLetters = [12 21]; % [nLetterRows nLetterColumns]
            dropLength = 25; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 1; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/10; % in sec
            xLimits = [0 500]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        case 6
            rng(1) % seed random generator to make results reproducible
            name = 'big_letters';
            nFrames = 60;
            sizeLetters = [6 9]; % [nLetterRows nLetterColumns]
            dropLength = 15; % should be adjusted with regard to nFrames and sizeLetters(1) (must be smaller as nFrames)
            doubleDropRattio = 1; % ratios of columns with 2 drops per loop instad of just 1
            DelayTime = 1/5; % in sec
            xLimits = [0 400]; % in pixel
            yLimits = [0 400]; % in pixel
            snapshotAtFrame = 50;
        otherwise
            error('not defined')
    end
 
    figHandle = figure(1562134155);
    clf
    axesHandle = axes;
    hold(axesHandle,'on')
    set(figHandle, 'Units','pixel');
    set(figHandle, 'Position',[1 1 xLimits(2) yLimits(2)]); % big start image for antialiasing later [x y width height]
    set(axesHandle,'Color',[0 0 0]); % black background
    set(axesHandle,'Position',[0 0 1 1]); % stretch axis as big as figure, [x y width height]
    set(axesHandle,'XTick',NaN) % get rid of ticks
    set(axesHandle,'YTick',NaN) % get rid of ticks
    set(axesHandle,'TickLength',[0 0]) % get rid of ticks
    set(axesHandle,'YColor',[0 0 0]) % remove outline
    set(axesHandle,'XColor',[0 0 0]) % remove outline
    
    xlim(xLimits);ylim(yLimits);
    
    letterCube = repmat(randi(nChar,sizeLetters),1,1,nFrames);
    for iRand = 1:numel(letterCube)*0.02 % small proportion of flipping symbols
        letterRow = randi(sizeLetters(1)); % select random position
        letterCol = randi(sizeLetters(2)); % select random position
        letterThroughTime = letterCube(letterRow,letterCol,:); % extract
        letterThroughTime = letterThroughTime(:)';
        letterThroughTime(1:randi(round(nFrames/3)+3,1,2)) = randi(nChar); % add a random section
        shift = randi(nFrames-1);
        letterThroughTime = [letterThroughTime(shift+1:end) letterThroughTime(1:shift)]; % time offset
        letterCube(letterRow,letterCol,:) = letterThroughTime; % write back
    end
 
    dropColMap = zeros(nFrames,3); % default Black
    dropColMap(1:dropLength,:) = letterColMap(dropLength); % drop colors with black to fill the list up
    
    glareColMap = zeros(nFrames,3); % default Black
    glareColMap(1,:) = 1; % drop tip white
    
    % for i=1:xLimits(2)
    %     plot(i,100,'.','Color',map(i,:))
    % end
    
    xDelta = xLimits(2)/sizeLetters(2);
    xCoordinates = (xDelta/2:xDelta:xLimits(2));
    
    yDelta = yLimits(2)/sizeLetters(1);
    yCoordinates = (yDelta/2:yDelta:yLimits(2))+yDelta/10;
    
    handMat = NaN(sizeLetters);
    for iRow = 1:sizeLetters(1)
        for iCol = 1:sizeLetters(2)
            handMat(iRow,iCol) = text(xCoordinates(iCol),yCoordinates(iRow),...
                charList(letterCube(iRow,iCol,1)),...
                'FontWeight','bold',...
                'FontName','monospaced',...
                'Color',[1 1 1],...
                'FontUnits','pixel',...
                'FontSize',yDelta*1.08,...
                'HorizontalAlignment','center',...
                'VerticalAlignment','middle');
        end
    end
    stateMat = repmat((1:sizeLetters(1))' ,1, sizeLetters(2)); % initiate the basic rain drops running down the screen
    stateOffset = randi(nFrames,1,sizeLetters(2)); % create a basic offsets for different delays
    stateMat = stateMat + ones(sizeLetters(1),1) * stateOffset;
    
    
    stateOffset = randi(round(nFrames/3),1,sizeLetters(2))+randi(round(nFrames/5),1,sizeLetters(2)); % create secondary offsets for different delays
    stateOffset(rand(1,sizeLetters(2))>doubleDropRattio) = 0; % only a portion of columns get 2 drops
    stateMat2 = stateMat + ones(sizeLetters(1),1) * stateOffset;
    
    clearRGBimage = uint8(ones(yLimits(2),xLimits(2),3,nFrames)); % allocate
    shineRGBimage = clearRGBimage;                                      % allocate
 
    for iFrame = 1:nFrames
        
        stateMat  = rem(stateMat ,nFrames); % bring back into range [0 nFrames-1]
        stateMat2 = rem(stateMat2,nFrames); % bring back into range [0 nFrames-1]
        
        for iRow = 1:sizeLetters(1)
            for iCol = 1:sizeLetters(2)
                if stateMat(iRow,iCol)>stateMat2(iRow,iCol) % use the second drop
                    set(handMat(iRow,iCol),'Color',dropColMap(stateMat2(iRow,iCol)+1,:),...
                        'string',charList(nChar-letterCube(iRow,iCol,iFrame)+1)); % use a mirrored charList to get different characters
                else  % use the first drop
                    set(handMat(iRow,iCol),'Color',dropColMap(stateMat(iRow,iCol)+1,:),...
                        'string',charList(letterCube(iRow,iCol,iFrame)));
                end
            end
        end
        drawnow
        fClear = getframe(figHandle);
        
        % secondary image using only the white letters to generate extra strong glare
        for iRow = 1:sizeLetters(1)
            for iCol = 1:sizeLetters(2)
                if stateMat(iRow,iCol)>stateMat2(iRow,iCol) % use the second drop
                    set(handMat(iRow,iCol),'Color',glareColMap(stateMat2(iRow,iCol)+1,:),...
                        'string',charList(nChar-letterCube(iRow,iCol,iFrame)+1)); % use a mirrored charList to get different characters
                else  % use the first drop
                    set(handMat(iRow,iCol),'Color',glareColMap(stateMat(iRow,iCol)+1,:),...
                        'string',charList(letterCube(iRow,iCol,iFrame)));
                end
            end
        end
        drawnow
        fGlare = getframe(figHandle);
        
        stateMat  = stateMat +1; % move drops "one position down"
        stateMat2 = stateMat2+1; % move drops "one position down"
        
        %% save animation
        fClear.cdata = fliplr(fClear.cdata); % view from "behind the code"
        fGlare.cdata = fliplr(fGlare.cdata); % view from "behind the code"
        
        weightFiddleMode = false; % for debugging ad adjusting
        
        if weightFiddleMode; figure(110); clf; imshow(fClear.cdata); end
        fShine.cdata = imgaussfilt(fClear.cdata,yDelta/3); % far reaching shine of all letters
        if weightFiddleMode; figure(111); clf; imshow(fShine.cdata); end
        fShine.cdata = fShine.cdata*1.5; % make brighter (automatically limited to range by unit8 format)
        if weightFiddleMode; figure(112); clf; imshow(fShine.cdata); end
        
        fEdge.cdata = imgaussfilt(fClear.cdata,yDelta/12); % stronger glow close to the letter edges
        if weightFiddleMode; figure(113); clf; imshow(fEdge.cdata); end
        
        fEdge.cdata = fEdge.cdata*0.7; % make darker
        if weightFiddleMode; figure(114); clf; imshow(fEdge.cdata); end
        
        fShine.cdata = imadd(fShine.cdata,fEdge.cdata); % combine shine and edge glow
        if weightFiddleMode; figure(115); clf; imshow(fShine.cdata); end
        
        
        if weightFiddleMode; figure(116); clf; imshow(fGlare.cdata); end
        fGlare.cdata = imgaussfilt(fGlare.cdata,yDelta/2); % far reaching shine of the white letter at the drop tip
        if weightFiddleMode; figure(117); clf; imshow(fGlare.cdata); end
        fGlare.cdata = fGlare.cdata*1.5; % make brighter (automatically limited to range by unit8 format)
        if weightFiddleMode; figure(118); clf; imshow(fGlare.cdata); end
        
        fShine.cdata = imadd(fShine.cdata,fGlare.cdata); % combine; this makes the drop tip double bright
        if weightFiddleMode; figure(119); clf; imshow(fShine.cdata); end
        
        fShine.cdata = imadd(fShine.cdata*0.8,fClear.cdata*0.5);  % combine shine with original sharp letters
        if weightFiddleMode; figure(120); clf; imshow(fShine.cdata); end
        if weightFiddleMode; return; end
 
        clearRGBimage(:,:,:,iFrame) = fClear.cdata; % store
        shineRGBimage(:,:,:,iFrame) = fShine.cdata; % store
        
        if snapshotAtFrame == iFrame
            imwrite(fClear.cdata,fullfile(pathstr, [fname '_' name '_clear.png'])) % save png (native RGB no colormap)
            imwrite(fShine.cdata,fullfile(pathstr, [fname '_' name '_shine.png'])) % save png (native RGB no colormap)
        end
    end
     
    colormapImage = permute(clearRGBimage(:,:,:,:),[1 2 4 3]); % step1; make unified image
    colormapImage = reshape(colormapImage, yLimits(2),xLimits(2)*nFrames,3,1); % step2; make unified image
    mapClear = createImMap(colormapImage,64,[0 0 0; 1 1 1]); % colormap
    colormapImage = permute(shineRGBimage(:,:,:,:),[1 2 4 3]); % step1; make unified image
    colormapImage = reshape(colormapImage, yLimits(2),xLimits(2)*nFrames,3,1); % step2; make unified image
    mapShine = createImMap(colormapImage,128,[0 0 0; 1 1 1]); % colormap
    
    imClear = uint8(ones(yLimits(2),xLimits(2),1,nFrames)); % allocate
    imShine = uint8(ones(yLimits(2),xLimits(2),1,nFrames)); % allocate
    for iFrame = 1:nFrames
        imClear(:,:,1,iFrame) = rgb2ind(clearRGBimage(:,:,:,iFrame),mapClear); % ,'nodither');
        imShine(:,:,1,iFrame) = rgb2ind(shineRGBimage(:,:,:,iFrame),mapShine); % ,'nodither');
    end

        imwrite(imClear,mapClear,fullfile(pathstr, [fname '_' name '_clear.gif']),'DelayTime',DelayTime,'LoopCount',inf) % save gif
        imwrite(imShine,mapShine,fullfile(pathstr, [fname '_' name '_shine.gif']),'DelayTime',DelayTime,'LoopCount',inf) % save gif
        disp([fname '_' name '_clear.gif  has ' num2str(numel(imClear)/10^6 ,4) ' Megapixels']) % Category:Animated GIF files exceeding the 50 MP limit
end
 
function map = letterColMap(nCol)
%  map:
% Pos 1:  white (short burst)
% a: bright green changing to green
% b: staying green ()
% c: fading to black
 
querries = linspace(0,100,nCol-1);
 
x = [0   15   40   100]; % percent of map
%      a    b    c 
red = interp1(x,... 
    [0.4  0.0  0.0   0],... intensity
    querries);
blue = interp1(x,... 
    [0.4  0.0  0.0   0],... intensity
    querries);
green = interp1(x,... 
    [1   0.8   0.8   0],... intensity
    querries);
 
map = [ [1 1 1];red(:) green(:) blue(:)]; % white in front


function map = createImMap(imRGB,nCol,startMap)
% createImMap creates a color-map including predefined colors.
% "rgb2ind" creates a map but there is no option to predefine some colors,
%         and it does not handle stacked images.
% Input:
%   imRGB:     image, [imRows x imColumns x 3(RGB) x nStack] (unit8)
%   nCol:      total number of colors the map should have, [integer]
%   startMap:  predefined colors; colormap format, [p x 3] (double)

imRGB = permute(imRGB,[1 2 4 3]); % step1; make unified column-image (handling possible nStack)
imRGBcolumn = reshape(imRGB,[],1,3,1); % step2; make unified column-image

fullMap = double(permute(imRGBcolumn,[1 3 2]))./255; % "column image" to color map 
[fullMap,~,imMapColumn] = unique(fullMap,'rows'); % find all unique colors; create indexed colormap-image
% "cmunique" could be used but is buggy and inconvenient because the output changes between "uint8" and "double"

nColFul = size(fullMap,1);
nColStart = size(startMap,1);
disp(['Number of colors: ' num2str(nColFul) ' (including ' num2str(nColStart) ' self defined)']);

if nCol<=nColStart;  error('Not enough colors');        end
if nCol>nColFul;   warning('More colors than needed');  end

isPreDefCol = false(size(imMapColumn)); % init
 
for iCol = 1:nColStart
    diff = sum(abs(fullMap-repmat(startMap(iCol,:),nColFul,1)),2); % difference between a predefined and all colors
    [mDiff,index] = min(diff); % find matching (or most similar) color
    if mDiff>0.05 % color handling is not precise
        warning(['Predefined color ' num2str(iCol) ' does not appear in image'])
        continue
    end
    isThisPreDefCol = imMapColumn==index; % find all pixel with predefined color
    disp([num2str(sum(isThisPreDefCol(:))) ' pixel have predefined color ' num2str(iCol)]);
    isPreDefCol = or(isPreDefCol,isThisPreDefCol); % combine with overall list
end
[~,mapAdditional] = rgb2ind(imRGBcolumn(~isPreDefCol,:,:),nCol-nColStart,'nodither'); % create map of remaining colors
map = [startMap;mapAdditional];

授權條款

我,本作品的著作權持有者,決定用以下授權條款發佈本作品:
Creative Commons CC-Zero 此檔案在創用CC CC0 1.0 通用公有領域貢獻宣告之下分發。
在此宣告之下分發本作品者,已依據各國著作權法,在全世界放棄其對本作品所擁有的著作權及所有相關相似的法律權利,從而將本作品貢獻至公有領域。您可以複製、修改、分發和演示該作品,用於任何商業用途,所有這些都不需要請求授權。

說明

添加單行說明來描述出檔案所代表的內容
Govt. Holkar College

在此檔案描寫的項目

描繪內容

創作作者 Chinese (Hong Kong) (已轉換拼寫)

沒有維基數據項目的某些值

作者姓名字串 繁體中文 (已轉換拼寫):​Jahobr
維基媒體使用者名稱 繁體中文 (已轉換拼寫):​Jahobr

著作權狀態 繁體中文 (已轉換拼寫)

檔案來源 Chinese (Taiwan) (已轉換拼寫)

上傳者的原創作品 繁體中文 (已轉換拼寫)

多媒體型式 繁體中文 (已轉換拼寫)

image/gif

檔案歷史

點選日期/時間以檢視該時間的檔案版本。

日期/時間縮⁠圖尺寸用戶備⁠註
目前2017年10月14日 (六) 21:55於 2017年10月14日 (六) 21:55 版本的縮圖500 × 400(6.49 MB)JahobrUser created page with UploadWizard

下列3個頁面有用到此檔案:

全域檔案使用狀況

以下其他 wiki 使用了這個檔案: