function [ScanThreshBar] = CodeRead(Img,EllipseData,steps)

%Funkce ma za ucel "naskenovat" okoli elipticke oblasti, kde by se mel
%nachazet carovy kod. Pri skenovani je treba kompenzovat afinni zkresleni.

%PRIPRAVA UHLU PRO VYPOCET SMERNIC RADIALNICH SKENOVACICH PAPRSKU

for i=1:size(EllipseData,1)
    
    a = EllipseData(i,6);                                                           %dulezite parametry dane elipsy
    b = EllipseData(i,7);
    alfa0 = EllipseData(i,8)/180*pi;
    dis = a/b;                                                              %afinni deformace
    
    for j=0:104;                                                            %celkem 210 paprsku
        
        Fi = pi/104*j+alfa0;                                                %priprava nedeformovanych uhlu
        xFi = cos(Fi);                                                      %nedeformovane slozky jednotkoveho smeroveho vektoru paprsku                                               
        yFi = sin(Fi);
        R = [cos(-alfa0),-sin(-alfa0),0;sin(-alfa0),cos(-alfa0),0;0,0,1];   %matice rotace - rotuje pripravene slozky o uhel alfa - afinni zkresleni po rotaci deformuje pouze jednu osu
        [RotCoor] = R*[xFi;yFi;0];                                          %jednotkovy smerovy vektor a jeho slozky v novem souradnem systemu, kde je osa x totozna s hlavni poloosou elipsy                      
        xFiR = RotCoor(1);
        yFiR = RotCoor(2);
        yFiR = yFiR*dis;                                                    %aplikace afinniho zkresleni
        R = [cos(alfa0),-sin(alfa0),0;sin(alfa0),cos(alfa0),0;0,0,1];       %rotace zpet do puvodniho souradneho systemu
        [RotCoor] = R*[xFiR;yFiR;0];
        xFi = RotCoor(1);                                                   %deformovane slozky jednotkoveho smeroveho vektoru
        yFi = RotCoor(2);
        FiDis(i,j+1) = atan(yFi/xFi);                                       %ulozeni uhlu
        
    end
end

for i=1:size(EllipseData,1)                                                 %serazeni uhlu
    FiDisS(i,:)=sort(FiDis(i,:));
end

%PRIPRAVA SOURADNIC BODU NA SKENOVACICH PAPRSCICH

for i=1:size(EllipseData,1)
    
    A = EllipseData(i,1);                                                   %dulezite parametry eliptickych oblasti                                                        
    B = EllipseData(i,2);
    C = EllipseData(i,3);
    x0 = EllipseData(i,4)+0.5;
    y0 = EllipseData(i,5)+0.5;
    
     for j=0:104                                                            %210 skenovacich paprsku
         
        vx(i,j+1) = cos(FiDisS(i,j+1));                                     %smerove vektory
        vy(i,j+1) = sin(FiDisS(i,j+1));
      
        t = sqrt(1/(A*vx(i,j+1)^2+C*vy(i,j+1)^2+B*vx(i,j+1)*vy(i,j+1)));    %vypocet parametru t parametricky dane primky - jedna se o parametr v bode pruseciku daneho paprsku s danou elipsou
        
        x1(i,j+1) = x0+t*vx(i,j+1);                                         %vytvoreni pruseciku s elipsou - reseni se rozpada na dve casti - poloviny elipsy
        x2(i,j+1) = x0-t*vx(i,j+1);
        y1(i,j+1) = y0+t*vy(i,j+1);
        y2(i,j+1) = y0-t*vy(i,j+1);
        
        SO1(i,j+1) = ((x1(i,j+1)-x0).^2+(y1(i,j+1)-y0).^2).^0.5;            %vzdalenost daneho pruseciku od stredu elipsy
        SO2(i,j+1) = ((x2(i,j+1)-x0).^2+(y2(i,j+1)-y0).^2).^0.5;
        
        step1(j+1)=SO1(i,j+1)/10;                                           %vzdalenosti jsou prevedeny na kroky v meritku - kvuli zachovani rozumneho meritka
        step2(j+1)=SO2(i,j+1)/10;
        
        scanpointx1(:,j+1,i)=steps*step1(j+1)*vx(i,j+1)+x1(i,j+1);          %vytoreni vektoru skenovacich bodu v souradnem systemu obrazu - dle vektoru "steps", empiricky zjisteneho, aby kod byl uprostred skenu
        scanpointx2(:,j+1,i)=-steps*step2(j+1)*vx(i,j+1)+x2(i,j+1);
        scanpointy1(:,j+1,i)=steps*step1(j+1)*vy(i,j+1)+y1(i,j+1);
        scanpointy2(:,j+1,i)=-steps*step2(j+1)*vy(i,j+1)+y2(i,j+1);
         
        for k=1:size(steps,2)                                               %samotne "skenovani" - hodnoty jasu pixelu na danych souradnicich jsou vypocitany bikubickou konvoluci
            scan1(k,j+1,i)= BiCubicConvolution(Img,scanpointx1(k,j+1,i),scanpointy1(k,j+1,i));
            scan2(k,j+1,i)= BiCubicConvolution(Img,scanpointx2(k,j+1,i),scanpointy2(k,j+1,i));
        end
     end
     scan(:,:,i)=horzcat(scan1(:,:,i),scan2(:,:,i));
end           

%OTOCENI KODU TAK, ABY ZACINAL PRECHODEM BITU, APLIKACE OTSUHO METODY
%PRAHOVANI

for i=1:size(EllipseData,1)                                                         
    
    ROT = scan(:,:,i);
    
    for k=1:14
        
           ROT = horzcat(ROT(:,size(ROT,2)),ROT);                           %vytovreni 14 "rotaci" cyklickeho skenu (14 dilku = 1 bit), prizpusobeno pro 15 bitove znacky
           ROT(:,size(ROT,2))=[];
           
           ROTmat(:,:,k,i)=ROT;                                             %ulozeni kazde "rotace"
           
           for j=1:15
               
               ROT1 = ROT(:,((j-1)*14+1):(14*j));                           %rozdeleni kazde rotace na jednotlive "bity"
               VAR1(k,j) = var(ROT1(:));                                    %vypocet rozptylu kazde oblasti
               
           end
    end
    
    VAR2 = sum(VAR1,2);                                                     %secteni rozptylu v ramce kazde "rotace", nalezeni minima                        
    minVAR = min(VAR2);
    
    for l = 1:size(VAR2,1)                                                  %nalezeni a ulozeni "rotace" s nejnizsim celkovym roztylem v ramci jednotlivych sekci - kod natoceny tak, aby 
        
        if VAR2(l,1)==minVAR
            VARi(i) = l;
            break
            
        end
    end
    
    ScanThresh(:,:,i) = im2bw(ROTmat(:,:,VARi(i),i)/255,graythresh(ROTmat(:,:,VARi(i),i)/255))*255;
                                                                            %aplikace Otsuho metody prahovani na spravne natoceny kod
end

%UPRAVA SKENU DO POZADOVANEHO TVARU, ULOZENI

for i=1:size(ScanThresh,3)
    
    for j=1:15                                                              %zmena formatu kodu - jednotlive bity jsou prevedeny na sloupcove vektory a poskaladany za sebe                                              
        A = ScanThresh(:,((j-1)*14+1):(14*j),i);
        ScanThreshBar(:,j,i) = A(:);
    end
    
end

end

