home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / rleapp / rle.c < prev    next >
C/C++ Source or Header  |  1992-09-12  |  6KB  |  248 lines

  1. /*--------------------------------------------------------------------------*\
  2. |   RLE.C - RLE Delta frame code                                             |
  3. |                                                                            |
  4. \*--------------------------------------------------------------------------*/
  5.  
  6.  
  7. /*
  8.      (C) Copyright Microsoft Corp. 1991, 1992.  All rights reserved.
  9.  
  10.      You have a royalty-free right to use, modify, reproduce and 
  11.      distribute the Sample Files (and/or any modified version) in 
  12.      any way you find useful, provided that you agree that 
  13.      Microsoft has no warranty obligations or liability for any 
  14.      Sample Application Files which are modified. 
  15.      
  16.      If you did not get this from Microsoft Sources, then it may not be the
  17.      most current version.  This sample code in particular will be updated
  18.      and include more documentation.  
  19.  
  20.      Sources are:
  21.          The MM Sys BBS: The phone number is 206 936-4082.
  22.     CompuServe: WINSDK forum, MDK section.
  23. */
  24.  
  25.  
  26. #include <windows.h>
  27. #include "gmem.h"
  28. #include "dib.h"
  29. #include "rle.h"
  30.  
  31. extern WORD PASCAL __WinFlags;
  32. #define WinFlags (WORD)(&__WinFlags)
  33.  
  34. #define RLE_ESCAPE  0
  35. #define RLE_EOL     0
  36. #define RLE_EOF     1
  37. #define RLE_JMP     2
  38. #define RLE_RUN     3
  39.  
  40. typedef BYTE huge * HPRLE;
  41. typedef BYTE far  * LPRLE;
  42.  
  43. /*----------------------------------------------------------------------------*\
  44.  * MEM.ASM
  45. \*----------------------------------------------------------------------------*/
  46. extern LPVOID FAR PASCAL MemCopy(LPVOID dest, LPVOID source, LONG count);
  47. extern LPVOID FAR PASCAL MemFill(LPVOID dest, LONG count, BYTE b);
  48. extern long   FAR PASCAL muldiv32(long,long,long);
  49.  
  50. void FAR  PASCAL DecodeRle386(LPBITMAPINFOHEADER lpbi, LPBYTE pb, LPBYTE prle);
  51. void NEAR PASCAL DecodeRle286(LPBITMAPINFOHEADER lpbi, HPRLE  pb, HPRLE  prle);
  52.  
  53. //
  54. //  RleDeltaFrame
  55. //
  56. //  Calculate the RLE bits to go from one dib to another
  57. //
  58. //      hdibPrev    - Previous DIB
  59. //      hdib        - DIB to RLE
  60. //
  61. //  returns
  62. //
  63. //      handle to a RLE DIB
  64. //
  65. HANDLE FAR PASCAL RleDeltaFrame(HANDLE hrle, HANDLE hdibPrev, HANDLE hdib, int iStart, int iLen, int minJump)
  66. {
  67.     LPBITMAPINFOHEADER lpbi;
  68.  
  69.     BOOL   fAlloc;
  70.     LPBYTE pbPrev;
  71.     LPBYTE pbDib;
  72.     LPBYTE pbRle;
  73.     int    biHeight;
  74.     WORD   cbJump=0;
  75.     int    dy;
  76.  
  77.     if (!hdib)
  78.         return NULL;
  79.  
  80.     if (minJump == 0)
  81.         minJump = 4;
  82.  
  83.     //
  84.     //  Get info on the source and dest dibs
  85.     //
  86.     lpbi = GLock(hdib);
  87.     biHeight = (int)lpbi->biHeight;
  88.  
  89.     if (iLen <= 0)
  90.         iLen = biHeight;
  91.  
  92.     iLen = min(biHeight-iStart, iLen);
  93.  
  94.     //
  95.     //  Hey! we only work with 8bpp DIBs if we get otherwise barf.
  96.     //
  97.     if (lpbi->biBitCount != 8 || lpbi->biCompression != BI_RGB)
  98.         return NULL;
  99.  
  100.     //
  101.     //  create an RLE buffer to place the RLE bits in
  102.     //
  103.     if (fAlloc = !hrle)
  104.     {
  105.         hrle = CreateDib(8, (int)lpbi->biWidth, (int)lpbi->biHeight*2);
  106.  
  107.         if (!hrle)
  108.            return NULL;
  109.  
  110.         //
  111.         //  copy over the color table from the DIB to the empty RLE
  112.     //
  113.         MemCopy(GLock(hrle),GLock(hdib),(int)lpbi->biSize+(int)lpbi->biClrUsed*sizeof(RGBQUAD));
  114.     }
  115.  
  116.     //
  117.     //  lock all the buffers, and start the delta framin'
  118.     //
  119.     lpbi  = GLock(hrle);
  120.     pbRle = DibPtr(hrle);
  121.     pbDib = DibLock(hdib,0,iStart);
  122.  
  123.     if (hdibPrev)
  124.         pbPrev = DibLock(hdibPrev,0,iStart);
  125.     else
  126.         pbPrev = NULL;
  127.  
  128.     while(iStart > 0)
  129.     {
  130.     dy = min(iStart,255);
  131.     *pbRle++ = RLE_ESCAPE;
  132.     *pbRle++ = RLE_JMP;
  133.     *pbRle++ = 0;
  134.     *pbRle++ = (BYTE)dy;
  135.         iStart  -= dy;
  136.         cbJump  += 4;
  137.     }
  138.  
  139.     lpbi->biHeight = iLen;
  140.  
  141.     DeltaFrame386(lpbi, pbPrev, pbDib, pbRle, minJump);
  142.  
  143.     lpbi->biHeight = biHeight;
  144.     lpbi->biSizeImage += cbJump;  // adjust size to include JUMP!
  145.  
  146.     //
  147.     //  hey we are done! Unlock the buffers and get out
  148.     //
  149.     if (fAlloc)
  150.         hrle = GReAlloc(hrle,lpbi->biSize+lpbi->biClrUsed*sizeof(RGBQUAD)+lpbi->biSizeImage);
  151.  
  152.     return hrle;
  153. }
  154.  
  155. //
  156. //  PlayRleDib
  157. //
  158. //  Play back a RLE buffer into a DIB
  159. //
  160. //      hdib        - dest DIB
  161. //      x,y         - position in dest DIB where to place RLE
  162. //      hrle        - src RLE
  163. //
  164. //  returns
  165. //
  166. //      none
  167. //
  168. void PlayRleDib(HANDLE hdib, int x, int y, HANDLE hrle)
  169. {
  170.     LPBITMAPINFOHEADER lpbi;
  171.  
  172.     lpbi = GLock(hdib);
  173.  
  174.     if (WinFlags & WF_CPU286)
  175.         DecodeRle286(lpbi, DibXY(lpbi,x,y), DibPtr(hrle));
  176.     else
  177.         DecodeRle386(lpbi, DibXY(lpbi,x,y), DibPtr(hrle));
  178. }
  179.  
  180. //
  181. //  DecodeRle286
  182. //
  183. //  Play back a RLE buffer into a DIB buffer
  184. //
  185. //  returns
  186. //
  187. //      none
  188. //
  189. void NEAR PASCAL DecodeRle286(LPBITMAPINFOHEADER lpbi, HPRLE pb, HPRLE prle)
  190. {
  191.     BYTE    cnt;
  192.     BYTE    b;
  193.     WORD    x;
  194.     WORD    dx,dy;
  195.     WORD    wWidthBytes;
  196.  
  197.     wWidthBytes = (WORD)lpbi->biWidth+3 & ~3;
  198.  
  199.     x = 0;
  200.  
  201.     for(;;)
  202.     {
  203.         cnt = *prle++;
  204.         b   = *prle++;
  205.  
  206.         if (cnt == RLE_ESCAPE)
  207.         {
  208.             switch (b)
  209.             {
  210.                 case RLE_EOF:
  211.                     return;
  212.  
  213.                 case RLE_EOL:
  214.                     pb += wWidthBytes - x;
  215.                     x = 0;
  216.                     break;
  217.  
  218.                 case RLE_JMP:
  219.                     dx = (WORD)*prle++;
  220.                     dy = (WORD)*prle++;
  221.  
  222.                     pb += (DWORD)wWidthBytes * dy + dx;
  223.                     x  += dx;
  224.  
  225.                     break;
  226.  
  227.                 default:
  228.                     cnt = b;
  229.                     x  += cnt;
  230.                     while (cnt-- > 0)
  231.                         *pb++ = *prle++;
  232.  
  233.                     if (b & 1)
  234.                         prle++;
  235.  
  236.                     break;
  237.             }
  238.         }
  239.         else
  240.         {
  241.             x += cnt;
  242.  
  243.             while (cnt-- > 0)
  244.                 *pb++ = b;
  245.         }
  246.     }
  247. }
  248.