Listing 1 demo.c — Enables user to experiment with image transforms

/***************************************************/
/*                                                 */
/* Demonstration program to transfrom images for   */
/* 320 x 200 256 color mode, Borland C             */
/* Christopher Dean 05/10/93                       */
/*                                                 */
/***************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <alloc.h>
#include <process.h>
#include <bios.h>
#include <math.h>

/* key defines */

#define KEY_END      0x4f00
#define KEY_DOWN     0x5000
#define KEY_LEFT     0x4b00
#define KEY_RIGHT    0x4d00
#define KEY_UP       0x4800

/* direction defines */

#define SHEAR_VERT_RIGHT 0
#define SHEAR_VERT_LEFT 1
#define SHEAR_HORZ_RIGHT 1
#define SHEAR_HORZ_LEFT 0

/* function prototypes for transformation routines */

extern char *TransXY(char *buffer,int width,
       int height,int newwidth,int newheight);
extern char *ShearVert(char *buffer,int width,
       int height,int newwidth,int newheight);
extern char *ShearHorz(char *buffer,int width,
       int height,int newwidth,int newheight);

/* detect the VGA256.BGI driver */

static int huge DetectVGA256(void)
{
  int DetectedDriver;
  int SuggestedMode;

  detectgraph(&DetectedDriver,&SuggestedMode);
  if ((DetectedDriver == VGA) ||
      (DetectedDriver == MCGA))
    return(0);
  else
    return (grError);
}

/* initialize the 320 x 200 256 color mode */

void InitGraphics (void)
{
   int GraphMode;
   int GraphDriver = DETECT;

  detectgraph(&GraphDriver,&GraphMode);
  if ((GraphDriver == MCGA) ||
        (GraphDriver == VGA)) {
     GraphDriver = MCGA;
     GraphMode = MCGAC0;
     installuserdriver("VGA256",DetectVGA256);
     GraphDriver = DETECT;
     initgraph(&GraphDriver,&GraphMode,"");
  }

}

/* my own version of the Borland C putimage function. If
   the color in the buffer is 255 then it does not
   put anything, the background color remains. */

void xputimage(int left,int top,void far *bitmap)
{
   int y,i;
   int width,height;        /* dimensions of image */
   char *w;                 /* pointer to screen */
   char *bitmap1;
   unsigned char c;


   /* get image dimensions from buffer and set bitmap1
      to start of image */

   width = *((int *)bitmap);
   height = *((int *)bitmap+1);
   bitmap1 = (char *) bitmap+4;


   /* set screen pointer */

   w = (char far *) 0xA0000000L + ((long)top * 320L) +
       (long)left;

   /* loop through rows of the image, placing them on
      the screen */

   for (y=top;y<top+height;y++) {
      for (i = 0; i < width; ++i) {
         c = *((char *) bitmap1);
         ++bitmap1;
         if (c != 0xff) /* preserve the background? */
            *(w+(long) i) = c;

         /* just for the demo set the background to
            black. Leave this out if you want to
            preserve the background. */

         else *(w+(long) i) = 0;
      }

      w += 320L;  /* next row on screen */
   }

}


