Group number and name: Group 4: Phonetics
Team members:  Félix Rodríguez and Daniel Switkin
Task number and name:  9 - Application (FaxToGif)
1. What did you set out to do? (1-2 pages) Use a figure and accompanying text to describe what you set out to do. You can reuse part of your first report if you wish. You should have sufficient detail so that someone who is not familiar with the project would still be able understand the scope of your work. For instance, imagine giving this to a friend who is not in the class--write something that this person would be able to understand without having to ask you for help.

Our main goal for this project was to set up a computer with a fax modem that can receive and manage faxes for multiple Internet users. Specifically, it would be able to do this by acting as a server, waiting for incoming faxes in a loop. As soon as it finds an incoming fax, it takes the incoming image and converts to the web standard GIF format, and passes it along to the intended recipient of the fax. This person is notified by email, and sent a link to a web page where all of their previous faxes have been archived and organized. If the recipient cannot be determined for any reason, the fax is saved to a lost and found location. Our software allows the user to stay in touch and check his or her faxes from any location with a web browser. Additionally, it provides a measure of security since each user’s personal directory on the web server is protected with their password.

Our system provides another service for users of the voice over IP project, and is compatible in that a five digit extension acts as both the user’s voice number and their fax number. It runs automatically and unattended, able to receive and process faxes 24 hours a day. It eliminates the paper shuffle which is so common in offices today, by handling all incoming transmissions electronically. It also bypasses the need for a person to physically retrieve new faxes, determine the recipient, and deliver it to a mailbox or an office. The software is designed to be easy to administer, and provides feedback to the management group as to the number of faxes each user has received.

Below is a diagram of the path a typical incoming fax takes on its way to its destination, and the way in which our system interfaces with a preexisting commercial application called FaxWizard. The scenario is that upon the transmission of a fax to the computer’s phone line, FaxWizard answers the call and saves the data as a TIFF. At this point our software detects a new fax waiting to be processed, and takes the steps outlined.

2. What did you actually accomplish? (2-3 pages) Write down exactly what you managed to get done by the time of the demo. Did you achieve all the goals you set out to do? Did you do something that you didn't expect to be doing when you started?

Our complete program actually managed to accomplish all of what we had originally set out to do. Although the implementation changed greatly from our original idea of how we were going to do this, we have satisfied the complete specification, and in terms of organization we actually did much more than we had originally planned.

As soon as we run our program, the first thing that happens is that it calls a configuration file function that reads in all the directories and settings from "config.txt". This was an added feature that we originally did not plan on, but ended up adding because it made the program much more portable between differing setups without the need to recompile.

Once this is done, we go into the main loop which basically polls the incoming fax directory for new files. Incoming faxes are sent by our helper program, a commercial piece of software called FaxWizard. Although we would have loved to actually write code that simulated this software, we simply could not communicate with Java only. Thus if we actually wanted to do this we would have had to write part of our code in C, and used Widows TAPI. This is obviously too big a task, because not only would we have been forced to learn TAPI, but also the exact handshaking and error control protocol of faxes, not to mention the fact that we found no free documentation of these protocols on the web. So, FaxWizard was the obvious choice. The tricky part about this decision, however, is that we are in danger of conflicting with FaxWizard if we try accessing the file before it is finished. For this we implemented a timing and file size mechanism so that if the file hasn’t grown in a certain interval, then we assume that the fax has been completed and we continue the process. This works fine, because the timeout is larger than the fax transmission timeout, so it must be that the fax has been sent.

Now that we have a fax file received, we send it through the TIFF class to be decoded. This class reads the header of the file, all the Image File Directories (the TIFF way to specify attributes of a bitmap), and moves to the next image in the file, if there is more than one (for multipage faxes). Then it goes into the CCITT decoder and turns all the encoded bits into an unencoded two dimensional array. The class also takes care of the TIFF’s big-endian way of storing data, converting to Intel’s little-endian standard.

Now that we have the decoded page, we attempt to find out who the recipient of the fax is. Our solution to the dilemma of determining this (detailed below) was unexpected and interesting. We wrote a scantron program to analyze the cover sheet of the fax transmission and determine the recipient. This involves a special cover page, which was designed as a graphic and saved into a Microsoft Word file for easy download and printing. The user simply bubbles in the extension of the person they are trying to reach, along with writing in the usual fax cover page info. The scantron software is very robust. It is insensitive to the size and position of the supplied bubble sheet, allowing for different printing sizes of the cover sheet. It is also very immune to noise, and does not seem affected by the typical bit errors and line noise encountered in fax transmissions, or stray marks typical of user error. Another feature we incorporated was ensuring that an unreadable page would not crash the software. It is designed to return ‘00000’ on a blank cover sheet. This code, or any other which is invalid will simply result in an error message from Directory Services. When this happens, we save the incoming fax to a lost and found directory, where anyone can view it and/or an administrator can forward the fax manually to the correct user.

