// local function: perform median filter to DIB void DoMedianFilterDIB(int *red, int *green, int *blue, int i, int j, WORD wBytesPerLine, LPBYTE lpDIBits) { BYTE b[9], g[9], r[9]; LONG lOffset; lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine); b[0] = *(lpDIBits + lOffset++); g[0] = *(lpDIBits + lOffset++); r[0] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine); b[1] = *(lpDIBits + lOffset++); g[1] = *(lpDIBits + lOffset++); r[1] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine); b[2] = *(lpDIBits + lOffset++); g[2] = *(lpDIBits + lOffset++); r[2] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine); b[3] = *(lpDIBits + lOffset++); g[3] = *(lpDIBits + lOffset++); r[3] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); b[4] = *(lpDIBits + lOffset++); g[4] = *(lpDIBits + lOffset++); r[4] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine); b[5] = *(lpDIBits + lOffset++); g[5] = *(lpDIBits + lOffset++); r[5] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine); b[6] = *(lpDIBits + lOffset++); g[6] = *(lpDIBits + lOffset++); r[6] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine); b[7] = *(lpDIBits + lOffset++); g[7] = *(lpDIBits + lOffset++); r[7] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine); b[8] = *(lpDIBits + lOffset++); g[8] = *(lpDIBits + lOffset++); r[8] = *(lpDIBits + lOffset); qsort(r, 9, 1, compare); qsort(g, 9, 1, compare); qsort(b, 9, 1, compare); *red = r[0]; *green = g[0]; *blue = b[0]; }
// local function: perform convolution to DIB with a kernel void DoConvoluteDIB(int *red, int *green, int *blue, int i, int j, WORD wBytesPerLine, LPBYTE lpDIBits, KERNEL *lpKernel) { BYTE b[9], g[9], r[9]; LONG lOffset; lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine); b[0] = *(lpDIBits + lOffset++); g[0] = *(lpDIBits + lOffset++); r[0] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine); b[1] = *(lpDIBits + lOffset++); g[1] = *(lpDIBits + lOffset++); r[1] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine); b[2] = *(lpDIBits + lOffset++); g[2] = *(lpDIBits + lOffset++); r[2] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine); b[3] = *(lpDIBits + lOffset++); g[3] = *(lpDIBits + lOffset++); r[3] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); b[4] = *(lpDIBits + lOffset++); g[4] = *(lpDIBits + lOffset++); r[4] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine); b[5] = *(lpDIBits + lOffset++); g[5] = *(lpDIBits + lOffset++); r[5] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine); b[6] = *(lpDIBits + lOffset++); g[6] = *(lpDIBits + lOffset++); r[6] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine); b[7] = *(lpDIBits + lOffset++); g[7] = *(lpDIBits + lOffset++); r[7] = *(lpDIBits + lOffset); lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine); b[8] = *(lpDIBits + lOffset++); g[8] = *(lpDIBits + lOffset++); r[8] = *(lpDIBits + lOffset); *red = *green = *blue = 0; for (int k=0; k<8; ++k) { *red += lpKernel->Element[k]*r[k]; *green += lpKernel->Element[k]*g[k]; *blue += lpKernel->Element[k]*b[k]; } if (lpKernel->Divisor != 1) { *red /= lpKernel->Divisor; *green /= lpKernel->Divisor; *blue /= lpKernel->Divisor; } // getoff opposite *red = abs(*red); *green = abs(*green); *blue = abs(*blue); }
/************************************************************************* * * ConvoluteDIB() * * Parameters: * * HDIB hDib - objective DIB handle * KERNEL *lpKernel - pointer of kernel used to convolute with DIB * int Strength - operation strength set to the convolute * int nKernelNum - kernel number used to convolute * * Return Value: * * BOOL - True is success, else False * * Description: * * This is the generic convolute function to DIB * ************************************************************************/ BOOL ConvoluteDIB(HDIB hDib, KERNEL *lpKernel, int Strength, int nKernelNum) { WaitCursorBegin(); HDIB hNewDib = NULL; // we only convolute 24bpp DIB, so first convert DIB to 24bpp WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 24) hNewDib = ConvertDIBFormat(hDib, 24, NULL); else hNewDib = CopyHandle(hDib); if (! hNewDib) { WaitCursorEnd(); return FALSE; } // new DIB attributes WORD wDIBWidth = (WORD)DIBWidth(hNewDib); WORD wDIBHeight = (WORD)DIBHeight(hNewDib); WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); DWORD dwImageSize = wBytesPerLine * wDIBHeight; // Allocate and lock memory for filtered image data HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); if (!hFilteredBits) { WaitCursorEnd(); return FALSE; } LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); // get bits address in DIB LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); LPBYTE lpDIBits = FindDIBBits(lpDIB); // convolute... for (int i=1; i<wDIBHeight-1; i++) for (int j=1; j<wDIBWidth-1; j++) { int red=0, green=0, blue=0; for (int k=0; k<nKernelNum; ++k) { int r=0, g=0, b=0; DoConvoluteDIB(&r, &g, &b, i, j, wBytesPerLine, lpDIBits, lpKernel+k); if (r > red) red = r; if (g > green) green = g; if (b > blue) blue = b; //red += r; green += g; blue += b; } // original RGB value in center pixel (j, i) LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); BYTE OldB = *(lpDIBits + lOffset++); BYTE OldG = *(lpDIBits + lOffset++); BYTE OldR = *(lpDIBits + lOffset); // When we get here, red, green and blue have the new RGB value. if (Strength != 10) { // Interpolate pixel data red = OldR + (((red - OldR) * Strength) / 10); green = OldG + (((green - OldG) * Strength) / 10); blue = OldB + (((blue - OldB) * Strength) / 10); } lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); *(lpDestImage + lOffset++) = BOUND(blue, 0, 255); *(lpDestImage + lOffset++) = BOUND(green, 0, 255); *(lpDestImage + lOffset) = BOUND(red, 0, 255); } // a filtered image is available in lpDestImage // copy it to DIB bits memcpy(lpDIBits, lpDestImage, dwImageSize); // cleanup temp buffers GlobalUnlock(hFilteredBits); GlobalFree(hFilteredBits); GlobalUnlock(hNewDib); // rebuild hDib HDIB hTmp = NULL; if (wBitCount != 24) hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL); else hTmp = CopyHandle(hNewDib); GlobalFree(hNewDib); DWORD dwSize = GlobalSize(hTmp); memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize); GlobalUnlock(hTmp); GlobalFree(hTmp); GlobalUnlock(hDib); WaitCursorEnd(); return TRUE; }
/************************************************************************* * * MedianFilterDIB() * * Parameters: * * HDIB hDib - objective DIB handle * * Return Value: * * BOOL - True is success, else False * * Description: * * This is the media filtering function to DIB * ************************************************************************/ BOOL MedianFilterDIB(HDIB hDib) { WaitCursorBegin(); HDIB hNewDib = NULL; // we only convolute 24bpp DIB, so first convert DIB to 24bpp WORD wBitCount = DIBBitCount(hDib); if (wBitCount != 24) hNewDib = ConvertDIBFormat(hDib, 24, NULL); else hNewDib = CopyHandle(hDib); if (! hNewDib) { WaitCursorEnd(); return FALSE; } // new DIB attributes WORD wDIBWidth = (WORD)DIBWidth(hNewDib); WORD wDIBHeight = (WORD)DIBHeight(hNewDib); WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib); DWORD dwImageSize = wBytesPerLine * wDIBHeight; // Allocate and lock memory for filtered image data HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize); if (!hFilteredBits) { WaitCursorEnd(); return FALSE; } LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits); // get bits address in DIB LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib); LPBYTE lpDIBits = FindDIBBits(lpDIB); // convolute... for (int i=1; i<wDIBHeight-1; i++) for (int j=1; j<wDIBWidth-1; j++) { int red=0, green=0, blue=0; DoMedianFilterDIB(&red, &green, &blue, i, j, wBytesPerLine, lpDIBits); LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine); *(lpDestImage + lOffset++) = BOUND(blue, 0, 255); *(lpDestImage + lOffset++) = BOUND(green, 0, 255); *(lpDestImage + lOffset) = BOUND(red, 0, 255); } // a filtered image is available in lpDestImage // copy it to DIB bits memcpy(lpDIBits, lpDestImage, dwImageSize); // cleanup temp buffers GlobalUnlock(hFilteredBits); GlobalFree(hFilteredBits); GlobalUnlock(hNewDib); // rebuild hDib HDIB hTmp = NULL; if (wBitCount != 24) hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL); else hTmp = CopyHandle(hNewDib); GlobalFree(hNewDib); DWORD dwSize = GlobalSize(hTmp); memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize); GlobalUnlock(hTmp); GlobalFree(hTmp); GlobalUnlock(hDib); WaitCursorEnd(); return TRUE; }
#define burst_count 1 #define rescale_in 8 #define rescale_out 7 #define artifacts_mid 1.5f #define artifacts_max 2.5f #define fringing_mid 1.0f #define std_decoder_hue 0 #define gamma_size 256 #include "atari_ntsc_impl.h" /* 2 input pixels -> 8 composite samples */ pixel_info_t const atari_ntsc_pixels [alignment_count] = { { PIXEL_OFFSET( -4, -9 ), { 1, 1, 1, 1 } }, { PIXEL_OFFSET( 0, -5 ), { 1, 1, 1, 1 } }, }; static void correct_errors( atari_ntsc_rgb_t color, atari_ntsc_rgb_t* out ) { unsigned i; for ( i = 0; i < rgb_kernel_size / 2; i++ ) { atari_ntsc_rgb_t error = color - out [i ] - out [(i+10)%14+14] - out [i + 7] - out [i + 3 +14]; CORRECT_ERROR( i + 3 + 14 ); } }
#define artifacts_mid 1.0f #define fringing_mid 1.0f /* Atari change: default palette is already at correct hue. #define std_decoder_hue -15 */ #define std_decoder_hue 0 /* Atari change: only one palette - remove base_palete field. */ #define STD_HUE_CONDITION( setup ) !(setup->palette) #include "atari_ntsc_impl.h" /* Atari change: adapted to 4/7 pixel ratio. */ /* 4 input pixels -> 8 composite samples */ pixel_info_t const atari_ntsc_pixels [alignment_count] = { { PIXEL_OFFSET( -6, -6 ), { 0, 0, 1, 1 } }, { PIXEL_OFFSET( -4, -4 ), { 0, 0, 1, 1 } }, { PIXEL_OFFSET( -2, -2 ), { 0, 0, 1, 1 } }, { PIXEL_OFFSET( 0, 0 ), { 0, 0, 1, 1 } }, }; /* Atari change: no alternating burst phases - removed merge_kernel_fields function. */ static void correct_errors( atari_ntsc_rgb_t color, atari_ntsc_rgb_t* out ) { int n; for ( n = burst_count; n; --n ) { unsigned i; for ( i = 0; i < rgb_kernel_size / 2; i++ ) {