sustaining_gazes/matlab_version/AU_training/data extraction/xml_io_tools_2010_11_05/base64decode.m

118 lines
4.2 KiB
Matlab

function y = base64decode(x, outfname, alg)
%BASE64DECODE Perform base64 decoding on a string.
%
% INPUT:
% x - block of data to be decoded. Can be a string or a numeric
% vector containing integers in the range 0-255. Any character
% not part of the 65-character base64 subset set is silently
% ignored. Characters occuring after a '=' padding character are
% never decoded. If the length of the string to decode (after
% ignoring non-base64 chars) is not a multiple of 4, then a
% warning is generated.
%
% outfname - if provided the binary date from decoded string will be
% saved into a file. Since Base64 coding is often used to embbed
% binary data in xml files, this option can be used to extract and
% save them.
%
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
% variable defaulting to 'java' which is a little faster. If
% 'java' is chosen than core of the code is performed by a call to
% a java library. Optionally all operations can be performed using
% matleb code.
%
% OUTPUT:
% y - array of binary data returned as uint8
%
% This function is used to decode strings from the Base64 encoding specified
% in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The Base64
% encoding is designed to represent arbitrary sequences of octets in a form
% that need not be humanly readable. A 65-character subset ([A-Za-z0-9+/=])
% of US-ASCII is used, enabling 6 bits to be represented per printable
% character.
%
% See also BASE64ENCODE.
%
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
%
% Matlab version based on 2004 code by Peter J. Acklam
% E-mail: pjacklam@online.no
% URL: http://home.online.no/~pjacklam
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
if nargin<3, alg='java'; end
if nargin<2, outfname=''; end
%% if x happen to be a filename than read the file
if (numel(x)<256)
if (exist(x, 'file')==2)
fid = fopen(x,'rb');
x = fread(fid, 'uint8');
fclose(fid);
end
end
x = uint8(x(:)); % unify format
%% Perform conversion
switch (alg)
case 'java'
base64 = org.apache.commons.codec.binary.Base64;
y = base64.decode(x);
y = mod(int16(y),256); % convert from int8 to uint8
case 'matlab'
%% Perform the mapping
% A-Z -> 0 - 25
% a-z -> 26 - 51
% 0-9 -> 52 - 61
% + - -> 62 '-' is URL_SAFE alternative
% / _ -> 63 '_' is URL_SAFE alternative
map = uint8(zeros(1,256)+65);
map(uint8(['A':'Z', 'a':'z', '0':'9', '+/=']))= 0:64;
map(uint8('-_'))= 62:63; % URL_SAFE alternatives
x = map(x); % mapping
x(x>64)=[]; % remove non-base64 chars
if rem(numel(x), 4)
warning('Length of base64 data not a multiple of 4; padding input.');
end
x(x==64)=[]; % remove padding characters
%% add padding and reshape
nebytes = length(x); % number of encoded bytes
nchunks = ceil(nebytes/4); % number of chunks/groups
if rem(nebytes, 4)>0
x(end+1 : 4*nchunks) = 0; % add padding
end
x = reshape(uint8(x), 4, nchunks);
y = repmat(uint8(0), 3, nchunks); % for the decoded data
%% Rearrange every 4 bytes into 3 bytes
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
% to form
% aaaaaabb bbbbcccc ccdddddd
y(1,:) = bitshift(x(1,:), 2); % 6 highest bits of y(1,:)
y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4)); % 2 lowest bits of y(1,:)
y(2,:) = bitshift(x(2,:), 4); % 4 highest bits of y(2,:)
y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2)); % 4 lowest bits of y(2,:)
y(3,:) = bitshift(x(3,:), 6); % 2 highest bits of y(3,:)
y(3,:) = bitor(y(3,:), x(4,:)); % 6 lowest bits of y(3,:)
%% remove extra padding
switch rem(nebytes, 4)
case 2
y = y(1:end-2);
case 3
y = y(1:end-1);
end
end
%% reshape to a row vector and make it a character array
y = uint8(reshape(y, 1, numel(y)));
%% save to file if needed
if ~isempty(outfname)
fid = fopen(outfname,'wb');
fwrite(fid, y, 'uint8');
fclose(fid);
end