-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTiffSim.m
More file actions
162 lines (145 loc) · 5.3 KB
/
Copy pathTiffSim.m
File metadata and controls
162 lines (145 loc) · 5.3 KB
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
157
158
159
160
161
classdef TiffSim < handle
%TIFFSIM Read & Write tiff3d by stream without config.
% Example:
% >>> tf = TiffSim('1.tif', 'w');
% >>> tf.write(imread('rice.png')); tf.write(imread('rice.png')); % write
% >>> tf.seek(1); tf.write(imgaussfilt(imread('rice.png'))); % overwrite
% >>> tf.seek(1); tf.read(); tf.read(); % read tiff
% >>> tf.eof() % file end, read over
% >>> tf.close();
% >>> imfinfo('1.tif') % can be opened by ImageJ
%
% when img is double, save as float unless using `write(img, 'double')`
% In other conditions, save format is same as img.
%
% 图像堆栈如果是统一格式的,默认便可以用 ImageJ 打开,double型除外
% 如果每张图像格式不一致,那么可以使用 ImageJ 的虚拟堆栈打开
%
% See other details in functions. Copyright 2022, https://github.com/w6Lc
properties (Access = protected)
tf % inner tiff handle
file % file
nums % nums of pics
end
methods
function obj = TiffSim(file, mode)
% mode: None('r+') | 'w' | 'r+'
if ~exist('mode', 'var'), mode = 'r+'; end
if strcmp(mode, 'w') || ~exist(file, 'file')
obj.tf = Tiff(file, 'w');
obj.nums = 0;
elseif strcmp(mode, 'r+')
obj.tf = Tiff(file, 'r+');
obj.nums = length(imfinfo(file));
end
obj.file = file;
end
function close(obj)
obj.tf.close();
end
function pos = tell(obj)
% pos: <1-n>
pos = obj.tf.currentDirectory();
end
function seek(obj, num)
% num: <1-n>
obj.tf.setDirectory(num);
end
function nums = len(obj)
% nums: <1-n>
nums = obj.nums;
end
function is_eof = eof(obj)
is_eof = obj.tell() > obj.len();
end
function info = get_info(obj)
info = imfinfo(obj.file);
end
function img = read(obj)
img = obj.tf.read();
if obj.tell() == obj.nums
obj.tf.writeDirectory();
else
obj.tf.nextDirectory();
end
end
function write(obj, img, fmt, tag)
% Args:
% img: <mat>(size: 2d | rgb,
% fmt: <matlab_fmt>('int<n>', 'uint<n>','float', 'double', ...))
% fmt: None(judge from img) | <num_fmt>('uint8', 'float', 'double', ...)
% PS: when img is double, fmt is float.
% tag: None(judge from img) | <tag_struct>
%
% Examples:
% >>> tf = TiffSim('1.tif', 'w');
% >>> tf.write(imread('rice.png'), 'float');
% >>> tf.write(imread('rice.png'), [], struct('Compression', Tiff.Compression.LZW));
% >>> tf.write(imread('rice.png'));
% >>> imfinfo('1.tif') % can also open use vitual stack with imageJ (256,256,3)
if ~exist('fmt', 'var'), fmt = []; end
if ~exist('tag', 'var'), tag = []; end
if isempty(fmt)
fmt = class(img);
if isa(img, 'double'), fmt = 'float'; end % img为double时默认保存为float
end
% =============================== tag ============================
% 测试写入时间,None 0.22, PackBits 0.38, LZW 0.56, Deflate 3.97, png 0.99, JPEG
% 测试读取时间,None 0.22, PackBits 0.22, LZW 0.38, Deflate 0.30, png 0.23
% 测试写入大小,None 25 , PackBits 25 , LZW 7 , Deflate 6 , png 4
% None最快, 大小速度综合考虑 pb,lzw,大小考虑 png
tag_.Compression = Tiff.Compression.None; % default None
tag_.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
% precision
if strcmp(fmt(1:4), 'uint')
tag_.SampleFormat = Tiff.SampleFormat.UInt; % can not set twice in 1 IFD
tag_.BitsPerSample = str2double(fmt(5:end));
img = eval([fmt, '(img)']);
elseif strcmp(fmt(1:3), 'int')
tag_.SampleFormat = Tiff.SampleFormat.Int;
tag_.BitsPerSample = str2double(fmt(4:end));
img = eval([fmt, '(img)']);
elseif strcmp(fmt, 'float') || strcmp(fmt, 'single')
tag_.SampleFormat = Tiff.SampleFormat.IEEEFP;
tag_.BitsPerSample = 32;
img = single(img);
elseif strcmp(fmt, 'double')
tag_.SampleFormat = Tiff.SampleFormat.IEEEFP;
tag_.BitsPerSample = 64;
img = double(img);
end
% size
tag_.ImageLength = size(img, 1);
tag_.ImageWidth = size(img, 2);
tag_.SamplesPerPixel = size(img, 3);
if tag_.SamplesPerPixel == 1
tag_.Photometric = Tiff.Photometric.MinIsBlack;
else
tag_.Photometric = Tiff.Photometric.RGB;
end
% rewrite
if ~isempty(tag)
keys = fieldnames(tag);
for i = 1:length(keys), tag_.(keys{i}) = tag.(keys{i}); end
end
% ============================ write ================================
obj.tf.setTag(tag_);
obj.tf.write(img); % write 后无法再setTag
if obj.tell() == 0 || obj.eof()
obj.tf.writeDirectory();
obj.nums = obj.nums + 1;
% matlab 初始 tell为0,修正为1; 运行正常时,obj.tell() <= obj.len()
if obj.tell()==1, obj.seek(1); obj.tf.writeDirectory(); end
else
tmp = obj.tf.currentDirectory();
obj.tf.rewriteDirectory(); % 运行之后必须重定位
if tmp < obj.len()
obj.seek(tmp+1);
else
obj.seek(tmp);
obj.tf.writeDirectory();
end
end
end
end
end