Creating Fax Files

One of the strong points in Async Professional is the ability to add fax capabilities to your application easily and with a high degree of reliability.  There is quite a bit more than simply sending and receiving faxes.

To get this document rolling, let's talk about what a fax is.  Technically, a fax is a system of transmitting and reproducing graphic matter by means of signals sent over telephone lines.  When a document is faxed, the document image is converted to individual compressed raster lines, transmitted over the phone line, received on the other end, uncompressed, and then reassembled into a close representation of the original document.  In APRO, the graphic matter is in our proprietary APF (Async Professional Fax) format.  When we transmit a fax, we convert an APF into compressed scan lines and transmit those; when we receive a fax, we assemble the compressed scan lines into an APF. 

An APF is created with the TApdFaxConverter component or by printing to the APRO fax printer driver.  The TApdFaxConverter component converts several popular graphics formats or ASCII text into an APF.  This component natively supports bitmaps, TIFF, PCX, DCX, ASCII text and TBitmaps.  Not just any bitmap, TIFF, PCX, DCX or ASCII text file, we do have a few limitations.  The graphics formats require true monochrome (not gray-scale), and the compression options that we support are somewhat limited (it's best to not use compression if you can get away from it).  ASCII text files need to be properly formatted (line breaks and page breaks) before they are converted, and the maximum length for each line is 255 chars.  If the document format you want to convert is not directly supported, you can convert it to something we do support or print the document to our fax printer driver.

Image conversion

 

Converting a document into a faxable APF is pretty easy to do, provided you know how to do it.  If the document that you want to convert is a bitmap, TIFF, PCX, DCX, or ASCII text file, or a TBitmap, use the TApdFaxConverter component.  If the document is anything else, you will need to either convert it to one of the previously mentioned formats or print it to the fax printer driver.  All it takes to create one of the natively supported formats is three lines of code assuming that you know the image/file format:

  { tell the converter which file to convert }

  ApdFaxConverter1.DocumentFile := 'bmp2fax.bmp';

  { tell the converter which format to convert from }

  ApdFaxConverter1.InputDocumentType := idBmp;

  { tell the converter to convert the file }

  ApdFaxConverter1.ConvertToFile;

The APF file that we create will be the DocumentFile with an APF extension.  You can change that by setting the OutFileName property.

That seems very simple, and it is.  However, there is always the chance that you have a graphic that isn't one of the ones we support directly.  Fortunately, most popular graphics formats can be loaded in a TPicture, and the TPicture supports bitmaps, and APRO supports bitmaps.  So, all you need to do is load the image file into the TPicture, assign the TPicture.Graphic to a bitmap, and then convert that bitmap.

var

  Picture : TPicture;

  Bitmap : TBitmap;

begin

  if OpenPictureDialog1.Execute then begin

    Picture := nil;

    Bitmap := nil;

    try

      Picture := TPicture.Create;

      Picture.LoadFromFile(OpenPictureDialog1.FileName);

      Bitmap := TBitmap.Create;

      Bitmap.Assign(Picture.Graphic);

      ApdFaxConverter1.OutFileName := ChangeFileExt(OpenPictureDialog1.FileName, '.apf');

      ApdFaxConverter1.ConvertBitmapToFile(Bitmap);

    finally

      Bitmap.Free;

      Picture.Free;

    end;

  end;

end;

If you have Delphi/C++Builder 3 or later, you can add JPG support using this technique simply by adding the JPeg unit to your uses clause/include list.  Other graphics formats can be supported in the same manner using other third-party graphics classes, as long as they register their format with the TPicture, the code above can convert it to an APF.

ASCII and thou will receive the fax...

Converting an ASCII text document to an APF is a little more involved.  The TApdFaxConverter will not wrap the text; we'll take each line in your text file and render them separately without adding line breaks.  To add the appropriate line breaks, you can use a hidden TMemo (which has built-in support for wrapping lines).  Create the TMemo, size it according to a fax page size, load the ASCII text file, save the wrapped text from the TMemo, and then convert that.  The only problem with using the TMemo to format our text document is that it doesn't add the CR/LF at the end of each of it's Lines, we have to do that ourselves.  Here's one way to do it:

var

  Memo : TMemo;

  I : Integer;

begin

  {

    This method creates an invisible TMemo, resizes the memo to roughly estimate

    an APF page width, loads a text file, inserts line breaks, and converts the

    wrapped text to an APF

  }

  Memo := TMemo.Create(Self);

  try

    Memo.Visible := False;

    Memo.Parent := Self;

    Memo.WordWrap := True;

    { rough guesstimation, APF is 1728 pixels wide, - left/right margins,

      then convert screen ppi to fax ppi (198ppi) is about 1000 pixels. Your

      mileage will vary depending on the screen's PPI }

    Memo.Width := 1000;

    Memo.Font := ApdFaxConverter1.EnhFont;

    Memo.Lines.LoadFromFile('e:\sales.txt');

    { insert our line breaks }

    for I := Memo.Lines.Count - 1 downto 0 do

      if Length(Memo.Lines[I]) > 0 then

        Memo.Lines[I] := Memo.Lines[I] + #13#10;

    Caption := IntToStr(Memo.Lines.Count);

    { create temp file with our line-breaks }

    Memo.Lines.SaveToFile('e:\temp.txt');

    ApdFaxConverter1.InputDocumentType := idTextEx;

    ApdFaxConverter1.DocumentFile := 'e:\temp.txt';

    ApdFaxConverter1.OutFileName := 'e:\sales.apf';

    ApdFaxConverter1.ConvertToFile;

  finally

    { delete our temp file }

    if FileExists('e:\temp.txt') then

      DeleteFile('e:\temp.txt');

    Memo.Free;

  end;

end;

One of the benefits of formatting an ASCII text document like this is you can specify which font you will be using and have the line breaks inserted at the correct, proportional location.

When all else fails, print it...

If your document can't be converted to an APF with the TApdFaxConverter, or it can't be converted to something the TApdFaxConverter supports, you can still make an APF using the fax printer drivers.  The fax printer drivers contain an internal fax converter that converts the print data from an application into an APF.  Anything that can be printed to a regular paper printer can be converted to an APF, which lets you fax Microsoft Word documents, database reports, RTF, HTML, PDF, etc.  The application that understands the document format will do the converting for us by rendering the page with the Windows printer subsystem, and we'll convert that to an APF.

If you have a component that understands the file format, and it has a print method, you can print programmatically.  When printing programmatically, you need to find our printer driver then select it.  APRO ships two printer drivers, one for 16-bit printer subsystems (Win3.1x, Win9x, and ME) and another for 32-bit printer subsystems (WinNT and 2K).  These printer drivers have different names once installed, so you'll want to try to find both of them.  The following snippet shows how to find our printer driver, select it, and then print an RTF using a TRichEdit.

var

   Device, Name, Port: array[0..100] of Char;

   DevMode: THandle;

   X : Integer;

begin

  with Printer do begin

    { see if the 16-bit printer is installed }

    X := Printers.IndexOf('Print to Fax on PRINTFAX:');

    if X = -1 then

      { it wasn't, see if the 32-bit printer is installed }

      X := Printers.IndexOf('APF Fax Printer');

    if X = -1 then begin

      { it wasn't, bail out }

      ShowMessage('APRO fax printer not found');

      Exit;

    end;

    PrinterIndex := X;

    { force the TPrinter to use our printer capabilities }

    GetPrinter(Device, Name, Port, DevMode);

    SetPrinter(Device, Name, Port, 0);

    end;

  { let the TRichEdit do the conversion }

  RichEdit1.Print('RichPrint');

  end;

end;

 

If you do not have a component that can print your document, you can still do it programmatically through COM or some shell commands, but that is beyond the scope of this tech tip.

When the printer driver begins converting the image data from the printer subsystem, the TApdFaxDriverInterface.OnDocStart event is generated; when the printer driver completes the conversion, and the APF is ready, the TApdFaxDriverInterface.OnDocEnd event is generated.  You can change the name of the resulting APF by changing the TApdFaxDriverInterface.FileName property before the OnDocStart event exits.  If you do not change the name, the resulting APF will be saved as 'C:\DEFAULT.APF'.

What next?

The primary reason for creating an APF file is to fax it.  The Developer's Guide and Reference Guide both have several examples and code snippets to illustrate how to actually send the APF that you've created. 

This site is not affiliated, endorsed, or otherwise associated with the entity formerly known as TurboPower Software. The owners and maintainers of Aprozilla.com were merely meager employees of the aforementioned organization, providing this site out of the pure goodness of their collective hearts. SourceForge.net Logo

Last updated: July 22, 2003.