|
|
//////////////////////////////////////////////////////////////////////////////
//
// DITH666.C - full color dither (to a palette with 6 red, 6 green 6 blue
// levels)
//
// NOTE this file contains the 'C' code and DITH666A.ASM has the ASM code.
//
// This file does the following dithering
//
// 32bpp -> 8bpp
// 24bpp -> 8bpp
// 16bpp -> 8bpp
//
// 8bpp -> 4bpp N/I
// 16bpp -> 4bpp N/I
// 24bpp -> 4bpp N/I
// 32bpp -> 4bpp N/I
//
//////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <windowsx.h>
#include "drawdibi.h"
#include "dither.h"
#if defined(WIN32) || defined(WANT_286) // 'C' code for Win32
#define USE_C
#endif
#include "dith666.h"
int giDitherTableUsage = 0; LPVOID glpDitherTable;
static void Get666Colors(LPBITMAPINFOHEADER lpbi);
//////////////////////////////////////////////////////////////////////////////
//
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither16(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID); void FAR PASCAL Dither24(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID); void FAR PASCAL Dither32(LPBITMAPINFOHEADER,LPVOID,int,int,int,int,LPBITMAPINFOHEADER,LPVOID,int,int,LPVOID);
//////////////////////////////////////////////////////////////////////////////
//
// DitherTableInit()
//
//////////////////////////////////////////////////////////////////////////////
static LPVOID DitherTableInit() { #ifdef DEBUG
DWORD time = timeGetTime(); #endif
#ifdef XDEBUG
int X,Y; char aBuffer[100]; char far *pBuffer = aBuffer;
GetProfileString("DrawDib", "Matrix5", "", aBuffer, sizeof(aBuffer));
if (aBuffer[0]) { for(Y = 0;Y < 4;Y++) { for(X = 0;X < 4;X++) { while(!isdigit(*pBuffer)) { pBuffer++; }
aHalftone4x4_5[X][Y] = *pBuffer - '0'; pBuffer++; } } } #endif
if (aHalftone8[0][0][0][0] == (BYTE)-1) { int i,x,y;
for (x=0; x<4; x++) for (y=0; y<4; y++) for (i=0; i<256; i++) aHalftone8[0][x][y][i] = (i/51 + (i%51 > aHalftone4x4[x][y]));
for (x=0; x<4; x++) for (y=0; y<4; y++) for (i=0; i<256; i++) aHalftone8[1][x][y][i] = 6 * (i/51 + (i%51 > aHalftone4x4[x][y]));
for (x=0; x<4; x++) for (y=0; y<4; y++) for (i=0; i<256; i++) aHalftone8[2][x][y][i] = 36 * (i/51 + (i%51 > aHalftone4x4[x][y])); }
#ifdef USE_C
if (aHalftone5[0][0][0][0] == (BYTE)-1) { int i,x,y,z,n;
for (x=0; x<4; x++) for (y=0; y<4; y++) for (z=0; z<256; z++) { n = (z >> 2) & 0x1F; i = n > 0 ? n-1 : 0; aHalftone5[0][x][y][z] = (i/6 + (i%6 > aHalftone4x4_5[x][y])); }
for (x=0; x<4; x++) for (y=0; y<4; y++) for (z=0; z<256; z++) { n = (z & 0x1F); i = n > 0 ? n-1 : 0; aHalftone5[1][x][y][z] = 6 * (i/6 + (i%6 > aHalftone4x4_5[x][y])); }
for (x=0; x<4; x++) for (y=0; y<4; y++) for (z=0; z<256; z++) { n = z & 0x1F; i = n > 0 ? n-1 : 0; aHalftone5[2][x][y][z] = 36 * (i/6 + (i%6 > aHalftone4x4_5[x][y])); } } #endif
DPF(("DitherTableInit() took %ldms", timeGetTime() - time));
return NULL; }
//////////////////////////////////////////////////////////////////////////////
//
// DitherInit()
//
//////////////////////////////////////////////////////////////////////////////
LPVOID FAR PASCAL Dither8Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable) { UINT x,y,i,r,g,b; BYTE FAR *pb;
Get666Colors(lpbiOut);
DitherTableInit();
if (lpDitherTable == NULL) lpDitherTable = GlobalAllocPtr(GHND, 256*8*8);
if (lpDitherTable == NULL) return (LPVOID)-1;
pb = (LPBYTE)lpDitherTable;
for (y=0; y<8; y++) { for (i=0; i<256; i++) { r = ((LPRGBQUAD)(lpbi+1))[i].rgbRed; g = ((LPRGBQUAD)(lpbi+1))[i].rgbGreen; b = ((LPRGBQUAD)(lpbi+1))[i].rgbBlue;
for (x=0; x<8; x++) { *pb++ = DITH8(x,y,r,g,b); } } }
*lpDitherProc = Dither8;
return lpDitherTable; }
//////////////////////////////////////////////////////////////////////////////
//
// DitherInit()
//
//////////////////////////////////////////////////////////////////////////////
LPVOID FAR PASCAL Dither16Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable) { Get666Colors(lpbiOut);
*lpDitherProc = Dither16;
DitherTableInit();
#ifndef USE_C
//
// we dont need to re-init the dither table, unless it is not ours then
// we should free it.
//
if (lpDitherTable && lpDitherTable != glpDitherTable) { DitherTerm(lpDitherTable); lpDitherTable = NULL; }
//
// we dont need to re-init table
//
if (lpDitherTable != NULL) return lpDitherTable;
if (glpDitherTable) { giDitherTableUsage++; return glpDitherTable; } else { //
// build a table that maps a RGB555 directly to a palette index
// we actualy build 4 tables, we assume a 2x2 dither and build
// a table for each position in the matrix.
//
UINT x,y,r,g,b; BYTE FAR *pb;
#ifdef DEBUG
DWORD time = timeGetTime(); #endif
lpDitherTable = GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE, 32768l*4);
if (lpDitherTable == NULL) return (LPVOID)-1;
glpDitherTable = lpDitherTable; giDitherTableUsage = 1;
for (y=0; y<2; y++) { if (y == 0) pb = (BYTE FAR *)lpDitherTable; else pb = (BYTE FAR *)((BYTE _huge *)lpDitherTable + 65536);
for (r=0; r<32; r++) for (g=0; g<32; g++) for (b=0; b<32; b++) for (x=0; x<2; x++) *pb++ = DITH31(x,y,r,g,b); }
DPF(("Dither16Init() took %ldms", timeGetTime() - time)); } #endif
return lpDitherTable; }
//////////////////////////////////////////////////////////////////////////////
//
// DitherTerm()
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither16Term(LPVOID lpDitherTable) { if (giDitherTableUsage == 0 || --giDitherTableUsage > 0) return;
if (glpDitherTable) { GlobalFreePtr(glpDitherTable); glpDitherTable = NULL; } }
//////////////////////////////////////////////////////////////////////////////
//
// Dither24Init()
//
//////////////////////////////////////////////////////////////////////////////
LPVOID FAR PASCAL Dither24Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable) { Get666Colors(lpbiOut);
*lpDitherProc = Dither24;
return DitherTableInit(); }
//////////////////////////////////////////////////////////////////////////////
//
// Dither24Term()
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither24Term(LPVOID lpDitherTable) { }
//////////////////////////////////////////////////////////////////////////////
//
// Dither32Init()
//
//////////////////////////////////////////////////////////////////////////////
LPVOID FAR PASCAL Dither32Init(LPBITMAPINFOHEADER lpbi, LPBITMAPINFOHEADER lpbiOut, DITHERPROC FAR *lpDitherProc, LPVOID lpDitherTable) { Get666Colors(lpbiOut);
*lpDitherProc = Dither32;
return DitherTableInit(); }
//////////////////////////////////////////////////////////////////////////////
//
// Dither32Term()
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither32Term(LPVOID lpDitherTable) { }
//////////////////////////////////////////////////////////////////////////////
//
// GetDithColors() get the dither palette
//
//////////////////////////////////////////////////////////////////////////////
static void Get666Colors(LPBITMAPINFOHEADER lpbi) { RGBQUAD FAR *prgb = (RGBQUAD FAR *)(((LPBYTE)lpbi) + (UINT)lpbi->biSize); int i;
for (i=0; i<256; i++) { prgb[i].rgbRed = pal666[i][0]; prgb[i].rgbGreen = pal666[i][1]; prgb[i].rgbBlue = pal666[i][2]; prgb[i].rgbReserved = 0; }
lpbi->biClrUsed = 256; }
#ifdef USE_C
//////////////////////////////////////////////////////////////////////////////
//
// Dither24 - dither from 24 to 8 using the Table method in 'C' Code
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither24( LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
LPVOID lpDst, // --> to destination bits
int DstX, // Destination origin - x coordinate
int DstY, // Destination origin - y coordinate
int DstXE, // x extent of the BLT
int DstYE, // y extent of the BLT
LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
LPVOID lpSrc, // --> to source bits
int SrcX, // Source origin - x coordinate
int SrcY, // Source origin - y coordinate
LPVOID lpDitherTable) // dither table.
{ int x,y; BYTE r,g,b; UINT wWidthSrc; UINT wWidthDst; BYTE _huge *pbS; BYTE _huge *pbD;
if (biDst->biBitCount != 8 || biSrc->biBitCount != 24) return;
wWidthSrc = ((UINT)biSrc->biWidth*3+3)&~3; wWidthDst = ((UINT)biDst->biWidth+3)&~3;
pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst; pbS = (BYTE _huge *)lpSrc + SrcX*3 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
wWidthSrc -= DstXE*3; wWidthDst -= DstXE;
#define GET24() \
b = *pbS++; \ g = *pbS++; \ r = *pbS++;
for (y=0; y<DstYE; y++) {
for (x=0; x<DstXE; x++) { GET24(); *pbD++ = DITH8(x,y,r,g,b); }
pbS += wWidthSrc; pbD += wWidthDst; } }
//////////////////////////////////////////////////////////////////////////////
//
// Dither32 - dither from 32 to 8 using the Table method in 'C' Code
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither32( LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
LPVOID lpDst, // --> to destination bits
int DstX, // Destination origin - x coordinate
int DstY, // Destination origin - y coordinate
int DstXE, // x extent of the BLT
int DstYE, // y extent of the BLT
LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
LPVOID lpSrc, // --> to source bits
int SrcX, // Source origin - x coordinate
int SrcY, // Source origin - y coordinate
LPVOID lpDitherTable) // dither table.
{ int x,y; BYTE r,g,b; UINT wWidthSrc; UINT wWidthDst; BYTE _huge *pbS; BYTE _huge *pbD;
if (biDst->biBitCount != 8 || biSrc->biBitCount != 32) return;
wWidthSrc = ((UINT)biSrc->biWidth*4+3)&~3; wWidthDst = ((UINT)biDst->biWidth+3)&~3;
pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst; pbS = (BYTE _huge *)lpSrc + SrcX*4 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
wWidthSrc -= DstXE*4; wWidthDst -= DstXE;
#define GET32() \
b = *pbS++; \ g = *pbS++; \ r = *pbS++; \ pbS++;
for (y=0; y<DstYE; y++) {
for (x=0; x<DstXE; x++) { GET32(); *pbD++ = DITH8(x,y,r,g,b); }
pbS += wWidthSrc; pbD += wWidthDst; } }
//////////////////////////////////////////////////////////////////////////////
//
// Dither16 - dither from 16 to 8 using the Table method in 'C' Code
//
//////////////////////////////////////////////////////////////////////////////
void FAR PASCAL Dither16( LPBITMAPINFOHEADER biDst, // --> BITMAPINFO of the dest
LPVOID lpDst, // --> to destination bits
int DstX, // Destination origin - x coordinate
int DstY, // Destination origin - y coordinate
int DstXE, // x extent of the BLT
int DstYE, // y extent of the BLT
LPBITMAPINFOHEADER biSrc, // --> BITMAPINFO of the source
LPVOID lpSrc, // --> to source bits
int SrcX, // Source origin - x coordinate
int SrcY, // Source origin - y coordinate
LPVOID lpDitherTable) // dither table.
{ int x,y; WORD w; UINT wWidthSrc; UINT wWidthDst; BYTE _huge *pbS; BYTE _huge *pbD;
if (biDst->biBitCount != 8 || biSrc->biBitCount != 16) return;
wWidthSrc = ((UINT)biSrc->biWidth*2+3)&~3; wWidthDst = ((UINT)biDst->biWidth+3)&~3;
pbD = (BYTE _huge *)lpDst + DstX + (DWORD)(UINT)DstY * (DWORD)wWidthDst; pbS = (BYTE _huge *)lpSrc + SrcX*2 + (DWORD)(UINT)SrcY * (DWORD)wWidthSrc;
wWidthSrc -= DstXE*2; wWidthDst -= DstXE;
#define GET16() \
w = *((WORD _huge *)pbS)++;
for (y=0; y<DstYE; y++) {
for (x=0; x<DstXE; x++) { GET16(); *pbD++ = DITH5(x,y,w); }
pbS += wWidthSrc; pbD += wWidthDst; } }
#endif
|