5
{$DEFINE noCOMPILEYOKE}
14
lclintf,LCLType,//gettickcount ,LMessages
18
{$IFNDEF FPC} E_memmap,RXSpin,capmenu,Math,ToolWin,Messages,
23
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,Menus,ComCtrls, ExtCtrls,
24
StdCtrls, GraphicsMathLibrary,ClipBrd,define_types, Spin,Buttons,
25
nifti_hdr,nifti_hdr_view,nifti_img, voismooth,
26
IniFiles,ReadInt,registry,stat,Distr,bet,mni,prefs,CropEdges,userdir,graphx,
27
GraphType,IntfGraphics, landmarks;
31
PINtBuffer = ^TIntBuffer;
32
TIntBuffer = Array[0..6] of single;
38
TImgForm = class(TForm)
39
AutoContrastBtn: TSpeedButton;
40
ColorBarBtn: TSpeedButton;
43
LutFromZeroBtn: TSpeedButton;
46
MaxWindowEdit: TFloatSpinEdit;
50
ApplyClusterThreshold1: TMenuItem;
52
ExportasRGBAnalyzeimage1: TMenuItem;
53
BatchROImean1: TMenuItem;
54
Batchprobmaps1: TMenuItem;
55
Batchclusterprobmaps1Batchclusterprobmaps1Click: TMenuItem;
60
Landmarks1: TMenuItem;
66
Resliceimage1: TMenuItem;
67
AdjustimagessoVOIintensityiszero1: TMenuItem;
68
Brainmask1: TMenuItem;
69
GenerateSPM5maskslesions1: TMenuItem;
70
RescaleMenu: TMenuItem;
71
BrainExtraction1: TMenuItem;
72
CropEdges1: TMenuItem;
74
MinWindowEdit: TFloatSpinEdit;
75
N4DTraces1: TMenuItem;
78
Preferences1: TMenuItem;
82
CloseImages: TMenuItem;
89
Crosshair1: TMenuItem;
91
Penautoclose1: TMenuItem;
92
CircleSquare1: TMenuItem;
98
ProgressBar1: TProgressBar;
103
Templates1: TMenuItem;
105
Controls1: TMenuItem;
108
Saveaspicture1: TMenuItem;
109
SaveDialog1: TSaveDialog;
110
ColorDialog1: TColorDialog;
111
RefreshImagesTimer: TTimer;
112
MagnifyMenuItem: TMenuItem;
113
OverlayMenu: TMenuItem;
114
OverlayOpen: TMenuItem;
115
LayerMenu: TMenuItem;
116
Noneopen1: TMenuItem;
117
OverlaySmoothMenu: TMenuItem;
118
CloseOverlayImg: TMenuItem;
119
BGTransPctMenu: TMenuItem;
120
OverlayTransPctMenu: TMenuItem;
122
BGtrans20: TMenuItem;
123
BGtrans40: TMenuItem;
124
BGtrans50: TMenuItem;
125
BGtrans60: TMenuItem;
126
BGtrans80: TMenuItem;
127
BGtrans100: TMenuItem;
128
N0opaque1: TMenuItem;
134
N100transparent1: TMenuItem;
135
Layerrange1: TMenuItem;
136
Noneopen2: TMenuItem;
138
BGAdditive: TMenuItem;
139
OverlayAdditive: TMenuItem;
141
ShowRender: TMenuItem;
147
TriplePanel: TScrollBox;
157
Applyintensityfiltertovolume1: TMenuItem;
158
Quicksmooth1: TMenuItem;
159
MaskimagewithVOI1: TMenuItem;
160
VOImaskDelete: TMenuItem;
161
VOImaskPreserve: TMenuItem;
162
SaveasNIfTI1: TMenuItem;
164
Overlaycomparisons1: TMenuItem;
165
IntersectionmutualtoVOIandoverlays1: TMenuItem;
166
UnionVOIoroverlays1: TMenuItem;
167
MaskVOIbutnotoverlays1: TMenuItem;
168
RescaleImagesTimer: TTimer;
169
SmoothVOI1: TMenuItem;
172
Chisquare1: TMenuItem;
176
Statistics1: TMenuItem;
177
ShowMultislice: TMenuItem;
178
DescriptiveMenuItem: TMenuItem;
182
HideROIBtn: TSpeedButton;
183
XBarBtn: TSpeedButton;
185
PenBtn: TSpeedButton;
186
ClosedPenBtn: TSpeedButton;
187
FillBtn: TSpeedButton;
188
EllipseBtn: TSpeedButton;
189
Fill3DBtn: TSpeedButton;
193
FlipLRmenu: TMenuItem;
195
Menu2DSmooth: TMenuItem;
202
Posterior1: TMenuItem;
203
Posterior2: TMenuItem;
205
procedure FormOpenFileMethod(const FileName : string);
206
procedure Landmarks1Click(Sender: TObject);
207
procedure SetIniMenus;
208
procedure Batchclusterprobmaps1Batchclusterprobmaps1ClickClick(Sender: TObject);
209
procedure Batchprobmaps1Click(Sender: TObject);
210
procedure BatchROImean1Click(Sender: TObject);
211
procedure BrainMask1Click(Sender: TObject);
212
procedure ControlPanelDragDrop(Sender, Source: TObject; X, Y: Integer);
213
procedure GenerateSPM5maskslesions1Click(Sender: TObject);
214
procedure LoadOverlay (lFilename: string);
215
procedure LoadOverlayIncludingRGB (lFilename: string);
216
procedure ApplyClusterThreshold1Click(Sender: TObject);
217
procedure BETmenuClick(Sender: TObject);
218
procedure C(Sender: TObject);
219
procedure CropMenuClick(Sender: TObject);
220
procedure ExportasRGBAnalyzeimage1Click(Sender: TObject);
221
procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
222
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
223
procedure FormKeyPress(Sender: TObject; var Key: char);
224
procedure Header1Click(Sender: TObject);
225
procedure HistoMenuClick(Sender: TObject);
226
procedure LayerDropChange(Sender: TObject);
227
procedure LUTdropChange(Sender: TObject);
228
procedure AdjustimagessoVOIintensityiszero1Click(Sender: TObject);
229
procedure MirrorNII1Click(Sender: TObject);
230
procedure MNIMenuClick(Sender: TObject);
231
procedure N4DTraces1Click(Sender: TObject);
232
procedure NIIVOIClick(Sender: TObject);
233
//procedure OptimizeViewClick(Sender: TObject);
234
procedure PGImageCorDblClick(Sender: TObject);
235
procedure Preferences1Click(Sender: TObject);
236
procedure RescaleMenuClick(Sender: TObject);
237
procedure Resliceimage1Click(Sender: TObject);
238
procedure SaveasNIfTI1Click(Sender: TObject);
239
procedure SaveDialog1Close(Sender: TObject);
240
procedure UpdateColorSchemes;
241
procedure UpdateTemplates;
243
procedure UpdateStatusLabel;
244
procedure Exit1Click(Sender: TObject);
245
procedure About1Click(Sender: TObject);
246
procedure DisplayHdrClick(Sender: TObject);
247
procedure Open1Click(Sender: TObject);
248
procedure ToolSelectClick(Sender: TObject);
249
procedure Copy1Click(Sender: TObject);
250
procedure FormCreate(Sender: TObject);
251
function OpenAndDisplayImg(var lFilename: string; lAdd2MRU: boolean): boolean;
252
procedure OpenTemplateMRU(Sender: TObject);
253
procedure XViewEditChange(Sender: TObject);
254
procedure ReadIniFile; //read init file values
255
procedure WriteIniFile;
257
procedure FormClose(Sender: TObject; var Action: TCloseAction);
259
procedure FormClose(Sender: TObject);
262
procedure MagnifyTimerTimer(Sender: TObject);
263
procedure MagnifyPanelResize(Sender: TObject);
264
procedure PGImageMouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
265
procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
266
MousePos: TPoint; var Handled: Boolean);
267
procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
268
MousePos: TPoint; var Handled: Boolean);
269
procedure PGImageMouseDown(Sender: TObject; Button: TMouseButton;
270
Shift: TShiftState; X, Y: Integer);
271
procedure PGImageMouseUp(Sender: TObject; Button: TMouseButton;
272
Shift: TShiftState; X, Y: Integer);
273
procedure LUTdropLoad(var lLayer: integer);
274
procedure LUTdropSelect(Sender: TObject);
275
procedure ZoomDropChange(Sender: TObject);
276
procedure ZoomDropSelect(Sender: TObject);
277
procedure ColorBarBtnMouseDown(Sender: TObject; Button: TMouseButton;
278
Shift: TShiftState; X, Y: Integer);
279
//procedure OptimizeViewMenuItemClick(Sender: TObject);
280
procedure Saveaspicture1Click(Sender: TObject);
281
procedure XBarBtnClick(Sender: TObject);
282
procedure XBarBtnMouseUp(Sender: TObject; Button: TMouseButton;
283
Shift: TShiftState; X, Y: Integer);
284
procedure XBarBtnMouseDown(Sender: TObject; Button: TMouseButton;
285
Shift: TShiftState; X, Y: Integer);
286
procedure AutoContrastBtnClick(Sender: TObject);
287
procedure RefreshImagesTimerTimer(Sender: TObject);
288
procedure MinContrastWindowEditChange(Sender: TObject);
289
procedure ImgPanelClick(Sender: TObject);
290
procedure MagnifyMenuItemClick(Sender: TObject);
291
procedure CloseImagesClick(Sender: TObject);
292
procedure UpdateLayerMenu;
293
procedure OverlayOpenCore (var lFilename: string; lOverlayNum: integer);
294
procedure OverlayOpenClick(Sender: TObject);
295
procedure CloseOverlayImgClick(Sender: TObject);
296
procedure BGtrans100Click(Sender: TObject);
297
procedure OverlayTransClick(Sender: TObject);
298
procedure LayerDropSelect(Sender: TObject);
299
procedure OverlaySmoothMenuClick(Sender: TObject);
300
procedure MaxContrastWindowEditChange(Sender: TObject);
301
procedure ShowRenderClick(Sender: TObject);
302
procedure PenBtnClick(Sender: TObject);
303
procedure OpenVOIClick(Sender: TObject);
304
procedure OpenVOICore(var lFilename : string);
305
procedure SaveVOIClick(Sender: TObject);
306
procedure VOIColorClick(Sender: TObject);
307
procedure CloseVOIClick(Sender: TObject);
308
procedure SetDimension8(lInPGHt,lInPGWid:integer; lBuff: ByteP; lUndoOnly: boolean);
309
procedure Undo1Click(Sender: TObject);
310
procedure Paste1Click(Sender: TObject);
311
procedure HideROIBtnMouseDown(Sender: TObject; Button: TMouseButton;
312
Shift: TShiftState; X, Y: Integer);
313
procedure HideROIBtnMouseUp(Sender: TObject; Button: TMouseButton;
314
Shift: TShiftState; X, Y: Integer);
316
procedure Applyintensityfiltertovolume1Click(Sender: TObject);
317
procedure Quicksmooth1Click(Sender: TObject);
318
procedure VOImaskClick(Sender: TObject);
319
procedure Sagittal1Click(Sender: TObject);
320
procedure ROIcomparisonClick(Sender: TObject);
321
procedure RescaleImagesTimerTimer(Sender: TObject);
322
procedure Fill3DBtnClick(Sender: TObject);
323
procedure SmoothVOI1Click(Sender: TObject);
324
procedure CreateOverlap(Sender: TObject);
325
procedure Chisquare1Click(Sender: TObject);
326
procedure ROIVOI1Click(Sender: TObject);
327
procedure LUTinvertBtnClick(Sender: TObject);
328
procedure LutFromZeroBtnClick(Sender: TObject);
329
procedure ShowMultisliceClick(Sender: TObject);
330
procedure DescriptiveMenuItemClick(Sender: TObject);
331
procedure FormResize(Sender: TObject);
332
procedure FormShow(Sender: TObject);
333
procedure FlipLRmenuClick(Sender: TObject);
334
procedure Menu2DSmoothClick(Sender: TObject);
335
procedure VALclick(Sender: TObject);
336
procedure VOI2NIIClick(Sender: TObject);
337
procedure TtoP1Click(Sender: TObject);
338
procedure DesignVALClick(Sender: TObject);
339
procedure Up1Click(Sender: TObject);
340
procedure SetShareMem (lXmm,lYmm,lZmm: single);
341
procedure CreateShareMem;
342
procedure CloseShareMem;
343
procedure YokeTimerTimer(Sender: TObject);
344
procedure FormDestroy(Sender: TObject);
345
procedure YokeMenuClick(Sender: TObject);
346
procedure DefaultControlPanel;
347
procedure ControlPanelDblClick(Sender: TObject);
348
procedure ResizeControlPanel (lRows: integer);
349
procedure SaveOrCopyImages(lCopy: boolean);
351
{ Private declarations }
354
procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
355
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
360
gShareIntBuf: PIntBuffer;
362
{$IFDEF FPC} function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;MousePos: TPoint): Boolean; override;{$ENDIF}
364
{ Public declarations }
366
//procedure WMSysCommand (var Msg: TWMSysCommand) ; message WM_SYSCOMMAND;
368
property OnMouseWheel;
373
knMRU = 5;//max items in most recently used list
375
kVOIOverlayNum = knMaxOverlay;
378
kVOIFilter = 'Volume of interest (*.voi)|*.voi|MRIcro ROI (*.roi)|*.roi|'+kImgFilter;
380
gYoke: boolean = false;
383
gMRIcroOverlay: array [0..knMaxOverlay] of TMRIcroHdr;
384
gColorSchemeDir,gTemplateDir: String;
385
gMRUstr: array [0..knMRU] of String; //most recently used files
386
gMouseDownX,gMouseDownY: integer;
387
gSelectOrigin: TPoint;
389
gOrigBGTransPct : integer= 50;
390
//gMaxCPUThreads : integer = 8;
391
gnCPUThreads : integer = 1;
392
gUndoImg,gDrawImg: Tfx8;
395
SingleArr = Array[1..kYokeItems] Of Single;
396
SingleArrPtr = ^SingleArr;
400
uses statclustertable,batch,imgutil, reslice_fsl,render,ROIfilt,autoroi, MultiSlice, Text, histoform,
401
about,clustering,ReadFloat;
406
procedure TImgForm.XBarColor;
408
ColorDialog1.Color := gBGImg.XBarClr;
409
if not ColorDialog1.Execute then exit;
410
gBGImg.XBarClr := ColorDialog1.Color;
411
RefreshImagesTimer.Enabled := true;
416
procedure DecViewEdit(var lEdit: TSpinEdit);
418
if lEdit.Value > 1 then
419
lEdit.value := lEdit.value -1
421
lEdit.Value := lEdit.MaxValue;
422
{$IFDEF FPC} ImgForm.XViewEditChange(nil); {$ENDIF}
425
procedure IncViewEdit(var lEdit: TSpinEdit);
427
if lEdit.Value < lEdit.MaxValue then
428
lEdit.value := lEdit.value +1
431
{$IFDEF FPC} ImgForm.XViewEditChange(nil); {$ENDIF}
435
function TImgForm.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
436
MousePos: TPoint): Boolean;
438
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
439
//ImgForm.Caption := inttostr(random(888));
440
//... actions after a possible OnMouseWheel[Down|Up]
441
//ImgForm.Caption := inttostr(WheelDelta)+' '+inttostr(random(888))+' '+inttostr(MousePos.X);
442
if WheelDelta < 0 then begin
443
Case SelectedImageNum of
444
3: DecViewEdit(YViewEdit);
445
2: DecViewEdit(XViewEdit);
446
else DecViewEdit(ZViewEdit);
449
Case SelectedImageNum of
450
3: IncViewEdit(YViewEdit);
451
2: IncViewEdit(XViewEdit);
452
else IncViewEdit(ZViewEdit);
459
procedure TImgForm.CloseShareMem;
467
//shared memory release START
468
gShareIntBuf^[0] := gShareIntBuf^[0] -1;
469
lInstances := gShareIntBuf^[0];
470
if Assigned (FSharePtr) then
472
//if FOwnShm then zssss
473
if lInstances = 0 then begin
474
//last running instance - close shared memory
475
if shmctl (FShmId, IPC_RMID, nil) = -1 then
476
raise Exception.Create (strerror (errno));
478
//shared memory release END
482
procedure TImgForm.SetShareMem (lXmm,lYmm,lZmm: single);
485
if not gYoke then exit;
486
EMemMap.EnterCriticalSection;
488
SingleArrPtr(EMemMap.MemMap)^[1]:=(lXmm);
489
SingleArrPtr(EMemMap.MemMap)^[2]:=(lYmm);
490
SingleArrPtr(EMemMap.MemMap)^[3]:=(lZmm);
492
EMemMap.LeaveCriticalSection;
497
gShareIntBuf^[1] := (lXmm);
498
gShareIntBuf^[2] := (lYmm);
499
gShareIntBuf^[3] := (lZmm);
504
procedure TImgForm.CreateShareMem;
508
//shared memory acquire START
511
Key := ftok (PChar(GetModuleName(0)),Key {1}); //use UserID so each user gets separate pool of shared memory
512
// try to open existing shared memory
513
FShmId := shmget (Key, 0, 0);
516
// doesn't exist, create it
517
FShmId := shmget (Key, kShareSegmentSize,
518
IPC_CREAT or IPC_EXCL or AccessMode);
520
raise Exception.Create (strerror (errno));
525
// attach to shared memory
526
FSharePtr := shmat (FShmId, nil, 0);
527
if Integer(FSharePtr) = -1 then
530
raise Exception.Create (strerror (errno));
532
gShareIntBuf := FSharePtr;
534
gShareIntBuf^[0] := 0;
535
gShareIntBuf^[0] := gShareIntBuf^[0]+1;
536
SetShareMem (gXProj,gYProj,gZProj);
541
//CompileYoke not set
544
{$ELSE}//not FPC - must be Delphi
549
EMemMap:=TEMemMap.Create(Self);
550
EMemMap.CreateMutex('MRICROMUTEX2');
551
If NOT EMemMap.MapExisting('MRICROMAP2',SizeOf(SingleArr)) then begin
553
For I:=1 To kYokeItems do
556
If NOT EMemMap.CreateMemMap('MRICROMAP2',SizeOf(SingleArr),IArr^) then
557
EMemMap.RaiseMappingException;
566
procedure TImgForm.YokeTimerTimer(Sender: TObject);
568
lXmm,lYmm,lZmm: single;
571
caption := inttostr(888);
572
if not gYoke then begin
573
YokeTimer.Enabled := false;
576
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems=0 then
580
lXmm:=gShareIntBuf^[1];
581
lYmm:=gShareIntBuf^[2];
582
lZmm:=gShareIntBuf^[3];
584
YokeTimer.Enabled := false;
589
EMemMap.EnterCriticalSection;
591
lXmm:=SingleArrPtr(EMemMap.MemMap)^[1];
592
lYmm:=SingleArrPtr(EMemMap.MemMap)^[2];
593
lZmm:=SingleArrPtr(EMemMap.MemMap)^[3];
595
EMemMap.LeaveCriticalSection;
598
MMToImgCoord(lX,lY,lZ,lXmm,lYmm,lZmm);
599
if lX <> XViewEdit.value then XViewEdit.value := lX;
600
if lY <> YViewEdit.value then YViewEdit.value := lY;
601
if lZ <> ZViewEdit.value then ZViewEdit.value := lZ;
602
YokeTimer.Enabled := false;
606
procedure TImgForm.WMSysCommand;
608
if (Msg.CmdType = SC_MINIMIZE) then
611
DefaultHandler(Msg) ;
612
if (Msg.CmdType = SC_MAXIMIZE) then RefreshImagesTimer.enabled := true;
616
function SelectedImagePanel: TScrollBox;
618
case SelectedImageNum of
619
3: result := ImgForm.TriplePanel;
620
2: result := ImgForm.TriplePanel;
621
else result := ImgForm.TriplePanel;
625
function DrawToolSelected: boolean;
627
if ( ImgForm.PenBtn.Down) or ( ImgForm.ClosedPenBtn.Down) or (ImgForm.FillBtn.Down) or (ImgForm.EllipseBtn.Down) then
633
procedure TImgForm.WriteIniFile;
640
// if not (gBGIMg.SaveDefaultIni) then
641
// showmessage(lIni+ inttostr(DiskFreeEx(lIni)));
642
if (DiskFreeEx(lIni) < 1) or (not gBGIMg.SaveDefaultIni) then
645
//lIniFile := TIniFile.Create(changefileext(paramstr(0),'.ini'));
646
lIniFile := TIniFile.Create(lIni);//DefaultsDir('')+ParseFileName(extractfilename(paramstr(0)))+'.ini');
648
lIniFile.WriteString('MRU', 'file0', gMRIcroOverlay[kBGOverlayNum].HdrFilename);
649
for lInc := 1 to knMRU do
650
lIniFile.WriteString('MRU', 'file'+inttostr(lInc), gMRUstr[lINc]);
652
lIniFile.WriteString('STR', 'FSLDIR',gBGImg.FSLDIR);
653
lIniFile.WriteString('STR', 'FSLOUTPUTTYPE',gBGImg.FSLOUTPUTTYPE);
655
lIniFile.WriteString('BOOL', 'Reslice',Bool2Char(gBGImg.ResliceOnLoad));
656
lIniFile.WriteString('BOOL', 'ResliceOrtho',Bool2Char(gBGImg.OrthoReslice));
657
lIniFile.WriteString('BOOL', 'ShowDraw',Bool2Char(ToolPanel.Visible));
658
lIniFile.WriteString('BOOL', 'ThinPen',Bool2Char(gBGImg.ThinPen));
659
lIniFile.WriteString('BOOL', 'Smooth2D',Bool2Char(Menu2DSmooth.checked));
660
lIniFile.WriteString('BOOL', 'XBar',Bool2Char(XBarBtn.Down));
661
lIniFile.WriteString('BOOL', 'OverlaySmooth',Bool2Char(OverlaySmoothMenu.Checked));
662
lIniFile.WriteString('BOOL', 'LRmirror',Bool2Char(gBGImg.Mirror));
663
lIniFile.WriteString('BOOL', 'Yoke',Bool2Char(gYoke));
664
lIniFile.WriteString('BOOL', 'SingleRow',Bool2Char(gBGImg.SingleRow));
665
lIniFile.WriteString('BOOL', 'FlipAx',Bool2Char(gBGImg.FlipAx));
666
lIniFile.WriteString('BOOL', 'FlipSag',Bool2Char(gBGImg.FlipSag));
667
YokeTimer.Enabled := gYoke;
669
//lIniFile.WriteString('INT', 'ResizeBeforeRescale',IntToStr(gBGImg.ResizeBeforeRescale));
670
lIniFile.WriteString('INT', 'FontSize',IntToStr(gBGImg.FontSize));
671
lIniFile.WriteString('INT', 'MaxDim',IntToStr(gBGImg.MaxDim));
672
lIniFile.WriteString('INT', 'LicenseID',IntToStr(gBGImg.LicenseID));
673
lIniFile.WriteString('INT', 'Zoom',IntToStr(ZoomDrop.ItemIndex));
674
lIniFile.WriteString('INT', 'LUT',IntToStr(gMRIcroOverlay[kBGOverlayNum].LUTindex));
675
lIniFile.WriteString('INT', 'XBarGap',IntToStr(gBGImg.XBarGap));
676
lIniFile.WriteString('INT', 'XBarThick',IntToStr(gBGImg.XBarThick));
677
lIniFile.WriteString('INT', 'XBarClr',IntToStr(gBGIMg.XBarClr));
678
lIniFile.WriteString('INT', 'VOIClr',IntToStr(gBGIMg.VOIClr));
679
if (gBGImg.BGTransPct < 0) or (gBGImg.BGTransPct > 90) then
680
gBGImg.BGTransPct := 20; //additive or transparent values can confuse users
681
if (gBGImg.OverlayTransPct < 0) or (gBGImg.OverlayTransPct > 90) then
682
gBGImg.OverlayTransPct := 20; //additive or transparent values can confuse users
683
lIniFile.WriteString('INT', 'BGTransPct',IntToStr(gBGImg.BGTransPct));
684
lIniFile.WriteString('INT', 'OverlayTransPct',IntToStr(gBGImg.OverlayTransPct));
685
lIniFile.WriteString('INT','MaxThreads',IntToStr(gnCPUThreads));
686
lIniFile.WriteString('INT', 'LesionSmooth',IntToStr(gBGImg.LesionSmooth));
688
// lIniFile.WriteString('INT', 'MaxThreads',IntToStr(gMaxCPUThreads));
690
lIniFile.WriteString('INT', 'SigDigits',IntToStr(gBGImg.SigDig));
691
lIniFile.WriteString('INT', 'ImageSeparation',IntToStr(gBGImg.ImageSeparation));
694
lIniFile.WriteString('INT', 'SPMDefaultsStatsFmriT',IntToStr(gBGImg.SPMDefaultsStatsFmriT));
695
lIniFile.WriteString('INT', 'SPMDefaultsStatsFmriT0',IntToStr(gBGImg.SPMDefaultsStatsFmriT0));
700
function registerfiletype(inft,inkey,desc,icon:string): boolean;
701
var myreg : treginifile;
709
while ct > 0 do begin
713
if (ft = '') or (Application.ExeName = '') then exit; //not a valid file-ext or ass. app
715
myreg := treginifile.create('');
717
myreg.rootkey := hkey_classes_root; // where all file-types are described
718
if key = '' then key := copy(ft,2,maxint)+'_auto_file'; // if no key-name is given, create one
719
myreg.writestring(ft,'',key); // set a pointer to the description-key
720
myreg.writestring(key,'',desc); // write the description
721
myreg.writestring(key+'\DefaultIcon','',icon); // write the def-icon if given
722
myreg.writestring(key+'\shell\open\command','',Application.ExeName+' %1'); //association
725
showmessage('Only administrators can change file associations. You are currently logged in as a restricted user.');
730
procedure TImgForm.SetIniMenus;
732
XBarBtn.Down := gBGImg.XBarVisible;
733
YokeMenu.Checked := gYoke;
734
Menu2DSmooth.checked := gBGImg.StretchQuality = sqHigh;
735
Menu2DSmoothClick(nil);//set quality
738
procedure TImgForm.ReadIniFile;
740
lInc,lFilenum: integer;
744
//lFilename := changefileext(paramstr(0),'.ini');
746
lFilename := ininame;//DefaultsDir('')+ParseFileName(extractfilename(paramstr(0)))+'.ini';
747
if not FileexistsEx(lFilename) then begin
748
DrawMenu.Visible := ToolPanel.visible;
752
lIniFile := TIniFile.Create(lFilename);
753
gMRUstr[0] := lIniFile.ReadString('MRU', 'file0', '');//file0 - last file viewed
755
for lInc := 1 to knMRU do begin
756
lFilename := lIniFile.ReadString('MRU', 'file'+inttostr(lInc), '');
757
if (length(lFilename) > 0) and (fileexistsex(lFilename)) then begin
759
gMRUstr[lFileNum] := lFilename;
762
gBGImg.FSLOUTPUTTYPE := lIniFile.ReadString('STR', 'FSLOUTPUTTYPE', '');
763
gBGImg.FSLDIR := lIniFile.ReadString('STR', 'FSLDIR', '');
764
gBGImg.ResliceOnLoad := IniBool(lIniFile,'Reslice',gBGImg.ResliceOnLoad);
765
gBGImg.OrthoReslice := IniBool(lIniFile,'ResliceOrtho',gBGImg.OrthoReslice);
766
gBGImg.ThinPen := IniBool(lIniFile, 'ThinPen',True);
767
ToolPanel.Visible := IniBool(lIniFile, 'ShowDraw',False);
768
DrawMenu.Visible := ToolPanel.visible;
769
if IniBool(lIniFile,'Smooth2D',Menu2DSmooth.checked) then
770
gBGImg.StretchQuality := sqHigh
772
gBGImg.StretchQuality := sqLow;
773
//Menu2DSmooth.checked := IniBool(lIniFile,'Smooth2D',Menu2DSmooth.checked);
774
Menu2DSmoothClick(nil);//set quality
775
gBGImg.XBarVisible := IniBool(lIniFile,'XBar',XBarBtn.Down);
776
gBGImg.OverlaySmooth := IniBool(lIniFile,'OverlaySmooth',gBGImg.OverlaySmooth);
777
OverlaySmoothMenu.Checked := gBGImg.OverlaySmooth;
778
gBGImg.Mirror := IniBool(lIniFile,'LRmirror',gBGImg.Mirror);
779
FlipLRmenu.Checked := gBGImg.Mirror;
780
gYoke := IniBool(lIniFile,'Yoke',gYoke);
781
gBGImg.SingleRow := IniBool(lIniFile,'SingleRow',gBGImg.SingleRow);
782
gBGImg.FlipAx := IniBool(lIniFile,'FlipAx',gBGImg.FlipAx);
783
gBGImg.FlipSag := IniBool(lIniFile,'FlipSag',gBGImg.FlipSag);
784
gBGImg.MaxDim := IniInt(lIniFile,'MaxDim',gBGImg.MaxDim);
785
gBGImg.LicenseID := IniInt(lIniFile,'LicenseID',gBGImg.LicenseID);
787
ZoomDrop.SetItemIndex(IniInt(lIniFile,'Zoom',ZoomDrop.ItemIndex));
788
LUTDrop.SetItemIndex(IniInt(lIniFile,'LUT',LUTDrop.ItemIndex));
790
ZoomDrop.ItemIndex := (IniInt(lIniFile,'Zoom',ZoomDrop.ItemIndex));
791
LUTDrop.ItemIndex:= (IniInt(lIniFile,'LUT',LUTDrop.ItemIndex));
793
gBGImg.XBarGap := IniInt(lIniFile,'XBarGap',gBGImg.XBarGap);
794
gBGImg.XBarThick := IniInt(lIniFile,'XBarThick',gBGImg.XBarThick);
795
gBGImg.XBarClr := IniInt(lIniFile,'XBarClr',gBGImg.XBarClr);
796
gBGImg.VOIClr := IniInt(lIniFile,'VOIClr',gBGImg.VOIClr);
797
gBGImg.BGTransPct := IniInt(lIniFile,'BGTransPct',gBGImg.BGTransPct);
798
gBGImg.OverlayTransPct := IniInt(lIniFile,'OverlayTransPct',gBGImg.OverlayTransPct);
799
gnCPUThreads := IniInt(lIniFile,'MaxThreads',gnCPUThreads);
800
gBGImg.SigDig := IniInt(lIniFile,'SigDigits',gBGImg.SigDig);
801
gBGImg.ImageSeparation := IniInt(lIniFile,'ImageSeparation',gBGImg.ImageSeparation);
802
gBGImg.FontSize := IniInt(lIniFile,'FontSize',gBGImg.FontSize);
804
gBGImg.SPMDefaultsStatsFmriT := IniInt(lIniFile,'SPMDefaultsStatsFmriT',gBGImg.SPMDefaultsStatsFmriT);
805
gBGImg.SPMDefaultsStatsFmriT0 := IniInt(lIniFile,'SPMDefaultsStatsFmriT0',gBGImg.SPMDefaultsStatsFmriT0);
806
gBGImg.LesionSmooth := IniInt(lIniFile,'LesionSmooth',gBGImg.LesionSmooth);
808
SetSubmenuWithTag(BGTransPctMenu, gBGImg.BGTransPct);
809
SetSubmenuWithTag(OverlayTransPctMenu, gBGImg.OverlayTransPct);
814
procedure TImgForm.UpdateColorSchemes;
816
lSearchRec: TSearchRec;
819
LUTdrop.Items.Add('Grayscale');
820
LUTdrop.Items.Add('Red');
821
LUTdrop.Items.Add('Blue');
822
LUTdrop.Items.Add('Green');
823
LUTdrop.Items.Add('Violet [r+b]');
824
LUTdrop.Items.Add('Yellow [r+g]');
825
LUTdrop.Items.Add('Cyan [g+b]');
826
if FindFirst(gColorSchemeDir+pathdelim+'*.lut', faAnyFile, lSearchRec) = 0 then
828
LUTdrop.Items.Add(ParseFileName(ExtractFileName(lSearchRec.Name)));
829
until (FindNext(lSearchRec) <> 0);
830
FindClose(lSearchRec);
831
//LUTDrop.DropDownCount := 66;//LUTDrop.Items.Count;
832
end;//UpdateColorSchemes
835
procedure TImgForm.BETmenuClick(Sender: TObject);
840
procedure TImgForm.ApplyClusterThreshold1Click(Sender: TObject);
842
lNumberofFiles,lC,lClusterSz: integer;
846
CloseImagesClick(nil);
847
if not OpenDialogExecute(kImgFilter,'Select NIfTI format images to convert',true) then exit;
848
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
849
lClusterSz := ReadIntForm.GetInt('Minimum cluster size [in voxels]: ', 1,32,9999);
850
lThresh := ReadFloatForm.GetFloat('Include voxels with an intensity above: ', 0,2,9999);
851
ProgressBar1.Min := 0;
852
ProgressBar1.Max :=lNumberofFiles;
853
ProgressBar1.Position := 0;
854
for lC:= 1 to lNumberofFiles do begin
855
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
856
ImgForm.OpenAndDisplayImg(lFilename,True);
857
//lFilename := changefileextX(lFilename,'I'+inttostr(round(lThresh))+'C'+inttostr(lClusterSz)+'.nii.gz');
858
lFilename := changefileprefix(lFilename,'I'+inttostr(round(lThresh))+'C'+inttostr(lClusterSz));
859
if ClusterFilterScrnImg (gMRIcroOverlay[kBGOverlayNum],lClusterSz,lThresh ) then
860
if ImgVaries(gMRIcroOverlay[kBGOverlayNum]) then
861
SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kBGOverlayNum].ImgBuffer,gMRIcroOverlay[kBGOverlayNum].ImgBufferItems,gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr)
863
showmessage('No clusters survive filter '+ HdrForm.OpenHdrDlg.Files[lC-1]);
864
ProgressBar1.Position := lC;
866
if fileexistsEX(lFilename) then
867
ImgForm.OpenAndDisplayImg(lFilename,True);
868
ProgressBar1.Position := 0;
871
procedure TImgForm.C(Sender: TObject);
876
procedure TImgForm.CropMenuClick(Sender: TObject);
881
procedure TImgForm.ExportasRGBAnalyzeimage1Click(Sender: TObject);
885
lFlip := gBGImg.Mirror;
886
gBGImg.Mirror := true;
888
gBGImg.Mirror := lFlip;
891
procedure TImgForm.FormDropFiles(Sender: TObject;
892
const FileNames: array of String);
896
if length(FileNames) < 1 then
898
lFilename := Filenames[0];
899
OpenAndDisplayImg(lFilename,true);
902
procedure TImgForm.FormKeyDown(Sender: TObject; var Key: Word;
905
//ImgForm.caption := inttostr(Key);
906
if (XViewEdit.focused) or (YViewEdit.focused) or (ZViewEdit.focused) or (MinWindowEdit.focused) or (MaxWindowEdit.focused) then
909
36: DecViewEdit(YViewEdit);
910
35: IncViewEdit(YViewEdit);
911
37: DecViewEdit(XViewEdit);
912
38: IncViewEdit(ZViewEdit);
913
39: IncViewEdit(XViewEdit);
914
40: DecViewEdit(ZViewEdit);
917
(* if WheelDelta < 0 then begin
918
Case SelectedImageNum of
919
3: DecViewEdit(YViewEdit);
920
2: DecViewEdit(XViewEdit);
921
else DecViewEdit(ZViewEdit);
924
Case SelectedImageNum of
925
3: IncViewEdit(YViewEdit);
926
2: IncViewEdit(XViewEdit);
927
else IncViewEdit(ZViewEdit);
932
procedure TImgForm.FormKeyPress(Sender: TObject; var Key: char);
934
//imgform.caption := 'zzz';
939
procedure TImgForm.Header1Click(Sender: TObject);
941
DisplayHdrClick(nil);
945
function ActiveLayer:integer;
947
result := ImgForm.LayerDrop.ItemIndex;
955
procedure DrawBMP2( lx, ly: integer; var lBuff: RGBQuadp; var lImage: TImage);
956
//uses GraphType, IntfGraphics
958
IntfImage: TLazIntfImage;
959
ScanLineImage: TLazIntfImage;
960
ImgFormatDescription: TRawImageDescription;
963
lBitmap:=TBitmap.Create;
964
ScanLineImage:=TLazIntfImage.Create(0,0);
965
ImgFormatDescription.Init_BPP32_B8G8R8_BIO_TTB(lx,ly);
966
ScanLineImage.DataDescription:=ImgFormatDescription;
967
// call the pf24bit specific drawing function
968
Move(lBuff^[1],PByte(ScanLineImage.GetDataLineStart(0))[1],lx*ly*sizeof(TRGBquad) );
969
lBitmap.Width:=ScanLineImage.Width;
970
lBitmap.Height:=ScanLineImage.Height;
971
IntfImage:=lBitmap.CreateIntfImage;
972
// convert the content from the very specific to the current format
973
IntfImage.CopyPixels(ScanLineImage);
974
lBitmap.LoadFromIntfImage(IntfImage);
977
lImage.Picture.Bitmap := lBitmap;
984
y,x,lx, ly, lpos: integer;
989
getmem(lBuff,(lx*ly)*sizeof( TRGBquad));
991
for y := 1 to ly do begin
992
for x := 1 to lx do begin
994
lBuff^[lpos].rgbblue := (y mod 255);
995
lBuff^[lpos].rgbgreen :=(y mod 255);
996
lBuff^[lpos].rgbred := (x mod 255) ;
997
lBuff^[lpos].rgbreserved := 0;
1000
l2Time := GetTickCount;
1001
for y := 1 to 100 do
1002
DrawBMP2( lx, ly, lBuff,HistogramForm.HistoImage{lImage});
1003
l2Time := GetTickCount - l2Time;
1004
lTime := GetTickCount;
1005
for y := 1 to 100 do
1006
DrawBMP( lx, ly, lBuff,HistogramForm.HistoImage{lImage});
1007
lTime := GetTickCount - lTime;
1008
HistogramForm.Caption := inttostr(lTime)+' '+inttostr(l2Time);
1013
procedure TImgForm.HistoMenuClick(Sender: TObject);
1020
lLayer := ActiveLayer;
1021
DrawHistogram(gMRIcroOverlay[lLayer],HistogramForm.HistoImage{lImage});
1022
HistogramForm.Caption := 'Histogram: '+extractfilename(gMRIcroOverlay[lLayer].HdrFileName);
1025
//HistogramForm.BringToFront;
1030
procedure TImgForm.MNIMenuClick(Sender: TObject);
1033
//MNIForm.BringToFront;
1037
procedure TImgForm.N4DTraces1Click(Sender: TObject);
1040
//Graph4DForm.BringToFront;
1043
procedure TImgForm.NIIVOIClick(Sender: TObject);
1045
lNumberofFiles,lC: integer;
1048
CloseImagesClick(nil);
1049
if not OpenDialogExecute(kImgFilter {10/2007},'Select NIfTI format images to convert',true) then exit;
1050
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
1051
ProgressBar1.Min := 0;
1052
ProgressBar1.Max :=lNumberofFiles;
1053
ProgressBar1.Position := 0;
1054
for lC:= 1 to lNumberofFiles do begin
1055
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
1056
ImgForm.OpenAndDisplayImg(lFilename,True);
1057
lFilename := changefileextx(lFilename,'.voi'); ////Xversion 10/2007 - removes .nii.gz not just gz
1058
//SaveAsVOIorNIFTIcore (lFilename, lByteP, lVoxels, 1, gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
1059
SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kBGOverlayNum].ScrnBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems, 1,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
1061
ProgressBar1.Position := lC;
1063
ProgressBar1.Position := 0;
1068
procedure TImgForm.PGImageCorDblClick(Sender: TObject);
1070
if Graph4DForm.visible then
1071
Graph4DForm.RefreshBtn.click;
1074
procedure TImgForm.Preferences1Click(Sender: TObject);
1079
function RescaleImg( lRescaleIntercept,lRescaleSlope: double): boolean;
1081
//lRow,lNumberofFiles,lX,lY,lZ: integer;
1082
//lFilename: string;
1084
lImgSamples,lInc,lBPP: integer;
1085
l32Buf,lo32Buf : SingleP;
1088
//note ignores input slope/intercept scaling values
1090
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
1091
showmessage('Please load a background image for rescaling.');
1094
if ((gBGImg.ScrnDim[1] * gBGImg.ScrnDim[2] * gBGImg.ScrnDim[3]) <> gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems) then begin
1095
showmessage('Unable to rescale.');
1098
lBPP := gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP;//check if BitsPerPixel is supported
1099
if (lBPP <> 4) and (lBPP <> 2) and (lBPP <> 1) then begin
1100
showmessage('RescaleImg Error: Unsupported BPP: '+inttostr(lBPP));
1103
lImgSamples := gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems;
1104
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],lHdr,0{min}, 0{max},0{p1},0{p2},0{p3},kNIFTI_INTENT_NONE,floattostr(lRescaleSlope) );
1105
GetMem(lHdr.ImgBufferUnaligned ,(lImgSamples*4)+16);
1106
//svn lHdr.ImgBuffer := ByteP($fffffff0 and (integer(lHdr.ImgBufferUnaligned)+15));
1107
lHdr.ImgBuffer := align(lHdr.ImgBufferUnaligned, 16);
1108
lo32Buf := SingleP( lHdr.ImgBuffer );
1109
if lBPP = 4 then begin
1110
l32Buf := SingleP( gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
1111
for lInc := 1 to lImgSamples do
1112
lo32Buf^[lInc] := (l32Buf^[lInc]+lRescaleIntercept) * lRescaleSlope;
1113
end else if lBPP = 2 then begin //lBPP=4 else
1114
l16Buf := SmallIntP( gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
1115
for lInc := 1 to lImgSamples do
1116
lo32Buf^[lInc] := (l16Buf^[lInc]+lRescaleIntercept) * lRescaleSlope;
1117
end else if lBPP = 1 then begin //lBPP=2 else
1118
for lInc := 1 to lImgSamples do
1119
lo32Buf^[lInc] := (gMRIcroOverlay[kBGOverlayNum].ImgBuffer^[lInc]+lRescaleIntercept) * lRescaleSlope;
1121
SaveAsVOIorNIFTI(bytep(lo32Buf),lImgSamples,4,1,false,lHdr.NiftiHdr,'rscl'+extractfilename(gMRIcroOverlay[kBGOverlayNum].HdrFilename));
1122
//SaveAsVOIorNIFTI(gMRIcroOverlay[lLayer].ImgBuffer,gMRIcroOverlay[lLayer].ImgBufferItems,gMRIcroOverlay[lLayer].ImgBufferBPP,1,false,gMRIcroOverlay[kBGOverlayNum].NiftiHdr,gMRIcroOverlay[lLayer].HdrFilename);
1123
FreeMem(lHdr.ImgBufferUnaligned);
1124
//lFilename := 'c:\striped2.hdr';
1125
//SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kBGOverlayNum].ScrnBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems, 1,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
1130
procedure TImgForm.RescaleMenuClick(Sender: TObject);
1131
var ldTE,lScale,lTE1,lTE2: double;
1134
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
1135
showmessage('Please load a background image for rescaling.');
1138
if gBGImg.Resliced then begin
1139
if not HdrForm.OpenAndDisplayHdr(gMRIcroOverlay[kBGOverlayNum].HdrFileName,gMRIcroOverlay[kBGOverlayNum]) then exit;
1140
if not OpenImg(gBGImg,gMRIcroOverlay[0],true,false,false,false,false) then exit;
1142
if (gMRIcroOverlay[kBGOverlayNum].GlMinUnscaledS < 0) or (gMRIcroOverlay[kBGOverlayNum].GlMaxUnscaledS > 4096) then begin
1143
showmessage('Error: you need to load a Siemens format Phase map with raw values in the range 0..4096');
1146
lTE1 := ReadFloatForm.GetFloat('Please enter the first TE (ms) used for phasemap. ', 0,5.19,9999);
1147
lTE2 := ReadFloatForm.GetFloat('Please enter the second TE (ms) used for phasemap. ', 0,7.65,9999);
1149
(*lStr := floattostr(5.19); //use floattostr for local decimal separator
1150
if not InputQuery('TEs used to create phasemap','Please enter the first TE in ms', lStr) then
1153
lTE1 := strtofloat(lStr);
1155
showmessage('Unable to convert the string '+lStr+' to a number');
1158
lStr := floattostr(7.65);
1159
if not InputQuery('TEs used to create phasemap','Please enter the second TE in ms', lStr) then
1162
lTE2 := strtofloat(lStr);
1164
showmessage('Unable to convert the string '+lStr+' to a number');
1167
if lTE1 = lTE2 then begin
1168
showmessage('In order to compute Rad/S the two TEs must be different.');
1173
//the fieldmap is simply a phase
1174
//difference image and is not scaled to any particular units. In Siemens
1175
//phase images the data goes from 0 to 4095 with 0 being -pi radians, 2048
1176
//is 0 radians, and 4095 is just short of +pi radians.
1177
//So, to get units of radians/s you would need to know the difference in
1178
//echo times (dTE) in units of s (not ms). You would then take
1179
//(x-2048)(2pi/4096)/dTE
1180
//Note ignore original intercept and scale values
1181
//ldTE := abs(5.19 - 7.65)/1000; // div 1000 to scale ms to sec
1182
ldTE := abs(lTE1 - lTE2)/1000; // div 1000 to scale ms to sec
1183
lScale := (2*pi/4096)/ldTE;
1184
//showmessage(floattostr(lScale));
1185
rescaleImg(-2048,lScale);
1188
procedure TImgForm.Resliceimage1Click(Sender: TObject);
1193
procedure TImgForm.SaveasNIfTI1Click(Sender: TObject);
1197
lLayer := ActiveLayer;
1198
if gMRIcroOverlay[lLayer].ImgBufferItems=0 then begin
1199
Showmessage('You must load an image [File/Open] before you can save the image.');
1202
if (not IsNifTiMagic(gMRIcroOverlay[lLayer].niftiHdr)) then
1203
Showmessage('Warning: image will be saved with NIfTI spatial transform - ensure this image matches the orientation of the template images.');
1204
SaveAsVOIorNIFTI(gMRIcroOverlay[lLayer].ImgBuffer,gMRIcroOverlay[lLayer].ImgBufferItems,gMRIcroOverlay[lLayer].ImgBufferBPP,1,false,gMRIcroOverlay[kBGOverlayNum].NiftiHdr,gMRIcroOverlay[lLayer].HdrFilename);
1208
procedure ApplySaveDlgFilter (lSaveDlg: TSaveDialog);
1210
lLen,lPos,lPipes,lPipesReq: integer;
1213
lPipesReq := (lSaveDlg.FilterIndex * 2)-1;
1214
if lPipesReq < 1 then exit;
1215
lLen := length(lSaveDlg.Filter);
1218
//Median(DeltaF, 1, N_inc) / LN2
1219
while (lPos < lLen) and (lPipes < lPipesReq) do begin
1220
if lSaveDlg.Filter[lPos] = '|' then
1224
if (lPos >= lLen) or (lPipes < lPipesReq) then
1227
while (lPos <= lLen) and (lSaveDlg.Filter[lPos] <> '|') do begin
1228
if lSaveDlg.Filter[lPos] <> '*' then
1229
lExt := lExt + lSaveDlg.Filter[lPos];
1233
lSaveDlg.Filename := ChangeFileExt(lSaveDlg.Filename,lExt);
1236
procedure TImgForm.SaveDialog1Close(Sender: TObject);
1238
ApplySaveDlgFilter(SaveDialog1);
1241
procedure Add2MRU (var lNewFilename: string); //add new file to most-recent list
1246
//first, increase position of all old MRUs
1247
lN := 0; //Number of MRU files
1248
for lPos := 1 to (knMRU) do begin//first, eliminate duplicates
1249
lStr := gMRUstr[lPos];
1250
if (lStr <> '') and (lStr <> lNewFileName) then begin
1252
gMRUstr[lN] := lStr;
1253
end; //keep in MRU list
1255
//next, increment positions
1258
for lPos := lN downto 1 do
1259
gMRUstr[lPos+1] := gMRUstr[lPos];
1260
if (lN+2) < (knMRU) then //+1 as we have added a file
1261
for lPos := (lN+2) to knMRU do
1262
gMRUstr[lPos] := '';
1263
gMRUstr[1] := lNewFilename;
1265
ImgForm.SaveDialog1.FileName := lNewFilename;
1268
procedure TImgForm.UpdateMRU;//most-recently-used menu
1273
While Recent1.Count > 0 do Recent1.Items[0].Free;
1275
for lPos := 1 to knMRU do begin//for each MRU
1276
if gMRUstr[lPos] <> '' then begin
1278
NewItem := TMenuItem.Create(Self);
1279
NewItem.Caption :=ExtractFileName(gMRUstr[lPos]);//(ParseFileName(ExtractFileName(lFName)));
1282
NewItem.onclick := @OpenTemplateMRU; //Lazarus
1284
NewItem.onclick := OpenTemplateMRU;
1286
NewItem.ShortCut := ShortCut(Word('1')+ord(lN-1), [ssCtrl]);
1287
Recent1.Add(NewItem);
1292
procedure TImgForm.UpdateTemplates;
1297
lSearchRec: TSearchRec;
1299
While Templates1.Count > 0 do Templates1.Items[0].Free;
1301
if FindFirst(gTemplateDir+pathdelim+'*.*', faAnyFile, lSearchRec) = 0 then begin
1303
lFName := lSearchRec.Name;
1304
if IsNIfTIHdrExt (lFName) then begin
1306
NewItem := TMenuItem.Create(Self);
1307
NewItem.Caption :=ExtractFileName(lFName);//(ParseFileName(ExtractFileName(lFName)));
1310
NewItem.onclick := @OpenTemplateMRU; //Lazarus
1312
NewItem.onclick := OpenTemplateMRU;
1314
if (lN+knMRU) <= 9 then
1315
NewItem.ShortCut := ShortCut(Word('1')+knMRU+ord(lN-1), [ssCtrl]);
1316
Templates1.Add(NewItem);
1318
until (FindNext(lSearchRec) <> 0)
1320
FindClose(lSearchRec);
1321
end;//UpdateTemplates
1323
procedure TImgForm.OpenTemplateMRU(Sender: TObject);//open template or MRU
1324
//Templates have tag set to 0, Most-Recently-Used items have tag set to position in gMRUstr
1328
if sender = nil then begin
1329
//autolaunch with last image, or last template image in list
1331
lFilename := gMRUstr[0];
1332
if (lFilename = '') or (not FileExistsEX(lFilename)) then begin
1333
if Templates1.Count > 0 then
1334
Templates1.Items[Templates1.Count-1].click;
1337
OpenAndDisplayImg(lFilename,true); //open but do not add templates to MRU
1338
end else if (Sender as TMenuItem).tag = 0 then begin
1339
lFilename := gTemplateDir+pathdelim+(Sender as TMenuItem).caption ;//+ '.hdr';
1340
OpenAndDisplayImg(lFilename,false); //open but do not add templates to MRU
1341
end else if (Sender as TMenuItem).tag <= knMRU then begin
1342
lFilename := gMRUstr[(Sender as TMenuItem).tag];
1343
OpenAndDisplayImg(lFilename,true);
1345
Showmessage('OpenTemplateMRU error.');
1348
function TImgForm.OpenAndDisplayImg(var lFilename: string; lAdd2MRU: boolean): boolean;
1353
if not HdrForm.OpenAndDisplayHdr(lFilename,gMRIcroOverlay[kBGOverlayNum]) then exit;
1356
//if (ssShift in KeyDataToShiftState(vk_Shift)) then begin
1357
// if not OpenImg(gBGImg,gMRIcroOverlay[0],true,false,false,not gBGImg.ResliceOnLoad,false) then exit
1359
if not OpenImg(gBGImg,gMRIcroOverlay[0],true,false,false,gBGImg.ResliceOnLoad,false) then exit;
1361
XViewEdit.MaxValue := gBGImg.ScrnDim[1];//gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[1];
1362
YViewEdit.MaxValue := gBGImg.ScrnDim[2];//gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[2];
1363
ZViewEdit.MaxValue :=gBGImg.ScrnDim[3];// gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[3];
1364
XViewEdit.Value := round(gBGImg.ScrnOri[1]);//gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[1] div 2;
1365
YViewEdit.Value := round(gBGImg.ScrnOri[2]);//gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[2]div 2;
1366
lVal := round(gBGImg.ScrnOri[3]);
1369
ZViewEdit.Value := lVal;//gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.dim[3] div 2;
1370
ImgForm.Caption := extractfilename(paramstr(0))+' - '+lFilename;
1371
StatusLabel.caption := 'opened: '+lFilename;
1373
//LayerDrop.ItemIndex := 0;
1374
//LayerDropSelect(nil);
1375
if lAdd2MRU then Add2MRU(lFilename);
1376
if gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.datatype = kDT_RGB then begin //RGB
1377
//we have loaded the first [red] plane - now load green and blue...
1378
OverlayOpenCore(lFilename,1);
1379
OverlayOpenCore(lFilename,2);
1380
//must use additive blending
1381
//gBGImg.BGTransPct := -1;
1382
//gBGImg.OverlayTransPct := -1;
1383
OverlayAdditive.Click;
1387
XViewEditChange(nil);
1389
//showmessage(lFilename+' 666 '+ChangeFileext(lFilename,'.anat'));
1390
AnatForm.OpenAnat( ChangeFileextx(lFilename,'.anat'));
1391
end; //OpenAndDisplayImg
1394
procedure TImgForm.WMDropFiles(var Msg: TWMDropFiles); //implement drag and drop
1396
CFileName: array[0..MAX_PATH] of Char;
1400
if DragQueryFile(Msg.Drop, 0, CFileName, MAX_PATH) > 0 then
1402
lFilename := CFilename;
1403
OpenAndDisplayImg(lFilename,true);
1407
DragFinish(Msg.Drop);
1412
procedure TImgForm.Exit1Click(Sender: TObject);
1417
function XToStr(lR: extended; lDec: integer): string;
1419
result := FloatToStrF(lR, ffFixed,7,lDec);
1424
procedure TImgForm.DisplayHdrClick(Sender: TObject);
1428
lLayer := ActiveLayer;
1429
HdrForm.SaveHdrDlg.Filename := gMRIcroOverlay[lLayer].HdrFilename;
1430
HdrForm.WriteHdrForm (gMRIcroOverlay[lLayer]);
1432
//HdrForm.BringToFront;
1435
procedure TImgForm.Open1Click(Sender: TObject);
1439
CloseImagesClick(nil);
1440
if not OpenDialogExecute(kImgFilter,'Select background image',false) then exit;
1441
lFilename := HdrForm.OpenHdrDlg.Filename;
1442
OpenAndDisplayImg(lFilename,True);
1445
procedure TImgForm.ToolSelectClick(Sender: TObject);
1447
if (not ToolPanel.Visible) and ((Sender as TMenuItem).Tag > 0) then exit; //tools disabled
1448
case (Sender as TMenuItem).Tag of
1450
XBarBtn.Down := not XBarBtn.Down;
1451
{$IFDEF Darwin} XBarbtnClick(nil); exit;{$ENDIF}
1453
2: PenBtn.Down := true;
1454
3: ClosedPenBtn.Down := true;
1455
4: FillBtn.Down := true;
1456
5: EllipseBtn.Down := true;
1458
PenBtn.Down := false;
1459
ClosedPenBtn.Down := false;
1460
FillBtn.Down := false;
1461
EllipseBtn.Down := false;
1464
RefreshImagesTimer.Enabled := true;
1467
function SelectedImage: TImage;
1469
case SelectedImageNum of
1470
kSagView0: result := ImgForm.PGImageSag;
1471
kCoroView0: result := ImgForm.PGImageCor;
1473
result := ImgForm.PGImageAx;
1477
procedure TImgForm.SetDimension8(lInPGHt,lInPGWid:integer; lBuff: ByteP; lUndoOnly: boolean);
1479
DefineBuffFX8(gDrawImg, lInPGWid,lInPGHt,lBuff);
1480
DefineBuffFX8(gUndoImg, lInPGWid,lInPGHt,lBuff);
1484
procedure WriteAxialVOI (lUndoOnly: boolean);
1485
var lX,lY,lSliceOffset,lSliceSz,lSlicePos: integer;
1488
lX := gBGImg.ScrnDim[1];
1489
lY := gBGImg.ScrnDim[2];
1491
if lSliceSz < 1 then exit;
1492
lSliceOffset := (ImgForm.ZViewEdit.Value-1)*lX*lY;
1493
gBGImg.VOIUndoSlice := ImgForm.ZViewEdit.Value;
1494
getmem(lInBuff,lSliceSz);
1495
for lSlicePos := 1 to lSliceSz do
1496
lInBuff^[lSlicePos] := gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lSliceOffset+lSlicePos];
1497
ImgForm.SetDimension8(lY,lX, lInBuff,lUndoOnly);
1501
procedure WriteCorVOI (lUndoOnly: boolean);
1502
var lX,lY,lZ,lYOffset,lZOffset,lXYSliceSz,lPixel,lZPos,lXPos: integer;
1505
lX := gBGImg.ScrnDim[1];
1506
lY := gBGImg.ScrnDim[2];
1507
lZ := gBGImg.ScrnDim[3];
1508
lYOffset := (lX) * (round(ImgForm.YViewEdit.Value)-1);
1509
gBGImg.VOIUndoSlice := ImgForm.YViewEdit.Value;
1510
lXYSliceSz := (lX*lY);
1511
getmem(lInBuff,lZ*lX);
1513
for lZPos := 1 to lZ do begin
1514
lZOffset := (lZPos-1) * lXYSliceSz;
1515
for lXPos := 1 to lX do begin
1518
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lZOffset+lYOffset+lXPos];
1521
ImgForm.SetDimension8(lZ,lX, lInBuff,lUndoOnly);
1525
procedure WriteSagVOI (lUndoOnly: boolean);
1526
var lX,lY,lZ,lXOffset,lYOffset,lZOffset,lXYSliceSz,lPixel,lZPos,lYPos: integer;
1529
lX := gBGImg.ScrnDim[1];
1530
lY := gBGImg.ScrnDim[2];
1531
lZ := gBGImg.ScrnDim[3];
1532
lXYSliceSz := lX*lY;
1533
lXOffset := round(ImgForm.XViewEdit.Value);
1534
//dec(lXOffset);//999+8
1535
gBGImg.VOIUndoSlice := ImgForm.XViewEdit.Value;
1536
getmem(lInBuff,lZ*lY);
1538
for lZPos := 1 to lZ do begin
1539
lZOffset := (lZPos-1) * lXYSliceSz;
1541
for lYPos := 1 to lY do begin
1543
lInBuff^[lPixel] := gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lZOffset+lYOffset+lXOffset];
1544
lYOffset := lYOffset+ lX;
1547
ImgForm.SetDimension8(lZ,lY, lInBuff, lUndoOnly);
1551
procedure WriteUndoVOI(lPanel: integer;lUndoOnly: boolean);
1555
3: WriteCorVOI(lUndoOnly);
1556
2: WriteSagVOI(lUndoOnly);
1557
else WriteAxialVOI(lUndoOnly);
1559
gBGImg.VOIchanged := true;
1560
if gBGImg.VOIUndoOrient = 4 then
1561
FreeUndoVol; //release 3D undo buffer when creating 2D buffer
1562
gBGImg.VOIUndoOrient := lPanel;
1565
procedure TImgForm.FormOpenFileMethod(const FileName : string);
1569
lFilename := Filename;
1570
OpenAndDisplayImg(lFilename,true);
1573
procedure TImgForm.Landmarks1Click(Sender: TObject);
1580
procedure TImgForm.FormCreate(Sender: TObject);
1585
Application.ShowButtonGlyphs := sbgNever;
1588
InitOpenDocHandler;//allows files to be associated...
1589
{$IFNDEF LCLgtk} //only for Carbon compile
1590
Open1.ShortCut := ShortCut(Word('O'), [ssMeta]);
1591
SaveasNIfTI1.ShortCut := ShortCut(Word('S'), [ssMeta,ssAlt]);
1592
Saveaspicture1.ShortCut := ShortCut(Word('S'), [ssMeta]);
1593
Copy1.ShortCut := ShortCut(Word('C'), [ssMeta]);
1594
Paste1.ShortCut := ShortCut(Word('V'), [ssMeta]);
1595
Undo1.ShortCut := ShortCut(Word('Z'), [ssMeta]);
1596
OverlayOpen.ShortCut := ShortCut(Word('A'), [ssMeta]);
1597
Applyintensityfiltertovolume1.ShortCut := ShortCut(Word('F'), [ssMeta]);
1598
HistoMenu.ShortCut := ShortCut(Word('H'), [ssMeta]);
1599
ShowRender.ShortCut := ShortCut(Word('R'), [ssMeta]);
1600
ShowMultislice.ShortCut := ShortCut(Word('M'), [ssMeta]);
1601
N4DTraces1.ShortCut := ShortCut(Word('D'), [ssMeta]);
1602
Header1.ShortCut := ShortCut(Word('I'), [ssMeta]);
1609
{$IFNDEF LCLgtk} //only for Carbon compile
1610
Exit1.visible := false;//with OSX users quit from application menu
1613
CreateFX8(gUndoImg);
1614
CreateFX8(gDrawImg);
1615
TriplePanel.OnMouseWheelDown:= @FormMouseWheelDown;
1616
TriplePanel.OnMouseWheelUp:= @FormMouseWheelUp;
1617
TriplePanel.OnMouseWheelDown:= @FormMouseWheelDown;
1618
TriplePanel.OnMouseWheelUp:= @FormMouseWheelUp;
1619
TriplePanel.OnMouseWheelDown:= @FormMouseWheelDown;
1620
TriplePanel.OnMouseWheelUp:= @FormMouseWheelUp;
1622
gnCPUThreads := GetLogicalCpuCount;
1624
ImgForm.Caption := extractfilename(paramstr(0));
1625
ImgForm.DoubleBuffered := true;
1626
TriplePanel.DoubleBuffered := true;
1627
TriplePanel.DoubleBuffered := true;
1628
TriplePanel.DoubleBuffered := true;
1629
for lInc := 0 to knMaxOverlay do begin
1630
FreeImgMemory(gMRIcroOverlay[lInc]);
1631
NIFTIhdr_ClearHdr(gMRIcroOverlay[lInc]);
1632
gMRIcroOverlay[lInc].ScrnBufferItems := 0;
1633
gMRIcroOverlay[lInc].ImgBufferItems := 0;
1634
if lInc < knAutoLUT then
1635
gMRIcroOverlay[lInc].LUTindex := lInc
1637
gMRIcroOverlay[lInc].LUTindex := lInc;//B&W
1638
LoadMonochromeLUT(gMRIcroOverlay[lInc].LUTindex,gBGImg,gMRIcroOverlay[lInc]);
1641
LoadMonochromeLUT(lInc,gBGImg,gMRIcroOverlay[kVOIOverlayNum]);
1642
SetBGImgDefaults(gBGImg);
1643
CloseImagesClick(nil);
1644
gColorSchemeDir := extractfilepath(paramstr(0))+'lut';
1645
{$IFNDEF Unix} DragAcceptFiles(Handle, True); //engage drag and drop
1649
LUTdrop.SetItemIndex(0);
1650
Zoomdrop.SetItemIndex(0);
1651
LayerDrop.SetItemIndex(0);
1653
LUTdrop.ItemIndex:=(0);
1654
Zoomdrop.ItemIndex:=(0);
1655
LayerDrop.ItemIndex:=(0);
1656
MagnifyMenuItem.visible := false;
1657
{$IFNDEF COMPILEYOKE}
1658
YokeMenu.visible := false;
1661
gTemplateDir := extractfilepath(paramstr(0))+'templates';
1664
for lInc := 1 to knMRU do
1665
gMRUstr[lInc] := '';
1667
(*if (ssShift in KeyDataToShiftState(vk_Shift)) then begin
1668
case MessageDlg('Shift key down during launch: do you want to reset the default preferences?', mtConfirmation,
1669
[mbYes, mbNo], 0) of { produce the message dialog box }
1675
if ResetDefaults then
1676
DrawMenu.Visible := ToolPanel.visible
1682
DefaultControlPanel;
1683
OverlaySmoothMenuClick(nil);
1684
LUTDrop.OnSelect(nil);
1685
ZoomDrop.OnSelect(nil);
1687
if YokeMenu.checked then YokeTimer.enabled := true;
1688
//gBGIMg.SaveDefaultIni := true;
1691
function ImgIntensity(var lHdr: TMRIcroHdr; lX,lY,lZ: integer): single;
1698
lPos := lX + ((lY-1)*gBGImg.ScrnDim[1])+((lZ-1)*gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2]);
1699
if (lPos > lHdr.ImgBufferItems) or (lPos < 1) then exit;
1700
if (lHdr.ImgBufferBPP = 4) then begin
1701
l32Buf := SingleP(lHdr.ImgBuffer );
1702
result := l32Buf^[lPos];
1703
end else if (lHdr.ImgBufferBPP = 2) then begin
1704
l16Buf := SmallIntP(lHdr.ImgBuffer );
1705
result := l16Buf^[lPos];
1706
end else if lHdr.ImgBufferBPP = 1 then
1707
result := lHdr.ImgBuffer^[lPos]
1709
showmessage('Unknown Image Buffer Bytes Per Pixel: '+inttostr(lHdr.ImgBufferBPP)+' '+lHdr.HdrFileName);
1712
result := Raw2ScaledIntensity (lHdr,result);
1715
function ImgIntensityString(var lHdr: TMRIcroHdr; lX,lY,lZ: integer): string;
1719
lPos := lX + ((lY-1)*gBGImg.ScrnDim[1])+((lZ-1)*gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2]);
1721
if lHdr.ImgBufferItems < 1 then exit;
1722
if not lHdr.UsesCustomPalette then begin
1723
result := realtostr(ImgIntensity(lHdr,lX,lY,lZ),gBGImg.SigDig);
1724
(* if lHdr.ScrnBuffer[lPos] = 0 then begin
1725
if lHdr.Slope8Bit < 0 then
1726
result := '>'+result
1728
result := '<'+result
1729
end else if lHdr.ScrnBuffer[lPos] = 255 then begin
1730
if lHdr.Slope8Bit < 0 then
1731
result := '<'+result
1733
result := '>'+result
1735
result := '~'+result;*)
1738
if (lPos > lHdr.ImgBufferItems) or (lPos < 1) then exit;
1739
result := gBGImg.LabelStr20[lHdr.ImgBuffer^[lPos]];
1742
procedure TImgForm.UpdateStatusLabel;
1744
lX,lY,lZ,lOverlay,lLen: integer;
1745
lXmm,lYmm,lZmm: single;
1749
lX := XviewEdit.value;
1750
lY := YviewEdit.value;
1751
lZ := ZviewEdit.value;
1752
ImgCoordToMM(lX,lY,lZ,lXmm,lYmm,lZmm);
1755
//StatusLabel.Caption := realtostr(lXmm,0)+'x'+realtostr(lYmm,0)+'x'+realtostr(lZmm,0);
1756
//lIntenStr := realtostr(lXmm,0)+'x'+realtostr(lYmm,0)+'x'+realtostr(lZmm,0)+'= '+lIntenStr;;
1758
//StatusLabel.Caption := lIntenStr;
1759
//StatusLabel.Caption := realtostr(lXmm,0)+'x'+realtostr(lYmm,0)+'x'+realtostr(lZmm,0)+'= '+lIntenStr;
1761
for lOverlay := kBGOverlayNum to (kVOIOverlayNum-1) do
1762
if gMRIcroOverlay[lOverlay].ImgBufferItems > 0 then
1763
lIntenStr := lIntenStr + ImgIntensityString(gMRIcroOverlay[lOverlay],lX,lY,lZ)+', ';
1764
lLen := length (lIntenstr);
1766
lIntenStr[lLen-1] := ' ';
1767
//StatusLabel.Caption := realtostr(lXmm,0)+'x'+realtostr(lYmm,0)+'x'+realtostr(lZmm,0)+'= '+lIntenStr;
1768
Caption := realtostr(lXmm,0)+'x'+realtostr(lYmm,0)+'x'+realtostr(lZmm,0)+'= '+lIntenStr;
1770
// SetShareMem (lXmm,lYmm,lZmm);
1773
procedure TImgForm.XViewEditChange(Sender: TObject);
1775
gBGImg.XViewCenter := XviewEdit.value;
1776
gBGImg.YViewCenter := YviewEdit.value;
1777
gBGImg.ZViewCenter := ZviewEdit.value;
1778
RefreshImagesTimer.Enabled := true;
1779
//UpdateStatusLabel; //caused crash! - only with refreshimagestimes
1783
procedure TImgForm.FormClose(Sender: TObject; var Action: TCloseAction);
1785
procedure TImgForm.FormClose(Sender: TObject);
1790
CloseImagesClick(nil);
1795
procedure TImgForm.MagnifyTimerTimer(Sender: TObject);
1798
// MagnifyTimer.Enabled := false;
1802
Srect,Drect,PosForme,ImgForme:TRect;
1803
lZoomSlider,iWidth,iHeight,DmX,DmY:Integer;
1810
MagnifyTimer.Enabled := false;
1812
If not IsIconic(Application.Handle) then begin
1813
hDesktop:= GetDesktopWindow;
1814
GetCursorPos(Kursor);
1815
ImgForme := Rect(ImgForm.Left+ImgForm.TriplePanel.Left,ImgForm.Top+ImgForm.TriplePanel.Top,ImgForm.Left+ImgForm.Width,ImgForm.Top+ImgForm.Height);
1816
PosForme:=Rect(MagnifyPanel.Left,MagnifyPanel.Top,MagnifyPanel.Left+MagnifyPanel.Width,MagnifyPanel.Top+MagnifyPanel.Height);
1818
iWidth:=MagnifyImage.Width;
1819
iHeight:=MagnifyImage.Height;
1820
if iHeight < 6 then exit;
1821
Drect:=Rect(0,0,iWidth,iHeight);
1822
iTmpX:=iWidth / (lZoomSlider*4);//(Slider.Position * 4);
1823
iTmpY:=iHeight / (lZoomSlider*4);//(Slider.Position * 4);
1824
Srect:=Rect(Kursor.x,Kursor.y,Kursor.x,Kursor.y);
1825
InflateRect(Srect,Round(iTmpX),Round(iTmpY));
1826
If Srect.Left<0 then OffsetRect(Srect,-Srect.Left,0);
1827
If Srect.Top<0 then OffsetRect(Srect,0,-Srect.Top);
1828
If Srect.Right>Screen.Width then OffsetRect(Srect,-(Srect.Right-Screen.Width),0);
1829
If Srect.Bottom>Screen.Height then OffsetRect(Srect,0,-(Srect.Bottom-Screen.Height));
1832
C.Handle:=GetDC(GetDesktopWindow);
1833
SetStretchBltMode(C.Handle,COLORONCOLOR);
1834
//SetStretchBltMode(C.Handle, STRETCH_DELETESCANS);
1835
//SetStretchBltMode(C.Handle,{BILINEAR}TransparencyEdit.value);
1836
MagnifyImage.Canvas.CopyRect(Drect,C,Srect);
1838
ReleaseDC(hDesktop, C.Handle);
1841
If True then begin // show crosshair
1842
MagnifyImage.Canvas.Pen.Color := gBGIMg.XBarClr;
1843
with MagnifyImage.Canvas do begin
1844
DmX:=lZoomSlider * 2 * (Kursor.X-Srect.Left);
1845
DmY:=lZoomSlider * 2 * (Kursor.Y-Srect.Top);
1847
LineTo(iWidth,DmY); // -
1849
LineTo(DmX,iHeight); // |
1850
end; // with MagnifyImage.Canvas
1851
end; // show crosshair
1852
Application.ProcessMessages;
1853
end // Cursor not inside form
1855
end; //magnify image
1858
procedure TImgForm.MagnifyPanelResize(Sender: TObject);
1860
(* MagnifyImage.Picture:=nil;
1861
if MagnifyPanel.Width < MagnifyPanel.Constraints.MinWidth then
1862
MagnifyPanel.Width := MagnifyPanel.Constraints.MinWidth;
1864
end; //Proc MagnifyPanelResize
1866
procedure SelectPanel (lPanelNumber: integer);
1868
gSelectedImageNum := lPanelNumber;
1869
end; //Proc SelectPanel
1871
procedure ShowFocusRect(lInRect: TRect);
1874
lImage := SelectedImage;
1875
lImage.Canvas.DrawFocusRect(lInRect);
1876
end; //proc ShowFocusRect
1878
procedure XYscrn2Img (lImage: TIMage;lPanel,lXinRaw,lYinRaw: integer; var lXout,lYOut,lZOut: integer);
1880
lYin,lXin,lZoom : integer;
1883
//amx - must match XYscrn2Img and DrawXBar - e.g. +0.5 for middle of zoomed slice
1884
lZoom := ImageZoomPct(lImage);
1885
if lZoom = 0 then lZoom := 100;
1886
if lZoom > 100 then lOffset := 0.5 else
1888
lXIn := lXinRaw + 1; //index from 0
1889
lYin := lImage.Height-lYinRaw;
1892
if gBGImg.FlipSag then
1893
lXin := lImage.Width-lXinRaw;
1894
lXOut := ImgForm.XViewEdit.value;
1895
lYOut := round((lXin*100) / lZoom +lOffset);
1896
lZOut := round((lYin*100) / lZoom +lOffset);
1899
lXOut := round((lXin*100) / lZoom +lOffset);
1900
lYOut := ImgForm.YViewEdit.value;
1901
lZOut := round((lYin*100) / lZoom +lOffset);
1905
if gBGImg.FlipAx then
1907
lXOut := round((lXin*100) / lZoom +lOffset);
1908
lYOut := round((lYin*100) / lZoom +lOffset);
1909
lZOut := ImgForm.ZViewEdit.value;
1912
//ImgForm.Caption := inttostr(lXOut)+' '+inttostr(lYOut)+' '+Inttostr(lZOut);
1913
end; //proc XYscrn2Img
1915
procedure AdjustContrastRectangle (lImage: TImage);
1917
lXpos,lYPos,lXOut,lYOut,lZOut,lPanel,lLayer: integer;
1918
lMinInten,lMaxInten,lVal: single;
1920
lPanel := SelectedImageNum;
1921
lLayer := ActiveLayer;
1922
XYscrn2Img (lImage,lPanel,gSelectRect.Left,gSelectRect.Top, lXout,lYOut,lZOut);
1923
lMinInten := ImgIntensity(gMRIcroOverlay[lLayer],lXout,lYOut,lZOut);
1924
lMaxInten := lMinInten;
1925
for lYpos := gSelectRect.Top to gSelectRect.Bottom do begin
1926
for lXpos := gSelectRect.Left to gSelectRect.Right do begin
1927
XYscrn2Img (lImage,lPanel,lXpos,lYPos, lXout,lYOut,lZOut);
1928
lVal:= ImgIntensity(gMRIcroOverlay[lLayer],lXout,lYOut,lZOut);
1929
if lVal < lMinInten then lMinInten := lVal;
1930
if lVal > lMaxInten then lMaxInten := lVal;
1931
end; //for PGX each column
1932
end; //for PGY2 - each row
1933
ImgForm.StatusLabel.caption := '^^Intensity range '+(RealToStr(lMinInten,4))+'..'+({x} RealToStr(lMaxInten,4));
1934
if lMinInten = lMaxInten then exit; //no range
1935
ImgForm.MinWindowEdit.value := lMinInten;
1936
ImgForm.MaxWindowEdit.value := lMaxInten;
1937
{$IFDEF FPC} ImgForm.MinContrastWindowEditChange(nil) {$ENDIF}
1940
procedure sortLTRB(var lXoutLow,lYOutLow,lXoutHi,lYOutHi: integer); //left<right, top<bottom
1941
var lXin1,lYin1,lXin2,lYin2: integer;
1947
if lXIn1 < lXin2 then begin
1954
if lYIn1 < lYin2 then begin
1963
procedure DrawEllipse (lImage: TImage;lRect: TRect; lShift: TShiftState; lPanel: integer);
1965
ScaleBMP2Draw(gBGImg.VOIInvZoom, lRect.Left,lRect.Top,lPanel,Limage);
1966
ScaleBMP2Draw(gBGImg.VOIInvZoom, lRect.Right,lRect.Bottom,lPanel,lImage);
1967
if (ssCtrl in lShift) then
1968
FillRectFX8(gDrawImg,lRect.Left,lRect.Top,lRect.Right,lRect.Bottom,kVOI8bit)
1970
FillEllipseFX8(gDrawImg,lRect.Left,lRect.Top,lRect.Right,lRect.Bottom,kVOI8bit);
1974
procedure TImgForm.PGImageMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
1975
var lZoom,lPanel,lX, lY,lXout,lYOut,lZOut,lBasePenThick,lX2, lY2: integer;
1978
//ImgForm.GetFocus := true;
1979
gSelectOrigin.X := -1;
1982
lImage := Sender as TImage;
1983
if lImage.Name = PGImageCor.Name {'PGImageCor'} then lPanel := kCoroView0
1984
else if lImage.Name = PGImageSag.Name {'PGImageSag'} then lPanel := kSagView0
1985
else lPanel := kAxView0;
1986
//lImage.Canvas.Pen.Width := 1;
1987
// lImage.Canvas.Pen.Color :=gBGImg.VOIClr;
1988
SelectPanel(lPanel);
1989
gBGImg.VOIInvZoom := ComputeInvZoomShl10(lPanel,lImage);
1991
if DrawToolSelected then begin //paint tool
1992
WriteUndoVOI(lPanel,false);
1993
if (ssShift in Shift) then begin //erase
1994
lImage.Canvas.Brush.Color:=clBlack;
1995
lImage.Canvas.Pen.Color := clBlack;
1997
lImage.Canvas.Brush.Color:=gBGImg.VOIClr;
1998
lImage.Canvas.Pen.Color := gBGImg.VOIClr;
2000
if gBGImg.ThinPen then
2002
else begin //adjust pen thickness for zoom level
2003
if gBGImg.ZoomPct < 100 then begin
2004
lZoom := ComputeZoomPct(lPanel,lImage);
2008
lBasePenThick := round((ComputeZoomPct(lPanel,lImage)+50) / 100);
2009
end else if gBGImg.ZoomPct > 100 then
2010
lBasePenThick := gBGImg.ZoomPct div 100
2013
end; //if not thinpen
2014
if (ssCtrl in Shift) then begin
2015
lImage.Canvas.Pen.Width := lBasePenThick*3;
2016
gDrawImg.PenThick := 3;
2018
lImage.Canvas.Pen.Width := lBasePenThick;
2019
gDrawImg.PenThick := 1;
2021
end; //paint tool selected
2022
//lImage.Canvas.Pen.Width := 1;//abba
2023
if (FillBtn.Down) and (ssCtrl in Shift) then begin //3D fill
2024
XYscrn2Img (lImage,lPanel,lX,lY, lXout,lYOut,lZOut);
2025
XViewEdit.value := lXOut;
2026
YViewEdit.value := lYOut;
2027
ZViewEdit.value := lZOut;
2028
if (ssShift in Shift) then //erase
2029
ROICluster(gBGImg.ScrnDim[1], gBGImg.ScrnDim[2], gBGImg.ScrnDim[3],XViewEdit.value,YViewEdit.value,ZViewEdit.value,true)
2031
ROICluster(gBGImg.ScrnDim[1], gBGImg.ScrnDim[2], gBGImg.ScrnDim[3],XViewEdit.value,YViewEdit.value,ZViewEdit.value,false);
2034
if (not PenBtn.Down) and (not ClosedPenBtn.Down) and (not FillBtn.Down) then begin
2035
if (EllipseBtn.Down) or (ssRight in Shift) then begin
2036
lImage.Canvas.Brush.Color:=gBGImg.VOIClr;
2037
//lImage.Canvas.Pen.Color :=gBGImg.VOIClr;
2038
ScaleScrn2BMP(lX,lY, lImage);
2039
gSelectRect.Left := lX;
2040
gSelectRect.Top := lY;
2041
gSelectRect.Right := lX;
2042
gSelectRect.Bottom := lY;
2043
ShowFocusRect(gSelectRect);
2044
gSelectOrigin.X := gSelectRect.Left;
2045
gSelectOrigin.Y := gSelectRect.Top;
2048
//next no paint tools selected - show position where click occurred
2049
XYscrn2Img (lImage,lPanel,lX,lY, lXout,lYOut,lZOut);
2050
XViewEdit.value := lXOut;
2051
YViewEdit.value := lYOut;
2052
ZViewEdit.value := lZOut;
2053
//showmessage(floattostr(lXOut)+'x'+floattostr(lYOut)+'x'+floattostr(lZOut));
2054
//ImgCoordToMM(lXOut,lYOut,lZOut,lXmm,lYmm,lZmm);
2055
//showmessage(floattostr(lXmm)+'x'+floattostr(lYmm)+'x'+floattostr(lZmm));
2057
//showmessage(floattostr(gBGImg.ScrnOri[1])+'x'+floattostr(gBGImg.ScrnOri[2])+'x'+floattostr(gBGImg.ScrnOri[3]));
2058
//MMToImgCoord(lXOut,lYOut,lZOut,lXmm,lYmm,lZmm);
2059
//showmessage(floattostr(lXOut)+'x'+floattostr(lYOut)+'x'+floattostr(lZOut));
2061
//SetShareMem (lXmm,lYmm,lZmm);
2064
XViewEditChange(nil);
2068
ScaleScrn2BMP(lX,lY, lImage);
2069
lImage.Canvas.MoveTo(lX,lY);
2072
ScaleBMP2Draw(gBGImg.VOIInvZoom, lX2,lY2,lPanel,lImage);
2073
if (FillBtn.Down) or(ssRight in Shift) then begin
2075
if (ssShift in Shift) then
2076
FloodFillFX8 (gDrawImg, lX2,lY2,kVOI8bit,0,true)
2077
//FloodFillX(DrawImg2,lX2-1,lY2-1,gBGImg.VOIClr, fsSurface)
2079
FloodFillFX8 (gDrawImg, lX2,lY2,kVOI8bit,kVOI8bit,false);
2080
//FloodFillX(DrawImg2,lX2-1,lY2-1,gBGImg.VOIClr, fsBorder);
2084
//ImgForm.caption := inttostr(lX2);
2085
MoveToFX8(gDrawImg,lX2,lY2);
2086
if lImage.Canvas.Pen.Color = clBlack then //ensure single pixel is drawn if user clicks without dragging
2087
LineToFX8(gDrawImg,lX2,lY2,0)
2089
LineToFX8(gDrawImg,lX2,lY2,kVOI8bit);
2093
end; //PGImageMouseDown
2096
gDragX,gDragY,gDragZ : integer;
2097
//gDragRefresh : boolean = false; //only redraw one snapshot at a time
2099
procedure TImgForm.PGImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
2100
var lX, lY,lPanel,lXOut,lYOut,lZOut: integer;
2103
lImage := Sender as TImage;
2105
ScaleScrn2BMP(lX,lY,lImage);
2106
//if MagnifyImage.Height > 10 then
2107
// MagnifyTimer.Enabled := true;//MagnifyBtn.Down;
2108
//StatusLabel.Caption := inttostr(lX)+','+inttostr(lY);
2109
if {(ssShift in Shift) and} (gSelectOrigin.X > 0) then begin
2110
ShowFocusRect(gSelectRect);
2111
gSelectRect.Left := gSelectOrigin.X;
2112
gSelectRect.Top := gSelectOrigin.Y;
2113
gSelectRect.Right := lX;
2114
gSelectRect.Bottom := lY;
2115
sortLTRB(gSelectRect.Left,gSelectRect.Top,gSelectRect.Right,gSelectRect.Bottom);
2116
ShowFocusRect(gSelectRect);
2119
if (not DrawToolSelected) and ((ssLeft in Shift)) then begin
2120
//RefreshImagesTimer.Enabled := false;
2121
//gDragRefresh := true;
2122
if lImage.Name = PGImageCor.Name then lPanel := kCoroView0
2123
else if lImage.Name = PGImageSag.Name then lPanel := kSagView0
2124
else lPanel := kAxView0;
2125
XYscrn2Img (lImage,lPanel,lX,lY, lXout,lYOut,lZOut);
2126
if (lXout = gDragX) and (lYout = gDragY) and (lZOut = gDragZ) then
2128
XViewEdit.value := lXOut;
2129
YViewEdit.value := lYOut;
2130
ZViewEdit.value := lZOut;
2132
{$IFDEF FPC}XViewEditChange(nil);{$ENDIF} //can generate crash!
2133
//gDragRefresh := false;
2137
if (not (ssLeft in Shift)) or (gMouseDownX < 0) then exit;
2138
if PenBtn.Down or ClosedPenBtn.Down then begin
2139
lImage.Canvas.LineTo(lX,lY);
2141
ScaleBMP2Draw(gBGImg.VOIInvZoom, lX,lY,lPanel,lImage);
2142
//DrawImg2.Canvas.LineTo(lX,lY);
2143
if lImage.Canvas.Pen.Color = clBlack then
2144
LineToFX8(gDrawImg,lX,lY,0)//zzzxx
2146
LineToFX8(gDrawImg,lX,lY,kVOI8bit);//zzzxx
2148
end; //PGImageMouseMove
2150
(*procedure Scrn2VOI (var lImage: TImage; lXvoi,lYvoi: integer; var lVOIBuffer: ByteP);
2153
kSh = 10; //bits to shift
2155
lInc,lXpos,lYPos,lVOISliceSz: integer;
2158
srcBmp := lImage.Picture.Bitmap;
2159
lVOISliceSz := lXvoi*lYvoi;
2160
GetMem (lVOIBuffer , lVOISliceSz);
2162
for lYpos:=(lYvoi-1) downto 0 do begin
2163
for lXpos:=0 to lXvoi-1 do begin
2165
if srcBmp.Canvas.Pixels[lXpos,lYPos] = clBlack then
2166
lVOIBuffer^[lInc] := 0
2168
lVOIBuffer^[lInc] := 100;
2174
procedure ReadCorVOI (var lImage: TFX8; lSlice: integer);
2175
var lX,lY,lZ,lYOffset,lZOffset,lXYSliceSz,lPixel,lZPos,lXPos: integer;
2177
lX := gBGImg.ScrnDim[1];
2178
lY := gBGImg.ScrnDim[2];
2179
lZ := gBGImg.ScrnDim[3];
2180
lYOffset := (lX) * (round(lSlice)-1);
2181
lXYSliceSz := (lX*lY);
2182
//Scrn2VOI (lImage,lX,lZ, lInBuff);
2184
for lZPos := 1 to lZ do begin
2185
lZOffset := (lZPos-1) * lXYSliceSz;
2186
for lXPos := 1 to lX do begin
2188
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lZOffset+lYOffset+lXPos] :=lImage.Img^[lPixel];
2193
procedure ReadSagVOI (var lImage: TFX8;lSlice: integer);
2194
var lX,lY,lZ,lXOffset,lYOffset,lZOffset,lXYSliceSz,lPixel,lZPos,lYPos: integer;
2196
lX := gBGImg.ScrnDim[1];
2197
lY := gBGImg.ScrnDim[2];
2198
lZ := gBGImg.ScrnDim[3];
2199
lXYSliceSz := lX*lY;
2200
lXOffset := round(lSlice);
2201
// dec(lXOffset);//999+8
2203
for lZPos := 1 to lZ do begin
2204
lZOffset := (lZPos-1) * lXYSliceSz;
2206
for lYPos := 1 to lY do begin
2208
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lZOffset+lYOffset+lXOffset] := lImage.Img^[lPixel];
2209
lYOffset := lYOffset+ lX;
2215
procedure ReadAxialVOI (var lImage: TFX8;lSlice: integer);
2216
var lX,lY,lSliceOffset,lSliceSz: integer;
2218
lX := gBGImg.ScrnDim[1];
2219
lY := gBGImg.ScrnDim[2];
2221
lSliceOffset := (lSlice-1)*lX*lY;
2222
//Scrn2VOI (lImage,lX,lY, lInBuff);
2223
for lX := 1 to lSliceSz do
2224
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lSliceOffset+lX] := lImage.Img^[lX];
2228
procedure ReadScrnVOI (lImage: TImage);
2232
if (gBGImg.VOIUndoSlice < 1) or (gBGImg.VOIUndoOrient < 1) or (gBGImg.VOIUndoOrient > 3) then exit;
2233
if (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1) or (lImage.Picture.Bitmap.Width < 1) or (lImage.Picture.Bitmap.Height < 1) then
2236
lView := SelectedImageNum;
2238
3: ReadCorVOI(gDrawImg,ImgForm.YViewEdit.Value);
2239
2: ReadSagVOI(gDrawImg,ImgForm.XViewEdit.Value);
2240
1: ReadAxialVOI(gDrawImg,ImgForm.ZViewEdit.Value);
2242
ImgForm.RefreshImagesTimer.Enabled := true;
2245
procedure TImgForm.PGImageMouseUp(Sender: TObject; Button: TMouseButton;
2246
Shift: TShiftState; X, Y: Integer);
2247
var lX, lY,lPanel: integer;
2250
lPanel := SelectedImageNum;
2251
lImage := Sender as TImage;
2253
ScaleScrn2BMP(lX,lY,lImage);
2254
if (gSelectOrigin.X > 0) then begin
2255
sortLTRB(gSelectRect.Left,gSelectRect.Top,gSelectRect.Right,gSelectRect.Bottom);
2256
ShowFocusRect(gSelectRect);
2257
gSelectOrigin.X := -1;
2258
if (EllipseBtn.Down) then
2259
DrawEllipse(Limage,gSelectRect,Shift,lPanel)
2261
AdjustContrastRectangle(lImage);
2266
if ((PenBtn.Down) or (ClosedPenBtn.Down)) and (gMouseDownX > 0) then begin
2267
ScaleBMP2Draw(gBGImg.VOIInvZoom, gMouseDownX,gMouseDownY,lPanel,lImage);
2268
//next: draw single pxiel if user clicks on image without moving the mouse
2269
//DrawImg2.Canvas.Pixels[gMouseDownX,gMouseDownY] := DrawImg2.Canvas.Pen.Color;
2270
if (ClosedPenBtn.Down) then begin
2271
if lImage.Canvas.Pen.Color = clBlack then
2272
LineToFX8(gDrawImg,gMouseDownX,gMouseDownY,0)
2274
LineToFX8(gDrawImg,gMouseDownX,gMouseDownY,kVOI8Bit);
2278
gMouseDownX := -1; //disable draws
2279
//if DrawToolSelected then
2280
if DrawToolSelected and (not (ssAlt in Shift)) then
2281
ReadScrnVOI (lImage);
2282
end; //PGImageMouseUp
2285
procedure TImgForm.FormMouseWheelDown(Sender: TObject; Shift: TShiftState;
2286
MousePos: TPoint; var Handled: Boolean);
2288
Case SelectedImageNum of
2289
3: DecViewEdit(YViewEdit);
2290
2: DecViewEdit(XViewEdit);
2291
else DecViewEdit(ZViewEdit);
2295
procedure TImgForm.FormMouseWheelUp(Sender: TObject; Shift: TShiftState;
2296
MousePos: TPoint; var Handled: Boolean);
2298
Case SelectedImageNum of
2299
3: IncViewEdit(YViewEdit);
2300
2: IncViewEdit(XViewEdit);
2301
else IncViewEdit(ZViewEdit);
2305
procedure TImgForm.ZoomDropSelect(Sender: TObject);
2307
gBGImg.ZoomPct := (ZoomDrop.ItemIndex-1)*100;
2308
RefreshImagesTimer.Enabled := true;
2311
procedure TImgForm.ColorBarBtnMouseDown(Sender: TObject;
2312
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
2313
var lLTRB,lLayer: integer;
2316
if (ssAlt in Shift) then begin
2317
//lImage := SelectedImage;
2318
lLayer := ActiveLayer;
2319
DrawHistogram(gMRIcroOverlay[lLayer],HistogramForm.HistoImage{lImage});
2320
HistogramForm.Caption := 'Histogram: '+extractfilename(gMRIcroOverlay[lLayer].HdrFileName);
2322
if (ssCtrl in Shift) then
2323
TextReportHisto(gMRIcroOverlay[lLayer]);
2327
if (ssRight in Shift) then
2329
if (ssCtrl in Shift) then
2331
lImage := SelectedImage;
2332
intenBar(lImage,gMRIcroOverlay[ActiveLayer],lLTRB,0,0);
2339
procedure TImgForm.XBarBtnClick(Sender: TObject);
2341
gBGImg.XBarVisible := XBarBtn.Down;
2342
RefreshImagesTimer.Enabled := true;
2345
procedure RepositionOrigin;
2347
gBGImg.ScrnOri[1] := ImgForm.XviewEdit.value;
2348
gBGImg.ScrnOri[2] := ImgForm.YviewEdit.value;
2349
gBGImg.ScrnOri[3] := ImgForm.ZviewEdit.value;
2352
procedure TImgForm.XBarBtnMouseUp(Sender: TObject; Button: TMouseButton;
2353
Shift: TShiftState; X, Y: Integer);
2358
procedure TImgForm.XBarBtnMouseDown(Sender: TObject; Button: TMouseButton;
2359
Shift: TShiftState; X, Y: Integer);
2362
if not (ssRight in shift) then exit;
2363
if (ssShift in Shift) then begin
2367
if (ssAlt in Shift) and (ssCtrl in Shift) then begin
2368
inc(gBGImg.FontSize,2);
2369
if gBGImg.FontSize > 24 then
2370
gBGImg.FontSize := 8;
2373
if (ssAlt in Shift) then begin
2374
inc(gBGImg.XBarThick,2);
2375
if gBGImg.XBarThick > 10 then
2376
gBGImg.XBarThick := 1;
2379
if (ssCtrl in Shift) then begin
2380
ColorDialog1.Color := gBGImg.XBarClr;
2381
if not ColorDialog1.Execute then exit;
2382
gBGImg.XBarClr := ColorDialog1.Color;
2385
inc(gBGImg.XBarGap);
2386
if gBGImg.XBarGap > 10 then
2387
gBGImg.XBarGap := 0;
2389
RefreshImagesTimer.Enabled := true;
2390
if MultiSliceForm.Visible then
2391
MultiSliceForm.CreateMultiSlice;
2392
end; //XBarBtnMouseDown
2396
procedure TImgForm.RefreshImagesTimerTimer(Sender: TObject);
2398
RefreshImagesTimer.Enabled := false;
2405
procedure TImgForm.ImgPanelClick(Sender: TObject);
2407
SelectPanel((Sender as TScrollBox).tag);
2410
procedure TImgForm.MagnifyMenuItemClick(Sender: TObject);
2412
(*if MagnifyPanel.Height < 20 then //Height constrained by Y
2413
MagnifyPanel.Height := 128
2415
MagnifyPanel.Height := MagnifyPanel.Constraints.MinHeight; *)
2418
procedure TImgForm.CloseImagesClick(Sender: TObject);
2424
for lC := 0 to knMaxOverlay do //background, all overlays, VOI
2425
FreeImgMemory(gMRIcroOverlay[lC]);
2426
gBGImg.VOIUndoSlice := 0;
2428
//next- set layers menu
2429
LayerDrop.Items.Clear;
2430
LayerDrop.Items.Add('Background');
2432
LayerDrop.SetItemIndex(0);
2434
LayerDrop.ItemIndex :=(0);
2436
LayerDropSelect(nil);
2439
procedure TImgForm.OverlayOpenCore (var lFilename: string; lOverlayNum: integer);
2441
if not HdrForm.OpenAndDisplayHdr(lFilename,gMRIcroOverlay[lOverlayNum]) then exit;
2442
//if not OpenImg(gBGImg,gMRIcroOverlay[lOverlayNum],false,false,false) then exit;
2443
//if (ssShift in KeyDataToShiftState(vk_Shift)) then begin
2444
// if not OpenImg(gBGImg,gMRIcroOverlay[lOverlayNum],false,false,false,not gBGImg.ResliceOnLoad,false) then exit;
2446
if not OpenImg(gBGImg,gMRIcroOverlay[lOverlayNum],false,false,false,gBGImg.ResliceOnLoad,false) then exit;
2447
ImgForm.UpdateLayerMenu;
2448
ImgForm.RefreshImagesTimer.Enabled := true;
2451
procedure TImgForm.LoadOverlay (lFilename: string);
2453
lOverlay,lC: integer;
2456
for lC := 1 to (knMaxOverlay-1) do //-1: save final overlay for VOI
2457
if (lOverlay = 0) and (gMRIcroOverlay[lC].ImgBufferItems = 0) then
2459
if lOverlay = 0 then begin
2460
showmessage('Unable to add an overlay. You have loaded the maximum number of overlays.');
2463
OverlayOpenCore ( lFilename, lOverlay);
2466
procedure TImgForm.LoadOverlayIncludingRGB (lFilename: string);
2468
lOverlay,lC: integer;
2471
for lC := 1 to (knMaxOverlay-1) do //-1: save final overlay for VOI
2472
if (lOverlay = 0) and (gMRIcroOverlay[lC].ImgBufferItems = 0) then
2474
if lOverlay = 0 then begin
2475
showmessage('Unable to add an overlay. You have loaded the maximum number of overlays.');
2478
OverlayOpenCore ( lFilename, lOverlay);
2479
if (gMRIcroOverlay[lOverlay].NIFTIhdr.datatype = kDT_RGB) then begin
2480
OverlayOpenCore ( lFilename, lOverlay+1);
2481
OverlayOpenCore ( lFilename, lOverlay+2);
2482
OverlayAdditive.click;
2486
procedure TImgForm.BrainMask1Click(Sender: TObject);
2490
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
2491
showmessage('Please load a background image for rescaling.');
2494
//lImgSamples := gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems;
2495
for lInc := 1 to gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems do
2496
if gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc] <> 0 then
2497
gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc] := 1;
2498
SaveAsVOIorNIFTI(gMRIcroOverlay[kBGOverlayNum].ScrnBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems,1,1,true,gMRIcroOverlay[kBGOverlayNum].NiftiHdr,gMRIcroOverlay[kVOIOverlayNum].HdrFileName);
2501
procedure TImgForm.ControlPanelDragDrop(Sender, Source: TObject; X, Y: Integer);
2506
procedure DescribeVOIonLabels (lOverlayNum: integer; lShowFilename: boolean);
2508
lLocalMax,lLocalSum : HistoDoubleRA;
2513
lXmm,lYmm,lZmm: single;
2514
lHisto,lRegionVol,lLocalMaxPos: HistoRA;
2515
lInc,lRegion: Integer;
2518
lLabelStr20 : Array[0..kHistoBins] of kstr20;
2520
lInten := 0;//just to hide compiler hint...
2521
if (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP = 2) and ('ratlas.nii.gz' = (extractfilename( gMRIcroOverlay[kBGOverlayNum].HdrFileName))) then begin
2522
// specific for PCDescribeVOIonLabelsRAT(lOverlayNum,lShowFilename);
2525
if (gMRIcroOverlay[lOverlayNum].ScrnBufferItems <> gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems) or (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP <> 1) or (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 2) then
2527
TextForm.Memo1.Lines.add(' Custom Region Analysis');
2528
TextForm.Memo1.Lines.add(' For Speculative Brodmann Map: 0=not cortical and 48=no Brodmann label');
2529
lVOI := IsVOIROIExt(gMRIcroOverlay[lOverlayNum].HdrFileName);
2530
if (not lVOI) and (lOverlayNum = kVOIOverlayNum) then
2532
//next describe format
2533
if lShowfilename then
2534
lLabelStr := ' Filename,'
2537
if lVOI then //intensity min/max position are not important
2538
TextForm.Memo1.Lines.add(lLabelStr+'Area,N>0,%N>0')
2540
TextForm.Memo1.Lines.add(lLabelStr+'Area,N>0,%N>0,Sum>0,Mean>0,Max,MaxX,MaxY,MaxZ');
2542
if lShowFilename then
2543
lLabelStr := gMRIcroOverlay[lOverlayNum].HdrFileName+','
2546
for lInc := 0 to kHistoBins do begin
2548
lLocalMax[lInc] := 0;
2549
lLocalSum[lInc] := 0;
2550
lRegionVol[lInc] := 0;
2551
if (gMRIcroOverlay[kBGOverlayNum].UsesCustomPalette) then
2552
lLabelStr20[lInc] := gBGImg.LabelStr20[lInc]
2554
lLabelStr20[lInc] := inttostr(lInc);
2556
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do
2557
if gMRIcroOverlay[lOverlayNum].ScrnBuffer^[lInc] > 0 then
2558
inc(lHisto[gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc]]);
2560
l32Buf := SingleP(gMRIcroOverlay[lOverlayNum].ImgBuffer );
2561
l16Buf := SmallIntP(gMRIcroOverlay[lOverlayNum].ImgBuffer );
2562
//NEXT if..else July07 - ROIs only use screen buffer, not imgbuffer...
2563
if gMRIcroOverlay[lOverlayNum].ScrnBufferItems = gMRIcroOverlay[lOverlayNum].ImgBufferItems then
2564
l8Buf := gMRIcroOverlay[lOverlayNum].ImgBuffer
2566
l8Buf := gMRIcroOverlay[lOverlayNum].ScrnBuffer;
2567
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do begin
2568
if (gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 4) then
2569
lInten := l32Buf^[lInc]
2570
else if (gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 2) then
2571
lInten := l16Buf^[lInc]
2572
else if gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 1 then
2573
lInten := l8Buf^[lInc];//July07
2574
lRegion := gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc];
2576
lLocalSum[lRegion] := lLocalSum[lRegion]+lInten;
2577
if lInten > lLocalMax[lRegion] then begin
2578
lLocalMax[lRegion] := lInten;//intensity
2579
lLocalMaxPos[lRegion] := lInc;//location
2581
inc(lRegionVol[lRegion]);
2583
for lInc := 0 to kHistoBins do begin
2584
if (not lVOI) and (lLocalMax[lInc] > 0) then begin
2585
lLocalMax[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[lOverlayNum],lLocalMax[lInc]);
2586
lLocalSum[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[lOverlayNum],lLocalSum[lInc]);
2587
ImgPosToMM(lLocalMaxPos[lInc], lXmm,lYmm,lZmm);
2588
TextForm.Memo1.Lines.Add(lLabelStr+ lLabelStr20[lInc] + ', ' + inttostr(lHisto[lInc])+','+floattostr( lHisto[lInc]/lRegionVol[lInc])
2589
+','+floattostr( lLocalSum[lInc])+','+floattostr( lLocalSum[lInc]/lRegionVol[lInc]) //Sum>0, mean>0
2590
+', ' + floattostr(lLocalMax[lInc])+','+floattostr(lXmm)+','+floattostr(lYmm)+','+floattostr(lZmm) );
2591
end else if (lHisto[lInc] > 0) {necessarily also and (lRegionVol[lInc] > 0)} then
2592
TextForm.Memo1.Lines.Add(lLabelStr+ lLabelStr20[lInc] + ', ' + inttostr(lHisto[lInc])+','+floattostr( lHisto[lInc]/lRegionVol[lInc])) ;
2596
procedure ShowDescriptive (lOverlayNum: integer; lShowFilename: boolean);
2598
lROIVol: array [1..3] of integer;
2600
lCenterOfMass,lROISum,lROISumSqr,lROImin,lROImax:array [1..3] of double;
2601
lCC,lVal,lSD,lROImean: double;
2602
lLabelStr,lStr: string;
2603
procedure AddVal( lRA: integer);
2606
lROISum[lRA] := lROISum[lRA]+lVal;
2607
lROISumSqr[lRA] := lROISumSqr[lRA] + sqr(lVal);
2608
if lVal > lROImax[lRA] then
2609
lROImax[lRA] := lVal;
2610
if lVal < lROImin[lRA] then
2611
lROImin[lRA] := lVal;
2613
begin //proc ShowDescript
2614
if gMRIcroOverlay[lOverlayNum].ScrnBufferItems <> gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems then
2617
if lShowFilename then
2618
lLabelStr := gMRIcroOverlay[lOverlayNum].HdrFileName
2621
for lInc := 1 to 3 do begin
2624
lROISumSqr[lInc] := 0;
2625
lROImin[lInc] := maxint;
2626
lROImax[lInc] := -maxint;
2628
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do begin
2629
if gMRIcroOverlay[lOverlayNum].ScrnBuffer^[lInc] > 0 then begin
2631
lVal := RawBGIntensity(lInc);
2638
end; //for each voxel
2639
//next - compute StDev
2640
//compute descriptives for each set of values
2641
if lOverlayNum = kVOIOverlayNum then
2642
lStr := 'VOI notes '
2644
lStr := 'Overlay #'+inttostr(lOverlayNum);
2645
if not lShowFilename then begin
2646
TextForm.Memo1.Lines.Add(lStr+' '+gMRIcroOverlay[lOverlayNum].HdrFileName);
2648
//TextForm.Memo1.Lines.Add('CoM');
2649
if CenterOfMass (lOverlayNum, lCenterOfMass[1],lCenterOfMass[2],lCenterOfMass[3]) > 0 then
2650
TextForm.Memo1.Lines.Add(' '+lLabelStr+' Center of mass XYZ '+RealToStr(lCenterOfMass[1],2)+'x'+RealToStr(lCenterOfMass[2],2)+'x'+RealToStr(lCenterOfMass[3],2));
2651
for lInc := 1 to 3 do begin
2652
if lROIVol[lInc] > 1 then begin
2653
lSD := (lROISumSqr[lInc] - ((Sqr(lROISum[lInc]))/lROIVol[lInc]));
2655
lSD := Sqrt ( lSD/(lROIVol[lInc]-1))
2661
if lROIVol[lInc] > 0 then begin
2662
lROImean := lROISum[lInc]/lROIVol[lInc];
2663
//next - calibrate values
2664
lROImin[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROImin[lInc]);
2665
lROIMean := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROIMean);
2666
lROImax[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROImax[lInc]);
2667
lSD := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lSD);
2669
end else begin //2/2008
2674
lcc := ((lROIVol[lInc]/1000)*gBGImg.ScrnMM[1]*gBGImg.ScrnMM[2]*gBGImg.ScrnMM[3]);
2676
3: lStr := 'VOI >0 ';
2677
2: lStr := 'VOI <>0 ';
2678
else lStr := 'VOI ';
2680
lStr := lStr+' n=min/mean/max=SD: '+inttostr(round(lROIVol[lInc]))+'['+RealToStr(lCC,2)+'cc]='+RealToStr(lROIMin[lInc],4)+'/'+realToStr(lROIMean,4)+'/'+realToStr(lROIMax[lInc],4)+'='+realtostr(lSD,4);
2681
TextForm.Memo1.Lines.Add(lLabelStr+ lStr);
2683
//June07 if (gMRIcroOverlay[kBGOverlayNum].UsesCustomPalette) or (lShowFilename) then
2684
DescribeVOIonLabels(lOverlayNum,lShowfilename);
2685
TextForm.Memo1.Lines.Add('');
2686
ImgForm.SaveDialog1.Filename := ExtractFileDirWithPathDelim(gMRIcroOverlay[lOverlayNum].HdrFileName)+'desc.csv';
2690
procedure TImgForm.BatchROImean1Click(Sender: TObject);
2692
lInc,lNumberofFiles: integer;
2695
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
2696
showmessage('Please load a background image for rescaling.');
2699
for lInc := 1 to (knMaxOverlay-1) do
2700
FreeImgMemory(gMRIcroOverlay[lInc]);
2702
if not OpenDialogExecute(kImgFilter,'Select images you wish to analyze',true) then exit;
2703
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
2704
if lNumberofFiles < 1 then
2706
TextForm.Memo1.Lines.Clear;
2707
for lInc:= 1 to lNumberofFiles do begin
2708
lFilename := HdrForm.OpenHdrDlg.Files[lInc-1];
2709
OverlayOpenCore ( lFilename, 2);
2710
ShowDescriptive(2,true);
2711
//LayerDrop.SetItemIndex(LayerDrop.Items.Count-1);
2712
//LayerDropSelect(nil);
2714
FreeImgMemory(gMRIcroOverlay[2]);
2716
//SaveDialog1.Filename := ExtractFileDirWithPathDelim(HdrForm.OpenHdrDlg.Files[0])+'desc.csv';
2720
procedure TImgForm.Batchprobmaps1Click(Sender: TObject);
2725
procedure TImgForm.Batchclusterprobmaps1Batchclusterprobmaps1ClickClick(
2731
procedure TImgForm.GenerateSPM5maskslesions1Click(Sender: TObject);
2733
VOISmoothForm.SmoothVOI_SPM5masks;
2737
procedure TImgForm.OverlayOpenClick(Sender: TObject);
2740
lOverlay,lInc: integer;
2742
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
2743
showmessage('Please load a background image (''File''/''Open'') before adding an overlay.');
2746
if not OpenDialogExecute(kImgFilter,'Select overlay image[s]',true) then exit;
2747
if HdrForm.OpenHdrDlg.Files.Count < 1 then
2749
for lInc := 1 to HdrForm.OpenHdrDlg.Files.Count do begin //vcx
2750
lFilename := HdrForm.OpenHdrDlg.Files[lInc-1];
2751
LoadOverlayIncludingRGB{LoadOverlay}(lFilename);
2752
LayerDrop.ItemIndex := (LayerDrop.Items.Count-1);
2754
LayerDrop.SetItemIndex(LayerDrop.Items.Count-1);
2756
LayerDrop.ItemIndex :=(LayerDrop.Items.Count-1);
2761
(* //HdrForm.OpenHdrDlg.Filter := kImgFilter;
2762
// if not HdrForm.OpenHdrDlg.Execute then exit;
2763
if not OpenDialogExecute(kImgFilter,'Select overlay image',false) then exit;
2765
for lC := 1 to (knMaxOverlay-1) do //-1: save final overlay for VOI
2766
if (lOverlay = 0) and (gMRIcroOverlay[lC].ImgBufferItems = 0) then
2768
if lOverlay = 0 then begin
2769
showmessage('Unable to add an overlay. You have loaded the maximum number of overlays.');
2772
lFilename := HdrForm.OpenHdrDlg.Filename;
2773
OverlayOpenCore ( lFilename, lOverlay);
2775
LayerDropSelect(nil);
2776
end; //OverlayOpenClick
2778
procedure TImgForm.BGtrans100Click(Sender: TObject);
2780
(sender as TMenuItem).checked := true;
2781
gBGImg.BGTransPct := (sender as TMenuItem).tag;
2782
RefreshImagesTimer.Enabled := true;
2785
procedure TImgForm.OverlayTransClick(Sender: TObject);
2787
(sender as TMenuItem).checked := true;
2788
gBGImg.OverlayTransPct := (sender as TMenuItem).tag;
2789
RefreshImagesTimer.Enabled := true;
2792
procedure TImgForm.LayerDropSelect(Sender: TObject);
2796
lLayer := ActiveLayer;
2797
MaxWindowEdit.Value := gMRIcroOverlay[lLayer].WindowScaledMax;
2798
MinWindowEdit.Value := gMRIcroOverlay[lLayer].WindowScaledMin;
2799
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems=0 then exit;
2801
LUTdrop.SetItemIndex(gMRIcroOverlay[lLayer].LUTindex);
2803
LUTdrop.ItemIndex :=(gMRIcroOverlay[lLayer].LUTindex);
2805
//LUTinvertBtn.down := gMRIcroOverlay[lLayer].LUTinvert;
2806
LutFromZeroBtn.down := gMRIcroOverlay[lLayer].LutFromZero;
2809
procedure TImgForm.UpdateLayerMenu;
2811
lStrings: TStringList;
2812
lPos,lLayer:integer;
2814
lStrings := TStringList.Create;
2815
lStrings.Add('Background');
2817
for lPos := 1 to (knMaxOverlay-1) do //-1 as max overlay is VOI
2818
if (gMRIcroOverlay[lPos].ImgBufferItems > 0) then begin
2819
lStrings.Add(ParseFileName(ExtractFileName(gMRIcroOverlay[lPos].HdrFileName)));
2821
LUTdropLoad(lLayer);
2823
LayerDrop.Items := lStrings;
2826
if LayerDrop.ItemIndex >= LayerDrop.Items.Count then
2827
LayerDrop.SetItemIndex(LayerDrop.Items.Count-1);
2829
if LayerDrop.ItemIndex >= LayerDrop.Items.Count then
2830
LayerDrop.ItemIndex :=(LayerDrop.Items.Count-1);
2833
LayerDropSelect(nil);
2837
procedure TImgForm.CloseOverlayImgClick(Sender: TObject);
2841
for lOverlay := 1 to (knMaxOverlay-1) do
2842
FreeImgMemory(gMRIcroOverlay[lOverlay]);
2844
RefreshImagesTimer.Enabled := true;
2847
procedure TImgForm.LUTdropLoad(var lLayer: integer);
2851
if gMRIcroOverlay[lLayer].UsesCustomPalette then begin
2854
//gMRIcroOverlay[lLayer].LUTindex := LUTdrop.ItemIndex;
2855
if gMRIcroOverlay[lLayer].LUTindex < knAutoLUT then begin
2856
LoadMonochromeLUT(gMRIcroOverlay[lLayer].LUTindex,gBGImg,gMRIcroOverlay[lLayer]);
2857
RefreshImagesTimer.Enabled := true;
2860
lStr := gColorSchemeDir+pathdelim+LUTdrop.Items.Strings[gMRIcroOverlay[lLayer].LUTindex]+'.lut';
2861
if not FileExistsEX(lStr) then
2862
showmessage('Can not find '+lStr);
2863
LoadColorScheme(lStr, gMRIcroOverlay[lLayer]);
2864
RefreshImagesTimer.Enabled := true;
2867
procedure TImgForm.LUTdropSelect(Sender: TObject);
2871
lLayer := ActiveLayer;
2872
gMRIcroOverlay[lLayer].LUTindex := LUTdrop.ItemIndex;
2873
//gMRIcroOverlay[lLayer].LUTinvert := LUTinvertBtn.down;
2874
//gMRIcroOverlay[lLayer].LutFromZero := LutFromZeroBtn.down;
2875
LUTdropLoad(lLayer);
2876
//RescaleImagesTimer.Enabled := true;
2877
end; //proc LUTdropSelect
2881
procedure TImgForm.AutoContrastBtnClick(Sender: TObject);
2885
lLayer := ActiveLayer;
2886
MinWindowEdit.Value := raw2ScaledIntensity(gMRIcroOverlay[lLayer], gMRIcroOverlay[lLayer].AutoBalMinUnscaled);
2887
MaxWindowEdit.Value := raw2ScaledIntensity(gMRIcroOverlay[lLayer],gMRIcroOverlay[lLayer].AutoBalMaxUnscaled);{}
2889
gMRIcroOverlay[lLayer].WindowScaledMin := MinWindowEdit.Value;
2890
gMRIcroOverlay[lLayer].WindowScaledMax := MaxWindowEdit.Value;
2891
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lLayer],lLayer);
2893
RefreshImagesTimer.Enabled := true;
2896
procedure TImgForm.MinContrastWindowEditChange(Sender: TObject);
2900
lLayer := ActiveLayer;
2901
if gMRIcroOverlay[lLayer].WindowScaledMin = MinWindowEdit.Value then exit;
2902
gMRIcroOverlay[lLayer].WindowScaledMin := MinWindowEdit.Value;
2903
RescaleImagesTimer.Enabled := true;
2906
procedure TImgForm.MaxContrastWindowEditChange(Sender: TObject);
2910
lLayer := ActiveLayer;
2911
if gMRIcroOverlay[lLayer].WindowScaledMax = MaxWindowEdit.Value then exit;
2912
gMRIcroOverlay[lLayer].WindowScaledMax := MaxWindowEdit.Value;
2913
RescaleImagesTimer.Enabled := true;
2916
procedure TImgForm.OverlaySmoothMenuClick(Sender: TObject);
2920
if Sender = nil then begin
2921
gBGImg.OverlaySmooth := OverlaySmoothMenu.Checked;
2924
OverlaySmoothMenu.Checked := not OverlaySmoothMenu.Checked;
2925
gBGImg.OverlaySmooth := OverlaySmoothMenu.Checked;
2926
for lC := 1 to knMaxOverlay do
2927
if gMRIcroOverlay[lC].ScrnBufferItems > 0 then
2928
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lC],lC);
2929
RefreshImagesTimer.Enabled := true;
2932
procedure TImgForm.ShowRenderClick(Sender: TObject);
2935
//RenderForm.BringToFront;
2938
procedure TImgForm.PenBtnClick(Sender: TObject);
2940
RefreshImagesTimer.Enabled := true;
2943
procedure OpenMRIcroROI (lFilename: string);
2946
kMax16bit = (256*256)-1;
2947
kMax15bit = kMax16bit shr 1;
2948
//kMax20bit = (16*256*256)-1;
2949
// k20v16bit = kMax20bit - kMax16bit;
2952
//k16v12bit = kMax16bit - kMax12bit;
2954
lFile32bitItems,lFileSz,lFilePos,lSliceSz,lZ,lRunsOnSlice,
2955
lRunLength,lRun,lRunOffset,lOutputSliceOffset,lRunPos: integer;
2956
lROIformatRA: LongIntp;
2958
lBigFormat: boolean;
2960
lFileSz := FSize(lFilename);
2961
if (lFileSz < 1) or ((lFileSz mod 4) <> 0) then begin
2962
showmessage('Unable to open ROI: file size should be divisible by 4.');
2965
lFile32bitItems := lFileSz div 4; //how many 32-bit items?
2966
lSliceSz := gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2];
2967
lZ := gBGImg.ScrnDim[3];
2968
if gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems > 0 then
2969
freemem(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer);
2970
gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems := lSliceSz * lZ;
2971
getmem(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer,lSliceSz * lZ);
2972
fillchar(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems,0);
2973
if lSliceSz > 65535 then
2976
lBigFormat := false;
2977
getmem(lROIformatRA,lFileSz); //file size must be divisible by 4
2979
AssignFile(lF, lFilename);
2980
FileMode := 0; { Set file access to read only }
2982
BlockRead(lF,lROIformatRA^,lFileSz);
2986
//next: check MSB of first byte to see if this is big format images
2987
if lBigFormat <> odd((lROIformatRA^[1] and kMax16bit) shr 15) then
2988
Showmessage('Warning: this ROI does not appear to be designed for the currently loaded background image.');
2990
if lBigFormat then begin //20-byte offset, 12-byte runlength
2991
while lFilePos < lFile32bitItems do begin
2992
lRunsOnSlice := (lROIformatRA^[lFilePos] shr 17) - 1; //shr 17: shift 16 bits, then div 2 (words instead of longints). Subtract 1 as the we have read slice number/ number of runs
2993
lZ := (lROIformatRA^[lFilePos] and kMax15bit);
2995
lOutputSliceOffset := (lZ-1) * lSliceSz;
2996
for lRun := 1 to lRunsOnSlice do begin
2997
if (lFilePos <= lFileSz) then begin
2998
lRunLength := (lROIformatRA^[lFilePos] shr 16) and kMax12bit;
2999
lRunOffset := (lROIformatRA^[lFilePos] and kMax16bit)+ ((lROIformatRA^[lFilePos] shr 28) shl 16);
3000
if (lOutputSliceOffset+lRunLength+lRunOffset-1)> gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems then
3001
//showmessage('Overrun on slice '+inttostr(lZ))
3002
else for lRunPos := lRunOffset to (lRunLength+lRunOffset-1) do
3003
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lRunPos+lOutputSliceOffset] := kVOI8bit;
3007
end; //while lPos < lFSz
3008
end else begin //not big format format - 16-byte offset, 16-byte length
3009
while lFilePos < lFile32bitItems do begin
3010
//lRunsOnSlice := (lROIformatRA[lFilePos] shr 16) and kMax16bit;
3011
lRunsOnSlice := (lROIformatRA^[lFilePos] shr 17) - 1; //shr 17: shift 16 bits, then div 2 (words instead of longints). Subtract 1 as the we have read slice number/ number of runs
3012
lZ := (lROIformatRA^[lFilePos] and kMax15bit);
3014
lOutputSliceOffset := (lZ-1) * lSliceSz;
3015
//showmessage(inttostr(lZ)+' '+inttostr(lRunsOnSlice)+' '+inttostr(lFilePos)+' '+inttostr(lFileSz));
3016
for lRun := 1 to lRunsOnSlice do begin
3017
if (lFilePos <= lFileSz) then begin
3018
lRunLength := (lROIformatRA^[lFilePos] shr 16) and kMax16bit;
3019
lRunOffset := (lROIformatRA^[lFilePos] and kMax16bit);
3020
{if (lRunLength+lRunOffset-1)> gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems then
3021
showmessage('Overrun on slice '+inttostr(lZ))
3022
else} for lRunPos := lRunOffset to (lRunLength+lRunOffset-1) do
3023
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lRunPos+lOutputSliceOffset] := kVOI8bit;
3027
end; //while lPos < lFSz
3028
end; //if bigformat ... else little format
3029
freemem(lROIformatRA);
3031
LoadMonochromeLUT(lRun,gBGImg,gMRIcroOverlay[kVOIOverlayNum]);
3034
procedure TImgForm.OpenVOICore(var lFilename : string);
3038
if gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems > 0 then
3039
ImgForm.CloseVOIClick(nil);
3040
lExt := UpCaseExt(lFileName);
3041
gBGImg.VOIchanged := false;
3042
if (lExt='.ROI') then begin
3043
Showmessage('Warning: MRIcro ROI format does not save image dimensions. The background image must be in the same dimensions as the ROI.');
3044
OpenMRIcroROI (lFileName);
3045
ImgForm.RefreshImagesTimer.Enabled := true;
3048
if not HdrForm.OpenAndDisplayHdr(lFilename,gMRIcroOverlay[kVOIOverlayNum]) then exit;
3049
if not OpenImg(gBGImg,gMRIcroOverlay[kVOIOverlayNum],false,true,false,gBGImg.ResliceOnLoad,false) then exit;
3050
ImgForm.RefreshImagesTimer.Enabled := true;
3054
procedure TImgForm.OpenVOIClick(Sender: TObject);
3058
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
3059
showmessage('Please load a background image (''File''/''Open'') before adding a VOI.');
3062
//HdrForm.OpenHdrDlg.Filter := '*.roi';//kVOIFilter;
3063
//if not HdrForm.OpenHdrDlg.Execute then exit;
3064
if not OpenDialogExecute(kVOIFilter,'Select Volume of Interest drawing',false) then exit;
3065
lFilename := HdrForm.OpenHdrDlg.Filename;
3066
OpenVOICore(lFilename);
3069
(*procedure TImgForm.SaveVOIClick(Sender: TObject);
3070
var lHdr: TMRIcroHdr;
3072
if gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems= 0 then begin
3073
Showmessage('You need to create a VOI before you can save it.');
3076
if gBGImg.Mirror then begin
3077
lHdr.ScrnBufferItems := gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems;
3078
Getmem(lHdr.ScrnBuffer,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems);
3079
Move(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[1],lHdr.ScrnBuffer^[1],lHdr.ScrnBufferItems);
3080
MirrorScrnBuffer(gBGImg,lHdr);
3081
SaveAsVOIorNIFTI(lHdr.ScrnBuffer,lHdr.ScrnBufferItems,1,1,true,gMRIcroOverlay[kBGOverlayNum].NiftiHdr,gMRIcroOverlay[kVOIOverlayNum].HdrFileName);
3082
Freemem(lHdr.ScrnBuffer);
3085
SaveAsVOIorNIFTI(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems,1,1,true,gMRIcroOverlay[kBGOverlayNum].NiftiHdr,gMRIcroOverlay[kVOIOverlayNum].HdrFileName);
3087
procedure TImgForm.SaveVOIClick(Sender: TObject);
3088
var lHdr: TMRIcroHdr;
3089
lNIFTIhdr: TNIFTIhdr;
3091
if gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems= 0 then begin
3092
Showmessage('You need to create a VOI before you can save it.');
3095
//Start 10/2007: adjust scl_slope;? 10/2007
3096
CopyNiftiHdr(gMRIcroOverlay[kBGOverlayNum].NiftiHdr,lNIFTIhdr);
3097
lNIFTIhdr.scl_slope := 1;
3098
lNIFTIhdr.scl_inter := 0;
3100
if gBGImg.Mirror then begin
3101
lHdr.ScrnBufferItems := gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems;
3102
Getmem(lHdr.ScrnBuffer,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems);
3103
Move(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[1],lHdr.ScrnBuffer^[1],lHdr.ScrnBufferItems);
3104
MirrorScrnBuffer(gBGImg,lHdr);
3105
SaveAsVOIorNIFTI(lHdr.ScrnBuffer,lHdr.ScrnBufferItems,1,1,true,lNIFTIhdr,gMRIcroOverlay[kVOIOverlayNum].HdrFileName);
3106
Freemem(lHdr.ScrnBuffer);
3109
SaveAsVOIorNIFTI(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems,1,1,true,lNiftiHdr,gMRIcroOverlay[kVOIOverlayNum].HdrFileName);
3112
procedure TImgForm.VOIColorClick(Sender: TObject);
3116
ColorDialog1.Color := gBGImg.VOIClr;
3117
if not ColorDialog1.Execute then exit;
3118
gBGImg.VOIClr := ColorDialog1.Color;
3119
if gBGImg.VOIClr = clBlack then
3120
gBGImg.VOIClr := 1; //reserve 0 for deleting
3122
LoadMonochromeLUT(lMaxi,gBGImg,gMRIcroOverlay[kVOIOverlayNum]);
3123
RefreshImagesTimer.Enabled := true;
3126
procedure TImgForm.CloseVOIClick(Sender: TObject);
3128
if (gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems>0) and (gBGImg.VOIChanged) then begin
3129
case MessageDlg('Do you wish to save the VOI drawing?', mtConfirmation,
3130
[mbYes, mbNo], 0) of { produce the message dialog box }
3131
{id_Yes}mrYes: SaveVOIClick(nil);
3135
FreeImgMemory(gMRIcroOverlay[kVOIOverlayNum]);
3136
gBGImg.VOIUndoSlice := 0;
3137
gBGImg.VOIchanged := false;
3138
gBGImg.VOIUndoOrient := 0;
3139
RefreshImagesTimer.Enabled := true;
3142
procedure ImageRB (var lMaxR,lMaxB: integer; var lImage: TImage);
3146
if not lImage.Visible then
3148
lPos := lImage.Left+lImage.Width;
3149
if lPos > lMaxR then
3151
lPos := lImage.Top+lImage.Height;
3152
if lPos > lMaxB then
3156
procedure CopyImg(var lSourceImg,lDestImg: TImage);
3160
if not lSourceImg.Visible then
3162
lDestImg.Canvas.Draw(lSourceImg.Left,lSourceImg.Top,lSourceImg.Picture.Graphic);
3165
procedure TImgForm.SaveOrCopyImages(lCopy: boolean);
3167
lMaxR,lMaxB: integer;
3172
ImageRB(lMaxR,lMaxB,ImgForm.PGImageAx);
3173
ImageRB(lMaxR,lMaxB,ImgForm.PGImageCor);
3174
ImageRB(lMaxR,lMaxB,ImgForm.PGImageSag);
3175
if (lMaxR < 1) or (lMaxB < 1) then
3177
lOutImg := TImage.Create(ImgForm);
3181
lOutImg.Width := lMaxR;
3182
lOutImg.Height := lMaxB;
3184
CreateImg(lMaxB,lMaxR,lOutImg);
3186
lOutImg.Canvas.Brush.color := ImgForm.TriplePanel.color;
3187
lOutImg.Canvas.Rectangle(0,0,lMaxR+1,lMaxB+1);
3188
CopyImg(ImgForm.PGImageAx,lOutImg);
3189
CopyImg(ImgForm.PGImageCor,lOutImg);
3190
CopyImg(ImgForm.PGImageSag,lOutImg);
3193
lOutImg.Picture.Bitmap.SaveToClipboardFormat(2);
3195
Clipboard.Assign(lOutImg.Picture.Graphic);
3198
SaveImgAsPNGBMP (lOutImg);
3200
FreeAndNil (lOutImg);
3204
procedure TImgForm.Saveaspicture1Click(Sender: TObject);
3206
SaveOrCopyImages(false);
3211
lImage := SelectedImage;
3212
SaveImgAsPNGBMP (lImage);
3213
end; //Proc Saveaspicture1Click
3215
procedure TImgForm.Copy1Click(Sender: TObject); //Requires 'ClipBrd' in uses section
3217
SaveOrCopyImages(true);
3220
(*procedure TImgForm.Copy1Click(Sender: TObject); //Requires 'ClipBrd' in uses section
3225
{$IFNDEF FPC}APalette : HPalette;{$ENDIF}
3227
lImage := SelectedImage;
3228
if (lImage.Picture.Graphic = nil) then begin //1420z
3229
Showmessage('You need to load an image before you can copy it to the clipboard.');
3233
lImage.Picture.Bitmap.SaveToClipBoardFormat(MyFormat,AData,APalette);
3234
ClipBoard.SetAsHandle(MyFormat,AData);
3236
lImage.Picture.Bitmap.SaveToClipboardFormat(2);
3238
if (gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems>0) then
3239
WriteUndoVOI(SelectedImageNum,false);
3243
procedure TImgForm.Undo1Click(Sender: TObject);
3245
if gBGImg.VOIUndoSlice < 1 then exit;
3246
case gBGImg.VOIUndoOrient of
3248
3: ReadCorVOI(gUndoImg,gBGImg.VOIUndoSlice);
3249
2: ReadSagVOI(gUndoImg,gBGImg.VOIUndoSlice);
3250
1: ReadAxialVOI(gUndoImg,gBGImg.VOIUndoSlice);
3252
ImgForm.RefreshImagesTimer.Enabled := true;
3255
procedure TImgForm.Paste1Click(Sender: TObject);
3257
if (gBGImg.VOIUndoSlice < 1) then exit;
3258
if gBGImg.VOIUndoOrient <> SelectedImageNum then //12/2007
3260
WriteUndoVOI(SelectedImageNum,true);
3261
case gBGImg.VOIUndoOrient of
3262
3: ReadCorVOI(gDrawImg,ImgForm.YViewEdit.Value);
3263
2: ReadSagVOI(gDrawImg,ImgForm.XViewEdit.Value);
3264
1: ReadAxialVOI(gDrawImg,ImgForm.ZViewEdit.Value);
3267
ImgForm.RefreshImagesTimer.Enabled := true;
3270
procedure TImgForm.HideROIBtnMouseDown(Sender: TObject;
3271
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
3273
gOrigBGTransPct := gBGImg.BGTransPct;
3274
gBGImg.BGTransPct := 100;
3275
refreshimagestimer.enabled := true;
3278
procedure TImgForm.HideROIBtnMouseUp(Sender: TObject; Button: TMouseButton;
3279
Shift: TShiftState; X, Y: Integer);
3281
gBGImg.BGTransPct := gOrigBGTransPct;
3282
Refreshimagestimer.enabled := true;
3285
procedure TImgForm.Applyintensityfiltertovolume1Click(Sender: TObject);
3287
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems=0 then begin
3288
showmessage('You must have open a background image in order to apply an intensity filter (use File/Open).');
3291
FilterROIform.showmodal;
3294
procedure TImgForm.Quicksmooth1Click(Sender: TObject);
3297
lXDim,lYDim,lZDim,lSum,lMinWt,lMaxWt,lMinInten,lMaxInten,lOutVolVox,lOutSliceSz,lX,lY,lZ,lXxi,l2,lZyi: integer;
3298
lSum32,lMinInten32,lMaxInten32: single;
3299
lTempBuff,lSrcBuff: Bytep;
3300
l16TempBuff,l16SrcBuff: SmallIntP;
3301
l32TempBuff,l32SrcBuff: SingleP;
3302
procedure AddPoint (lInten,lWeight:integer);
3304
lSum := lSum + (lInten*lWeight);
3305
if lInten <= lMinInten then begin
3307
lMinInten := lInten;
3308
end else if lInten >= lMaxInten then begin
3310
lMaxInten := lInten;
3312
end; //nested AddPoint
3313
procedure AddPoint32 (lInten32: single; lWeight:integer);
3315
lSum32 := lSum32 + (lInten32*lWeight);
3316
if lInten32 <= lMinInten32 then begin
3318
lMinInten32 := lInten32;
3319
end else if lInten32 >= lMaxInten32 then begin
3321
lMaxInten32 := lInten32;
3323
end; //nested AddPoint32
3325
lHdr := gMRIcroOverlay[kBGOverlayNum];
3326
lXDim := gBGImg.ScrnDim[1];
3327
lYDim := gBGImg.ScrnDim[2];
3328
lZDim := gBGImg.ScrnDim[3];
3329
lOutSliceSz := gBGImg.ScrnDim[1] * gBGImg.ScrnDim[2];
3330
lOutVolVox := lOutSliceSz * lZDim;
3331
if (lXDim < 3) or (lYDim < 3) or (lZDim < 3) or (lOutVolVox < 36) then begin
3332
showmessage('The 3D smoothing can only be applied to images with at least 3 slices in each dimension.');
3335
if (lHdr.ImgBufferItems < 1) then begin
3336
showmessage('Please first load the image you would like to smooth.');
3339
ProgressBar1.Min := 0;
3340
ProgressBar1.Max :=lZDim;
3341
StatusLabel.caption := 'Removing noise speckles and smoothing data [blur]';
3342
if lHdr.ImgBufferBPP = 4 then begin //32-bit float data
3343
l32SrcBuff := SingleP(lHdr.ImgBuffer);
3344
GetMem(l32TempBuff,lOutVolVox*sizeof(single));
3345
Move(l32SrcBuff^,l32TempBuff^,lOutVolVox*sizeof(single));
3346
for lZ := 1 to lOutVolVox do
3347
l32SrcBuff^[lZ] := 0;
3348
for lZ := lZDim-1 downto 2 do begin
3349
ProgressBar1.Position := (lZDim-lZ);
3350
for lY := lYDim-1 downto 2 do begin
3351
lZyi := ((lZ-1)*lOutSliceSz) + ((lY-1) * lXDim);
3352
for lX := lXDim-1 downto 2 do begin
3354
//next: gaussian mean after min/max values are excluded
3356
lMinInten32 := l32TempBuff^[lXxi];
3357
lMaxInten32 := l32TempBuff^[lXxi];
3360
AddPoint32(l32TempBuff^[lXxi],12);//quad-weight center
3361
AddPoint32(l32TempBuff^[lXxi-lOutSliceSz],2);//prev slice
3362
AddPoint32(l32TempBuff^[lXxi+lOutSliceSz],2);//next slices
3363
AddPoint32(l32TempBuff^[lXxi-1],2);//Left
3364
AddPoint32(l32TempBuff^[lXxi+1],2);//right
3365
AddPoint32(l32TempBuff^[lXxi-lXDim],2);//up
3366
AddPoint32(l32TempBuff^[lXxi+lXDim],2);//down
3367
AddPoint32(l32TempBuff^[lXxi-lOutSliceSz-1],1);
3368
AddPoint32(l32TempBuff^[lXxi-lOutSliceSz+1],1);
3369
AddPoint32(l32TempBuff^[lXxi-lOutSliceSz-lXDim],1);
3370
AddPoint32(l32TempBuff^[lXxi-lOutSliceSz+lXDim],1);
3371
AddPoint32(l32TempBuff^[lXxi+lOutSliceSz-1],1);
3372
AddPoint32(l32TempBuff^[lXxi+lOutSliceSz+1],1);
3373
AddPoint32(l32TempBuff^[lXxi+lOutSliceSz-lXDim],1);
3374
AddPoint32(l32TempBuff^[lXxi+lOutSliceSz+lXDim],1);
3375
AddPoint32(l32TempBuff^[lXxi-lXDim-1],1);
3376
AddPoint32(l32TempBuff^[lXxi+lXDim-1],1);
3377
AddPoint32(l32TempBuff^[lXxi-lXDim+1],1);
3378
AddPoint32(l32TempBuff^[lXxi+lXDim+1],1);
3379
if lMinInten32 = lMaxInten32 then
3380
l32SrcBuff^[lXxi] := lMaxInten32 //no variability in data
3382
l2 := 36 - lMinWt -lMaxWt; //weight after we exceed brightest and darkest
3383
lSum32 := lSum32 -(lMinWt*lMinInten32) - (lMaxWt*lMaxInten32); //exclude brightest/darkest
3384
l32SrcBuff^[lXxi] := (lSum32/l2);
3389
Freemem(l32TempBuff);
3390
end else if (lHdr.ImgBufferBPP = 2) then begin //16-bit int data*)
3391
l16SrcBuff := SmallIntP(lHdr.ImgBuffer );
3392
GetMem(l16TempBuff,lOutVolVox*sizeof(word));
3393
Move(l16SrcBuff^,l16TempBuff^,lOutVolVox*sizeof(word));
3394
for lZ := 1 to lOutVolVox do
3395
l16SrcBuff^[lZ] := 0;
3396
for lZ := lZDim-1 downto 2 do begin
3397
ProgressBar1.Position := (lZDim-lZ);
3398
for lY := lYDim-1 downto 2 do begin
3399
lZyi := ((lZ-1)*lOutSliceSz) + ((lY-1) * lXDim);
3400
for lX := lXDim-1 downto 2 do begin
3402
//next: gaussian mean after min/max values are excluded
3404
lMinInten := l16TempBuff^[lXxi];
3405
lMaxInten := l16TempBuff^[lXxi];
3408
AddPoint(l16TempBuff^[lXxi],12);//quad-weight center
3409
AddPoint(l16TempBuff^[lXxi-lOutSliceSz],2);//prev slice
3410
AddPoint(l16TempBuff^[lXxi+lOutSliceSz],2);//next slices
3411
AddPoint(l16TempBuff^[lXxi-1],2);//Left
3412
AddPoint(l16TempBuff^[lXxi+1],2);//right
3413
AddPoint(l16TempBuff^[lXxi-lXDim],2);//up
3414
AddPoint(l16TempBuff^[lXxi+lXDim],2);//down
3415
AddPoint(l16TempBuff^[lXxi-lOutSliceSz-1],1);
3416
AddPoint(l16TempBuff^[lXxi-lOutSliceSz+1],1);
3417
AddPoint(l16TempBuff^[lXxi-lOutSliceSz-lXDim],1);
3418
AddPoint(l16TempBuff^[lXxi-lOutSliceSz+lXDim],1);
3419
AddPoint(l16TempBuff^[lXxi+lOutSliceSz-1],1);
3420
AddPoint(l16TempBuff^[lXxi+lOutSliceSz+1],1);
3421
AddPoint(l16TempBuff^[lXxi+lOutSliceSz-lXDim],1);
3422
AddPoint(l16TempBuff^[lXxi+lOutSliceSz+lXDim],1);
3423
AddPoint(l16TempBuff^[lXxi-lXDim-1],1);
3424
AddPoint(l16TempBuff^[lXxi+lXDim-1],1);
3425
AddPoint(l16TempBuff^[lXxi-lXDim+1],1);
3426
AddPoint(l16TempBuff^[lXxi+lXDim+1],1);
3427
if lMinInten = lMaxInten then
3428
l16SrcBuff^[lXxi] := lMaxInten //no variability in data
3430
l2 := 36 - lMinWt -lMaxWt; //weight after we exceed brightest and darkest
3431
lSum := lSum -(lMinWt*lMinInten) - (lMaxWt*lMaxInten); //exclude brightest/darkest
3432
l16SrcBuff^[lXxi] := round(lSum/l2);
3437
Freemem(l16TempBuff);
3438
//OptimizeSingle(nil);
3439
end else if lHdr.ImgBufferBPP = 1 then begin //8-bit data
3440
lSrcBuff := lHdr.ImgBuffer;
3441
GetMem(lTempBuff,lOutVolVox);
3442
Move(lSrcBuff^,lTempBuff^,lOutVolVox);
3443
fillchar(lSrcBuff^,lOutVolVox,0); //set edges to 0, as outside voxel is not smoothed
3444
for lZ := lZDim-1 downto 2 do begin
3445
ProgressBar1.Position := (lZDim-lZ);
3446
for lY := lYDim-1 downto 2 do begin
3447
lZyi := ((lZ-1)*lOutSliceSz) + ((lY-1) * lXDim);
3448
for lX := lXDim-1 downto 2 do begin
3450
//next: gaussian mean after min/max values are excluded
3452
lMinInten := lTempBuff^[lXxi];
3453
lMaxInten := lTempBuff^[lXxi];
3456
AddPoint(lTempBuff^[lXxi],12);//quad-weight center
3457
AddPoint(lTempBuff^[lXxi-lOutSliceSz],2);//prev slice
3458
AddPoint(lTempBuff^[lXxi+lOutSliceSz],2);//next slices
3459
AddPoint(lTempBuff^[lXxi-1],2);//Left
3460
AddPoint(lTempBuff^[lXxi+1],2);//right
3461
AddPoint(lTempBuff^[lXxi-lXDim],2);//up
3462
AddPoint(lTempBuff^[lXxi+lXDim],2);//down
3463
AddPoint(lTempBuff^[lXxi-lOutSliceSz-1],1);
3464
AddPoint(lTempBuff^[lXxi-lOutSliceSz+1],1);
3465
AddPoint(lTempBuff^[lXxi-lOutSliceSz-lXDim],1);
3466
AddPoint(lTempBuff^[lXxi-lOutSliceSz+lXDim],1);
3467
AddPoint(lTempBuff^[lXxi+lOutSliceSz-1],1);
3468
AddPoint(lTempBuff^[lXxi+lOutSliceSz+1],1);
3469
AddPoint(lTempBuff^[lXxi+lOutSliceSz-lXDim],1);
3470
AddPoint(lTempBuff^[lXxi+lOutSliceSz+lXDim],1);
3471
AddPoint(lTempBuff^[lXxi-lXDim-1],1);
3472
AddPoint(lTempBuff^[lXxi+lXDim-1],1);
3473
AddPoint(lTempBuff^[lXxi-lXDim+1],1);
3474
AddPoint(lTempBuff^[lXxi+lXDim+1],1);
3475
if lMinInten = lMaxInten then
3476
lSrcBuff^[lXxi] := lMaxInten //no variability in data
3478
l2 := 36 - lMinWt -lMaxWt; //weight after we exceed brightest and darkest
3479
lSum := lSum -(lMinWt*lMinInten) - (lMaxWt*lMaxInten); //exclude brightest/darkest
3480
lSrcBuff^[lXxi] := round(lSum/l2);
3486
end else begin //8bit data
3487
showmessage('Unknown bits per pixel '+inttostr(lHdr.ImgBufferBPP) );
3489
ProgressBar1.Position := 0;
3490
RescaleImgIntensity(gBGImg,gMRIcroOverlay[kBGOverlayNum],kBGOverlayNum);
3491
RefreshImagesTimer.Enabled := true;
3494
procedure TImgForm.VOImaskClick(Sender: TObject);
3497
lHdr,lMaskHdr: TMRicroHdr;
3498
lXDim,lYDim,lZDim,lOutVolVox,lOutSliceSz,lZ: integer;
3499
lSrcBuff,lMaskBuff: Bytep;
3500
l16SrcBuff: SmallIntP;
3501
l32SrcBuff: SingleP;
3503
lPreserve := (sender as TMenuItem).tag;
3504
lHdr := gMRIcroOverlay[kBGOverlayNum];
3505
lMaskHdr := gMRIcroOverlay[kVOIOverlayNum];
3507
lXDim := gBGImg.ScrnDim[1];
3508
lYDim := gBGImg.ScrnDim[2];
3509
lZDim := gBGImg.ScrnDim[3];
3510
lOutSliceSz := gBGImg.ScrnDim[1] * gBGImg.ScrnDim[2];
3511
lOutVolVox := lOutSliceSz * lZDim;
3512
if (lXDim < 2) or (lYDim < 2) or (lZDim < 2) then begin
3513
showmessage('Masking can only be applied to images with multiple slices in 3 dimensions.');
3516
if (lHdr.ImgBufferItems <> lMaskHdr.ScrnBufferItems) or (lHdr.ImgBufferItems < 8) then begin
3517
showmessage('Please first load both an image (File/Open) and a masking VOI (Draw/Open).');
3520
if gBGImg.Mirror then
3521
MirrorScrnBuffer(gBGImg,lMaskHdr);//4/2008
3522
lMaskBuff := (lMaskHdr.ScrnBuffer);
3523
ProgressBar1.Min := 0;
3524
ProgressBar1.Max :=lZDim;
3525
StatusLabel.caption := 'Masking data';
3526
if lHdr.ImgBufferBPP = 4 then begin //32-bit float data
3527
l32SrcBuff := SingleP(lHdr.ImgBuffer);
3528
if lPreserve = 1 then begin
3529
for lZ := 1 to lOutVolVox do
3530
if lMaskBuff^[lZ] = 0 then
3531
l32SrcBuff^[lZ] := 0;
3533
for lZ := 1 to lOutVolVox do
3534
if lMaskBuff^[lZ] <> 0 then
3535
l32SrcBuff^[lZ] := 0;
3537
end else if (lHdr.ImgBufferBPP = 2) then begin //16-bit int data*)
3538
l16SrcBuff := SmallIntP(lHdr.ImgBuffer );
3539
if lPreserve = 1 then begin
3540
for lZ := 1 to lOutVolVox do
3541
if lMaskBuff^[lZ] = 0 then
3542
l16SrcBuff^[lZ] := 0;
3544
for lZ := 1 to lOutVolVox do
3545
if lMaskBuff^[lZ] <> 0 then
3546
l16SrcBuff^[lZ] := 0;
3548
end else if lHdr.ImgBufferBPP = 1 then begin //8-bit data
3549
lSrcBuff := lHdr.ImgBuffer;
3550
if lPreserve = 1 then begin
3551
for lZ := 1 to lOutVolVox do
3552
if lMaskBuff^[lZ] = 0 then
3555
for lZ := 1 to lOutVolVox do
3556
if lMaskBuff^[lZ] <> 0 then
3559
end else begin //8bit data
3560
showmessage('Unknown bits per pixel '+inttostr(lHdr.ImgBufferBPP) );
3562
if gBGImg.Mirror then
3563
MirrorScrnBuffer(gBGImg,lMaskHdr);//4/2008
3565
ProgressBar1.Position := 0;
3566
RescaleImgIntensity(gBGImg,gMRIcroOverlay[kBGOverlayNum],kBGOverlayNum);
3567
RefreshImagesTimer.Enabled := true;
3570
procedure TImgForm.Sagittal1Click(Sender: TObject);
3572
gBGImg.SliceView := (Sender as TMenuItem).Tag;
3573
RefreshImagesTimer.Enabled := true;
3576
procedure TImgForm.ROIcomparisonClick(Sender: TObject);
3577
var lComparison,lVolItems,lOverlay,lnOverlays,lPos: integer;
3579
lComparison := (Sender as TMenuItem).tag; //0=intersect AND,1=union OR ,2=mask
3580
lVolItems := gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2]* gBGImg.ScrnDim[3];
3581
if (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems <> lVolItems) or (gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems <> lVolItems) then begin
3582
Showmessage('VOI comparisons require a VOI loaded onto a background image (Draw/Open).');
3586
for lOverlay := 1 to knMaxOverlay do
3587
if gMRIcroOverlay[lOverlay].ScrnBufferItems = lVolItems then
3589
if (lnOverlays = 0) then begin
3590
Showmessage('VOI comparisons require loaded overlays (Overlay/Add).');
3594
if lComparison = 0 then begin //intersect AND
3595
for lOverlay := 1 to (knMaxOverlay-1) do begin
3596
if gMRIcroOverlay[lOverlay].ScrnBufferItems = lVolItems then begin
3597
for lPos := 1 to lVolItems do
3598
if gMRIcroOverlay[lOverlay].ScrnBuffer^[lPos] = 0 then
3599
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lPos] := 0;
3600
end; //if overlay loaded
3601
end; //for each overlay
3602
end else if lComparison = 1 then begin //if intersect else UNION OR
3603
for lOverlay := 1 to (knMaxOverlay-1) do begin
3604
if gMRIcroOverlay[lOverlay].ScrnBufferItems = lVolItems then begin
3605
for lPos := 1 to lVolItems do
3606
if gMRIcroOverlay[lOverlay].ScrnBuffer^[lPos] > 0 then
3607
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lPos] := kVOI8bit;
3608
end; //if overlay loaded
3609
end; //for each overlay
3610
end else if lComparison = 2 then begin //if union else MASK
3611
for lOverlay := 1 to (knMaxOverlay-1) do begin
3612
if gMRIcroOverlay[lOverlay].ScrnBufferItems = lVolItems then begin
3613
for lPos := 1 to lVolItems do
3614
if gMRIcroOverlay[lOverlay].ScrnBuffer^[lPos] > 0 then
3615
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^[lPos] := 0;
3616
end; //if overlay loaded
3617
end; //for each overlay
3618
end; //if ..else MASK
3619
RefreshImagesTimer.Enabled := true;
3620
end; //ROIcomparisonClick
3622
procedure TImgForm.RescaleImagesTimerTimer(Sender: TObject);
3626
lLayer := ActiveLayer;
3627
RescaleImagesTimer.Enabled := false;
3628
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lLayer],lLayer);
3632
procedure TImgForm.Fill3DBtnClick(Sender: TObject);
3638
procedure TImgForm.SmoothVOI1Click(Sender: TObject);
3640
voismoothform.showmodal;
3641
//SmoothVOIForm.Showmodal
3644
procedure TImgForm.CreateOverlap(Sender: TObject);
3646
lNumberofFiles,lC,lOverlay,lPos: integer;
3647
lFilename,lExt: string;
3648
lOverlapBuffer: ByteP;
3650
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
3651
showmessage('Please load a background image (''File''/''Open'') before adding an overlay.');
3655
for lC := 1 to (knMaxOverlay-1) do //-1: save final overlay for VOI
3656
if (lOverlay = 0) and (gMRIcroOverlay[lC].ImgBufferItems = 0) then
3658
if lOverlay = 0 then begin
3659
showmessage('Unable to add an overlay. You have loaded the maximum number of overlays.');
3662
if not OpenDialogExecute(kVOIFilter,'Select VOIs you wish to combine',true) then exit;
3663
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
3664
if lNumberofFiles < 2 then begin
3665
Showmessage('Error: This function is designed to overlay MULTIPLE images. You selected less than two images.');
3668
ProgressBar1.Min := 0;
3669
ProgressBar1.Max :=lNumberofFiles;
3670
ProgressBar1.Position := 0;
3671
getmem(lOverlapBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems);
3672
fillchar(lOverlapBuffer^,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems,0);
3673
for lC:= 1 to lNumberofFiles do begin
3674
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
3675
lExt := UpCaseExt(lFileName);
3676
gBGImg.VOIchanged := false;
3677
if not HdrForm.OpenAndDisplayHdr(lFilename,gMRIcroOverlay[lOverlay]) then exit;
3678
if not OpenImg(gBGImg,gMRIcroOverlay[lOverlay],false,false,false,gBGImg.ResliceOnLoad,false) then exit;
3679
ProgressBar1.Position := lC;
3680
for lPos := 1 to gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems do
3681
if gMRIcroOverlay[lOverlay].ScrnBuffer^[lPos] > 0 then
3682
lOverlapBuffer^[lPos] := lOverlapBuffer^[lPos]+1;
3683
FreeImgMemory(gMRIcroOverlay[lOverlay]);
3684
end; //for each image
3685
//July07 getmem for unaligned buffer getmem(gMRIcroOverlay[lOverlay].ImgBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems);
3686
GetMem(gMRIcroOverlay[lOverlay].ImgBufferUnaligned ,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems + 16); //July072007
3687
//gMRIcroOverlay[lOverlay].ImgBuffer := ByteP($fffffff0 and (integer(gMRIcroOverlay[lOverlay].ImgBufferUnaligned)+15));
3688
gMRIcroOverlay[lOverlay].ImgBuffer := system.align(gMRIcroOverlay[lOverlay].ImgBufferUnaligned, 16);
3689
gMRIcroOverlay[lOverlay].ImgBufferItems := gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems;
3690
for lPos := 1 to gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems do
3691
gMRIcroOverlay[lOverlay].ImgBuffer[lPos] := lOverlapBuffer[lPos];
3692
freemem(lOverlapBuffer);
3693
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],gMRIcroOverlay[lOverlay],0, lNumberofFiles,1,0,0,kNIFTI_INTENT_ESTIMATE,'N'+inttostr(lNumberofFiles) );
3695
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lOverlay],lOverlay);
3696
ProgressBar1.Position := 0;
3697
//SaveAsVOIorNIFTI(gMRIcroOverlay[lOverlay].ImgBuffer,gMRIcroOverlay[lOverlay].ScrnBufferItems,1,false,gMRIcroOverlay[lOverlay].niftiHdr,'sum'+inttostr(lNumberofFiles));
3698
SaveAsVOIorNIFTI(gMRIcroOverlay[lOverlay].ImgBuffer,gMRIcroOverlay[lOverlay].ScrnBufferItems,1,1,false,gMRIcroOverlay[lOverlay].niftiHdr,'sum'+inttostr(lNumberofFiles));
3699
RefreshImagesTimer.Enabled := true;
3700
end;//proc CreateOverlap
3702
procedure TImgForm.Chisquare1Click(Sender: TObject);
3704
lNegativeNumbers: boolean;
3705
lVolVoxels,lPos,lnTotalThreshold,lLoop,lnVoxelsTested:integer;
3706
lMinExp,lChi,lChip,luChi, luChiP: double;
3707
lMaxChi,lMinChi: single;
3708
lBufferAligned,lBufferUnAligned,lBuffer: ByteP;
3711
lTotal,lYes,lNo: array [1..2] of integer;
3712
lMRIcroHdr: TMRIcroHdr;
3714
lVolVoxels := gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems;
3715
if lVolVoxels < 1 then begin
3716
showmessage('Please load a background image (''File''/''Open'') before adding an overlay.');
3719
CloseOverlayImgClick(nil);
3720
for lLoop := 1 to 2 do begin //open two images
3721
if lLoop = 1 then begin
3722
if not OpenDialogExecute(kImgFilter,'Select POSITIVE overlap image',false) then exit
3724
if not OpenDialogExecute(kImgFilter,'Select NEGATIVE overlap image',false) then exit;
3726
lFilename := HdrForm.OpenHdrDlg.Filename;
3727
if not HdrForm.OpenAndDisplayHdr(lFilename,gMRIcroOverlay[lLoop]) then exit;
3728
if not OpenImg(gBGImg,gMRIcroOverlay[lLoop],false,false,true,gBGImg.ResliceOnLoad,false) then exit;
3729
lTotal[lLoop] := round(gMRIcroOverlay[lLoop].NIFTIhdr.glmax);
3730
if (gMRIcroOverlay[lLoop].NIFTIhdr.intent_code <> kNIFTI_INTENT_ESTIMATE) then
3731
showmessage('Warning: header intent_code is not set to ESTIMATE. Compute Chi-squared only with cumulative maps created with this program.');
3732
if (gMRIcroOverlay[lLoop].NIFTIhdr.intent_name[1] <> 'N') then
3733
showmessage('Warning: header intention not N. Compute Chi-squared only with cumulative maps created with this program.');
3735
RefreshImagesTimer.Enabled := true;
3737
if (lVolVoxels<> gMRIcroOverlay[1].ScrnBufferItems)
3738
or (lVolVoxels<> gMRIcroOverlay[2].ScrnBufferItems) then begin
3739
showmessage('Error loading images.');
3742
//next - chi squared
3743
lnTotalThreshold:= ReadIntForm.GetInt('Only test voxels damaged in at least N patients [A+B]', 1,1,(lTotal[1]+lTotal[2]));
3744
GetMem(lBufferUnaligned ,(lVolVoxels *sizeof(single) )+16);
3745
//lBufferAligned := ByteP($fffffff0 and (integer(lBufferUnaligned)+15));
3746
lBufferAligned := system.align(lBufferUnaligned, 16);
3747
l32Buf := SingleP(lBufferAligned);
3748
lnVoxelsTested := 0;
3749
lNegativeNumbers := false;
3752
for lPos := 1 to lVolVoxels do begin
3754
lYes[1] := gMRIcroOverlay[1].ScrnBuffer^[lPos];
3755
lNo[1] := lTotal[1]-lYes[1];
3756
lYes[2] := gMRIcroOverlay[2].ScrnBuffer^[lPos];
3757
lNo[2] := lTotal[2]-lYes[2];
3758
if (lYes[1] < 0) or (lNo[1] < 0) or (lYes[2] < 0) or (lNo[2] < 0) then
3759
lNegativeNumbers := true
3760
else if (lYes[1]+lYes[2]) >= lnTotalThreshold then begin//e.g. at least 30% of all patients
3761
inc(lnVoxelsTested);
3762
//showmessage(inttostr(lYes[1])+'x'+inttostr(lNo[1])+'x'+ inttostr(lYes[2])+'x'+inttostr(lNo[2]) );
3763
Chi2x2 (lYes[1], lNo[1], lYes[2], lNo[2],lMinExp,lChi,lChip,luChi, luChiP);
3764
if (luChi) > lMaxChi then
3766
else if (luChi < lMinChi) then
3768
if (lYes[1]/lTotal[1]) > (lYes[2]/lTotal[2]) then
3769
l32Buf^[lPos] := luChi//100-(100*luChip) //positives more likely than negative
3771
l32Buf^[lPos] := -luChi;//-100+(100*luChip); //negatives more common
3773
end; //for each voxel
3774
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],lMRIcroHdr,lMinChi, lMaxChi,1{df},0,lnVoxelsTested,kNIFTI_INTENT_CHISQ,inttostr(lnVoxelsTested) );
3775
if lNegativeNumbers then
3776
Showmessage('Serious error: some group sizes were negative. This should be impossible with a Chi-Squared.');
3777
//SaveAsVOIorNIFTI(lBufferAligned,lVolVoxels,4,false,lMRIcroHdr.NiftiHdr,'chi'+inttostr(lnTotalThreshold));
3778
SaveAsVOIorNIFTI(lBufferAligned,lVolVoxels,4,1,false,lMRIcroHdr.NiftiHdr,'log10p'+inttostr(lnTotalThreshold));
3779
//next - save log10 p values...
3780
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],lMRIcroHdr,lMinChi, lMaxChi,1{df},0,lnVoxelsTested,NIFTI_INTENT_LOG10PVAL,inttostr(lnVoxelsTested) );
3781
for lPos := 1 to lVolVoxels do
3782
if l32Buf^[lPos] > 0 then
3783
l32Buf^[lPos] := -log(abs(gammq(0.5, 0.5 * l32Buf^[lPos])),10)
3786
SaveAsVOIorNIFTI(lBufferAligned,lVolVoxels,4,1,false,lMRIcroHdr.NiftiHdr,'log10p'+inttostr(lnTotalThreshold));
3787
//next - free float buffer
3788
FreeMem(lBufferUnaligned);
3789
StatusLabel.Caption := 'Voxels tested: '+inttostr(lnVoxelsTested);
3790
//next - subtraction
3791
GetMem(lBuffer ,(lVolVoxels ));
3792
lNegativeNumbers := false;
3793
fillchar(lBuffer^,lVolVoxels,100);
3794
for lPos := 1 to lVolVoxels do begin
3795
lYes[1] := gMRIcroOverlay[1].ScrnBuffer^[lPos];
3796
lNo[1] := lTotal[1]-lYes[1];
3797
lYes[2] := gMRIcroOverlay[2].ScrnBuffer^[lPos];
3798
lNo[2] := lTotal[2]-lYes[2];
3799
if (lYes[1] < 0) or (lNo[1] < 0) or (lYes[2] < 0) or (lNo[2] < 0) then
3800
lNegativeNumbers := true
3801
else if (lYes[1] >0) or (lYes[2] > 0) then begin
3802
lBuffer^[lPos] := round((100* ((lYes[1]/lTotal[1])-(lYes[2]/lTotal[2])))+100);
3804
end; //for each voxel
3805
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],lMRIcroHdr,-100, 100,1,0,0,kNIFTI_INTENT_ESTIMATE,'%'+inttostr(lTotal[1])+':'+inttostr(lTotal[2]) );
3806
lMRIcroHdr.NIFTIhdr.scl_inter:= -100;
3807
if lNegativeNumbers then
3808
Showmessage('Serious error: some group sizes were negative. This should be impossible with a subtraction analysis.');
3809
SaveAsVOIorNIFTI(lBuffer,lVolVoxels,1,1,false,lMRIcroHdr.NiftiHdr,'Sub'+inttostr(lTotal[1])+'_'+inttostr(lTotal[2]));
3811
end; //procedure Chisquare1Click
3813
procedure TImgForm.ROIVOI1Click(Sender: TObject);
3815
lNumberofFiles,lC: integer;
3818
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 1 then begin
3819
showmessage('Please load a background image (''File''/''Open'') before adding an overlay.');
3822
if gBGImg.Resliced then begin
3823
if not HdrForm.OpenAndDisplayHdr(gMRIcroOverlay[kBGOverlayNum].HdrFileName,gMRIcroOverlay[kBGOverlayNum]) then exit;
3824
if not OpenImg(gBGImg,gMRIcroOverlay[0],true,false,false,false,false) then exit;
3826
showmessage('Warning: the currently open background image must have the dimensions (size, space between slices, etc) as the image used when creating the ROIs.');
3827
if gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems > 0 then
3829
if not OpenDialogExecute('MRIcro ROI (.roi)|*.roi','Select MRIcro format ROIs to convert',true) then exit;
3830
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
3831
ProgressBar1.Min := 0;
3832
ProgressBar1.Max :=lNumberofFiles;
3833
ProgressBar1.Position := 0;
3834
for lC:= 1 to lNumberofFiles do begin
3835
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
3836
OpenMRIcroROI (lFileName);
3837
lFilename := changefileextX(lFilename,'.voi');
3838
SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer,gMRIcroOverlay[kVOIOverlayNum].ScrnBufferItems, 1,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
3840
ProgressBar1.Position := lC;
3842
ProgressBar1.Position := 0;
3845
procedure TImgForm.LUTinvertBtnClick(Sender: TObject);
3847
end; //proc LUTdropSelect
3849
procedure TImgForm.LutFromZeroBtnClick(Sender: TObject);
3853
lLayer := ActiveLayer;
3854
gMRIcroOverlay[lLayer].LUTfromZero := LUTfromZeroBtn.down;
3855
LUTdropLoad(lLayer);
3856
RescaleImagesTimer.Enabled := true;
3859
procedure TImgForm.ShowMultisliceClick(Sender: TObject);
3861
(* if gBGImg.XBarClr = TColor(gMRIcroOverlay[kBGOverlayNum].LUTinvisible) then
3862
MultiSliceForm.MultiImage.canvas.font.Color := clBlack//clWhite;//gLUT[lClr].rgbRed+(gLUT[lClr].rgbGreen shl 8)+(gLUT[lClr].rgbBlue shl 16);
3864
MultiSliceForm.MultiImage.canvas.font.Color := gBGImg.XBarClr;*)
3865
MultiSliceForm.Show;
3866
//MultiSliceForm.BringToFront;
3869
function RawBGIntensity(lPos: integer): single;
3875
if (lPos > gMRIcroOverlay[kBGOverlayNum].ImgBufferItems) or (lPos < 1) then exit;
3876
if (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP = 4) then begin
3877
l32Buf := SingleP(gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
3878
result := l32Buf^[lPos];
3879
end else if (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP = 2) then begin
3880
l16Buf := SmallIntP(gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
3881
result := l16Buf^[lPos];
3882
end else if gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP = 1 then
3883
result := gMRIcroOverlay[kBGOverlayNum].ImgBuffer^[lPos]
3885
showmessage('Unknown Background Buffer Bytes Per Pixel');
3890
procedure DescribeVOIonLabels (lOverlayNum: integer);
3892
lShowfilename: boolean = true;
3893
lLocalMax,lLocalSum : HistoDoubleRA;
3898
lXmm,lYmm,lZmm: single;
3899
lHisto,lRegionVol,lLocalMaxPos: HistoRA;
3900
lInc,lRegion: Integer;
3903
lLabelStr20 : Array[0..kHistoBins] of kstr20;
3905
lInten := 0;//just to hide compiler hint...
3906
if (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP = 2) and ('ratlas.nii.gz' = (extractfilename( gMRIcroOverlay[kBGOverlayNum].HdrFileName))) then begin
3907
//DescribeVOIonLabelsRAT(lOverlayNum,lShowFilename);
3908
Showmessage('Please use Windows version.');
3911
if (gMRIcroOverlay[lOverlayNum].ScrnBufferItems <> gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems) or (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP <> 1) or (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 2) then
3913
TextForm.Memo1.Lines.add(' Custom Region Analysis');
3914
TextForm.Memo1.Lines.add(' For Speculative Brodmann Map: 0=not cortical and 48=no Brodmann label');
3915
lVOI := IsVOIROIExt(gMRIcroOverlay[lOverlayNum].HdrFileName);
3916
if (not lVOI) and (lOverlayNum = kVOIOverlayNum) then
3918
//next describe format
3919
if lShowfilename then
3920
lLabelStr := ' Filename,'
3923
if lVOI then //intensity min/max position are not important
3924
TextForm.Memo1.Lines.add(lLabelStr+'Area,N>0,%N>0')
3926
TextForm.Memo1.Lines.add(lLabelStr+'Area,N>0,%N>0,Sum>0,Mean>0,Max,MaxX,MaxY,MaxZ');
3928
if lShowFilename then
3929
lLabelStr := gMRIcroOverlay[lOverlayNum].HdrFileName+','
3932
for lInc := 0 to kHistoBins do begin
3934
lLocalMax[lInc] := 0;
3935
lLocalSum[lInc] := 0;
3936
lRegionVol[lInc] := 0;
3937
if (gMRIcroOverlay[kBGOverlayNum].UsesCustomPalette) then
3938
lLabelStr20[lInc] := gBGImg.LabelStr20[lInc]
3940
lLabelStr20[lInc] := inttostr(lInc);
3942
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do
3943
if gMRIcroOverlay[lOverlayNum].ScrnBuffer^[lInc] > 0 then
3944
inc(lHisto[gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc]]);
3946
l32Buf := SingleP(gMRIcroOverlay[lOverlayNum].ImgBuffer );
3947
l16Buf := SmallIntP(gMRIcroOverlay[lOverlayNum].ImgBuffer );
3948
//NEXT if..else July07 - ROIs only use screen buffer, not imgbuffer...
3949
if gMRIcroOverlay[lOverlayNum].ScrnBufferItems = gMRIcroOverlay[lOverlayNum].ImgBufferItems then
3950
l8Buf := gMRIcroOverlay[lOverlayNum].ImgBuffer
3952
l8Buf := gMRIcroOverlay[lOverlayNum].ScrnBuffer;
3953
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do begin
3954
if (gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 4) then
3955
lInten := l32Buf^[lInc]
3956
else if (gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 2) then
3957
lInten := l16Buf^[lInc]
3958
else if gMRIcroOverlay[lOverlayNum].ImgBufferBPP = 1 then
3959
lInten := l8Buf^[lInc];//July07
3960
lRegion := gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc];
3962
lLocalSum[lRegion] := lLocalSum[lRegion]+lInten;
3963
if lInten > lLocalMax[lRegion] then begin
3964
lLocalMax[lRegion] := lInten;//intensity
3965
lLocalMaxPos[lRegion] := lInc;//location
3967
inc(lRegionVol[lRegion]);
3969
for lInc := 0 to kHistoBins do begin
3970
if (not lVOI) and (lLocalMax[lInc] > 0) then begin
3971
lLocalMax[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[lOverlayNum],lLocalMax[lInc]);
3972
lLocalSum[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[lOverlayNum],lLocalSum[lInc]);
3973
ImgPosToMM(lLocalMaxPos[lInc], lXmm,lYmm,lZmm);
3974
TextForm.Memo1.Lines.Add(lLabelStr+ lLabelStr20[lInc] + ', ' + inttostr(lHisto[lInc])+','+floattostr( lHisto[lInc]/lRegionVol[lInc])
3975
+','+floattostr( lLocalSum[lInc])+','+floattostr( lLocalSum[lInc]/lRegionVol[lInc]) //Sum>0, mean>0
3976
+', ' + floattostr(lLocalMax[lInc])+','+floattostr(lXmm)+','+floattostr(lYmm)+','+floattostr(lZmm) );
3977
end else if (lHisto[lInc] > 0) {necessarily also and (lRegionVol[lInc] > 0)} then
3978
TextForm.Memo1.Lines.Add(lLabelStr+ lLabelStr20[lInc] + ', ' + inttostr(lHisto[lInc])+','+floattostr( lHisto[lInc]/lRegionVol[lInc])) ;
3982
(*procedure DescribeVOIonLabels (lOverlayNum: integer);
3987
if (gMRIcroOverlay[lOverlayNum].ScrnBufferItems <> gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems) or (gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP <> 1) or (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < 2) then
3989
TextForm.Memo1.Lines.Add('');
3990
TextForm.Memo1.Lines.add('Custom Region Analysis');
3991
TextForm.Memo1.Lines.add(' For Speculative Brodmann Map, 0=not cortical, 48=no Brodmann label');
3992
for lInc := 0 to 255 do
3994
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do
3995
if gMRIcroOverlay[lOverlayNum].ScrnBuffer^[lInc] > 0 then
3996
inc(lHisto[gMRIcroOverlay[kBGOverlayNum].ScrnBuffer^[lInc]]);
3997
for lInc := 0 to 255 do begin
3998
if lHisto[lInc] > 0 then
3999
TextForm.Memo1.Lines.Add( gBGImg.LabelStr20[lInc] + ', ' + inttostr(lHisto[lInc]) );
4004
procedure TImgForm.DescriptiveMenuItemClick(Sender: TObject);
4006
lROIVol: array [1..3] of integer;
4007
lInc,lOverlayNum,lImgSz: integer;
4008
lCenterOfMass,lROISum,lROISumSqr,lROImin,lROImax:array [1..3] of double;
4009
lCC,lVal,lSD,lROImean: double;
4011
procedure AddVal( lRA: integer);
4014
lROISum[lRA] := lROISum[lRA]+lVal;
4015
lROISumSqr[lRA] := lROISumSqr[lRA] + sqr(lVal);
4016
if lVal > lROImax[lRA] then
4017
lROImax[lRA] := lVal;
4018
if lVal < lROImin[lRA] then
4019
lROImin[lRA] := lVal;
4023
for lOverlayNum := 1 to knMaxOverlay do
4024
if gMRIcroOverlay[lOverlayNum].ScrnBufferItems > lImgSz then
4025
lImgSz := gMRIcroOverlay[lOverlayNum].ScrnBufferItems;
4026
if (lImgSz < 1) or (gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems < lImgSz) then begin
4027
Showmessage('You need to create or load an overlay (Overlay/Open or Draw/OpenVOI) to get overlay statistics.');
4030
TextForm.Memo1.Lines.Clear;
4031
for lOverlayNum := 1 to knMaxOverlay do begin
4032
if gMRIcroOverlay[lOverlayNum].ScrnBufferItems = gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems then begin
4033
for lInc := 1 to 3 do begin
4036
lROISumSqr[lInc] := 0;
4037
lROImin[lInc] := maxint;
4038
lROImax[lInc] := -maxint;
4041
for lInc := 1 to gMRIcroOverlay[lOverlayNum].ScrnBufferItems do begin
4042
if gMRIcroOverlay[lOverlayNum].ScrnBuffer^[lInc] > 0 then begin
4043
lVal := RawBGIntensity(lInc);
4050
end; //for each voxel
4051
//next - compute StDev
4052
//compute descriptives for each set of values
4053
TextForm.Memo1.Lines.Add('Overlay '+gMRIcroOverlay[lOverlayNum].HdrFileName);
4054
if CenterOfMass (lOverlayNum, lCenterOfMass[1],lCenterOfMass[2],lCenterOfMass[3]) > 0 then
4055
TextForm.Memo1.Lines.Add(' Center of mass XYZ '+RealToStr(lCenterOfMass[1],2)+'x'+RealToStr(lCenterOfMass[2],2)+'x'+RealToStr(lCenterOfMass[3],2));
4056
for lInc := 1 to 3 do begin
4057
if lROIVol[lInc] > 1 then begin
4058
lSD := (lROISumSqr[lInc] - ((Sqr(lROISum[lInc]))/lROIVol[lInc]));
4060
lSD := Sqrt ( lSD/(lROIVol[lInc]-1))
4066
if lROIVol[lInc] > 0 then
4067
lROImean := lROISum[lInc]/lROIVol[lInc]
4070
//next - calibrate values
4071
lROImin[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROImin[lInc]);
4072
lROIMean := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROIMean);
4073
lROImax[lInc] := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lROImax[lInc]);
4074
lSD := Raw2ScaledIntensity (gMRIcroOverlay[kBGOverlayNum],lSD);
4075
lcc := ((lROIVol[lInc]/1000)*gBGImg.ScrnMM[1]*gBGImg.ScrnMM[2]*gBGImg.ScrnMM[3]);
4077
3: lStr := 'VOI >0 ';
4078
2: lStr := 'VOI <>0 ';
4079
else lStr := 'VOI ';
4081
lStr := lStr+' n=min/mean/max=SD: '+inttostr(round(lROIVol[lInc]))+'['+RealToStr(lCC,2)+'cc]='+RealToStr(lROIMin[lInc],4)+'/'+realToStr(lROIMean,4)+'/'+realToStr(lROIMax[lInc],4)+'='+realtostr(lSD,4);
4082
TextForm.Memo1.Lines.Add(lStr);
4084
if gMRIcroOverlay[kBGOverlayNum].UsesCustomPalette then
4085
DescribeVOIonLabels(lOverlayNum);
4086
TextForm.Memo1.Lines.Add('');
4087
end; //overlaynum loaded
4088
end; //for each overlay
4092
procedure TImgForm.FormResize(Sender: TObject);
4094
if not ImgForm.visible then
4096
RefreshImagesTimer.enabled := true;
4099
function ParamStrFilename (var lParamPos: integer): string;
4105
if (ParamCount < lParamPos) then exit;
4108
if I = lParamPos then
4111
lStr := lStr +' '+ ParamStr(I);
4113
until (I>ParamCount) or (fileexistsex(lStr));
4115
if fileexistsex(lStr) then
4121
procedure TImgForm.FormShow(Sender: TObject);
4124
lMaximize,lRender,lMultislice : boolean;
4126
I,lError,lOverlayNum,lInc,lLUT: integer;
4128
procedure ReadCmdVal;//nested
4131
lStr := ParamStr(I);
4133
lStr := string(StrUpper(PChar(lStr))) ;
4136
lStr := UpCase(lStr); //unix file names are case specific /EXAMPLE/ATTENTION.NII <> /Example/Attention
4139
end; //nested ReadCmdVal
4141
//gBGIMg.SaveDefaultIni := true;
4143
//Darwin starts passing a strange paramstr....
4144
//ImgForm.OpenTemplateMRU(nil);
4145
//RefreshImagesTimer.enabled := true;
4146
//with Darwin, opening a file can interfere with opening by association...
4148
//ResliceImg ('/Users/crlab/Documents/example_func.nii.gz','/Users/crlab/Documents/v1x.voi','/Users/crlab/Documents/example_func2standard.mat','/Users/crlab/Documents/z1x.nii.gz');
4151
if (ParamCount < 1) then begin
4152
ImgForm.OpenTemplateMRU(nil);
4153
RefreshImagesTimer.enabled := true;
4154
//Graph4DForm.show;//abba
4160
lMultislice := false;
4163
lStr := ParamStrFilename(I);
4165
OpenAndDisplayImg(lStr,True)
4166
else begin //no requested image
4167
OpenTemplateMRU(nil);
4171
//ShowMultisliceClick(nil);
4172
if I >= ParamCount then exit;
4173
gBGIMg.SaveDefaultIni := false; //do not store changes loaded by script
4182
lStr := lStr +' '+ ParamStr(I)
4184
lStr := ParamStr(I);
4186
if (length(lStr)>1) and (lStr[1] = '-') then begin //special command
4187
lCommandChar := UpCase(lStr[2]);
4188
case lCommandChar of
4189
'B': begin //background transparency
4191
Val(lStr,lSingle,lError);
4193
gBGImg.BGTransPct := round(lSingle);
4194
SetSubmenuWithTag(BGTransPctMenu, gBGImg.BGTransPct);
4196
'C': begin //color look up table
4198
if (Length(lStr)>1) then begin
4199
if lStr[1] = '-' then begin //LUT index number
4200
Val(lStr,lSingle,lError);
4202
lLUT := abs(round(lSingle))
4206
lStr := ParseFileName(ExtractFileName(lStr));
4208
lStr := UpCase(lStr);
4211
for lInc := 1 to (LUTdrop.Items.Count-1) do
4212
if lStr = string(StrUpper(PChar(LUTdrop.Items.Strings[lINc]))) then
4214
end; //else text LUTname
4215
if lLUT >= 0 then begin
4216
gMRIcroOverlay[lOverlayNum].LUTindex := lLUT;
4217
LUTdropLoad(lOverlayNum);
4219
end; //str length > 1
4221
'D': gBGIMg.SaveDefaultIni := true;
4222
'F': gBGImg.ResliceOnLoad := false; //turn off reslicing... loads files flat
4225
Val(lStr,lSingle,lError);
4227
gMRIcroOverlay[lOverlayNum].WindowScaledMax := (lSingle);
4229
'L': begin //Low intensity scale
4231
Val(lStr,lSingle,lError);
4233
gMRIcroOverlay[lOverlayNum].WindowScaledMin := (lSingle);
4235
'M': begin //multislice
4236
lMultislice := true;
4238
if (lStr <> '') and (lStr <> '-')and (FileexistsEx(lStr)) and (lOverlayNum < (knMaxOverlay-1)) then
4239
gMultiSliceStartupFilename := (lStr);
4244
//Showmessage('o'+lStr);
4245
if (lStr <> '') and (FileexistsEx(lStr)) and (lOverlayNum < (knMaxOverlay-1)) then begin
4246
//Showmessage('oexists'+lStr);
4248
OverlayOpenCore (lStr,lOverlayNum);
4252
lRender := true;//Render
4254
if (lStr <> '') and (lStr <> '-')and (FileexistsEx(lStr)) and (lOverlayNum < (knMaxOverlay-1)) then
4255
gRenderStartupFilename := (lStr);
4259
Val(lStr,lSingle,lError);
4260
if lError = 0 then begin
4261
if odd(round(lSingle)) then begin
4262
gBGImg.StretchQuality := sqHigh;
4263
Menu2DSmooth.checked := true;
4265
gBGImg.StretchQuality := sqLow;
4266
Menu2DSmooth.checked := false;
4269
gBGIMg.OverlaySmooth := true
4271
gBGIMg.OverlaySmooth := false;
4272
OverlaySmoothMenu.Checked := gBGIMg.OverlaySmooth;
4275
'T': begin //overlay transparency
4277
Val(lStr,lSingle,lError);
4279
gBGImg.OverlayTransPct := round(lSingle);
4280
SetSubmenuWithTag(OverlayTransPctMenu, gBGImg.OverlayTransPct);
4282
'V': begin //open voi
4284
if (lStr <> '') and (FileexistsEx(lStr)) then
4287
'X': lMaximize := true; //open maximized
4288
'Z': gMRIcroOverlay[lOverlayNum].LUTfromZero := true;
4291
end; //special command
4292
until (I=ParamCount) or (fileexists(lStr)) {or (gAbort)};
4293
until I >= ParamCount;
4294
LayerDropSelect(nil);
4295
for lInc := 0 to lOverlayNum do
4296
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lInc],lINc);
4299
ShowMultisliceClick(nil);
4301
ShowRenderClick(nil);
4302
if lMaximize then begin
4303
ImgForm.WindowState := wsMaximized;
4304
RefreshImagesTimer.enabled := true;
4309
procedure TImgForm.FlipLRmenuClick(Sender: TObject);
4314
(sender as TMenuItem).checked := not (sender as TMenuItem).checked;
4315
gBGImg.Mirror := (sender as TMenuItem).checked ;
4316
gBGImg.VOImirrored := true;
4317
for lC := 0 to knMaxOverlay do
4318
if gMRIcroOverlay[lC].ScrnBufferItems > 0 then
4319
RescaleImgIntensity(gBGImg,gMRIcroOverlay[lC],lC);
4320
RefreshImagesTimer.Enabled := true;
4321
if gBGImg.Mirror then
4322
lStr := 'radiological [right on left side]'
4324
lStr := 'neurological [left on left side]';
4325
showmessage('Warning: left-right flips can be confusing. From now on, this software will attempt to show NIfTI images in '+lStr+' orientation.');
4326
if MultiSliceForm.Visible then
4327
MultiSliceForm.CreateMultiSlice;
4330
procedure TImgForm.Menu2DSmoothClick(Sender: TObject);
4332
if Sender <> nil then
4333
(sender as TMenuItem).checked := not (sender as TMenuItem).checked;
4334
if Menu2DSmooth.checked then
4335
gBGImg.StretchQuality := sqHigh
4337
gBGImg.StretchQuality := sqLow;
4338
RefreshImagesTimer.Enabled := true;
4341
procedure TImgForm.VALclick(Sender: TObject);
4343
//ComputeValFile( (sender as Tmenuitem).tag);
4346
procedure TImgForm.VOI2NIIClick(Sender: TObject);
4348
lNumberofFiles,lC: integer;
4351
CloseImagesClick(nil);
4352
if not OpenDialogExecute('VOI Drawings (.VOI)|*.VOI','Select VOI format images to convert',true) then exit;
4353
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
4354
ProgressBar1.Min := 0;
4355
ProgressBar1.Max :=lNumberofFiles;
4356
ProgressBar1.Position := 0;
4357
for lC:= 1 to lNumberofFiles do begin
4358
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
4359
OpenAndDisplayImg(lFilename,True);
4360
lFilename := changefileextx(lFilename,'.nii');
4361
//SaveAsVOIorNIFTIcore (lFilename, lByteP, lVoxels, 1, gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
4362
SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kBGOverlayNum].ScrnBuffer,gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems, 1,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
4364
ProgressBar1.Position := lC;
4366
ProgressBar1.Position := 0;
4369
procedure TImgForm.TtoP1Click(Sender: TObject);
4371
lBufferAligned,lBufferUnAligned: ByteP;
4372
l32Buf,l32BufSrc : SingleP;
4373
l16BufSrc : SmallIntP;
4374
lSlope,lIntercept: single;
4375
lMRIcroHdr: TMRIcroHdr;
4376
lVolVoxels,lPos: integer;
4378
//alfa - currently open image
4379
lVolVoxels := gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems;
4380
if lVolVoxels < 1 then begin
4381
showmessage('Please load a background image (''File''/''Open'') before adding an overlay.');
4384
GetMem(lBufferUnaligned ,(lVolVoxels *sizeof(single) )+16);
4385
//lBufferAligned := ByteP($fffffff0 and (integer(lBufferUnaligned)+15));
4386
lBufferAligned := system.align(lBufferUnaligned, 16);
4387
l32Buf := SingleP(lBufferAligned);
4389
case gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP of
4391
l32BufSrc := SingleP(gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
4392
for lPos := 1 to lVolVoxels do
4393
l32Buf^[lPos] := l32BufSrc^[lPos];
4396
l16BufSrc := SmallIntP(gMRIcroOverlay[kBGOverlayNum].ImgBuffer );
4397
for lPos := 1 to lVolVoxels do
4398
l32Buf^[lPos] := l16BufSrc^[lPos];
4401
for lPos := 1 to lVolVoxels do
4402
l32Buf^[lPos] := gMRIcroOverlay[kBGOverlayNum].ImgBuffer^[lPos];
4405
showmessage('unknown datatype');
4408
//next calibrate values
4409
lSlope := gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.scl_slope;
4410
lIntercept := gMRIcroOverlay[kBGOverlayNum].NIFTIhdr.scl_inter;
4411
if (lSlope=0) or ((lSlope=1) and (lIntercept=0)) then
4414
for lPos := 1 to lVolVoxels do
4415
l32Buf^[lPos] := (l32Buf^[lPos] * lSlope)+lIntercept;
4417
//next - save log10 p values...
4418
MakeStatHdr (gMRIcroOverlay[kBGOverlayNum],lMRIcroHdr,0, 255,1{df},0,666,NIFTI_INTENT_LOG10PVAL,inttostr(666) );
4419
for lPos := 1 to lVolVoxels do
4420
if l32Buf^[lPos] > 0 then
4421
l32Buf^[lPos] := -log(abs(pTdistr(42,l32Buf^[lPos])),10)
4424
SaveAsVOIorNIFTI(lBufferAligned,lVolVoxels,4,1,false,lMRIcroHdr.NiftiHdr,'log10p'+inttostr(666));
4425
//next - free float buffer
4426
FreeMem(lBufferUnaligned);
4429
procedure TImgForm.DesignVALClick(Sender: TObject);
4434
procedure TImgForm.Up1Click(Sender: TObject);
4435
var lVolVox,lPos,lShift: integer;
4437
if gMRIcroOverlay[kBGOverlayNum].ScrnBufferItems=0 then begin
4438
showmessage('You must have open a background image in order to apply an intensity filter (use File/Open).');
4441
if not IsVOIOpen then begin
4442
ShowMessage('You have not created or opened a region of interest.');
4445
CreateUndoVol;//create gBGImg.VOIUndoVol
4446
Move(gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer^,gBGImg.VOIUndoVol^,gBGImg.VOIUndoVolItems);
4447
lVolVox := gBGImg.ScrnDim[1]* gBGImg.ScrnDim[2]*gBGImg.ScrnDim[3];
4448
case (Sender as TMenuItem).tag of
4451
2: lShift := gBGImg.ScrnDim[1];
4452
3: lShift := -gBGImg.ScrnDim[1];
4453
4: lShift := gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2];
4454
5: lShift := -gBGImg.ScrnDim[1]*gBGImg.ScrnDim[2];
4456
if lShift > 0 then begin
4457
for lPos := 1 to (lVolVox-lShift) do
4458
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer[lPos] := gBGImg.VOIUndoVol[lPos+lShift];
4460
for lPos := (1+abs(lShift)) to lVolVox do
4461
gMRIcroOverlay[kVOIOverlayNum].ScrnBuffer[lPos] := gBGImg.VOIUndoVol[lPos+lShift];
4463
gBGImg.VOIchanged := true;
4464
ImgForm.ProgressBar1.Position := 0;
4465
ImgForm.RefreshImagesTimer.Enabled := true;
4469
procedure TImgForm.FormDestroy(Sender: TObject);
4472
FormClose(nil); //OSX does not send a FormClose Event if you choose the Application/Quit option
4477
procedure TImgForm.YokeMenuClick(Sender: TObject);
4479
(sender as TMenuItem).checked := not (sender as TMenuItem).checked;
4480
gYoke := (sender as TMenuItem).checked ;
4481
YokeTimer.Enabled := gYoke;
4484
procedure TImgForm.About1Click(Sender: TObject);
4488
//for lLoop := 1 to 4 do
4489
// RefreshImagesTImer.enabled := true;
4491
//290 347 fx(TriplePanel.Width,TriplePanel.Width);
4492
AboutForm.ThreadLabel.Caption := ' '+inttostr(gnCPUThreads)+' threads';
4493
AboutForm.Showmodal;
4495
procedure TImgForm.LayerDropChange(Sender: TObject);
4498
LayerDropSelect(nil);
4502
procedure TImgForm.LUTdropChange(Sender: TObject);
4509
procedure TImgForm.AdjustimagessoVOIintensityiszero1Click(Sender: TObject);
4511
BatchChangeInterceptSoVOIEqualsZero;
4514
procedure TImgForm.MirrorNII1Click(Sender: TObject);
4516
lNumberofFiles,lC: integer;
4519
Showmessage('WARNING: This will flip the images in the Left-Right dimension: this has serious consequences');
4520
CloseImagesClick(nil);
4521
if not OpenDialogExecute(kImgFilter,'Select NIfTI format images to convert',true) then exit;
4522
lNumberofFiles:= HdrForm.OpenHdrDlg.Files.Count;
4523
ProgressBar1.Min := 0;
4524
ProgressBar1.Max :=lNumberofFiles;
4525
ProgressBar1.Position := 0;
4526
for lC:= 1 to lNumberofFiles do begin
4527
lFilename := HdrForm.OpenHdrDlg.Files[lC-1];
4528
ImgForm.OpenAndDisplayImg(lFilename,True);
4529
lFilename := changefileextX(lFilename,'lr.nii.gz');
4531
//showmessage(lFilename);
4532
if MirrorImgBuffer (gMRIcroOverlay[kBGOverlayNum] ) then begin
4533
//showmessage(lFilename);
4534
SaveAsVOIorNIFTIcore (lFilename, gMRIcroOverlay[kBGOverlayNum].ImgBuffer,gMRIcroOverlay[kBGOverlayNum].ImgBufferItems,gMRIcroOverlay[kBGOverlayNum].ImgBufferBPP,1,gMRIcroOverlay[kBGOverlayNum].NiftiHdr);
4537
ProgressBar1.Position := lC;
4539
ProgressBar1.Position := 0;
4543
procedure TImgForm.ZoomDropChange(Sender: TObject);
4546
ZoomDropSelect(nil);
4552
procedure TImgForm.ResizeControlPanel (lRows: integer);
4554
if lRows = 2 then begin
4555
ControlPanel.Tag := 2;
4556
LayerPanel.Top := 36;
4557
LayerPanel.Left := 1;
4559
ControlPanel.Height := 72;
4561
HideROIBtn.left := 307;
4562
XBarBtn.Left := 307+29;
4563
ToolPanel.Left := 307+61;
4565
ControlPanel.Tag := 1;
4566
LayerPanel.Top := 1;
4567
LayerPanel.Left := 307;
4568
HideROIBtn.left := 809;
4569
XBarBtn.Left := 809+29;
4570
ToolPanel.Left := 809+61;
4571
ControlPanel.Height := 40;
4575
procedure TImgForm.ControlPanelDblClick(Sender: TObject);
4577
if ControlPanel.Tag = 1 then
4578
ResizeControlPanel(2)
4580
ResizeControlPanel(1);
4581
ImgForm.RefreshImagesTimer.enabled := true;
4584
procedure TImgForm.DefaultControlPanel;
4586
if gBGImg.SingleRow then begin
4587
ResizeControlPanel(1);
4588
ImgForm.Width := 1025;
4589
ImgForm.Height := 469;
4591
ResizeControlPanel(2);
4592
ImgForm.Width := 524;
4593
ImgForm.Height := 640;
4599
{$I nifti_img_view.lrs}
4601
for gMouseDownY := 0 to knMaxOverlay do
4602
gMRIcroOverlay[gMouseDownY].index := gMouseDownY; //RGB