Now that the user is determined (or at least it is determined that the file is lost), the program calls the web update function. This function, another addition that we hadn’t originally planned upon, checks if the recipient has a directory in the web server. If not, the directory is created and the home page is updated with the new fax user. Then it goes into the user’s directory and checks if "default.htm" exists. If not, the software creates it with a header to make it look nice, and then adds an entry for the current fax with a link to the image. Each fax is annotated with the current date and time, and mutipage faxes are numbered sequentially. Overall we produce a complete directory system with HTML files for every user and a top level navigation page that works very well. Ideally these directories would be password protected and readable only by the owner of the faxes, as well as administrators.

Next, we send the bits to the GIF encoder that we wrote so that the image can be displayed on the web. The encoder outputs a black and white GIF image of the fax received to wherever the configuration file points to, which is typically a subtree of the webserver’s main directory. Since most faxes contain more than just the cover page, our program then loops through the rest of the pages, decoding, updating the HTML, and encoding the GIF, until there are no more pages left.

Finally, we open up a sockets connection to the Mail Server pointed to by the configuration file (it is currently set to cornell.edu). We then manually send a mail from FaxServer@(server) to the user notifying him/her that there is a new fax in their directory and point to where their directory is located, in case they do not know. To round things off, we also delete the fax that has been processed, and go back to reading the directory where incoming faxes could be located.

For ease of administration we also provide a tie-in to the interface our management team established. Upon receiving a query from them, we do a live count of how many user directories there are and how many faxes reside in each one. This seamlessly integrates with their GUI and provides important statistics back to the main monitoring console, and ensures that this information is always current.

