unit Init;

interface


	uses
		Types, Memory, QuickDraw, QuickDrawText, Packages, Menus, Events, Fonts, 
		Scrap, ToolUtils, Resources, Errors, Palettes, StandardFile, Windows,
		Controls, TextEdit, Files, Dialogs, TextUtils, Finder, MixedMode, SegLoad,
		Folders, Slots, OSUtils, Strings, GestaltEqu, Processes,
		globals, Utilities, Graphics, Lut;

	procedure Init;
	procedure AllocateBuffers;
	procedure AllocateArrays;
	procedure SetupMenus;
	procedure GetPreferences(f: integer);
	procedure GetSettings;
	procedure FindPlugIns;
	
	{To compile NIH Image so that it supports Scion PCI frame grabbers you
	will need to set 'SupportScionPCI' to 1 and add the following libraries
	in the NIH Image project:
	
					ScionPCI.lib
					PCILib
					NameRegistryLib
					DriverServicesLib
	
	ScionPCI.lib is included with the NIH Image source. The other libraries
	are on Apple's Developer CD.}
	
	{$SETC SupportScionPCI := 1}

	{$ifc PowerPC and SupportScionPCI}
	function LookForPCIFrameGrabbers(model: integer; var base0: longint; var base1: longint; var buffers: longint): boolean; C; EXTERNAL;
	{$endc}


implementation


	procedure MakeCursors;
		var
			TempCurH: CursHandle;
			i, id: integer;
	begin
		TempCurH := GetCursor(PickerCursorID);
		if TempCurH <> nil then
			begin
				PickerCursor := TempCurH^^;
				ToolCursor[PickerTool] := PickerCursor;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(CrossCursorPlusID);
		if TempCurH <> nil then
			begin
				CrossPlusCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(CrossCursorMinusID);
		if TempCurH <> nil then
			begin
				CrossMinusCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(WandPlusCursorID);
		if TempCurH <> nil then
			begin
				WandPlusCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(WandMinusCursorID);
		if TempCurH <> nil then
			begin
				WandMinusCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(CrossCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[SelectionTool] := TempCurH^^;
				ToolCursor[FreehandTool] := TempCurH^^;
				ToolCursor[PolygonTool] := TempCurH^^;
				ToolCursor[ruler] := TempCurH^^;
				ToolCursor[PlotTool] := TempCurH^^;
				ToolCursor[OvalSelectionTool] := TempCurH^^;
				ToolCursor[LineTool] := TempCurH^^;
				ToolCursor[AngleTool] := TempCurH^^;
				ToolCursor[CrossHairTool] := TempCurH^^;
				ToolCursor[LUTTool] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(LUTCursorID);
		if TempCurH <> nil then
			begin
				LUTCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(gmCursorID);
		if TempCurH <> nil then
			begin
				gmCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(GrabberCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[Grabber] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(PencilCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[Pencil] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(GlassCursorPlusID);
		if TempCurH <> nil then
			begin
				ToolCursor[MagnifyingGlass] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(GlassCursorMinusID);
		if TempCurH <> nil then
			begin
				GlassMinusCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(BucketCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[PaintBucket] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(WandCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[Wand] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(TextCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[TextTool] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(EraserCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[eraser] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(SprayCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[SprayCanTool] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(BrushCursorID);
		if TempCurH <> nil then
			begin
				ToolCursor[brush] := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;

		TempCurH := GetCursor(WatchCursor);
		if TempCurH <> nil then
			begin
				watch := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;
			
		for i := 1 to 8 do
			AnimatedWatch[i] := watch;
		id := FirstAnimatedWatchID;
		for i := 2 to 8 do
			begin
				TempCurH := GetCursor(id);
				id := id + 1;
				if TempCurH <> nil then
					begin
						AnimatedWatch[i] := TempCurH^^;
						ReleaseResource(handle(TempCurH));
					end;
			end;

		TempCurH := GetCursor(FingerCursorID);
		if TempCurH <> nil then
			begin
				FingerCursor := TempCurH^^;
				ReleaseResource(handle(TempCurH));
			end;
			
	end;


	procedure MakeToolsBitMap;
  {Creates the offscreen bitmap used to draw the tool palette.}
		var
			tPort: GrafPtr;
			TempPort: GrafPort;
			PicH: PicHandle;
			FrameRect: rect;
			fwidth, fheight: integer;
	begin
		PicH := GetPicture(130);
		if PicH = nil then
			ExitToShell;
		FrameRect := PicH^^.PicFrame;
		with FrameRect do
			begin
				fwidth := right - left;
				fheight := bottom - top;
			end;
		GetPort(tPort);
		OpenPort(@TempPort);
		with ToolBits, FrameRect do
			begin
				baseAddr := NewPtr((fwidth * fheight) div 8);
				if baseAddr = nil then
					ExitToShell;
				rowBytes := fwidth div 8;
				SetRect(bounds, 0, 0, fwidth, fheight);
			end;
		SetPortBits(ToolBits);
		DrawPicture(PicH, ToolBits.bounds);
		ReleaseResource(handle(PicH));
		ClosePort(@TempPort);
		SetPort(tPort);
	end;


	procedure InitTools;
		var
			ToolTop, LinesTop, i: integer;
			Tool: ToolType;
	begin
		MakeToolsBitmap;
		FirstTool := MagnifyingGlass;
		LastTool := CrossHairTool;
		CurrentTool := SelectionTool;
		isSelectionTool := true;
		PreviousTool := CurrentTool;
		ToolTop := 0;
		for tool := FirstTool to LastTool do
			with ToolRect[tool] do
				begin
					top := ToolTop;
					bottom := top + tmiddle;
					if odd(ord(tool) + 1) then
						left := 0
					else
						begin
							left := tmiddle;
							ToolTop := ToolTop + tmiddle;
						end;
					right := left + tmiddle;
				end;
		ToolTime := 0;
		LutTime := 0;
		StartOfLines := ToolRect[LastTool].bottom - 1;
		LinesTop := StartOfLines + 10;
		for i := 1 to nLineTypes do
			with lines[i] do
				begin
					left := LinesLeft;
					top := LinesTop;
					right := LinesRight;
					case i of
						1, 2, 3, 4: 
							bottom := top + i;
						5: 
							bottom := top + 6;
						6: 
							bottom := top + 8
					end;
					LinesTop := bottom + 4;
				end;
		LineWidth := 1;
		LineIndex := 1;
		with CheckRect do
			begin
				left := 0;
				top := StartOfLines;
				right := LinesLeft;
				bottom := theight;
			end;
	end;


	procedure AllocateBuffers;
		var
			tPort: GrafPtr;
			err: OSErr;
			BufSizeStr: str255;
			atemp: integer;
			SaveGDevice: GDHandle;
	begin
		SaveGDevice := GetGDevice;
		SetGDevice(osGDevice);
		GetPort(tPort);
		NumToString(BufferSize div 1024, BufSizeStr);
		BigBufSize := BufferSize * 2;
		if FreeMem > (BigBufSize + 300000) then
			BigBuf := NewPtr(BigBufSize)
		else
			BigBuf := nil;
		if BigBuf = nil then
			BigBufSize := 0;
		if BigBuf <> nil then
			UndoBuf := BigBuf
		else
			begin
				if FreeMem > (BufferSize + 200000) then
					UndoBuf := NewPtr(BufferSize)
				else
					UndoBuf := nil;
			end;
		if UndoBuf <> nil then
			UndoBufSize := BufferSize
		else
			begin
				PutError(concat('There is not enough memory available to allocate the ', BufSizeStr, 'K Undo buffer. Many operations may fail or may not be Undoable.'));
				UndoBufSize := 0;
			end;
		if BigBuf <> nil then
			ClipBuf := ptr(ord4(BigBuf) + BufferSize)
		else
			begin
				if FreeMem > (BufferSize + 300000) then
					ClipBuf := NewPtr(BufferSize)
				else
					ClipBuf := nil;
			end;
		UndoInfoRec := NoInfo^;
		UndoInfo := @UndoInfoRec;
		if UndoBuf <> nil then
			with UndoInfo^ do
				begin
					roiRgn := NewRgn;
					PicBaseAddr := UndoBuf;
					osPort := CGrafPtr(NewPtr(SizeOf(CGrafPort)));
					OpenCPort(osPort);
					osPort^.portPixMap^^.BaseAddr := PicBaseAddr;
					SetPalette(WindowPtr(osPort), ExplicitPalette, false);
				end;
		if ClipBuf <> nil then
			begin
				ClipBufSize := BufferSize;
				ClipBufInfoRec := NoInfo^;
				ClipBufInfo := @ClipBufInfoRec;
				with ClipBufInfo^ do
					begin
						roiRgn := NewRgn;
						PicBaseAddr := ClipBuf;
						osPort := CGrafPtr(NewPtr(SizeOf(CGrafPort)));
						OpenCPort(osPort);
						osPort^.portPixMap^^.BaseAddr := PicBaseAddr;
						BytesPerRow := 0;
						SetPalette(WindowPtr(osPort), ExplicitPalette, false);
					end;
			end
		else
			begin
				PutError(concat('There is not enough memory available to allocate the ', BufSizeStr, 'K Clipboard Buffer. Many operations, including Copy and Paste, may fail.'));
				ClipBufSize := 0;
			end;
		SetPort(tPort);
		SetGDevice(SaveGDevice);
	end;


	procedure AllocateArrays;
		var
			nItems: LongInt;
			i: integer;

		procedure Abort;
		begin
			PutError('Not enough memory available to allocate arrays.');
			ExitToShell;
		end;

	begin
		PlotData := rLinePtr(NewPtr(SizeOf(rLineType)));
		if PlotData = nil then
			abort;
		nItems := maxCoordinates;
		xCoordinates := xCoordinatesPtr(NewPtr(nItems * SizeOf(integer)));
		if xCoordinates = nil then
			abort;
		yCoordinates := yCoordinatesPtr(NewPtr(nItems * SizeOf(integer)));
		if yCoordinates = nil then
			abort;
		nItems := MaxMeasurements + 1;
		mean := meanPtr(NewPtr(nItems * SizeOf(real)));
		if mean = nil then
			abort;
		sd := sdPtr(NewPtr(nItems * SizeOf(real)));
		if sd = nil then
			abort;
		PixelCount := PixelCountPtr(NewPtr(nItems * SizeOf(LongInt)));
		if PixelCount = nil then
			abort;
		mArea := AreaPtr(NewPtr(nItems * SizeOf(real)));
		if mArea = nil then
			abort;
		mode := modePtr(NewPtr(nItems * SizeOf(real)));
		if mode = nil then
			abort;
		IntegratedDensity := IntegratedDensityPtr(NewPtr(nItems * SizeOf(real)));
		if IntegratedDensity = nil then
			abort;
		idBackground := idBackgroundPtr(NewPtr(nItems * SizeOf(real)));
		if idBackground = nil then
			abort;
		xcenter := xcenterPtr(NewPtr(nItems * SizeOf(real)));
		if xcenter = nil then
			abort;
		ycenter := ycenterPtr(NewPtr(nItems * SizeOf(real)));
		if ycenter = nil then
			abort;
		MajorAxis := MajorAxisPtr(NewPtr(nItems * SizeOf(real)));
		if MajorAxis = nil then
			abort;
		MinorAxis := MinorAxisPtr(NewPtr(nItems * SizeOf(real)));
		if MinorAxis = nil then
			abort;
		orientation := orientationPtr(NewPtr(nItems * SizeOf(real)));
		if orientation = nil then
			abort;
		mMin := MinPtr(NewPtr(nItems * SizeOf(real)));
		if mMin = nil then
			abort;
		mMax := MaxPtr(NewPtr(nItems * SizeOf(real)));
		if mMax = nil then
			abort;
		plength := plengthPtr(NewPtr(nItems * SizeOf(real)));
		if plength = nil then
			abort;
		User1 := User1Ptr(NewPtr(nItems * SizeOf(real)));
		if User1 = nil then
			abort;
		for i := 0 to MaxMeasurements do
			User1^[i] := 0.0;
		User2 := User2Ptr(NewPtr(nItems * SizeOf(real)));
		if User2 = nil then
			abort;
		for i := 0 to MaxMeasurements do
			User2^[i] := 0.0;
		ClearResults(0);
		if FreeMem < MinFree then
			Abort;
	end;


	procedure GetKernelsWorkingDir (var settings: SettingsType);
		var
			wdRefNum: integer;
			err: OSErr;
	begin
		with settings do
			if sKernelsVRefNum <> 0 then
				begin
					err := OpenWD(sKernelsVRefNum, sKernelsDirID, 0, wdRefNum);
					if err = NoErr then
						KernelsRefNum := wdRefNum;
          {ShowMessage(concat('KernelsRefNum=', long2str(KernelsRefNum), crStr, 'vRefNum=', long2str(sKernelsVRefNum), crStr, 'DirID=', long2str(sKernelsDirID)));}
				end;
	end;


	procedure GetDefaultWorkingDir (var settings: SettingsType);
		var
			wdRefNum: integer;
			err: OSErr;
	begin
		with settings do
			if sDefaultVRefNum <> 0 then
				begin
					err := OpenWD(sDefaultVRefNum, sDefaultDirID, 0, wdRefNum);
					if err = NoErr then
						DefaultRefNum := wdRefNum;
				end;
	end;



procedure GetPreferences(f: integer);
		var
			err: OSErr;
			ByteCount: LongInt;
			ok: boolean;
			size: LongInt;
			settings: SettingsType;
			i: integer;
			SaveInfo: InfoPtr;
			okay: boolean;
	begin
		err := GetEof(f, ByteCount);
		if ByteCount > SizeOf(settings) then
			ByteCount := SizeOf(settings);
		err := fsRead(f, ByteCount, @settings);
		if err <> NoErr then
			exit(GetPreferences);
		err := fsClose(f);
		with settings, info^ do
			begin
				if sID <> 'IMAG' then begin
						PutError('The "Image Prefs" file in the System folder is corrupted. Please delete it and try again.');
						exitToShell;
					end;
				ForegroundIndex := sForegroundIndex;
				BackgroundIndex := sBackgroundIndex;
				BrushHeight := sBrushHeight;
				BrushWidth := sBrushWidth;
				SprayCanDiameter := sSprayCanDiameter;
				SprayCanRadius := SprayCanDiameter div 2;
				SprayCanRadius2 := SprayCanRadius * SprayCanRadius;
				CurrentFontID := sCurrentFontID;
				CurrentStyle := SCurrentStyle;
				CurrentSize := sCurrentSize;
				TextJust := sTextJust;
				TextBack := sTextBack;
				nExtraColors := sNExtraColors;
				ExtraColors := sExtraColors;
				InvertVideo := sInvertVideo;
				Measurements := sMeasurements;
				InvertPlots := sInvertPlots;
				AutoScalePlots := sAutoScalePlots;
				LinePlot := sLinePlot;
				DrawPlotLabels := sDrawPlotLabels;
				FixedSizePlot := sFixedSizePlot;
				ProfilePlotWidth := sProfilePlotWidth;
				ProfilePlotHeight := sProfilePlotHeight;
				FramesToAverage := sFramesToAverage;
				NewPicWidth := sNewPicWidth;
				NewPicHeight := sNewPicHeight;
				BufferSize := sBufferSize;
				ThresholdToForeground := sThresholdToForeground;
				NonThresholdToBackground := sNonThresholdToBackground;
				VideoChannel := sVideoChannel;
				WhatToImport := sWhatToImport;
				ImportCustomWidth := sImportCustomWidth;
				ImportCustomHeight := sImportCustomHeight;
				ImportCustomOffset := sImportCustomOffset;
        {WandAutoMeasure := sWandAutoMeasure;}
				WandAdjustAreas := sWandAdjustAreas;
				BinaryIterations := sBinaryIterations;
				ScaleArithmetic := sScaleArithmetic;
				InvertPixelValues := sInvertPixelValues;
				InvertYCoordinates := sInvertYCoordinates;
				FieldWidth := sFieldWidth;
				precision := sPrecision;
				MinParticleSize := sMinParticleSize;
				MaxParticleSize := sMaxParticleSize;
				IgnoreParticlesTouchingEdge := sIgnoreParticlesTouchingEdge;
				LabelParticles := sLabelParticles;
				OutlineParticles := sOutlineParticles;
         {IncludeHoles := sIncludeHoles;}
				OscillatingMovies := sOscillatingMovies;
         {DriverHalftoning := sDriverHalftoning;}
				MaxMeasurements := sMaxMeasurements;
				ImportCustomDepth := sImportCustomDepth;
				ImportSwapBytes := sImportSwapBytes;
				ImportCalibrate := sImportCalibrate;
				ImportAutoscale := sImportAutoscale;
				ShowHeadings := sShowHeadings;
				if sVersion >= 140 then
					begin
						ProfilePlotMin := sProfilePlotMin;
						ProfilePlotMax := sProfilePlotMax;
						ImportMin := sImportMin;
						ImportMax := sImportMax;
						HighlightSaturatedPixels := sHighlightPixels;
					end;
				if sVersion >= 141 then
					begin
						BallRadius := sBallRadius;
						FasterBackgroundSubtraction := sFasterBackgroundSubtraction;
						ScaleConvolutions := sScaleConvolutions;
					end;
				if sVersion >= 142 then
					begin
						BinaryCount := sBinaryCount;
						BinaryThreshold := BinaryCount * 255;
						if (not GrayMapReady) and (sLUTMode = Pseudocolor) and (sColorTable <> CustomTable) and (sColorTable <= Spectrum) then
							begin
								ColorTable := sColorTable;
								ColorStart := sColorStart;
								ColorEnd := sColorEnd;
								LutMode := Pseudocolor;
								InvertedColorTable := sInvertedTable;
							end;
					end;
				if sVersion >= 144 then
					begin
						HalftoneFrequency := sHalftoneFrequency;
						HalftoneAngle := sHalftoneAngle;
						HalftoneDotFunction := sHalftoneDotFunction;
					end;
				if sVersion >= 146 then
					begin
						DacLow := sDacLow;
						DacHigh := sDacHigh;
					end;
				if (sVersion >= 147) and ((FrameGrabber = ScionLG3) or (FrameGrabber = ScionAG5) or (FrameGrabber = ScionVG5f)) then
					SyncMode := sSyncMode;
				if sVersion >= 149 then
					begin
						SwitchLUTOnSuspend := sSwitchLUTOnSuspend;
						VideoRateAveraging := sVideoRateAveraging;
					end;
				if sVersion >= 150 then
					begin
						ImportInvert := sImportInvert;
					end;
				if sVersion >= 152 then
					begin
						if sTextCreator[1] <> chr(0) then
							TextCreator := sTextCreator;
					end;
				if sVersion >= 156 then
					begin
						if sMathSubGain <> 0.0 then begin
							MathSubGain:=sMathSubGain;
							MathSubOffset:=sMathSubOffset;
							MathGain:=MathSubGain;
							MathOffset:=MathSubOffset;
						end;
					end;
				if sVersion >= 160 then begin
						fgScale := sfgScale;
						UseBuiltinDigitizer := sUseBuiltinDigitizer;
						DigitizerMode := sDigitizerMode;
						DigitizerStandard := sDigitizerStandard;
						LutFriendlyMode := sLutFriendlyMode;
					end;
				{GetKernelsWorkingDir(settings);}
				{GetDefaultWorkingDir(settings);}
				UpdateFitEllipse;
			end; {with}
	end;
	
	
	procedure GetSettings;
		var
			err: OSErr;
			f: integer;
			ByteCount: LongInt;
			ok: boolean;
			size: LongInt;
			settings: SettingsType;
			i: integer;
			PrefsFound:boolean;
			PrefsVRef: integer;
			PrefsDirID: LongInt;
			PrefsSpec: FSSpec;
	begin
		PrefsFound:=false;
		if System7 then begin
			{Look in the Preferences folder}
			err:=FindFolder(kOnSystemDisk, kPreferencesFolderType,
						kDontCreateFolder, PrefsVRef, PrefsDirID);
			if err=noErr then
				err:=FSMakeFSSpec(PrefsVRef, PrefsDirID, PrefsName, PrefsSpec);
			if err=noErr then
				err:=FSpOpenDF(PrefsSpec, fsCurPerm, f);
			if err=noErr then
				PrefsFound:=true;
		end;
		if not PrefsFound then begin
			{Look in the System folder}
			err := fsopen(PrefsName, SystemRefNum, f);
			if err <> NoErr then
				exit(GetSettings);
		end;
		GetPreferences(f);
	end;


	procedure MakePatterns;
{Creates the patterns used to create the "marching ants". Thanks to}
{Seth Snyder on CompuServe for the example.}
		var
			i, j: Integer;
	begin
		j := 0;
		for i := 0 to 7 do
			begin
				AntPattern[i].pat[(j + 0) mod 8] := $1F;
				AntPattern[i].pat[(j + 1) mod 8] := $3E;
				AntPattern[i].pat[(j + 2) mod 8] := $7C;
				AntPattern[i].pat[(j + 3) mod 8] := $F8;
				AntPattern[i].pat[(j + 4) mod 8] := $F1;
				AntPattern[i].pat[(j + 5) mod 8] := $E3;
				AntPattern[i].pat[(j + 6) mod 8] := $C7;
				AntPattern[i].pat[(j + 7) mod 8] := $8F;
				j := j + 1;
			end;
		PatIndex := 0;
	end;


	procedure InitExtraColors;
		var
			i, j, ctop, cbottom, entry: integer;
			tRect: rect;
	begin
		with ExtraColors[1] do
			begin
				red := -1;
				green := 0;
				blue := 0;
			end;
		with ExtraColors[2] do
			begin
				red := 0;
				green := -1;
				blue := 0;
			end;
		with ExtraColors[3] do
			begin
				red := 0;
				green := 0;
				blue := -1;
			end;
		with ExtraColors[4] do
			begin
				red := -1;
				green := -1;
				blue := 0;
			end;
		with ExtraColors[5] do
			begin
				red := 0;
				green := -1;
				blue := -1;
			end;
		with ExtraColors[6] do
			begin
				red := -1;
				green := 0;
				blue := -1;
			end;
		ctop := 256;
		cbottom := ctop + ExtraColorsHeight;
		for i := 1 to MaxExtraPlus2 do
			begin
				SetRect(tRect, 0, ctop, cwidth, cbottom);
				ExtraColorsRect[i] := tRect;
				ctop := ctop + ExtraColorsHeight;
				cbottom := cbottom + ExtraColorsHeight;
			end;
		ExtraColorsEntry[1] := WhiteIndex;
		ExtraColorsEntry[2] := BlackIndex;
		entry := FirstExtraColorsEntry;
		j := 3;
		for i := 1 to MaxExtraColors do
			begin
				ExtraColorsEntry[j] := entry;
				j := j + 1;
				Entry := Entry + 1;
			end;
	end;


	function GetSlotBase (id: integer): LongInt;
  {Returns the slot base address of the NuBus card with the specified id. The address}
  {returned is in the form $Fss00000, which is valid in both 24 and 32-bit modes.}
  {Returns 0 if a card with the given id is not found.}
		type
			SPRAMRecord = packed record
					BoardId: integer;
					VenderUse: packed array[1..6] of SignedByte;
				end;
		var
			SlotBlock: SpBlock;
			sparm: SPRAMRecord;
			SparmAddr: LongInt;
			i: integer;
			err: OSErr;
	begin
		with SlotBlock do
			begin
				SparmAddr := LongInt(@sparm);
				spResult := SparmAddr;
				for i := 9 to 15 do
					begin
						spSlot := i;
						err := sReadPRAMRec(@SlotBlock);
						if sparm.BoardID = id then
							begin
								GetSlotBase := bor($F0000000, spSlot * $100000 + spSlot * $1000000);
                superSlotBase := spSlot * $10000000;
								exit(GetSlotBase)
							end;
					end;
				GetSlotBase := 0;
			end;
	end;


	procedure SetupFGPort;
{So we can use CopyBits, this routine sets up a color graf port that}
{uses the memory on the frame grabber board as the PixMap.}
		const
			baseAddr32 = 4;
		var
			tPort: GrafPtr;
			trect: rect;
			SaveGDevice: GDHandle;
	begin
		SaveGDevice := GetGDevice;
		SetGDevice(osGDevice);
		GetPort(tPort);
		fgPort := CGrafPtr(NewPtr(SizeOf(CGrafPort)));
		OpenCPort(fgPort);
		SetRect(trect, 0, 0, fgWidth, fgHeight);
		with fgPort^ do
			begin
				with PortPixMap^^ do
					begin
						if PCIFrameGrabber then
							BaseAddr := ptr(fgSuperSlotBase0)
						else
							BaseAddr := ptr(fgSlotBase);
						bounds := trect;
						RowBytes := BitOr(fgRowBytes, $8000);
						pmVersion := baseAddr32; {Needed for 8*24 GC card. See TN 275.}
					end;
				PortRect := trect;
				RectRgn(visRgn, trect);
			end;
		hlock(handle(fgPort^.PortPixMap));
		fgPixMap := fgPort^.PortPixMap;
		SetPort(tPort);
		SetPalette(WindowPtr(fgPort), ExplicitPalette, false);
		SetGDevice(SaveGDevice);
	end;


	function is50HzLG3: boolean;
		const
			BoardResourceID = 1;
			VendorInfoID = 36;
			PartNumberID = 4;
			PartNumber50Hz = 'LG-3 50Hz';
		var
			SlotBlock: SpBlock;
			err: OSErr;
			PartNumberPtr: StringPtr;
	begin
		is50HzLG3 := false;
		SlotBlock.spSlot := byte(bsr(band(fgSlotBase, $0f000000), 24));
		SlotBlock.spId := BoardResourceID;
		SlotBlock.spExtDev := 0;
		err := SRsrcInfo(@SlotBlock);
		if err <> 0 then
			exit(is50HzLG3);
		SlotBlock.spId := VendorInfoID;
		err := SFindStruct(@SlotBlock);
		if err <> 0 then
			exit(is50HzLG3);
		SlotBlock.spID := PartNumberID;
		err := SGetCString(@SlotBlock);
		if err <> 0 then
			exit(is50HzLG3);
		PartNumberPtr := C2PStr(SlotBlock.spResult);
		if PartNumberPtr^ = PartNumber50Hz then
			is50HzLG3 := true;
		DisposePtr(Ptr(SlotBlock.spResult)); {need to free memory allocated by SGetCString()}
	end;


	function is50HzAG5: boolean;
		const
			BoardResourceID = 1;
			VendorInfoID = 36;
			PartNumberID = 4;
			PartNumber50Hz = 'AG-5 50Hz';
		var
			SlotBlock: SpBlock;
			err: OSErr;
			PartNumberPtr: StringPtr;
	begin
		is50HzAG5 := false;
		SlotBlock.spSlot := byte(bsr(band(fgSlotBase, $0f000000), 24));
		SlotBlock.spId := BoardResourceID;
		SlotBlock.spExtDev := 0;
		err := SRsrcInfo(@SlotBlock);
		if err <> 0 then
			exit(is50HzAG5);
		SlotBlock.spId := VendorInfoID;
		err := SFindStruct(@SlotBlock);
		if err <> 0 then
			exit(is50HzAG5);
		SlotBlock.spID := PartNumberID;
		err := SGetCString(@SlotBlock);
		if err <> 0 then
			exit(is50HzAG5);
		PartNumberPtr := C2PStr(SlotBlock.spResult);
		if PartNumberPtr^ = PartNumber50Hz then
			is50HzAG5 := true;
		DisposePtr(Ptr(SlotBlock.spResult));  {need to free memory allocated by SGetCString()}
	end;


	function is50HzVG5: boolean;
		const
			BoardResourceID = 1;
			VendorInfoID = 36;
			PartNumberID = 4;
			PartNumber50Hz = 'VG-5 50Hz';
		var
			SlotBlock: SpBlock;
			err: OSErr;
			PartNumberPtr: StringPtr;
	begin
		is50HzVG5 := false;
		SlotBlock.spSlot := byte(bsr(band(fgSlotBase, $0f000000), 24));
		SlotBlock.spId := BoardResourceID;
		SlotBlock.spExtDev := 0;
		err := SRsrcInfo(@SlotBlock);
		if err <> 0 then
			exit(is50HzVG5);
		SlotBlock.spId := VendorInfoID;
		err := SFindStruct(@SlotBlock);
		if err <> 0 then
			exit(is50HzVG5);
		SlotBlock.spID := PartNumberID;
		err := SGetCString(@SlotBlock);
		if err <> 0 then
			exit(is50HzVG5);
		PartNumberPtr := C2PStr(SlotBlock.spResult);
		if PartNumberPtr^ = PartNumber50Hz then
			is50HzVG5 := true;
		DisposePtr(Ptr(SlotBlock.spResult)); {need to free memory allocated by SGetCString()}
	end;


 procedure CheckLG3Buffer;
  type
   LongintPtr = ^Longint;
  const
   Pattern = $A596A596;
  var
   BufferPtr: LongintPtr;
   mode: signedbyte;
   
   procedure SwapMode;
   begin
	  {$ifc not PowerPC}
	  SwapMMUMode(mode);
	  {$endc}
   end;
   
 begin
  mode := true32b;
  SwapMode;
  BufferPtr := LongintPtr(fgSlotBase);
  BufferPtr^ := Pattern;
  BufferPtr := LongintPtr(bsl(band(fgSlotBase, $0f000000), 4) + (524288 * 2));
  if BufferPtr^ = Pattern then begin
    MaxLG3Frames := 2;
	  SwapMode;
    exit(CheckLG3Buffer);
   end;
  BufferPtr := LongintPtr(bsl(band(fgSlotBase, $0f000000), 4) + (524288 * 8));
  if BufferPtr^ = Pattern then begin
    MaxLG3Frames := 8;
	  SwapMode;
    exit(CheckLG3Buffer);
   end;
  BufferPtr := LongintPtr(bsl(band(fgSlotBase, $0f000000), 4) + (524288 * 32));
  if BufferPtr^ = Pattern then begin
    MaxLG3Frames := 32;
	  SwapMode;
    exit(CheckLG3Buffer);
   end
  else begin
    MaxLG3Frames := 128;
	  SwapMode;
   end;
 end;


	procedure LookForFrameGrabbers;
		const
			ControlRegOffset = $80000;
			ChannelRegOffset = $80004;
			LG3ControlRegOffset = $C0000;
			LG3ChannelRegOffset = $C0008;
			AG5ControlRegOffset = $C0000;
			AG5ChannelRegOffset = $C0008;
			AG5BufferRegOffset = $C0014;
			VG5ControlRegOffset = $C0000;
			VG5ChannelRegOffset = $C0008;
			VG5BufferRegOffset = $C0014;
			BufferRegOffset = $C0004;
			DacHighRegOffset = $C000C;
			DacLowRegOffset = $C0010;
			DacARegOffset = $C0014;
			DacBRegOffset = $C0018;
			ConstantRegOffset = $C0004;
			ScaleHighRegOffset = $D0000;
			ScaleLowRegOffset = $D0004;
			DT2255id = $11A;
			ScionLG3id = $48B;
			ScionAG5id = $620;
			ScionVG5id = $67E;
			ScionLG3PCIid = 1;
			ScionVG5PCIid = 2;
			ScionAG5PCIid = 3;
			PalBufferSize = 393216; {768 x 512}
		var
			err: OSErr;
			tPort: GrafPtr;
			OptionKeyIsDown: boolean;
			found : boolean;
			model: integer;
			base0, base1, buffers: longint;
	begin
		FrameGrabber := NoFrameGrabber;
		PCIFrameGrabber := false;
		DoubleBuffering := false;
		fgPixMap := nil;
		DacLow := DefaultDacLow;
		DacHigh := DefaultDacHigh;
		if ShiftKeyDown then
			exit(LookForFrameGrabbers);
		OptionKeyIsDown := OptionKeyDown;
		fgPort := nil;
		
		{Scion LG-3}
		fgSlotBase := GetSlotBase(ScionLG3id);
		fgRowBytes := 1024;
		if (fgSlotBase <> 0) and not OptionKeyIsDown then begin
				FrameGrabber := ScionLG3;
				ControlReg := ptr(fgSlotBase + LG3ControlRegOffset);
				ChannelReg := ptr(fgSlotBase + LG3ChannelRegOffset);
				BufferReg := ptr(fgSlotBase + BufferRegOffset);
				DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
				DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
				DacAReg := ptr(fgSlotBase + DacARegOffset);
				DacBReg := ptr(fgSlotBase + DacBRegOffset);
				fgWidth := 640;
				fgHeight := 480;
				if is50HzLG3 then begin
						fgWidth := 768;
						fgHeight := 512;
						if BufferSize < PalBufferSize then
							BufferSize := PalBufferSize;
					end;
				CheckLG3Buffer;
				SetupFGPort;
				ResetScionLG3;
				exit(LookForFrameGrabbers);
			end;
			
		{Scion AG-5}
		fgSlotBase := GetSlotBase(ScionAG5id);
		if (fgSlotBase <> 0) and not OptionKeyIsDown then begin
				FrameGrabber := ScionAG5;
				ControlReg := ptr(fgSlotBase + AG5ControlRegOffset);
				ChannelReg := ptr(fgSlotBase + AG5ChannelRegOffset);
				ConstantReg := ptr(fgSlotBase + ConstantRegOffset);
				DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
				DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
				ScaleHighReg := IntegerPtr(fgSlotBase + ScaleHighRegOffset);
				ScaleLowReg := IntegerPtr(fgSlotBase + ScaleLowRegOffset);
				fgWidth := 640;
				fgHeight := 480;
				if is50HzAG5 then begin
						fgWidth := 768;
						fgHeight := 512;
						if BufferSize < PalBufferSize then
							BufferSize := PalBufferSize;
					end;
				SetupFGPort;
				ResetScionAG5;
				exit(LookForFrameGrabbers);
			end;
			
		{Scion VG-5}
		fgSlotBase := GetSlotBase(ScionVG5id);
		if (fgSlotBase <> 0) and not OptionKeyIsDown then begin
				FrameGrabber := ScionVG5f;
				ControlReg := ptr(fgSlotBase + VG5ControlRegOffset);
				ChannelReg := ptr(fgSlotBase + VG5ChannelRegOffset);
				DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
				DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
				fgWidth := 640;
				fgHeight := 480;
				if is50HzVG5 then begin
						fgWidth := 768;
						fgHeight := 512;
						if BufferSize < PalBufferSize then
							BufferSize := PalBufferSize;
					end;
				SetupFGPort;
				ResetScionVG5f;
				exit(LookForFrameGrabbers);
			end;
			
		{Data Translation QuickCapture}
		fgSlotBase := GetSlotBase(DT2255id);
		if fgSlotBase <> 0 then begin
				FrameGrabber := QuickCapture;
				ControlReg := ptr(fgSlotBase + ControlRegOffset);
				ChannelReg := ptr(fgSlotBase + ControlRegOffset + 4);
				fgWidth := 640;
				fgHeight := 480;
				if band(ChannelReg^, 8) = 8 then begin {Check for 50Hz(PAL) card}
						fgWidth := 768;
						fgHeight := 512;
						if BufferSize < PalBufferSize then
							BufferSize := PalBufferSize;
					end;
				SetupFGPort;
				ResetQuickCapture;
				exit(LookForFrameGrabbers);
			end;
			
			{$ifc PowerPC and SupportScionPCI}
			
			{Scion LG-3 (PCI)}
			model := ScionLG3PCIid;
			base0 := 0;
			base1 := 0;
			buffers:= 0;
			found := false;
			found := LookForPCIFrameGrabbers(model, base0, base1, buffers);
			if found then begin
				fgSlotBase := base0;
				fgSuperSlotBase0 := base1;
				fgSuperSlotBase1 := base1 + 524288;
				FrameGrabber := ScionLG3;
				PCIFrameGrabber := true;
				ControlReg := ptr(fgSlotBase + LG3ControlRegOffset);
				ChannelReg := ptr(fgSlotBase + LG3ChannelRegOffset);
				BufferReg := ptr(fgSlotBase + BufferRegOffset);
				DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
				DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
				DacAReg := ptr(fgSlotBase + DacARegOffset);
				DacBReg := ptr(fgSlotBase + DacBRegOffset);
				fgWidth := 640;
				fgHeight := 480;
				if (band(ControlReg^, $40) <> 0) then begin
						fgWidth := 768;
						fgHeight := 512;
						if BufferSize < PalBufferSize then
							BufferSize := PalBufferSize;
					end;
				MaxLG3Frames := buffers;
				SetupFGPort;
				ResetScionLG3;
				exit(LookForFrameGrabbers);
			end;
			
			{Scion VG-5 PCI}
			model := ScionVG5PCIid;
			base0 := 0;
			base1 := 0;
			buffers:= 0;
			found := false;
			found := LookForPCIFrameGrabbers(model, base0, base1, buffers);
			if (found) then begin
					fgSlotBase := base0;
					fgSuperSlotBase0 := base1;
					fgSuperSlotBase1 := base1 + 524288;
					FrameGrabber := ScionVG5f;
					PCIFrameGrabber := true;
					ControlReg := ptr(fgSlotBase + VG5ControlRegOffset);
					ChannelReg := ptr(fgSlotBase + VG5ChannelRegOffset);
					BufferReg := ptr(fgSlotBase + VG5BufferRegOffset);
					DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
					DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
					fgWidth := 640;
					fgHeight := 480;
					if (band(ControlReg^, $40) <> 0) then begin
							fgWidth := 768;
							fgHeight := 512;
							if BufferSize < PalBufferSize then
								BufferSize := PalBufferSize;
						end;
					SetupFGPort;
					ResetScionVG5f;
					exit(LookForFrameGrabbers);
				end;
			
			{Scion AG-5 PCI}
			model := ScionAG5PCIid;
			base0 := 0;
			base1 := 0;
			buffers:= 0;
			found := false;
			found := LookForPCIFrameGrabbers(model, base0, base1, buffers);
			if (found) then begin
					fgSlotBase := base0;
					fgSuperSlotBase0 := base1;
					fgSuperSlotBase1 := base1 + 2097152;
					FrameGrabber := ScionAG5;
					PCIFrameGrabber := true;
					ControlReg := ptr(fgSlotBase + AG5ControlRegOffset);
					ChannelReg := ptr(fgSlotBase + AG5ChannelRegOffset);
					ConstantReg := ptr(fgSlotBase + ConstantRegOffset);
					BufferReg := ptr(fgSlotBase + AG5BufferRegOffset);
					DacHighReg := ptr(fgSlotBase + DacHighRegOffset);
					DacLowReg := ptr(fgSlotBase + DacLowRegOffset);
					ScaleHighReg := IntegerPtr(fgSlotBase + ScaleHighRegOffset);
					ScaleLowReg := IntegerPtr(fgSlotBase + ScaleLowRegOffset);
					fgWidth := 640;
					fgHeight := 480;
					if (band(ControlReg^, $40) <> 0) then begin
							fgWidth := 768;
							fgHeight := 512;
							if BufferSize < PalBufferSize then
								BufferSize := PalBufferSize;
						end;
					SetupFGPort;
					ResetScionAG5;
					exit(LookForFrameGrabbers);
				end;

			{$endc} {if PowerPC}

	end; {LookForFrameGrabbers}


	procedure CheckBits;
		const
			QD32Trap = $AB03;
			UnimplementedTrap = $A89F;
		var
			MainDevice: GDHandle;
			myEnvRec: SysEnvRec;
			err: OSErr;
	begin
		err := SysEnvirons(1, myEnvRec);
		if err <> envNotPresent then
			with MyEnvRec do
				begin
					if not HasColorQD then
						begin
							PutError('Sorry, NIH Image requires a Macintosh with Color QuickDraw.');
							ExitToShell;
						end;
					if not HasFPU and UsingFPU then
						begin
							PutError('Use the NonFPU version of NIH Image on Macs without a floating-point coprocessor.');
							ExitToShell;
						end;
					OldSystem := systemVersion < $0605;
					System7 := systemVersion >= $0700;
					if not System7 then
						begin
							PutError('System 7 required.');
							if not OptionKeyDown then
								ExitToShell;
						end;
					SystemRefnum := sysVRefNum;
				end;
		Has32BitQuickDraw := nGetTrapAddress(QD32Trap, ToolTrap) <> nGetTrapAddress(UnimplementedTrap, ToolTrap);
		MainDevice := GetMainDevice;
		ScreenPixMap := MainDevice^^.gdPMap;
		ScreenRowBytes := BitAnd(ScreenPixMap^^.rowBytes, $1fff);
		ScreenBase := ScreenPixMap^^.baseAddr;
		FindMonitors(ScreenPixMap^^.PixelSize);
	end;


	procedure SetupMenus;
		var
			i: integer;
	begin
		AppleMenuH := GetMenu(AppleMenu);
		InsertMenu(AppleMenuH, 0);
		FileMenuH := GetMenu(FileMenu);
		InsertMenu(FileMenuH, 0);
		EditMenuH := GetMenu(EditMenu);
		InsertMenu(EditMenuH, 0);
		OptionsMenuH := GetMenu(OptionsMenu);
		InsertMenu(OptionsMenuH, 0);
		ProcessMenuH := GetMenu(ProcessMenu);
		InsertMenu(ProcessMenuH, 0);
		AnalyzemenuH := GetMenu(AnalyzeMenu);
		InsertMenu(AnalyzemenuH, 0);
		SpecialMenuH := GetMenu(SpecialMenu);
		InsertMenu(SpecialMenuH, 0);
		StacksMenuH := GetMenu(StacksMenu);
		InsertMenu(StacksMenuH, 0);
		WindowsMenuH := GetMenu(WindowsMenu);
		InsertMenu(WindowsMenuH, 0);

		FontMenuH := GetMenu(FontMenu);
		InsertMenu(FontMenuH, -1);
		SizeMenuH := GetMenu(SizeMenu);
		InsertMenu(SizeMenuH, -1);
		StyleMenuH := GetMenu(StyleMenu);
		InsertMenu(StyleMenuH, -1);
		BinaryMenuH := GetMenu(BinaryMenu);
		InsertMenu(BinaryMenuH, -1);
		ArithmeticMenuH := GetMenu(ArithmeticMenu);
		InsertMenu(ArithmeticMenuH, -1);
		fftMenuH := GetMenu(fftMenu);
		InsertMenu(fftMenuH, -1);
		BackgroundMenuH := GetMenu(BackgroundMenu);
		InsertMenu(BackgroundMenuH, -1);
		PropagateMenuH := GetMenu(PropagateMenu);
		InsertMenu(PropagateMenuH, -1);
		ColorTablesMenuH := GetMenu(ColorTablesMenu);
		InsertMenu(ColorTablesMenuH, -1);
		AcquireMenuH := GetMenu(AcquireMenu);
		InsertMenu(AcquireMenuH, -1);
		ExportMenuH := GetMenu(ExportMenu);
		InsertMenu(ExportMenuH, -1);
		FilterMenuH := GetMenu(FilterMenu);
		InsertMenu(FilterMenuH, -1);

		TransferModeMenuH := GetMenu(TransferModeMenu);
		InsertMenu(TransferModeMenuH, -1);

		LineToolMenuH := GetMenu(LineToolMenu);
		InsertMenu(LineToolMenuH, -1);

		ImageMathOpsMenuH := GetMenu(ImageMathOpsMenu);
		InsertMenu(ImageMathOpsMenuH, -1);

		ImageListMenuH := GetMenu(ImageListMenu);
		InsertMenu(ImageListMenuH, -1);

		UnitsMenuH := GetMenu(UnitsMenu);
		InsertMenu(UnitsMenuH, -1);

		DrawMenuBar;
		AppendResMenu(AppleMenuH, 'DRVR');
		AppendResMenu(FontMenuH, 'FONT');
		NumFontItems := CountMItems(FontMenuH);
	end;


	function GetFolderDirID (parentFolderVRefNum: Integer; parentFolderDirID: LongInt; folderName: Str63; var folderDirID: LongInt): OSErr;
  {Given a folder's name, vRefNum, and parent dirID, find its dirID }
		var
			myCInfoPBRec: CInfoPBRec;
			retCode: OSErr;
	begin
		myCInfoPBRec.ioCompletion := nil;
		myCInfoPBRec.ioNamePtr := @folderName;
		myCinfoPBRec.ioVRefNum := parentFolderVRefNum;
		myCInfoPBRec.ioFDirIndex := 0; { use name, vRefNum, dirID }
		myCInfoPBRec.ioDrDirID := parentFolderDirID; { will be changed }
		retCode := PBGetCatInfoSync(@myCInfoPBRec); { IM IV-155 }
		if retCode = noErr then
			folderDirID := myCInfoPBRec.ioDrDirID;
		GetFolderDirID := retCode;
	end;


	procedure MyAppendMenu (menu: MenuHandle; item: integer; str: str255);
	begin
		AppendMenu(menu, ' ');
		SetMenuItemText(menu, item, str);
	end;


	procedure FindPlugIns;
		var
			err: OSErr;
			wdRefNum, index, SystemVRefNum: integer;
			name: Str255;
			ftype: OSType;
			PB: CInfoPBRec;
			ProcID, SystemDirID: LongInt;
			spec: FSSpec;
			pb2: WDPBRec;
			rCount, iFileRef: integer;
	begin
		if not System7 then
			exit(FindPlugIns);
		err := GetFolderDirID(LaunchVRefNum, LaunchDirID, 'Plug-Ins', PlugInsDirID);
		if err = NoErr then
			PlugInsVRefNum := LaunchVRefNum
		else if GetWDInfo(SystemRefNum, SystemVRefNum, SystemDirID, ProcID) = NoErr then
			if GetFolderDirID(SystemVRefNum, SystemDirID, 'Plug-Ins', PlugInsDirID) = NoErr then
				PlugInsVRefNum := SystemVRefNum
			else
				exit(FindPlugIns);
		err := OpenWD(PlugInsVRefNum, PlugInsDirID, 0, wdRefNum);
		if err <> NoErr then
			exit(FindPlugIns);
		index := 0;
		while true do
			begin
				index := index + 1;
				with PB do
					begin
						ioCompletion := nil;
						ioNamePtr := @name;
						ioVRefNum := wdRefNum;
						ioDirID:=PlugInsDirID;
						ioFDirIndex := index;
						err := PBGetCatInfoSync(@PB); {ppc-bug}
						if err = fnfErr then
							leave;
					end;
				spec.vrefnum := PluginsVRefNum;
				spec.parID := PlugInsDirID;
				spec.name := name;
				iFileRef := FSpOpenResFile(spec, fsCurPerm);
				if iFileRef <> -1 then
					begin
						UseResFile(iFileRef);
						rCount := Count1Resources('8BAM');
						if rCount > 0 then
							begin
								nAcqPlugIns := nAcqPlugIns + 1;
								if nAcqPlugIns = 1 then
									SetMenuItemText(AcquireMenuH, 1, name)
								else
									MyAppendMenu(AcquireMenuH, nAcqPlugIns, name);
							end;
						rCount := Count1Resources('8BEM');
						if rCount > 0 then
							begin
								nExportPlugIns := nExportPlugIns + 1;
								if nExportPlugIns = 1 then
									SetMenuItemText(ExportMenuH, 1, name)
								else
									MyAppendMenu(ExportMenuH, nExportPlugIns, name);
							end;
						rCount := Count1Resources('8BFM');
						if rCount > 0 then
							begin
								nFilterPlugIns := nFilterPlugIns + 1;
								if nFilterPlugIns = 1 then
									SetMenuItemText(FilterMenuH, 1, name)
								else
									MyAppendMenu(FilterMenuH, nFilterPlugIns, name);
							end;
						CloseResFile(iFileRef);
					end;
				ShowAnimatedWatch;
			end; {while}
		err := CloseWD(wdRefNum);
	end;


	procedure MakeGDevice;
  {Sets up an offscreen 8-bit graphics environment for use when the screen is not 8-bits.}
		var
			DeviceRect: Rect;
			h: CTabHandle;
			SaveDevice: GDHandle;

		procedure Abort;
		begin
			PutError('Error creating GDevice.');
			ExitToShell;
		end;

	begin
		SaveDevice := GetGDevice;
		SetRect(DeviceRect, 0, 0, 64, 64);
		h := GetCTable(AppleDefaultClut);
		if h = nil then
			abort;
		osGDevice := NewGDevice(0, -1);
		if osGDevice = nil then
			abort;
		with osGDevice^^ do
			begin
				gdId := 0;
				gdType := clutType;
				gdResPref := 3;											{ Color matching resolution. }
				gdSearchProc := nil;
				gdCompProc := nil;
				gdFlags := $C401;											{ 1100 0100 0000 0001 }
				gdRect := DeviceRect;
				with gdPMap^^ do
					begin
						baseAddr := nil;
						bounds := DeviceRect;
						rowBytes := 64 + $8000;
						pixelSize := 8;
						cmpCount := 1;
						cmpSize := 8;
						DisposeCTable(pmTable);
						pmTable := h;
					end;
			end;
		SetGDevice(SaveDevice);
	end;


	procedure LoadColorTable(PrefsStart, PrefsEnd: integer; PrefsInvert: boolean);
	{Load the pseudocolor LUT specified in preferences file.}
	begin
		with Info^ do begin
			if	LutMode = Pseudocolor then begin
					SwitchColorTables(GetColorTableItem(ColorTable), false);
					ColorStart := PrefsStart;
					ColorEnd := PrefsEnd;
					if PrefsInvert then
						InvertPalette;
					UpdateLut;
				end;
			end;
	end;


	procedure Init;
		var
			i: integer;
			p: SyspPtr;
			mbhp: ^integer;
			str: str255;
			err: OSErr;
	begin
		SetApplLimit(ptr(ord4(GetApplLimit) - StackSize));
		MaxApplZone;
		for i := 1 to 20 do
			MoreMasters;
		InitGraf(@qd.thePort);
		InitFonts;
		InitWindows;
		InitCursor;
		TEInit;
		InitDialogs(@SysResume);
		CheckBits;
		ScreenPort := GrafPtr(NewPtr(SizeOf(GrafPort)));
		OpenPort(ScreenPort);
		NoInfo := @NoInfoRec;
		Info := NoInfo;
		InfoWindow := nil;
		with BlackRGB do
			begin
				red := 0;
				blue := 0;
				green := 0;
			end;
		with WhiteRGB do
			begin
				red := -1;
				blue := -1;
				green := -1;
			end;

		with NoInfo^ do
			begin
				iVersion:=version;
				nlines := 0;
				PixelsPerLine := 0;
				ImageSize := 0;
				PixMapSize := 0;
				PicBaseAddr := nil;
				PicBaseHandle := nil;
				osPort := nil;
				RoiShowing := false;
				RoiType := NoRoi;
				RoiRect := SrcRect;
				roiRgn := NewRgn;
				title := 'NoInfo';
				Magnification := 1.0;
				PictureType := NullPicture;
				wptr := nil;
				Changes := false;
				BytesPerRow := 0;
				SetRect(SrcRect, 0, 0, 0, 0);
				PicRect := SrcRect;
				wrect := SrcRect;
				initwrect := wrect;
				savewrect := wrect;
				SaveSrcRect := SrcRect;
				SaveMagnification := magnification;
				savehloc := 0;
				savevloc := 0;
				ScaleToFitWindow := false;
				nColors := 256;
				ColorStart := 0;
				ColorEnd := 255;
				SaveColorStart := 0;
				SaveColorEnd := 255;
				FillColor1 := BlackRGB;
				FillColor2 := BlackRGB;
				SaveFill1 := BlackRGB;
				SaveFill2 := BlackRGB;
				ColorTable := CustomTable;
				LUTMode := GrayScale;
				InvertedColorTable := false;
				xUnit := 'pixel';
				xScale := 0.0;
				yScale := 0.0;
				zScale := 1.0;
				PixelAspectRatio := 1.0;
				SpatiallyCalibrated := false;
				UnitOfMeasure := '';
				PicNum := 1;
				PidNum := 0;
				HeaderOffset := -1;
				ImageDataOffset := -1;
				ColorMapOffset := -1;
				for i := 0 to 255 do
					ctable[i].value := 0;
				Fit := Uncalibrated;
				ZeroClip := false;
				nCoefficients := 0;
				for i := 1 to 6 do
					Coefficient[i] := 0.0;
				BinaryPic := false;
				WindowState := NormalWindow;
				Revertable := false;
				LX1 := -1.0;
				LY1 := -1.0;
				LX2 := -1.0;
				LY2 := -1.0;
				LAngle := 0.0;
				IdentityFunction := false;
				StackInfo := nil;
				Thresholding := false;
				fileVersion := 0;
				vref := 0;
				DataType := EightBits;
				AbsoluteMin := 0;
				AbsoluteMax := 0;
				CurrentMin := 0;
				CurrentMax := 0;
				LittleEndian := false;
				InvertedImage := false;
				DataH := nil;
			end;
			
		MakeGDevice;
		LookForFrameGrabbers;

	{Default settings that can be changed by GetSettings.}
		ForegroundIndex := BlackIndex;
		BackgroundIndex := WhiteIndex;
		BrushWidth := 14;
		BrushHeight := 14;
		SprayCanDiameter := 32;
		SprayCanRadius := 16;
		SprayCanRadius2 := 256;
		CurrentFontID := Helvetica;
		CurrentStyle := []; {plain}
		CurrentSize := 12;
		TextJust := teJustLeft;
		TextBack := NoBack;
		nExtraColors := 0;
		InitExtraColors;
		InvertVideo := false;
		measurements := [AreaM, MeanM];
		InvertPlots := false;
		AutoscalePlots := true;
		LinePlot := true;
		DrawPlotLabels := true;
		FixedSizePlot := false;
		ProfilePlotWidth := 300;
		ProfilePlotHeight := 150;
		if FrameGrabber=ScionAG5 then begin
			FramesToAverage := 32;
			VideoRateAveraging:=true
		end else begin
			FramesToAverage := 16;
			VideoRateAveraging := false;
		end;
		NewPicWidth := 552;
		NewPicHeight := 436;
		BufferSize := DefaultBufferSize;
		ThresholdToForeground := true;
		NonThresholdToBackground := true;
		VideoChannel := 0;
		WhatToImport := ImportTIFF;
		ImportCustomWidth := 512;
		ImportCustomHeight := 512;
		ImportCustomOffset := 0;
		WandAdjustAreas := false;
		BinaryIterations := 1;
		ScaleArithmetic := true;
		InvertPixelValues := false;
		InvertYCoordinates := true;
		FieldWidth := 9;
		precision := 2;
		MinParticleSize := 1;
		MaxParticleSize := 999999;
		IgnoreParticlesTouchingEdge := false;
		LabelParticles := true;
		OutlineParticles := false;
		OscillatingMovies := false;
		MaxMeasurements := 256;
	 	ImportCustomDepth := EightBits;
		ImportSwapBytes := false;
		ImportCalibrate := true;
		ImportAutoScale := true;
		ShowHeadings := false;
		ProfilePlotMin := 0;
		ProfilePlotMax := 255;
		ImportMin := 0.0;
		ImportMax := 255.0;
		HighlightSaturatedPixels := false;
		BallRadius := 50;
		FasterBackgroundSubtraction := true;
		ScaleConvolutions := true;
		BinaryCount := 4;
		BinaryThreshold := BinaryCount * 255;
		HalftoneFrequency := 53;
		HalftoneAngle := 45;
		HalftoneDotFunction := true;
		SyncMode := NormalSync;
		SwitchLUTOnSuspend := false;
		ImportInvert := false;
		TextCreator := 'Imag';
		MathSubGain := 0.5;
		MathSubOffset := 128.0;
		MathGain := MathSubGain;
		MathOffset := MathSubOffset;
		fgScale := 1;
		UseBuiltinDigitizer := true;
		DigitizerMode := digitizeGrayscale;
		DigitizerStandard:= defaultStd;
		LUTFriendlyMode := false;
		{end default settings}
		
		GrayMapReady := false;
		GetSettings; {from 'Image Prefs' file}

		ExplicitPalette := NewPalette(256, nil, pmExplicit, 0);
		CScreenPort := CGrafPtr(NewPtr(SizeOf(CGrafPort)));
		OpenCPort(CScreenPort);
		SetPalette(WindowPtr(CScreenPort), ExplicitPalette, false);
		finished := false;
		FlushEvents(EveryEvent, 0);
		mbhp := pointer(MBarHeight);
		MenuBarHeight := mbhp^;
		SetRect(trect, tleft, ttop, tleft + twidth, ttop + theight);
		ToolWindow := NewCWindow(nil, trect, 'Tools', true, NoGrowDocProc, nil, false, 0);
		SetPalette(ToolWindow, ExplicitPalette, false);
		WindowPeek(ToolWindow)^.WindowKind := ToolKind;
		BringToFront(ToolWindow);
		ScreenWidth := qd.ScreenBits.Bounds.right;
		ScreenHeight := qd.ScreenBits.Bounds.bottom;
		SliceStart := 100;
		SliceEnd := 150;
		with SliceColor do
			begin
				red := -1;
				green := 0;
				blue := 0;
			end;
		DensitySlicing := false;
		with NoInfo^ do
			if LutMode = grayscale then
				ResetGrayMap
			else
				LoadColorTable(ColorStart, ColorEnd, InvertedColorTable); {Use Image Prefs LUT}
		InitMenus;  {LUT must be setup before InitMenus}
		SetRect(gmrect, gmleft, gmtop, gmleft + gmwidth, gmtop + gmheight);
		SetRect(gmSlide1, gmrectleft, gmrectbottom + gmSlide1Offset, gmrectleft + gmSlideWidth, gmrectbottom + gmSlide1Offset + gmSlideHeight);
		gmSlide1i := gmSlide1;
		InsetRect(gmSlide1i, 1, 1);
		SetRect(gmSlide2, gmrectleft, gmrectbottom + gmSlide2Offset, gmrectleft + gmSlideWidth, gmrectbottom + gmSlide2Offset + gmSlideHeight);
		gmSlide2i := gmSlide2;
		InsetRect(gmSlide2i, 1, 1);
		SetRect(gmIcon1, gmIcon1left, gmrectbottom + gmIconOffset, gmIcon1left + gmIconWidth, gmrectbottom + gmIconOffset + gmIconHeight);
		SetRect(gmIcon2, gmIcon2left, gmrectbottom + gmIconOffset, gmIcon2left + gmIconWidth, gmrectbottom + gmIconOffset + gmIconHeight);
		MapWindow := NewWindow(nil, gmrect, 'Map', true, NoGrowDocProc, nil, false, 0);
		WindowPeek(MapWindow)^.WindowKind := MapKind;
		SetRect(MapRect1, gmRectLeft, gmRectTop, gmRectRight, gmRectBottom);
		MapRect2 := MapRect1;
		InsetRect(MapRect2, -2, -2);
		cheight := 256 + (2 + nExtraColors) * ExtraColorsHeight;
		SetRect(crect, cleft, ctop, cleft + cwidth, ctop + cheight);
		LUTWindow := NewCWindow(nil, crect, 'LUT', true, NoGrowDocProc, nil, false, 0);
		SetPalette(LUTWindow, ExplicitPalette, false);
		WindowPeek(LUTWindow)^.WindowKind := LUTKind;
		rleft := 2;
		if ScreenHeight > 480 then
			rtop := ScreenHeight - rheight - 5
		else
			rtop := 358;
		SetRect(trect, rleft, rtop, rleft + rwidth, rtop + rheight);
		InfoWindow := NewWindow(nil, trect, 'Info', true, NoGrowDocProc, nil, false, 0);
		BringToFront(InfoWindow);
		WindowPeek(InfoWindow)^.WindowKind := InfoKind;
		BuggyWatch := GetCursor(WatchCursor);
		InitTools;
		MakeCursors;
		nPics := 0;
		nextPid := -1;
		HistoWindow := nil;
		PlotWindow := nil;
		IsInsertionPoint := false;
		MaskRgn := NewRgn;
		PlotPICT := nil;
		CurrentUndoSize := 0;
		p := GetSyspPtr;
		BlinkTime := BitAnd($000F, p^.volclik) * 4;
		MakePatterns;
		PicLeftBase := twidth + cwidth + 10;
		PicTopBase := MenuBarHeight + 20;
		PicLeft := PicLeftBase;
		PicTop := PicTopBase;
		MouseState := NotInRoi;
		WhatsOnClip := NothingOnClip;
		OldScrapCount := GetScrapCount;
		ClipboardConverted := false;
		Digitizing := false;
		debugging := false;
		BlankFieldInfo := nil;
		PlotCount := 0;
		PlotAvg := 1;
		ActualPlotMin := 0.0;
		ActualPlotMax := 0.0;
		ClipTextInBuffer := false;
		TextBufP := TextBufPtr(NewPtr(SizeOf(TextBufType)));
		if TextBufP = nil then
			ExitToShell;
		MacrosP := MacrosPtr(NewPtr(SizeOf(MacrosRec)));
		if MacrosP = nil then
			ExitToShell;
		mCount := 0;
		mCount2 := 0;
		nPoints := 0;
		nLengths := 0;
		nAngles := 0;
		for i := 1 to MaxStandards do
			StandardValues[i] := BadReal;
		nStandards := 0;
		nKnownValues := 0;
		for i := 0 to 255 do
			cvalue[i] := i;
		WhatToUndo := NothingToUndo;
		WhatToCopy := NothingToCopy;
		PrintRecord := nil;
		printing := false;
		cr := chr(13);
		crStr:=chr(13);
		tab := chr(9);
		BackSpace := chr(8);
		eofChr := chr(4);
		measuring := false;
		UpdateFitEllipse;
		nListColumns := 0;
		if FrameGrabber=ScionAG5 then
			VideoRateAveraging:=true;
		RestoreUndoBuf := true;
		SelectionMode := NewSelection;
		RoiMovementState := Unconstrained;
		PasteControl := nil;
		PasteTransferMode := SrcCopy;
		ImportCustomSlices := 1;
		ImportAll := false;
		RoiNudged := false;
		OpPending := false;
		RedoSelection := false;
		WandAutoMeasure := false;
		OptionKeyWasDown := false;
		InfoMessage := '';
		SaveAsWhat := asTIFF;
		ExportAsWhat := asRaw;
		AnalyzingParticles := false;
		RedirectSampling := false;
		IncludeHoles := false;
		SaveAllState := NoSaveAll;
		ContinuousHistogram := false;
		DrawLabels(' ', '', '');
		HistogramSliceStart := 0;
		HistogramSliceEnd := 255;
		RoiUpdateTime := 0;
		MeasurementToRedo := 0;
		nMacros := 0;
		macro := false;
		KernelsRefNum := 0;
		DefaultRefNum := 0;
		MacrosRefNum := 0;
		LaunchVRefNum := 0;
		LaunchDirID := 0;
		PlugInsVRefNum := 0;
		PlugInsDirID := 0;
		DefaultFileName := '';
		rsHScale := 1.0;
		rsVScale := 1.0;
		rsAngle := 0.0;
		rsMethod := NearestNeighbor;
		rsCreateNewWindow := true;
		rsInteractive := false;
		DriverHalftoning := true;
		LivePasteMode := false;
		ShowCount := true;
		PasteControlLeft := ScreenWidth - pcwidth - 10;
		PasteControlTop := trunc(ScreenHeight * 0.2);
		MaxCoordinates := 10000;
		ResultsLeft := PicLeftBase;
		ResultsTop := 56;
		UnsavedResults := false;
		MajorLabel := 'Major';
		MinorLabel := 'Minor';
		User1Label := 'User 1';
		User2Label := 'User 2';
		MakingLOI := false;
		LOIType := Straight;
		MakingStack := false;
		FramesWanted := 20;
		DelayTicks := 0;
		CmdPeriodToStop := 'Type cmd-''.'' to stop.';
		CommandKey := chr(17);
		ClipboardColor := BlackRGB;
		InitAngle := 0;                                             {default is one full revolution of volume}
		TotalAngle := 360;
		AngleInc := 10;                                           {in ten-degree increments}
		TransparencyUpper := 254;                      {default has only value 255 transparent}
		TransparencyLower := 0;
		DepthCueSurf := 0;                                     {default has full depth-cueing for surface}
		DepthCueInt := 50;                                     {components and 50% depth-cueing elsewhere}
		Opacity := 0;
		SaveProjections := FALSE;                         {by default, do not save and close projections}
		AxisOfRotation := xAxis;
		MinProjSize := TRUE;                                {by default, make all windows just big enough}
		ProjectionMethod := NearestPoint;
		MeterWindow := nil;
		nCoordinates := 0;
		CoordinatesWidth := 0;
		CoordinatesHeight := 0;
		CoordinatesRoiType := NoRoi;
		SumFrames := false;
		ShowIntegratedValues := false;
		FixIntegrationScale := false;
		IntegrationMin := 0;
		IntegrationMax := 4096;
		ExternalTrigger := false;
		BlindMovieCapture := false;
		VideoControl := nil;
		DitherColor := true;
		RGBLut := CustomLUT;
		with Highlight1 do
			begin
				red := -1;
				green := 0;
				blue := 0;
			end;
		with Highlight254 do
			begin
				red := -1;
				green := -1;
				blue := 0;
			end;
		HighlightMode := false;
		LegalWithoutImage := [UpdateLutC, StartC, ShowResultsC, GetPicSizeC, PutMsgC, ExitC, CaptureC, MoveToC, BeepC, MakeNewC, SetPaletteC, SetBackC, GetRoiC, OpenC, ImportC, SetImportC, SetMinMaxC, SetCustomC, nPicsC, WaitC, SetSizeC, TriggerC, AverageFramesC, SaveStateC, RestoreStateC, SetCounterC, MakeStackC, ShowMsgC, SetUser1C, SetUser2C, SetOptionsC, RequiresC];
		LegalWithoutImage := LegalWithoutImage + [DisposeAllC, GetTimeC, SetForeC, SetBackC, GetStringC, OpenSerialC, GetSerialC, PutSerialC, SetCursorC, TickCountC, ConcatC, SetVideoC, StringToNumC, ChannelC, AcquireC, UndoSizeC, CallFilterC, PhotoModeC, DrawTextC, WriteC, WritelnC, NewTextWindowC, UserCodeC, SelectWindowC, BitAndC, BitOrC, WindowTitleC, ScaleConvolutionsC];
		LegalWithoutImage := LegalWithoutImage + [SaveC, SaveAsC, CloseC, DisposeC, PosC, DeleteC, LengthC, SetPrecisionC, SetExportC, ExportC, SetFontC, SetFontSizeC, SetTextC, GetC, MoveWindowC, GetFileInfoC, SelectToolC];
		TopOfStack := 0;
		SerialBufferP := nil;
		OpeningPlugInWindow := false;
		LG3DacA := 0;
		LG3DacB := 0;
		LG3DataOut := 0;
		nAcqPlugIns := 0;
		nExportPlugIns := 0;
		nFilterPlugIns := 0;
		LastAcqPlugIn := '';
		LastFilterPlugIn := '';
		LastExportPlugIn := '';
		TextInfo := nil;
		nTextWindows := 0;
		NewTitle := 'Untitled';
		CurrentWPtr := nil;
		CurrentKind := 0;
		SearchString := '';
		CurrentMathOp := SubMath;
		MathSrc1 := 1;
		MathSrc2 := 1;
		MathResult := 'Result';
		APReset := true;
		ShowPlot := true;
		FiducialMethod := OnScreen;
		ConfirmFidClicks := false;
		WatchIndex := 1;
		WireframeSurfacePlots := true;
		GrayscaleSurfacePlots := false;
		RankFilter := MedianRank;
		RankIterations := 1;
		TextScrollActionProc:=nil;
		AboutBoxFilterProc:=nil;	
		AboutBoxUserProc:=nil;
		ResultsScrollActionProc:=nil;
		ImageMathUserProc:=nil;
		SetScaleUserProc:=nil;
		OpenDHookProc:=nil;
		SaveAsDHookProc:=nil;
		ImportDHookProc:=nil;
		ExportDHookProc:=nil;
		BitInfoProc:=nil;
		GetPictDataProc:=nil;
		TestAbortProc:=nil;
		UpdateProgressProc:=nil;
		AG5LutMode := false;
		AG5GrabMode := GrabNormal;
		AG5BufferMode := Read0Lut1Grab0;
		IntegrateOnChip:=false;
		OpeningFinderFiles:=false;
		gNumberSlices:=true;
		gBorders:=true;
		RealImageMath:=false;
		DicomInitialized := false;
		ImportingDicom := false;
		err := HGetVol(nil, StartupSpec.vRefNum, StartupSpec.parID);
		OpeningRGB := false;
		PrecisionTiming := false;
		LG3BufferCapture := false;
		TimeStamp := false;
		SecondsPerFrame := 0.0;
		TriggerFirstFrameOnly := true;
		UseExistingStack := false;
		RealArithmetic := false;
		vdig := nil;
		GWorldLUT := nil;
		osGWorld := nil;
		if InvertPixelValues then
			InvertGrayLevels;
		MovieToolboxInitialized := false;
end;


end.
