1
by Michael Hanke
Import upstream version 0.20100725.1~dfsg.1 |
1 |
unit reslice_fsl; |
2 |
{$H+}
|
|
3 |
interface
|
|
4 |
uses
|
|
5 |
nifti_hdr,define_types,metagraph,sysutils; |
|
6 |
||
7 |
function ResliceImg (lTargetImgName,lSrcImgName,lSrc2TargetMatName,lOutputName: string): boolean; |
|
8 |
procedure ResliceFSL; |
|
9 |
||
10 |
implementation
|
|
11 |
||
12 |
uses nifti_img_view,dialogs,nifti_img,text,graphx,math,nifti_hdr_view,GraphicsMathLibrary,classes; |
|
13 |
||
14 |
procedure ResliceFSL; |
|
15 |
label
|
|
16 |
666; |
|
17 |
var
|
|
18 |
lInc,lNumberofFiles: integer; |
|
19 |
lSrc2TargetMatName,lSrcImgName,lTargetImgName,lOutputName:string; |
|
20 |
lStrings : TStringList; |
|
21 |
begin
|
|
22 |
ImgForm.CloseImagesClick(nil); |
|
23 |
if not OpenDialogExecute(kImgFilter,'Select source image[s]',true) then exit; |
|
24 |
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count; |
|
25 |
if lNumberofFiles < 1 then |
|
26 |
exit; |
|
27 |
lStrings := TStringList.Create; |
|
28 |
lStrings.AddStrings(HdrForm.OpenHdrDlg.Files); |
|
29 |
if not OpenDialogExecute('FSL (*.mat)|*.mat','Select FSL source-to-target matrix',false) then goto 666; |
|
30 |
lSrc2TargetMatName := HdrForm.OpenHdrDlg.Filename; |
|
31 |
if not OpenDialogExecute(kImgFilter,'Select target image (source image will be warped to this)',false) then goto 666; |
|
32 |
lTargetImgName := HdrForm.OpenHdrDlg.Filename; |
|
33 |
||
1.1.1
by Michael Hanke
Import upstream version 0.20100820.1~dfsg.1 |
34 |
TextForm.MemoT.Lines.Clear; |
1
by Michael Hanke
Import upstream version 0.20100725.1~dfsg.1 |
35 |
for lInc:= 1 to lNumberofFiles do begin |
36 |
lSrcImgName := lStrings[lInc-1]; |
|
37 |
lOutputName := ChangeFilePrefix (lSrcImgName,'w'); |
|
1.1.1
by Michael Hanke
Import upstream version 0.20100820.1~dfsg.1 |
38 |
TextForm.MemoT.Lines.Add(' Source->Matrix->Target '+lSrcImgName+'->'+ lSrc2TargetMatName+'->'+lTargetImgName); |
1
by Michael Hanke
Import upstream version 0.20100725.1~dfsg.1 |
39 |
ResliceImg (lTargetImgName,lSrcImgName,lSrc2TargetMatName,lOutputName); |
40 |
end;//lLoop |
|
41 |
TextForm.Show; |
|
42 |
666: |
|
43 |
lStrings.free; |
|
44 |
end; |
|
45 |
||
46 |
function ReadFSLMat (var lMat: TMatrix; lSrc2TargetMatName: string):boolean; |
|
47 |
var
|
|
48 |
lF: TextFile; |
|
49 |
xx,xy,xz,xo |
|
50 |
,yx,yy,yz,yo |
|
51 |
,zx,zy,zz,zo: double; |
|
52 |
begin
|
|
53 |
result := false; |
|
54 |
if not fileexists(lSrc2TargetMatName) then exit; |
|
55 |
Assign(lF,lSrc2TargetMatName); |
|
56 |
Filemode := 0; |
|
57 |
Reset(lF); |
|
58 |
readln(lF,xx,xy,xz,xo,yx,yy,yz,yo,zx,zy,zz,zo); |
|
59 |
//read all with one readln -
|
|
60 |
// separate readlns only work for native eoln
|
|
61 |
CloseFile(lF); |
|
62 |
lMat:= Matrix3D (xx,xy,xz,xo |
|
63 |
,yx,yy,yz,yo |
|
64 |
,zx,zy,zz,zo |
|
65 |
,0,0,0,1); |
|
66 |
result := true; |
|
67 |
Filemode := 2; |
|
68 |
end; |
|
69 |
||
70 |
function Rx (var lDestHdr,lSrcHdr: TMRIcroHdr; var lInMat: TMatrix; var lOutputName: string):boolean; |
|
71 |
var
|
|
72 |
lPos,lXYs,lXYZs,lXs,lYs,lZs,lXi,lYi,lZi,lX,lY,lZ, |
|
73 |
lXo,lYo,lZo,lMinY,lMinZ,lMaxY,lMaxZ: integer; |
|
74 |
lXrM1,lYrM1,lZrM1, |
|
75 |
lXreal,lYreal,lZreal: double; |
|
76 |
lOutImg: bytep; |
|
77 |
lScale,lMat: TMatrix; |
|
78 |
begin
|
|
79 |
result := false; |
|
80 |
lXs := lSrcHdr.NIFTIhdr.Dim[1]; |
|
81 |
lYs := lSrcHdr.NIFTIhdr.Dim[2]; |
|
82 |
lZs := lSrcHdr.NIFTIhdr.Dim[3]; |
|
83 |
if (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems <> lXs*lYs*lZs) then begin |
|
84 |
showmessage('Reslice error: background image not loaded.'); |
|
85 |
exit; |
|
86 |
end; |
|
87 |
lXYs:=lXs*lYs; //slicesz |
|
88 |
lXYZs := lXYs*lZs; |
|
89 |
lX := lDestHdr.NIFTIhdr.Dim[1]; |
|
90 |
lY := lDestHdr.NIFTIhdr.Dim[2]; |
|
91 |
lZ := lDestHdr.NIFTIhdr.Dim[3]; |
|
92 |
//TextForm.Memo1.Lines.Add(inttostr(lXs)+'x'+inttostr(lYs)+'x'+inttostr(lZs)+'->'+inttostr(lX)+'x'+inttostr(lY)+'x'+inttostr(lZ));
|
|
93 |
lDestHdr.NIFTIhdr.Dim[4] := 1; |
|
94 |
getmem(lOutImg, lX*lY*lZ*sizeof(byte)); |
|
95 |
lPos := 0; |
|
96 |
//http://eeg.sourceforge.net/MJenkinson_coordtransforms.pdf
|
|
97 |
//FLIRT transforms are in world coordinates [mm]
|
|
98 |
//to convert to a vxl-vxl transform, the matrix must be
|
|
99 |
//PRE-multiplied by inv(Dest) and POST-multiplied by Src
|
|
100 |
//where Dest and Src are the spatial dimensions in mm
|
|
101 |
lScale:= Matrix3D (abs(lSrcHdr.NIFTIhdr.pixdim[1]),0,0,0 |
|
102 |
,0,abs(lSrcHdr.NIFTIhdr.pixdim[2]),0,0 |
|
103 |
,0,0,abs(lSrcHdr.NIFTIhdr.pixdim[3]),0 |
|
104 |
,0,0,0,1); |
|
105 |
lScale := InvertMatrix3D(lScale); |
|
106 |
lMat := MultiplyMatrices(lScale,lInMat); |
|
107 |
lScale:= Matrix3D (abs(lDestHdr.NIFTIhdr.pixdim[1]),0,0,0 |
|
108 |
,0,abs(lDestHdr.NIFTIhdr.pixdim[2]),0,0 |
|
109 |
,0,0,abs(lDestHdr.NIFTIhdr.pixdim[3]),0 |
|
110 |
,0,0,0,1); |
|
111 |
lMat := MultiplyMatrices(lMat,lScale); |
|
112 |
for lZi := 0 to (lZ-1) do begin |
|
113 |
for lYi := 0 to (lY-1) do begin |
|
114 |
for lXi := 0 to (lX-1) do begin |
|
115 |
inc(lPos); |
|
116 |
lOutImg^[lPos] := 0; |
|
117 |
lXreal := (lXi*lMat.matrix[1][1]+lYi*lMat.matrix[1][2]+lZi*lMat.matrix[1][3]+lMat.matrix[1][4]); |
|
118 |
lYreal := (lXi*lMat.matrix[2][1]+lYi*lMat.matrix[2][2]+lZi*lMat.matrix[2][3]+lMat.matrix[2][4]); |
|
119 |
lZreal := (lXi*lMat.matrix[3][1]+lYi*lMat.matrix[3][2]+lZi*lMat.matrix[3][3]+lMat.matrix[3][4]); |
|
120 |
//need to test Xreal as -0.01 truncates to zero
|
|
121 |
if (lXreal >= 0) and (lYreal >= 1) and (lZreal >= 1) and |
|
122 |
(lXreal < (lXs -1)) and (lYreal < (lYs -1) ) and (lZreal < (lZs -1)) |
|
123 |
then begin |
|
124 |
lXo := trunc(lXreal); |
|
125 |
lYo := trunc(lYreal); |
|
126 |
lZo := trunc(lZreal); |
|
127 |
lXreal := lXreal-lXo; |
|
128 |
lYreal := lYreal-lYo; |
|
129 |
lZreal := lZreal-lZo; |
|
130 |
lXrM1 := 1-lXreal; |
|
131 |
lYrM1 := 1-lYreal; |
|
132 |
lZrM1 := 1-lZreal; |
|
133 |
lMinY := ((lYo)*lXs); |
|
134 |
lMinZ := ((lZo)*lXYs); |
|
135 |
lMaxY := ((lYo+1)*lXs); |
|
136 |
lMaxZ := ((lZo+1)*lXYs); |
|
137 |
inc(lXo);//images incremented from 1 not 0 |
|
138 |
{if lMax <(lXreal) then
|
|
139 |
lMax := lXreal;
|
|
140 |
if lMin >(lXreal) then
|
|
141 |
lMin := lXreal; }
|
|
142 |
lOutImg^[lPos] := |
|
143 |
round ( |
|
144 |
{all min} ( (lXrM1*lYrM1*lZrM1)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+lMinY+lMinZ]) |
|
145 |
{x+1}+((lXreal*lYrM1*lZrM1)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+1+lMinY+lMinZ]) |
|
146 |
{y+1}+((lXrM1*lYreal*lZrM1)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+lMaxY+lMinZ]) |
|
147 |
{z+1}+((lXrM1*lYrM1*lZreal)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+lMinY+lMaxZ]) |
|
148 |
{x+1,y+1}+((lXreal*lYreal*lZrM1)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+1+lMaxY+lMinZ]) |
|
149 |
{x+1,z+1}+((lXreal*lYrM1*lZreal)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+1+lMinY+lMaxZ]) |
|
150 |
{y+1,z+1}+((lXrM1*lYreal*lZreal)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+lMaxY+lMaxZ]) |
|
151 |
{x+1,y+1,z+1}+((lXreal*lYreal*lZreal)*gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lXo+1+lMaxY+lMaxZ]) ); |
|
152 |
end; |
|
153 |
end;//z |
|
154 |
end;//y |
|
155 |
end;//z |
|
156 |
deletefile(lOutputName); |
|
157 |
SaveAsVOIorNIFTIcore (lOutputName,lOutImg, lX*lY*lZ, 1,1,lDestHdr.NIFTIhdr); |
|
158 |
lPos := 1; |
|
159 |
while (lPos <= (lX*lY*lZ)) and (lOutImg^[lPos] = 0) do |
|
160 |
inc(lPos); |
|
161 |
if lPos > (lX*lY*lZ) then |
|
162 |
result := false |
|
163 |
else
|
|
164 |
result := true; |
|
165 |
freemem(lOutImg); |
|
166 |
end; |
|
167 |
||
168 |
function ResliceImg (lTargetImgName,lSrcImgName,lSrc2TargetMatName,lOutputName: string): boolean; |
|
169 |
label
|
|
170 |
666; |
|
171 |
var
|
|
172 |
lReslice,lOrtho : boolean; |
|
173 |
lDestHdr,lSrcHdr: TMRIcroHdr; |
|
174 |
lMat: TMatrix; |
|
175 |
begin
|
|
176 |
result := false; |
|
177 |
if not fileexists(lTargetImgName) then exit; |
|
178 |
if not fileexists(lSrcImgName) then exit; |
|
179 |
if not fileexists(lSrc2TargetMatName) then exit; |
|
180 |
if not ReadFSLMat(lMat,lSrc2TargetMatName) then exit; |
|
181 |
ImgForm.CloseImagesClick(nil); |
|
182 |
lReslice := gBGImg.ResliceOnLoad; |
|
183 |
lOrtho := gBGImg.OrthoReslice; |
|
184 |
gBGImg.OrthoReslice := false; |
|
185 |
gBGImg.ResliceOnLoad := false; |
|
186 |
//if not HdrForm.OpenAndDisplayHdr(lTargetImgName,lDestHdr) then goto 666;
|
|
187 |
if not NIFTIhdr_LoadHdr(lTargetImgName, lDestHdr) then goto 666; |
|
188 |
if not NIFTIhdr_LoadHdr(lSrcImgName, lSrcHdr) then goto 666; |
|
189 |
ImgForm.OpenAndDisplayImg(lSrcImgName,True); |
|
190 |
if not Rx(lDestHdr,lSrcHdr,lMat,lOutputName) then goto 666; |
|
191 |
result := true; |
|
192 |
666: |
|
193 |
if not result then |
|
194 |
showmessage('Error applying transform '+lSrcImgName+'->'+lTargetImgName+' using '+lSrc2TargetMatName); |
|
195 |
gBGImg.ResliceOnLoad := lReslice; |
|
196 |
gBGImg.OrthoReslice := lOrtho; |
|
197 |
end; |
|
198 |
||
199 |
||
200 |
end. |
|
201 |