-
Notifications
You must be signed in to change notification settings - Fork 5
/
zmat.m
156 lines (138 loc) · 5.72 KB
/
zmat.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
function varargout = zmat(varargin)
%
% output=zmat(input)
% or
% [output, info]=zmat(input, iscompress, method)
% [output, info]=zmat(input, iscompress, method, options ...)
% output=zmat(input, info)
%
% A portable data compression/decompression toolbox for MATLAB/GNU Octave
%
% author: Qianqian Fang <q.fang at neu.edu>
% initial version created on 04/30/2019
%
% input:
% input: a char, non-complex numeric or logical vector or array
% iscompress: (optional) if iscompress is 1, zmat compresses/encodes the input,
% if 0, it decompresses/decodes the input. Default value is 1.
%
% if iscompress is set to a negative integer, (-iscompress) specifies
% the compression level. For zlib/gzip, default level is 6 (1-9); for
% lzma/lzip, default level is 5 (1-9); for lz4hc, default level is 8 (1-16).
% the default compression level is used if iscompress is set to 1.
%
% zmat removes the trailing newline when iscompress=2 and method='base64'
% all newlines are kept when iscompress=3 and method='base64'
%
% if one defines iscompress as the info struct (2nd output of zmat), zmat
% will perform a decoding/decompression operation and recover the original
% input using the info stored in the info structure.
% method: (optional) compression method, currently, zmat supports the below methods
% 'zlib': zlib/zip based data compression (default)
% 'gzip': gzip formatted data compression
% 'lzip': lzip formatted data compression
% 'lzma': lzma formatted data compression
% 'lz4': lz4 formatted data compression
% 'lz4hc':lz4hc (LZ4 with high-compression ratio) formatted data compression
% 'zstd': zstd formatted data compression
% 'blosc2blosclz': blosc2 meta-compressor with blosclz compression
% 'blosc2lz4': blosc2 meta-compressor with lz4 compression
% 'blosc2lz4hc': blosc2 meta-compressor with lz4hc compression
% 'blosc2zlib: blosc2 meta-compressor with zlib/zip compression
% 'blosc2zstd': blosc2 meta-compressor with zstd compression
% 'base64': encode or decode use base64 format
% options: a series of ('name', value) pairs, supported options include
% 'nthread': followed by an integer specifying number of threads for blosc2 meta-compressors
% 'typesize': followed by an integer specifying the number of bytes per data element (used for shuffle)
% 'shuffle': shuffle methods in blosc2 meta-compressor, 0 disable, 1, byte-shuffle
%
% output:
% output: a uint8 row vector, storing the compressed or decompressed data;
% empty when an error is encountered
% info: (optional) a struct storing additional info regarding the input data, may have
% 'type': the class of the input array
% 'size': the dimensions of the input array
% 'byte': the number of bytes per element in the input array
% 'method': a copy of the 3rd input indicating the encoding method
% 'status': the zlib/lzma/lz4 compression/decompression function return value,
% including potential error codes; see documentation of the respective
% libraries for details
% 'level': a copy of the iscompress flag; if non-zero, specifying compression
% level, see above
%
% example:
%
% [ss, info]=zmat(eye(5))
% orig=zmat(ss,0)
% orig=zmat(ss,info)
% ss=char(zmat('zmat test',1,'base64'))
% orig=char(zmat(ss,0,'base64'))
%
% -- this function is part of the ZMAT toolbox (https://github.com/NeuroJSON/zmat)
%
if (exist('zipmat') ~= 3 && exist('zipmat') ~= 2)
error('zipmat mex file is not found. you must download the mex file or recompile');
end
if (nargin == 0)
fprintf(1, 'Usage:\n\t[output,info]=zmat(input,iscompress,method);\nPlease run "help zmat" for more details.\n');
return
end
input = varargin{1};
iscompress = 1;
zipmethod = 'zlib';
if (~(ischar(input) || islogical(input) || (isnumeric(input) && isreal(input))))
error('input must be a char, non-complex numeric or logical vector or N-D array');
end
inputinfo=whos('input');
if(~isempty(input))
typesize=inputinfo.bytes/numel(input);
else
typesize=0;
end
if (ischar(input))
input = uint8(input);
end
if (nargin > 1)
iscompress = varargin{2};
if (isstruct(varargin{2}))
inputinfo = varargin{2};
iscompress = 0;
zipmethod = inputinfo.method;
end
end
if (nargin > 2)
zipmethod = varargin{3};
end
opt=struct;
if (nargin > 4 && ischar(varargin{4}) && bitand(length(varargin), 1)==1)
opt=cell2struct(varargin(5:2:end), varargin(4:2:end), 2);
end
shuffle=0;
if(strfind(zipmethod,'blosc2'))
shuffle=1;
end
nthread=getoption('nthread', 1, opt);
shuffle=getoption('shuffle', shuffle, opt);
typesize=getoption('typesize', typesize, opt);
iscompress = round(iscompress);
if ((strcmp(zipmethod, 'zlib') || strcmp(zipmethod, 'gzip')) && iscompress <= -10)
iscompress = -9;
end
[varargout{1:max(1, nargout)}] = zipmat(input, iscompress, zipmethod, nthread, shuffle, typesize);
if (strcmp(zipmethod, 'base64') && iscompress > 1)
varargout{1} = char(varargout{1});
end
if (exist('inputinfo', 'var') && isfield(inputinfo, 'type'))
if(strcmp(inputinfo.type,'logical'))
varargout{1} = logical(varargout{1});
else
varargout{1} = typecast(varargout{1}, inputinfo.type);
end
varargout{1} = reshape(varargout{1}, inputinfo.size);
end
%--------------------------------------------------------------------------------
function value=getoption(key, default, opt)
value=default;
if(isfield(opt, key))
value=opt.(key);
end