home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / video / aviview / cdib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-05  |  15.2 KB  |  490 lines

  1. /*****************************************************************************
  2.  *
  3.  *  CrunchDIB  - shrink a DIB down by 2 with color averaging
  4.  *
  5.  *****************************************************************************/
  6. /**************************************************************************
  7.  *
  8.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  9.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  10.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  11.  *  PURPOSE.
  12.  *
  13.  *  Copyright (C) 1993 - 1997  Microsoft Corporation.  All Rights Reserved.
  14.  * 
  15.  **************************************************************************/
  16.  
  17.  
  18. #include <windows.h>
  19. #include <windowsx.h>
  20. #include <mmsystem.h>
  21. #include <memory.h>
  22.  
  23. //
  24. // support huge >64k DIBs?
  25. //
  26. #ifndef WIN32
  27. #define HUGE_DIBS
  28. #endif
  29. #ifdef HUGE_DIBS
  30. #define LPBYTE  BYTE _huge *
  31. #define LPWORD  WORD _huge *
  32. #undef FAR
  33. #define FAR _huge
  34. #endif
  35.  
  36. /*****************************************************************************
  37.  *
  38.  *  These are the standard VGA colors, we will be stuck with until the
  39.  *  end of time!
  40.  *
  41.  *****************************************************************************/
  42.  
  43. static DWORD VGAColors[16] = {
  44.      0x00000000        // 0000  black
  45.     ,0x00800000        // 0001  dark red
  46.     ,0x00008000        // 0010  dark green
  47.     ,0x00808000        // 0011  mustard
  48.     ,0x00000080        // 0100  dark blue
  49.     ,0x00800080        // 0101  purple
  50.     ,0x00008080        // 0110  dark turquoise
  51.     ,0x00C0C0C0        // 1000  gray
  52.     ,0x00808080        // 0111  dark gray
  53.     ,0x00FF0000        // 1001  red
  54.     ,0x0000FF00        // 1010  green
  55.     ,0x00FFFF00        // 1011  yellow
  56.     ,0x000000FF        // 1100  blue
  57.     ,0x00FF00FF        // 1101  pink (magenta)
  58.     ,0x0000FFFF        // 1110  cyan
  59.     ,0x00FFFFFF        // 1111  white
  60.     };
  61.  
  62. /*****************************************************************************
  63.  *
  64.  *  bit(b,n)   - get the Nth bit of BYTE b
  65.  *
  66.  *****************************************************************************/
  67.  
  68. #define bit(b,n) (BYTE)(((b) & (1 << (n))) >> (n))
  69.  
  70. /*****************************************************************************
  71.  *
  72.  *  SumMono
  73.  *
  74.  *     this routine taks four "mono" values and returns the average value.
  75.  *
  76.  *     ((b0) + (b1) + (b2) + (b3) >= 2)
  77.  *
  78.  *
  79.  *****************************************************************************/
  80.  
  81. #define SumMono(b0,b1,b2,b3) (BYTE)(((b0) + (b1) + (b2) + (b3) + 2) / 4)
  82.  
  83. /*****************************************************************************
  84.  *
  85.  *  MapVGA
  86.  *
  87.  *     map a rgb value to a VGA index
  88.  *
  89.  *        0000  black
  90.  *        0001  dark red
  91.  *        0010  dark green
  92.  *        0011  mustard
  93.  *        0100  dark blue
  94.  *        0101  purple
  95.  *        0110  dark turquoise
  96.  *        1000  gray
  97.  *        0111  dark gray
  98.  *        1001  red
  99.  *        1010  green
  100.  *        1011  yellow
  101.  *        1100  blue
  102.  *        1101  pink (magenta)
  103.  *        1110  cyan
  104.  *        1111  white
  105.  *
  106.  *****************************************************************************/
  107.  
  108. #define MapVGA(r,g,b) (((r&~3) == (g&~3) && (g&~3) == (b&~3)) ?        \
  109.         ((r < 64) ? 0 : (r <= 128) ? 8 : (r <= 192) ? 7 : 15) :        \
  110.         (((r>192) || (g>192) || (b>192)) ?                             \
  111.            (((r>191) ? 1:0) | ((g>191) ? 2:0) | ((b>191) ? 4:0) | 8) : \
  112.            (((r>64) ? 1:0) | ((g>64) ? 2:0) | ((b>64) ? 4:0))) )
  113.  
  114. /*****************************************************************************
  115.  *
  116.  *  SumRGB
  117.  *
  118.  *****************************************************************************/
  119.  
  120. #define SumRGB(b0,b1,b2,b3) RGB(\
  121.         ((int)pal.palPalEntry[b0].peRed +        \
  122.          (int)pal.palPalEntry[b1].peRed +        \
  123.          (int)pal.palPalEntry[b2].peRed +        \
  124.          (int)pal.palPalEntry[b3].peRed) >> 2,   \
  125.                                                  \
  126.         ((int)pal.palPalEntry[b0].peGreen +      \
  127.          (int)pal.palPalEntry[b1].peGreen +      \
  128.          (int)pal.palPalEntry[b2].peGreen +      \
  129.          (int)pal.palPalEntry[b3].peGreen) >> 2, \
  130.                                                   \
  131.         ((int)pal.palPalEntry[b0].peBlue +       \
  132.          (int)pal.palPalEntry[b1].peBlue +       \
  133.          (int)pal.palPalEntry[b2].peBlue +       \
  134.          (int)pal.palPalEntry[b3].peBlue) >> 2)
  135.  
  136. /*****************************************************************************
  137.  *
  138.  *  RGB16
  139.  *
  140.  *****************************************************************************/
  141.  
  142. typedef struct { BYTE b,g,r; } RGB24;
  143.  
  144. #define RGB16(r,g,b) (\
  145.             (((UINT)(r) >> 3) << 10) |  \
  146.             (((UINT)(g) >> 3) << 5)  |  \
  147.             (((UINT)(b) >> 3) << 0)  )
  148.  
  149. #define rgb16(r,g,b) (\
  150.             ((UINT)(r) << 10) |  \
  151.             ((UINT)(g) << 5)  |  \
  152.             ((UINT)(b) << 0)  )
  153.  
  154. //#define RGB16R(rgb)     ((((UINT)(rgb) >> 10) & 0x1F) * 255u / 31u)
  155. //#define RGB16G(rgb)     ((((UINT)(rgb) >> 5)  & 0x1F) * 255u / 31u)
  156. //#define RGB16B(rgb)     ((((UINT)(rgb) >> 0)  & 0x1F) * 255u / 31u)
  157.  
  158. #define RGB16R(rgb)     aw5to8[((UINT)(rgb) >> 10) & 0x1F]
  159. #define RGB16G(rgb)     aw5to8[((UINT)(rgb) >> 5)  & 0x1F]
  160. #define RGB16B(rgb)     aw5to8[((UINT)(rgb) >> 0)  & 0x1F]
  161. #define RGB16r(rgb)     ((BYTE)((UINT)(rgb) >> 10) & 0x1F)
  162. #define RGB16g(rgb)     ((BYTE)((UINT)(rgb) >> 5)  & 0x1F)
  163. #define RGB16b(rgb)     ((BYTE)((UINT)(rgb) >> 0)  & 0x1F)
  164.  
  165. /*****************************************************************************
  166.  *
  167.  *  Pel() used for 24bit Crunch
  168.  *
  169.  *****************************************************************************/
  170.  
  171. #define Pel(p,x) (BYTE)(BitCount == 1 ? Pel1(p,x) : \
  172.                         BitCount == 4 ? Pel4(p,x) : Pel8(p,x))
  173.  
  174. #define Pel1(p,x)   (BYTE)bit(((LPBYTE)(p))[(x)/8],7-((x)%8))
  175. #define Pel4(p,x)   (BYTE)((x & 1) ? (((LPBYTE)(p))[(x)/2] & 15) : (((LPBYTE)(p))[(x)/2] >> 4))
  176. #define Pel8(p,x)   (BYTE)(((LPBYTE)(p))[(x)])
  177. #define Pel16(p,x)  (((LPWORD)(p))[(x)])
  178. #define Pel24(p,x)  (((RGB24 FAR *)(p))[(x)])
  179.  
  180. /*****************************************************************************
  181.  *
  182.  *  CrunchDIB  - shrink a DIB down by 2 with color averaging
  183.  *
  184.  *     this routine works on 1,4 bpp DIBs
  185.  *
  186.  *     for mono DIBs it is assumed they are black and white
  187.  *
  188.  *     for 4bpp DIBs it is assumed they use the VGA colors
  189.  *
  190.  *     this routine can't be used "in place"
  191.  *
  192.  *****************************************************************************/
  193.  
  194. BOOL CrunchDIB(
  195.     LPBITMAPINFOHEADER  lpbiSrc,    // BITMAPINFO of source
  196.     LPVOID              lpSrc,      // input bits to crunch
  197.     LPBITMAPINFOHEADER  lpbiDst,    // BITMAPINFO of dest
  198.     LPVOID              lpDst)      // output bits to crunch
  199. {
  200.     LPBYTE      pbSrc;
  201.     LPBYTE      pbDst;
  202.     LPBYTE      pb;
  203.     LPWORD      pw;
  204.     BYTE        r,g,b,b0,b1,b2,b3;
  205.     WORD        w0,w1,w2,w3;
  206.     RGB24       rgb0,rgb1,rgb2,rgb3;
  207.     int         WidthBytesSrc;
  208.     int         WidthBytesDst;
  209.     UINT        x;
  210.     UINT        y;
  211.     UINT        dx;
  212.     UINT        dy;
  213.     int         i;
  214.     COLORREF    rgb;
  215.     int         BitCount;
  216.     UINT        aw5to8[32];
  217.  
  218.     struct {
  219.         WORD         palVersion;
  220.     WORD         palNumEntries;
  221.     PALETTEENTRY palPalEntry[256];
  222.     }   pal;
  223.  
  224.     if (lpbiSrc->biCompression != BI_RGB)
  225.         return FALSE;
  226.  
  227.     BitCount = (int)lpbiSrc->biBitCount;
  228.  
  229.     if (BitCount == 16)
  230.         for (i=0; i<32; i++)
  231.             aw5to8[i] = (UINT)i * 255u / 31u;
  232.  
  233.     dx = (int)lpbiDst->biWidth;
  234.     WidthBytesDst = (((UINT)lpbiDst->biBitCount * dx + 31)&~31) / 8;
  235.  
  236.     dy = (int)lpbiSrc->biHeight;
  237.     dx = (int)lpbiSrc->biWidth;
  238.     WidthBytesSrc = (((UINT)lpbiSrc->biBitCount * dx + 31)&~31) / 8;
  239.  
  240.     dx &= ~1;
  241.     dy &= ~1;
  242.  
  243.     pbSrc = lpSrc;
  244.     pbDst = lpDst;
  245.  
  246.     if (lpbiSrc->biClrUsed == 0 && lpbiSrc->biBitCount <= 8)
  247.         lpbiSrc->biClrUsed = (1 << (int)lpbiSrc->biBitCount);
  248.  
  249.     pal.palVersion = 0x300;
  250.     pal.palNumEntries = (int)lpbiSrc->biClrUsed;
  251.  
  252.     for (i=0; i<(int)pal.palNumEntries; i++)
  253.     {
  254.         pal.palPalEntry[i].peRed   = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbRed;
  255.         pal.palPalEntry[i].peGreen = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbGreen;
  256.         pal.palPalEntry[i].peBlue  = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbBlue;
  257.         pal.palPalEntry[i].peFlags = 0;
  258.     }
  259.  
  260.     if (lpbiDst->biBitCount == 8)
  261.         _fmemcpy(lpbiDst+1,lpbiSrc+1,(int)lpbiSrc->biClrUsed*sizeof(RGBQUAD));
  262.  
  263.     if (lpbiDst->biBitCount == 4)
  264.         _fmemcpy(lpbiDst+1,VGAColors,sizeof(VGAColors));
  265.  
  266.     if ((int)lpbiDst->biBitCount == (int)lpbiSrc->biBitCount)
  267.     {
  268.         switch((int)lpbiSrc->biBitCount)
  269.         {
  270.         case 1:
  271.             dx = dx / 8;    // dx is byte count
  272.  
  273.             for (y=0; y<dy; y+=2)
  274.             {
  275.                 pb = pbDst;
  276.  
  277.                 for (x=0; x<dx; x += 2)
  278.                 {
  279.                     b0 = pbSrc[x];
  280.                     b1 = pbSrc[x + WidthBytesSrc];
  281.  
  282.                     b = (BYTE)(
  283.                         (SumMono(bit(b0,7), bit(b0,6), bit(b1,7), bit(b1,6)) << 7) |
  284.                         (SumMono(bit(b0,5), bit(b0,4), bit(b1,5), bit(b1,4)) << 6) |
  285.                         (SumMono(bit(b0,3), bit(b0,2), bit(b1,3), bit(b1,2)) << 5) |
  286.                         (SumMono(bit(b0,1), bit(b0,0), bit(b1,1), bit(b1,0)) << 4));
  287.  
  288.                     b0 = pbSrc[x + 1];
  289.                     b1 = pbSrc[x + 1 + WidthBytesSrc];
  290.  
  291.                     b |=(SumMono(bit(b0,7), bit(b0,6), bit(b1,7), bit(b1,6)) << 3) |
  292.                         (SumMono(bit(b0,5), bit(b0,4), bit(b1,5), bit(b1,4)) << 2) |
  293.                         (SumMono(bit(b0,3), bit(b0,2), bit(b1,3), bit(b1,2)) << 1) |
  294.                         (SumMono(bit(b0,1), bit(b0,0), bit(b1,1), bit(b1,0)) << 0);
  295.  
  296.                     *pb++ = b;
  297.                 }
  298.  
  299.                 pbSrc += WidthBytesSrc*2;
  300.                 pbDst += WidthBytesDst;
  301.             }
  302.             break;
  303.  
  304.         case 4:
  305.             dx = dx / 2;    // dx is byte count
  306.  
  307.             for (y=0; y<dy; y+=2)
  308.             {
  309.                 pb = pbDst;
  310.  
  311.                 for (x=0; x<dx; x+=2)
  312.                 {
  313.                     b0 = pbSrc[x];
  314.                     b1 = pbSrc[x + WidthBytesSrc];
  315.  
  316.                     rgb = SumRGB((b0 >> 4),(b0 & 0x0F),
  317.                                  (b1 >> 4),(b1 & 0x0F));
  318.  
  319.                     b = (BYTE)(MapVGA(GetRValue(rgb),GetGValue(rgb),GetBValue(rgb)) << 4);
  320.  
  321.                     b0 = pbSrc[x + 1];
  322.                     b1 = pbSrc[x + 1 + WidthBytesSrc];
  323.  
  324.                     rgb = SumRGB((b0 >> 4),(b0 & 0x0F),
  325.                                  (b1 >> 4),(b1 & 0x0F));
  326.  
  327.                     b |= MapVGA(GetRValue(rgb),GetGValue(rgb),GetBValue(rgb));
  328.  
  329.                     *pb++ = b;
  330.                 }
  331.  
  332.                 pbSrc += WidthBytesSrc*2;
  333.                 pbDst += WidthBytesDst;
  334.             }
  335.             break;
  336. #if 0
  337.         case 8:
  338.             {
  339.             HPALETTE hpal;
  340.  
  341.             hpal = CreatePalette((LPLOGPALETTE)&pal);
  342.  
  343.             for (y=0; y<dy; y+=2)
  344.             {
  345.                 pb = pbDst;
  346.  
  347.                 for (x=0; x<dx; x+=2)
  348.                 {
  349.                     b0 = Pel8(pbSrc,x);
  350.                     b1 = Pel8(pbSrc+WidthBytesSrc, x);
  351.                     b2 = Pel8(pbSrc,x+1);
  352.                     b3 = Pel8(pbSrc+WidthBytesSrc,x+1);
  353.  
  354.                     *pb++ = (BYTE)GetNearestPaletteIndex(hpal,
  355.                         SumRGB(b0,b1,b2,b3));
  356.                 }
  357.  
  358.                 pbSrc += WidthBytesSrc*2;
  359.                 pbDst += WidthBytesDst;
  360.             }
  361.  
  362.             DeleteObject(hpal);
  363.             }
  364.             break;
  365. #endif
  366.         case 16:
  367.             for (y=0; y<dy; y+=2)
  368.             {
  369.                 pw = (LPWORD)pbDst;
  370.  
  371.         for (x=0; x<dx; x += 2)
  372.                 {
  373.                     w0 = Pel16(pbSrc,x);
  374.                     w1 = Pel16(pbSrc,x+1);
  375.                     w2 = Pel16(pbSrc+WidthBytesSrc,x);
  376.                     w3 = Pel16(pbSrc+WidthBytesSrc,x+1);
  377.  
  378.                     r = ((BYTE)RGB16r(w0) + RGB16r(w1) + RGB16r(w2) + RGB16r(w3)) >> 2;
  379.                     g = ((BYTE)RGB16g(w0) + RGB16g(w1) + RGB16g(w2) + RGB16g(w3)) >> 2;
  380.                     b = ((BYTE)RGB16b(w0) + RGB16b(w1) + RGB16b(w2) + RGB16b(w3)) >> 2;
  381.  
  382.                     *pw++ = rgb16(r,g,b);
  383.                 }
  384.  
  385.                 pbSrc += WidthBytesSrc*2;
  386.                 pbDst += WidthBytesDst;
  387.             }
  388.             break;
  389.  
  390.         case 24:
  391.             for (y=0; y<dy; y+=2)
  392.             {
  393.                 pb = pbDst;
  394.  
  395.         for (x=0; x<dx; x += 2)
  396.                 {
  397.                     rgb0 = Pel24(pbSrc,x);
  398.                     rgb1 = Pel24(pbSrc,x+1);
  399.                     rgb2 = Pel24(pbSrc+WidthBytesSrc,x);
  400.                     rgb3 = Pel24(pbSrc+WidthBytesSrc,x+1);
  401.  
  402.                     rgb = RGB(
  403.                         ((UINT)rgb0.r + rgb1.r + rgb2.r + rgb3.r)/4,
  404.                         ((UINT)rgb0.g + rgb1.g + rgb2.g + rgb3.g)/4,
  405.                         ((UINT)rgb0.b + rgb1.b + rgb2.b + rgb3.b)/4);
  406.  
  407.                     *pb++ = GetBValue(rgb);
  408.                     *pb++ = GetGValue(rgb);
  409.                     *pb++ = GetRValue(rgb);
  410.                 }
  411.  
  412.                 pbSrc += WidthBytesSrc*2;
  413.                 pbDst += WidthBytesDst;
  414.             }
  415.             break;
  416.  
  417.         default:
  418.             return FALSE;
  419.         }
  420.     }
  421.     else if ((int)lpbiDst->biBitCount == 24)
  422.     {
  423.         switch((int)lpbiSrc->biBitCount)
  424.         {
  425.         case 1:
  426.         case 4:
  427.         case 8:
  428.             for (y=0; y<dy; y+=2)
  429.             {
  430.                 pb = pbDst;
  431.  
  432.         for (x=0; x<dx; x += 2)
  433.                 {
  434.                     b0 = Pel(pbSrc,x);
  435.                     b1 = Pel(pbSrc,x+1);
  436.                     b2 = Pel(pbSrc+WidthBytesSrc,x);
  437.                     b3 = Pel(pbSrc+WidthBytesSrc,x+1);
  438.  
  439.                     rgb = SumRGB(b0,b1,b2,b3);
  440.  
  441.                     *pb++ = GetBValue(rgb);
  442.                     *pb++ = GetGValue(rgb);
  443.                     *pb++ = GetRValue(rgb);
  444.                 }
  445.  
  446.                 pbSrc += WidthBytesSrc*2;
  447.                 pbDst += WidthBytesDst;
  448.             }
  449.             break;
  450.  
  451.         case 16:
  452.             for (y=0; y<dy; y+=2)
  453.             {
  454.                 pb = pbDst;
  455.  
  456.         for (x=0; x<dx; x += 2)
  457.                 {
  458.                     w0 = Pel16(pbSrc,x);
  459.                     w1 = Pel16(pbSrc,x+1);
  460.                     w2 = Pel16(pbSrc+WidthBytesSrc,x);
  461.                     w3 = Pel16(pbSrc+WidthBytesSrc,x+1);
  462.  
  463.                     r = (RGB16R(w0) + RGB16R(w1) + RGB16R(w2) + RGB16R(w3)) / 4;
  464.                     g = (RGB16G(w0) + RGB16G(w1) + RGB16G(w2) + RGB16G(w3)) / 4;
  465.                     b = (RGB16B(w0) + RGB16B(w1) + RGB16B(w2) + RGB16B(w3)) / 4;
  466.  
  467.                     rgb = RGB(r,g,b);
  468.  
  469.                     *pb++ = GetBValue(rgb);
  470.                     *pb++ = GetGValue(rgb);
  471.                     *pb++ = GetRValue(rgb);
  472.                 }
  473.  
  474.                 pbSrc += WidthBytesSrc*2;
  475.                 pbDst += WidthBytesDst;
  476.             }
  477.             break;
  478.  
  479.         default:
  480.             return FALSE;
  481.         }
  482.     }
  483.     else
  484.     {
  485.         return FALSE;
  486.     }
  487.  
  488.     return TRUE;
  489. }
  490.