unit Correlation; interface uses QuickDraw, Palettes, PrintTraps, globals, Utilities, Graphics, FFT; procedure DoCorrelation; implementation const CorrDLOG = 2500; CorrOk = 1; CorrCancel = 2; CorrHorizontal = 4; CorrVertical = 5; Corrtwod = 6; CorrAuto = 8; CorrPairwise = 9; CorrWindow1 = 10; CorrScrollbar1 = 11; CorrWindow2 = 13; CorrScrollBar2 = 14; CorrNext = 15; AutoButton = 17; FixedButton = 18; CorrScaleMenu = 160; ScaleNumber = 19; MaxLines = 12; type CorrDim = (horizontal, vertical, twodimensional); CorrKind = (Auto, NextLine, Pair); {CorrBut = (AutoB, Fixed);declared in unit fft} var n1, n2, sel1, sel2, ctlPos1, ctlPos2: integer; Scalingfactor: real; Dimension: CorrDim; Kind: CorrKind; Button: CorrBut; procedure ShowKind (mylog: DialogPtr; Kind: CorrKind); begin SetDialogItem(mylog, CorrAuto, 0); SetDialogItem(mylog, CorrPairwise, 0); SetDialogItem(mylog, CorrNext, 0); case kind of Auto: SetDialogItem(mylog, CorrAuto, 1); NextLine: SetDialogItem(mylog, CorrNext, 1); Pair: SetDialogItem(mylog, CorrPairwise, 1); end; end; procedure ShowDim (mylog: DialogPtr; Dim: CorrDim); begin SetDialogItem(mylog, CorrHorizontal, 0); SetDialogItem(mylog, CorrVertical, 0); SetDialogItem(mylog, Corrtwod, 0); case dim of horizontal: SetDialogItem(mylog, CorrHorizontal, 1); vertical: SetDialogItem(mylog, CorrVertical, 1); twodimensional: SetDialogItem(mylog, Corrtwod, 1); end; end; procedure ShowBut (mylog: DialogPtr; But: CorrBut); begin SetDialogItem(mylog, AutoButton, 0); SetDialogItem(mylog, FixedButton, 0); case But of AutoB: SetDialogItem(mylog, AutoButton, 1); Fixed: SetDialogItem(mylog, FixedButton, 1); end; end; function Item2Dim (item: integer): Corrdim; begin case item of CorrHorizontal: Item2Dim := horizontal; CorrVertical: Item2Dim := vertical; Corrtwod: Item2Dim := twodimensional; end; end; function Item2Kind (item: integer): Corrkind; begin case item of CorrAuto: Item2Kind := Auto; CorrPairwise: Item2Kind := Pair; CorrNext: Item2Kind := NextLine; end; end; function Item2But (item: integer): CorrBut; begin case item of Autobutton: Item2But := AutoB; FixedButton: Item2But := Fixed; end; end; procedure ShowScalingNumber (dlog: DialogPtr; number: real); var Itemtype, Temp: integer; BoxRect: rect; ItemH: handle; text: str255; begin GetDItem(dlog, ScaleNumber, ItemType, ItemH, BoxRect); with BoxRect do begin EraseRect(BoxRect); FrameRect(BoxRect); MoveTo(left + 5, bottom); LineTo(right, bottom); LineTo(right, top + 5); MoveTo(left + 5, bottom - 5); Temp := trunc(number * 10); case Temp of 1: text := '0.1'; 2: text := '0.2'; 3: text := '0.3'; 5: text := '0.5'; 10, 20, 30, 50: begin NumToString(Temp div 10, text); end; end; DrawString(text); end; end; function HandleScalingNumber (dlog: DialogPtr; number: real): real; var Itemtype, Result, number2, Temp: integer; TitleRect, BoxRect: rect; PopUpMenuH: MenuHandle; ItemH: handle; pt: Point; begin GetDItem(dlog, ScaleNumber, ItemType, ItemH, BoxRect); GetDItem(dlog, ScaleNumber - 1, ItemType, ItemH, TitleRect); InvertRect(TitleRect); PopUpMenuH := GetMenu(CorrScaleMenu); InsertMenu(PopUpMenuH, -1); pt := BoxRect.topleft; LocalToGlobal(pt); Temp := trunc(number * 10); case Temp of 1, 2, 3: number2 := Temp; 5: number2 := 4; 10, 20, 30: number2 := trunc(number) + 4; 50: number2 := 8; end; Result := PopUpMenuSelect(PopUpMenuH, pt.v, pt.h, number2); if Result > 0 then begin case Result of 1: HandleScalingNumber := 0.1; 2: HandleScalingNumber := 0.2; 3: HandleScalingNumber := 0.3; 4: HandleScalingNumber := 0.5; 5, 6, 7: HandleScalingNumber := Result - 4; 8: HandleScalingNumber := 5 end; end else HandleScalingNumber := number; InvertRect(TitleRect); DeleteMenu(CorrScaleMenu); end; procedure ChecKInputOptions; var isOk: boolean; Temp: integer; begin isOk := true; Temp := trunc(ScalingFactor * 10); if Temp in [1, 2, 3, 5, 10, 20, 30, 50] then else Scalingfactor := 1; isOk := false; case Button of Autob, Fixed: isOk := true; end; if isOk = false then Button := Autob; isOk := false; case Kind of Auto, NextLine, Pair: isOk := true; end; if isOk = false then Kind := Auto; isOk := false; case Dimension of horizontal, vertical, twodimensional: isOk := true; end; if isOk = false then Dimension := horizontal; end; procedure ShowWindows (mylog: DialogPtr; Box, Bar, n, sel: integer); var i, start, stop: integer; TInfo: InfoPtr; Itemtype: integer; ItemHandle: handle; tport: GrafPtr; trect, irect: Rect; begin GetPort(tPort); SetPort(mylog); if nPics < MaxLines then begin start := 1; stop := nPics; end else begin start := n; stop := n + MaxLines - 1; if stop > nPics then begin stop := nPics; start := stop - MaxLines + 1; end; end; GetDitem(myLog, Box, ItemType, itemHandle, trect); EraseRect(trect); FrameRect(trect); ClipRect(trect); with trect do begin for i := start to stop do begin MoveTo(left + 2, top + (i - start + 1) * 15); TInfo := pointer(WindowPeek(PicWindow[i])^.RefCon); DrawString(TInfo^.title); if i = sel then begin SetRect(irect, left + 1, top + (i - start) * 15 + 2, right - 1, top + (i - start + 1) * 15 + 2); InvertRect(irect); end; end; end; ClipRect(mylog^.PortRect); GetDitem(myLog, Bar, ItemType, itemHandle, trect); SetCtlMin(ControlHandle(itemHandle), 1); if nPics > MaxLines then begin SetCtlMax(ControlHandle(itemHandle), nPics - MaxLines + 1); end else SetCtlMax(ControlHandle(itemHandle), 1); SetCtlValue(ControlHandle(itemHandle), start); if bar = corrScrollbar1 then ctlPos1 := start; if bar = corrScrollbar2 then ctlPos2 := start; SetPort(tPort); end; function HandleControls (myLog: DialogPtr; var Event: EventRecord; var item: integer): boolean; var theCtl: ControlHandle; Itemtype, aux, Position, Control: integer; ItemHandle: handle; trect: Rect; auxDLOG: DialogPtr; auxItem: integer; thePoint: Point; tport: GrafPtr; charcode: longint; begin HandleControls := false; if IsDialogEvent(event) then if DialogSelect(event, auxDLOG, auxItem) then begin GetPort(tPort); SetPort(auxDLOG); thePoint := Event.where; GlobalToLocal(thePoint); case auxitem of -1: begin GetDitem(myLog, CorrScrollbar1, ItemType, itemHandle, trect); if PtInRect(thePoint, trect) then aux := FindControl(thePoint, myLog, theCtl); HandleControls := false; end; CorrScrollbar1: begin GetDitem(myLog, CorrScrollbar1, ItemType, itemHandle, trect); Control := FindControl(thePoint, myLog, theCtl); case Control of inUpButton: begin if n1 > 1 then n1 := n1 - 1; if sel1 > (n1 + MaxLines - 1) then sel1 := n1; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); end; inDownButton: begin if n1 < (nPics - MaxLines + 1) then n1 := n1 + 1; if sel1 < n1 then sel1 := n1; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); end; inPageUp: begin Position := getctlvalue(ControlHandle(ItemHandle)); if Position <> ctlPos1 then begin n1 := Position; if (sel1 < n1) or (sel1 > n1 + maxLines - 1) then sel1 := n1; end else begin if n1 > MaxLines then n1 := n1 - MaxLines else n1 := 1; sel1 := n1; end; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); end; inPageDown: begin Position := getctlvalue(ControlHandle(ItemHandle)); if Position <> ctlPos1 then begin n1 := Position; if (sel1 < n1) or (sel1 > n1 + maxLines - 1) then sel1 := n1; end else begin if n1 < (nPics - MaxLines + 1) then begin n1 := n1 + MaxLines; if n1 > nPics - MaxLines + 1 then n1 := nPics - MaxLines + 1 end else n1 := nPics - MaxLines + 1; sel1 := n1; end; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); end; inThumb: begin Position := getctlvalue(ControlHandle(ItemHandle)); n1 := Position; if (sel1 < n1) or (sel1 > n1 + maxLines - 1) then sel1 := n1; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); handlecontrols := true; end; end; end; CorrWindow1: begin GetDitem(myLog, CorrWindow1, ItemType, itemHandle, trect); sel1 := n1 + (Event.where.v - trect.top) div 15 - 3; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); HandleControls := false; end; CorrScrollbar2: begin GetDitem(myLog, CorrScrollbar2, ItemType, itemHandle, trect); case FindControl(thePoint, myLog, theCtl) of inUpButton: begin if n2 > 1 then n2 := n2 - 1; if sel2 > (n2 + MaxLines - 1) then sel2 := n2; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); end; inDownButton: begin if n2 < nPics - MaxLines + 1 then n2 := n2 + 1; if sel2 < n2 then sel2 := n2; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); end; inPageUp: begin Position := getctlvalue(ControlHandle(ItemHandle)); if Position <> ctlPos2 then begin n2 := Position; if (sel2 < n2) or (sel2 > n2 + maxLines - 1) then sel2 := n2; end else begin if n2 > MaxLines then n2 := n2 - MaxLines else n2 := 1; sel2 := n2; end; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); end; inPageDown: begin Position := getctlvalue(ControlHandle(ItemHandle)); if Position <> ctlPos2 then begin n2 := Position; if (sel2 < n2) or (sel2 > n2 + maxLines - 1) then sel2 := n2; end else begin if n2 < nPics - MaxLines + 1 then begin n2 := n2 + MaxLines; if n2 > nPics - MaxLines + 1 then n2 := nPics - MaxLines + 1 end else n2 := nPics - MaxLines + 1; sel2 := n2; end; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); end; inThumb: begin Position := getctlvalue(ControlHandle(ItemHandle)); n2 := Position; if (sel2 < n2) or (sel2 > n2 + maxLines - 1) then sel2 := n2; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); handlecontrols := true; end; end; end; CorrWindow2: begin GetDitem(myLog, CorrWindow2, ItemType, itemHandle, trect); sel2 := n2 + (Event.where.v - trect.top) div 15 - 3; ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); HandleControls := false; end; otherwise begin item := auxItem; HandleControls := true; end; end; SetPort(tPort); end else if event.what = keydown then begin charcode := BitAnd(event.message, charCodemask); if charcode = $0d then begin Item := CorrOk; HandleControls := true end; end; end; function GetCorrelationOpts: boolean; var mylog: DialogPtr; item, i: integer; auxScalingFactor: real; auxkind: Corrkind; auxDim: Corrdim; auxbut: CorrBut; tport: GrafPtr; TheCtl: ControlHandle; begin mylog := GetNewDialog(CorrDLOG, nil, pointer(-1)); GetPort(tport); Setport(mylog); OutlineButton(mylog, CorrOK, 16); ShowDim(mylog, Dimension); ShowKind(mylog, Kind); ShowBut(mylog, Button); ShowScalingNumber(mylog, ScalingFactor); auxkind := kind; auxdim := Dimension; auxbut := Button; auxScalingFactor := ScalingFactor; sel1 := 1; n1 := 1; n2 := 1; sel2 := 1; ShowWindows(mylog, CorrWindow1, CorrScrollbar1, n1, sel1); ShowWindows(mylog, CorrWindow2, CorrScrollbar2, n2, sel2); repeat ModalDialog(@HandleControls, item); case item of CorrHorizontal, CorrVertical, Corrtwod: begin auxdim := Item2dim(item); Showdim(mylog, auxdim); end; CorrAuto, CorrPairwise, CorrNext: begin auxkind := Item2Kind(item); ShowKind(mylog, auxkind); end; AutoButton, FixedButton: begin auxbut := Item2but(item); ShowBut(mylog, auxbut); end; ScaleNumber: begin auxScalingFactor := HandleScalingNumber(mylog, auxScalingFactor); ShowScalingNumber(mylog, auxScalingFactor); end; end; until (item = CorrOk) or (item = CorrCancel); GetCorrelationOpts := false; if item = CorrOk then begin Kind := Auxkind; Dimension := Auxdim; Button := auxbut; ScalingFactor := auxScalingFactor; GetCorrelationOpts := true; end; SetPort(tport); DisposDialog(mylog); end; function cutwindow2D (switch: integer; var w, h: longint; var name2: str255): boolean; var source, dest: BitMap; dstrect, sourcrect: Rect; name: str255; src, dst: ptr; Size, offset: longint; SaveInfo: InfoPtr; i: integer; begin cutwindow2D := true; if (notrectangular or notinbounds) then begin cutwindow2D := false; exit(cutwindow2D); end; with info^ do begin GetWTitle(wptr, name); end; case Switch of 1: begin name2 := name; name := concat('FFT2D - ', name); end; 2: begin delete(name, 1, 5); name := concat('Autocorr2D', name) end; 3: begin delete(name, 1, 5); name := concat('Corr2D', name, ' - ', name2); end; end; if h < w then w := h; Size := round(w div 32); case Size of 0, 1: w := 32; 2, 3: w := 32 * 2; 4, 5, 6, 7: w := 32 * 4; 8, 9, 10, 11, 12, 13, 14, 15: w := 32 * 8; 16, 17, 18, 19, 20: w := 32 * 16; otherwise w := NNN; end; h := w; if not info^.RoiShowing then KillRoi; SaveInfo := Info; if NewPicWindow(name, w, h) then with SaveInfo^ do begin Info^.x_range := x_range; Info^.y_range := y_range; Info^.z_range := z_range; offset := longint(RoiRect.top) * BytesPerRow + RoiRect.left; src := ptr(ord4(PicBaseAddr) + offset); dst := Info^.PicBaseAddr; for i := 0 to h - 1 do begin BlockMove(src, dst, w); src := ptr(ord4(src) + BytesPerRow); dst := ptr(ord4(dst) + w); end; dest.baseaddr := info^.PicBaseAddr; dest.rowBytes := info^.BytesPerRow; dest.bounds := info^.RoiRect; dstrect := dest.bounds; source.baseaddr := PicBaseAddr; source.rowBytes := BytesPerRow; source.bounds := RoiRect; sourcrect.top := RoiRect.top; sourcrect.bottom := RoiRect.top + h; sourcrect.left := RoiRect.left; sourcrect.right := RoiRect.left + w; end; {copybits(source, dest, sourcrect, dstrect, srcCopy, nil)} with Info^ do ScaleToFitWindow := true; end; function cutwindowhorizontal (switch: integer; var w, h: longint; var name2: str255): boolean; var source, dest: BitMap; dstrect, sourcrect: Rect; name: str255; src, dst: ptr; Size, offset: longint; SaveInfo: InfoPtr; i: integer; begin cutwindowhorizontal := true; if (notrectangular or notinbounds) then begin cutwindowhorizontal := false; exit(cutwindowhorizontal); end; with info^ do begin GetWTitle(wptr, name); end; case Switch of 1: begin name2 := name; name := concat('FFTHor - ', name); end; 2: begin delete(name, 1, 6); name := concat('AutocorrHor', name) end; 3: begin delete(name, 1, 6); name := concat('CorrHor', name, ' - ', name2); end; 4: begin delete(name, 1, 6); name := concat('CorrHorNext', name) end; end; Size := round(w div 32); case Size of 0, 1: w := 32; 2, 3: w := 32 * 2; 4, 5, 6, 7: w := 32 * 4; 8, 9, 10, 11, 12, 13, 14, 15: w := 32 * 8; 16, 17, 18, 19, 20: w := 32 * 16; otherwise w := NNN; end; if odd(h) then h := h - 1; if not info^.RoiShowing then KillRoi; SaveInfo := Info; if NewPicWindow(name, w, h) then with SaveInfo^ do begin Info^.x_range := x_range; Info^.y_range := y_range; Info^.z_range := z_range; offset := longint(RoiRect.top) * BytesPerRow + RoiRect.left; src := ptr(ord4(PicBaseAddr) + offset); dst := Info^.PicBaseAddr; for i := 0 to h - 1 do begin BlockMove(src, dst, w); src := ptr(ord4(src) + BytesPerRow); dst := ptr(ord4(dst) + w); end; dest.baseaddr := info^.PicBaseAddr; dest.rowBytes := info^.BytesPerRow; dest.bounds := info^.RoiRect; dstrect := dest.bounds; source.baseaddr := PicBaseAddr; source.rowBytes := BytesPerRow; source.bounds := RoiRect; sourcrect.top := RoiRect.top; sourcrect.bottom := RoiRect.top + h; sourcrect.left := RoiRect.left; sourcrect.right := RoiRect.left + w; end; {copybits(source, dest, sourcrect, dstrect, srcCopy, nil)} with Info^ do ScaleToFitWindow := true; end; procedure DoCorr2DAuto (sel: integer); var name: str255; ReFFTDataPtr, FFTDataPtr: FFTArrayPtr; i, j: longint; realpart, imagpart: extended; w, h, n_half: longint; begin if (sel <= 0) or (sel > nPics) then begin PutMessage('You have not selected any window ! No Correlation is possible'); exit(DoCorr2DAuto); end; Info := pointer(WindowPeek(PicWindow[sel])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection must be smaller than 65537 !'); exit(DoCorr2DAuto); end; w := right - left; h := bottom - top; end; name := ''; if not cutwindow2D(1, w, h, name) then exit(DoCorr2DAuto); with info^ do begin ShowWatch; ReadPictandScale(FFTArrayH, w); FFT2D(FFTArrayH, w, 1); { here we compute the auto correlation } HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; n_half := w div 2; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin realpart := FFTDataPtr^[(i * w + j) * 2] * FFTDataPtr^[(i * w + j) * 2]; imagpart := FFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2 + 1]; ReFFTDataPtr^[(i * w + j) * 2] := realpart + imagpart; ReFFTDataPtr^[(i * w + j) * 2 + 1] := 0; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); WriteFFTPict(FFTArrayH, w); { now we have to do the retransform and show the picture } ShowWatch; if not cutwindow2D(2, w, h, name) then exit(DoCorr2DAuto); ReFFT2D(ReFFTArrayH, w, -1); WriteAndScaleRealPict2D(ReFFTArrayH, w, h, Scalingfactor, Button); with FFTInfo do begin FFT_Done := true; FFTPict_Info := Info; end; end; end; procedure DoCorrHorizontalAuto (sel: integer); var ReFFTDataPtr, FFTDataPtr: FFTArrayPtr; i, j: longint; name: str255; realpart, imagpart: extended; w, h, n_half: longint; begin if (sel <= 0) or (sel > nPics) then begin PutMessage('You have not selected any window ! No Correlation is possible'); exit(DoCorrHorizontalAuto); end; Info := pointer(WindowPeek(PicWindow[sel])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection must be smaller than 65537 !'); exit(DoCorrHorizontalAuto); end; w := right - left; h := bottom - top; end; name := ''; if not cutwindowHorizontal(1, w, h, name) then exit(DoCorrHorizontalAuto); with info^ do begin ShowWatch; ReadPictAndScaleHorizontal(FFTArrayH, w, h); FFTHorizontal(FFTArrayH, w, h, 1); { here we compute the auto correlation } HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; n_half := w div 2; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin realpart := FFTDataPtr^[(i * w + j) * 2] * FFTDataPtr^[(i * w + j) * 2]; imagpart := FFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2 + 1]; ReFFTDataPtr^[(i * w + j) * 2] := realpart + imagpart; ReFFTDataPtr^[(i * w + j) * 2 + 1] := 0; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); WriteHorizontalFFTPict(FFTArrayH, w, h); { now we have to do the retransform and show the picture } ShowWatch; if not cutwindowhorizontal(2, w, h, name) then exit(DoCorrHorizontalAuto); ReFFTHorizontal(ReFFTArrayH, w, h, -1); WriteAndScaleRealPictHorizontal(ReFFTArrayH, w, h, Scalingfactor, Button); with FFTInfo do begin FFT_Done := true; FFTPict_Info := Info; end; end; end; procedure DoCorrHorizontalPair (sel1, sel2: integer); var name, savename: str255; ReFFTDataPtr, FFTDataPtr: FFTArrayPtr; i, j: longint; realpart, imagpart: extended; w, h, w1, w2, h1, h2, n_half: longint; { musste hier schnell w und h einfuehren } { da ich lauffaehige version brauchte } begin if (sel1 <= 0) or (sel1 > nPics) or (sel2 <= 0) or (sel2 > nPics) then begin PutMessage('You have not selected enough windows ! No Correlation is possible'); exit(DoCorrHorizontalPair); end; Info := pointer(WindowPeek(PicWindow[sel1])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection 1 must be smaller than 65537 !'); exit(DoCorrHorizontalPair); end; w1 := right - left; h1 := bottom - top; end; Info := pointer(WindowPeek(PicWindow[sel2])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection 2 must be smaller than 65537 !'); exit(DoCorrHorizontalPair); end; w2 := right - left; h2 := bottom - top; end; if w1 < w2 then w := w1 else w := w2; if h1 < h2 then h := h1 else h := h2; Info := pointer(WindowPeek(PicWindow[sel1])^.RefCon); name := ''; if not cutwindowhorizontal(1, w, h, name) then exit(DoCorrHorizontalPair); with info^ do begin ShowWatch; ReadPictAndScaleHorizontal(FFTArrayH, w, h); FFTHorizontal(FFTArrayH, w, h, 1); WriteHorizontalFFTPict(FFTArrayH, w, h); HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin ReFFTDataPtr^[(i * w + j) * 2] := FFTDataPtr^[(i * w + j) * 2]; ReFFTDataPtr^[(i * w + j) * 2 + 1] := FFTDataPtr^[(i * w + j) * 2 + 1]; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); end; Info := pointer(WindowPeek(PicWindow[sel2])^.RefCon); savename := name; if not cutwindowhorizontal(1, w, h, name) then exit(DoCorrHorizontalPair); name := savename; with info^ do begin ReadPictAndScaleHorizontal(FFTArrayH, w, h); FFTHorizontal(FFTArrayH, w, h, 1); WriteHorizontalFFTPict(FFTArrayH, w, h); HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin realpart := ReFFTDataPtr^[(i * w + j) * 2] * FFTDataPtr^[(i * w + j) * 2] + ReFFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2 + 1]; imagpart := ReFFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2] - FFTDataPtr^[(i * w + j) * 2 + 1] * ReFFTDataPtr^[(i * w + j) * 2]; ReFFTDataPtr^[(i * w + j) * 2] := realpart; ReFFTDataPtr^[(i * w + j) * 2 + 1] := imagpart; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); { now we have to do the retransform and show the picture } ShowWatch; if not cutwindowhorizontal(3, w, h, name) then exit(DoCorrHorizontalPair); ReFFTHorizontal(ReFFTArrayH, w, h, -1); WriteAndScaleRealPictHorizontal(ReFFTArrayH, w, h, ScalingFactor, Button); with FFTInfo do begin FFT_Done := true; FFTPict_Info := Info; end; end; end; procedure DoCorr2DPair (sel1, sel2: integer); var name, savename: str255; ReFFTDataPtr, FFTDataPtr: FFTArrayPtr; i, j: longint; realpart, imagpart: extended; w, h, n_half, w1, w2, h1, h2: longint; begin if (sel1 <= 0) or (sel1 > nPics) or (sel2 <= 0) or (sel2 > nPics) then begin PutMessage('You have not selected enough windows ! No Correlation is possible'); exit(DoCorr2DPair); end; Info := pointer(WindowPeek(PicWindow[sel1])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection 1 must be smaller than 65537 !'); exit(DoCorr2DPair); end; w1 := right - left; h1 := bottom - top; end; Info := pointer(WindowPeek(PicWindow[sel2])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection 2 must be smaller than 65537 !'); exit(DoCorr2DPair); end; w2 := right - left; h2 := bottom - top; end; if w1 < w2 then w := w1 else w := w2; if h1 < h2 then h := h1 else h := h2; Info := pointer(WindowPeek(PicWindow[sel1])^.RefCon); name := ''; if not cutwindow2D(1, w, h, name) then exit(DoCorr2DPair); with info^ do begin ShowWatch; ReadPictandScale(FFTArrayH, w); FFT2D(FFTArrayH, w, 1); WriteFFTPict(FFTArrayH, w); { here we compute the auto correlation } HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin ReFFTDataPtr^[(i * w + j) * 2] := FFTDataPtr^[(i * w + j) * 2]; ReFFTDataPtr^[(i * w + j) * 2 + 1] := FFTDataPtr^[(i * w + j) * 2 + 1]; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); end; Info := pointer(WindowPeek(PicWindow[sel2])^.RefCon); savename := name; if not cutwindow2D(1, w, h, name) then exit(DoCorr2DPair); name := savename; with info^ do begin ShowWatch; ReadPictandScale(FFTArrayH, w); FFT2D(FFTArrayH, w, 1); WriteFFTPict(FFTArrayH, w); HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; n_half := w div 2; for i := 0 to h - 1 do begin for j := 0 to w - 1 do begin realpart := ReFFTDataPtr^[(i * w + j) * 2] * FFTDataPtr^[(i * w + j) * 2] + ReFFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2 + 1]; imagpart := ReFFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2] - FFTDataPtr^[(i * w + j) * 2 + 1] * ReFFTDataPtr^[(i * w + j) * 2]; ReFFTDataPtr^[(i * w + j) * 2] := realpart; ReFFTDataPtr^[(i * w + j) * 2 + 1] := imagpart; end; end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); { now we have to do the retransform and show the picture } ShowWatch; if not cutwindow2D(3, w, h, name) then exit(DoCorr2DPair); ReFFT2D(ReFFTArrayH, w, -1); WriteAndScaleRealPict2D(ReFFTArrayH, w, h, Scalingfactor, Button); with FFTInfo do begin FFT_Done := true; FFTPict_Info := Info; end; end; end; procedure DoCorrHorizontalNextLine (sel: integer); var ReFFTDataPtr, FFTDataPtr: FFTArrayPtr; name: str255; i, j: longint; realpart, imagpart: extended; w, h, n_half: longint; begin if (sel <= 0) or (sel > nPics) then begin PutMessage('You have not selected any window No Correlation is possible'); exit(DoCorrHorizontalNextLine); end; Info := pointer(WindowPeek(PicWindow[sel])^.RefCon); if not info^.RoiShowing then SelectAll(false); with info^.RoiRect do begin if (longint(right - left) * longint(bottom - top)) > 65536 then begin putmessage('Width * Height of the selection must be smaller than 65537 !'); exit(DoCorrHorizontalNextLine); end; w := right - left; h := bottom - top; end; name := ''; if not cutwindowHorizontal(1, w, h, name) then exit(DoCorrHorizontalNextLine); with info^ do begin ShowWatch; ReadPictAndScaleHorizontal(FFTArrayH, w, h); FFTHorizontal(FFTArrayH, w, h, 1); { here we compute the auto correlation } HLock(Handle(FFTArrayH)); FFTDataPtr := FFTArrayH^; HLock(Handle(ReFFTArrayH)); ReFFTDataPtr := ReFFTArrayH^; n_half := w div 2; for i := 0 to h - 2 do begin for j := 0 to w - 1 do begin realpart := FFTDataPtr^[(i * w + j) * 2] * FFTDataPtr^[((i + 1) * w + j) * 2] + FFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[((i + 1) * w + j) * 2 + 1]; imagpart := FFTDataPtr^[(i * w + j) * 2 + 1] * FFTDataPtr^[((i + 1) * w + j) * 2] - FFTDataPtr^[((i + 1) * w + j) * 2 + 1] * FFTDataPtr^[(i * w + j) * 2]; ReFFTDataPtr^[(i * w + j) * 2] := realpart; ReFFTDataPtr^[(i * w + j) * 2 + 1] := imagpart; end; end; for j := 0 to w - 1 do begin ReFFTDataPtr^[((h - 1) * w + j) * 2] := 0; ReFFTDataPtr^[((h - 1) * w + j) * 2 + 1] := 0 end; HUnlock(handle(FFTArrayH)); HUnlock(handle(ReFFTArrayH)); WriteHorizontalFFTPict(FFTArrayH, w, h); { now we have to do the retransform and show the picture } ShowWatch; if not cutwindowhorizontal(4, w, h, name) then exit(DoCorrHorizontalNextLine); ReFFTHorizontal(ReFFTArrayH, w, h, -1); WriteAndScaleRealPictHorizontal(ReFFTArrayH, w, h, ScalingFactor, Button); with FFTInfo do begin FFT_Done := true; FFTPict_Info := Info; end; end; end; procedure DoCorrelation; begin CheckInputOptions; if GetCorrelationOpts then case kind of auto: begin case Dimension of horizontal: DoCorrHorizontalAuto(sel1); vertical: PutMessage('Sorry ! This kind of correlation is not implemented yet'); twodimensional: DoCorr2DAuto(sel1); end; end; NextLine: begin case Dimension of horizontal: DoCorrHorizontalNextLine(sel1); vertical: PutMessage('Sorry ! This kind of correlation is not implemented yet'); twodimensional: PutMessage('Sorry ! This kind of correlation is not implemented yet'); end; end; pair: begin case Dimension of horizontal: DoCorrHorizontalPair(sel1, sel2); vertical: PutMessage('Sorry ! This kind of correlation is not implemented yet'); twodimensional: DoCorr2DPair(sel1, sel2); end; end; end; end; end.