1
by Michael Hanke
Import upstream version 0.20100725.1~dfsg.1 |
1 |
unit MultiSlice; |
2 |
interface
|
|
3 |
||
4 |
uses
|
|
5 |
{$IFNDEF Unix} Windows,wgraphics, |
|
6 |
{$ELSE}
|
|
7 |
//not used by Darwin... RGBGraphics,rgbroutines,
|
|
8 |
{$ENDIF}
|
|
9 |
LResources,LCLType,SysUtils, Classes, Graphics, Controls, Forms, Dialogs, |
|
10 |
ExtCtrls,nifti_img,define_types,nifti_img_view, |
|
11 |
StdCtrls,GraphicsMathLibrary, Menus,ClipBrd,IniFiles,userdir; |
|
12 |
const
|
|
13 |
kMaxMultiSlice = 24; |
|
14 |
type
|
|
15 |
TMultiSlice = record |
|
16 |
Orient,nSlices,OverslicePct: integer; |
|
17 |
OrthoView,SliceLabel: boolean; |
|
18 |
SliceList: array [1..kMaxMultiSlice] of integer; |
|
19 |
end;//TMultiSlice |
|
20 |
||
21 |
{ TMultiSliceForm }
|
|
22 |
||
23 |
TMultiSliceForm = class(TForm) |
|
24 |
MainMenu1: TMainMenu; |
|
25 |
File1: TMenuItem; |
|
26 |
Closewindow1: TMenuItem; |
|
27 |
Saveasbitmap1: TMenuItem; |
|
28 |
Edit1: TMenuItem; |
|
29 |
Copy1: TMenuItem; |
|
30 |
MultiPanel: TScrollBox; |
|
31 |
MultiImage: TImage; |
|
32 |
View1: TMenuItem; |
|
33 |
OrientMenu: TMenuItem; |
|
34 |
Axial1: TMenuItem; |
|
35 |
Sagittal1: TMenuItem; |
|
36 |
Coronal1: TMenuItem; |
|
37 |
Orthoview: TMenuItem; |
|
38 |
Slices1: TMenuItem; |
|
39 |
Savesettings1: TMenuItem; |
|
40 |
Settings1: TMenuItem; |
|
41 |
MultiSaveDialog: TSaveDialog; |
|
42 |
SliceLabelCheck: TMenuItem; |
|
43 |
OversliceMenu: TMenuItem; |
|
44 |
N501: TMenuItem; |
|
45 |
N331: TMenuItem; |
|
46 |
N201: TMenuItem; |
|
47 |
N01: TMenuItem; |
|
48 |
N202: TMenuItem; |
|
49 |
N351: TMenuItem; |
|
50 |
N502: TMenuItem; |
|
51 |
procedure Copy1Click(Sender: TObject); |
|
52 |
procedure MenuItem1Click(Sender: TObject); |
|
53 |
procedure Saveasbitmap1Click(Sender: TObject); |
|
54 |
procedure OrientClick(Sender: TObject); |
|
55 |
procedure FormShow(Sender: TObject); |
|
56 |
procedure CreateMultiAx; |
|
57 |
procedure CreateMultiCor; |
|
58 |
procedure CreateMultiSag; |
|
59 |
procedure CreateMultiSlice; |
|
60 |
procedure OrthoviewClick(Sender: TObject); |
|
61 |
procedure Settings1Click(Sender: TObject); |
|
62 |
procedure Slices1Click(Sender: TObject); |
|
63 |
procedure Closewindow1Click(Sender: TObject); |
|
64 |
procedure FormCreate(Sender: TObject); |
|
65 |
procedure UpdateMultiSliceDisplay; |
|
66 |
procedure OpenMultiMRU(Sender:TObject); |
|
67 |
procedure UpdateMultiSliceMRU; |
|
68 |
{$IFNDEF FPC}
|
|
69 |
procedure FormClose(Sender: TObject; var Action: TCloseAction); |
|
70 |
{$ELSE}
|
|
71 |
procedure FormClose(Sender: TObject); |
|
72 |
||
73 |
{$ENDIF}
|
|
74 |
procedure Savesettings1Click(Sender: TObject); |
|
75 |
procedure SliceLabelCheckClick(Sender: TObject); |
|
76 |
procedure OverlsiceClick(Sender: TObject); |
|
77 |
private
|
|
78 |
{ Private declarations }
|
|
79 |
public
|
|
80 |
{ Public declarations }
|
|
81 |
end; |
|
82 |
||
83 |
var
|
|
84 |
MultiSliceForm: TMultiSliceForm; |
|
85 |
gMulti:TMultiSlice; |
|
86 |
gMultiSliceDir,gMultiSliceStartupFilename,gMultiSliceDefaultsFilename:string; |
|
87 |
{$IFDEF FPC}
|
|
88 |
gMultiBuff: RGBQuadp; |
|
89 |
gMultiWid,gMultiHt: Integer; |
|
90 |
gMultiXCenterRA: array [1..kMaxMultiSlice] of integer; |
|
91 |
{$ENDIF}
|
|
92 |
implementation
|
|
93 |
||
94 |
{$IFNDEF FPC}
|
|
95 |
{$R *.DFM}
|
|
96 |
{$ENDIF}
|
|
97 |
||
98 |
function MultiSliceNum2String: string; |
|
99 |
var
|
|
100 |
lSlice: integer; |
|
101 |
begin
|
|
102 |
if gMulti.nSlices = 0 then begin |
|
103 |
gMulti.nSlices := 1; |
|
104 |
gMulti.SliceList[1] := 1; |
|
105 |
end; |
|
106 |
result := ''; |
|
107 |
for lSlice := 1 to gMulti.nSlices do begin |
|
108 |
result := result+inttostr(gMulti.SliceList[lSlice]); |
|
109 |
if lSlice < gMulti.nSlices then |
|
110 |
result := result+','; |
|
111 |
end; //for each slice |
|
112 |
end; |
|
113 |
||
114 |
procedure MultiSliceString2Num (var lStr: string); |
|
115 |
var
|
|
116 |
lSliceStr: string; |
|
117 |
lStrPos,lStrLen,lSlice: integer; |
|
118 |
begin
|
|
119 |
//showmessage(lStr);
|
|
120 |
lStrLen := length(lStr); |
|
121 |
if lStrLen < 1 then exit; |
|
122 |
lSlice := 0; |
|
123 |
lSliceStr := ''; |
|
124 |
for lStrPos := 1 to lStrLen do begin |
|
125 |
if lStr[lStrPos] in ['0'..'9'] then |
|
126 |
lSliceStr := lSliceStr+lStr[lStrPos]; |
|
127 |
if ((not (lStr[lStrPos] in ['0'..'9'])) or (lStrPos=lStrLen)) and (lSliceStr<>'') then begin |
|
128 |
inc(lSlice); |
|
129 |
if lSlice <= kMaxMultiSlice then |
|
130 |
gMulti.SliceList[lSlice] := strtoint(lSliceStr); |
|
131 |
lSliceStr := ''; |
|
132 |
end; //if white space or eoln |
|
133 |
end; //for lStrPos |
|
134 |
gMulti.nSlices := lSlice; |
|
135 |
if lSlice > kMaxMultiSlice then begin |
|
136 |
showmessage('Warning: maximum number of slices is '+inttostr(kMaxMultiSlice)); |
|
137 |
gMulti.nSlices := kMaxMultiSlice; |
|
138 |
end; |
|
139 |
end; |
|
140 |
||
141 |
procedure WriteMultiSliceIniFile (lFilename: string); |
|
142 |
var
|
|
143 |
lIniFile: TIniFile; |
|
144 |
begin
|
|
145 |
if DiskFreeEx(lFilename) < 1 then |
|
146 |
exit; |
|
147 |
if not DirectoryExists(extractfiledir(lFilename)) then begin |
|
148 |
mkDir(extractfiledir(lFilename)); |
|
149 |
end; |
|
150 |
lIniFile := TIniFile.Create(lFilename); |
|
151 |
//Slice Index
|
|
152 |
lIniFile.WriteString('STR', 'Slices', MultiSliceNum2String); |
|
153 |
//Booleans
|
|
154 |
lIniFile.WriteString('BOOL', 'OrthoView',Bool2Char( gMulti.OrthoView)); |
|
155 |
lIniFile.WriteString('BOOL', 'SliceLabel',Bool2Char( gMulti.SliceLabel)); |
|
156 |
//Integers LicenseID
|
|
157 |
lIniFile.WriteString('INT', 'Orient',IntToStr(gMulti.Orient)); |
|
158 |
lIniFile.WriteString('INT', 'OverslicePct',IntToStr(gMulti.OverslicePct)); |
|
159 |
lIniFile.Free; |
|
160 |
end; |
|
161 |
||
162 |
procedure ReadMultiSliceIniFile (lFilename: string); |
|
163 |
var
|
|
164 |
lStr: string; |
|
165 |
lIniFile: TIniFile; |
|
166 |
begin
|
|
167 |
if not FileexistsEx(lFilename) then begin |
|
168 |
exit; |
|
169 |
end; |
|
170 |
lIniFile := TIniFile.Create(lFilename); |
|
171 |
lStr := lIniFile.ReadString('STR', 'Slices', '10,20,30');//file0 - last file viewed |
|
172 |
MultiSliceString2Num(lStr); |
|
173 |
gMulti.OrthoView := IniBool(lIniFile,'OrthoView',gMulti.OrthoView); |
|
174 |
gMulti.SliceLabel := IniBool(lIniFile,'SliceLabel',gMulti.SliceLabel); |
|
175 |
gMulti.Orient:= IniInt(lIniFile,'Orient',gMulti.Orient); |
|
176 |
gMulti.OverslicePct:= IniInt(lIniFile,'OverslicePct',gMulti.OverslicePct); |
|
177 |
lIniFile.Free; |
|
178 |
end; |
|
179 |
||
180 |
procedure TMultiSliceForm.OpenMultiMRU(Sender:TObject); |
|
181 |
var
|
|
182 |
lFilename: string; |
|
183 |
begin
|
|
184 |
lFilename := gMultiSliceDir +(Sender as TMenuItem).caption+'.ini' ; |
|
185 |
ReadMultiSliceIniFile(lFilename); |
|
186 |
UpdateMultiSliceDisplay; |
|
187 |
CreateMultiSlice; |
|
188 |
end; |
|
189 |
||
190 |
procedure TMultiSliceForm.UpdateMultiSliceMRU; |
|
191 |
var
|
|
192 |
NewItem: TMenuItem; |
|
193 |
lSearchRec: TSearchRec; |
|
194 |
begin
|
|
195 |
While Settings1.Count > 0 do Settings1.Items[0].Free; |
|
196 |
if FindFirst(gMultiSliceDir +'*.ini', faAnyFile, lSearchRec) = 0 then |
|
197 |
repeat
|
|
198 |
NewItem := TMenuItem.Create(Self); |
|
199 |
NewItem.Caption := ParseFileName(ExtractFileName(lSearchRec.Name)); |
|
200 |
{$IFDEF FPC}
|
|
201 |
NewItem.Onclick := @OpenMultiMRU; //Lazarus |
|
202 |
{$ELSE}
|
|
203 |
NewItem.Onclick := OpenMultiMRU; |
|
204 |
{$ENDIF}
|
|
205 |
Settings1.Add(NewItem); |
|
206 |
until (FindNext(lSearchRec) <> 0); |
|
207 |
FindClose(lSearchRec); |
|
208 |
end; |
|
209 |
||
210 |
procedure TMultiSliceForm.Copy1Click(Sender: TObject); |
|
211 |
{$IFNDEF FPC}
|
|
212 |
var
|
|
213 |
MyFormat : Word; |
|
214 |
AData: THandle; |
|
215 |
APalette : HPalette; |
|
216 |
{$ENDIF}
|
|
217 |
begin
|
|
218 |
{$IFDEF Darwin}
|
|
219 |
Showmessage('Copy not yet supported with OSX: use File/Save'); |
|
220 |
{$ENDIF}
|
|
221 |
if (MultiImage.Picture.Graphic = nil) then begin //1420z |
|
222 |
Showmessage('You need to load an image before you can copy it to the clipboard.'); |
|
223 |
exit; |
|
224 |
end; |
|
225 |
{$IFNDEF FPC}
|
|
226 |
MultiImage.Picture.Bitmap.SaveToClipBoardFormat(MyFormat,AData,APalette); |
|
227 |
ClipBoard.SetAsHandle(MyFormat,AData); |
|
228 |
{$ELSE}
|
|
229 |
MultiSliceForm.MultiImage.Picture.Bitmap.SaveToClipboardFormat(2); |
|
230 |
{$ENDIF}
|
|
231 |
end; |
|
232 |
||
233 |
procedure TMultiSliceForm.MenuItem1Click(Sender: TObject); |
|
234 |
begin
|
|
235 |
||
236 |
||
237 |
end; |
|
238 |
||
239 |
||
240 |
||
241 |
procedure TMultiSliceForm.Saveasbitmap1Click(Sender: TObject); |
|
242 |
begin
|
|
243 |
SaveImgAsPNGBMP (MultiImage); |
|
244 |
end; |
|
245 |
||
246 |
{$IFNDEF FPC} //if delphi... |
|
247 |
procedure CreateBlankBitmap (lPGHt,lPGWid:integer;var lImage: TImage); |
|
248 |
var
|
|
249 |
sbBits : PByteArray; |
|
250 |
l32BitP: DWordp; |
|
251 |
lBGInvisibleColor: DWord; |
|
252 |
lBMP: TBitmap; |
|
253 |
lInc : integer; |
|
254 |
begin
|
|
255 |
lBMP := TBitmap.Create; |
|
256 |
TRY
|
|
257 |
lBMP.PixelFormat := pf32bit; |
|
258 |
lBMP.Width := lPGwid; |
|
259 |
lBMP.Height := lPGHt; |
|
260 |
sbBits := lBmp.ScanLine[lPGHt-1]; |
|
261 |
//FillChar(sbBits^,(lPGHt*lPGwid*4), 0);
|
|
262 |
//FillChar fills with black, the next bit will fill current background color
|
|
263 |
lBGInvisibleColor := gMRIcroOverlay[kBGOverlayNum].LUTinvisible; |
|
264 |
l32BitP := DWordp(sbBits); |
|
265 |
for lInc := 1 to (lPGwid*lPGHt) do |
|
266 |
l32BitP[lInc] := lBGInvisibleColor; |
|
267 |
lImage.Width := (lBmp.Width);//xx |
|
268 |
lImage.Height := (lBmp.Height);//xx |
|
269 |
lImage.Picture.Graphic := lBMP; |
|
270 |
FINALLY
|
|
271 |
lBMP.Free; |
|
272 |
END; //try..finally |
|
273 |
end; //proc CreateBlankBitmap |
|
274 |
{$ELSE} //else freepascal |
|
275 |
||
276 |
procedure CreateBlankBitmap (lPGHt,lPGWid:integer;var lImage: TImage); |
|
277 |
var
|
|
278 |
lPos: integer; |
|
279 |
lBGInvisibleColor: TRGBQuad; |
|
280 |
begin
|
|
281 |
{$IFDEF ENDIAN_BIG}
|
|
282 |
lBGInvisibleColor :=TColor2TRGBQuad(clBlack); |
|
283 |
{$ELSE}
|
|
284 |
//lBGInvisibleColor := gMRIcroOverlay[kBGOverlayNum].LUTinvisible;
|
|
285 |
lBGInvisibleColor := gMRIcroOverlay[kBGOverlayNum].LUT[0]; |
|
286 |
{$ENDIF}
|
|
287 |
gMultiWid := lPGWid; |
|
288 |
gMultiHt := lPGHt; |
|
289 |
if (gMultiWid < 1) or (gMultiHt < 1) then |
|
290 |
exit; |
|
291 |
getmem (gMultiBuff, gMultiHt*gMultiWid*sizeof(TRGBQuad) ); |
|
292 |
//fillchar(gMultiBuff^,gMultiHt*gMultiWid*sizeof(TRGBQuad),0);
|
|
293 |
for lPos := 1 to (gMultiHt*gMultiWid) do |
|
294 |
gMultiBuff^[lPos] := lBGInvisibleColor; |
|
295 |
end; |
|
296 |
{$ENDIF}
|
|
297 |
||
298 |
procedure MultiHLine (lX1,lX2,lY1,lThick: integer; lClr: TRGBQuad); |
|
299 |
var
|
|
300 |
lLine,lY,lYPos,lX,lXlo,lXhi: integer; |
|
301 |
begin
|
|
302 |
if (lThick < 1) or (gMultiWid < 1) or (gMultiHt < 1) or (lY1 < 1) or (lY1 >gMultiHt) or (gMultiBuff = nil) then |
|
303 |
exit; |
|
304 |
lXlo := lX1; |
|
305 |
lXHi := lX2; |
|
306 |
SortInteger(lXlo,lXhi); |
|
307 |
if lXlo < 1 then |
|
308 |
lXlo := 1; |
|
309 |
if lXlo > gMultiWid then |
|
310 |
lXlo := gMultiWid; |
|
311 |
if lXhi < 1 then |
|
312 |
lXhi := 1; |
|
313 |
if lXhi > gMultiWid then |
|
314 |
lXhi := gMultiWid; |
|
315 |
lY := lY1-((lThick{+1}) div 2); |
|
316 |
for lLine := 1 to lThick do begin |
|
317 |
lYPos := (lY)*gMultiWid; |
|
318 |
if lY < gMultiHt then |
|
319 |
for lX := lXlo to lXhi do |
|
320 |
gMultiBuff^[lYPos+lX] := lClr; |
|
321 |
inc(lY); |
|
322 |
end; |
|
323 |
end; |
|
324 |
||
325 |
procedure MultiVLine (lX1,lY1,lY2,lThick: integer; lClr: TRGBQuad); |
|
326 |
var
|
|
327 |
lXs, lX,lY,lYlo,lYhi: integer; |
|
328 |
begin
|
|
329 |
if (lThick < 1) or (gMultiWid < 1) or (gMultiHt < 1) or (lX1 < 1) or (lX1 >gMultiWid) or (gMultiBuff = nil) then |
|
330 |
exit; |
|
331 |
lYlo := lY1; |
|
332 |
lYHi := lY2; |
|
333 |
SortInteger(lYlo,lYhi); |
|
334 |
if lYlo < 1 then |
|
335 |
lYlo := 1; |
|
336 |
if lYlo > gMultiHt then |
|
337 |
lYlo := gMultiHt; |
|
338 |
if lYhi < 1 then |
|
339 |
lYhi := 1; |
|
340 |
if lYhi > gMultiHt then |
|
341 |
lYhi := gMultiHt; |
|
342 |
lXs := lX1-((lThick{+1}) div 2)-2;//-2 as indexed from 0 and line is at least 1 pixel thick |
|
343 |
for lX := lXs to (lXs+lThick-1) do |
|
344 |
if (lX >= 0) and (lX < gMultiWid) then |
|
345 |
for lY := lYlo to lYHi do |
|
346 |
gMultiBuff^[((lY-1)*gMultiWid)+lX] := lClr; |
|
347 |
||
348 |
end; |
|
349 |
||
350 |
procedure DefineBackGround(var lBMP: DWordp; lBGInvisibleColor: DWord; lMaskHt,lMaskWid: integer); |
|
351 |
//lMaskP should have all invis voxels as 128, non as 255
|
|
352 |
//sets all invis boundary voxels to 0
|
|
353 |
var
|
|
354 |
lMaskP: ByteP; |
|
355 |
lBGvisibleColor: DWord; |
|
356 |
lPos,lMaskSz, |
|
357 |
lQSz,lQHead,lQTail: integer; |
|
358 |
lQRA: LongIntp; |
|
359 |
Procedure IncQra(var lVal, lQSz: integer); |
|
360 |
begin
|
|
361 |
inc(lVal); |
|
362 |
if lVal >= lQSz then |
|
363 |
lVal := 1; |
|
364 |
end; |
|
365 |
PROCEDURE RetirePixel; //FIFO cleanup |
|
366 |
VAR
|
|
367 |
lVal,lPos: integer; |
|
368 |
BEGIN
|
|
369 |
lVal := lQra^[lQTail]; |
|
370 |
lPos := lVal-1; |
|
371 |
if (lPos > 0) and (lMaskP^[lPos]=128) then begin//add item to left |
|
372 |
incQra(lQHead,lQSz); |
|
373 |
lMaskP^[lPos] := 0; |
|
374 |
lQra^[lQHead] := lPos; |
|
375 |
end; |
|
376 |
if (lPos > 0) then lMaskP^[lPos] := 0; |
|
377 |
lPos := lVal+1; |
|
378 |
if (lPos < lMaskSz) and (lMaskP^[lPos]=128) then begin//add item to right |
|
379 |
incQra(lQHead,lQSz); |
|
380 |
lMaskP^[lPos] := 0; |
|
381 |
lQra^[lQHead] := lPos; |
|
382 |
end; |
|
383 |
if (lPos < lMaskSz) then lMaskP^[lPos] := 0; |
|
384 |
lPos := lVal-lMaskWid; |
|
385 |
if (lPos > 0) and (lMaskP^[lPos]=128) then begin//add item above |
|
386 |
incQra(lQHead,lQSz); |
|
387 |
lMaskP^[lPos] := 0; |
|
388 |
lQra^[lQHead] := lPos; |
|
389 |
end; |
|
390 |
if (lPos > 0) then lMaskP^[lPos] := 0; |
|
391 |
lPos := lVal+lMaskWid; |
|
392 |
if (lPos < lMaskSz) and(lMaskP^[lPos]=128) then begin//add item below |
|
393 |
incQra(lQHead,lQSz); |
|
394 |
lMaskP^[lPos] := 0; |
|
395 |
lQra^[lQHead] := lPos; |
|
396 |
end; |
|
397 |
if (lPos < lMaskSz) then lMaskP^[lPos] := 0; |
|
398 |
incQra(lQTail,lQSz); //done with this pixel |
|
399 |
END; |
|
400 |
||
401 |
procedure FillStart (lPt: integer); {FIFO algorithm: keep memory VERY low} |
|
402 |
begin
|
|
403 |
if (lPt < 1) or (lPt > lMaskSz) or (lMaskP^[lPt] <> 128) then exit; |
|
404 |
//lQSz := 8000;//size of FIFO Queue Array
|
|
405 |
lQHead := 1; |
|
406 |
lQTail := 1; |
|
407 |
lQra^[lQTail] := (lPt); //NOTE: both X and Y start from 0 not 1 |
|
408 |
lMaskP^[lPt] := 0; |
|
409 |
RetirePixel; |
|
410 |
if lQHead >= lQTail then begin |
|
411 |
while lQHead <> lQTail do |
|
412 |
RetirePixel; |
|
413 |
end; |
|
414 |
end; |
|
415 |
begin //proc DefineBG |
|
416 |
lMaskSz := lMaskWid * lMaskHt; |
|
417 |
Getmem(lMaskP,lMaskSz); |
|
418 |
for lPos := 1 to lMaskSz do |
|
419 |
if lBMP^[lPos] = lBGInvisibleColor then |
|
420 |
lMaskP^[lPos] := 128 |
|
421 |
else
|
|
422 |
lMaskP^[lPos] := 255; |
|
423 |
lQSz := lMaskSz div 4; |
|
424 |
GetMem(lQra,lQSz*sizeof(LongInt)); |
|
425 |
//erase all rows
|
|
426 |
for lPos := 1 to lMaskHt do begin |
|
427 |
FillStart( (lPos-1)*lMaskWid + 1); |
|
428 |
FillStart( (lPos)*lMaskWid); |
|
429 |
end; |
|
430 |
//erase all cols
|
|
431 |
for lPos := 1 to lMaskWid do begin |
|
432 |
FillStart( lPos + 1); |
|
433 |
FillStart( ((lMaskHt-1) *lMaskWid) + lPos); |
|
434 |
end; |
|
435 |
Freemem(lQRa); |
|
436 |
//make sure bright blue 0000FF becauses neighbor 0000FE instead of 000100
|
|
437 |
if (lBGInvisibleColor and 255) = 255 then |
|
438 |
lBGVisibleColor:= lBGInvisibleColor-1 |
|
439 |
else
|
|
440 |
lBGVisibleColor:= lBGInvisibleColor+1; |
|
441 |
//now, fill in islands so they are not transparent
|
|
442 |
for lPos := 1 to lMaskSz do |
|
443 |
if lMaskP^[lPos] = 128 then |
|
444 |
lBMP^[lPos] := lBGVisibleColor; |
|
445 |
Freemem(lMaskP); |
|
446 |
end; |
|
447 |
||
448 |
{$IFDEF FPC} //Delphi draws bitmaps directly, Lazarus can use two indirect methods... |
|
449 |
procedure SetDim (lInPGHt,lInPGWid,lWriteColumn: integer; var l32OutBitP : DWordp); |
|
450 |
var
|
|
451 |
lLen,lSrc,lDest,lY: integer; |
|
452 |
lTBuff: RGBQuadp; |
|
453 |
begin
|
|
454 |
getmem(lTBuff,lInPGHt*lWriteColumn*4); |
|
455 |
lLen := lWriteColumn*4; |
|
456 |
lSrc := 1; |
|
457 |
lDest := 1; |
|
458 |
for lY := 1 to lInPGHt do begin |
|
459 |
//svn Move(Pointer(l32OutBitP^[lSrc]),Pointer(lTBuff^[lDest]),lLen);
|
|
460 |
Move(l32OutBitP^[lSrc],lTBuff^[lDest],lLen); |
|
461 |
lSrc := lSrc + lInPGWid; |
|
462 |
lDest := lDest + lWriteColumn; |
|
463 |
end; |
|
464 |
DrawBMP( lWriteColumn, lInPGHt, lTBuff, MultiSliceForm.MultiImage); |
|
465 |
freemem(lTBuff); |
|
466 |
end; |
|
467 |
{$ENDIF} //ifdef FPC |
|
468 |
||
469 |
procedure RemoveHorizGaps (lMaxOverlapWid,lColWid: integer); //will overlap gaps from 1..lMaxOverlapWid, leave right non-overlapped); |
|
470 |
var
|
|
471 |
l32BitP,l32OutBitP : DWordp; |
|
472 |
lBGInvisibleColor,lBGInvisibleColorShr8: DWord; |
|
473 |
lIsGap,lPrevIsGap: boolean; |
|
474 |
lInc,lPrevSliceStart,lPrevSliceEnd,lPrevWriteColumn,lWid,lHt,lReadRow, |
|
475 |
lMaxWriteColumn,lReadColumn,lWriteColumn,lReadOffset,lWriteOffset,lPos,x,y: integer; |
|
476 |
lTextPos,lTextReadColumn: integer; |
|
477 |
begin
|
|
478 |
(*freemem (gMultiBuff );
|
|
479 |
gMultiBuff := nil;
|
|
480 |
exit;*)
|
|
481 |
||
482 |
||
483 |
for lTextPos := 1 to kMaxMultiSlice do |
|
484 |
gMultiXCenterRA[lTextPos] := 0; |
|
485 |
lTextPos := 0; |
|
486 |
lTextReadColumn := lColWid div 2; |
|
487 |
if (gMultiWid < 1) or (gMultiHt < 1) or (gMultiBuff = nil) then |
|
488 |
exit; |
|
489 |
lBGInvisibleColor := TRGBQuad2DWord(gMRIcroOverlay[kBGOverlayNum].LUTinvisible); |
|
490 |
//fx(lBGInvisibleColor);
|
|
491 |
//lBGInvisibleColorShr8 := lBGInvisibleColor Shr 8;
|
|
492 |
lHt := gMultiHt;//MultiSliceForm.MultiImage.Picture.Bitmap.Height; |
|
493 |
lWid := gMultiWid; //MultiSliceForm.MultiImage.Picture.Bitmap.Width; |
|
494 |
if (lHt < 2) or (lWid < 2) then exit; |
|
495 |
//next: prepare input
|
|
496 |
l32BitP := DWordP(gMultiBuff); |
|
497 |
(*GetMem(l32BitP,lHt*lWid*sizeof(DWord));
|
|
498 |
lPos := 0;
|
|
499 |
for y:= 0 to (lHt-1) do begin
|
|
500 |
for x:=0 to lWid-1 do begin
|
|
501 |
inc(lPos);
|
|
502 |
l32BitP^[lPos] := MultiSliceForm.MultiImage.Picture.Bitmap.Canvas.Pixels[x,y];
|
|
503 |
end;
|
|
504 |
end;*)
|
|
505 |
lBGInvisibleColor := l32BitP^[1]; |
|
506 |
DefineBackGround(l32BitP,lBGInvisibleColor, lHt,lWid); |
|
507 |
//next prepare output
|
|
508 |
GetMem(l32OutBitP,lHt*lWid*sizeof(DWord)); |
|
509 |
for lInc := 1 to (lwid*lHt) do |
|
510 |
l32OutBitP^[lInc] := lBGInvisibleColor; |
|
511 |
//next: compress by deleting empty columns
|
|
512 |
lWriteColumn := 0; |
|
513 |
lPrevIsGap := true; |
|
514 |
lPrevSliceStart := maxint -10; |
|
515 |
lPrevSliceEnd := 0; |
|
516 |
lPrevWriteColumn := maxint-10;//do not degap 1st line |
|
517 |
||
518 |
||
519 |
if gMulti.OverSlicePct = 0 then begin //simply remove gaps between slice |
|
520 |
for lReadColumn := 1 to lWid do begin |
|
521 |
lReadOffset := lReadColumn; |
|
522 |
lIsGap := true; |
|
523 |
lReadRow := 1; |
|
524 |
if lReadColumn >= lTextReadColumn then begin |
|
525 |
inc(lTextPos); |
|
526 |
lTextReadColumn := lTextReadColumn+lColWid; |
|
527 |
if lTextPos <= kMaxMultiSlice then |
|
528 |
gMultiXCenterRA[lTextPos] := lWriteColumn; |
|
529 |
end; |
|
530 |
while (lReadRow < lHt) and (lIsGap) do begin |
|
531 |
if l32BitP^[lReadOffset] <> lBGInvisibleColor then |
|
532 |
lIsGap := false; |
|
533 |
inc(lReadOffset,lWid); |
|
534 |
inc(lReadRow); |
|
535 |
end; //while each readrow |
|
536 |
if not lIsGap then begin//data in this column |
|
537 |
if lReadColumn > (lPrevWriteColumn+1) then begin //leave one pixel gap between noncontiguous columns |
|
538 |
inc(lWriteColumn); |
|
539 |
lReadOffset := lReadColumn-1; |
|
540 |
lWriteOffset := lWriteColumn; |
|
541 |
//showmessage(inttostr(lWriteColumn)+' '+inttostr(lReadOffset));
|
|
542 |
for lReadRow := 1 to lHt do begin |
|
543 |
l32OutBitP[lWriteOffset] := l32BitP[lReadOffset]; |
|
544 |
inc(lReadOffset,lWid); |
|
545 |
inc(lWriteOffset,lWid); |
|
546 |
end; |
|
547 |
end; //leave 1 pixel gap |
|
548 |
inc(lWriteColumn); |
|
549 |
lReadOffset := lReadColumn; |
|
550 |
lWriteOffset := lWriteColumn; |
|
551 |
for lReadRow := 1 to lHt do begin |
|
552 |
l32OutBitP[lWriteOffset] := l32BitP[lReadOffset]; |
|
553 |
inc(lReadOffset,lWid); |
|
554 |
inc(lWriteOffset,lWid); |
|
555 |
end; |
|
556 |
lPrevWriteColumn := lReadColumn; |
|
557 |
end; //not Gap - write this column |
|
558 |
end; //for each column |
|
559 |
end else begin //overslice <> 0: show subsequent slices above/below each other |
|
560 |
lMaxWriteColumn := -maxint; |
|
561 |
for lReadColumn := 1 to lMaxOverlapWid do begin |
|
562 |
lReadOffset := lReadColumn; |
|
563 |
lIsGap := true; |
|
564 |
lReadRow := 1; |
|
565 |
while (lReadRow < lHt) and (lIsGap) do begin |
|
566 |
//ovx
|
|
567 |
if l32BitP^[lReadOffset] <> lBGInvisibleColor then |
|
568 |
lIsGap := false; |
|
569 |
inc(lReadOffset,lWid); |
|
570 |
inc(lReadRow); |
|
571 |
end; //while each readrow |
|
572 |
if (lPrevIsGap <> lIsGap) then begin//change from prev column |
|
573 |
if not (lIsGap) then begin |
|
574 |
//fx(lPrevSliceStart,lPrevSliceEnd,lReadColumn,abs(((lPrevSliceEnd-lPrevSliceStart) * gMulti.OverSlicePct)div 100));
|
|
575 |
if lPrevSliceEnd > lPrevSliceStart then |
|
576 |
lWriteColumn := lPrevSliceEnd-abs(((lPrevSliceEnd-lPrevSliceStart) * gMulti.OverSlicePct)div 100); |
|
577 |
lPrevSliceStart := lWriteColumn; |
|
578 |
||
579 |
end; |
|
580 |
if (lIsGap) then |
|
581 |
lPrevSliceEnd := lWriteColumn; |
|
582 |
end; |
|
583 |
lPrevIsGap := lIsGap; |
|
584 |
if gMulti.OverSlicePct > 0 then begin |
|
585 |
if not lIsGap then begin//data in this column |
|
586 |
inc(lWriteColumn); |
|
587 |
lReadOffset := lReadColumn; |
|
588 |
lWriteOffset := lWriteColumn; |
|
589 |
for lReadRow := 1 to lHt do begin |
|
590 |
if l32BitP^[lReadOffset] <> lBGInvisibleColor then |
|
591 |
l32OutBitP^[lWriteOffset] := l32BitP^[lReadOffset]; |
|
592 |
inc(lReadOffset,lWid); |
|
593 |
inc(lWriteOffset,lWid); |
|
594 |
end; |
|
595 |
end; //not Gap - write this column |
|
596 |
end else begin //if overwrite, else underwrite |
|
597 |
if not lIsGap then begin//data in this column |
|
598 |
inc(lWriteColumn); |
|
599 |
lReadOffset := lReadColumn; |
|
600 |
lWriteOffset := lWriteColumn; |
|
601 |
for lReadRow := 1 to lHt do begin |
|
602 |
if l32OutBitP^[lWriteOffset] = lBGInvisibleColor then |
|
603 |
l32OutBitP^[lWriteOffset] := l32BitP^[lReadOffset]; |
|
604 |
inc(lReadOffset,lWid); |
|
605 |
inc(lWriteOffset,lWid); |
|
606 |
end; |
|
607 |
end; //not Gap - write this column |
|
608 |
end; |
|
609 |
if lReadColumn >= lTextReadColumn then begin //text |
|
610 |
inc(lTextPos); |
|
611 |
lTextReadColumn := lTextReadColumn+lColWid; |
|
612 |
if lTextPos <= kMaxMultiSlice then |
|
613 |
gMultiXCenterRA[lTextPos] := lWriteColumn; |
|
614 |
end; //text |
|
615 |
if lWriteColumn > lMaxWriteColumn then |
|
616 |
lMaxWriteColumn := lWriteColumn; |
|
617 |
end; //for each column |
|
618 |
if lWriteColumn < lMaxWriteColumn then |
|
619 |
lWriteColumn := lMaxWriteColumn; |
|
620 |
if lMaxOverlapWid < lWid then begin |
|
621 |
lReadColumn := lMaxOverlapWid; |
|
622 |
if (lWriteColumn) < lReadColumn then //add gap if some compression |
|
623 |
inc(lWriteColumn); |
|
624 |
for lReadColumn := (lMaxOverlapWid+1) to lWid do begin |
|
625 |
lReadOffset := lReadColumn; |
|
626 |
lIsGap := true; |
|
627 |
lReadRow := 1; |
|
628 |
while (lReadRow < lHt) and (lIsGap) do begin |
|
629 |
if l32BitP^[lReadOffset] <> lBGInvisibleColor then |
|
630 |
lIsGap := false; |
|
631 |
inc(lReadOffset,lWid); |
|
632 |
inc(lReadRow); |
|
633 |
end; //while each readrow |
|
634 |
if not lIsGap then begin |
|
635 |
inc(lWriteColumn); |
|
636 |
lReadOffset := lReadColumn; |
|
637 |
lWriteOffset := lWriteColumn; |
|
638 |
for lReadRow := 1 to lHt do begin |
|
639 |
l32OutBitP[lWriteOffset] := l32BitP[lReadOffset]; |
|
640 |
inc(lReadOffset,lWid); |
|
641 |
inc(lWriteOffset,lWid); |
|
642 |
end; //for each row |
|
643 |
end; //not gap |
|
644 |
end; //for each column |
|
645 |
if (lWriteColumn+1) < lWid then |
|
646 |
inc(lWriteColumn); |
|
647 |
end; //if maxwid < wid - unoverlapped |
|
648 |
end; |
|
649 |
||
650 |
SetDim (lHt,lWid,lWriteColumn,l32OutBitP); |
|
651 |
FreeMem(l32OutBitP); |
|
652 |
freemem (gMultiBuff ); |
|
653 |
gMultiBuff := nil; |
|
654 |
end; |
|
655 |
||
656 |
||
657 |
procedure TMultiSliceForm.CreateMultiSag; |
|
658 |
var
|
|
659 |
lSlice,lHt,lWid,lSlicePos,lSliceWid: integer; |
|
660 |
begin
|
|
661 |
||
662 |
lHt:= gBGIMg.ScrnDim[3]; |
|
663 |
lSliceWid :=gBGIMg.ScrnDim[2]+2;//+1 for 1-voxel gap between slices - ensures we can detect slice boundary |
|
664 |
lWid := (lSliceWid*gMulti.nSlices); |
|
665 |
if lWid < 2 then exit; |
|
666 |
if gMulti.OrthoView then //coro crossview |
|
667 |
lWid := lWid + gBGIMg.ScrnDim[1]+2; |
|
668 |
if lWid < 2 then exit; |
|
669 |
||
670 |
CreateBlankBitmap (lHt,lWid, MultiImage); |
|
671 |
for lSlice := 1 to gMulti.nSlices do begin |
|
672 |
DrawSag (gMulti.SliceList[lSlice],1+((lSlice-1)*lSliceWid));//+lSlice because we want 1-voxel gap between slices |
|
673 |
//if gMulti.SliceLabel then DrawLabel(MultiImage,DimToMM(gMulti.SliceList[lSlice],1),((lSlice-1)*lSliceWid)+(lSliceWid div 2),lWid);
|
|
674 |
end; |
|
675 |
if gMulti.OrthoView then begin //coro crossview |
|
676 |
DrawCor (gBGImg.ScrnDim[2] div 2,(lSliceWid*gMulti.nSlices)-1); |
|
677 |
//MultiImage.Canvas.Pen.Color := clWhite;
|
|
678 |
//MultiImage.Canvas.Pen.Color := gBGIMg.XBarClr;
|
|
679 |
//MultiImage.Canvas.Pen.Width := gBGImg.XBarThick;
|
|
680 |
for lSlice := 1 to gMulti.nSlices do begin //draw lines |
|
681 |
lSlicePos := (gMulti.nSlices*lSliceWid)+(gMulti.SliceList[lSlice]); |
|
682 |
MultiVLine (lSlicePos,0,lHt,gBGImg.XBarThick,TColor2TRGBQuad(gBGImg.XBarClr)); |
|
683 |
{MultiImage.Canvas.MoveTo(lSlicePos,0);
|
|
684 |
MultiImage.Canvas.LineTo(lSlicePos,lHt);}
|
|
685 |
end;//line for each slice |
|
686 |
end;//if cross view |
|
687 |
RemoveHorizGaps(lSliceWid*gMulti.nSlices,lSliceWid); |
|
688 |
end; //CreateMultiSag |
|
689 |
||
690 |
procedure TMultiSliceForm.CreateMultiCor; |
|
691 |
var
|
|
692 |
lSlice,lHt,lWid,lLeft,lSliceWid: integer; |
|
693 |
begin
|
|
694 |
lHt:= gBGIMg.ScrnDim[3]; |
|
695 |
lSliceWid :=gBGIMg.ScrnDim[1]+2;//+1 for 1-voxel gap between slices - ensures we can detect slice boundary |
|
696 |
lWid := lSliceWid*gMulti.nSlices; |
|
697 |
if lWid < 2 then exit; |
|
698 |
if gMulti.OrthoView then //sag crossview |
|
699 |
lWid := lWid + gBGIMg.ScrnDim[2]+2; |
|
700 |
if lWid < 2 then exit; |
|
701 |
CreateBlankBitmap (lHt,lWid, MultiImage); |
|
702 |
for lSlice := 1 to gMulti.nSlices do begin |
|
703 |
//ImgForm.YViewEdit.value := gMulti.SliceList[lSlice];
|
|
704 |
DrawCor (gMulti.SliceList[lSlice],1+((lSlice-1)*lSliceWid)); |
|
705 |
//if gMulti.SliceLabel then DrawLabel(MultiImage,DimToMM(gMulti.SliceList[lSlice],2),((lSlice-1)*lSliceWid)+(gBGIMg.ScrnDim[1] div 2),lWid);
|
|
706 |
end; |
|
707 |
if gMulti.OrthoView then begin |
|
708 |
DrawSag (gBGImg.ScrnDim[1] div 2,(gMulti.nSlices*lSliceWid)-1); |
|
709 |
//MultiImage.Canvas.Pen.Color := gBGIMg.XBarClr;
|
|
710 |
//MultiImage.Canvas.Pen.Color := clWhite;
|
|
711 |
MultiImage.Canvas.Pen.Color := gBGIMg.XBarClr; |
|
712 |
MultiImage.Canvas.Pen.Width := gBGImg.XBarThick; |
|
713 |
||
714 |
for lSlice := 1 to gMulti.nSlices do begin |
|
715 |
lLeft := gMulti.nSlices*lSliceWid+(gMulti.SliceList[lSlice]); |
|
716 |
MultiVLine (lLeft,0,lHt,gBGImg.XBarThick,TColor2TRGBQuad(gBGImg.XBarClr)); |
|
717 |
||
718 |
{MultiImage.Canvas.MoveTo(lLeft,0);
|
|
719 |
MultiImage.Canvas.LineTo(lLeft,lHt);}
|
|
720 |
end; |
|
721 |
end;//if orthoview |
|
722 |
RemoveHorizGaps(lSliceWid*gMulti.nSlices,lSliceWid); |
|
723 |
end; //CreateMultiCor |
|
724 |
||
725 |
procedure TMultiSliceForm.CreateMultiAx; |
|
726 |
var
|
|
727 |
lSliceWid,lSlice,lHt,lWid,lLeft: integer; |
|
728 |
begin
|
|
729 |
lHt:= gBGIMg.ScrnDim[2]; |
|
730 |
lSliceWid :=gBGIMg.ScrnDim[1]+2;//+1 for 1-voxel gap between slices - ensures we can detect slice boundary |
|
731 |
lWid := lSliceWid*gMulti.nSlices; |
|
732 |
if lWid < 2 then exit; |
|
733 |
if gMulti.OrthoView then begin //sag crossview |
|
734 |
lWid := lWid + gBGIMg.ScrnDim[2]+2; |
|
735 |
if gBGIMg.ScrnDim[3]> lHt then |
|
736 |
lHt := gBGIMg.ScrnDim[3]; |
|
737 |
end; |
|
738 |
if lWid < 2 then exit; |
|
739 |
CreateBlankBitmap (lHt,lWid, MultiImage); |
|
740 |
for lSlice := 1 to gMulti.nSlices do begin |
|
741 |
DrawAxial (gMulti.SliceList[lSlice],1+((lSlice-1)*lSliceWid)); |
|
742 |
//if gMulti.SliceLabel then DrawLabel(MultiImage,DimToMM(gMulti.SliceList[lSlice],3),((lSlice-1)*lSliceWid)+(gBGIMg.ScrnDim[1] div 2),lWid);
|
|
743 |
end; |
|
744 |
if gMulti.OrthoView then begin |
|
745 |
lLeft := gMulti.nSlices*lSliceWid; |
|
746 |
//DrawSag (gBGImg.ScrnDim[1] div 2,lLeft);
|
|
747 |
DrawSag (gBGImg.ScrnDim[1] div 2,lLeft-1); |
|
748 |
||
749 |
//MultiImage.Canvas.pen.Color := clWhite;
|
|
750 |
//MultiImage.Canvas.Pen.Color := gBGIMg.XBarClr;
|
|
751 |
//MultiImage.Canvas.Pen.Width := gBGImg.XBarThick;
|
|
752 |
||
753 |
for lSlice := 1 to gMulti.nSlices do begin |
|
754 |
lHt := gBGImg.ScrnDim[3]-(gMulti.SliceList[lSlice]); |
|
755 |
MultiHLine (lLeft,lWid,lHt,gBGImg.XBarThick,TColor2TRGBQuad(gBGImg.XBarClr)); |
|
756 |
end; |
|
757 |
end; |
|
758 |
RemoveHorizGaps(lSliceWid*gMulti.nSlices,lSliceWid); |
|
759 |
end; //CreateMultiAx |
|
760 |
||
761 |
procedure DrawLabels; |
|
762 |
var
|
|
763 |
lSlice,lOrient: integer; |
|
764 |
begin
|
|
765 |
case gMulti.Orient of |
|
766 |
3: lOrient := 2; |
|
767 |
2: lOrient := 1; |
|
768 |
else lOrient := 3; |
|
769 |
end;//case |
|
770 |
||
771 |
if not gMulti.SliceLabel then |
|
772 |
exit; |
|
773 |
for lSlice := 1 to gMulti.nSlices do begin |
|
774 |
if gMultiXCenterRA[lSlice] > 0 then DrawLabel(MultiSliceForm.MultiImage,DimToMM(gMulti.SliceList[lSlice],gMulti.SliceList[lSlice],gMulti.SliceList[lSlice],lOrient),gMultiXCenterRA[lSlice],maxint); |
|
775 |
end; |
|
776 |
end; |
|
777 |
//gMultiXCenterRA
|
|
778 |
||
779 |
procedure TMultiSliceForm.CreateMultiSlice; |
|
780 |
//test var lI: integer;
|
|
781 |
begin
|
|
782 |
if gMulti.nSlices < 1 then begin |
|
783 |
showmessage('No valid slices selected - please use View/Slices.'); |
|
784 |
end; |
|
785 |
//MultiImage.Canvas.Font.Color := clWhite;
|
|
786 |
//for lI := 1 to 32 do begin //test
|
|
787 |
case gMulti.Orient of |
|
788 |
3: CreateMultiCor; |
|
789 |
2: CreateMultiSag; |
|
790 |
else CreateMultiAx; |
|
791 |
end;//case |
|
792 |
DrawLabels; |
|
793 |
// end; //test
|
|
794 |
end;//CreateMultiSlice |
|
795 |
||
796 |
procedure TMultiSliceForm.OrientClick(Sender: TObject); |
|
797 |
begin
|
|
798 |
(sender as TMenuItem).checked := true; |
|
799 |
gMulti.Orient := (sender as TMenuItem).tag; |
|
800 |
CreateMultiSlice; |
|
801 |
end; |
|
802 |
||
803 |
procedure TMultiSliceForm.FormShow(Sender: TObject); |
|
804 |
begin
|
|
805 |
ReadMultiSliceIniFile (gMultiSliceStartupFilename ); |
|
806 |
UpdateMultiSliceMRU; |
|
807 |
UpdateMultiSliceDisplay; |
|
808 |
CreateMultiSlice; |
|
809 |
MultiSliceForm.BringToFront; |
|
810 |
end; |
|
811 |
||
812 |
procedure TMultiSliceForm.OrthoviewClick(Sender: TObject); |
|
813 |
begin
|
|
814 |
OrthoView.checked := not OrthoView.Checked; |
|
815 |
gMulti.OrthoView := OrthoView.checked; |
|
816 |
CreateMultiSlice; |
|
817 |
end; |
|
818 |
||
819 |
procedure TMultiSliceForm.Settings1Click(Sender: TObject); |
|
820 |
begin
|
|
821 |
||
822 |
end; |
|
823 |
||
824 |
procedure TMultiSliceForm.Slices1Click(Sender: TObject); |
|
825 |
var
|
|
826 |
lStr: string; |
|
827 |
begin
|
|
828 |
lStr := InputBox('Select multislices', 'Slice numbers [e.g. 10,16,24]',MultiSliceNum2String); |
|
829 |
//now parse line
|
|
830 |
MultiSliceString2Num(lStr); |
|
831 |
CreateMultiSlice; |
|
832 |
end; |
|
833 |
||
834 |
procedure TMultiSliceForm.Closewindow1Click(Sender: TObject); |
|
835 |
begin
|
|
836 |
MultiSliceForm.Close; |
|
837 |
end; |
|
838 |
||
839 |
procedure TMultiSliceForm.UpdateMultiSliceDisplay; |
|
840 |
begin
|
|
841 |
SetSubmenuWithTag(OversliceMenu, gMulti.OverslicePct); |
|
842 |
SetSubmenuWithTag(OrientMenu, gMulti.Orient); |
|
843 |
OrthoView.Checked := gMulti.OrthoView; |
|
844 |
SliceLabelCheck.Checked := gMulti.SliceLabel; |
|
845 |
end; |
|
846 |
||
847 |
procedure TMultiSliceForm.FormCreate(Sender: TObject); |
|
848 |
var
|
|
849 |
lSlice:integer; |
|
850 |
begin
|
|
851 |
gMultiBuff := nil; |
|
852 |
gMultiSliceDir := DefaultsDir('multislice'); |
|
853 |
//gMultiSliceDir := extractfiledir(paramstr(0))+pathdelim+'multislice'+pathdelim;
|
|
854 |
gMultiSliceDefaultsFilename := gMultiSliceDir + 'default.ini'; |
|
855 |
gMultiSliceStartupFilename := gMultiSliceDefaultsFilename; |
|
856 |
gMulti.Orient := 1; |
|
857 |
gMulti.OverslicePct := 0; |
|
858 |
gMulti.nSlices:= 4; |
|
859 |
gMulti.OrthoView := true; |
|
860 |
gMulti.SliceLabel := true; |
|
861 |
for lSlice := 1 to gMulti.nSlices do |
|
862 |
gMulti.SliceList[lSlice] := 62+10*lSlice; |
|
863 |
end; |
|
864 |
||
865 |
{$IFNDEF FPC}
|
|
866 |
procedure TMultiSliceForm.FormClose(Sender: TObject; var Action: TCloseAction); |
|
867 |
{$ELSE}
|
|
868 |
procedure TMultiSliceForm.FormClose(Sender: TObject); |
|
869 |
{$ENDIF}
|
|
870 |
begin
|
|
871 |
WriteMultiSliceIniFile (gMultiSliceDefaultsFilename ); |
|
872 |
end; |
|
873 |
||
874 |
procedure TMultiSliceForm.Savesettings1Click(Sender: TObject); |
|
875 |
begin
|
|
876 |
MultiSaveDialog.InitialDir := extractfiledir(gMultiSliceDir ); |
|
877 |
if not MultiSaveDialog.Execute then exit; |
|
878 |
{$IFDEF Unix}
|
|
879 |
WriteMultiSliceIniFile(extractfiledir(gMultiSliceDir)+pathdelim+extractfilename(MultiSaveDialog.Filename)); |
|
880 |
||
881 |
{$ELSE}
|
|
882 |
WriteMultiSliceIniFile(MultiSaveDialog.Filename); |
|
883 |
{$ENDIF}
|
|
884 |
UpdateMultiSliceMRU; |
|
885 |
end; |
|
886 |
||
887 |
procedure TMultiSliceForm.SliceLabelCheckClick(Sender: TObject); |
|
888 |
begin
|
|
889 |
SliceLabelCheck.checked := not SliceLabelCheck.Checked; |
|
890 |
gMulti.SliceLabel := SliceLabelCheck.checked; |
|
891 |
CreateMultiSlice; |
|
892 |
end; |
|
893 |
||
894 |
procedure TMultiSliceForm.OverlsiceClick(Sender: TObject); |
|
895 |
begin
|
|
896 |
(sender as TMenuItem).checked := true; |
|
897 |
gMulti.OverslicePct := (sender as TMenuItem).tag; |
|
898 |
CreateMultiSlice; |
|
899 |
end; |
|
900 |
||
901 |
{$IFDEF FPC}
|
|
902 |
initialization
|
|
903 |
{$I MultiSlice.lrs}
|
|
904 |
{$ENDIF}
|
|
905 |
||
906 |
end. |