home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / IMSCALE.ZIP / SCALE.C < prev    next >
C/C++ Source or Header  |  1993-05-17  |  9KB  |  344 lines

  1. /**********************************************************************
  2. **
  3. ** SCALE.C
  4. **
  5. ** Hi,
  6. ** I've gotten a lot of questions from people about the scaling routine
  7. ** in my Image Processing program called Improces. Quite a few folks
  8. ** have been interested in getting the source code to the program. As a
  9. ** matter of policy, I decided a long time ago not to give away any part
  10. ** of the source code to the Improces program. Sorry.
  11. **
  12. ** Well, here is a _similar_ scaling routine. It works the same as the
  13. ** Improces one, only the one in the Improces program can handle images
  14. ** larger then 64K, and it does the scaling with a single buffer.
  15. ** Besides that, it's the same idea, and speed.
  16. **
  17. ** If you'ld like the shareware version of Improces, it can be had from:
  18. **
  19. **      Dust Devil BBS: (702)796-7134
  20. **
  21. **      The Matrix BBS (This board is a monster!)
  22. **
  23. **              205-323-2016 for 2400 bps access only
  24. **              205-323-6016 for HST/V.32bis access only (no 2400)
  25. **              205-458-3449 for V.32bis access only (no 2400)
  26. **
  27. **       or CompuServe
  28. **
  29. ** I can be reached on any of the above BBS's, or CompuServe
  30. ** John Wagner, CIS-ID 72122,2412
  31. **
  32. **
  33. ** Legal stuff:
  34. ** Free, give it away, use it, not for resale, all that other
  35. ** good stuff... John Wagner, 1993
  36. **
  37. ** Not responsible for any damage this code may cause!!!
  38. **
  39. ** Small program that shows how to scale an when the source and
  40. ** destination are both under 64K. NO ERROR CHECKING IS PERFORMED!!!
  41. **
  42. ***************************************************************************
  43. ***************************************************************************
  44. **                                                                        *
  45. ** WARNING!!!WARNING!!!WARNING!!!WARNING!!!WARNING!!!WARNING!!!WARNING!!! *
  46. **                                                                        *
  47. ***************************************************************************
  48. ***************************************************************************
  49. ** Req. VGA hardware and file JOHN.CLB
  50. ** This program performs NO error checking, so make sure you have
  51. ** a VGA and the file JOHN.CLB. There is no error checking for
  52. ** memory allocation failures, add them if you like!
  53. **
  54. ** It should be noted that this program will only work in mode 0x13
  55. ** without some major modifications on GetImage and PutImage. This
  56. ** program lives, eats and breaths on the fact that each pixel is
  57. ** 8 bits, and video memory is linear. (Just like Improces<g>).
  58. **
  59. ** COMPILER: Borland C++ 3.1, Large model
  60. **
  61. ** Command line: bcc -ml scale.c
  62. **
  63. ** Should compile with Turbo C++ as well, tcc -ml scale.c
  64. ** and MS C family by modifying the #includes
  65. **
  66. **********************************************************************/
  67.  
  68. #include <dos.h>
  69. #include <mem.h>
  70. #include <malloc.h>
  71. #include <io.h>
  72. #include <fcntl.h>
  73. #include <conio.h>
  74.  
  75. #include "scale.h"
  76.  
  77. /*********************************************************************
  78. **
  79. ** main
  80. **
  81. *********************************************************************/
  82. void main()
  83. {
  84.    //These are the coords for a bounding box around John
  85.    static Rect JohnRect = {0, 0, 191, 164};
  86.  
  87.    //this is the size of the screen in mode 0x13
  88.    static Rect ScreenRect = {0, 0, 319, 199};
  89.  
  90.    //this is a rect that is smaller
  91.    static Rect SmallerRect = {200, 40, 310, 120};
  92.    Rect EffectRect;
  93.    int i;
  94.  
  95.    //setup
  96.    SetVideoMode(0x13);
  97.    PalGrayScale();
  98.    LoadJohn();
  99.  
  100.    //wait a sec...
  101.    GetKey();
  102.  
  103.    //scale John to the screen rect
  104.    Scale(&JohnRect, &ScreenRect);
  105.  
  106.    //wait another sec...
  107.    GetKey();
  108.  
  109.    //reload
  110.    LoadJohn();
  111.  
  112.    //wait...
  113.    GetKey();
  114.  
  115.    //get small
  116.    Scale(&JohnRect, &SmallerRect);
  117.  
  118.    //take a look-c...
  119.    GetKey();
  120.  
  121.    //special effects!
  122.    do
  123.    {
  124.       memcpy(&EffectRect, &SmallerRect, sizeof(Rect));
  125.       for(i = 0 ; i < 30 ; i++)
  126.       {
  127.          EffectRect.Sx += 2;
  128.          EffectRect.Sy += 2;
  129.          EffectRect.Ex -= 2;
  130.          EffectRect.Ey -= 2;
  131.          Scale(&JohnRect, &EffectRect);
  132.       }
  133.    }while(!kbhit());
  134.  
  135.    //flush
  136.    GetKey();
  137.  
  138.    //and exit
  139.    SetVideoMode(3);
  140. }
  141.  
  142. /*********************************************************************
  143. **
  144. ** ImageSize
  145. **
  146. ** Returns the number of bytes needed to capture a given image
  147. **
  148. *********************************************************************/
  149. unsigned int ImageSize(pRect r)
  150. {
  151.    return (unsigned)((unsigned)((r->Ex - r->Sx)+1) *
  152.                         (unsigned)((r->Ey - r->Sy)+1));
  153. }
  154.  
  155. /*********************************************************************
  156. **
  157. ** GetImage
  158. **
  159. ** Captures a given image and places it in a buffer
  160. **
  161. *********************************************************************/
  162. void GetImage(pRect r, unsigned char *Buffer)
  163. {
  164.    int y, Width;
  165.    unsigned char *Ptr = Buffer;
  166.  
  167.    Width = r->Ex - r->Sx + 1;
  168.  
  169.    for(y = r->Sy ;  y <= r->Ey ; y++, Ptr+=Width)
  170.       memcpy(Ptr, VgaMem + (y * 320) + r->Sx, Width);
  171. }
  172.  
  173. /*********************************************************************
  174. **
  175. ** PutImage
  176. **
  177. ** Takes an image from a buffer and places it on the screen
  178. **
  179. *********************************************************************/
  180. void PutImage(pRect r, unsigned char * Buffer)
  181. {
  182.    int y, Width;
  183.    unsigned char *Ptr = Buffer;
  184.  
  185.    Width = r->Ex - r->Sx + 1;
  186.  
  187.    for(y = r->Sy ;  y <= r->Ey ; y++, Ptr+=Width)
  188.       memcpy(VgaMem + (y * 320) + r->Sx, Ptr, Width);
  189. }
  190.  
  191. /*********************************************************************
  192. **
  193. ** Scale
  194. **
  195. ** Scales the image from Source to Dest
  196. **
  197. *********************************************************************/
  198. void Scale(pRect Source, pRect Dest)
  199. {
  200.    unsigned char *Image, *Screen, *PtrScreen;
  201.    float XRatio, YRatio, X, Y;
  202.    int Xc, Yc;
  203.    int DestWidth, DestHeight;
  204.    int SourceWidth, SourceHeight;
  205.    int *XPoints, *YPoints, Offset;
  206.  
  207.    SourceWidth = Source->Ex - Source->Sx + 1;
  208.    SourceHeight = Source->Ey - Source->Sy + 1;
  209.  
  210.    DestWidth = Dest->Ex - Dest->Sx + 1;
  211.    DestHeight = Dest->Ey - Dest->Sy + 1;
  212.                           
  213.    //ok, I lied, a little error checking
  214.    if(!SourceWidth || !SourceHeight || !DestWidth || !DestHeight)
  215.       return;
  216.  
  217.    //should add error checking<g>
  218.    Image = (unsigned char *)malloc(ImageSize(Source));
  219.    Screen = (unsigned char *)malloc(ImageSize(Dest));
  220.  
  221.    //capture the source image
  222.    GetImage(Source, Image);
  223.  
  224. /************************************************************************
  225.  
  226.    Compute the scaling ratios
  227.  
  228. ************************************************************************/
  229.  
  230.    XRatio = (float) ( (float)SourceWidth /
  231.                       (float)DestWidth );
  232.  
  233.    YRatio = (float) ( (float)SourceHeight /
  234.                       (float)DestHeight );
  235.  
  236.    //alloc the look up table
  237.    XPoints = (int *)malloc(DestWidth * sizeof(int));
  238.  
  239.    for( Xc=0, X = Source->Sx ; Xc < DestWidth ; X+=XRatio, Xc++ )
  240.        XPoints[Xc] = X;
  241.  
  242.    //same for the y axis
  243.    YPoints = (int *)malloc(DestHeight * sizeof(int));
  244.  
  245.    for( Yc=0, Y = Source->Sy ; Yc < DestHeight ; Y+=YRatio, Yc++ )
  246.        YPoints[Yc] = Y;
  247.  
  248.    //use a pointer to run through the array
  249.    PtrScreen = Screen;
  250.  
  251.    //This is it, actually scales the bitmap using the look up table
  252.    //to go from the dest to the source...
  253.    for( Yc = 0 ; Yc < DestHeight ; Yc++ )
  254.    {
  255.       Offset = YPoints[Yc] * SourceWidth;
  256.       for( Xc = 0 ; Xc < DestWidth ; Xc++)
  257.            *PtrScreen++ = Image[Offset + XPoints[Xc]];
  258.    }
  259.  
  260.    //put the result on the screen
  261.    PutImage(Dest, Screen);
  262.  
  263.    //free up the allocated memory
  264.    free(Screen);
  265.    free(Image);
  266.    free(YPoints);
  267.    free(XPoints);
  268. }
  269.  
  270. /*********************************************************************
  271. **
  272. ** LoadJohn
  273. **
  274. ** Loads an image of yours truly directly into video memory
  275. ** (JOHN.CLB is a 320x200 clipboard image saved with Improces)
  276. **
  277. *********************************************************************/
  278. void LoadJohn(void)
  279. {
  280.    int FileHandle;
  281.    
  282.    FileHandle = open("john.clb", O_RDONLY | O_BINARY);
  283.  
  284.    read(FileHandle, VgaMem, 64000);
  285.  
  286.    close(FileHandle);
  287. }
  288.  
  289. /*********************************************************************
  290. **
  291. ** SetVideoMode
  292. **
  293. ** Mixes six oranges and two pineapples...
  294. **
  295. *********************************************************************/
  296. void SetVideoMode(int Mode)
  297. {
  298.    union REGS r;
  299.  
  300.    r.x.ax = Mode;
  301.    int86(0x10, &r, &r); //click...
  302. }
  303.  
  304. /*********************************************************************
  305. **
  306. ** PalGrayScale
  307. **
  308. ** Sets the VGA palette to grayscale
  309. **
  310. *********************************************************************/
  311. void PalGrayScale(void)
  312. {
  313.    register i=0;
  314.  
  315.    //start at 0
  316.    outp(VgaStartColor, 0);
  317.  
  318.    for(i = 0 ; i < 256 ; i++)
  319.    {
  320.       outp(VgaPort, i>>2); //Red
  321.       outp(VgaPort, i>>2); //Green
  322.       outp(VgaPort, i>>2); //Blue
  323.    }
  324. }
  325.  
  326. /*********************************************************************
  327. **
  328. ** GetKey
  329. **
  330. ** Returns the key pressed
  331. **
  332. *********************************************************************/
  333. int GetKey(void)
  334. {
  335.    int Key;
  336.  
  337.    Key = getch();
  338.  
  339.    if(!Key)
  340.       Key = getch() + 256;
  341.  
  342.    return Key;
  343. }
  344.