unit File3; {Routines used by Image for loading ??} interface uses QuickDraw, Palettes, PrintTraps, globals, Utilities, Graphics; function OpenATM3File (fname: str255; vnum: integer): boolean; function OpenAPICFile (fname: str255; vnum: integer): boolean; function OpenAPI2File (fname: str255; vnum: integer): boolean; type TransformType = (None, SubtractOffset, SubtractLine); ScalingType = (Auto, Fix); NoiseFilter = (NoFilter, Gauss5, Gauss7, Linear5); { types for opening afm header } var Transform: TransformType; Scaling: ScalingType; Scalingfactor: integer; Filt: NoiseFilter; implementation function CloseAWindow (WhichWindow: WindowPtr): integer; external; procedure DoBusyBox (n, a: integer); external; procedure OpenBusyBox (text: str255); external; procedure CloseBusyBox; external; const InputOptionsDLOG = 2400; InputOk = 1; InputCancel = 2; TransNone = 5; TransOffset = 6; TransLine = 7; ScaleAuto = 9; ScaleFixed = 10; ScaleNumber = 11; LineFilterNone = 13; LineFilterLinear = 14; LineFilterGauss5 = 15; LineFilterGauss7 = 16; ScalingMenu = 150; type PiezoRec = record x_low: integer; x_high: integer; x_gauge: extended; x_gain: integer; y_low: integer; y_high: integer; y_gauge: extended; y_gain: integer; z_low: integer; z_high: integer; z_gauge: extended; z_gain: integer; step_width: extended; end; Direction = (NorthWest, North, NorthEast, East); ScanRec = record width: integer; {pixels} height: integer; direction: Direction; x_null: extended; y_null: extended; dx_pixel: extended; { A } dy_pixel: extended; dx_line: extended; dy_line: extended; steps: integer; end; ForceRec = record low: integer; high: integer; steps: integer; end; MacAdiosRec = record gain: integer; mode: integer; slot: integer; AD16BitFlag: boolean; end; FileInfoRec = record width: integer; height: integer; x_Range: extended; y_Range: extended; x_Null: extended; y_Null: extended; revision: integer; sample: string[50]; prep: string[50]; exp: string[50]; comment: string[50]; cantilever: string[50]; n_Channels: integer; end; ChannelInfoRec = record InvertFlag: boolean; z_Range: extended; ADNumber: integer; AD_Name: string[50]; end; AFMDataArray = array[0..262144] of integer; AFMDataArrayPtr = ^AFMDataArray; AFMDataArrayHandle = ^AFMDataArrayPtr; procedure ShowTrans (mylog: DialogPtr; Transform: TransformType); begin SetDialogItem(mylog, TransNone, 0); SetDialogItem(mylog, TransOffset, 0); SetDialogItem(mylog, TransLine, 0); case Transform of None: SetDialogItem(mylog, TransNone, 1); SubtractOffset: SetDialogItem(mylog, TransOffset, 1); SubtractLine: SetDialogItem(mylog, TransLine, 1); end; end; procedure ShowScaling (mylog: DialogPtr; Scaling: ScalingType); begin SetDialogItem(mylog, ScaleAuto, 0); SetDialogItem(mylog, ScaleFixed, 0); case Scaling of Auto: SetDialogItem(mylog, ScaleAuto, 1); Fix: SetDialogItem(mylog, ScaleFixed, 1); end; end; procedure ShowFilter (mylog: DialogPtr; Filter: NoiseFilter); begin SetDialogItem(mylog, LineFilterNone, 0); SetDialogItem(mylog, LineFilterLinear, 0); SetDialogItem(mylog, LineFilterGauss5, 0); SetDialogItem(mylog, LineFilterGauss7, 0); case Filter of NoFilter: SetDialogItem(mylog, LineFilterNone, 1); Linear5: SetDialogItem(mylog, LineFilterLinear, 1); Gauss5: SetDialogItem(mylog, LineFilterGauss5, 1); Gauss7: SetDialogItem(mylog, LineFilterGauss7, 1); end; end; function Item2Trans (item: integer): TransformType; begin Item2Trans := None; case item of TransNone: Item2Trans := None; TransOffset: Item2Trans := SubtractOffset; TransLine: Item2Trans := SubtractLine end; end; function Item2Scaling (item: integer): ScalingType; begin Item2Scaling := Auto; case item of ScaleAuto: Item2Scaling := Auto; ScaleFixed: Item2Scaling := Fix; end; end; function Item2Filter (item: integer): NOISEFILTER; begin Item2Filter := Linear5; case item of LineFilterNone: Item2Filter := NoFilter; LineFilterLinear: Item2Filter := Linear5; LineFilterGauss5: Item2Filter := Gauss5; LineFilterGauss7: Item2Filter := Gauss7; end; end; procedure ShowScalingNumber (dlog: DialogPtr; number: integer); var Itemtype: 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); NumToString(number, text); DrawString(text); end; end; function HandleScalingNumber (dlog: DialogPtr; number: integer): integer; var Itemtype, Result: 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(ScalingMenu); InsertMenu(PopUpMenuH, -1); pt := BoxRect.topleft; LocalToGlobal(pt); Result := PopUpMenuSelect(PopUpMenuH, pt.v, pt.h, number); if Result > 0 then HandleScalingNumber := Result else HandleScalingNumber := number; InvertRect(TitleRect); DeleteMenu(ScalingMenu); end; procedure ChecKInputOptions; var isOk: boolean; begin if ScalingFactor < 1 then ScalingFactor := 1 else if Scalingfactor > 20 then ScalingFactor := 20; isOk := false; case Transform of None, SubtractOffset, SubtractLine: isOk := true; end; if isOk = false then Transform := SubtractLine; isOk := false; case Scaling of Auto, Fix: isOk := true; end; if isOk = false then Scaling := Auto; isOk := false; case Filt of NoFilter, Gauss5, Gauss7, Linear5: isOk := true; end; if isOk = false then Filt := Gauss7; end; procedure GetInputOptions (var Transform: TransformType; var Scaling: ScalingType; var Scalingfactor: integer); var mylog: DialogPtr; item, i: integer; auxTrans: TransformType; auxScaling: ScalingType; auxScalingFactor: integer; auxFilter: NoiseFilter; tport: GrafPtr; begin mylog := GetNewDialog(InputOptionsDLOG, nil, pointer(-1)); GetPort(tport); SetPort(mylog); OutlineButton(mylog, InputOK, 16); ShowTrans(mylog, Transform); ShowScaling(mylog, Scaling); ShowFilter(myLog, Filt); auxFilter := Filt; auxTrans := Transform; auxScaling := Scaling; auxScalingFactor := ScalingFactor; ShowScalingNumber(mylog, auxScalingFactor); repeat ModalDialog(nil, item); case item of TransNone, TransOffset, TransLine: begin auxtrans := Item2Trans(item); ShowTrans(mylog, auxtrans); end; ScaleAuto, ScaleFixed: begin auxScaling := Item2Scaling(item); ShowScaling(mylog, auxScaling); end; LineFilterNone, LineFilterLinear, LineFilterGauss5, LineFilterGauss7: begin auxFilter := Item2Filter(item); ShowFilter(mylog, auxFilter); end; ScaleNumber: begin auxScalingFactor := HandleScalingNumber(mylog, auxScalingFactor); ShowScalingNumber(mylog, auxScalingFactor); end; otherwise ; end; until (item = InputOk) or (item = InputCancel); if item = InputOk then begin Scaling := AuxScaling; Transform := AuxTrans; ScalingFactor := AuxScalingFactor; Filt := auxFilter; end; SetPort(tport); DisposDialog(mylog); end; procedure DoFilter (buffer: AFMDataArrayPtr; Filter: NoiseFilter; ScanRecord: ScanRec); var line, i, j, n, filtersize, gauge: integer; offset, sum: longint; transform: array[0..10] of LongInt; aLine: array[0..1024] of integer; {we need one line buffer } begin n := ScanRecord.width; case Filter of Gauss5: begin filtersize := 2; transform[0] := 17; transform[1] := 12; transform[2] := -3; gauge := 35; end; Gauss7: begin filtersize := 3; transform[0] := 7; transform[1] := 6; transform[2] := 3; transform[3] := -2; gauge := 21; end; linear5: begin filtersize := 2; gauge := 5; end; otherwise ; end; { der lineare Filter ist trivial und wird sofort gemacht } offset := 0; if Filter <> NoFilter then for line := 0 to ScanRecord.height - 1 do begin if Filter = Linear5 then begin for i := filtersize to n - filtersize do begin sum := 0; for j := i - filtersize to i + filtersize do begin sum := sum + buffer^[j + offset]; end; sum := sum div gauge; aLine[i] := sum; end; for i := 0 to filtersize - 1 do aLine[i] := aLine[filtersize]; for i := n - filtersize to n - 1 do aLine[i] := aLine[n - filtersize]; end { end linear Filter } else begin for i := filtersize + 1 to n - filtersize do begin sum := 0; for j := 1 to filtersize do begin sum := sum + transform[j] * buffer^[i - j + offset]; sum := sum + transform[j] * buffer^[i + j + offset]; end; sum := sum + transform[0] * buffer^[i + offset]; sum := sum div gauge; aLine[i] := sum; end; for i := 1 to filtersize do aLine[i] := aLine[filtersize + 1]; for i := n - filtersize + 1 to n do aLine[i] := aLine[n - filtersize]; end; { end else filter } { copy the buffer to the data } for i := 0 to n - 1 do buffer^[i + offset] := aLine[i]; offset := offset + ScanRecord.width; end; end; function OpenAPICFile (fname: str255; vnum: integer): boolean; var AFMDataArrayH: AFMDataArrayHandle; AFMDataP: AFMDataArrayPtr; aLine: LineType; LineAverage: LongInt; aNumber, value_range: integer; min, max: integer; k: integer; ticks, ByteCount, i, j, LineOffset: LongInt; err: OSErr; f: integer; line, pixel: integer; r2, r3: rect; loc: Point; p: ptr; value: byte; iptr: ptr; name: str255; buffer: array[0..512] of Byte; ScanRecord: ScanRec; PiezoRecord: PiezoRec; MacAdiosRecord: MacAdiosRec; size: LongInt; comment: str255; InfoWindow, OldInfo, SaveInfo: InfoPtr; S, S_x, S_xx, S_xy, S_y, delta_s: double; a, b, c: double; begin AFMDataArrayH := AFMDataArrayHandle(NewHandle(sizeof(AFMDataArray))); if AFMDataArrayH = nil then begin DisposHandle(Handle(AFMDataArrayH)); exit(OpenAPICFile) end; OpenAPICFile := false; ChecKInputOptions; if OptionKeyDown or OptionKeyWasDown then GetInputOptions(Transform, Scaling, Scalingfactor); ShowWatch; err := fsopen(fname, vNum, f); if err <> 0 then begin PutMessage('Sorry, error opening file'); exit(OpenApicFile); end; { first create a info window and copy all interesting stuff in it } p := ptr(@ScanRecord); size := longint(sizeof(ScanRecord)); err := FSRead(f, size, p); p := ptr(@PiezoRecord); size := longint(sizeof(PiezoRecord)); err := FSRead(f, size, p); p := ptr(@MacAdiosRecord); size := longint(sizeof(MacAdiosRecord)); err := FSRead(f, size, p); p := ptr(@comment); size := 255; err := FSRead(f, size, p); SaveInfo := Info; name := concat('Info about ', fname); if NewPicWindow(name, 300, 200) then begin with Info^ do begin SetPort(GrafPtr(osPort)); osPort^.fgcolor := BlackIndex; end; InfoWindow := Info; TextSize(12); MoveTo(10, 15); DrawString('Filename :'); MoveTo(100, 15); DrawString(fname); MoveTo(10, 30); DrawString('comment :'); MoveTo(100, 30); DrawString(comment); with ScanRecord do begin MoveTo(10, 45); DrawString('size : '); MoveTo(80, 45); DrawLong(width); MoveTo(150, 45); DrawString('*'); MoveTo(170, 45); DrawLong(height); MoveTo(80, 60); DrawReal(width * sqrt(dx_pixel * dx_pixel + dy_pixel * dy_pixel), 2, 2); MoveTo(150, 60); DrawString('*'); MoveTo(170, 60); DrawReal(height * sqrt(dx_line * dx_line + dy_line * dy_line), 2, 2); MoveTo(10, 75); DrawString('start : '); MoveTo(80, 75); DrawReal(x_null, 2, 2); MoveTo(150, 75); DrawString(','); MoveTo(170, 75); DrawReal(y_null, 2, 2); end; MoveTo(10, 100); DrawString('MinValue MaxValue Range[]'); UpdatePicWindow; ResetGrayMap; for k := 0 to 3 do begin case k of 0: begin name := concat('F-', fname); loc.h := 0; loc.v := 220; end; 1: begin name := concat('B-', fname); loc.h := ScanRecord.width; loc.v := 220; end; 2: begin name := concat('FU-', fname); loc.h := 0; loc.v := 240 + ScanRecord.height; end; 3: begin name := concat('BU-', fname); loc.h := ScanRecord.width; loc.v := 240 + ScanRecord.height; end; end; if CommandPeriod then begin DisposHandle(Handle(AFMDataArrayH)); err := fsclose(f); exit(OpenAPICFile); end; OldInfo := Info; if NewPicWindow(name, ScanRecord.width, ScanRecord.height) then begin with Info^ do begin MoveWindow(wptr, loc.h, loc.v, true); SaveInfo := Info; Info := OldInfo; UpdatePicWindow; Info := SaveInfo; ScaleToFitWindow := true; LUTMode := GrayScale; ByteCount := 512 + k * SizeOf(integer) * ImageSize; err := SetFPos(f, fsFromStart, ByteCount); ByteCount := SizeOf(integer) * ImageSize; Hlock(handle(AFMDataArrayH)); AFMDataP := AFMDataArrayH^; err := fsread(f, ByteCount, ptr(AFMDataP)); if err <> NoErr then begin PutMessage('Error while reading data ! Unexpected end of data'); err := fsclose(f); DisposHandle(Handle(AFMDataArrayH)); err := CloseAWindow(FrontWindow); exit(OpenAPICFile); end; { Transform the Line } LineOffset := 0; for i := 0 to nlines - 1 do begin case transform of SubtractLine: begin S := PixelsPerLine; S_x := S * (S + 1) * 0.5; S_xx := S * (S + 1) * (2 * S + 1) / 6.0; S_xy := 0; S_y := 0; for j := 0 to (PixelsPerLine - 1) do begin aNumber := AFMDataP^[LineOffset + j]; S_y := S_y + aNumber; S_xy := S_xy + j * aNumber; end; delta_S := (S * S_xx - S_x * S_x); b := (S * S_xy - S_x * S_y) / delta_S; a := (S_xx * S_y - S_x * S_xy) / delta_S; for j := 0 to (PixelsPerLine - 1) do AFMDataP^[LineOffset + j] := round(AFMDataP^[LineOffset + j] - a - b * j); end; SubtractOffset: begin LineAverage := 0; for j := 0 to PixelsPerLine - 1 do begin aNumber := AFMDataP^[LineOffset + j]; LineAverage := LineAverage + aNumber; end; LineAverage := round(LineAverage / PixelsPerLine); for j := 0 to PixelsPerLine - 1 do AFMDataP^[LineOffset + j] := AFMDataP^[LineOffset + j] - LineAverage; end; otherwise ; end; LineOffset := LineOffset + PixelsPerLine; end; { end of transform } { Filter the line } DoFilter(AFMDataP, Filt, ScanRecord); { end of Filter } Min := 16000; Max := -16000; if scaling = Auto then begin LineOffset := 0; for i := 0 to nlines - 1 do begin for j := 0 to PixelsPerLine - 1 do begin aNumber := AFMDataP^[LineOffset + j]; if min > aNumber then min := aNumber; if Max < aNumber then Max := aNumber; end; LineOffset := LineOffset + PixelsPerLine; end; if max > -min then scalingfactor := round(max / (128)) + 1 else begin scalingfactor := round(-min / (128)) + 1; max := -min; end; end; { now scale and write the data } with ScanRecord do begin x_range := sqrt(dx_pixel * dx_pixel + dy_pixel * dy_pixel); y_range := sqrt(dx_line * dx_line + dy_line * dy_line); { check the entries in the header of afm file } if (MacAdiosRecord.gain > 0) and (PiezoRecord.z_gauge > 0) and (PiezoRecord.z_gain > 0) then z_range := 10.0 * PiezoRecord.z_gauge * PiezoRecord.z_gain / (4096.0 * MacAdiosRecord.gain) else z_range := 1; if (z_range < 1e-6) or (z_range > 1e6) then z_range := 1; end; LineOffset := 0; for i := 0 to nlines - 1 do begin for j := 0 to PixelsPerLine - 1 do begin aNumber := 128 + AFMDataP^[LineOffset + j] div ScalingFactor; if aNumber > 255 then aNumber := 255; if aNumber < 0 then aNumber := 0; aLine[j] := aNumber; end; LineOffset := LineOffset + PixelsPerLine; PutLine(0, i, PixelsPerLine, aLine); end; HUnlock(handle(AFMDataArrayH)); if ImageSize > UndoBufSize then PutWarning; end; end; SetupUndo; UpdatePicWindow; SaveInfo := Info; Info := InfoWindow; MoveTo(10, 115 + k * 15); DrawLong(min); MoveTo(70, 115 + k * 15); DrawLong(max); MoveTo(130, 115 + k * 15); DrawLong(ScalingFactor); MoveTo(190, 115 + k * 15); DrawReal(SaveInfo^.z_range, 2, 2); Info := SaveInfo; end; {with} OpenAPICFile := true; end; err := fsclose(f); DisposHandle(Handle(AFMDataArrayH)); end; function OpenAPI2File (fname: str255; vnum: integer): boolean; const PosOffset = 10240; MaxChannels = 5; var AFMDataArrayH: AFMDataArrayHandle; AFMDataP: AFMDataArrayPtr; aLine: LineType; LineAverage: LongInt; aNumber, value_range, channel: integer; min, max: integer; k: integer; ticks, ByteCount, i, j, LineOffset: LongInt; err: OSErr; f: integer; line, pixel: integer; r2, r3: rect; loc: Point; p: ptr; channelstring: str255; value: byte; iptr: ptr; name: str255; buffer: array[0..512] of Byte; ScanRecord: ScanRec; PiezoRecord: PiezoRec; MacAdiosRecord: MacAdiosRec; FileInfo: FileInfoRec; ChannelInfo: array[1..MaxChannels] of ChannelInfoRec; size: LongInt; comment: str255; InfoWindow, OldInfo, SaveInfo: InfoPtr; S, S_x, S_xx, S_xy, S_y, delta_s: double; a, b, c: double; begin AFMDataArrayH := AFMDataArrayHandle(NewHandle(sizeof(AFMDataArray))); if AFMDataArrayH = nil then begin DisposHandle(Handle(AFMDataArrayH)); exit(OpenAPI2File) end; OpenAPI2File := false; ChecKInputOptions; if OptionKeyDown or OptionKeyWasDown then GetInputOptions(Transform, Scaling, Scalingfactor); ShowWatch; err := fsopen(fname, vNum, f); if err <> 0 then begin PutMessage('Sorry, error opening file'); exit(OpenApi2File); end; { first create an info window and copy all interesting stuff in it } err := SetFPos(f, fsFromStart, PosOffset); p := ptr(@FileInfo); size := longint(sizeof(FileInfo)); err := FSRead(f, size, p); for channel := 1 to FileInfo.n_channels do begin p := ptr(@ChannelInfo[Channel]); size := longint(sizeof(ChannelInfo[Channel])); err := FSRead(f, size, p); end; SaveInfo := Info; name := concat('Info about ', fname); if NewPicWindow(name, 450, 160 + FileInfo.n_channels * 60) then begin with Info^ do begin SetPort(GrafPtr(osPort)); osPort^.fgcolor := BlackIndex; end; with FileInfo do begin InfoWindow := Info; TextSize(12); MoveTo(10, 15); DrawString('Filename:'); MoveTo(100, 15); DrawBString(fname); MoveTo(10, 30); DrawString('Sample:'); MoveTo(100, 30); DrawString(sample); MoveTo(10, 45); DrawString('Experiment.:'); MoveTo(100, 45); DrawString(exp); MoveTo(10, 60); DrawString('Preparation:'); MoveTo(100, 60); DrawString(prep); MoveTo(10, 75); DrawString('comment:'); MoveTo(100, 75); DrawString(comment); MoveTo(10, 90); DrawString('size : '); MoveTo(80, 90); DrawLong(width); MoveTo(150, 90); DrawString('*'); MoveTo(170, 90); DrawLong(height); MoveTo(80, 105); DrawReal(width * x_range, 2, 2); MoveTo(150, 105); DrawString('*'); MoveTo(170, 105); DrawReal(height * y_range, 2, 2); MoveTo(10, 120); DrawString('start : '); MoveTo(80, 120); DrawReal(x_null, 2, 2); MoveTo(150, 120); DrawString(','); MoveTo(170, 120); DrawReal(y_null, 2, 2); MoveTo(10, 140); DrawBString('MinValue MaxValue Range[] AD# AD Name'); UpdatePicWindow; ResetGrayMap; end; for channel := 1 to FileInfo.n_channels do begin numtostring(longint(channel), channelstring); for k := 0 to 3 do begin case k of 0: begin name := concat('F-', fname, ' ', channelstring); loc.h := 0; loc.v := 220; end; 1: begin name := concat('B-', fname, ' ', channelstring); loc.h := FileInfo.width; loc.v := 220; end; 2: begin name := concat('FU-', fname, ' ', channelstring); loc.h := 0; loc.v := 240 + FileInfo.height; end; 3: begin name := concat('BU-', fname, ' ', channelstring); loc.h := FileInfo.width; loc.v := 240 + FileInfo.height; end; end; if CommandPeriod then begin DisposHandle(Handle(AFMDataArrayH)); err := fsclose(f); exit(OpenAPI2File); end; OldInfo := Info; if NewPicWindow(name, FileInfo.width, FileInfo.height) then begin with Info^ do begin MoveWindow(wptr, loc.h, loc.v, true); SaveInfo := Info; Info := OldInfo; UpdatePicWindow; Info := SaveInfo; ScaleToFitWindow := true; LUTMode := GrayScale; ByteCount := SizeOf(integer) * ImageSize; Hlock(handle(AFMDataArrayH)); AFMDataP := AFMDataArrayH^; err := fsread(f, ByteCount, ptr(AFMDataP)); if err <> NoErr then begin PutMessage('Error while reading data ! Unexpected end of data'); err := fsclose(f); DisposHandle(Handle(AFMDataArrayH)); err := CloseAWindow(FrontWindow); exit(OpenAPI2File); end; { Transform the Line } LineOffset := 0; for i := 0 to nlines - 1 do begin case transform of SubtractLine: begin S := PixelsPerLine; S_x := S * (S + 1) * 0.5; S_xx := S * (S + 1) * (2 * S + 1) / 6.0; S_xy := 0; S_y := 0; for j := 0 to (PixelsPerLine - 1) do begin aNumber := AFMDataP^[LineOffset + j]; S_y := S_y + aNumber; S_xy := S_xy + j * aNumber; end; delta_S := (S * S_xx - S_x * S_x); b := (S * S_xy - S_x * S_y) / delta_S; a := (S_xx * S_y - S_x * S_xy) / delta_S; for j := 0 to (PixelsPerLine - 1) do AFMDataP^[LineOffset + j] := round(AFMDataP^[LineOffset + j] - a - b * j); end; SubtractOffset: begin LineAverage := 0; for j := 0 to PixelsPerLine - 1 do begin aNumber := AFMDataP^[LineOffset + j]; LineAverage := LineAverage + aNumber; end; LineAverage := round(LineAverage / PixelsPerLine); for j := 0 to PixelsPerLine - 1 do AFMDataP^[LineOffset + j] := AFMDataP^[LineOffset + j] - LineAverage; end; otherwise ; end; LineOffset := LineOffset + PixelsPerLine; end; { end of transform } { Filter the line } DoFilter(AFMDataP, Filt, ScanRecord); { end of Filter } Min := 16000; Max := -16000; if scaling = Auto then begin LineOffset := 0; for i := 0 to nlines - 1 do begin for j := 0 to PixelsPerLine - 1 do begin aNumber := AFMDataP^[LineOffset + j]; if min > aNumber then min := aNumber; if Max < aNumber then Max := aNumber; end; LineOffset := LineOffset + PixelsPerLine; end; if max > -min then scalingfactor := round(max / (128)) + 1 else begin scalingfactor := round(-min / (128)) + 1; max := -min; end; end; Info^.x_range := FileInfo.x_range; Info^.y_range := FileInfo.y_range; Info^.z_range := ChannelInfo[channel].z_range; LineOffset := 0; if ChannelInfo[channel].invertflag then begin for i := 0 to nlines - 1 do begin for j := 0 to PixelsPerLine - 1 do begin aNumber := 128 + AFMDataP^[LineOffset + j] div ScalingFactor; if aNumber > 255 then aNumber := 255; if aNumber < 0 then aNumber := 0; aLine[j] := aNumber; end; LineOffset := LineOffset + PixelsPerLine; PutLine(0, i, PixelsPerLine, aLine); end; end else begin for i := 0 to nlines - 1 do begin for j := 0 to PixelsPerLine - 1 do begin aNumber := 127 - AFMDataP^[LineOffset + j] div ScalingFactor; if aNumber > 255 then aNumber := 255; if aNumber < 0 then aNumber := 0; aLine[j] := aNumber; end; LineOffset := LineOffset + PixelsPerLine; PutLine(0, i, PixelsPerLine, aLine); end; end; HUnlock(handle(AFMDataArrayH)); if ImageSize > UndoBufSize then PutWarning; end; end; SetupUndo; UpdatePicWindow; SaveInfo := Info; Info := InfoWindow; textSize(10); MoveTo(10, 160 + (channel - 1) * 60 + k * 12); DrawLong(min); MoveTo(95, 160 + (channel - 1) * 60 + k * 12); DrawLong(max); MoveTo(145, 160 + (channel - 1) * 60 + k * 12); DrawLong(ScalingFactor); MoveTo(190, 160 + (channel - 1) * 60 + k * 12); DrawReal(SaveInfo^.z_range, 2, 2); MoveTo(280, 160 + (channel - 1) * 60 + k * 12); DrawLong(ChannelInfo[channel].ADNumber); MoveTo(335, 160 + (channel - 1) * 60 + k * 12); DrawString(ChannelInfo[channel].AD_Name); Info := SaveInfo; end; OpenAPI2File := true; end; end; err := fsclose(f); DisposHandle(Handle(AFMDataArrayH)); end; function OpenATM3File (fname: str255; vnum: integer): boolean; begin PutMessage('Sorry, this Datatype is not supported yet'); OpenATM3File := false; end; end.