在v3d中也支持nrrd图像的处理,但是windows 系统下不支持打开?不知道是不是我的v3d版本的问题。
因此写了一个nrrd图像批量转化为tif文件的代码,不过运行效率比较低。主要分为三个文件
nrrdread.m
nrrdread.m 这个是从网上下的,这个文件里面,我去掉了Endian属性,因为我处理的图像是8位的,没有这个属性可选。
function [X, meta] = nrrdread(filename)
%NRRDREAD Import NRRD imagery and metadata.
% [X, META] = NRRDREAD(FILENAME) reads the image volume and associated
% metadata from the NRRD-format file specified by FILENAME.
% [X, META] = nrrdread('test.nrrd');
% Current limitations/caveats:
% * "Block" datatype is not supported.
% * Only tested with "gzip" and "raw" file encodings.
% * Very limited testing on actual files.
% * I only spent a couple minutes reading the NRRD spec.
%
% See the format specification online:
% http://teem.sourceforge.net/nrrd/format.html
% Copyright 2012 The MathWorks, Inc.
% Open file.
fid = fopen(filename, 'rb');
assert(fid > 0, 'Could not open file.');
cleaner = onCleanup(@() fclose(fid));
% Magic line.
theLine = fgetl(fid);
assert(numel(theLine) >= 4, 'Bad signature in file.')
assert(isequal(theLine(1:4), 'NRRD'), 'Bad signature in file.')
% The general format of a NRRD file (with attached header) is:
%
% NRRD000X
% <field>: <desc>
% <field>: <desc>
% # <comment>
% ...
% <field>: <desc>
% <key>:=<value>
% <key>:=<value>
% <key>:=<value>
% # <comment>
%
% <data><data><data><data><data><data>...
meta = struct([]);
% Parse the file a line at a time.
while (true)
theLine = fgetl(fid);
if (isempty(theLine) || feof(fid))
% End of the header.
break;
end
if (isequal(theLine(1), '#'))
% Comment line.
continue;
end
% "fieldname:= value" or "fieldname: value" or "fieldname:value"
parsedLine = regexp(theLine, ':=?\s*', 'split','once');
assert(numel(parsedLine) == 2, 'Parsing error')
field = lower(parsedLine{1});
value = parsedLine{2};
field(isspace(field)) = '';
meta(1).(field) = value;
end
datatype = getDatatype(meta.type);
% Get the size of the data.
assert(isfield(meta, 'sizes') && ...
isfield(meta, 'dimension') && ...
isfield(meta, 'encoding'), ...
'Missing required metadata fields.')
%在此处添加endian信息。 加入 isfield(meta, 'endian')
dims = sscanf(meta.sizes, '%d');
ndims = sscanf(meta.dimension, '%d');
assert(numel(dims) == ndims);
data = readData(fid, meta, datatype);
% data = adjustEndian(data, meta);
% Reshape and get into MATLAB's order.
X = reshape(data, dims');
X = permute(X, [2 1 3]);
function datatype = getDatatype(metaType)
% Determine the datatype
switch (metaType)
case {'signed char', 'int8', 'int8_t'}
datatype = 'int8';
case {'uchar', 'unsigned char', 'uint8', 'uint8_t'}
datatype = 'uint8';
case {'short', 'short int', 'signed short', 'signed short int', ...
'int16', 'int16_t'}
datatype = 'int16';
case {'ushort', 'unsigned short', 'unsigned short int', 'uint16', ...
'uint16_t'}
datatype = 'uint16';
case {'int', 'signed int', 'int32', 'int32_t'}
datatype = 'int32';
case {'uint', 'unsigned int', 'uint32', 'uint32_t'}
datatype = 'uint32';
case {'longlong', 'long long', 'long long int', 'signed long long', ...
'signed long long int', 'int64', 'int64_t'}
datatype = 'int64';
case {'ulonglong', 'unsigned long long', 'unsigned long long int', ...
'uint64', 'uint64_t'}
datatype = 'uint64';
case {'float'}
datatype = 'single';
case {'double'}
datatype = 'double';
otherwise
assert(false, 'Unknown datatype')
end
function data = readData(fidIn, meta, datatype)
switch (meta.encoding)
case {'raw'}
data = fread(fidIn, inf, [datatype '=>' datatype]);
case {'gzip', 'gz'}
tmpBase = tempname();
tmpFile = [tmpBase '.gz'];
fidTmp = fopen(tmpFile, 'wb');
assert(fidTmp > 3, 'Could not open temporary file for GZIP decompression')
tmp = fread(fidIn, inf, 'uint8=>uint8');
fwrite(fidTmp, tmp, 'uint8');
fclose(fidTmp);
gunzip(tmpFile)
fidTmp = fopen(tmpBase, 'rb');
cleaner = onCleanup(@() fclose(fidTmp));
meta.encoding = 'raw';
data = readData(fidTmp, meta, datatype);
case {'txt', 'text', 'ascii'}
data = fscanf(fidIn, '%f');
data = cast(data, datatype);
otherwise
assert(false, 'Unsupported encoding')
end
function data = adjustEndian(data, meta)
[~,~,endian] = computer();
needToSwap = (isequal(endian, 'B') && isequal(lower(meta.endian), 'little')) || ...
(isequal(endian, 'L') && isequal(lower(meta.endian), 'big'));
if (needToSwap)
data = swapbytes(data);
end
nrrd2tif.m
第二个文件是对单个nrrd文件转化为tif
function [ output_args ] = nrrd2tif( input_args )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
if nargin<1,
error('please input file');
end;
if exist(input_args, 'file')==0,
error('You have specified a file which does not exist.');
end;
save_file_name=[ input_args '.tif'];
if exist(save_file_name)
error('outputfile already exist');
% delete( save_file_name);
end
[X, meta] = nrrdread(input_args);
dims = sscanf(meta.sizes, '%d');
z_number=dims(3);
% Height=dims(2);
width=dims(1);
X1(1:1:width,:,:)=X(width:-1:1,:,:);
%X1=X;
for i=1:z_number
J=uint8(X1(:,:,i)); %%一层一层写出图像
imwrite(J,save_file_name,'WriteMode','Append');
end
end
但是在这个里面,我改了一下输出的图片,因为我总认为matlab的图片写入有点不同。
nrrd2tif_1.m
第三个文件是nrrd2tif_1.m,这个图片的作用是将当前路径下的nrrd文件转化为tif文件。
fileFolder=fullfile('.');
dirOutput=dir(fullfile(fileFolder,'*.nrrd'));
fileNames={dirOutput.name};
number=size(fileNames,2)
for i=1: number
nrrd2tif(fileNames{i})
end