function b = svd_gray_approximate ( m, n, r, u, s, v )

%*****************************************************************************80
%
%% svd_gray_approximate() creates an SVD approximation of a grayscale image.
%
%  Discussion:
%
%    The program uses the singular value decomposition (SVD) to find
%    the best low rank approximation to the matrix representing the image.
%
%    Presumably, the input data U, S, V came by starting with a uint8 
%    array A representing a grayscale image, described by uint8 values
%    between 0 and 255, which was converted to numeric type, and then
%    factored with the SVD command.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    10 October 2018
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    integer M, N, the number of rows and columns in the original data.
%
%    integer R, the rank of the desired approximation.
%    1 <= R <= min ( M, N ).
%
%    real U(M,M), S(M,N), V(N,N), the output from the SVD command.
%
%  Output:
%
%    uint8 B(M,N), the rank R approximation to the image.
%
  if ( r < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'svd_gray_approximate(): Fatal error!\n' );
    fprintf ( 1, '  Rank R = %d, but must be at least 1.\n', r );
    error ( 'svd_gray_approximate(): Fatal error!' )
  end

  if ( min ( m, n ) < r )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'svd_gray_approximate(): Fatal error!\n' );
    fprintf ( 1, '  Rank R = %d, but must be no more than %d.\n', r, min ( m, n ) );
    error ( 'svd_gray_approximate(): Fatal error!' )
  end
%
%  Compute the rank R approximation.
%
  b(1:m,1:n) = u(1:m,1:r) * s(1:r,1:r) * v(1:n,1:r)';
%
%  Convert all data to values between 0 and 255.
%
  b_min = min ( min ( b ) );
  b_max = max ( max ( b ) );

  if ( b_min == b_max ) 
    b = 128;
  else
    b = round ( 255 * ( b - b_min ) / ( b_max - b_min ) );
  end
%
%  Convert from double to UINT8.
%
  b = uint8 ( b );

  return
end

