📄 dcmio.m
字号:
% number of objects
switch (ddt)
case {'double'}
dvl = round(dvl / 8);
case {'int32', 'single', 'uint32'}
dvl = round(dvl / 4);
case {'int16', 'uint16'}
dvl = dvl / 2;
end
dval = fread(rfid, [1, dvl], ['*' ddt]);
if ischar(dval) && ...
isempty(dval)
dval = '';
end
if DataVR.deblank
dval = deblank(dval);
end
else
dval = [];
end
MetaStr(MetaKeyCount).Value = dval;
MetaKeyCount = MetaKeyCount + 1;
end
% put meta back
dcmcont.Meta = MetaStr;
mkey = cell(length(MetaStr), 1);
mkys = struct;
for c = 1:length(mkey)
mky = sprintf('k_%04X_%04X', MetaStr(c).Key);
mkey{c} = mky;
mkys.(mky) = c;
end
dcmcont.MetaKeys = mkey;
dcmcont.MetaKeyLookup = mkys;
end
% initialize data struct
dstr = dcmcont.Data;
DataLEndian = true;
% check implicit/explicit TS for data part
vrcheck = fc_uint8(fpos+4:fpos+5);
dcmcont.DataTSExplicit = all(vrcheck > 64 & vrcheck < 91);
dvs = dcmcont.DataTSExplicit;
% check endian only on explicit VR syntax
if dcmcont.DataTSExplicit
lecheck = fc_uint8(fpos:fpos+4);
if lecheck(1) < lecheck(2)
dcmcont.DataLittleEndian = false;
elseif lecheck(1) == lecheck(2)
if lecheck(3) < lecheck(4)
dcmcont.DataLittleEndian = false;
elseif lecheck(3) == lecheck(4)
warning( ...
'BVQXtools:FileDetectionFailed', ...
'Error detecting Endian type in Data part, assuming LE.' ...
);
dcmcont.DataLittleEndian = true;
end
end
DataLEndian = dcmcont.DataLittleEndian;
end
if DataLEndian
rfid = fid;
else
rfid = fidbe;
end
% data part until fpos > flenmin
DStrKeyCount = numel(dstr);
while fpos <= flenmin
% get correct key format
DataKeyCount = DataKeyCount + 1;
fposh = round(fpos/2);
if DataLEndian
DicomKey = double([fc_uint16_le(fposh), fc_uint16_le(fposh+1)]);
else
DicomKey = double([fc_uint16_be(fposh), fc_uint16_be(fposh+1)]);
end
if DataKeyCount > DStrKeyCount
if DStrKeyCount < 128
DStrKeyCount = 128;
end
dstr(2 * DStrKeyCount).Key = [];
DStrKeyCount = numel(dstr);
end
dstr(DataKeyCount).Key = DicomKey;
fpos = fpos + 4;
% sequence ?
if DicomKey(1) > 65533
DataSequence = true;
DataVR = vrSQ;
else
DataSequence = false;
end
% VR ?
if ~DataSequence && ...
dvs
DataVR = upper(char(fc_uint8(fpos:fpos+1)));
fpos = fpos + 2;
if ~isfield(my_dicom_vr, DataVR)
error( ...
'BVQXtools:InvalidToken', ...
'Invalid VR found: %s.', ...
DataVR ...
);
end
DataVR = my_dicom_vr.(DataVR);
elseif ~dvs
tkey = sprintf('k_%04X_%04X', DicomKey(1), DicomKey(2));
try
DataVR = my_dicom_vr.(upper(my_dicom_dic.Dictionary.(tkey).vr));
catch
DataVR = vrUN;
end
elseif ~DataSequence
DataVR = vrUN;
end
dstr(DataKeyCount).VR = DataVR.tag;
if DataVR.length(2) > 32767
DataShortVLength = false;
else
DataShortVLength = true;
end
% length
fposh = round(fpos/2);
if DataLEndian
DataVLengthShort = double(fc_uint16_le(fposh));
else
DataVLengthShort = double(fc_uint16_be(fposh));
end
if ~DataShortVLength && ...
~DataSequence && ...
dvs && ...
DataVLengthShort > 0
error( ...
'BVQXtools:InvalidFileContent', ...
'Invalid 16-bit VL for given VR.' ...
);
elseif DataSequence && ...
any([57357, 57565] == DicomKey(2)) && ...
all(fc_uint16_le(fposh:fposh+1) == 0)
fpos = fpos - 2;
fposh = fposh - 1;
end
if ~DataShortVLength || ...
~dvs
if DataVLengthShort == 0 && ...
dvs
if DataLEndian
DataVLengthLong = 65536 * ...
double(fc_uint16_le(fposh+2)) + ...
double(fc_uint16_le(fposh+1));
else
DataVLengthLong = 65536 * ...
double(fc_uint16_le(fposh+1)) + ...
double(fc_uint16_le(fposh+2));
end
fpos = fpos + 6;
else
if DataLEndian
DataVLengthLong = 65536 * ...
double(fc_uint16_le(fposh+1)) + ...
double(fc_uint16_le(fpos));
else
DataVLengthLong = 65536 * ...
double(fc_uint16_le(fposh)) + ...
double(fc_uint16_le(fposh+1));
end
fpos = fpos + 4;
end
dvl = DataVLengthLong;
else
fpos = fpos + 2;
DataVLengthLong = NaN;
dvl = DataVLengthShort;
end
dstr(DataKeyCount).VLShort = DataVLengthShort;
dstr(DataKeyCount).VLLong = DataVLengthLong;
dvl = 2 * round(dvl/2);
% get value according to type
ddt = lower(DataVR.datatype);
if ~strcmp(ddt, 'sequence')
% go to and update position
fseek(rfid, fpos - 1, -1);
fpos = fpos + dvl;
% number of objects
switch (ddt)
case {'double'}
dvl = round(dvl / 8);
case {'int32', 'single', 'uint32'}
dvl = round(dvl / 4);
case {'int16', 'uint16'}
dvl = dvl / 2;
end
dval = fread(rfid, [1, dvl], ['*' ddt]);
if ischar(dval) && ...
isempty(dval)
dval = '';
end
if DataVR.deblank
dval = deblank(dval);
end
else
dval = [];
end
dstr(DataKeyCount).Value = dval;
end
% put meta back
dcmcont.Data = dstr(1:DataKeyCount);
DicomKey = cell(numel(dcmcont.Data), 1);
dkys = struct;
for c = 1:length(DicomKey)
dky = dcmiofmtkey(dstr(c).Key);
DicomKey{c} = dky;
dkys.(dky) = c;
end
dcmcont.DataKeys = DicomKey;
dcmcont.DataKeyLookup = dkys;
% writing
else
% not yet implemented
end
catch
% do nothing here...
end % try forcemode
% close main file
fclose(fid);
% create good object
hfile = bless(BVQXfile('new:dcm'), 1);
setcont(hfile, dcmcont);
% close big-endian file
if ~writemode
fclose(fidbe);
end
% give correct output
varargout = [{hfile}, cell(1, max(0, nargout - 1))];
% format a dicom key
function dfk = dcmiofmtkey(k)
persistent dfkc;
if isempty(dfkc)
dfkc = '0123456789ABCDEF';
end
fkr = min(65535, max(0, floor(real(k))));
fk1 = '0000';
fc = 4;
fk = fkr(1);
while fk > 0
fk1(fc) = dfkc(mod(fk, 16) + 1);
fk = floor(fk/16);
fc = fc - 1;
end
fk2 = '0000';
fc = 4;
fk = fkr(2);
while fk > 0
fk2(fc) = dfkc(mod(fk, 16) + 1);
fk = floor(fk/16);
fc = fc - 1;
end
dfk = ['k_' fk1 '_' fk2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -