function img=sfmov_read(file,start_img,stop_img,skip_img,start_area,stop_area)
%read an area of n image from the sfmov "file".
% the syntaxe is:
% img=sfmov_read(file,start_img,stop_img,skip_img,start_area,stop_area);
% or img=sfmov_read(file) mean all image in the file
% or img=sfmov_read(file,start_img,stop_img,skip_img) mean no selected area 
% where:
% img = array of n image 
% file = the 'file.sfmov'
% start_img = the firt image to be read
% stop_img = the last img to be read
% skip_img = number of image to skip
% start_area = [X Y] position of the top left corner of the selected area
% stop_area = [X Y] position of the bottom right corner of the selected area 



%version 0.8
% I volontary do this code to be inside the same function to be less memory
% as possible ( avoiding the stack memory )
img=0;

% test file name and location
if exist(file)==0;
    fprintf('no correct file input \n');
    return
end

% set start and skip for img=sfmov_read(file) mode
if nargin < 2
    start_img = 1;
    skip_img=0;
end

% check arg number for img=sfmov_read(file,start_img,stop_img,skip_img) mode
if (nargin > 1 ) & (nargin < 4 )
    fprintf('missing argument\n');
    return
end

% check arg number for img=sfmov_read(file,start,stop,skip,area,area) mode
if (nargin > 4 ) & (nargin < 6 ) | nargin > 6
    fprintf('missing selection argument\n');
    return
end

% test index limit
if start_img < 1
    fprintf('start_img should be > 0 \n');
    return
end




%open file
try
    file_id=fopen(file);
catch
    fprintf('impossible to open file \n');
    return
end