main()
{
   int i,j;
   char *newpic,*newpic1,*newpic2=NULL;
   int w,h,nw,nh,nw1,nh1;  /* image dimensions */
   char text[40];
   int key,valid_key,option;


   do {
      printf("\n\nDemonstration functions:\n\n");
      printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n",
         "  1) Scaling",
         "  2) Vertical Shearing Right",
         "  3) Vertical Shearing Left",
         "  4) Horizontal Shearing Right",
         "  5) Horzontal Shearing Left",
         "  6) Rotations",
         "  7) Exit" );
      key = getch();
      valid_key = 1;
      switch(key) {
         case '1':
            option = 0;
            break;
         case '2':
            option = 1;
            break;
         case '3':
            option = 2;
            break;
         case '4':
            option = 3;
            break;
         case '5':
            option = 4;
            break;
         case '6':
            option = 5;
            break;
         case '7':
            option = 6;
            break;
         default:
            valid_key = 0;
      }
   }
   while (!valid_key);
   if (option == 6)
     exit(0);

   InitGraphics();  /* Initialize graphics */

   /* draw the house */
   setfillstyle(SOLID_FILL,0);
   bar(0,0,319,199);
   setcolor(15);
   setlinestyle(SOLID_LINE,0,THICK_WIDTH);
   rectangle(91,71,171,121);
   line(1,21,91,71);
   line(1,71,91,121);
   line(1,21,1,71);
   line(1,21,41,1);
   line(41,1,131,51);
   line(131,51,171,71);
   line(91,71,131,51);
   setcolor(2);
   rectangle(121,96,141,121);
   newpic = malloc(imagesize(0,0,182,134));
   getimage(0,0,182,134,newpic);

   /* initialize dimensions */

   nw = nw1 = w = *((int *) newpic);
   nh = nh1 = h = *((int *) newpic+1);

   setcolor(15);
   sprintf(text,"width: %d height: %d",nw,nh);
   outtextxy(10,190,text);
   while ((key= bioskey(0)) != KEY_END) {
      switch(option) {
        case 0:

           /* scaling */

           switch(key) {
              case KEY_LEFT:

                 /* decrease width */

                 bar(nw,1,nw-5,1+nh);
                 nw -= 5;
                 if (nw < 1)  /* keep within screen */
                   nw = 1;
                 break;
              case KEY_RIGHT:

                 /* increase width  */

                 nw = nw + 5;
                 if (nw > 318) /* keep within screen */
                   nw = 318;
                 break;
              case KEY_UP:

                 /* decrease height */

                 bar(1,nh,1+nw,nh-5);
                 nh -= 5;
                 if (nh < 1)
                   nh = 1;
                 break;
              case KEY_DOWN:

                 /* increase height */

                 nh = nh + 5;
                 if (nh > 189)
                   nh = 189;
                 break;

           }

           /* change size */

           newpic1 = TransXY(newpic,w,h,nw,nh);
           break;
        case 1:
        case 2:

           /* vertical shearing */

           switch(key) {
              case KEY_DOWN:

                 /* increase height of shear */

                 nh += 5;
                 if (nh > 189)
                   nh = 189;
                 break;
              case KEY_UP:

                 /* decrease height of shear */

                 bar(1,1+nh,1+w,nh-4);
                 nh -= 5;
                 if (nh < h)
                   nh = h;
                 break;
            }
            if (option == 1)
               newpic1 = ShearVert(newpic,w,h,nh,SHEAR_VERT_RIGHT);
            else
               newpic1 = ShearVert(newpic,w,h,nh,SHEAR_VERT_LEFT);
            break;
         case 3:
         case 4:

            /* horizontal shearing */

            switch(key) {
              case KEY_RIGHT:

                /* increase width of shear */

                nw += 5;
                if (nw > 318)
                  nw = 318;
                break;
              case KEY_LEFT:

                /* decrease width of shear */

                bar(1+nw,1,nw-4,1+h);
                nw -= 5;
                if (nw < w)
                  nw = w;
                break;
            }
            if (option == 4)
               newpic1 = ShearHorz(newpic,w,h,nw,SHEAR_HORZ_LEFT);
            else
               newpic1 = ShearHorz(newpic,w,h,nw,SHEAR_HORZ_RIGHT);
            break;
         case 5:

            /* rotations */

            switch(key) {

              /* rotate clockwise */

              case KEY_RIGHT:
                 if (nw <= 273)
                 nw += 5;
                 else nh -= 5;

                 if (nw < w) {

                 /* handle case when we have previously
                    been rotating counter-clockwise */


                    /* make sure we always shear >
                       width of image */

                    nw1 = w + w - nw;
                    newpic2 = ShearHorz(newpic,w,h,nw1,
                        SHEAR_HORZ_RIGHT);
                    nh += 5;

                    /* make sure we always shear >
                       height of image */

                    nh1 = h + h - nh;
                    newpic1 = ShearVert(newpic2,nw1,h,
                       nh1,SHEAR_VERT_LEFT);
                 }
                 else {
                    newpic2 = ShearHorz(newpic,w,h,nw,
                       SHEAR_HORZ_LEFT);
                    nh += 5;
                    newpic1 = ShearVert(newpic2,nw,h,
                       nh,SHEAR_VERT_RIGHT);
                 }
                 break;
              case KEY_LEFT:

                 /* rotate counter-clockwise */

                 if (nw1 <= 273)
                    nw -= 5;
                 else nh += 5;
                    if (nw < w) {
                       nw1 = w + w - nw;
                       newpic2 = ShearHorz(newpic,w,h,nw1,SHEAR_HORZ_RIGHT);
                       nh -= 5;
                       nh1 = h + h - nh;
                       newpic1 = ShearVert(newpic2,nw1,hnh1,SHEAR_VERT_LEFT);
                    }
                    else {

                       /* handle case when we have
                          previously been rotating
                          clockwise */

                       newpic2 = ShearHorz(newpic,w,h,nw,SHEAR_HORZ_LEFT);
                       nh -= 5;
                       newpic1 = ShearVert(newpic2,nw,h,nh,SHEAR_VERT_RIGHT);
                    }
                 break;
          }
      }
      xputimage(0,0,newpic1);
      setcolor(15);
      if ((option == 5) && (nw < w))

         /* use different dimensions for rotation */

         sprintf(text,"width: %d height: %d",nw1,nh1);
      else
         sprintf(text,"width: %d height: %d",nw,nh);
      bar(10,190,300,199);
      outtextxy(10,190,text);
      free(newpic1);
      if (newpic2 != NULL) {
         free(newpic2);
         newpic2 = NULL;
      }
   }
   closegraph();           /* shut down graphics */
   textmode(LASTMODE);     /* restore old textmode */
   free(newpic);
}

/* End of File */