unit Camera; {Routines used by the Image program for supporting the Data Translation} {QuickCapture card and the Scion Image Capture 2.} interface uses QuickDraw, Palettes, PrintTraps, globals, Utilities, Graphics, File1; procedure AverageFrames; procedure CaptureAndDisplayQCFrame; procedure StartDigitizing; procedure StopDigitizing; procedure SetVideoChannel; procedure MakeMovie; function GetQCPixel (h, v: integer): integer; procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect); implementation var SavePicBaseAddr: ptr; procedure CorrectShadingOfLine (PicPtr, BFPtr: ptr; width, BFMean: integer); {} {TYPE} { lptr=^LineType;} {VAR} { PicLine,BFLine:lptr;} { i,value:integer;} {BEGIN} { PicLine:=lptr(PicPtr);} { BFLine:=lptr(BFPtr);} { FOR i:=0 TO width-1 DO BEGIN} { value:=PicLine^[i];} { value:=255-value;} { value:=(LongInt(value)*BFMean+(BFLine^[i] DIV 2)) DIV BFLine^[i];} { IF value>254 THEN value:=254;} { IF value<1 THEN value:=1;} { PicLine^[i]:=255-value;} { END;} { } {a0=data pointer} {a1=blank field data pointer} {d0=count} {d1=pixel value} {d2=blank field pixel value} {d3=blank field mean} {d4=temp} {d5=max pixel value(245)} {d6=min pixel value(1)} inline $4E56, $0000, { link a6,#0} $48E7, $FEC0, { movem.l a0-a1/d0-d6,-(sp)} $206E, $000C, { move.l 12(a6),a0} $226E, $0008, { move.l 8(a6),a1} $4280, { clr.l d0} $302E, $0006, { move.w 6(a6),d0} $362E, $0004, { move.w 4(a6),d3} $2A3C, $0000, $00FE, { move.l #254,d5} $2C3C, $0000, $0001, { move.l #1,d6} $5380, { subq.l #1,d0} $4281, { clr.l d1} $4282, { clr.l d2} $1210, {L1 move.b (a0),d1} $1419, { move.b (a1)+,d2} $4601, { not.b d1} $C2C3, { mulu.w d3,d1} $2802, { move.l d2,d4} $E244, { asr.w #1,d4} $D284, { add.l d4,d1} $82C2, { divu.w d2,d1} $B245, { cmp.w d5,d1} $6F02, { ble.s L2} $3205, { move.w d5,d1} $B246, {L2 cmp.w d6,d1} $6C02, { bge.s L3} $3206, { move.w d6,d1} $4601, {L3 not.b d1} $10C1, { move.b d1,(a0)+} $51C8, $FFDE, { dbra d0,L1} $4CDF, $037F, { movem.l (sp)+,a0-a1/d0-d6} $4E5E, { unlk a6} $DEFC, $000C; { add.w #12,sp} {END;} procedure CorrectShading; var i: integer; offset: LongInt; p1, p2: ptr; begin with info^ do begin if ImageSize <> BlankFieldInfo^.ImageSize then begin beep; exit(CorrectShading); end; ShowWatch; p1 := PicBaseAddr; p2 := BlankFieldInfo^.PicBaseAddr; for i := 1 to nLines do begin CorrectShadingOfLine(p1, p2, PixelsPerLine, BlankFieldMean); p1 := ptr(ord4(p1) + info^.BytesPerRow); p2 := ptr(ord4(p2) + BlankFieldInfo^.BytesPerRow); if i mod 96 = 0 then UpdatePicWindow; end; UpdatePicWindow; SetWTitle(wptr, 'Camera(Corrected)'); end; end; procedure CopyOffscreen (src, dst: PixMapHandle; sRect, dRect: rect); begin hlock(handle(src)); hlock(handle(dst)); CopyBits(BitMapHandle(src)^^, BitMapHandle(dst)^^, sRect, dRect, SrcCopy, nil); hunlock(handle(src)); hunlock(handle(dst)); end; procedure StopDigitizing; begin if digitizing then with info^ do begin ShowFrameRate('', DTStartTicks, DTFrameCount); CopyOffscreen(qcPort^.portPixMap, osPort^.portPixMap, PicRect, PicRect); SetItem(SpecialMenuH, StartItem, 'Start Capturing'); Digitizing := false; ContinuousHistogram := false; with info^ do if PictureType = QuickCaptureType then begin title := 'Camera'; ShowMagnification; end; if (BlankFieldInfo <> nil) and not OptionKeyDown then CorrectShading; end; end; procedure GetQuickCaptureFrame; begin if OptionKeyWasDown then begin {Wait for external trigger, then capture one frame} ControlReg^ := BitAnd($82, 255); while ControlReg^ < 0 do ; {Wait for it to complete} StopDigitizing; end else begin ControlReg^ := BitAnd($80, 255); {Start frame capture} while ControlReg^ < 0 do ; {Wait for it to complete} end; DTFrameCount := DTFrameCount + 1; end; procedure CaptureAndDisplayQCFrame; var tPort: GrafPtr; begin with info^ do begin if (PictureType <> QuickCaptureType) or (PixelsPerLine <> qcWidth) or (nlines <> qcHeight) then begin Digitizing := false; exit(CaptureAndDisplayQCFrame); end; GetQuickCaptureFrame; getPort(tPort); SetPort(wptr); hlock(handle(qcPort^.portPixMap)); hlock(handle(CGrafPort(wptr^).PortPixMap)); CopyBits(BitMapHandle(qcPort^.portPixMap)^^, BitMapHandle(CGrafPort(wptr^).PortPixMap)^^, SrcRect, wrect, SrcCopy, nil); hunlock(handle(qcPort^.portPixMap)); hunlock(handle(CGrafPort(wptr^).PortPixMap)); SetPort(tPort); end; end; procedure SetReg (index, value: integer); const RegOffset = $f5fe0; var reg: ptr; begin reg := ptr(ScionSlotBase + RegOffset + index * 4); reg^ := value; end; procedure ResetScion (GrabRect: rect; DisplayPoint: point); const ilutOffset = $f0000; LineStartsRamOffset = $f4000; type LineStartsArray = packed array[0..8191] of UnsignedByte; LineStartsType = ^LineStartsArray; var ScreenRowBytesx2: LongInt; LutPtr: ptr; LineStarts: LineStartsType; EvenStart, OddStart: LongInt; width, height, IndexOdd, IndexEven, index, i: integer; hstart, vstart: integer; begin ScreenRowBytesx2 := ScreenRowBytes * 2; LoadInputLookUpTable(Ptr(ScionSlotBase + ilutOffset)); with GrabRect, DisplayPoint do begin hstart := BitAnd(left, $fffc); vstart := BitAnd(top, $fffe); width := right - left; height := bottom - top; EvenStart := LongInt(ScreenBase) + h + ScreenRowBytes * v; OddStart := EvenStart + ScreenRowBytes; IndexOdd := 0; IndexEven := (height div 2) * 16; end; LineStarts := LineStartsType(ScionSlotBase + LineStartsRamOffset); for i := 1 to height div 2 do begin LineStarts^[IndexOdd] := BSR(BitAnd(OddStart, $ff000000), 24); LineStarts^[IndexOdd + 4] := BSR(BitAnd(OddStart, $ff0000), 16); LineStarts^[IndexOdd + 8] := BSR(BitAnd(OddStart, $ff00), 8); LineStarts^[IndexOdd + 12] := BitAnd(OddStart, $fc); LineStarts^[IndexEven] := BSR(BitAnd(EvenStart, $ff000000), 24); LineStarts^[IndexEven + 4] := BSR(BitAnd(EvenStart, $ff0000), 16); LineStarts^[IndexEven + 8] := BSR(BitAnd(EvenStart, $ff00), 8); LineStarts^[IndexEven + 12] := BitAnd(EvenStart, $fc); IndexOdd := IndexOdd + 16; IndexEven := IndexEven + 16; OddStart := OddStart + ScreenRowBytesx2; EvenStart := EvenStart + ScreenRowBytesx2; end; Index := height * 16; LineStarts^[Index] := 0; LineStarts^[Index + 4] := 0; LineStarts^[Index + 8] := 0; LineStarts^[Index + 12] := 1; SetReg(1, 0); SetReg(2, 162 - (width div 4)); SetReg(3, 0); SetReg(4, 225 - (hstart div 4)); SetReg(5, 255 - (width div 4)); SetReg(6, 241 - (vstart div 2)); SetReg(7, 255 - (height div 2)); end; procedure GetScionFrame (DisplayPoint: point); {Captures a single Scion frame to screen memory.} type IntPtr = ^integer; var FlagLoc: IntPtr; StartTime: LongInt; begin with DisplayPoint do FlagLoc := IntPtr(LongInt(ScreenBase) + h + ScreenRowBytes * v + 4); FlagLoc^ := $00ff; StartTime := TickCount; SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable} while FlagLoc^ = $00ff do if TickCount > (StartTime + 5) then begin SetReg(1, 0); {Stop Grabbing} exit(GetScionFrame) end; SetReg(1, 0); {Stop Grabbing} end; function GetScreenPixel (h, v: integer): integer; var offset: LongInt; p: ptr; begin offset := LongInt(v) * ScreenRowBytes + h; p := ptr(ord4(ScreenBase) + offset); GetScreenPixel := BAND(p^, 255); end; procedure CopyScionFrameOffscreen (DisplayPoint: point; wwidth, wheight: integer); var src, dst: ptr; line: integer; begin with Info^ do begin with DisplayPoint do src := ptr(LongInt(ScreenBase) + h + ScreenRowBytes * v); dst := ptr(LongInt(PicBaseAddr)); for line := 1 to wheight do begin BlockMove(src, dst, wwidth); src := ptr(ord4(src) + ScreenRowBytes); dst := ptr(ord4(dst) + BytesPerRow); end; end; end; procedure DoMiniEventLoop (FullScreenMode: boolean); var loc: point; event: EventRecord; begin FlushEvents(EveryEvent, 0); if not FullScreenMode then DrawLabels('X:', 'Y:', 'Value:'); repeat GetMouse(loc); LocalToGlobal(loc); if not FullScreenMode then with loc do Show3Values(h, v, GetScreenPixel(h, v)); until WaitNextEvent(mDownMask + KeyDownMask, Event, 0, nil); end; procedure CaptureUsingScion; var GrabRect, ScreenSrcRect: rect; DisplayPoint: point; FullScreenMode: boolean; wwidth, wheight: integer; tPort: GrafPtr; SaveBackgroundColor, hstart, vstart: integer; ignore: integer; mloc: point; MainDevice: GDHandle; SrcPixMap: PixMapHandle; begin FullScreenMode := OptionKeyDown and (ScreenWidth = 640); if FullScreenMode or (ScreenWidth > 640) then begin wwidth := MaxScionWidth; wheight := 480 end else begin wwidth := 552; if wwidth > MaxScionWidth then wwidth := MaxScionWidth; wheight := 436; end; if ScionInfo <> nil then with ScionInfo^.wrect, ScionInfo^ do if (wwidth <> right) or (wheight <> bottom) then begin changes := false; ignore := CloseAWindow(wptr); end; if (ScionInfo <> nil) and (info^.PictureType <> ScionType) then begin SelectWindow(ScionInfo^.wptr); info := ScionInfo; end; if ScionInfo <> nil then BringToFront(ScionInfo^.wptr); with info^ do if PictureType <> ScionType then begin if not NewPicWindow('Camera(Scion)', wwidth, wheight) then begin beep; exit(CaptureUsingScion) end; ScionInfo := info; end; KillRoi; with info^ do begin PictureType := ScionType; changes := true; SetWTitle(wptr, 'Camera(Live)'); end; hstart := (640 - wwidth) div 2; vstart := (480 - wheight) div 2; SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight); if FullScreenMode then with DisplayPoint do begin h := BitAnd((640 - wwidth) div 2, $fffc); v := 0; end else with DisplayPoint do begin h := PicLeftBase; v := PicTopBase; end; ResetScion(GrabRect, DisplayPoint); if FullScreenMode then begin GetPort(tPort); SaveBackgroundColor := BackgroundIndex; SetBackgroundColor(BlackIndex); EraseScreen; end; if info^.magnification <> 1.0 then Unzoom; SetReg(1, BitOr(128, VideoChannel * 4)); {Grab Enable} DoMiniEventLoop(FullScreenMode); SetReg(1, 0); {Stop Grabbing} HideCursor; GetScionFrame(DisplayPoint); MainDevice := GetMainDevice; SrcPixMap := MainDevice^^.gdPMap; with DisplayPoint, ScreenSrcRect do begin left := h; top := v; right := left + wwidth; bottom := top + wheight; end; with info^ do CopyOffscreen(SrcPixMap, osPort^.portPixMap, ScreenSrcRect, PicRect); ShowCursor; if FullScreenMode then begin RestoreScreen; SetBackgroundColor(SaveBackgroundColor); SetPort(tPort); end; info^.title := 'Camera'; ShowMagnification; SetWTitle(info^.wptr, 'Camera'); if (BlankFieldInfo <> nil) and not OptionKeyDown then CorrectShading; FlushEvents(EveryEvent, 0); end; procedure StartDigitizing; var i, width, height: integer; begin if FrameGrabber = Scion then begin CaptureUsingScion; exit(StartDigitizing) end; if Digitizing then begin StopDigitizing; if BlankFieldInfo <> nil then wait(15); FlushEvents(EveryEvent, 0); {In case user holds key down too long} exit(StartDigitizing) end; if FrameGrabber = NoFrameGrabber then begin PutMessage('Digitizing Requires a Data Translation or SCION frame grabber card.'); exit(StartDigitizing) end; if (QuickCaptureInfo <> nil) and (info^.PictureType <> QuickCaptureType) then begin SelectWindow(QuickCaptureInfo^.wptr); info := QuickCaptureInfo; end; with info^ do if (PictureType <> QuickCaptureType) or (PixelsPerLine <> qcWidth) or (nlines <> qcHeight) then begin if not NewPicWindow('Camera', qcWidth, qcHeight) then exit(StartDigitizing); with info^ do if not EqualRect(SrcRect, PicRect) then {Center Frame} with SrcRect do begin width := right - left; height := bottom - top; left := (PicRect.right - width) div 2; right := left + width; top := (PicRect.bottom - height) div 2; bottom := top + height; end; end; KillRoi; with info^ do begin if ScaleToFitWindow then ScaleToFit; with SrcRect do {Prevents bus errors when Camera window moved.} if (top = 0) and (bottom < PicRect.bottom) then begin top := top + 1; bottom := bottom + 1; end; ResetQuickCapture; Digitizing := true; SetItem(SpecialMenuH, StartItem, 'Stop Capturing'); changes := true; BinaryPic := false; SetWTitle(wptr, 'Camera(Live)'); end; DTFrameCount := 0; DTStartTicks := TickCount; ContinuousHistogram := false; end; procedure AddLineToSum (src, dst: ptr; width: LongInt); {$IFC false} type SumLineType = array[0..2047] of integer; fptr = ^SumLineType; lptr = ^LineType; var FrameLine: lptr; SumLine: fptr; i: integer; begin FrameLine := lptr(src); SumLine := fptr(dst); for i := 0 to width - 1 do SumLine^[i] := SumLine^[i] + FrameLine^[i]; end; {$ENDC} inline {a0=data pointer} {a1=sum buffer pointer} {d0=count} {d1=pixel value} {d2=temp} $4E56, $0000, {link a6,#0} $48E7, $E0C0, {movem.l a0-a1/d0-d2,-(sp)} $206E, $000C, {move.l 12(a6),a0} $226E, $0008, {move.l 8(a6),a1} $202E, $0004, {move.l 4(a6),d0} $5380, {subq.l #1,d0} $4281, {clr.l d1} $4282, {clr.l d2} $1218, {L1 move.b (a0)+,d1} $3411, {move.w (a1),d2} $D441, {add.w d1,d2} $32C2, {move.w d2,(a1)+} $51C8, $FFF6, {dbra d0,L1} $4CDF, $0307, {movem.l (sp)+,a0-a1/d0-d2} $4E5E, {unlk a6} $DEFC, $000C; {add.w #12,sp} procedure AverageFrames; type IntPtr = ^integer; SumLineType = array[0..2047] of integer; sptr = ^SumLineType; lptr = ^LineType; var AutoSelectAll: boolean; SelectionSize, FrameBufferSize, offset, StartTicks: LongInt; SumBase, src, srcbase, dst, OffscreenBase: ptr; str1, str2: str255; xLines, xPixelsPerLine, xPixelsPerLine2, frame, line, pixel: integer; aline: LineType; GrabRect: rect; DisplayPoint: point; hstart, vstart, wwidth, wheight, MinV, MaxV, value: integer; j, range, FramesAveraged: integer; SrcRowBytes, DstRowBytes, i: LongInt; SumFrames: boolean; iptr: IntPtr; FrameLine: lptr; SumLine: sptr; SaveBlankFieldInfo: InfoPtr; begin SaveBlankFieldInfo := BlankFieldInfo; BlankFieldInfo := nil; {We don't want to do shading correction now} StopDigitizing; BlankFieldInfo := SaveBlankFieldInfo; SumFrames := OptionKeyWasDown; OptionKeyWasDown := false; DrawLabels('Frame:', 'Total:', ''); if (info <> QuickCaptureInfo) and (info <> ScionInfo) then begin PutMessage('You must have an active Camera window(created using Start Digitizing) in order to average frames.'); exit(AverageFrames) end; if NotRectangular or NotinBounds then exit(AverageFrames); ShowWatch; AutoSelectAll := not Info^.RoiShowing; if AutoSelectAll then SelectAll(false); with info^.RoiRect do SelectionSize := (LongInt(right) - left) * (bottom - top); FrameBufferSize := SelectionSize * 2; if FrameBufferSize > BigBufSize then begin NumToString(FrameBufferSize div 1024, str1); NumToString(BigBufSize div 1024, str2); str2 := concat(str1, 'K bytes are required, but only ', str2, 'K bytes are available.'); PutMessage(concat('There is not enough memory to do the requested frame averaging. ', str2)); if AutoSelectAll or (BlankFieldInfo <> nil) then KillRoi else ShowRoi; exit(AverageFrames) end; WhatToUndo := NothingToUndo; WhatsOnClip := Nothing; SumBase := BigBuf; if FrameGrabber = QuickCapture then begin ContinuousHistogram := false; ResetQuickCapture end else begin with info^.wrect do begin wwidth := right; wheight := bottom; end; hstart := (640 - wwidth) div 2; vstart := (480 - wheight) div 2; SetRect(GrabRect, hstart, vstart, hstart + wwidth, vstart + wheight); with DisplayPoint do begin h := PicLeftBase; v := PicTopBase; end; ResetScion(GrabRect, DisplayPoint); HideCursor; end; with info^, info^.RoiRect do begin offset := left + LongInt(top) * BytesPerRow; OffscreenBase := ptr(ord4(PicBaseAddr) + offset); if FrameGrabber = QuickCapture then begin offset := left + LongInt(top) * qcRowBytes; srcbase := ptr(ord4(ptr(DTSlotBase)) + offset); SrcRowBytes := qcRowBytes; end else with DisplayPoint do begin BringToFront(wptr); offset := left + h + (v + top) * ScreenRowBytes; srcbase := ptr(ord4(ScreenBase) + offset); SrcRowBytes := ScreenRowBytes; end; xLines := bottom - top; xPixelsPerLine := right - left; xPixelsPerLine2 := xPixelsPerLine * 2; end; dst := SumBase; for line := 1 to xLines do begin {zero buffer} BlockMove(@BlankLine, dst, xPixelsPerLine2); dst := ptr(ord4(dst) + xPixelsPerLine2); end; info^.title := 'Camera'; ShowMagnification; StartTicks := TickCount; for frame := 0 to FramesToAverage - 1 do begin Show2Values(frame + 1, FramesToAverage); if FrameGrabber = QuickCapture then GetQuickCaptureFrame else GetScionFrame(DisplayPoint); src := srcbase; dst := SumBase; for line := 1 to xLines do begin AddLineToSum(src, dst, xPixelsPerLine); src := ptr(ord4(src) + SrcRowBytes); dst := ptr(ord4(dst) + xPixelsPerLine2); end; if FrameGrabber = QuickCapture then UpdateScreen(info^.RoiRect); if CommandPeriod then begin beep; if AutoSelectAll then KillRoi else ShowRoi; exit(AverageFrames); end; end; {for} src := SumBase; dst := OffscreenBase; DstRowBytes := info^.BytesPerRow; if SumFrames then begin MinV := 32767; MaxV := 0; iptr := IntPtr(src); for i := 1 to SelectionSize do begin value := iptr^; if value > MaxV then MaxV := value; if value < MinV then MinV := value; iptr := IntPtr(ord4(iptr) + 2); end; range := MaxV - MinV; if range <> 0 then for line := 1 to xLines do begin SumLine := sptr(src); FrameLine := lptr(dst); for j := 0 to xPixelsPerLine - 1 do begin value := SumLine^[j] - MinV + 1; value := LongInt(value) * 254 div range; FrameLine^[j] := value; end; src := ptr(ord4(src) + xPixelsPerLine2); dst := ptr(ord4(dst) + DstRowBytes); end else beep; end else for line := 1 to xLines do begin SumLine := sptr(src); FrameLine := lptr(dst); for j := 0 to xPixelsPerLine - 1 do FrameLine^[j] := SumLine^[j] div FramesToAverage; src := ptr(ord4(src) + xPixelsPerLine2); dst := ptr(ord4(dst) + DstRowBytes); end; RealToString((TickCount - StartTicks) / 60.0, 1, 2, str1); ShowFrameRate(concat(Long2str(FramesToAverage), ' frames', cr, str1, ' seconds', cr), StartTicks, FramesToAverage); UpdatePicWindow; if AutoSelectAll then KillRoi else ShowRoi; if BlankFieldInfo <> nil then CorrectShading; end; procedure SetVideoChannel; var TempChannel: integer; begin if FrameGrabber = Scion then begin TempChannel := GetInt('Scion Input Channel(1..4):', VideoChannel + 1); TempChannel := TempChannel - 1; end else TempChannel := GetInt('QuickCapture Input Channel(0..3):', VideoChannel); if (TempChannel >= 0) and (TempChannel <= 3) then VideoChannel := TempChannel; end; procedure MakeMovie; var nFrames, wleft, wtop, width, height, frame, i, LastFrame: integer; FramesWanted: integer; OutOfMemory: boolean; name, str1, str2: str255; FrameInfo: array[1..MaxPics] of InfoPtr; DisplayPoint: point; StartTicks, NextTicks, interval, ElapsedTime: LongInt; SecondsBetweenFrames, seconds: extended; frect: rect; MainDevice: GDHandle; SourcePixMap: PixMapHandle; TimeStamp: array[1..MaxPics] of LongInt; begin with info^ do begin if (PictureType <> QuickCaptureType) and (PictureType <> ScionType) then begin PutMessage('You must be digitizing in order to make a movie.'); exit(MakeMovie); end; StopDigitizing; FramesWanted := GetInt('Number of Frames:', 10); if FramesWanted = -MaxInt then {cancel} exit(MakeMovie); if FramesWanted < 1 then FramesWanted := 1; if FramesWanted > MaxPics then FramesWanted := MaxPics; if RoiShowing then with RoiRect do begin if odd(right - left) and (right < PicRect.right) then begin right := right + 1; MakeRegion; end; wleft := left; wtop := top; width := right - left; height := bottom - top; end else with PicRect do begin wleft := 0; wtop := 0; width := right - left; height := bottom - top; end; end; {with info^} if FrameGrabber = Scion then begin with DisplayPoint do begin h := PicLeftBase; v := PicTopBase; end; with frect do begin left := PicLeftBase + wleft; top := PicTopBase + wtop; right := left + width; bottom := top + height; end; end else with frect do begin left := wleft; top := wtop; right := left + width; bottom := top + height; end; nFrames := 0; repeat NumToString(nFrames, name); OutOfMemory := not NewPicWindow(name, width, height); if not OutOfMemory then begin nFrames := nFrames + 1; FrameInfo[nFrames] := info; end; until (nFrames = FramesWanted) or OutOfMemory; SecondsBetweenFrames := GetReal('Delay Between Frames(seconds):', 0.0); DrawLabels('Frame:', 'Total:', ''); if SecondsBetweenFrames = BadReal then Exit(MakeMovie); if SecondsBetweenFrames < 0.0 then SecondsBetweenFrames := 0.0; interval := round(60.0 * SecondsBetweenFrames); if FrameGrabber = Scion then begin HideCursor; MainDevice := GetMainDevice; SourcePixMap := MainDevice^^.gdPMap; end else begin ShowWatch; SourcePixMap := qcPort^.portPixMap; ResetQuickCapture; end; StartTicks := TickCount; NextTicks := StartTicks; LastFrame := nFrames; for frame := 1 to nFrames do begin NextTicks := NextTicks + Interval; TimeStamp[frame] := TickCount; with FrameInfo[frame]^ do begin if FrameGrabber = QuickCapture then GetQuickCaptureFrame else GetScionFrame(DisplayPoint); CopyOffscreen(SourcePixMap, osPort^.portPixMap, frect, SrcRect); changes := true; end; if Interval > 0 then begin Show2Values(frame, nFrames); while TickCount < NextTicks do begin if CommandPeriod then begin beep; LastFrame := frame; exit(MakeMovie); end; end; end; end; {for} seconds := (TickCount - StartTicks) / 60.0; RealToString(seconds, 1, 2, str1); str1 := concat(long2str(nFrames), ' frames', cr, str1, ' seconds', cr); if nFrames >= seconds then ShowFrameRate(str1, StartTicks, nFrames) else begin RealToString(seconds / nFrames, 1, 2, str2); ShowMessage(concat(str1, str2, ' seconds/frame')); end; for frame := 1 to LastFrame do begin ElapsedTime := TimeStamp[frame] - StartTicks; if interval < 60 then RealToString(ElapsedTime, 6, 0, name) else RealToString(ElapsedTime / 60.0, 9, 2, name); i := 1; while (name[i] = ' ') and (i <= 6) do begin name[i] := '0'; i := i + 1; end; SetWTitle(FrameInfo[frame]^.wptr, name); with FrameInfo[frame]^ do begin title := name; UpdateWindowsMenuItem(ImageSize, title, PicNum); end; end; end; function GetQCPixel (h, v: integer): integer; var offset: LongInt; p: ptr; begin with Info^ do begin if (h < 0) or (v < 0) or (h >= qcWidth) or (v >= qcHeight) then begin GetQCPixel := WhiteIndex; exit(GetQCPixel); end; offset := LongInt(v) * qcRowBytes + h; if offset >= LongInt(qcHeight) * qcRowBytes then begin GetQCPixel := WhiteIndex; exit(GetQCPixel); end; p := ptr(ord4(ptr(DTSlotBase)) + offset); GetQCPixel := BAND(p^, 255); end; end; end.