%path
last_path=findstr(file, '\');
path=file(1:max(last_path));


%find the "data" key word , mean end of the header

run=true;
nb_of_line_header=0;
while run

    try
        tline = native2unicode(fgetl(file_id));
        nb_of_line_header=nb_of_line_header+1;
    catch
        run=false;
        fprintf('header file not readable \n');
        return;
    end

    if   1 == strmatch('DATA', tline,'exact');
        run=false;
    end

end %while

position = ftell(file_id);

%read header

fseek(file_id, 0, 'bof');

for i=1:nb_of_line_header;

    rem = native2unicode(fgetl(file_id)); % read line
    [token, rem] = strtok(rem);% separe data

    switch token
        case ('HDSIZE')
            if( 0 == strcmp( 'Auto', rem(2:end) ))
                fprintf('file not readable, yet');
                return
            end
        case ('XPIXLS')
            width_pixel = str2double(rem);
        case ('YPIXLS')
            high_pixel = str2double(rem);

        case ('ZPIXLS')
            dip_pixel = str2double(rem);
        case ('IMSIZE')
            img_size= str2double(rem);
        case ('NUMDPS') % not sure if it is the number of image
            img_nb =  str2double(rem);
        case ('INCLUDE')
            include_file = strcat(path,rem(2:end));
        case ('REFILE')
        case ('CGFILE') % gain pixel correction file
            gain_file = strcat( path,rem(2:end));
        case ('COFILE') % offest pixel correction file
            offset_file= strcat( path,rem(2:end));
        case ('BPFILE') % bad pixel correction file
            bad_pixel_file = strcat( path,rem(2:end));

    end
end

%check the index with the number of image inside file
fprintf(' %d images of %dx%d pixels\n',img_nb, high_pixel,width_pixel);
if nargin < 2
    stop_img = img_nb;
    start_area=[1 1];
    stop_area=[width_pixel high_pixel];
end

if nargin < 5 
    start_area=[1 1];
    stop_area=[width_pixel high_pixel];
end

if start_area(1) < 0 
    start_area=[1 start_area(2)];
end

if stop_area(1) < 0 
    stop_area=[1 stop_area(2)];
end

if ( start_area(1) > width_pixel) | ( stop_area(1) > width_pixel ) | (start_area(2) > high_pixel ) | ( stop_area(2) > high_pixel) 
   fprintf('Area selected out of image\n');
   return
end

if (start_area(1) > stop_area(1)) | start_area(2) > stop_area(2)
    fprintf('Area selection problem\n');
    return
end

% calcule the size of the area 

area_wide = (stop_area(1) - start_area(1))+1;
area_high = (stop_area(2) - start_area(2))+1; 



if ( stop_img > img_nb )
    fprintf('stop_img is greater than number of image inside the file (%d) \n',img_nb)
    return
end

if ( skip_img > img_nb)
    frpintf('Not using skip, too big\n');
    skip=0;
end

% recalculate the last img for skip option

if ( skip_img == 0 )

    img_nb_skip=((stop_img-start_img)+1);
    
else

    a=1:img_nb;
    b=a(start_img:skip_img+1:stop_img);
    img_nb_skip=size(b,2);
    

end
%reading gain matrix ------------------------------------------------------

%open gain file '.scg'
try
    file_gain_id=fopen(gain_file);
catch
    fprintf('impossible to open gain file \n');
    return
end

position_gain=0;
%read header
fseek(file_gain_id, position_gain+1, 'bof');

%check the basic bad pixel flag
temp_gain_file=fread(file_gain_id,1,'int8');
if temp_gain_file~=0
    fprintf('this seems not to be a gain file!\n')
    return
end

% read
NumX=fread(file_gain_id,1,'int16');
NumY=fread(file_gain_id,1,'int16');
if (NumX~=width_pixel) ||(NumY~=high_pixel)
    fprintf('this file does not match the image size!\n')
    return
end

matrix_gain=zeros(NumX,NumY)';

fseek(file_gain_id, position_gain+419, 'bof');

matrix_gain=fread(file_gain_id,[NumX, NumY],'float32')';

fclose(file_gain_id);

%reading offset matrix ----------------------------------------------------

%open offset file '.sco'
try
    file_offset_id=fopen(offset_file);
catch
    fprintf('impossible to open offset file \n');
    return
end

position_offset=0;
%read header
fseek(file_offset_id, position_offset+1, 'bof');

%check the basic bad pixel flag
temp_offset_file=fread(file_offset_id,1,'int8');
if temp_offset_file~=1
    fprintf('this seems not to be a offset file!\n')
    return
end

% read
NumX=fread(file_offset_id,1,'int16');
NumY=fread(file_offset_id,1,'int16');
if (NumX~=width_pixel) ||(NumY~=high_pixel)
    fprintf('this file does not match the image size!\n')
    return
end

matrix_offset=zeros(NumX,NumY,'int16')';

fseek(file_offset_id, position_offset+419, 'bof');

matrix_offset=fread(file_offset_id,[NumX,NumY],'int16')';


fclose(file_offset_id);

%read data img ------------------------------------------------------------
%jump to the first img
first_img=(start_img*img_size)-img_size;
fseek(file_id, position+first_img, 'bof');

% allocate the final array img  
try
    mat = zeros(area_high, area_wide,img_nb_skip, 'uint16' );
catch
    fprintf('Not enough memory for %d images \n',img_nb_skip);
    return;
end

img_temp = zeros(high_pixel,width_pixel,1);


for i=1:img_nb_skip;

 
    img_temp = fread(file_id, [width_pixel,high_pixel] , 'uint16')';
    mat(:,:,i)=uint16((double(img_temp(start_area(2):stop_area(2),start_area(1):stop_area(1))).*matrix_gain(start_area(2):stop_area(2),start_area(1):stop_area(1)))+matrix_offset(start_area(2):stop_area(2),start_area(1):stop_area(1)));

    skip_position = ftell(file_id);
    fseek(file_id, skip_position+(img_size*skip_img), 'bof');
 

end

fclose(file_id);


% read bad pixel ----------------------------------------------------------

%open bp file '.sbp'
try
    file_bp_id=fopen(bad_pixel_file);
catch
    fprintf('impossible to open Bad pixel file \n');
    return
end

position_bp=0;
%read header
fseek(file_bp_id, position_bp+1, 'bof');

%check the basic bad pixel flag
temp_bp_file=fread(file_bp_id,1,'int8');
if temp_bp_file~=2
    fprintf('this seems not to be a gain file!\n')
    return
end

% read
NumX=fread(file_bp_id,1,'int16');
NumY=fread(file_bp_id,1,'int16');
if (NumX~=width_pixel) ||(NumY~=high_pixel)
    fprintf('this file does not match the image size!\n')
    return
end

matrix_bad_pixel=zeros(NumX,NumY)';

% fseek(file_bp_id, position_bp+30, 'bof');
%
% temp=fread(file_bp_id,1,'float32');
% fprintf('bad pixel tolerance: %f \n',temp)

fseek(file_bp_id, position_bp+419, 'bof');

matrix_bad_pixel=uint8(fread(file_bp_id,[NumX,NumY],'int8')');
fclose(file_bp_id);

% apply bad pixel ---------------------------------------------------------

% on the external line , only copy neirbourg pixel is done , on the center
% area the 8 pixel average is done

%correction bad pixel top line
pos_bp = find( matrix_bad_pixel(start_area(2),start_area(1):stop_area(1)) > 0 );
s = [1,stop_area(1)-start_area(1)+1];
[I,J] = ind2sub(s,pos_bp);
mat(I,J,:)=uint16(mat(I+1,J,:));
%correction bad pixel bottom line
pos_bp = find( matrix_bad_pixel(stop_area(2),start_area(1):stop_area(1)) > 0 );
s = [1,stop_area(1)-start_area(1)+1];
[I,J] = ind2sub(s,pos_bp);
mat(I,J,:)=uint16(mat(I-1,J,:));
%correction bad pixel right side 
pos_bp = find( matrix_bad_pixel(start_area(2):stop_area(2),start_area(1)) > 0 );
s = [stop_area(2)-start_area(2)+1,1];
[I,J] = ind2sub(s,pos_bp);
mat(I,J,:)=uint16(mat(I,J+1,:));
%correction bad pixel left side 
pos_bp = find( matrix_bad_pixel(start_area(2):stop_area(2),stop_area(1)) > 0 );
s = [stop_area(2)-start_area(2)+1,1];
[I,J] = ind2sub(s,pos_bp);
mat(I,J,:)=uint16(mat(I,J-1,:));

%correction bad pixel all central area
pos_corrected=matrix_bad_pixel(start_area(2):stop_area(2),start_area(1):stop_area(1));
pos_corrected( 1,: )=0; %reduice the area , because the externe line are allready done
pos_corrected(end,:)=0;
pos_corrected(:,1)=0;
pos_corrected(:,end)=0;

pos_bp = find( pos_corrected > 0 );
s = [area_high,area_wide];
[I,J] = ind2sub(s,pos_bp);



mat(I,J,:)=uint16((mat(I-1,J+1,:)+mat(I-1,J,:)+mat(I,J-1,:)+mat(I+1,J-1,:)+mat(I+1,J,:)+mat(I+1,J+1,:)+mat(I,J+1,:)+mat(I,J-1,:))/8);


img=mat;


