CDIB.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

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