home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Pascal / Applications / NIH Image 1.59 / 1.59 Source / File2.p < prev    next >
Encoding:
Text File  |  1995-10-26  |  72.3 KB  |  2,571 lines  |  [TEXT/PJMM]

  1. unit File2;
  2.  
  3. {Routines used by NIH Image for printing plus a few additional File Menu routines.}
  4.  
  5. interface
  6.  
  7.  
  8.     uses
  9.         Memory, QuickDraw, Packages, Menus, Events, Fonts, Scrap, ToolUtils, Resources, Errors, Palettes, Printing, StandardFile, Folders, globals, Utilities, Graphics, Lut;
  10.  
  11.  
  12.     procedure GetInfo;
  13.     procedure DoPageSetup;
  14.     procedure Print (ShowDialog: boolean);
  15.     procedure SetHalftone;
  16.     function OpenMacPaint (fname: str255; vnum: integer): boolean;
  17.     procedure TypeMismatch (fname: str255);
  18.     procedure SaveAsMacPaint (fname: str255; RefNum: integer);
  19.     function GetTextFile (var name: str255; var RefNum: integer): boolean;
  20.     procedure InitTextInput (name: str255; RefNum: integer);
  21.     procedure GetLineFromText (var rLine: RealLine; var count: integer);
  22.     function ImportTextFile (name: str255; RefNum: integer): boolean;
  23.     procedure PlotXYZ;
  24.     procedure SaveSettings;
  25.     procedure ExportAsText (fname: str255; RefNum: integer);
  26.     procedure ExportMeasurements (fname: str255; RefNum: integer);
  27.     function OpenTiffHeader (f: integer; var DirOffset: LongInt): boolean;
  28.     function OpenTiffDirectory (f: integer; DirOffset: LongInt; var TiffInfo: TiffInfoRec; Importing: boolean): boolean;
  29.     procedure SaveTiffColorMap (f: integer; ImageDataSize: LongInt);
  30.     procedure GetTiffColorMap (f: integer);
  31.     function SaveTiffDir (f, slines, sPixelsPerLine: integer; SavingSelection: boolean; ctabSize, ImageDataSize: LongInt): OSErr;
  32.     function RoomForFile (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  33.     function WriteExtraTiffIFDs (f: integer; ImageDataSize, cTabSize: LongInt): integer;
  34.     procedure SaveLUT (fname: str255; RefNum: integer);
  35.     procedure SaveColorTable (fname: str255; RefNum: integer);
  36.     procedure ExportCoordinates (fname: str255; RefNum: integer);
  37.     procedure SaveOutline (fname: str255; RefNum: integer);
  38.     procedure OpenOutline (fname: str255; RefNum: integer);
  39.     function CheckIO (err: OSerr): integer;
  40.     function GetTIFFParameters (name: str255; RefNum: integer; var HasColorMap: boolean): boolean;
  41.     procedure GetXUnits (UnitsKind: UnitsType);
  42.     procedure GetUnitsKInd (var UnitsKind: UnitsType; var UnitsPerCM: extended);
  43.     procedure Swap2Bytes (var i: integer);
  44.  
  45.  
  46. implementation
  47.  
  48.     var
  49.         gstr: str255;
  50.  
  51.  
  52. {$PUSH}
  53. {$D-}
  54.  
  55.     procedure PrintErrCheck;
  56.         var
  57.             err: integer;
  58.             ticks: LongInt;
  59.     begin
  60.         err := PrError;
  61.         if err < 0 then
  62.             beep;
  63.     end;
  64.  
  65.  
  66.     procedure DoPageSetup;
  67.         var
  68.             result: boolean;
  69.     begin
  70.         PrOpen;
  71.         if PrintRecord = nil then begin
  72.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  73.                 PrintDefault(PrintRecord);
  74.             end;
  75.         if PrError = NoErr then begin
  76.                 result := PrValidate(PrintRecord);
  77.                 result := PrStlDialog(PrintRecord);
  78.             end;
  79.         PrClose;
  80.     end;
  81.  
  82.  
  83.     procedure PrintHalftone;
  84.         const
  85.             PostScriptBegin = 190;
  86.             PostScriptEnd = 191;
  87.             PostScriptHandle = 192;
  88.             TextIsPostScript = 194;
  89.         var
  90.             HexBufH: handle;
  91.             hloc, vloc, HexCount, iheight, iwidth, hstart, vstart: integer;
  92.             Height, Width, eofStr, angle, freq: str255;
  93.             aLine: LineType;
  94.             HexBuf: packed array[0..4200] of char;
  95.             err: OSErr;
  96.             table: LookupTable;
  97.  
  98.         procedure PutHEX (byt: integer);
  99.             var
  100.                 i, LowByte, HighByte, tmp: integer;
  101.                 h: char;
  102.         begin
  103.             if not info^.IdentityFunction then
  104.                 byt := table[byt];
  105.             byt := 255 - byt;
  106.             LowByte := byt mod 16;
  107.             byt := byt div 16;
  108.             HighByte := byt mod 16;
  109.             for i := 1 to 2 do begin
  110.                     if i = 1 then
  111.                         tmp := HighByte
  112.                     else
  113.                         tmp := LowByte;
  114.                     case tmp of
  115.                         0: 
  116.                             h := '0';
  117.                         1: 
  118.                             h := '1';
  119.                         2: 
  120.                             h := '2';
  121.                         3: 
  122.                             h := '3';
  123.                         4: 
  124.                             h := '4';
  125.                         5: 
  126.                             h := '5';
  127.                         6: 
  128.                             h := '6';
  129.                         7: 
  130.                             h := '7';
  131.                         8: 
  132.                             h := '8';
  133.                         9: 
  134.                             h := '9';
  135.                         10: 
  136.                             h := 'a';
  137.                         11: 
  138.                             h := 'b';
  139.                         12: 
  140.                             h := 'c';
  141.                         13: 
  142.                             h := 'd';
  143.                         14: 
  144.                             h := 'e';
  145.                         15: 
  146.                             h := 'f';
  147.                     end;
  148.                     hexbuf[HexCount] := h;
  149.                     HexCount := HexCount + 1;
  150.                     if HexCount mod 80 = 0 then begin
  151.                             HexBuf[HexCount] := cr;
  152.                             HexCount := HexCount + 1
  153.                         end;
  154.                 end;
  155.         end;
  156.  
  157.     begin
  158.         with info^ do begin
  159.                 if not IdentityFunction then
  160.                     GetLookupTable(table);
  161.                 MoveTo(-1, -1);
  162.                 LineTo(-1, -1); {Nothing prints without this dummy dot!}
  163.                 PicComment(PostScriptBegin, 0, nil); {See Tech Note #91}
  164.                 PicComment(TextIsPostScript, 0, nil);
  165.                 NumToString(HalftoneFrequency, freq);
  166.                 NumToString(HalftoneAngle, angle);
  167.                 if HalftoneDotFunction then
  168.                     DrawString(concat(freq, ' ', angle, ' {dup mul exch dup mul add 1 exch sub} setscreen'))
  169.                 else
  170.                     DrawString(concat(freq, ' ', angle, ' {pop} setscreen'));
  171.                 DrawString('0 0 translate');
  172.                 with RoiRect do begin
  173.                         iwidth := right - left;
  174.                         if iwidth > MaxLine then
  175.                             iwidth := MaxLine;
  176.                         iheight := bottom - top;
  177.                         hstart := left;
  178.                         vstart := top;
  179.                     end;
  180.                 NumToString(iwidth, width);
  181.                 NumToString(iheight, height);
  182.                 DrawString(concat(width, ' ', height, ' scale'));
  183.                 DrawString(concat('/PicStr ', width, ' string def'));
  184.                 DrawString(concat(width, ' ', height, ' 8 [', width, ' 0 0 ', height, ' 0 0]'));
  185.                 DrawString('{currentfile PicStr readhexstring pop} image');
  186.                 for vloc := vstart to vstart + iheight - 1 do begin
  187.                         GetLine(hstart, vloc, iwidth, aline);
  188.                         HexCount := 0;
  189.                         for hloc := 0 to iwidth - 1 do
  190.                             PutHex(aline[hloc]);
  191.                         HexBuf[HexCount] := cr;
  192.                         HexCount := HexCount + 1;
  193.                         err := PtrToHand(@HexBuf, HexBufH, HexCount);
  194.                         if err <> noErr then
  195.                             exit(PrintHalftone);
  196.                         PicComment(PostScriptHandle, HexCount, HexBufH);
  197.                         DisposeHandle(HexBufH);
  198.                         Show2Values(vloc - vstart, iheight);
  199.                         if CommandPeriod then begin
  200.                                 beep;
  201.                                 eofStr := chr(4);
  202.                                 DrawString(eofStr);
  203.                                 exit(PrintHalftone)
  204.                             end;
  205.                     end;
  206.             end;
  207.     end;
  208.  
  209.  
  210.     procedure PrintTheImage (PageWidth, PageHeight: integer);
  211.         var
  212.             PrintRect: rect;
  213.             Width, Height: integer;
  214.  
  215.         procedure ScaleToFitPage;
  216.             var
  217.                 hscale, vscale, scale: extended;
  218.         begin
  219.             hscale := PageWidth / width;
  220.             vscale := PageHeight / height;
  221.             if hscale <= vscale then
  222.                 scale := hscale
  223.             else
  224.                 scale := vscale;
  225.             width := trunc(scale * width);
  226.             height := trunc(scale * height);
  227.         end;
  228.  
  229.         procedure CenterOnPage;
  230.         begin
  231.             with PrintRect do begin
  232.                     left := 0;
  233.                     top := 0;
  234.                     if width < PageWidth then
  235.                         left := (PageWidth - width) div 2;
  236.                     if height < PageHeight then
  237.                         top := (Pageheight - height) div 2;
  238.                     right := left + width;
  239.                     bottom := top + height;
  240.                 end;
  241.         end;
  242.  
  243.     begin
  244.         if isLaserWriter and (not DriverHalftoning) then
  245.             PrintHalftone
  246.         else
  247.             with info^ do begin
  248.                     LoadLUT(cTable);
  249.                     hlock(handle(osPort^.portPixMap));
  250.                     with RoiRect do begin
  251.                             width := right - left;
  252.                             height := bottom - top;
  253.                         end;
  254.                     if (width > PageWidth) or (height > PageHeight) then
  255.                         ScaleToFitPage;
  256.                     CenterOnPage;
  257.                     if BitAnd(qd.thePort^.portBits.rowBytes, $8000) = $8000 then begin
  258.                {Assume driver understands Color QD}
  259.                             CopyBits(BitMapHandle(osPort^.portPixMap)^^, BitMapHandle(CGrafPtr(qd.thePort)^.PortPixMap)^^, RoiRect, PrintRect, SrcCopy, nil);
  260.                         end
  261.                     else
  262.                         CopyBits(BitMapHandle(osPort^.portPixMap)^^, qd.thePort^.PortBits, RoiRect, PrintRect, SrcCopy, nil);
  263.                 end;
  264.     end;
  265.  
  266.  
  267.     procedure PrintTextBuffer (PageHeight: integer; var PrintPort: TPPrPort);
  268.         const
  269.             LineInc = 13;
  270.         var
  271.             vloc, i, LineCount, CharCount, LinesPerPage, MaxCount: integer;
  272.             aLine: str255;
  273.     begin
  274.         ClipTextInBuffer := false;
  275.         LinesPerPage := PageHeight div LineInc;
  276.         vloc := LineInc;
  277.         LineCount := 0;
  278.         CharCount := 0;
  279.         TextFont(Monaco);
  280.         TextSize(9);
  281.         if WhatToPrint = PrintText then
  282.             MaxCount := 85
  283.         else
  284.             MaxCount := 255;
  285.         i := 1;
  286.         repeat
  287.             CharCount := 0;
  288.             while (TextBufP^[i] <> cr) and (CharCount < MaxCount) and (i <= TextBufSize) do begin
  289.                     CharCount := CharCount + 1;
  290.                     aLine[CharCount] := TextBufP^[i];
  291.                     i := i + 1;
  292.                 end;
  293.             if TextBufP^[i] = cr then
  294.                 i := i + 1
  295.             else if CharCount = MaxCount then begin
  296.                     while (aLine[CharCount] <> ' ') and (CharCount > (MaxCount - 15)) do begin
  297.                             CharCount := CharCount - 1;
  298.                             i := i - 1;
  299.                         end;
  300.                     if TextBufP^[i] = ' ' then
  301.                         i := i + 1;
  302.                 end;
  303.             aLine[0] := chr(CharCount);
  304.             MoveTo(0, vloc);
  305.             DrawString(aLine);
  306.             vLoc := vLoc + LineInc;
  307.             LineCount := LineCount + 1;
  308.             if LineCount >= LinesPerPage then begin
  309.                     LineCount := 0;
  310.                     if i < TextBufSize then begin
  311.                             PrClosePage(PrintPort);
  312.                             PrintErrCheck;
  313.                             PrOpenPage(PrintPort, nil);
  314.                             vloc := LineInc
  315.                         end;
  316.                 end;
  317.         until i > TextBufSize;
  318.     end;
  319.  
  320.  
  321.     procedure DoPrintText (PageHeight: integer; var PrintPort: TPPrPort);
  322.         var
  323.             ByteCount: LongInt;
  324.     begin
  325.         if TextInfo <> nil then
  326.             with TextInfo^.TextTE^^ do begin
  327.                     ByteCount := TELength;
  328.                     BlockMove(hText^, ptr(TextBufP), ByteCount);
  329.                     TextBufSize := ByteCount;
  330.                     PrintTextBuffer(PageHeight, PrintPort);
  331.                 end;
  332.     end;
  333.  
  334.  
  335.     procedure Print (ShowDialog: boolean);
  336.         var
  337.             err, i, LinesToPrint: Integer;
  338.             tPort: GrafPtr;
  339.             PrintPort: TPPrPort;
  340.             PrintStatusRec: TPrStatus;
  341.             prect: rect;
  342.             result: boolean;
  343.     begin
  344.         if WhatToPrint = PrintImage then
  345.             SelectAll(false);
  346.         if (WhatToPrint = PrintImage) or (WhatToPrint = PrintSelection) then begin
  347.                 if OpPending then
  348.                     KillRoi;
  349.                 with info^.RoiRect do
  350.                     LinesToPrint := bottom - top;
  351.                 if not DriverHalftoning then begin
  352.                         DrawLabels('Line:', 'Total:', '');
  353.                         Show2Values(0, LinesToPrint);
  354.                     end;
  355.             end;
  356.         GetPort(tPort);
  357.         PrOpen;
  358.         if PrintRecord = nil then begin
  359.                 PrintRecord := THPrint(NewHandle(SizeOF(TPrint)));
  360.                 PrintDefault(PrintRecord);
  361.             end;
  362.         if PrError = NoErr then begin
  363.                 InitCursor;
  364.                 result := PrValidate(PrintRecord);
  365.                 isLaserWriter := BSR(PrintRecord^^.prStl.wDev, 8) = 3;
  366.                 prect := PrintRecord^^.prInfo.rPage;
  367.                 if ShowDialog then
  368.                     result := PrJobDialog(PrintRecord)
  369.                 else
  370.                     result := true;
  371.                 if not DriverHalftoning then
  372.                     ShowMessage(CmdPeriodToStop);
  373.                 ShowWatch;
  374.                 if result then
  375.                     for i := 1 to PrintRecord^^.PrJob.icopies do begin
  376.                             PrintPort := PrOpenDoc(PrintRecord, nil, nil);
  377.                             PrintErrCheck;
  378.                             Printing := true;
  379.                             PrOpenPage(PrintPort, nil);
  380.                             if PrError = NoErr then
  381.                                 case WhatToPrint of
  382.                                     PrintImage, PrintSelection: 
  383.                                         PrintTheImage(prect.right, prect.bottom);
  384.                                     PrintMeasurements:  begin
  385.                                             CopyResultsToBuffer(1, mCount, true);
  386.                                             PrintTextBuffer(prect.Bottom, PrintPort);
  387.                                             UnsavedResults := false;
  388.                                         end;
  389.                                     PrintPlot: 
  390.                                         DrawPlot;
  391.                                     PrintHistogram: 
  392.                                         DrawHistogram;
  393.                                     PrintText: 
  394.                                         DoPrintText(prect.Bottom, PrintPort);
  395.                                 end;
  396.                             Printing := false;
  397.                             PrClosePage(PrintPort);
  398.                             PrintErrCheck;
  399.                             PrCloseDoc(PrintPort);
  400.                             PrintErrCheck;
  401.                             if PrintRecord^^.prJob.bJDocLoop = bSpoolLoop then
  402.                                 PrPicFile(PrintRecord, nil, nil, nil, PrintStatusRec);
  403.                         end;
  404.             end;
  405.         PrClose;
  406.         SetPort(tPort);
  407.         if WhatToPrint = PrintImage then
  408.             KillRoi;
  409.         ShowMessage(' ');
  410.     end;
  411.  
  412.  
  413.     procedure SetHalftone;
  414.         const
  415.             FrequencyID = 8;
  416.             AngleID = 10;
  417.             DotID = 4;
  418.             LineID = 5;
  419.             CustomID = 13;
  420.         var
  421.             mylog: DialogPtr;
  422.             item, i, ignore, SaveFrequency, SaveAngle: integer;
  423.             SaveFunction, SaveCustom: boolean;
  424.             str: str255;
  425.     begin
  426.         SaveFrequency := HalftoneFrequency;
  427.         SaveAngle := HalftoneAngle;
  428.         SaveFunction := HalftoneDotFunction;
  429.         SaveCustom := DriverHalftoning;
  430.         mylog := GetNewDialog(30, nil, pointer(-1));
  431.         SetDNum(MyLog, FrequencyID, HalftoneFrequency);
  432.         SelectdialogItemText(MyLog, FrequencyID, 0, 32767);
  433.         SetDNum(MyLog, AngleID, HalftoneAngle);
  434.         SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  435.         OutlineButton(MyLog, ok, 16);
  436.         if HalftoneDotFunction then
  437.             SetDlogItem(mylog, DotID, 1)
  438.         else
  439.             SetDlogItem(mylog, LineID, 1);
  440.         repeat
  441.             ModalDialog(nil, item);
  442.             if item = FrequencyID then begin
  443.                     HalftoneFrequency := GetDNum(MyLog, FrequencyID);
  444.                     DriverHalftoning := false;
  445.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  446.                 end;
  447.             if item = AngleID then begin
  448.                     HalftoneAngle := GetDNum(MyLog, AngleID);
  449.                     if (HalftoneAngle < 0) or (HalftoneAngle > 180) then begin
  450.                             beep;
  451.                             HalftoneAngle := SaveAngle;
  452.                         end;
  453.                     DriverHalftoning := false;
  454.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  455.                 end;
  456.             if (item >= DotID) and (item <= LineID) then begin
  457.                     for i := DotID to LineID do
  458.                         SetDlogItem(mylog, i, 0);
  459.                     SetDlogItem(mylog, item, 1);
  460.                     HalftoneDotFunction := item = DotID;
  461.                     DriverHalftoning := false;
  462.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  463.                 end;
  464.             if item = CustomID then begin
  465.                     DriverHalftoning := not DriverHalftoning;
  466.                     SetDlogItem(mylog, CustomID, ord(not DriverHalftoning));
  467.                 end;
  468.         until (item = ok) or (item = cancel);
  469.         DisposeDialog(mylog);
  470.         if item = cancel then begin
  471.                 HalftoneFrequency := SaveFrequency;
  472.                 HalftoneAngle := SaveAngle;
  473.                 HalftoneDotFunction := SaveFunction;
  474.                 DriverHalftoning := SaveCustom;
  475.             end;
  476.     end;
  477.  
  478.  
  479. {$POP}
  480.  
  481.     procedure GetFileInfo (name: str255; vnum: integer; var DateCreated, LastModified: str255);
  482.         var
  483.             FileParmBlock: CInfoPBRec;
  484.             theErr: OSErr;
  485.             DateVar, TimeVar: str255;
  486.             Secs: LongInt;
  487.     begin
  488.         DateCreated := '';
  489.             with FileParmBlock do begin
  490.                     ioCompletion := nil;
  491.                     ioNamePtr := @name;
  492.                     ioVRefNum := vnum;
  493.                     ioFVersNum := 0;
  494.                     ioFDirIndex := 0;
  495.                     theErr := PBGetCatInfoSync(@FileParmBlock); {ppc-bug}
  496.                     if theErr = NoErr then begin
  497.                             Secs := ioFlCrDat;
  498.                             IUDateString(Secs, abbrevDate, DateVar);
  499.                             IUTimeString(Secs, true, TimeVar);
  500.                             DateCreated := concat(DateVar, '  ', TimeVar);
  501.                             Secs := ioFlMDDat;
  502.                             IUDateString(Secs, abbrevDate, DateVar);
  503.                             IUTimeString(Secs, true, TimeVar);
  504.                             LastModified := concat(DateVar, '  ', TimeVar);
  505.                         end;
  506.                 end;
  507.     end;
  508.  
  509.  
  510.     procedure GetVolumnInfo (vnum: integer; var VolumnName: str255; var FreeSpace: LongInt);
  511.         var
  512.             theErr: OSErr;
  513.             str: str255;
  514.             VolParmBlock: ParamBlockRec;
  515.     begin
  516.         VolumnName := '';
  517.             with VolParmBlock do begin
  518.                     str := '';
  519.                     ioVRefNum := vnum;
  520.                     ioNamePtr := @str;
  521.                     ioCompletion := nil;
  522.                     ioVolIndex := -1;
  523.                     theErr := PBGetVInfoSync(@VolParmBlock); {ppc-bug}
  524.                     VolumnName := ioNamePtr^;
  525.                     FreeSpace := ioVAlBlkSiz * ioVFrBlk;
  526.                 end;
  527.     end;
  528.  
  529.  
  530.     function RoomForFile (fname: str255; RefNum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  531.         var
  532.             err: OSErr;
  533.             f: integer;
  534.             VolumnName: str255;
  535.             FreeSpace, ExistingFileSize, NeededSize: LongInt;
  536.     begin
  537.         with info^ do begin
  538.                 ExistingFileSize := 0;
  539.                 RoomForFile := true;
  540.                 err := fsopen(fname, RefNum, f);
  541.                 if err = 0 then begin
  542.                         err := GetEOF(f, ExistingFileSize);
  543.                         err := fsClose(f);
  544.                     end;
  545.                 if ExistingFileSize <> 0 then begin
  546.                         if SavingSelection then begin
  547.                                 NeededSize := sLines;
  548.                                 NeededSize := NeededSize * sPixelsPerLine
  549.                             end
  550.                         else
  551.                             NeededSize := ImageSize;
  552.                         if StackInfo <> nil then
  553.                             with StackInfo^ do
  554.                                 NeededSize := NeededSize * nSlices + nSlices * SizeOf(StackIFDType);
  555.                         GetVolumnInfo(RefNum, VolumnName, FreeSpace);
  556.                         if (NeededSize - ExistingFileSize + 8192) > FreeSpace then begin
  557.                                 PutError('There is not enough free space on this disk to save this image.');
  558.                                 RoomForFile := false;
  559.                             end;
  560.                     end;
  561.             end;
  562.     end;
  563.  
  564.  
  565.     procedure GetInfo;
  566.         var
  567.             name, str, DateCreated, LastModified, VolumnName, str2: str255;
  568.             hloc, vloc, InfoWidth, InfoHeight: integer;
  569.             SaveRoiShowing: boolean;
  570.             FreeSpace, DataSize: LongInt;
  571.             SaveForeIndex, SaveBackIndex: integer;
  572.             ImageInfo, InfoWindowInfo: InfoPtr;
  573.             x1, y1, x2, y2, ulength, clength: extended;
  574.             SaveGDevice: GDHandle;
  575.  
  576.         procedure NewLine;
  577.         begin
  578.             vloc := vloc + 13;
  579.             MoveTo(hloc, vloc);
  580.         end;
  581.  
  582.         procedure NewParagraph;
  583.         begin
  584.             vloc := vloc + 18;
  585.             MoveTo(hloc, vloc);
  586.         end;
  587.  
  588.     begin
  589.         InfoWidth := 260;
  590.         InfoHeight := 260;
  591.         with info^ do begin
  592.                 if RoiShowing then
  593.                     InfoHeight := InfoHeight + 50;
  594.                 if RoiShowing and (RoiType = LineRoi) then
  595.                     InfoHeight := InfoHeight + 20;
  596.                 if vref <> 0 then
  597.                     InfoHeight := InfoHeight + 60;
  598.                 name := concat('Info About ', title);
  599.                 SaveRoiShowing := RoiShowing;
  600.             end;
  601.         SaveForeIndex := ForegroundIndex;
  602.         SaveBackIndex := BackgroundIndex;
  603.         SetForegroundColor(BlackIndex);
  604.         SetBackgroundColor(WhiteIndex);
  605.         ImageInfo := info;
  606.         if NewPicWindow(name, InfoWidth, InfoHeight) then
  607.             with ImageInfo^ do begin
  608.                     InfoWindowInfo := Info;
  609.                     SaveGDevice := GetGDevice;
  610.                     SetGDevice(osGDevice);
  611.                     SetPort(GrafPtr(info^.osPort));
  612.                     TextFont(Geneva);
  613.                     TextSize(9);
  614.                     hloc := 15;
  615.                     vloc := 10;
  616.                     NewLine;
  617.                     DrawBString('Name: ');
  618.                     DrawString(title);
  619.                     NewParagraph;
  620.                     DrawBString('Width: ');
  621.                     DrawXDimension(PixelsPerLine, 0);
  622.                     NewLine;
  623.                     DrawBString('Height: ');
  624.                     DrawYDimension(nlines, 0);
  625.                     if StackInfo <> nil then begin
  626.                             NewLine;
  627.                             DrawBString('Depth: ');
  628.                             DrawLong(StackInfo^.nSlices);
  629.                         end;
  630.                     NewLine;
  631.                     DrawBString('Size: ');
  632.                     if StackInfo <> nil then
  633.                         DataSize := PixMapSize * StackInfo^.nSlices
  634.                     else if DataH <> nil then
  635.                         DataSize := PixMapSize + PixMapSize * SizeOf(real)
  636.                     else
  637.                         DataSize := PixMapSize;
  638.                     DrawLong((DataSize + 511) div 1024);
  639.                     DrawString('K');
  640.                     NewParagraph;
  641.                     GetFileInfo(title, vref, DateCreated, LastModified); {DateCreated:='';}
  642.                     if DateCreated <> '' then begin
  643.                             DrawBString('Creation Date: ');
  644.                             DrawString(DateCreated);
  645.                             NewLine;
  646.                             DrawBString('Last Modified: ');
  647.                             DrawString(LastModified);
  648.                             NewLine;
  649.                         end;
  650.                     if fileVersion > 0 then begin
  651.                             DrawBString('Version: ');
  652.                             DrawString('Created by NIH Image ');
  653.                             DrawReal(fileVersion / 100.0, 1, 2);
  654.                             NewParagraph;
  655.                         end;
  656.                     DrawBString('Type: ');
  657.                     if StackInfo <> nil then case StackInfo^.StackType of
  658.                         VolumeStack, MovieStack:
  659.                             str := concat('Stack (', long2str(StackInfo^.nSlices), '  slices)');
  660.                         rgbStack:
  661.                             str := 'RGB color stack';
  662.                         else
  663.                         ;
  664.                     end else begin
  665.                             case PictureType of
  666.                                 NewPicture: 
  667.                                     str := 'New';
  668.                                 Normal: 
  669.                                     str := 'Normal';
  670.                                 PictFile: 
  671.                                     str := 'PICT';
  672.                                 TiffFile: 
  673.                                     str := 'TIFF';
  674.                                 Leftover: 
  675.                                     str := 'Left Over';
  676.                                 Imported:  begin
  677.                                         if DataType = EightBits then
  678.                                             str := 'Imported 8-bit image'
  679.                                         else
  680.                                             str := 'Imported 16-bit image';
  681.                                     end;
  682.                                 FrameGrabberType: 
  683.                                     str := 'Camera';
  684.                                 BlankField: 
  685.                                     str := 'Blank Field';
  686.                                 otherwise
  687.                                     ;
  688.                             end;
  689.                             if BinaryPic then
  690.                                 str := concat(str, ' (Binary)');
  691.                         end;
  692.                     DrawString(str);
  693.                     if StackInfo <> nil then
  694.                         with StackInfo^ do
  695.                             if SliceSpacing <> 0.0 then begin
  696.                                     NewLine;
  697.                                     DrawBString('Slice Spacing: ');
  698.                                     if SpatiallyCalibrated then
  699.                                         DrawString(StringOf(SliceSpacing / xScale:1:2, ' ', xunit, ' (', SliceSpacing:1:2, ' pixels)'))
  700.                                     else
  701.                                         DrawString(StringOf(SliceSpacing:1:2, ' pixels'));
  702.                                 end;
  703.                     NewLine;
  704.                     DrawBString('Lookup Table: ');
  705.                     case LutMode of
  706.                         PseudoColor: 
  707.                             str := concat('Pseudocolor (', long2str(ncolors), ', ', long2str(ColorStart), '-', long2str(ColorEnd), ')');
  708.                         GrayScale: 
  709.                             str := concat('Grayscale (', long2str(ncolors), ', ', long2str(ColorStart), '-', long2str(ColorEnd), ')');
  710.                         ColorLut: 
  711.                             str := 'Color';
  712.                         CustomGrayscale: 
  713.                             str := 'Custom Grayscale';
  714.                         otherwise
  715.                     end;
  716.                     DrawString(str);
  717.                     NewLine;
  718.                     DrawBString('Magnification: ');
  719.                     if ScaleToFitWindow then begin
  720.                             DrawReal(magnification, 1, 2);
  721.                             DrawString(' (Scale to Window Mode)')
  722.                         end
  723.                     else begin
  724.                             DrawReal(magnification, 1, 0);
  725.                             DrawString(':1')
  726.                         end;
  727.                     NewLine;
  728.                     DrawBString('Scale: ');
  729.                     if SpatiallyCalibrated then begin
  730.                             DrawReal(xScale, 1, 3);
  731.                             DrawString(' pixels per ');
  732.                             DrawString(xUnit);
  733.                             if PixelAspectRatio <> 1.0 then begin
  734.                                     NewLine;
  735.                                     DrawBString('Pixel Aspect Ratio: ');
  736.                                     DrawReal(PixelAspectRatio, 1, 4);
  737.                                 end;
  738.                         end
  739.                     else
  740.                         DrawString('None');
  741.                     if fit <> uncalibrated then begin
  742.                             NewLine;
  743.                             DrawBString('Unit of Measure: ');
  744.                             if UnitOfMEasure = '' then
  745.                                 DrawString('None')
  746.                             else
  747.                                 DrawString(UnitOfMeasure)
  748.                         end;
  749.                     NewParagraph;
  750.                     DrawBString('Free RAM: ');
  751.                     DrawLong(FreeMem div 1024);
  752.                     DrawString('K');
  753.                     NewLine;
  754.                     DrawBString('Largest Free Block: ');
  755.                     DrawLong(MaxBlock div 1024);
  756.                     DrawString('K');
  757.                     if FrameGrabber <> NoFrameGrabber then begin
  758.                             NewLine;
  759.                             DrawBString('Frame Grabber: ');
  760.                             case FrameGrabber of
  761.                                 QuickCapture:  begin
  762.                                         if fgWidth = 768 then
  763.                                             DrawString('50Hz')
  764.                                         else
  765.                                             DrawString('60Hz');
  766.                                         DrawString(' Data Translation QuickCapture');
  767.                                     end;
  768.                                 ScionLG3:  begin
  769.                                         if fgWidth = 768 then
  770.                                             DrawString('50Hz')
  771.                                         else
  772.                                             DrawString('60Hz');
  773.                                         DrawString(' Scion LG-3 (');
  774.                                         DrawLong(MaxLG3Frames div 2);
  775.                                         DrawString(' MB)');
  776.                                     end;
  777.                                 ScionAG5:  begin
  778.                                     if fgWidth = 768 then
  779.                                         DrawString('50Hz')
  780.                                     else
  781.                                         DrawString('60Hz');
  782.                                     DrawString(' Scion AG-5');
  783.                                 end;
  784.                                 ScionVG5f:  begin
  785.                                     if fgWidth = 768 then
  786.                                         DrawString('50Hz')
  787.                                     else
  788.                                         DrawString('60Hz');
  789.                                     DrawString(' Scion VG-5');
  790.                                 end
  791.                                 QTvdig:
  792.                                     DrawString('QuickTime Video Digitizer');
  793.                             end;
  794.                         end;
  795.                     NewParagraph;
  796.                     if RoiType <> NoRoi then begin
  797.                             DrawBString('Selection Type: ');
  798.                             case RoiType of
  799.                                 PolygonRoi: 
  800.                                     DrawString('Polygon');
  801.                                 FreehandRoi: 
  802.                                     DrawString('Freehand');
  803.                                 RectRoi: 
  804.                                     DrawString('Rectangle');
  805.                                 OvalRoi: 
  806.                                     DrawString('Oval');
  807.                                 LineRoi: 
  808.                                     DrawString('Straight Line');
  809.                                 FreeLineOF(f, srcSize);
  810.         srcSize := srcSize - 512;
  811.         srcPtr := NewPtr(srcSize);
  812.         if srcPtr = nil then begin
  813.             abort;
  814.             exit(OpenMacPaint);
  815.         end;
  816.         err := SetFPos(f, fsFromStart, 512);
  817.         err := fsRead(f, srcSize, srcPtr);
  818.         if CheckIO(err) <> noErr then
  819.             exit(OpenMacPaint);
  820.         err := fsClose(f);
  821.         dstPtr := NewPtrClear(MaxUnPackedSize);
  822.         if dstPtr = nil then begin
  823.             abort;
  824.             exit(OpenMacPaint);
  825.         end;
  826.         src := srcPtr;
  827.         dst := dstPtr;
  828.         for scanLine := 1 to 720 do
  829.             UnPackBits(src, dst, 72); {bumps both ptrs}
  830.         DisposePtr(srcPtr);
  831.         mpArray := mpArrayP(dstPtr);
  832.         LastLine := 720;
  833.         BlankLine := true;
  834.         repeat
  835.             for i := 1 to 18 do
  836.                 blankLine := BlankLine and (mpArray^[LastLine, i] = 0);
  837.             if BlankLine then
  838.                 LastLine := LastLine - 1;
  839.         until (not BlankLine) or (LastLine = 1);
  840.         LastWord := 18;
  841.         BlankColumn := true;
  842.         repeat
  843.             for i := 1 to LastLine do
  844.                 blankColumn := BlankColumn and (mpArray^[i, LastWord] = 0);
  845.             if BlankColumn then
  846.                 LastWord := LastWord - 1;
  847.         until (not BlankColumn) or (LastWord = 1);
  848.         LastColumn := LastWord * 32;
  849.         LastColumn := LastColumn + 8;
  850.         if LastColumn > 576 then
  851.             LastColumn := 576;
  852.         LastLine := LastLine + 8;
  853.         if LastLine > 720 then
  854.             LastLine := 720;
  855.         SetRect(frect, 0, 0, LastColumn, LastLine);
  856.         with theBitMap do begin
  857.                 baseAddr := dstPtr;
  858.                 rowBytes := 72;
  859.                 bounds := frect;
  860.             end;
  861.         if not NewPicWindow(fname, LastColumn, LastLine) then begin
  862.             abort;
  863.             exit(OpenMacPaint);
  864.         end;
  865.         SaveGDevice := GetGDevice;
  866.         SetGDevice(osGDevice);
  867.         SetForegroundColor(BlackIndex);
  868.         SetBackgroundColor(WhiteIndex);
  869.         with info^ do begin
  870.                 CopyBits(theBitMap, BitMapHandle(osPort^.PortPixMap)^^, frect, frect, SrcCopy, nil);
  871.                 DisposePtr(dstPtr);
  872.                 PictureType := imported;
  873.                 BinaryPic := true;
  874.                 SetGDevice(SaveGDevice);
  875.                 if PixMapSize > UndoBufSize then
  876.                     PutWarning;
  877.             end;
  878.         OpenMacPaint := true;
  879.     end;
  880.  
  881.  
  882.     procedure TypeMismatch (fname: str255);
  883.     begin
  884.         PutError(concat('The file "', fname, '" is a different type, and therefore cannot be replaced'));
  885.     end;
  886.  
  887.  
  888.     procedure SaveAsMacPaint (fname: str255; RefNum: integer);
  889.         const
  890.             MaxFileSize = 53072;   { maximum MacPaint file size. }
  891.         var
  892.             TheInfo: FInfo;
  893.             dstPtr, srcPtr, mpBufPtr: Ptr;
  894.             i, f, scanLine, err, width, height: integer;
  895.             dstBuffer: array[1..128] of LongInt;
  896.             size, dstSize: LongInt;
  897.             theBitMap: BitMap;
  898.             mprect, srect, drect: rect;
  899.  
  900.         procedure abort;
  901.         begin
  902.             beep;
  903.             if mpBufPtr <> nil then
  904.                 DisposePtr(mpBufPtr);
  905.             if f <> -1 then
  906.                 err := fsclose(f);
  907.             {exit(SaveAsMacPaint);} {ppc-bug}
  908.         end;
  909.  
  910.     begin
  911.         f := -1;
  912.         err := GetFInfo(fname, RefNum, TheInfo);
  913.         case err of
  914.             NoErr: 
  915.                 with TheInfo do begin
  916.                         if fdType <> 'PNTG' then begin
  917.                                 TypeMismatch(fname);
  918.                                 exit(SaveAsMacPaint)
  919.                             end;
  920.                     end;
  921.             FNFerr:  begin
  922.                     err := create(fname, RefNum, 'MPNT', 'PNTG');
  923.                     if CheckIO(err) <> 0 then
  924.                         exit(SaveAsMacPaint);
  925.                 end;
  926.             otherwise
  927.                 if CheckIO(err) <> 0 then
  928.                     exit(SaveAsMacPaint);
  929.         end;
  930.         mpBufPtr := NewPtrClear(MaxFileSize);
  931.         if mpBufPtr = nil then begin
  932.             abort;
  933.             exit(SaveAsMacPaint);
  934.         end;
  935.         ShowWatch;
  936.         SetRect(mprect, 0, 0, 576, 720);
  937.         with theBitMap do begin
  938.                 baseAddr := mpBufPtr;
  939.                 rowBytes := 72;
  940.                 bounds := mprect;
  941.             end;
  942.         with info^ do begin
  943.                 if roiShowing then
  944.                     srect := RoiRect
  945.                 else
  946.                     srect := PicRect;
  947.                 with srect do begin
  948.                         width := right - left;
  949.                         height := bottom - top;
  950.                         if width > 576 then
  951.                             width := 576;
  952.                         if height > 720 then
  953.                             height := 720;
  954.                         right := left + width;
  955.                         bottom := top + height;
  956.                     end;
  957.                 SetRect(drect, 0, 0, width, height);
  958.                 CopyBits(BitMapHandle(osPort^.PortPixMap)^^, theBitMap, srect, drect, srcCopy, nil);
  959.             end;
  960.         err := fsOpen(fname, RefNum, f);
  961.         if CheckIO(err) <> noErr then begin
  962.             abort;
  963.             exit(SaveAsMacPaint);
  964.         end;
  965.         for I := 1 to 128 do
  966.             dstBuffer[I] := 0;
  967.         Size := 512;
  968.         err := FSWrite(f, Size, @dstBuffer);
  969.         if CheckIO(err) <> noErr then begin
  970.             abort;
  971.             exit(SaveAsMacPaint);
  972.         end;
  973.         srcPtr := theBitMap.baseAddr;
  974.         for scanLine := 1 to 720 do begin
  975.                 dstPtr := @dstBuffer; { reset the pointer to bottom }
  976.                 PackBits(srcPtr, dstPtr, 72); { bumps both ptrs}
  977.                 dstSize := ord(dstPtr) - ord(@dstBuffer);{calc packed size}
  978.                 err := fsWrite(f, dstSize, @dstBuffer);
  979.                 if CheckIO(err) <> noErr then begin
  980.                     abort;
  981.                     exit(SaveAsMacPaint);
  982.                 end;
  983.             end;
  984.         err := fsclose(f);
  985.         DisposePtr(mpBufPtr);
  986.         if not info^.RoiShowing then
  987.             info^.changes := false;
  988.     end;
  989.  
  990.  
  991.     function GetTextFile (var name: str255; var RefNum: integer): boolean;
  992.         var
  993.             where: Point;
  994.             typeList: SFTypeList;
  995.             reply: SFReply;
  996.             err: OSErr;
  997.             pBlock: WDPBRec;
  998.     begin
  999.         where.v := 120;
  1000.         where.h := 120;
  1001.         typeList[0] := 'TEXT';
  1002.         SFGetFile(Where, '', nil, 1, @typeList, nil, reply);
  1003.         if reply.good then
  1004.             with reply do begin
  1005.                     name := fname;
  1006.                     RefNum := vRefNum;
  1007.                     GetTextFile := true;
  1008.                 end
  1009.         else
  1010.             GetTextFile := false;
  1011.     end;
  1012.  
  1013.  
  1014.     procedure GetBuffer;
  1015.         var
  1016.             err: OSErr;
  1017.             count, FilePos: LongInt;
  1018.     begin
  1019.         count := MaxTextBufSize;
  1020.         err := fsread(Textf, count, ptr(TextBufP));
  1021.         TextBufSize := count;
  1022.         err := GetFPos(Textf, FilePos);
  1023.         if FilePos = TextFileSize then begin
  1024.                 TextBufSize := TextBufSize + 1;
  1025.                 if TextBufSize > MaxTextBufSize then
  1026.                     TextBufSize := MaxTextBufSize;
  1027.                 TextBufP^[TextBufSize] := eofChr;
  1028.                 err := fsclose(Textf);
  1029.             end;
  1030.         TextIndex := 1;
  1031.     end;
  1032.  
  1033.  
  1034.     function GetByte: char;
  1035.     begin
  1036.         GetByte := TextBufP^[TextIndex];
  1037.         TextIndex := TextIndex + 1;
  1038.         if TextIndex > MaxTextBufSize then
  1039.             GetBuffer;
  1040.     end;
  1041.  
  1042.  
  1043.     function GetNumber: extended;
  1044.         var
  1045.             c: char;
  1046.             str: str255;
  1047.     begin
  1048.         repeat
  1049.             c := GetByte;
  1050.             if c = tab then begin
  1051.                     GetNumber := 0.0; {Assume 0 zero for missing value.}
  1052.                     exit(GetNumber);
  1053.                 end;
  1054.             if (c = cr) or (c = eofChr) then begin
  1055.                     TextEol := true;
  1056.                     TextEof := c = eofChr;
  1057.                     GetNumber := NoValue;
  1058.                     exit(GetNumber);
  1059.                 end;
  1060.         until c in ['0'..'9', '-', '.'];
  1061.         Str := '';
  1062.         while c in ['0'..'9', '+', '-', '.', 'e', 'E'] do begin
  1063.                 Str := concat(str, c);
  1064.                 c := GetByte;
  1065.                 if (c = cr) or (c = eofChr) then begin
  1066.                         TextEol := true;
  1067.                         TextEof := c = eofChr;
  1068.                     end;
  1069.             end;
  1070.         GetNumber := StringToReal(str);
  1071.     end;
  1072.  
  1073.  
  1074.     procedure GetLineFromText (var rLine: RealLine; var count: integer);
  1075.         var
  1076.             n: extended;
  1077.     begin
  1078.         count := 0;
  1079.         if TextEof then
  1080.             exit(GetLineFromText);
  1081.         repeat
  1082.             n := GetNumber;
  1083.             if n <> NoValue then begin
  1084.                     count := count + 1;
  1085.                     rLine[count] := n;
  1086.                 end;
  1087.         until TextEol or (count = MaxLine);
  1088.         TextEol := false;
  1089.     end;
  1090.  
  1091.  
  1092.     procedure InitTextInput (name: str255; RefNum: integer);
  1093.         var
  1094.             err: OSErr;
  1095.     begin
  1096.         err := FSOpen(name, RefNum, Textf);
  1097.         err := GetEof(Textf, TextFileSize);
  1098.         err := SetFPos(Textf, fsFromStart, 0);
  1099.         ShowWatch;
  1100.         if WhatsOnClip = TextOnClip then
  1101.             WhatsOnClip := NothingOnClip;
  1102.         GetBuffer;
  1103.         TextEol := false;
  1104.         TextEof := false;
  1105.     end;
  1106.  
  1107.  
  1108.     function ImportTextFile (name: str255; RefNum: integer): boolean;
  1109.         var
  1110.             nRows, nColumns, count, i, vloc, BlankPixel, nPixelsPerLine: integer;
  1111.             rLine: RealLine;
  1112.             pvalue: extended;
  1113.             min, max, ScaleFactor, DefaultValue, tvalue: extended;
  1114.             err: OSErr;
  1115.             line, BlankLine: LineType;
  1116.             TheInfo: FInfo;
  1117.             noScaling:boolean;
  1118.     begin
  1119.         ImportTextFile := false;
  1120.         err := GetFInfo(name, RefNum, TheInfo);
  1121.         if TheInfo.fdType <> 'TEXT' then begin
  1122.                 PutError('File is not of type ''TEXT''.');
  1123.                 exit(ImportTextFile);
  1124.             end;
  1125.         InitTextInput(name, RefNum);
  1126.         nRows := 0;
  1127.         nColumns := 0;
  1128.         max := -10e-10;
  1129.         min := 10e10;
  1130.         ShowMessage(concat('First pass used to find ', crStr, 'width, height,min, and max.', crStr, crStr, CmdPeriodToStop));
  1131.         DrawLabels('Line:', '', '');
  1132.         while not TextEof do begin
  1133.                 GetLineFromText(rLine, count);
  1134.                 if not (TextEof and (count = 0)) then
  1135.                     nRows := nRows + 1;
  1136.                 if count > nColumns then
  1137.                     nColumns := count;
  1138.                 for i := 1 to count do begin
  1139.                         pvalue := rLine[i];
  1140.                         if pvalue > max then
  1141.                             max := pvalue;
  1142.                         if pvalue < min then
  1143.                             min := pvalue;
  1144.                     end;
  1145.                 if nRows mod 10 = 0 then begin
  1146.                         Show1Value(nRows, NoValue);
  1147.                         ShowAnimatedWatch;
  1148.                         if CommandPeriod then begin
  1149.                                 beep;
  1150.                                 err := fsclose(Textf);
  1151.                                 Exit(ImportTextFile);
  1152.                             end;
  1153.                     end;
  1154.             end;
  1155.         ShowMessage(concat('rows= ', long2str(nRows), crStr, 'columns= ', long2str(ncolumns), crStr, 'min= ', long2str(round(min)), crStr, 'max= ', long2str(round(max))));
  1156.         if nColumns > MaxLine then begin
  1157.                 PutError(concat('More than ',long2str(MaxLine),' pixels per line.'));
  1158.                 Exit(ImportTextFile);
  1159.             end;
  1160.         nPixelsPerLine := nColumns;
  1161.         if NewPicWindow(name, nPixelsPerLine, nrows) then
  1162.             with info^ do begin
  1163.                     if (not ImportAutoScale) and (max > min) then begin
  1164.                             min := ImportMin;
  1165.                             max := ImportMax;
  1166.                         end;
  1167.                     ScaleFactor := 253.0 / (max - min);
  1168.                     InitTextInput(name, RefNum);
  1169.                     vloc := 0;
  1170.                     DefaultValue := 0.0;
  1171.                     if DefaultValue < min then
  1172.                         DefaultValue := min;
  1173.                     if DefaultValue > max then
  1174.                         DefaultValue := max;
  1175.                     BlankPixel := round((DefaultValue - min) * ScaleFactor + 1);
  1176.                     for i := 0 to nColumns - 1 do
  1177.                         BlankLine[i] := BlankPixel;
  1178.                     NoScaling:=not ImportAutoScale and ((min=0) and (max=255));
  1179.                     DrawLabels('Line:', 'Total:', '');
  1180.                     while not TextEof do begin
  1181.                             GetLineFromText(rLine, count);
  1182.                             if not (TextEof and (count = 0)) then begin
  1183.                                     line := BlankLine;
  1184.                                     if ImportAutoScale then     {Map values into the range 1-254}
  1185.                                         for i := 1 to count do
  1186.                                             line[i - 1] := round((rLine[i] - min) * ScaleFactor + 1)
  1187.                                     else
  1188.                                         for i := 1 to count do begin
  1189.                                                 tvalue := rLine[i];
  1190.                                                 if tvalue < min then
  1191.                                                     tvalue := min;
  1192.                                                 if tvalue > max then
  1193.                                                     tvalue := max;
  1194.                                                 if noScaling
  1195.                                                     then line[i - 1]:=round(tvalue)
  1196.                                                     else line[i - 1] := round((tvalue - min) * ScaleFactor + 1);
  1197.                                             end;
  1198.                                     PutLine(0, vloc, PixelsPerLine, line);
  1199.                                     vloc := vloc + 1;
  1200.                                 end;
  1201.                             if vloc mod 10 = 0 then begin
  1202.                                     Show2Values(vloc, nRows);
  1203.                                     ShowAnimatedWatch;
  1204.                                     if CommandPeriod then begin
  1205.                                             beep;
  1206.                                             err := fsclose(Textf);
  1207.                                             Exit(ImportTextFile);
  1208.                                         end;
  1209.                                 end;
  1210.                         end;
  1211.                     if noScaling then
  1212.                         ImportCalibrate:=false
  1213.                     else begin
  1214.                         fit := StraightLine;
  1215.                         nCoefficients := 2;
  1216.                         coefficient[2] := (max - min) / 253.0;
  1217.                         coefficient[1] := min - coefficient[2];
  1218.                         nKnownValues := 0;
  1219.                         UpdateTitleBar;
  1220.                         if macro then
  1221.                             GenerateValues;
  1222.                         ZeroClip := false;
  1223.                     end;
  1224.                     changes := true;
  1225.                     PictureType := imported;
  1226.                 end; {with}
  1227.         ImportTextFile := true;
  1228.     end;
  1229.  
  1230.  
  1231.     procedure PlotXYZ;
  1232. {Reads X-Y coordinate pairs and optional intensiy(Z) values from a}
  1233. {two or three column tab-delimited text file and plots them in the current window.}
  1234.         var
  1235.             fname, str: str255;
  1236.             RefNum, i, nColumns, nValues, index, wheight: integer;
  1237.             rLine: RealLine;
  1238.     begin
  1239.         RefNum := 0;
  1240.         if not GetTextFile(fname, RefNum) then
  1241.             exit(PlotXYZ);
  1242.         InitTextInput(fname, RefNum);
  1243.         GetLineFromText(rLine, nValues);
  1244.         nColumns := nValues;
  1245.         if not ((nColumns = 2) or (nColumns = 3)) then begin
  1246.                 PutError('File must have two or three columns.');
  1247.                 exit(PlotXYZ);
  1248.             end;
  1249.         wheight := info^.nLines;
  1250.         index := ForegroundIndex;
  1251.         repeat
  1252.             if nColumns = 3 then begin
  1253.                     index := round(rLine[3]);
  1254.                     if index > 255 then
  1255.                         index := 255;
  1256.                     if index < 0 then
  1257.                         index := 0;
  1258.                 end;
  1259.             PutPixel(round(rLine[1]), wheight - round(rLine[2] + 1), index);
  1260.             GetLineFromText(rLine, nValues);
  1261.         until nValues = 0;
  1262.         InitCursor;
  1263.     end;
  1264.  
  1265.  
  1266.  
  1267.     procedure SaveSettings;
  1268.         var
  1269.             TheInfo: FInfo;
  1270.             ByteCount: LongInt;
  1271.             f, i: integer;
  1272.             err: OSErr;
  1273.             settings: SettingsType;
  1274.             PrefsVRef: integer;
  1275.             PrefsDirID: LongInt;
  1276.             PrefsSpec: FSSpec;
  1277.             PrefsError:boolean;
  1278.     begin
  1279.         with settings, info^ do begin
  1280.                 sID := 'IMAG';
  1281.                 sVersion := version;
  1282.                 sForegroundIndex := ForegroundIndex;
  1283.                 sBackgroundIndex := BackgroundIndex;
  1284.                 sBrushHeight := BrushHeight;
  1285.                 sBrushWidth := BrushWidth;
  1286.                 sSprayCanDiameter := SprayCanDiameter;
  1287.                 sLUTMode := LUTMode;
  1288.                 sOldColorStart := 30;
  1289.                 sOldColorWidth := 10;
  1290.                 sCurrentFontID := CurrentFontID;
  1291.                 sCurrentStyle := CurrentStyle;
  1292.                 sCurrentSize := CurrentSize;
  1293.                 sTextJust := TextJust;
  1294.                 sTextBack := TextBack;
  1295.                 sNExtraColors := nExtraColors;
  1296.                 sExtraColors := ExtraColors;
  1297.                 sInvertVideo := InvertVideo;
  1298.                 sMeasurements := Measurements;
  1299.                 sInvertPlots := InvertPlots;
  1300.                 sAutoScalePlots := AutoScalePlots;
  1301.                 sLinePlot := LinePlot;
  1302.                 sDrawPlotLabels := DrawPlotLabels;
  1303.                 for i := 1 to 12 do
  1304.                     sUnused1[i] := 0;
  1305.                 sFixedSizePlot := FixedSizePlot;
  1306.                 sProfilePlotWidth := ProfilePlotWidth;
  1307.                 sProfilePlotHeight := ProfilePlotHeight;
  1308.                 sFramesToAverage := FramesToAverage;
  1309.                 sNewPicWidth := NewPicWidth;
  1310.                 sNewPicHeight := NewPicHeight;
  1311.                 sBufferSize := BufferSize;
  1312.                 sMaxScionWidth := MaxScionWidth;
  1313.                 sThresholdToForeground := ThresholdToForeground;
  1314.                 sNonThresholdToBackground := NonThresholdToBackground;
  1315.                 sVideoChannel := VideoChannel;
  1316.                 sWhatToImport := WhatToImport;
  1317.                 sImportCustomWidth := ImportCustomWidth;
  1318.                 sImportCustomHeight := ImportCustomHeight;
  1319.                 sImportCustomOffset := ImportCustomOffset;
  1320.                 sWandAutoMeasure := WandAutoMeasure;
  1321.                 sWandAdjustAreas := WandAdjustAreas;
  1322.                 sBinaryIterations := BinaryIterations;
  1323.                 sScaleArithmetic := ScaleArithmetic;
  1324.                 sInvertPixelValues := InvertPixelValues;
  1325.                 sInvertYCoordinates := InvertYCoordinates;
  1326.                 sFieldWidth := FieldWidth;
  1327.                 sPrecision := precision;
  1328.                 sMinParticleSize := MinParticleSize;
  1329.                 sMaxParticleSize := MaxParticleSize;
  1330.                 sIgnoreParticlesTouchingEdge := IgnoreParticlesTouchingEdge;
  1331.                 sLabelParticles := LabelParticles;
  1332.                 sOutlineParticles := OutlineParticles;
  1333.                 sIncludeHoles := IncludeHoles;
  1334.                 sOscillatingMovies := OscillatingMovies;
  1335.                 sDriverHalftoning := DriverHalftoning;
  1336.                 sMaxMeasurements := MaxMeasurements;
  1337.                 sImportCustomDepth := ImportCustomDepth;
  1338.                 sImportSwapBytes := ImportSwapBytes;
  1339.                 sImportCalibrate := ImportCalibrate;
  1340.                 sImportAutoscale := ImportAutoscale;
  1341.                 for i := 1 to 12 do
  1342.                     sUnused2[i] := 0;
  1343.                 sShowHeadings := ShowHeadings;
  1344.                 sDefaultVRefNum := 0;
  1345.                 sDefaultDirID := 0;
  1346.                 sKernelsVRefNum := 0;
  1347.                 sKernelsDirID := 0;
  1348.         {***}
  1349.                 sProfilePlotMin := ProfilePlotMin;
  1350.                 sProfilePlotMax := ProfilePlotMax;
  1351.                 sImportMin := ImportMin;
  1352.                 sImportMax := ImportMax;
  1353.                 sHighlightPixels := HighlightSaturatedPixels;
  1354.         {***}
  1355.                 sBallRadius := BallRadius;
  1356.                 sFasterBackgroundSubtraction := FasterBackgroundSubtraction;
  1357.                 sScaleConvolutions := ScaleConvolutions;
  1358.         {V1.42}
  1359.                 sBinaryCount := BinaryCount;
  1360.                 sColorTable := ColorTable;
  1361.                 sColorStart := ColorStart;
  1362.                 sColorEnd := ColorEnd;
  1363.                 sInvertedTable := InvertedColorTable;
  1364.         {V1.44}
  1365.                 sHalftoneFrequency := HalftoneFrequency;
  1366.                 sHalftoneAngle := HalftoneAngle;
  1367.                 sHalftoneDotFunction := HalftoneDotFunction;
  1368.                 sDacLow := DacLow;
  1369.                 sDacHigh := DacHigh;
  1370.                 sSyncMode := SyncMode;
  1371.                 sSwitchLUTOnSuspend := SwitchLUTOnSuspend;
  1372.                 sVideoRateAveraging := VideoRateAveraging;
  1373.                 sImportInvert := ImportInvert;
  1374.                 sTextCreator := TextCreator;
  1375.                 sMathSubGain:=MathSubGain;
  1376.                 sMathSubOffset:=round(MathSubOffset);
  1377.                 for i := 1 to 10 do
  1378.                     sUnused[i] := 0;
  1379.             end; {with}
  1380.         if System7 then begin
  1381.             {Save in Preferences folder}
  1382.             PrefsError:=true;
  1383.             err:=FindFolder(kOnSystemDisk, kPreferencesFolderType,
  1384.                         kDontCreateFolder, PrefsVRef, PrefsDirID);
  1385.             if err=noErr then
  1386.                 err:=FSMakeFSSpec(PrefsVRef, PrefsDirID, PrefsName, PrefsSpec);
  1387.             if err=noErr
  1388.                 then err:=FSpDelete(PrefsSpec);
  1389.             if (err=noErr) or (err=fnfErr) then begin
  1390.                 err:=FSpCreate(PrefsSpec, 'Imag', 'pref', smSystemScript);
  1391.                 if err=noErr then
  1392.                     err:=FSpOpenDF(PrefsSpec, fsCurPerm, f);
  1393.                 if err=noErr then
  1394.                     PrefsError:=false;
  1395.             end;
  1396.             if PrefsError then begin
  1397.                 PutError('Error saving settings file');
  1398.                 exit(SaveSettings);
  1399.             end;
  1400.         end else begin
  1401.             {Save in System folder}
  1402.             err := GetFInfo(PrefsName, SystemRefNum, TheInfo);
  1403.             if err = FNFerr then begin
  1404.                     err := create(PrefsName, SystemRefNum, 'Imag', 'pref');
  1405.                     if CheckIO(err) <> 0 then
  1406.                         exit(SaveSettings);
  1407.                 end;
  1408.             err := fsopen(PrefsName, SystemRefNum, f);
  1409.         end;
  1410.         if CheckIO(err) <> 0 then
  1411.             exit(SaveSettings);
  1412.         err := SetFPos(f, FSFromStart, 0);
  1413.         ByteCount := SizeOf(settings);
  1414.         err := fswrite(f, ByteCount, @settings);
  1415.         if CheckIO(err) <> 0 then begin
  1416.                 err := fsclose(f);
  1417.                 exit(SaveSettings)
  1418.             end;
  1419.         err := SetEof(f, ByteCount);
  1420.         err := fsclose(f);
  1421.         err := FlushVol(nil, SystemRefNum);
  1422.     end;
  1423.  
  1424.  
  1425.     procedure ExportAsText (fname: str255; RefNum: integer);
  1426.         var
  1427.             err, f, width, hloc, vloc: integer;
  1428.             TheInfo: FInfo;
  1429.             ByteCount, FileSize: LongInt;
  1430.             AutoSelectAll, InvertValues: boolean;
  1431.             tLine: LineType;
  1432.     begin
  1433.         if info = NoInfo then
  1434.             exit(ExportAsText);
  1435.         err := GetFInfo(fname, RefNum, TheInfo);
  1436.         case err of
  1437.             NoErr: 
  1438.                 if TheInfo.fdType <> 'TEXT' then begin
  1439.                         TypeMismatch(fname);
  1440.                         exit(ExportAsText)
  1441.                     end;
  1442.             FNFerr:  begin
  1443.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1444.                     if CheckIO(err) <> 0 then
  1445.                         exit(ExportAsText);
  1446.                 end;
  1447.             otherwise
  1448.                 if CheckIO(err) <> 0 then
  1449.                     exit(ExportAsText)
  1450.         end;
  1451.         ShowWatch;
  1452.         err := fsopen(fname, RefNum, f);
  1453.         if CheckIO(err) <> 0 then
  1454.             exit(ExportAsText);
  1455.         AutoSelectAll := not info^.RoiShowing;
  1456.         if AutoSelectAll then
  1457.             SelectAll(true);
  1458.         if TooWide then
  1459.             exit(ExportAsText);
  1460.         FileSize := 0;
  1461.         with info^, info^.RoiRect do begin
  1462.                 InvertValues := isInvertingFunction;
  1463.                 width := right - left;
  1464.                 for vloc := top to bottom - 1 do begin
  1465.                         GetLine(left, vloc, width, tLine);
  1466.                         TextBufSize := 0;
  1467.                         for hloc := 0 to width - 1 do begin
  1468.                                 if fit = uncalibrated then
  1469.                                     PutLong(tLine[hloc], 0)
  1470.                                 else if InvertValues then
  1471.                                     PutLong(255 - tLine[hloc], 0)
  1472.                                 else
  1473.                                     PutString(StringOf(cValue[tLine[hloc]]:1:precision));
  1474.                                 if hloc <> (width - 1) then
  1475.                                     PutTab;
  1476.                             end;
  1477.                         PutChar(cr);
  1478.                         ByteCount := TextBufSize;
  1479.                         err := fswrite(f, ByteCount, ptr(TextBufP));
  1480.                         FIleSize := FileSize + ByteCount;
  1481.                         if (CheckIO(err) <> 0) or CommandPeriod then
  1482.                             leave;
  1483.                         if (vloc mod 10) = 0 then ShowAnimatedWatch;
  1484.                     end;
  1485.                 err := SetEof(f, FileSize);
  1486.                 err := fsclose(f);
  1487.                 err := FlushVol(nil, RefNum);
  1488.             end;
  1489.         if AutoSelectAll then
  1490.             KillRoi;
  1491.     end;
  1492.  
  1493.  
  1494.     procedure ExportCoordinates (fname: str255; RefNum: integer);
  1495.         var
  1496.             err, f, i, y: integer;
  1497.             TheInfo: FInfo;
  1498.             ByteCount, FileSize: LongInt;
  1499.             InvertY: boolean;
  1500.     begin
  1501.         if not CoordinatesAvailableMsg then begin
  1502.                 exit(ExportCoordinates)
  1503.             end;
  1504.         err := GetFInfo(fname, RefNum, TheInfo);
  1505.         case err of
  1506.             NoErr: 
  1507.                 if TheInfo.fdType <> 'TEXT' then begin
  1508.                         TypeMismatch(fname);
  1509.                         exit(ExportCoordinates)
  1510.                     end;
  1511.             FNFerr:  begin
  1512.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1513.                     if CheckIO(err) <> 0 then
  1514.                         exit(ExportCoordinates);
  1515.                 end;
  1516.             otherwise
  1517.                 if CheckIO(err) <> 0 then
  1518.                     exit(ExportCoordinates)
  1519.         end;
  1520.         ShowWatch;
  1521.         err := fsopen(fname, RefNum, f);
  1522.         if CheckIO(err) <> 0 then
  1523.             exit(ExportCoordinates);
  1524.         FileSize := 0;
  1525.         InvertY := InvertYCoordinates and (Info <> NoInfo);
  1526.         with info^ do
  1527.             for i := 1 to nCoordinates do begin
  1528.                     TextBufSize := 0;
  1529.                     PutLong(xCoordinates^[i] + RoiRect.left, 0);
  1530.                     PutTab;
  1531.                     y := yCoordinates^[i] + RoiRect.top;
  1532.                     if InvertY then
  1533.                         y := PicRect.bottom - y - 1;
  1534.                     PutLong(y, 0);
  1535.                     PutChar(cr);
  1536.                     ByteCount := TextBufSize;
  1537.                     err := fswrite(f, ByteCount, ptr(TextBufP));
  1538.                     FIleSize := FileSize + ByteCount;
  1539.                     if (CheckIO(err) <> 0) or CommandPeriod then
  1540.                         leave;
  1541.                 end;
  1542.         err := SetEof(f, FileSize);
  1543.         err := fsclose(f);
  1544.         err := FlushVol(nil, RefNum);
  1545.     end;
  1546.  
  1547.  
  1548.     procedure ExportMeasurements (fname: str255; RefNum: integer);
  1549.         const
  1550.             LinesPerPass = 25;
  1551.         var
  1552.             err, f, i, first, last: integer;
  1553.             TheInfo: FInfo;
  1554.             ByteCount, FileSize: LongInt;
  1555.     begin
  1556.         err := GetFInfo(fname, RefNum, TheInfo);
  1557.         case err of
  1558.             NoErr: 
  1559.                 if TheInfo.fdType <> 'TEXT' then begin
  1560.                         TypeMismatch(fname);
  1561.                         exit(ExportMeasurements)
  1562.                     end;
  1563.             FNFerr:  begin
  1564.                     err := create(fname, RefNum, FourCharCode(TextCreator), 'TEXT');
  1565.                     if CheckIO(err) <> 0 then
  1566.                         exit(ExportMeasurements);
  1567.                 end;
  1568.             otherwise
  1569.                 if CheckIO(err) <> 0 then
  1570.                     exit(ExportMeasurements)
  1571.         end;
  1572.         ShowWatch;
  1573.         err := fsopen(fname, RefNum, f);
  1574.         if CheckIO(err) <> 0 then
  1575.             exit(ExportMeasurements);
  1576.         FileSize := 0;
  1577.         first := 1;
  1578.         last := LinesPerPass;
  1579.         repeat
  1580.             if last > mCount then
  1581.                 last := mCount;
  1582.             CopyResultsToBuffer(first, last, ShowHeadings or OptionKeyWasDown);
  1583.             ByteCount := TextBufSize;
  1584.             err := fswrite(f, ByteCount, ptr(TextBufP));
  1585.             FIleSize := FileSize + ByteCount;
  1586.             if (CheckIO(err) <> 0) or CommandPeriod or (last = mCount) then
  1587.                 leave;
  1588.             first := first + LinesPerPass;
  1589.             last := last + LinesPerPass;
  1590.         until false;
  1591.         err := SetEof(f, FileSize);
  1592.         err := fsclose(f);
  1593.         err := FlushVol(nil, RefNum);
  1594.         UnsavedResults := false;
  1595.     end;
  1596.  
  1597.  
  1598.  
  1599.     procedure Swap2Bytes (var i: integer);
  1600.         type
  1601.             atype = packed array[1..2] of char;
  1602.         var
  1603.             a: atype;
  1604.             c: char;
  1605.     begin
  1606.         a := atype(i);
  1607.         c := a[1];
  1608.         a[1] := a[2];
  1609.         a[2] := c;
  1610.         i := integer(a)
  1611.     end;
  1612.  
  1613.  
  1614.     procedure Swap4Bytes (var i: LongInt);
  1615.         var
  1616.             a: ostype;
  1617.             c: char;
  1618.     begin
  1619.         a := ostype(i);
  1620.         c := a[1];
  1621.         a[1] := a[4];
  1622.         a[4] := c;
  1623.         c := a[2];
  1624.         a[2] := a[3];
  1625.         a[3] := c;
  1626.         i := LongInt(a)
  1627.     end;
  1628.     
  1629.  
  1630.  
  1631.     function OpenTiffHeader (f: integer; var DirOffset: LongInt): boolean;
  1632.         var
  1633.             TiffHeader: TiffHdr;
  1634.             ByteCount: LongInt;
  1635.             err: OSErr;
  1636.     begin
  1637.         ByteCount := 8;
  1638.         err := SetFPos(f, fsFromStart, 0);
  1639.         err := fsread(f, ByteCount, @TiffHeader);
  1640.         if CheckIO(err) <> NoErr then begin
  1641.                 OpenTiffHeader := false;
  1642.                 exit(OpenTiffHeader);
  1643.             end;
  1644.         with TiffHeader do begin
  1645.                 IntelByteOrder := ByteOrder = 'II';
  1646.                 if (ByteOrder <> 'MM') and (ByteOrder <> 'II') then begin
  1647.                         PutError('Invalid TIFF header.');
  1648.                         OpenTiffHeader := false;
  1649.                         exit(OpenTiffHeader)
  1650.                     end;
  1651.                 DirOffset := FirstIFDOffset;
  1652.                 if IntelByteOrder then
  1653.                     Swap4Bytes(DirOffset);
  1654.                 OpenTiffHeader := true;
  1655.             end;
  1656.     end;
  1657.  
  1658.  
  1659.     procedure GetTiffEntry (f: integer; var tag: integer; var N, value: LongInt);
  1660.         var
  1661.             IFDEntry: TiffEntry;
  1662.             ByteCount: LongInt;
  1663.             IntValue: integer;
  1664.             err: OSErr;
  1665.             str: str255;
  1666.     begin
  1667.         ByteCount := 12;
  1668.         err := FSRead(f, ByteCount, @IFDEntry);
  1669.         with IFDEntry do begin
  1670.                 tag := TagField;
  1671.                 N := length;
  1672.                 if IntelByteOrder then begin
  1673.                         Swap2Bytes(tag);
  1674.                         Swap2Bytes(ftype);
  1675.                         Swap4Bytes(N);
  1676.                     end;
  1677.                 value := offset;
  1678.                 if (ftype = short) and (N = 1) then begin
  1679.                         value := bsr(value, 16);
  1680.                         if IntelByteOrder then begin
  1681.                                 IntValue := value;
  1682.                                 Swap2Bytes(IntValue);
  1683.                                 value := IntValue
  1684.                             end
  1685.                     end
  1686.                 else if IntelByteOrder then
  1687.                     Swap4Bytes(value);
  1688.                 if OptionKeyWasDown then begin
  1689.                         gstr := concat(gstr, long2str(tag), '  ', long2str(ftype), '  ', long2str(N), '  ', long2str(value), crStr);
  1690.                         ShowMessage(gstr);
  1691.                     end;
  1692.             end;
  1693.     end;
  1694.  
  1695.  
  1696.     function OpenTiffDirectory (f: integer; DirOffset: LongInt; var TiffInfo: TiffInfoRec; Importing: boolean): boolean;
  1697.         const
  1698.             NoUnit = 1;
  1699.             inch = 2;
  1700.             centimeter = 3;
  1701.         var
  1702.             ByteCount, length, ftype, N, value, BytesPerStrip, SaveFPos: LongInt;
  1703.             err: OSErr;
  1704.             nEntries, i, tag, entry: integer;
  1705.             StripOffsetsArray: array[1..2] of LongInt;
  1706.             xRes, yRes: extended;
  1707.  
  1708.         function GetResolution: extended;
  1709.             var
  1710.                 resolution: array[1..2] of LongInt;
  1711.         begin
  1712.             err := GetFPos(f, SaveFPos);
  1713.             err := SetFPos(f, fsFromStart, value);
  1714.             ByteCount := 8;
  1715.             err := fsread(f, ByteCount, @Resolution);
  1716.             if IntelByteOrder then begin
  1717.                     Swap4Bytes(Resolution[1]);
  1718.                     Swap4Bytes(Resolution[2]);
  1719.                 end;
  1720.             err := SetFPos(f, fsFromStart, SaveFPos);
  1721.             if resolution[2] <> 0 then
  1722.                 GetResolution := resolution[1] / resolution[2]
  1723.             else
  1724.                 GetResolution := 0.0;
  1725.         end;
  1726.  
  1727.     begin
  1728.         if OptionKeyWasDown then
  1729.             gstr := '';
  1730.         xRes := 0.0;
  1731.         err := SetFPos(f, fsFromStart, DirOffset);
  1732.         ByteCount := 2;
  1733.         err := FSRead(f, ByteCount, @nEntries);
  1734.         if CheckIO(err) <> NoErr then begin
  1735.                 OpenTiffDirectory := false;
  1736.                 exit(OpenTiffDirectory);
  1737.             end;
  1738.         if IntelByteOrder then
  1739.             Swap2Bytes(nEntries);
  1740.         with TiffInfo do begin
  1741.                 width := 0;
  1742.                 height := 0;
  1743.                 BitsPerPixel := 8;
  1744.                 SamplesPerPixel:=1;
  1745.                 PlanarConfig := 1;
  1746.                 OffsetToData := 0;
  1747.                 Resolution := 0.0;
  1748.                 ResUnits := tNoUnits;
  1749.                 OffsetToColorMap := 0;
  1750.                 OffsetToImageHeader := -1;
  1751.                 StripOffsetsArray[1] := 0;
  1752.                 for entry := 1 to nEntries do begin
  1753.                         GetTiffEntry(f, tag, N, value);
  1754.                         if tag = 0 then begin
  1755.                                 PutError('Invalid TIFF format.');
  1756.                                 OpenTiffDirectory := false;
  1757.                                 exit(OpenTiffDirectory)
  1758.                             end;
  1759.                         case tag of
  1760.                             ImageWidth: 
  1761.                                 width := value;
  1762.                             ImageLength: 
  1763.                                 height := value;
  1764.                             BitsPerSample:  begin
  1765.                                     if N = 1 then
  1766.                                         BitsPerPixel := value;
  1767.                                     if value = 1 then begin
  1768.                                             PutError('NIH Image cannot open 1-bit TIFF files.');
  1769.                                             OpenTiffDirectory := false;
  1770.                                             exit(OpenTiffDirectory)
  1771.                                         end;
  1772.                                     if (value = 16) and not importing then begin
  1773.                                             PutError('Use Import to open 16-bit TIFF files.');
  1774.                                             OpenTiffDirectory := false;
  1775.                                             exit(OpenTiffDirectory)
  1776.                                         end;
  1777.                                 end;
  1778.                             SamplesPerPixelTag:
  1779.                                 if (value = 1) or (value = 3) then
  1780.                                      SamplesPerPixel:=value
  1781.                                 else begin
  1782.                                     PutError('NIH Image can only open TIFF files with 1 or 3 samples per pixel.');
  1783.                                     OpenTiffDirectory := false;
  1784.                                     exit(OpenTiffDirectory)
  1785.                                 end;
  1786.                             PlanarConfigTag:
  1787.                                 PlanarConfig := value;
  1788.                             Compression: 
  1789.                                 if value <> 1 then begin
  1790.                                         PutError('NIH Image cannot open compressed TIFF files.');
  1791.                                         OpenTiffDirectory := false;
  1792.                                         exit(OpenTiffDirectory)
  1793.                                     end;
  1794.                             PhotoInterp: 
  1795.                                 ZeroIsBlack := value = 1;
  1796.                             StripOffsets: 
  1797.                                 if N = 1 then
  1798.                                     OffsetToData := value
  1799.                                 else begin
  1800.                                         err := GetFPos(f, SaveFPos);
  1801.                                         err := SetFPos(f, fsFromStart, value);
  1802.                                         ByteCount := 8;
  1803.                                         err := fsread(f, ByteCount, @StripOffsetsArray);
  1804.                                         if IntelByteOrder then begin
  1805.                                                 Swap4Bytes(StripOffsetsArray[1]);
  1806.                                                 Swap4Bytes(StripOffsetsArray[2]);
  1807.                                             end;
  1808.                                         err := SetFPos(f, fsFromStart, SaveFPos);
  1809.                                     end;
  1810.                             RowsPerStrip: 
  1811.                                 if (OffsetToData=0) and (value < height) then begin
  1812.                                         BytesPerStrip := value * width;
  1813.                                         if BitsPerPixel = 16 then
  1814.                                             BytesPerStrip := BytesPerStrip * 2
  1815.                                         else if SamplesPerPixel = 3 then
  1816.                                             BytesPerStrip := BytesPerStrip * 3;
  1817.                                         if StripOffsetsArray[1] = 0 then begin
  1818.                                                 PutError('Invalid TIFF directory.');
  1819.                                                 OpenTiffDirectory := false;
  1820.                                                 exit(OpenTiffDirectory)
  1821.                                             end;
  1822.                                         if StripOffsetsArray[2] <> (StripOffsetsArray[1] + BytesPerStrip) then begin
  1823.                                                 PutError('NIH Image cannot open TIFF files with discontiguous strips.');
  1824.                                                 OpenTiffDirectory := false;
  1825.                                                 exit(OpenTiffDirectory)
  1826.                                             end;
  1827.                                         OffsetToData := StripOffsetsArray[1];
  1828.                                     end;
  1829.                             XResolution: 
  1830.                                 XRes := GetResolution;
  1831.                             YResolution:  begin
  1832.                                     yRes := GetResolution;
  1833.                                     if (xRes = yRes) and (xRes > 0.0) then begin
  1834.                                             resolution := xRes;
  1835.                                             ResUnits := tInches;
  1836.                                         end;
  1837.                                 end;
  1838.                             ResolutionUnit: 
  1839.                                 case value of
  1840.                                     NoUnit: 
  1841.                                         ResUnits := tNoUnits;
  1842.                                     Centimeter: 
  1843.                                         ResUnits := tCentimeters;
  1844.                                     otherwise
  1845.                                 end;
  1846.                             ColorMapTag: 
  1847.                                 if N = 768 then
  1848.                                     OffsetToColorMap := value;
  1849.                             ImageHdrTag: 
  1850.                                 OffsetToImageHeader := value;
  1851.                             otherwise
  1852.                         end;
  1853.                     end; {for}
  1854.                 ByteCount := 4;
  1855.                 err := FSRead(f, ByteCount, @NextIFD);
  1856.                 if IntelByteOrder then
  1857.                     Swap4Bytes(NextIFD);
  1858.                 if OptionKeyWasDown then begin
  1859.                         gstr := concat(gstr, 'Next IFD=', long2str(NextIFD));
  1860.                         ShowMessage(gstr);
  1861.                     end;
  1862.                 if width = 0 then begin
  1863.                         PutError('Error opening TIFF directory');
  1864.                         OpenTiffDirectory := false;
  1865.                         exit(OpenTiffDirectory)
  1866.                     end;
  1867.                 if (SamplesPerPixel = 3) and (PlanarConfig <> 1) then begin
  1868.                     PutError('NIH Image cannot open RGB files with separate planes.');
  1869.                     OpenTiffDirectory := false;
  1870.                     exit(OpenTiffDirectory)
  1871.                 end;
  1872.  
  1873.             end; {with}
  1874.         OpenTiffDirectory := true;
  1875.     end;
  1876.  
  1877.  
  1878.     procedure SaveTiffColorMap (f: integer; ImageDataSize: LongInt);
  1879.         var
  1880.             i: integer;
  1881.             err: OSErr;
  1882.             ColorMap: TiffColorMapType;
  1883.             ColorMapSize: LongInt;
  1884.     begin
  1885.         LoadLUT(info^.cTable);
  1886.         if ScreenDepth=8 then begin
  1887.             for i := 0 to 255 do
  1888.                 with cScreenPort^.portPixMap^^.pmTable^^.ctTable[i].rgb do begin
  1889.                     ColorMap[1, i] := red;
  1890.                     ColorMap[2, i] := green;
  1891.                     ColorMap[3, i] := blue;
  1892.                     end;
  1893.         end else begin
  1894.             for i := 0 to 255 do
  1895.                 with info^.cTable[i].rgb do begin
  1896.                     ColorMap[1, i] := red;
  1897.                     ColorMap[2, i] := green;
  1898.                     ColorMap[3, i] := blue;
  1899.                     end;
  1900.         end;
  1901.         err := SetFPos(f, FSFromStart, HeaderSize + TiffDirSize + ImageDataSize);
  1902.         ColorMapSize := SizeOf(ColorMap);
  1903.         err := fswrite(f, ColorMapSize, @ColorMap);
  1904.         if CheckIO(err) <> 0 then
  1905.             beep;
  1906.     end;
  1907.  
  1908.  
  1909.     procedure GetTiffColorMap (f: integer);
  1910.         var
  1911.             i: integer;
  1912.             ByteCount: LongInt;
  1913.             err: OSErr;
  1914.             ColorMap: TiffColorMapType;
  1915.     begin
  1916.         with info^ do begin
  1917.                 ByteCount := SizeOf(ColorMap);
  1918.                 err := SetFPos(f, fsFromStart, ColorMapOffset);
  1919.                 err := fsRead(f, ByteCount, @ColorMap);
  1920.                 if err = NoErr then begin
  1921.                         if IntelByteOrder then
  1922.                             for i := 0 to 255 do begin
  1923.                                     Swap2Bytes(ColorMap[1, i]);
  1924.                                     Swap2Bytes(ColorMap[2, i]);
  1925.                                     Swap2Bytes(ColorMap[3, i]);
  1926.                                 end;
  1927.                         for i := 0 to 255 do
  1928.                             with cTable[i].rgb do begin
  1929.                                     red := ColorMap[1, i];
  1930.                                     green := ColorMap[2, i];
  1931.                                     blue := ColorMap[3, i];
  1932.                                 end;
  1933.                         LoadLUT(cTable);
  1934.                         LUTMode := ColorLut;
  1935.                         SetupPseudocolor;
  1936.                         IdentityFunction := false;
  1937.                         if isGrayScaleLUT then begin
  1938.                                 info^.LutMode := CustomGrayScale;
  1939.                                 DrawMap;
  1940.                             end;
  1941.                     end
  1942.                 else
  1943.                     beep;
  1944.             end;{with}
  1945.     end;
  1946.  
  1947.  
  1948.     function SaveTiffDir (f, slines, sPixelsPerLine: integer; SavingSelection: boolean; ctabSize, ImageDataSize: LongInt): OSErr;
  1949.         var
  1950.             i: integer;
  1951.             err: OSErr;
  1952.             SavingStack, SavingRGBStack: boolean;
  1953.             ByteCount, width, height: LongInt;
  1954.             TiffInfo1: record
  1955.                     Header: TiffHdr;   {8}
  1956.                     nEntries: integer; {2}
  1957.                     TiffDir: array[1..9] of TiffEntry; {108}
  1958.                 end;
  1959.             ColorMapEntry: TiffEntry;  {12 (Optional)}
  1960.             TiffInfo2: record
  1961.                     ImageHdrEntry: TiffEntry;  {12}
  1962.                     NextIFD: LongInt;  {4}
  1963.                     BitsPerPixelData: array[1..3] of integer; {6} {only used for RGB files}
  1964.                     filler: array[1..TiffFillerSize] of integer; {116}
  1965.                 end;
  1966.             BitsPerSampleData: record
  1967.                 rBitsPerSample, gBitsPerSample, bBitsPerSample:integer;
  1968.             end;
  1969.     begin
  1970.         with info^ do begin
  1971.             SavingStack := false;
  1972.             SavingRGBStack := false;
  1973.             if StackInfo <> nil then
  1974.                 SavingStack := StackInfo^.nSlices > 1;
  1975.             if SavingStack then
  1976.                 if (StackInfo^.StackType = rgbStack) and (StackInfo^.nSlices = 3) then begin
  1977.                     SavingRGBStack := true;
  1978.                     ctabSize := 0;
  1979.                 end;
  1980.             if SavingSelection then begin
  1981.                     width := sPixelsPerLine;
  1982.                     height := sLines
  1983.                 end
  1984.             else begin
  1985.                     width := PixelsPerLine;
  1986.                     height := nLines
  1987.                 end;
  1988.             with TiffInfo1 do begin
  1989.                     with header do begin
  1990.                             ByteOrder := 'MM';
  1991.                             Version := 42;
  1992.                             FirstIFDOffset := 8;
  1993.                         end;
  1994.                     if ctabSize > 0 then
  1995.                         nEntries := 11
  1996.                     else
  1997.                         nEntries := 10;
  1998.                     for i := 1 to 9 do
  1999.                         with TiffDir[i] do begin
  2000.                                 ftype := 3;
  2001.                                 length := 1
  2002.                             end;
  2003.                     with TiffDir[1] do begin
  2004.                             TagField := NewSubfileType;
  2005.                             ftype := 4;
  2006.                             offset := 0;
  2007.                         end;
  2008.                     with TiffDir[2] do begin
  2009.                             TagField := ImageWidth;
  2010.                             offset := bsl(width, 16);
  2011.                         end;
  2012.                     with TiffDir[3] do begin
  2013.                             TagField := ImageLength;
  2014.                             offset := bsl(height, 16);
  2015.                         end;
  2016.                     with TiffDir[4] do begin
  2017.                             TagField := BitsPerSample;
  2018.                             if SavingRGBStack then begin
  2019.                                 ftype := 3;
  2020.                                 length := 3;
  2021.                                 offset := SizeOf(TiffInfo1) + SizeOf(TiffEntry) + SizeOf(LongInt);
  2022.                                 with TiffInfo2 do
  2023.                                     for i := 1 to 3 do
  2024.                                         BitsPerPixelData[i] := 8;
  2025.                             end else begin
  2026.                                 offset := bsl(8, 16);
  2027.                                 with TiffInfo2 do
  2028.                                     for i := 1 to 3 do
  2029.                                         BitsPerPixelData[i] := 0;
  2030.                             end;
  2031.                         end;
  2032.                     with TiffDir[5] do begin
  2033.                             TagField := PhotoInterp;
  2034.                             if SavingRGBStack then
  2035.                                 offset := bsl(2, 16)
  2036.                             else if ctabSize > 0 then
  2037.                                 offset := bsl(3, 16)
  2038.                             else
  2039.                                 offset := 0;
  2040.                         end;
  2041.                     with TiffDir[6] do begin
  2042.                             TagField := StripOffsets;
  2043.                             ftype := 4;
  2044.                             offset := TiffDirSize + HeaderSize;
  2045.                         end;
  2046.                     with TiffDir[7] do begin
  2047.                             TagField := SamplesPerPixelTag;
  2048.                             if SavingRGBStack then
  2049.                                 offset := bsl(3, 16)
  2050.                             else
  2051.                                 offset := bsl(1, 16);
  2052.                         end;
  2053.                     with TiffDir[8] do begin
  2054.                             TagField := RowsPerStrip;
  2055.                             offset := bsl(height, 16);
  2056.                         end;
  2057.                     with TiffDir[9] do begin
  2058.                             TagField := StripByteCount;
  2059.                             ftype := 4;
  2060.                             if SavingRGBStack then
  2061.                                 offset := width * height * 3
  2062.                             else
  2063.                                 offset := width * height;
  2064.                         end;
  2065.                 end;
  2066.             ByteCount := SizeOf(TiffInfo1);
  2067.             err := SetFPos(f, FSFromStart, 0);
  2068.             err := FSWrite(f, ByteCount, @TiffInfo1);
  2069.             if CheckIO(err) <> NoErr then begin
  2070.                     SaveTiffDir := err;
  2071.                     exit(SaveTiffDir);
  2072.                 end;
  2073.             if ctabSize > 0 then
  2074.                 with ColorMapEntry do begin
  2075.                         TagField := ColorMapTag;
  2076.                         ftype := 3;
  2077.                         length := 768;
  2078.                         offset := HeaderSize + TiffDirSize + ImageDataSize;
  2079.                         ByteCount := SizeOf(ColorMapEntry);
  2080.                         err := FSWrite(f, ByteCount, @ColorMapEntry);
  2081.                         if CheckIO(err) <> NoErr then begin
  2082.                                 SaveTiffDir := err;
  2083.                                 exit(SaveTiffDir);
  2084.                             end;
  2085.                     end;
  2086.             with TiffInfo2 do begin
  2087.                     with ImageHdrEntry do begin
  2088.                             TagField := ImageHdrTag;
  2089.                             ftype := 3;
  2090.                             length := 256;
  2091.                             offset := TiffDirSize;
  2092.                         end;
  2093.                     NextIFD := 0;
  2094.                     if SavingStack then
  2095.                         NextIFD := HeaderSize + TiffDirSize + ImageDataSize + ctabSize;
  2096.                     for i := 1 to TiffFillerSize do
  2097.                         filler[i] := 0;
  2098.                 end;
  2099.             end; {with info^}
  2100.         ByteCount := SizeOf(TiffInfo2);
  2101.         err := FSWrite(f, ByteCount, @TiffInfo2);
  2102.         SaveTiffDir := CheckIO(err);
  2103.     end;
  2104.  
  2105.  
  2106.     function WriteExtraTiffIFDs (f: integer; ImageDataSize, cTabSize: LongInt): integer;
  2107.         var
  2108.             IFD, entry: integer;
  2109.             StackIFD: StackIFDType;
  2110.             err: OSErr;
  2111.             IFDoffset, SliceOffset, ByteCount: LongInt;
  2112.     begin
  2113.         with info^, StackInfo^, StackIFD do begin
  2114.                 IFDoffset := HeaderSize + TiffDirSize + ImageDataSize + ctabSize;
  2115.                 err := SetFPos(f, FSFromStart, IFDoffset);
  2116.                 SliceOffset := HeaderSize + TiffDirSize + ImageSize;
  2117.                 for IFD := 2 to nSlices do  {IFD=Image File Directory}
  2118.                     begin
  2119.                         nEntries := 6;
  2120.                         for entry := 1 to nEntries do
  2121.                             with TiffDir[entry] do begin
  2122.                                     ftype := 3;
  2123.                                     length := 1
  2124.                                 end;
  2125.                         with TiffDir[1] do begin
  2126.                                 TagField := NewSubfileType;
  2127.                                 ftype := 4;
  2128.                                 offset := 0;
  2129.                             end;
  2130.                         with TiffDir[2] do begin
  2131.                                 TagField := ImageWidth;
  2132.                                 offset := bsl(PixelsPerLine, 16);
  2133.                             end;
  2134.                         with TiffDir[3] do begin
  2135.                                 TagField := ImageLength;
  2136.                                 offset := bsl(nLines, 16);
  2137.                             end;
  2138.                         with TiffDir[4] do begin
  2139.                                 TagField := BitsPerSample;
  2140.                                 offset := bsl(8, 16);
  2141.                             end;
  2142.                         with TiffDir[5] do begin
  2143.                                 TagField := PhotoInterp;
  2144.                                 offset := 0;
  2145.                             end;
  2146.                         with TiffDir[6] do begin
  2147.                                 TagField := StripOffsets;
  2148.                                 ftype := 4;
  2149.                                 offset := SliceOffset;
  2150.                             end;
  2151.                         SliceOffset := SliceOffset + ImageSize;
  2152.                         IFDoffset := IFDoffset + SizeOf(StackIFD);
  2153.                         if IFD <> nSlices then
  2154.                             NextIFD := IFDoffset
  2155.                         else
  2156.                             NextIFD := 0;
  2157.                         ByteCount := SizeOf(StackIFD);
  2158.                         err := fswrite(f, ByteCount, @StackIFD);
  2159.                         if err <> NoErr then begin
  2160.                                 WriteExtraTiffIFDs := err;
  2161.                                 exit(WriteExtraTiffIFDs);
  2162.                             end;
  2163.                     end; {for}
  2164.             end; {with}
  2165.         WriteExtraTiffIFDs := NoErr;
  2166.     end;
  2167.  
  2168.  
  2169.     procedure SaveLUT (fname: str255; RefNum: integer);
  2170.         var
  2171.             err: integer;
  2172.             TheInfo: FInfo;
  2173.             LUT: array[1..3] of packed array[0..255] of byte;
  2174.             i, f: integer;
  2175.             ByteCount: LongInt;
  2176.     begin
  2177.         err := GetFInfo(fname, RefNum, TheInfo);
  2178.         case err of
  2179.             NoErr: 
  2180.                 if TheInfo.fdType <> 'ICOL' then begin
  2181.                         TypeMismatch(fname);
  2182.                         exit(SaveLUT)
  2183.                     end;
  2184.             FNFerr:  begin
  2185.                     err := create(fname, RefNum, 'Imag', 'ICOL');
  2186.                     if CheckIO(err) <> 0 then
  2187.                         exit(SaveLUT);
  2188.                 end;
  2189.             otherwise
  2190.                 if CheckIO(err) <> 0 then
  2191.                     exit(SaveLUT);
  2192.         end;
  2193.         DisableDensitySlice;
  2194.         LoadLUT(Info^.cTable);
  2195.         for i := 0 to 255 do
  2196.             with cScreenPort^.portPixMap^^.pmTable^^.ctTable[i].rgb do begin
  2197.                     LUT[1, i] := band(bsr(red, 8), 255);
  2198.                     LUT[2, i] := band(bsr(green, 8), 255);
  2199.                     LUT[3, i] := band(bsr(blue, 8), 255);
  2200.                 end;
  2201.         err := fsopen(fname, RefNum, f);
  2202.         if CheckIO(err) <> 0 then
  2203.             exit(SaveLUT);
  2204.         err := SetFPos(f, FSFromStart, 0);
  2205.         ByteCount := SizeOf(LUT);
  2206.         err := fswrite(f, ByteCount, @LUT);
  2207.         if CheckIO(err) <> 0 then begin
  2208.                 err := fsclose(f);
  2209.                 err := FSDelete(fname, RefNum);
  2210.                 exit(SaveLUT)
  2211.             end;
  2212.         err := SetEof(f, ByteCount);
  2213.         err := fsclose(f);
  2214.         err := GetFInfo(fname, RefNum, TheInfo);
  2215.         if TheInfo.fdCreator <> 'Imag' then begin
  2216.                 TheInfo.fdCreator := 'Imag';
  2217.                 err := SetFInfo(fname, RefNum, TheInfo);
  2218.             end;
  2219.         err := FlushVol(nil, RefNum);
  2220.     end;
  2221.  
  2222.  
  2223.     procedure SaveColorTable (fname: str255; RefNum: integer);
  2224.         var
  2225.             err: integer;
  2226.             TheInfo: FInfo;
  2227.             i, f: integer;
  2228.             ByteCount: LongInt;
  2229.             hdr: PaletteHeader;
  2230.     begin
  2231.         with info^ do
  2232.             err := GetFInfo(fname, RefNum, TheInfo);
  2233.         case err of
  2234.             NoErr: 
  2235.                 if TheInfo.fdType <> 'ICOL' then begin
  2236.                         TypeMismatch(fname);
  2237.                         exit(SaveColorTable)
  2238.                     end;
  2239.             FNFerr:  begin
  2240.                     err := create(fname, RefNum, 'Imag', 'ICOL');
  2241.                     if CheckIO(err) <> 0 then
  2242.                         exit(SaveColorTable);
  2243.                 end;
  2244.             otherwise
  2245.                 if CheckIO(err) <> 0 then
  2246.                     exit(SaveColorTable);
  2247.         end;
  2248.         with info^ do begin
  2249.                 InitPaletteHeader(hdr);
  2250.                 err := fsopen(fname, RefNum, f);
  2251.                 if CheckIO(err) <> 0 then
  2252.                     exit(SaveColorTable);
  2253.                 err := SetFPos(f, FSFromStart, 0);
  2254.                 ByteCount := SizeOf(PaletteHeader);
  2255.                 if ByteCount <> 32 then
  2256.                     PutError('Palette header size <> 32.');
  2257.                 err := fswrite(f, ByteCount, @hdr);
  2258.                 ByteCount := nColors;
  2259.                 err := fswrite(f, ByteCount, @redLUT);
  2260.                 ByteCount := nColors;
  2261.                 err := fswrite(f, ByteCount, @greenLUT);
  2262.                 ByteCount := nColors;
  2263.                 err := fswrite(f, ByteCount, @blueLUT);
  2264.                 if CheckIO(err) <> 0 then begin
  2265.                         err := fsclose(f);
  2266.                         err := FSDelete(fname, RefNum);
  2267.                         exit(SaveColorTable)
  2268.                     end;
  2269.                 err := SetEOF(f, SizeOf(PaletteHeader) + 3 * nColors);
  2270.                 err := fsclose(f);
  2271.                 err := GetFInfo(fname, RefNum, TheInfo);
  2272.                 if TheInfo.fdCreator <> 'Imag' then begin
  2273.                         TheInfo.fdCreator := 'Imag';
  2274.                         err := SetFInfo(fname, RefNum, TheInfo);
  2275.                     end;
  2276.                 err := FlushVol(nil, RefNum);
  2277.             end; {with info^}
  2278.     end;
  2279.  
  2280.  
  2281.     procedure SaveOutline (fname: str255; RefNum: integer);
  2282.         var
  2283.             err: integer;
  2284.             TheInfo: FInfo;
  2285.             i, f: integer;
  2286.             ByteCount, DataSize: LongInt;
  2287.             hdr: RoiHeader;
  2288.             SaveCoordinates: boolean;
  2289.             dX1, dY1, dX2, dY2: extended;
  2290.     begin
  2291.         with info^ do begin
  2292.                 if not RoiShowing then begin
  2293.                         PutError('No outline available to save.');
  2294.                         exit(SaveOutline);
  2295.                     end;
  2296.                 if (RoiType = FreeLineRoi) or (RoiType = SegLineRoi) then begin
  2297.                         PutError('Freehand and segmented line selections cannot be saved.');
  2298.                         exit(SaveOutline);
  2299.                     end;
  2300.                 SaveCoordinates := (RoiType = PolygonRoi) or (RoiType = FreehandRoi) or (RoiType = TracedRoi);
  2301.                 if SaveCoordinates then
  2302.                     if not CoordinatesAvailableMsg then begin
  2303.                             exit(SaveOutline);
  2304.                         end;
  2305.                 err := GetFInfo(fname, RefNum, TheInfo);
  2306.                 case err of
  2307.                     NoErr: 
  2308.                         if TheInfo.fdType <> 'Iout' then begin
  2309.                                 TypeMismatch(fname);
  2310.                                 exit(SaveOutline)
  2311.                             end;
  2312.                     FNFerr:  begin
  2313.                             err := create(fname, RefNum, 'Imag', 'Iout');
  2314.                             if CheckIO(err) <> 0 then
  2315.                                 exit(SaveOutline);
  2316.                         end;
  2317.                     otherwise
  2318.                         if CheckIO(err) <> 0 then
  2319.                             exit(SaveOutline);
  2320.                 end;
  2321.                 with hdr do begin
  2322.                         rID := 'Iout';
  2323.                         rVersion := version;
  2324.                         rRoiType := RoiType;
  2325.                         rRoiRect := RoiRect;
  2326.                         rNCoordinates := nCoordinates;
  2327.                         GetLoi(dX1, dY1, dX2, dY2);
  2328.                         rX1:=dX1; rY1:=dY1; rX2:=dX2; rY2:=dY2;
  2329.                         rLineWidth := LineWidth;
  2330.                         for i := 1 to 14 do
  2331.                             rUnused[i] := 0;
  2332.                     end;
  2333.                 err := fsopen(fname, RefNum, f);
  2334.                 if CheckIO(err) <> 0 then
  2335.                     exit(SaveOutline);
  2336.                 err := SetFPos(f, FSFromStart, 0);
  2337.                 ByteCount := SizeOf(RoiHeader);
  2338.                 if ByteCount <> 64 then
  2339.                     PutError('Roi header size <> 32.');
  2340.                 err := fswrite(f, ByteCount, @hdr);
  2341.                 if SaveCoordinates then begin
  2342.                         ByteCount := nCoordinates * 2;
  2343.                         err := fswrite(f, ByteCount, ptr(xCoordinates));
  2344.                         ByteCount := nCoordinates * 2;
  2345.                         err := fswrite(f, ByteCount, ptr(yCoordinates));
  2346.                         DataSize := nCoordinates * 4;
  2347.                     end
  2348.                 else
  2349.                     DataSize := 0;
  2350.                 if CheckIO(err) <> 0 then begin
  2351.                         err := fsclose(f);
  2352.                         err := FSDelete(fname, RefNum);
  2353.                         exit(SaveOutline)
  2354.                     end;
  2355.                 err := SetEOF(f, SizeOf(RoiHeader) + DataSize);
  2356.                 err := fsclose(f);
  2357.                 err := GetFInfo(fname, RefNum, TheInfo);
  2358.                 if TheInfo.fdCreator <> 'Imag' then begin
  2359.                         TheInfo.fdCreator := 'Imag';
  2360.                         err := SetFInfo(fname, RefNum, TheInfo);
  2361.                     end;
  2362.                 err := FlushVol(nil, RefNum);
  2363.             end; {with info^}
  2364.     end;
  2365.  
  2366.  
  2367.     procedure OpenOutline (fname: str255; RefNum: integer);
  2368.         var
  2369.             err, f, i: integer;
  2370.             count: LongInt;
  2371.             hdr: RoiHeader;
  2372.             okay: boolean;
  2373.     begin
  2374.         if Info = NoInfo then begin
  2375.                 if (NewPicWidth * NewPicHeight) <= UndoBufSize then begin
  2376.                         if not NewPicWindow('Untitled', NewPicWidth, NewPicHeight) then
  2377.                             exit(OpenOutline)
  2378.                     end
  2379.                 else begin
  2380.                         beep;
  2381.                         exit(OpenOutline)
  2382.                     end;
  2383.             end;
  2384.         KillRoi;
  2385.         err := fsopen(fname, RefNum, f);
  2386.         with info^, hdr do begin
  2387.                 count := SizeOf(RoiHeader);
  2388.                 err := fsread(f, count, @hdr);
  2389.                 if rID <> 'Iout' then begin
  2390.                         err := fsclose(f);
  2391.                         PutError('File is corrupted.');
  2392.                         exit(OpenOutline)
  2393.                     end;
  2394.                 if (rRoiRect.right > PicRect.right) or (rRoiRect.bottom > PicRect.bottom) then begin
  2395.                         err := fsclose(f);
  2396.                         PutError('Image is too small for the outline.');
  2397.                         exit(OpenOutline)
  2398.                     end;
  2399.                 case rRoiType of
  2400.                     LineRoi:  begin
  2401.                             LX1 := rX1;
  2402.                             LY1 := rY1;
  2403.                             LX2 := rX2;
  2404.                             LY2 := rY2;
  2405.                             RoiType := LineRoi;
  2406.                             MakeRegion;
  2407.                             SetupUndo;
  2408.                             RoiShowing := true;
  2409.                         end;
  2410.                     RectRoi, OvalRoi:  begin
  2411.                             RoiType := rRoiType;
  2412.                             RoiRect := rRoiRect;
  2413.                             MakeRegion;
  2414.                             SetupUndo;
  2415.                             RoiShowing := true;
  2416.                         end;
  2417.                     PolygonRoi, FreehandRoi, TracedRoi: 
  2418.                         if (rNCoordinates > 2) and (rNCoordinates <= MaxCoordinates) then begin
  2419.                                 count := rNCoordinates * 2;
  2420.                                 err := fsread(f, count, ptr(xCoordinates));
  2421.                                 count := rNCoordinates * 2;
  2422.                                 err := fsread(f, count, ptr(yCoordinates));
  2423.                                 if CheckIO(err) = 0 then begin
  2424.                                         nCoordinates := rNCoordinates;
  2425.                                         SelectionMode := NewSelection;
  2426.                                         if rVersion >= 148 then
  2427.                                             for i := 1 to nCoordinates do
  2428.                                                 with rRoiRect do begin
  2429.                                                         xCoordinates^[i] := xCoordinates^[i] + left;
  2430.                                                         yCoordinates^[i] := yCoordinates^[i] + top;
  2431.                                                     end;
  2432.                                         MakeOutline(rRoiType);
  2433.                                         SetupUndo;
  2434.                                     end;
  2435.                             end;
  2436.                 end;
  2437.             end;
  2438.         err := fsclose(f);
  2439.     end;
  2440.  
  2441.  
  2442.     function GetTIFFParameters (name: str255; RefNum: integer; var HasColorMap: boolean): boolean;
  2443.         var
  2444.             err: OSErr;
  2445.             f: integer;
  2446.             DirOffset: LongInt;
  2447.             TiffInfo: TiffInfoRec;
  2448.     begin
  2449.         GetTIFFParameters := false;
  2450.         HasColorMap := false;
  2451.         err := fsopen(name, RefNum, f);
  2452.         if err <> NoErr then
  2453.             exit(GetTIFFParameters);
  2454.         if not OpenTiffHeader(f, DirOffset) then begin
  2455.                 err := fsclose(f);
  2456.                 exit(GetTIFFParameters)
  2457.             end;
  2458.         if not OpenTiffDirectory(f, DirOffset, TiffInfo, true) then begin
  2459.                 err := fsclose(f);
  2460.                 exit(GetTIFFParameters)
  2461.             end;
  2462.         with TiffInfo do begin
  2463.                 ImportCustomWidth := width;
  2464.                 ImportCustomHeight := height;
  2465.                 ImportCustomOffset := OffsetToData;
  2466.                 ImportAutoScale:=true;
  2467.                 if BitsPerPixel = 16 then begin
  2468.                         ImportCustomDepth := SixteenBitsUnsigned;
  2469.                         ImportSwapBytes := IntelByteOrder;
  2470.                     end
  2471.                 else begin
  2472.                         ImportCustomDepth := EightBits;
  2473.                         ImportInvert := ZeroIsBlack;
  2474.                     end;
  2475.                 HasColorMap := OffsetToColorMap > 0;
  2476.             end;
  2477.         if ImportCustomDepth = EightBits then begin
  2478.             WhatToImport := ImportTiff;
  2479.             WhatToOpen := OpenTiff
  2480.         end else begin
  2481.             WhatToImport := ImportCustom;
  2482.             WhatToOpen := OpenCustom
  2483.         end;
  2484.         err := fsclose(f);
  2485.         GetTIFFParameters := true;
  2486.     end;
  2487.  
  2488.  
  2489.     procedure GetXUnits (UnitsKind: UnitsType);
  2490.     begin
  2491.         with info^ do
  2492.             case UnitsKind of
  2493.                 Nanometers: 
  2494.                     xUnit := 'nm';
  2495.                 Micrometers: 
  2496.                     xUnit := 'µm';
  2497.                 Millimeters: 
  2498.                     xUnit := 'mm';
  2499.                 Centimeters: 
  2500.                     xUnit := 'cm';
  2501.                 Meters: 
  2502.                     xUnit := 'meter';
  2503.                 Kilometers: 
  2504.                     xUnit := 'km';
  2505.                 Inches: 
  2506.                     xUnit := 'inch';
  2507.                 feet: 
  2508.                     xUnit := 'ft';
  2509.                 Miles: 
  2510.                     xUnit := 'mile';
  2511.                 Pixels: 
  2512.                     xUnit := 'pixel';
  2513.                 otherwise
  2514.                     ;
  2515.             end;
  2516.     end;
  2517.  
  2518.  
  2519.     procedure GetUnitsKInd (var UnitsKind: UnitsType; var UnitsPerCM: extended);
  2520.     begin
  2521.         with info^ do begin
  2522.                 if xunit = 'nm' then begin
  2523.                         UnitsKind := Nanometers;
  2524.                         UnitsPerCm := 10000000.0;
  2525.                     end
  2526.                 else if xUnit = 'µm' then begin
  2527.                         UnitsKind := Micrometers;
  2528.                         UnitsPerCm := 10000.0;
  2529.                     end
  2530.                 else if xUnit = 'mm' then begin
  2531.                         UnitsKind := Millimeters;
  2532.                         UnitsPerCm := 10.0;
  2533.                     end
  2534.                 else if xUnit = 'cm' then begin
  2535.                         UnitsKind := Centimeters;
  2536.                         UnitsPerCm := 1.0;
  2537.                     end
  2538.                 else if xUnit = 'meter' then begin
  2539.                         UnitsKind := Meters;
  2540.                         UnitsPerCm := 0.01;
  2541.                     end
  2542.                 else if xUnit = 'km' then begin
  2543.                         UnitsKind := Kilometers;
  2544.                         UnitsPerCm := 0.00001;
  2545.                     end
  2546.                 else if xUnit = 'inch' then begin
  2547.                         UnitsKind := Inches;
  2548.                         UnitsPerCm := 0.3937;
  2549.                     end
  2550.                 else if xUnit = 'ft' then begin
  2551.                         UnitsKind := feet;
  2552.                         UnitsPerCm := 0.0328083;
  2553.                     end
  2554.                 else if xUnit = 'mile' then begin
  2555.                         UnitsKind := Miles;
  2556.                         UnitsPerCm := 0.000006213;
  2557.                     end
  2558.                 else if xUnit = 'pixel' then begin
  2559.                         UnitsKind := pixels;
  2560.                         UnitsPerCm := 0.0;
  2561.                         SpatiallyCalibrated := false;
  2562.                     end
  2563.                 else begin
  2564.                         UnitsKind := OtherUnits;
  2565.                         UnitsPerCm := 0.0;
  2566.                     end;
  2567.             end;
  2568.     end;
  2569.  
  2570.  
  2571. end.