/***************************************************************************** * * CrunchDIB - shrink a DIB down by 2 with color averaging * *****************************************************************************/ #define _WINDOWS #include #include #include #include // // support huge >64k DIBs? // #ifndef WIN32 #define HUGE_DIBS #endif #ifdef HUGE_DIBS #define LPBYTE BYTE _huge * #define LPWORD WORD _huge * #define FAR _huge #endif /***************************************************************************** * * These are the standard VGA colors, we will be stuck with until the * end of time! * *****************************************************************************/ static DWORD VGAColors[16] = { 0x00000000 // 0000 black ,0x00800000 // 0001 dark red ,0x00008000 // 0010 dark green ,0x00808000 // 0011 mustard ,0x00000080 // 0100 dark blue ,0x00800080 // 0101 purple ,0x00008080 // 0110 dark turquoise ,0x00C0C0C0 // 1000 gray ,0x00808080 // 0111 dark gray ,0x00FF0000 // 1001 red ,0x0000FF00 // 1010 green ,0x00FFFF00 // 1011 yellow ,0x000000FF // 1100 blue ,0x00FF00FF // 1101 pink (magenta) ,0x0000FFFF // 1110 cyan ,0x00FFFFFF // 1111 white }; /***************************************************************************** * * bit(b,n) - get the Nth bit of BYTE b * *****************************************************************************/ #define bit(b,n) (BYTE)(((b) & (1 << (n))) >> (n)) /***************************************************************************** * * SumMono * * this routine taks four "mono" values and returns the average value. * * ((b0) + (b1) + (b2) + (b3) >= 2) * * *****************************************************************************/ #define SumMono(b0,b1,b2,b3) (BYTE)(((b0) + (b1) + (b2) + (b3) + 2) / 4) /***************************************************************************** * * MapVGA * * map a rgb value to a VGA index * * 0000 black * 0001 dark red * 0010 dark green * 0011 mustard * 0100 dark blue * 0101 purple * 0110 dark turquoise * 1000 gray * 0111 dark gray * 1001 red * 1010 green * 1011 yellow * 1100 blue * 1101 pink (magenta) * 1110 cyan * 1111 white * *****************************************************************************/ #define MapVGA(r,g,b) (((r&~3) == (g&~3) && (g&~3) == (b&~3)) ? \ ((r < 64) ? 0 : (r <= 128) ? 8 : (r <= 192) ? 7 : 15) : \ (((r>192) || (g>192) || (b>192)) ? \ (((r>191) ? 1:0) | ((g>191) ? 2:0) | ((b>191) ? 4:0) | 8) : \ (((r>64) ? 1:0) | ((g>64) ? 2:0) | ((b>64) ? 4:0))) ) /***************************************************************************** * * SumRGB * *****************************************************************************/ #define SumRGB(b0,b1,b2,b3) RGB(\ ((int)pal.palPalEntry[b0].peRed + \ (int)pal.palPalEntry[b1].peRed + \ (int)pal.palPalEntry[b2].peRed + \ (int)pal.palPalEntry[b3].peRed) >> 2, \ \ ((int)pal.palPalEntry[b0].peGreen + \ (int)pal.palPalEntry[b1].peGreen + \ (int)pal.palPalEntry[b2].peGreen + \ (int)pal.palPalEntry[b3].peGreen) >> 2, \ \ ((int)pal.palPalEntry[b0].peBlue + \ (int)pal.palPalEntry[b1].peBlue + \ (int)pal.palPalEntry[b2].peBlue + \ (int)pal.palPalEntry[b3].peBlue) >> 2) /***************************************************************************** * * RGB16 * *****************************************************************************/ typedef struct { BYTE b,g,r; } RGB24; #define RGB16(r,g,b) (\ (((UINT)(r) >> 3) << 10) | \ (((UINT)(g) >> 3) << 5) | \ (((UINT)(b) >> 3) << 0) ) #define rgb16(r,g,b) (\ ((UINT)(r) << 10) | \ ((UINT)(g) << 5) | \ ((UINT)(b) << 0) ) //#define RGB16R(rgb) ((((UINT)(rgb) >> 10) & 0x1F) * 255u / 31u) //#define RGB16G(rgb) ((((UINT)(rgb) >> 5) & 0x1F) * 255u / 31u) //#define RGB16B(rgb) ((((UINT)(rgb) >> 0) & 0x1F) * 255u / 31u) #define RGB16R(rgb) aw5to8[((UINT)(rgb) >> 10) & 0x1F] #define RGB16G(rgb) aw5to8[((UINT)(rgb) >> 5) & 0x1F] #define RGB16B(rgb) aw5to8[((UINT)(rgb) >> 0) & 0x1F] #define RGB16r(rgb) ((BYTE)((UINT)(rgb) >> 10) & 0x1F) #define RGB16g(rgb) ((BYTE)((UINT)(rgb) >> 5) & 0x1F) #define RGB16b(rgb) ((BYTE)((UINT)(rgb) >> 0) & 0x1F) /***************************************************************************** * * Pel() used for 24bit Crunch * *****************************************************************************/ #define Pel(p,x) (BYTE)(BitCount == 1 ? Pel1(p,x) : \ BitCount == 4 ? Pel4(p,x) : Pel8(p,x)) #define Pel1(p,x) (BYTE)bit(((LPBYTE)(p))[(x)/8],7-((x)%8)) #define Pel4(p,x) (BYTE)((x & 1) ? (((LPBYTE)(p))[(x)/2] & 15) : (((LPBYTE)(p))[(x)/2] >> 4)) #define Pel8(p,x) (BYTE)(((LPBYTE)(p))[(x)]) #define Pel16(p,x) (((LPWORD)(p))[(x)]) #define Pel24(p,x) (((RGB24 FAR *)(p))[(x)]) /***************************************************************************** * * CrunchDIB - shrink a DIB down by 2 with color averaging * * this routine works on 1,4 bpp DIBs * * for mono DIBs it is assumed they are black and white * * for 4bpp DIBs it is assumed they use the VGA colors * * this routine can't be used "in place" * *****************************************************************************/ BOOL CrunchDIB( LPBITMAPINFOHEADER lpbiSrc, // BITMAPINFO of source LPVOID lpSrc, // input bits to crunch LPBITMAPINFOHEADER lpbiDst, // BITMAPINFO of dest LPVOID lpDst) // output bits to crunch { LPBYTE pbSrc; LPBYTE pbDst; LPBYTE pb; LPWORD pw; BYTE r,g,b,b0,b1,b2,b3; WORD w0,w1,w2,w3; RGB24 rgb0,rgb1,rgb2,rgb3; int WidthBytesSrc; int WidthBytesDst; UINT x; UINT y; UINT dx; UINT dy; int i; COLORREF rgb; int BitCount; UINT aw5to8[32]; struct { WORD palVersion; WORD palNumEntries; PALETTEENTRY palPalEntry[256]; } pal; if (lpbiSrc->biCompression != BI_RGB) return FALSE; BitCount = (int)lpbiSrc->biBitCount; if (BitCount == 16) for (i=0; i<32; i++) aw5to8[i] = (UINT)i * 255u / 31u; dx = (int)lpbiDst->biWidth; WidthBytesDst = (((UINT)lpbiDst->biBitCount * dx + 31)&~31) / 8; dy = (int)lpbiSrc->biHeight; dx = (int)lpbiSrc->biWidth; WidthBytesSrc = (((UINT)lpbiSrc->biBitCount * dx + 31)&~31) / 8; dx &= ~1; dy &= ~1; pbSrc = lpSrc; pbDst = lpDst; if (lpbiSrc->biClrUsed == 0 && lpbiSrc->biBitCount <= 8) lpbiSrc->biClrUsed = (1 << (int)lpbiSrc->biBitCount); pal.palVersion = 0x300; pal.palNumEntries = (int)lpbiSrc->biClrUsed; for (i=0; i<(int)pal.palNumEntries; i++) { pal.palPalEntry[i].peRed = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbRed; pal.palPalEntry[i].peGreen = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbGreen; pal.palPalEntry[i].peBlue = ((LPRGBQUAD)(lpbiSrc+1))[i].rgbBlue; pal.palPalEntry[i].peFlags = 0; } if (lpbiDst->biBitCount == 8) _fmemcpy(lpbiDst+1,lpbiSrc+1,(int)lpbiSrc->biClrUsed*sizeof(RGBQUAD)); if (lpbiDst->biBitCount == 4) _fmemcpy(lpbiDst+1,VGAColors,sizeof(VGAColors)); if ((int)lpbiDst->biBitCount == (int)lpbiSrc->biBitCount) { switch((int)lpbiSrc->biBitCount) { case 1: dx = dx / 8; // dx is byte count for (y=0; y> 4),(b0 & 0x0F), (b1 >> 4),(b1 & 0x0F)); b = (BYTE)(MapVGA(GetRValue(rgb),GetGValue(rgb),GetBValue(rgb)) << 4); b0 = pbSrc[x + 1]; b1 = pbSrc[x + 1 + WidthBytesSrc]; rgb = SumRGB((b0 >> 4),(b0 & 0x0F), (b1 >> 4),(b1 & 0x0F)); b |= MapVGA(GetRValue(rgb),GetGValue(rgb),GetBValue(rgb)); *pb++ = b; } pbSrc += WidthBytesSrc*2; pbDst += WidthBytesDst; } break; #if 0 case 8: { HPALETTE hpal; hpal = CreatePalette((LPLOGPALETTE)&pal); for (y=0; y> 2; g = ((BYTE)RGB16g(w0) + RGB16g(w1) + RGB16g(w2) + RGB16g(w3)) >> 2; b = ((BYTE)RGB16b(w0) + RGB16b(w1) + RGB16b(w2) + RGB16b(w3)) >> 2; *pw++ = rgb16(r,g,b); } pbSrc += WidthBytesSrc*2; pbDst += WidthBytesDst; } break; case 24: for (y=0; ybiBitCount == 24) { switch((int)lpbiSrc->biBitCount) { case 1: case 4: case 8: for (y=0; y