3. Problems: (1-2 pages) It is possible that you did not actually accomplish what you set out to do :-( If so, why? What problems did you run into? Include both technical problems, and problems in coordinating your work with others. Be as specific as you can about technical problems. This is the only way we have to determine whether you really tried to solve the problem, instead of just giving up with token effort.

One item that we wanted to add, but simply could not get the time to finish, was automatic permissions. As we have already specified, each fax recipient gets their own directory with all its faxes. Since every fax recipient should already have an account on the computer, as they are registered with the system, we wanted to write a script using Windows Scripting Host that automatically set the user’s permissions when we created the directory. This would have been a really nice plus, but unfortunately we didn’t have the time to learn the scripting host from scratch and implement this. On the other hand, we didn’t actually leave this out because this wasn’t a part of the original specs. The idea just came into our minds as we expanded the organization of the fax locations from the original one directory approach to its final implementation.

We had two big time wasters throughout most of the project that had us very much stumped, and took a very considerable amount of time to get resolved. The first problem was reading the actual fax image. The encoded bits coming in from FaxWizard, the program that we used to read the faxes from the faxmodem, are saved to disk almost exactly as they are read from the fax, with the small exception of a 2 byte header and an extra tag to include copyright information. Thus we had to do research to determine the exact format that faxes are ultimately saved in. Once we found it, it turned out that this format is very close to a standard TIFF file, which allowed us to begin writing a decoder for it.

This is where the problems arose. First, the decoded bits, although close to a TIFF file, aren’t completely the same, so it took some time to figure out what the differences were. Second, even after we were able to do that, the TIFF Class F format, which is supposedly the most common fax standard out there, isn’t a real TIFF supported format, and so the official documentation does not include the extra information. The CCITT group did not have the files ready for us, due to the fact that they charge an unreasonable amount of money to actually read their standards. Also, this format includes a large amount of error control, which made it very hard to decode correctly.

Once we finally managed to correctly decode the pseudo-TIFF file, more problems arose when we tried multiple pages, due to the fact that the files handled multiple pages in the same TIFF file, while faxes handle it slightly differently. In the end, the entire TIFF problem was resolved, but the amount of time that it took was triple what we had allocated for it.

The second problem that we faced was our attempt at figuring out the correct recipient of the fax. Our problem here was that we kept switching between a number of different ideas, all with their own technological hurdles. For us, it seemed that every possible way to do this was marred with technological difficulties that would have been amazingly hard to solve in the span of the project.

We began by trying to capture tones from the fax keypad at the internal faxmodem. It seemed that JTAPI would be perfect for this function. However, it turns out that there is no JTAPI implementation for personal faxmodems, just for more sophisticated hardware like the gateway. We also considered switching to C++ and using Windows NT’s native TAPI. This also turned out to be impossible. Not only was the documentation immense and convoluted, neither of us has experience talking to Microsoft APIs, and this method would have required building several classes and at least one DLL. Even had this worked, it is possible that TAPI would require a voice faxmodem for these functions, which we didn’t have.

The second major option was to do the tone detection at the gateway, and then somehow pass the call on to the internal faxmodem. While there was a menu system in place to detect DTMF tones, it turned out that transferring the call was immensely difficult. If we had done this through the gateway, it would have meant digitizing the incoming call and then reconverting to analog to send out the fax on another phone line. This would not only tie up two phone lines which might not always be available, but also means adding significant noise to the transmission and risks corrupting the fax in the process. It also would make unreasonable demands on our gateway team, which unfortunately was only one person. The only other solution in this area was to switch the call at the PBX after grabbing the tones at the gateway. We discovered this less than a week before the final demo, and again it was unreasonable to ask the switching team to add this functionality. The whole idea of doing tone detection at the gateway is limiting to start with. It means that a user cannot send a fax from a computer, since he can’t use a keypad and then switch the call over to fax. It also makes assumptions about the timing of when the call is switched to the correct phone line our end, compared to when the user switches from voice to fax mode at their end.

In the end, we went with the scantron approach described above which does not suffer from either of these difficulties. It is more usable, conforming to a pattern of sending a cover sheet which people are already used to. It was also an economic decision because it was the best working solution within limited time. It caused less inconvenience for other groups, which in the real world would have prevented the shipping date of the software from slipping. Our other contender in this category was to use a commercial OCR product. However we were unable to find a software package which could be run as a command line program and reliably return an email address.

4. What you learnt: (1-2 pages) What did you learn by working on the project? Include details on technical things you learnt, as well as what you learnt about dealing with large projects, collaborating with other busy people, and dealing with other coursework.

In terms of technical details, we learned quite a bit. First of all, there were the specific details on how TIFFs and GIFs work. Since we had to write a decoder and an encoder, respectively, we are now very familiar with both image types. Expanding from this, we were also forced to learn the CCITT Huffman encoding scheme, which is ideal for fax images due to a very large compression ratio, and the standard way that Fax TIFFs are sent. For GIF this meant an understanding of LZW variable-length bit code compression, which is applicable to other on-the-fly compression formats like ZIP. Also related to this, we have learned pretty much exactly what faxes do to communicate between each other, with the one exception of the initial handshake, because we let our external FaxWizard program take care of this. There is very little documentation about this specific part of faxing in the free areas of the web.

Continuing on the specific technical aspects, we have also learned much about pattern recognition and dealing with imperfect bitmap data. Specifically related to our scantron-type bubble sheet and the methods that we used to scan the results off them. It was an interesting challenge to make the software independent of scale and position, which in turn meant designing the bubble sheet to give reliable information. For instance, the feature we used to measure scale and aspect ratio needed to be reliable, because the digit detection depended on it. An advantage of incorporating this flexibility was that we were able to receive faxes in both standard and fine resolution without specifically adding this ability. The nature of the scaling software dealt with these differences automatically. It was also necessary to engineer margin for slight rotation and a reasonable amount of noise. This was accomplished by searching slightly larger areas than the expected size of a feature on the page, and using a scanning technique which found the most likely candidate and then continued searching to avoid local maxima.

On a more abstract note, the knowledge that we have gained in the Java language has been quite immense. We have had very little experience with the language before this project, and writing this 1300+ line project has certainly made us feel much more comfortable when dealing with the language. There were significant challenges here, especially in the TIFF and GIF code where Java’s lack of unsigned data types caused quite a bit of difficulty. Usually the solution was to move to a larger data type, but in some instances we forced values into smaller data types (like putting 200 into a signed 8 bit integer).

When dealing with this large project and collaborating with other people, the key for us was picking the right divisions of work, and trying to be as independent as possible for as long as possible. Taking full advantage of the object oriented capabilities of Java, we tried to split our work between logical classes that could be run and tested independently of each other. When we needed integration with some specific part, the trick was to write a dummy code that output some correct value and use that until the final code was available. It was imperative that one of us was able to code whenever it was possible, independent on whether the other had 5 projects and 3 midterms due the next day. It was also important that we both worked on different classes at a time, so it wouldn’t be hard to join up code, and possibly incur conflicts between us. In fact we accomplished this quite well, only needing to exchange e-mails and meet for small amounts of time during most of the project. Of course, in the last week the integration does come into place, but as long as the code was sturdy we had no problems with that.

5. What would you do differently next time: (1-2 pages) Everyone makes mistakes. But good learners don't repeat mistakes, they make all new ones! This project gave you a lot of freedom to make mistakes. What will you look out for the next time you undertake a large collaborative project?

Our biggest mistake was the fact that we spent such a large amount of time trying to overcome the hardest technological barriers first. Our first month was spent basically trying to solve the hardest problems, and so we left the smaller pieces for later. I think ideally it would have been better if we had done it in reverse, or at least in a fairly parallel manner, so that way we would have had the overall structure much faster. Although it wasn’t too bad, we did spent a fair amount of time completely paralyzed as we tried to solve these hard problems. It could be argued that the time would have been spent anyway, but I think it could have been reduced. As the structure of the program became more apparent, the specifications also become more refined, and the problem shrinks. This way we could have had a more manageable puzzle to solve.

We could have also lessened our work load considerably by using more prewritten code. In talking with another student in the class who did a similar fax program, we realized how many pieces of this software were already available off the shelf, particularly in the Linux community where source code is almost always available. While this would not nearly have been as good a learning experience, it would have lessened our development time. This could be a valuable lesson in the real world where you can’t justify spending the extra time to reinvent the wheel.

6. Interface that your team will provide to other teams or use: Please give the exact procedure calls that you will make or support. This is your final interface spec. C/C++/Java code is OK.

Due to the fact that we were one of the top most tasks in the hierarchy, the number of procedure calls that we made for other teams was quite minimal. In terms of procedures that we made for other people there was actually only one for management. We first create an instance of their class in our constructor:

public FaxToGif() {
	PMServerFax mgmt = new PMServerFax(this);
	mgmt.start();
}
Then we wrote the data gathering function which looks like:

public GetStat(Vector List)
This code is done so they can keep in their database how many faxes each user has received. The faxes themselves are kept on the web server which we handle ourselves without any other group, so we did not need to share procedures with anyone. It returns a vector of FaxUser:

Class FaxUser {
	String UserName;
	Int NumFax;
}
and is filled with all the users that have received faxes and the number received, plus the list of Lost and Found faxes under the UserName "lost".

On the other side of the coin, we needed another procedure, specifically from Directory Services so we could decode the bit numbers to find the recipient’s e-mail. This was done with the following function, which is supported by them:

DirectoryService ds = new DirectoryService("config_client");
String netid = ds.GetUserFromExtension(ocr.extension);

7. Advice for the course staff: What mistakes did we make in running this project? Please help us improve the course.

Overall, the course staff was extremely helpful in getting us up and running. When we needed equipment, or advice they were readily available and willing to help. The one exception to the rule, however was when we were discussing OCR or possible alternatives and I felt that we were led slightly astray for a while. The solution that was given to us, was almost impossible to implement, and for a small time we felt stuck with no solution no matter what we did. Eventually we overcame the problem and the staff later did give us a possible good solution which although we didn’t implement in the end, helped us in our way of thinking about the problem.

The only other thing that would have made our task easier would have been better equipment. While the new machines were fast and came with lots of software, the demo would have been almost unmanageable if we hadn’t been able to take over two other CS519 machines. There were simply too many services running simultaneously, in addition to the difficulty of scheduling access to the machine in order to install and test the code in its final location. I think two machines per 20 person group would have been better. Also, the internal modems turned out to be incompatible with our software and we had to bring an external modem from home. I believe the group which used Red Hat had a similar problem and needed to upgrade their hardware as well.

8. References: What sources did you consult in working out the details of your project? URLs for Web pages are acceptable for references.

http://java.sun.com/products/jtapi/index.html - Java Telephony API home page

http://java.ibm.com - The IBM Java Repository

www.java.sun.com - Sun’s main Java site with a fairly complete reference manual

ftp.sgi.com/fax - The site of HylaFAX, an open source program that does faxes. This includes documentation and all the source code.

www.neutralzone.org/home/faqsys/ - Contains references for the GIF and TIFF formats, and general coding algorithms.

http://www.faximum.com/w3vlib/fax - The World Web Virtual Library Faxsimile Subsection

http://www-mipl.jpl.nasa.gov/~ndr/tiff1 -The Unofficial TIFF Home Page

http://www.microsoft.com/communications/tapi.htm?RLD=40 - Windows Telephony API Home Page

http://www.microsoft.com/communications/tapi_wp.htm - Microsoft TAPI 2.0 White Papers

http://ccsmacinfo.ccs.queensu.ca/mark/formats/TIFFInternal.html - Internal Tiff File Format listings.

http://www.cica.indiana.edu/graphics/image_specs/tiff.6.0.format.ps Official TIFF 6.0 Revision document. Does not contain the unofficial FAX extensions, but it does contain everything else.

TIFF-F Revised Specification, Wimsley Associates. alt.fax.comp.graphics message on 29 Apr 1990 6:52:03 GMT.

Aldus/Microsoft Technical Memorandum:  8/8/88 - Complete TIFF 4.0 Specification detailing all the codewords and the CCITT compression standard