Previous Table of Contents Next


Support Programs

The two support programs used in this chapter are GS.C, used to display “non-format” grey-scale files, and GSDIFF.C, used to display the differences between two files and to print the rms value of the error. They follow.

/*************************** Start of GS.C *****************************/
*
* This is the GS program, which displays grey-scale files on the
* IBM VGA adaptor. It assumes that the grey-scale values run from
* zero to 255, and scales them down to a range of zero to sixty-three,
* so they will be displayed properly on the VGA.
*
* This program can be called with a list of files, and will display them
* in consecutive order, which is useful for trying to measure visual
* differences in compressed files.
*
* This program writes directly to video memory, which should work
* properly on most VGA adaptors. In the event that it doesn't, the
* constant USE_BIOS can be turned on, and the code will use BIOS calls
* to write pixels instead. This will be somewhat slower, but should work
* on every VGA adaptor.
*
* Note that the use of far pointers means this program should probably
* be compiled without using the strict ANSI option of your compiler.
*/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>

main( int argc, char *argv[] )
{
 union REGS rin;
 union REGS rout;
 int i;
 FILE *file;
 char far *video;

 if ( argc < 2 ) {
  printf( "Usage: gs file\n\n" );
  exit( 1 );
 }
 rin.h.ah = 0;
 rin.h.al = 0x13;
 int86( 0x10, &rin, &rout );
 rin.h.ah = 0x10;
 rin.h.al = 0x10;

  for ( i = 0 ; i < 64 ; i++ ) {
   rin.h.dh = (unsigned char) i;
   rin.h.ch = (unsigned char) i;
   rin.h.cl = (unsigned char) i;
   rin.x.bx = i;
   int86( 0x10, &rin, &rout );
  }
  rin.h.ah = 0x10;
  rin.h.al = 0x1b;
  rin.x.cx = 256;
  rin.x.bx = 0;
  int86( 0x10. &rin, &rout );

  argv++;
  while ( —argc > 0 ) {
   file = fopen( *argv++, "rb" );
   if ( file == NULL ) {
     putc( 7, stdout );
     break;
   }
   video = (char far *) 0xA0000000L;
   rin.h.ah = 0x0c;
   rin.h.bh = 0;
   for ( rin.x.dx = 0 ; rin.x.dx < 200 ; rin.x.dx++ ) {
     for ( rin.x.cx = 0 ; rin.x.cx < 320 ; rin.x.cx++ ) {
#ifdef USE_BIOS
        rin.h.al = (unsigned char) ( getc( file ) >> 2);
        int86( 0x10, &rin, &rout );
#else
        *video++ = (char) ( getc( file ) >> 2);
#endif
    }
   }
   fclose( file );
   getch();
  }
  rin.h.ah = 0;
 rin.h.al = 3;
 int86( 0x10. &rin, &rout );
 return 0;
}
/***************************** End of GS.C *****************************/

/***************************** Start of GSDIFF.C ***********************
*
* This is the GSDIFF program, which displays the differences between
* two grey-scale files on the IBM VGA adaptor. It assumes that the
* grey-scale values run from zero to 255, and scales them down to a
* range of zero to sixty-three, so they will be displayed properly on
* the VGA.
*
* This program writes directly to video memory, which should work
* properly on most VGA adaptors. In the event that it doesn't, the
* constant USE_BIOS can be turned on, and the code will use BIOS calls
* to write pixels instead. This will be somewhat slower, but should work
* on every VGA adaptor.
*
* While this program is writing out to the display, it is also keeping a
* running total of the error differences. When the program is
* complete, it prints out the RMS error. If the -B switch is turned
* on, the program operates in batch mode, and doesn't display the
* differences. It just computes and prints the rms error value.
*
* Note that the use of far pointers means this program should probably
* be compiled without using the strict ANSI option of your compiler.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <dos.h>
#include <conio.h>
#include <math.h>
main( int argc, char *argv[] )
{
 union REGS rin;
 union REGS rout;
 int i;
 FILE *file1;
 FILE *file2;
 int diff;
 int c1;
 int c2;
 char far *video;
 double error;
 int batch;

 if ( argc < 3 ) {
  printf( "Usage: gsdiff file1 file2 [-B]\n\n" );
  exit( 1 );
 }
 file1 = fopen( argv[ 1 ], "rb" );
 file2 = fopen( argv[ 2 ], "rb" );
 if ( file1 == NULL || file2 == NULL ) {
  printf( "Could not open file!\n" );
  exit( 1 );
 }
 batch = 0;
 if ( argc > 3 )
  if ( strcmp( argv[ 3 ], "-b" ) == 0 ||
   strcmp( argv [ 3 ], "-B" ) == 0 )
   batch = 1;
 if ( !batch ) {
  rin.h.ah = 0;
  rin.h.al = 0x13;
  int86( 0x10, &rin, &rout );
  rin.h.ah = 0x10;
  rin.h.al = 0x10;
  for ( i = 0 ; i < 64 ; i++ ) {
    rin.h.dh = (unsigned char) i;
    rin.h.ch = (unsigned char) i;
    rin.h.cl = (unsigned char) i;
    rin.x.bx = i;
    int86( 0x10, &rin, &rout );
  }
  rin.h.ah = 0x10;
  rin.h.al = 0x1b;
  rin.x.cx = 256;
  rin.x.bx = 0;
  int86( 0x10, &rin, &rout );
 }
 error = 0.0;
 video = (char far *) 0xA0000000L;
 rin.h.ah = 0x0c;
 rin.h.bh = 0;
 for ( rin.x.dx = 0 ; rin.x.dx < 200 ; rin.x.dx++ ) {
   for ( rin.x.cx = 0 ; rin.x.cx < 320 ; rin.x.cx++ ) {
    c1 = getc( file1 );
    c2 = getc( file2 );
    diff = c1 - c2;
    error += diff*diff;
    if ( diff < 0 )
     diff *= -1;
    if ( diff > 63 )
     diff = 63;
    if ( !batch ) {
#ifdef USE_BIOS
     rin.h.al = diff;
     int86( 0x10, &rin, &rout );
#else
     *video++ = diff;
#endif
    }
   }
 }
 fclose( file1 );
 fclose( file2 );
 if ( !batch ) {
  getch();
  rin.h.ah = 0;
  rin.h.al = 3;
  int86( 0x10, &rin, &rout );
 }
 error /= 320.0 * 200.0;
 printf( "RMS error between %s and %s is %lf\n",
  argv[ 1 ], argv[ 2 ], sqrt( error ) );
  return 0;
 }
/*************************** End of GSDIFF.C ***************************/


Previous Table of Contents Next