home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / SDI.ZIP / SDIMAGE.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-11-26  |  29.6 KB  |  797 lines

  1.  
  2. { *********************************************************************** }
  3. {                            SDImage  V1.02                               }
  4. {                        as of 25 November 1988                           }
  5. {                                                                         }
  6. {    SDImage V1.01 is a graphics image save/display utility which allows  }
  7. {  you to save graphic images to memory or disk and redisplay them.       }
  8. {  Image files can be read in another program or at a later date by       }
  9. {  referring to the file by it's reference number in DisplayImage.        }
  10. {    This unit is only dependant upon the BGI Graph unit. All activity is }
  11. {  performed through the BGI, so anything that BGI supports SDImage also  }
  12. {  supports automatically. Image size is not a factor. SDImage            }
  13. {  automatically handles images that are larger than 64K. In fact, it     }
  14. {  can handle any size image without requiring massive heap storage.      }
  15. {    If the image size exceeds the buffer size, it will be automatically  }
  16. {  stored to a disk file. Thus a full VGA screen could be saved with      }
  17. {  a buffer size of only 1K. Note: It will take longer to save/display    }
  18. {  the image with smaller buffers since the image has to be stored and    }
  19. {  retrieved to disk.                                                     }
  20. {                                                                         }
  21. {    The mechanism that SDImage uses to save an image to disk is one      }
  22. {  file per image. Thus if you intend to save lots of images, I strongly  }
  23. {  recommend that you place them in a seperate subdirectory to help keep  }
  24. {  things uncluttered. Also be aware that SDImage will leave image files  }
  25. {  laying around if you don't remove them yourself. Which is another      }
  26. {  good reason for putting the image files in their own directory so      }
  27. {  that you can quickly find them and delete them if this is a problem.   }
  28. {                                                                         }
  29. {    It should be further noted that to operate correctly, the image      }
  30. {  buffer size that is used to read in an image must be the same size     }
  31. {  (or larger) than the image buffer that was used to save the image.     }
  32. {  Because of this, if the image buffer size is too small, SDImage will   }
  33. {  automatically resize the image read buffer to the correct size.        }
  34. {                                                                         }
  35. {         Originally written by Michael Day 12 November 1988              }
  36. {                    Copyright 1988 by Michael Day                        }
  37. {                                                                         }
  38. {       This version (V1.02) is released to the public domain             }
  39. {                     as of 25 November 1988                              }
  40. { *********************************************************************** }
  41. { History:                                                                }
  42. { V1.01 - Original release                                                }
  43. { V1.02 - Corrected special effects bug                                   }
  44.  
  45. unit SDImage;
  46. interface
  47. uses graph;
  48.  
  49. const
  50.       ImageError : word = 0;   {contains one of the possible errors below}
  51.  
  52.       NoImageError      = 0;   {Don't Worry, Be Happy! Everything's cool.}
  53.       ImageDiskError    = 1;   {Either file not found or a bum disk}
  54.       ImageBufNumTooBig = 2;   {Too big a number, See MaxImageBuf const}
  55.  
  56. {-------------------------------------------------------------------------}
  57. {Save a graphic screen Image, using Image reference number "Img" and}
  58. {working buffer "Buf". x1,y1,x2,y2 specify the screen area to save}
  59. {If something goes wrong, this function will return false.}
  60. {The lower four bits of "Style" controls the special effects.}
  61. {The upper four bits of Style controls the disk/buffer action.}
  62. {If bit 7 is on, then the image will always be forced to disk.}
  63. {If bit 7 is off, then the image will stay in the buffer if it can.}
  64. {If the image is bigger than the buffer then it is flushed to disk anyway.}
  65. {Note: special effects only operate when the image is read from the disk.}
  66. {In fact it works because it uses the disk buffering as an inherent part}
  67. {of the effects control. EMS buffering is not currently implemented.}
  68. {0=Pull Down, 1=Pull Up, 2=Pull Right, 3=Pull Left, 4=Merge Vertical,}
  69. {5=Expand Vertical, 6=Merge Horizontal, 7=Expand Horizontal.}
  70.  
  71. function SaveImage(Img,Buf:word; x1,y1,x2,y2:integer; Style:word):boolean;
  72.  
  73. {-------------------------------------------------------------------------}
  74. {Displays a graphic screen image using image reference number Img and}
  75. {working buffer "Buf". If an image is residing in the buffer and is the}
  76. {correct image, then it will be displayed from the buffer. If the image}
  77. {is not the correct one, or there is no image currently saved in the}
  78. {buffer, then the buffer will be flushed to disk and the requested image}
  79. {will be read from the disk (if found) and displayed. If ImgClr is ture,}
  80. {then the image will be cleared from the buffer after being displayed.}
  81. {If the image came from disk, then the disk file will be erased as well.}
  82. {If ImgClr is false, then the image buffer and disk are left as they}
  83. {were found. If something goes wrong, this function will return false.}
  84.  
  85. function DisplayImage(Img,Buf:word; ImgClr:boolean):boolean;
  86.  
  87. {-------------------------------------------------------------------------}
  88. {The SaveImage function will automatically allocate an image buffer of the}
  89. {default size on the first use if none exists. If you wish to use a larger}
  90. {or smaller buffer, then you must use AllocImageBuf to allocate the desired}
  91. {image buffer size. If an image already exists in the buffer, it will be}
  92. {lost. Any existing old buffer space will be automatically released.}
  93. {If there is not enough heap space to allocate the buffer, this function}
  94. {will return a false condition.}
  95.  
  96. function AllocImageBuf(Buf:word; Size:word):boolean;
  97.  
  98. {-------------------------------------------------------------------------}
  99. {This releases the image buffer used with an image. You can call this to}
  100. {pick up heap space if you don't need the buffer anymore. As always,}
  101. {if the buffer is not allocated at the time SaveImage is called, then}
  102. {the default sized buffer will be allocated. Thus if you don't mind a}
  103. {slight slow down in the image process, you could call this after calling}
  104. {DisplayImage to keep heap usage to a minimum. Though keep in mind that}
  105. {if you release the buffer, any saved image in the buffer will be lost.}
  106.  
  107. function ReleaseImageBuf(Buf:word):boolean;
  108.  
  109. {-------------------------------------------------------------------------}
  110. {This sets a new path to be used for the image files. If the path does not}
  111. {exist, then it will be unchanged, and the function returns false.}
  112. {the Default path is to use the current default directory (i.e. no path).}
  113.  
  114. function SetImagePath(Path:string):boolean;
  115.  
  116. {-------------------------------------------------------------------------}
  117. {If an image is in the specified buffer, then the image will be flushed}
  118. {to disk. This can be used in preperation to releasing the buffer in order}
  119. {to gain more heap space. If the image could not be written to disk, then}
  120. {the function is aborted and returns false.}
  121.  
  122. function FlushImage(Buf:word):boolean;
  123.  
  124. {-------------------------------------------------------------------------}
  125. {An image can be deleted with this function. This will delete both images}
  126. {in the buffer and/or on disk. Retuns false if the image cannot be deleted}
  127.  
  128. function DeleteImage(Img,Buf:word):boolean;
  129.  
  130.  
  131. { *********************************************************************** }
  132.  
  133. implementation
  134.  
  135. type
  136.      string8  = string[8];
  137.      string80 = string[80];
  138.      ImgRect  = record Xmin,Ymin,Xmax,Ymax:integer; end;
  139.  
  140.      {- this gets saved to disk at the beginning of the image file -}
  141.      ImageDefRec = record     {18 bytes}
  142.        ImageNum    : word;    {image reference number in use}
  143.        MaxImgSize  : word;    {size of buffer used to write the image}
  144.        ImgArea     : ImgRect; {the overall image area definition}
  145.        ImgType     : word;    {how to save/display (special effects)}
  146.        StepSize    : word;    {how many pixel rows per segment}
  147.        StepCount   : word;    {how many image segments used}
  148.        WrkSize     : word;    {how big full image is; $ffff= over 64K}
  149.      end;
  150.  
  151.      {- this is only used by the image buffer -}
  152.      ImageBufRec = record     {16 bytes}
  153.        MaxBufSize  : word;    {how big the image buffer is}
  154.        RawImage    : pointer; {points to image buffer on heap}
  155.        RawArea     : ImgRect; {image segment area}
  156.        RawSize     : word;    {size of image segment; 0=empty buffer}
  157.      end;
  158.  
  159. const  {variable constants}
  160.       ImgFileError : boolean  = false; {a disk error of some sort occured}
  161.       ImgPath      : string80 = '';    {Path used to get to the image files}
  162.  
  163. const  {fixed constants}
  164.       MaxImageBuf  = 20;       {maximum allowed working buffers}
  165.       MaxRawImage  = 5000;     {default image buffer size in bytes}
  166.       ImgExpCount  = 5;        {Explode increment count}
  167.       ImgName      = 'SDI';    {Image file name (five digits are added)}
  168.       ImgNameTag   = '.IMG';   {Image file name tag (extent)}
  169.       ImgFileWrite = true;     {Open an image file for writing}
  170.       ImgFileRead  = false;    {Open an image file for reading}
  171.       ImgAreaWrite = true;     {Write to the image file}
  172.       ImgAreaRead  = false;    {Read from the image file}
  173.  
  174. var   {plain old variables}
  175.      ImgBuf  : array[0..MaxImageBuf] of ImageBufRec; {buffer info}
  176.      ImgDef  : array[0..MaxImageBuf] of ImageDefRec; {disk info}
  177.      ImgFile : file;
  178.  
  179. { ----------------------------------------------------------------------- }
  180. {                                  ImgType                                }
  181. { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
  182. { |bit|  3  |    2    |  1   |      0      | |  7   |   6   |  5  |  4  | }
  183. { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
  184. { | 1 | --- | Xpd/Mrg | Horz | Xpd/Left/Dn | | Disk |  EMS  | --- | --- | }
  185. { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
  186. { | 0 | --- |  Pull   | Vert | Mrg/Rght/Up | | Auto | NoEMS | --- | --- | }
  187. { +---+-----+---------+------+-------------+ +------+-------+-----+-----+ }
  188.  
  189. {Note: EMS is not currently implemented }
  190.  
  191. { *********************************************************************** }
  192. {                         misc support functions                          }
  193. { *********************************************************************** }
  194.  
  195. {--------------------------------------------------}
  196. {convert a word to a zero filled string}
  197. function z5str(W:word):string8;
  198. var S:string8;
  199. begin
  200.   str(W,S);
  201.   while length(S) < 5 do S := '0'+S;
  202.   z5str := S;
  203. end;
  204.  
  205. {--------------------------------------------------}
  206. {check for invalid Buf # }
  207. function ImageCheckOK(Buf:word):boolean;
  208. begin
  209.    if Buf > MaxImageBuf then
  210.    begin
  211.      ImageCheckOK := false;
  212.      ImageError := ImageBufNumTooBig;
  213.      Exit;
  214.    end;
  215.    ImageError := NoImageError;
  216.    ImageCheckOK := true;
  217. end;
  218.  
  219.  
  220. { *********************************************************************** }
  221. {                           Internal disk functions                       }
  222. { *********************************************************************** }
  223.  
  224. {$I-}
  225.  
  226. {--------------------------------------------------}
  227. {open an image file for reading or writing }
  228. function OpenImageFile(Buf:word; ImgWrite:boolean):boolean;
  229. var RawCount:word;
  230. begin
  231.   OpenImageFile := false;
  232.   if IOResult = 0 then {nop} ;
  233.   ImgFileError := true;
  234.   Assign(ImgFile,ImgPath+ImgName+z5str(ImgDef[Buf].ImageNum)+ImgNameTag);
  235.   if ImgWrite then
  236.   begin
  237.     ImgDef[Buf].MaxImgSize := ImgBuf[Buf].MaxBufSize;
  238.     rewrite(ImgFile,1);
  239.     BlockWrite(ImgFile, ImgDef[Buf], sizeof(ImgDef[Buf]), RawCount);
  240.     if (IOResult <> 0) or (sizeof(ImgDef[Buf]) <> RawCount) then Exit;
  241.   end
  242.   else
  243.   begin
  244.     reset(ImgFile,1);
  245.     BlockRead(ImgFile, ImgDef[Buf], sizeof(ImgDef[Buf]), RawCount);
  246.     if (IOResult <> 0) or (sizeof(ImgDef[Buf]) <> RawCount) then Exit;
  247.     if ImgDef[Buf].MaxImgSize > Imgbuf[Buf].MaxBufSize then
  248.     begin
  249.       if not AllocImageBuf(Buf,ImgDef[Buf].MaxImgSize) then Exit;
  250.     end;
  251.   end;
  252.   ImgFileError := false;
  253.   OpenImageFile := true;
  254. end;
  255.  
  256. {--------------------------------------------------}
  257. {close the image file 'cause we're done with it}
  258. function CloseImageFile:boolean;
  259. begin
  260.   CloseImageFile := false;
  261.   Close(ImgFile);
  262.   if (IOResult <> 0) then ImgFileError := true;
  263.   if ImgFileError then
  264.   begin
  265.     ImageError := ImageDiskError;
  266.     Exit;
  267.   end;
  268.   CloseImageFile := true;
  269. end;
  270.  
  271. {--------------------------------------------------}
  272. {read/write the image segment from/to disk }
  273. procedure RWrawImage(Buf:word; ImgWrt:boolean);
  274. var RawCount:word;
  275. begin
  276.    with ImgBuf[Buf],RawArea do
  277.    begin
  278.      RawSize := ImageSize(Xmin,Ymin,Xmax,Ymax);
  279.      if ImgWrt then
  280.      begin
  281.        GetImage(Xmin,Ymin,Xmax,Ymax,RawImage^);
  282.        BlockWrite(ImgFile, RawImage^, RawSize, RawCount);
  283.      end
  284.      else
  285.      begin
  286.        BlockRead(ImgFile, RawImage^, RawSize, RawCount);
  287.        PutImage(Xmin,Ymin,RawImage^,NormalPut);
  288.      end;
  289.      if RawCount <> RawSize then ImgFileError := true;
  290.      RawSize := 0;
  291.    end;
  292. end;
  293.  
  294. {--------------------------------------------------}
  295. procedure RWImageArea(Buf:byte; ImgWrt:boolean);
  296. var Area1,Area2:ImgRect;
  297. begin
  298.    with ImgBuf[Buf],ImgDef[Buf],RawArea do
  299.    begin
  300.      RawArea := ImgArea;
  301.      if WrkSize <= MaxBufSize then
  302.      begin
  303.        RWrawImage(Buf,ImgWrt);
  304.        Exit;
  305.      end;
  306.  
  307.      case (ImgType and $07) of
  308.  
  309.        $00 :  {Pull Down (Vertical)}
  310.        begin
  311.          Ymax := Ymin + pred(StepSize);
  312.          while Ymax < ImgArea.Ymax do
  313.          begin
  314.            RWrawImage(Buf,ImgWrt);
  315.            Ymin := Ymin + StepSize;
  316.            Ymax := Ymax + StepSize;
  317.          end;
  318.          Ymax := ImgArea.Ymax;
  319.          RWrawImage(Buf,ImgWrt);
  320.        end;
  321.  
  322.        $01 :  {Pull Up (Vertical)}
  323.        begin
  324.          Ymin := Ymax - pred(StepSize);
  325.          while Ymin > ImgArea.Ymin do
  326.          begin
  327.            RWrawImage(Buf,ImgWrt);
  328.            Ymin := Ymin - StepSize;
  329.            Ymax := Ymax - StepSize;
  330.          end;
  331.          Ymin := ImgArea.Ymin;
  332.          RWrawImage(Buf,ImgWrt);
  333.        end;
  334.  
  335.        $02 :  {Pull Right (Horizontal)}
  336.        begin
  337.          Xmax := Xmin + pred(StepSize);
  338.          while Xmax < ImgArea.Xmax do
  339.          begin
  340.            RWrawImage(Buf,ImgWrt);
  341.            Xmin := Xmin + StepSize;
  342.            Xmax := Xmax + StepSize;
  343.          end;
  344.          Xmax := ImgArea.Xmax;
  345.          RWrawImage(Buf,ImgWrt);
  346.        end;
  347.  
  348.        $03 :  {Pull Left (Horizontal)}
  349.        begin
  350.          Xmin := Xmax - pred(StepSize);
  351.          while Xmin > ImgArea.Xmin do
  352.          begin
  353.            RWrawImage(Buf,ImgWrt);
  354.            Xmin := Xmin - StepSize;
  355.            Xmax := Xmax - StepSize;
  356.          end;
  357.          Xmin := ImgArea.Xmin;
  358.          RWrawImage(Buf,ImgWrt);
  359.        end;
  360.  
  361.        $04 :  {Mrg Vertical}
  362.        begin
  363.          begin
  364.            Area1 := ImgArea;
  365.            Area2 := ImgArea;
  366.            Area1.Ymax := Area1.Ymin + pred(StepSize);
  367.            Area2.Ymin := Area2.Ymax - pred(StepSize);
  368.            while Area1.Ymax < Area2.Ymin do
  369.            begin
  370.              RawArea := Area1;
  371.              RWrawImage(Buf,ImgWrt);
  372.              Area1.Ymin := Area1.Ymin + StepSize;
  373.              Area1.Ymax := Area1.Ymax + StepSize;
  374.              RawArea := Area2;
  375.              RWrawImage(Buf,ImgWrt);
  376.              Area2.Ymin := Area2.Ymin - StepSize;
  377.              Area2.Ymax := Area2.Ymax - StepSize;
  378.            end;
  379.            RawArea := Area1;
  380.            while RawArea.Ymax < Area2.Ymax do
  381.            begin
  382.              RWrawImage(Buf,ImgWrt);
  383.              Ymin := Ymin + StepSize;
  384.              Ymax := Ymax + StepSize;
  385.            end;
  386.            Ymax := Area2.Ymax;
  387.            RWrawImage(Buf,ImgWrt);
  388.          end;
  389.        end;
  390.  
  391.        $05 :  {Xpd Vertical}
  392.        begin
  393.          begin
  394.            Area1 := ImgArea;
  395.            Area2 := ImgArea;
  396.            Area1.Ymax := ImgArea.Ymin+((ImgArea.Ymax-ImgArea.Ymin)shr 1);
  397.            Area1.Ymin := Area1.Ymax - pred(StepSize);
  398.            Area2.Ymin := succ(Area1.Ymax);
  399.            Area2.Ymax := Area2.Ymin + pred(StepSize);
  400.            while (Area1.Ymin>ImgArea.Ymin) and (Area2.Ymax<ImgArea.Ymax) do
  401.            begin
  402.              if (Area1.Ymin > ImgArea.Ymin) then
  403.              begin
  404.                RawArea := Area1;
  405.                RWrawImage(Buf,ImgWrt);
  406.                Area1.Ymin := Area1.Ymin - StepSize;
  407.                Area1.Ymax := Area1.Ymax - StepSize;
  408.              end;
  409.              if (Area2.Ymax < ImgArea.Ymax) then
  410.              begin
  411.                RawArea := Area2;
  412.                RWrawImage(Buf,ImgWrt);
  413.                Area2.Ymin := Area2.Ymin + StepSize;
  414.                Area2.Ymax := Area2.Ymax + StepSize;
  415.              end;
  416.            end;
  417.            RawArea := Area1;
  418.            if (RawArea.Ymax > ImgArea.Ymin) then
  419.            begin
  420.              RawArea.Ymin := ImgArea.Ymin;
  421.              RWrawImage(Buf,ImgWrt);
  422.            end;
  423.            RawArea := Area2;
  424.            if (RawArea.Ymin < ImgArea.Ymax) then
  425.            begin
  426.              RawArea.Ymax := ImgArea.Ymax;
  427.              RWrawImage(Buf,ImgWrt);
  428.            end;
  429.          end;
  430.        end;
  431.  
  432.        $06 :  {Mrg Horizontal}
  433.        begin
  434.          begin
  435.            Area1 := ImgArea;
  436.            Area2 := ImgArea;
  437.            Area1.Xmax := Area1.Xmin + pred(StepSize);
  438.            Area2.Xmin := Area2.Xmax - pred(StepSize);
  439.            while Area1.Xmax < Area2.Xmin do
  440.            begin
  441.              RawArea := Area1;
  442.              RWrawImage(Buf,ImgWrt);
  443.              Area1.Xmin := Area1.Xmin + StepSize;
  444.              Area1.Xmax := Area1.Xmax + StepSize;
  445.              RawArea := Area2;
  446.              RWrawImage(Buf,ImgWrt);
  447.              Area2.Xmin := Area2.Xmin - StepSize;
  448.              Area2.Xmax := Area2.Xmax - StepSize;
  449.            end;
  450.            RawArea := Area1;
  451.            while RawArea.Xmax < Area2.Xmax do
  452.            begin
  453.              RWrawImage(Buf,ImgWrt);
  454.              Xmin := Xmin + StepSize;
  455.              Xmax := Xmax + StepSize;
  456.            end;
  457.            Xmax := Area2.Xmax;
  458.            RWrawImage(Buf,ImgWrt);
  459.          end;
  460.        end;
  461.  
  462.        $07 :  {Xpd Horizontal}
  463.        begin
  464.          begin
  465.            Area1 := ImgArea;
  466.            Area2 := ImgArea;
  467.            Area1.Xmax := ImgArea.Xmin+((ImgArea.Xmax-ImgArea.Xmin)shr 1);
  468.            Area1.Xmin := Area1.Xmax - pred(StepSize);
  469.            Area2.Xmin := succ(Area1.Xmax);
  470.            Area2.Xmax := Area2.Xmin + pred(StepSize);
  471.            while (Area1.Xmin > ImgArea.Xmin) and (Area2.Xmax < ImgArea.Xmax) do
  472.            begin
  473.              if (Area1.Xmin > ImgArea.Xmin) then
  474.              begin
  475.                RawArea := Area1;
  476.                RWrawImage(Buf,ImgWrt);
  477.                Area1.Xmin := Area1.Xmin - StepSize;
  478.                Area1.Xmax := Area1.Xmax - StepSize;
  479.              end;
  480.              if (Area2.Xmax < ImgArea.Xmax) then
  481.              begin
  482.                RawArea := Area2;
  483.                RWrawImage(Buf,ImgWrt);
  484.                Area2.Xmin := Area2.Xmin + StepSize;
  485.                Area2.Xmax := Area2.Xmax + StepSize;
  486.              end;
  487.            end;
  488.            RawArea := Area1;
  489.            if (RawArea.Xmax > ImgArea.Xmin) then
  490.            begin
  491.              RawArea.Xmin := ImgArea.Xmin;
  492.              RWrawImage(Buf,ImgWrt);
  493.            end;
  494.            RawArea := Area2;
  495.            if (RawArea.Xmin < ImgArea.Xmax) then
  496.            begin
  497.              RawArea.Xmax := ImgArea.Xmax;
  498.              RWrawImage(Buf,ImgWrt);
  499.            end;
  500.          end;
  501.        end;
  502.  
  503.  
  504.      end; {case}
  505.    end; {with}
  506. end;
  507.  
  508. {--------------------------------------------------}
  509. {write an image to buffer/disk }
  510. function WriteImage(Buf:word):boolean;
  511. var Iss,Ssc:word;
  512. begin
  513.    WriteImage := false;
  514.    with ImgBuf[Buf],ImgDef[Buf] do
  515.    begin
  516.      with ImgArea do
  517.      begin
  518.        if ImgType and $02 = $00 then  {- $00=vertical action, $02=horizontal -}
  519.        begin
  520.          Ssc := Ymax-Ymin;                             {total image rows used}
  521.          Iss :=  ImageSize(Xmin,Ymin,Xmax,succ(Ymin)); {image row size (bytes)}
  522.        end
  523.        else                        {Ssc= total row count}
  524.        begin                       {Iss= row size in bytes}
  525.          Ssc := Xmax-Xmin;
  526.          Iss := ImageSize(Xmin,Ymin,succ(Xmin),Ymax);
  527.        end;
  528.        if MaxBufSize < Iss then                 {gotta have at least one rows}
  529.          if not AllocImageBuf(Buf,Iss) then Exit;  {worth of buffer space}
  530.        StepSize := MaxBufSize div Iss;
  531.        StepCount := Ssc div StepSize;
  532.        if Ssc mod StepSize > 0 then inc(StepCount);
  533.      end;
  534.  
  535.      if OpenImageFile(Buf,ImgFileWrite) then
  536.         RWImageArea(Buf,ImgAreaWrite);
  537.  
  538.      if not CloseImageFile then
  539.      begin
  540.        Erase(ImgFile);
  541.        RawSize := 0;
  542.        if IOResult <> 0 then {nop} ;
  543.        Exit;
  544.      end;
  545.    end;
  546.    WriteImage := true;
  547. end;
  548.  
  549.  
  550. {--------------------------------------------------}
  551. {Read an image from the disk}
  552. function ReadImage(Buf:word; ImgClr:boolean):boolean;
  553. begin
  554.    ReadImage := false;
  555.    with ImgBuf[Buf],ImgDef[Buf] do
  556.    begin
  557.      if OpenImageFile(Buf,ImgFileRead) then
  558.        RWImageArea(Buf,ImgAreaRead);
  559.  
  560.      if not CloseImageFile then Exit;
  561.      if ImgClr then Erase(ImgFile);
  562.      if IOResult <> 0 then Exit;
  563.    end;
  564.    ReadImage := true;
  565. end;
  566.  
  567. {$I+}
  568.  
  569.  
  570. { *********************************************************************** }
  571. {                         External access functions                       }
  572. { *********************************************************************** }
  573.  
  574. {-------------------------------------------------------------------------}
  575. {                          AllocImageBuf                                  }
  576. {-------------------------------------------------------------------------}
  577. {This allocates a buffer for use with an image. You must call this before}
  578. {you can use an image buffer if you want it to be a different size than}
  579. {the default. If the buffer is not allocated at the time SaveImage is}
  580. {called, then the default sized buffer will be allocated.}
  581.  
  582. function AllocImageBuf(Buf:word; Size:word):boolean;
  583. begin
  584.   AllocImageBuf := false;
  585.   if not ImageCheckOK(Buf) then Exit;
  586.   with ImgBuf[Buf] do
  587.   begin
  588.     if RawImage <> nil then
  589.       freemem(RawImage,MaxBufSize);
  590.     RawSize := 0;
  591.     MaxBufSize := 0;
  592.     If MaxAvail < Size then Exit;
  593.     GetMem(RawImage,Size);
  594.     MaxBufSize := Size;
  595.     ImgDef[Buf].MaxImgSize := Size;
  596.   end;
  597.   AllocImageBuf := true;
  598. end;
  599.  
  600.  
  601. {-------------------------------------------------------------------------}
  602. {                        ReleaseImageBuf                                  }
  603. {-------------------------------------------------------------------------}
  604. {This releases the image buffer used with an image. You can call this to}
  605. {pick up heap space if you don't need the buffer anymore. As always,}
  606. {if the buffer is not allocated at the time SaveImage is called, then}
  607. {the default sized buffer will be allocated. Thus if you don't mind a}
  608. {slight slow down in the image process, you could call this after calling}
  609. {DisplayImage to keep heap usage to a minimum.}
  610.  
  611. function ReleaseImageBuf(Buf:word):boolean;
  612. begin
  613.   ReleaseImageBuf := false;
  614.   if not ImageCheckOK(Buf) then Exit;
  615.   with ImgBuf[Buf] do
  616.   begin
  617.     if RawImage <> nil then
  618.       freemem(RawImage,MaxBufSize);
  619.     RawImage := nil;
  620.     RawSize := 0;
  621.     MaxBufSize := 0;
  622.   end;
  623.   ReleaseImageBuf := true;
  624. end;
  625.  
  626.  
  627. {-------------------------------------------------------------------------}
  628. {                          SetImagePath                                   }
  629. {-------------------------------------------------------------------------}
  630. {This sets a new path to be used for the image files. If the path does not}
  631. {exist, then it will be created. If an error occurs the function returns }
  632. {a false condition. The Default path is to use the current default directory}
  633. {(i.e. no path).}
  634.  
  635. {$I-}
  636.  
  637. function SetImagePath(Path:string):boolean;
  638. var TPath:string;
  639. begin
  640.   SetImagePath := false;
  641.   GetDir(0,TPath);
  642.   ChDir(Path);
  643.   if IOResult <> 0 then MkDir(Path);
  644.   ChDir(TPath);
  645.   if IOResult = 0 then ImgPath := Path+'\';
  646.   if IOResult <> 0 then Exit;
  647.   SetImagePath := true;
  648. end;
  649.  
  650. {$I+}
  651.  
  652. {-------------------------------------------------------------------------}
  653. {                          FlushImage                                     }
  654. {-------------------------------------------------------------------------}
  655. {if there is an image in the buffer, flush it to disk}
  656.  
  657. function FlushImage(Buf:word):boolean;
  658. var RawCount : word;
  659. begin
  660.   FlushImage := false;
  661.   if not ImageCheckOK(Buf) then Exit;
  662.   with ImgBuf[Buf] do
  663.   begin
  664.     if RawSize > 0 then
  665.     begin
  666.       if OpenImageFile(Buf,ImgFileWrite) then
  667.       begin
  668.         BlockWrite(ImgFile, RawImage^, RawSize, RawCount);
  669.         if RawCount <> RawSize then ImgFileError := true;
  670.       end;
  671.       RawSize := 0;
  672.       if not CloseImageFile then Exit;
  673.     end;
  674.   end;
  675.   FlushImage := true;
  676. end;
  677.  
  678.  
  679. {-------------------------------------------------------------------------}
  680. {                         DeleteImage                                     }
  681. {-------------------------------------------------------------------------}
  682. {This deletes images in the buffer and on disk. Any image that might}
  683. {be in the buffer is lost. Any image disk file that exists by the given}
  684. {number will be deleted. If an error occurs during the delete, such }
  685. {as the requested image is not found, the function will return false.}
  686.  
  687. {$I-}
  688.  
  689. function DeleteImage(Img,Buf:word):boolean;
  690. var RawCount : word;
  691. begin
  692.   DeleteImage := false;
  693.   if not ImageCheckOK(Buf) then Exit;
  694.   with ImgBuf[Buf] do
  695.   begin
  696.     RawSize := 0;
  697.     if OpenImageFile(Buf,ImgFileWrite) then {nop} ;
  698.     if CloseImageFile then Erase(ImgFile);
  699.     RawSize := 0;
  700.     if ImgFileError or (IOResult <> 0) then Exit;
  701.   end;
  702.   DeleteImage := true;
  703. end;
  704.  
  705. {$I+}
  706.  
  707. {-------------------------------------------------------------------------}
  708. {                          SaveImage                                      }
  709. {-------------------------------------------------------------------------}
  710. { Saves the screen image under the box. This can be called to save the}
  711. { screen image before writing the box to the screen. Use DisplayImage to}
  712. { restore the image. The lower four bits of "Style" controls the special}
  713. { effects. The upper four bits of Style controls the disk/buffer action.}
  714. { If bit 7 is on, then the image will always be forced to disk.}
  715. { If bit 7 is off, then the image will stay in the buffer if it can.}
  716. { If the image is bigger than the buffer then it is flushed to disk anyway.}
  717. { Note: special effects only operate when the image is read from the disk.}
  718. { In fact it works because it uses the disk buffering as an inherent part}
  719. { of the effects control. EMS buffering is not currently implemented.}
  720. { 0=Pull Down, 1=Pull Up, 2=Pull Right, 3=Pull Left, 4=Merge Vertical,}
  721. { 5=Expand Vertical, 6=Merge Horizontal, 7=Expand Horizontal.}
  722.  
  723. function SaveImage(Img,Buf:word; x1,y1,x2,y2:integer; Style:word):boolean;
  724. begin
  725.    SaveImage := false;
  726.    if not ImageCheckOK(Buf) then Exit;
  727.    if not FlushImage(Buf) then Exit;  {flush image buffer}
  728.    if ImgBuf[Buf].RawImage = nil then
  729.      if not AllocImageBuf(Buf,MaxRawImage) then Exit;
  730.  
  731.    with ImgDef[Buf],ImgArea do
  732.    begin
  733.      ImageNum := Img;
  734.      ImgType := Style;
  735.      Xmin := x1;
  736.      Ymin := y1;
  737.      Xmax := x2;
  738.      Ymax := y2;
  739.      ImgBuf[Buf].RawArea := ImgArea;
  740.      StepSize := Ymax-Ymin;
  741.      StepCount := 1;
  742.      WrkSize := ImageSize(Xmin,Ymin,Xmax,Ymax);
  743.      if WrkSize = 0 then WrkSize := $ffff;
  744.  
  745.      if (ImgType and $80 = 0) and (WrkSize < ImgBuf[Buf].MaxBufSize) then
  746.      begin    {- save image to heap buffer -}
  747.        ImgBuf[Buf].RawSize := WrkSize;
  748.        GetImage(Xmin,Ymin,Xmax,Ymax,ImgBuf[Buf].RawImage^);
  749.      end
  750.      else
  751.      begin    {- write the image to disk -}
  752.        if not WriteImage(Buf) then Exit;
  753.      end;
  754.    end;
  755.    SaveImage := true;
  756. end;
  757.  
  758. {-------------------------------------------------------------------------}
  759. {                             DisplayImage                                }
  760. {-------------------------------------------------------------------------}
  761. { Restores a previously saved box screen image. See SaveImage. }
  762. { If the desired image is in the buffer, then it comes from there.}
  763. { Otherwise the disk is searched for the desired image.}
  764. { If ImgClr is true, then the image buffer/file will be erased after}
  765. { the image has been displayed.}
  766.  
  767. function DisplayImage(Img,Buf:word; ImgClr:boolean):boolean;
  768. begin
  769.    DisplayImage := false;
  770.    if not ImageCheckOK(Buf) then Exit;
  771.  
  772.    with ImgBuf[Buf] do
  773.    begin
  774.      if (Img = ImgDef[Buf].ImageNum) and (RawSize <> 0) then
  775.      begin
  776.        PutImage(RawArea.Xmin,RawArea.Ymin,RawImage^,NormalPut);
  777.        if ImgClr then RawSize := 0;
  778.      end
  779.      else
  780.      begin
  781.        if not FlushImage(Buf) then Exit;  {flush image buffer if not same}
  782.        ImgDef[Buf].ImageNum := Img;
  783.        if not ReadImage(Buf,ImgClr) then Exit;  {read the requested image}
  784.      end;
  785.    end;
  786.    DisplayImage := true;
  787. end;
  788.  
  789.  
  790. { *********************************************************************** }
  791. { initialization }
  792. begin
  793.   fillchar(ImgBuf,sizeof(ImgBuf),0);
  794.   fillchar(ImgDef,sizeof(ImgDef),0);
  795. end.
  796.  
  797.