Skip to content

Commit 977c945

Browse files
committed
feat: add thermal facade and FLIR postprocess app
1 parent 1699295 commit 977c945

43 files changed

Lines changed: 2553 additions & 28 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

+labkit/+contract/checkRequirements.m

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
% Inputs:
99
% req - struct returned by labkit.contract.requirements.
1010
% versions - optional struct array of facade version structs. When omitted,
11-
% current labkit.ui/dta/rhs/biosignal/image version APIs are queried.
11+
% current labkit.ui/dta/rhs/biosignal/image/thermal version APIs are
12+
% queried.
1213
%
1314
% Outputs:
1415
% report - struct with ok, failures, and message fields. ok is true only
@@ -65,7 +66,8 @@
6566
labkit.dta.version()
6667
labkit.rhs.version()
6768
labkit.biosignal.version()
68-
labkit.image.version()];
69+
labkit.image.version()
70+
labkit.thermal.version()];
6971
end
7072

7173
function entries = normalizeRequirements(req)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function filterSpec = fileDialogFilter(varargin)
2+
%FILEDIALOGFILTER Return a file-chooser-compatible thermal image filter.
3+
%
4+
% App-facing contract:
5+
% filterSpec = labkit.thermal.fileDialogFilter()
6+
% filterSpec = labkit.thermal.fileDialogFilter("IncludeAll", true)
7+
%
8+
% Inputs:
9+
% IncludeAll - optional logical scalar, default false. When true, append an
10+
% "All files (*.*)" row after the thermal-file row.
11+
%
12+
% Outputs:
13+
% filterSpec - cell array accepted by filePanel filters and MATLAB
14+
% file-chooser filter specs.
15+
16+
opts = parseOptions(varargin{:});
17+
thermalRow = {'*.jpg;*.jpeg;*.rjpg', ...
18+
'FLIR radiometric JPEG (*.jpg, *.jpeg, *.rjpg)'};
19+
if opts.IncludeAll
20+
filterSpec = [thermalRow; {'*.*', 'All files (*.*)'}];
21+
else
22+
filterSpec = thermalRow;
23+
end
24+
end
25+
26+
function opts = parseOptions(varargin)
27+
p = inputParser;
28+
p.FunctionName = "labkit.thermal.fileDialogFilter";
29+
p.addParameter("IncludeAll", false, @isLogicalScalar);
30+
p.parse(varargin{:});
31+
opts = p.Results;
32+
opts.IncludeAll = logical(opts.IncludeAll);
33+
end
34+
35+
function tf = isLogicalScalar(value)
36+
tf = (islogical(value) || isnumeric(value)) && isscalar(value);
37+
end

+labkit/+thermal/inspectFile.m

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
function info = inspectFile(path, opts)
2+
%INSPECTFILE Report whether one file contains readable thermal data.
3+
%
4+
% App-facing contract:
5+
% info = labkit.thermal.inspectFile(path)
6+
% info = labkit.thermal.inspectFile(path, opts)
7+
%
8+
% Inputs:
9+
% path - scalar char/string path.
10+
% opts - optional scalar struct with fields accepted by
11+
% labkit.thermal.readFile.
12+
%
13+
% Outputs:
14+
% info - scalar struct with path, name, supportedExtension, isThermal,
15+
% format, identifier, and message fields. This function catches reader
16+
% failures and never throws for unsupported or non-radiometric image
17+
% content.
18+
19+
if nargin < 2 || isempty(opts)
20+
opts = struct();
21+
end
22+
[~, base, ext] = fileparts(char(string(path)));
23+
info = struct( ...
24+
'path', string(path), ...
25+
'name', string([base ext]), ...
26+
'supportedExtension', labkit.thermal.isSupportedPath(path), ...
27+
'isThermal', false, ...
28+
'format', "", ...
29+
'identifier', "", ...
30+
'message', "");
31+
32+
if ~info.supportedExtension
33+
info.identifier = "labkit:thermal:UnsupportedFile";
34+
info.message = "Unsupported thermal image file extension.";
35+
return;
36+
end
37+
38+
try
39+
record = labkit.thermal.readFile(path, opts);
40+
info.isThermal = true;
41+
info.format = record.format;
42+
info.message = record.message;
43+
catch ME
44+
info.identifier = string(ME.identifier);
45+
info.message = string(ME.message);
46+
end
47+
end

+labkit/+thermal/isSupportedPath.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function tf = isSupportedPath(path)
2+
%ISSUPPORTEDPATH Return true for supported thermal source paths.
3+
%
4+
% App-facing contract:
5+
% tf = labkit.thermal.isSupportedPath(path)
6+
%
7+
% Inputs:
8+
% path - char, string, or scalar path-like value.
9+
%
10+
% Outputs:
11+
% tf - logical scalar. True when the extension is supported by the current
12+
% thermal facade reader set.
13+
14+
[~, ~, ext] = fileparts(char(string(path)));
15+
tf = any(lower(string(ext)) == labkit.thermal.supportedExtensions());
16+
end

0 commit comments

Comments
 (0)