HRESULT CCorePNGSubtitlerFilter::Transform(IMediaSample *pIn, IMediaSample *pOut) { DShowIMediaSampleCopy(pIn, pOut, false); LONG lActual = pIn->GetActualDataLength(); BYTE *pBuffer; pIn->GetPointer(&pBuffer); //LONGLONG rtStart; //LONGLONG rtEnd; //pIn->GetMediaTime(&rtStart, &rtEnd); BYTE *pOutBuffer; pOut->GetPointer(&pOutBuffer); if (m_HaveSubtitle) { BlendImages((RGBTRIPLE *)pBuffer, (RGBTRIPLE *)pOutBuffer); m_HaveSubtitle = false; } else { //m_Image.Draw(GetDC(NULL)); CopyMemory(pOutBuffer, pBuffer, m_VideoHeader.bmiHeader.biSizeImage); } pOut->SetActualDataLength(m_VideoHeader.bmiHeader.biSizeImage); return S_OK; };
/** * Compute a morph between two images by first distorting each toward the * other, then combining the results with a blend operation. */ STImage *MorphImages(STImage *sourceImage, const std::vector<Feature> &sourceFeatures, STImage *targetImage, const std::vector<Feature> &targetFeatures, float t, float a, float b, float p) { STImage *morph1 = FieldMorph(sourceImage, gSourceFeatures, gTargetFeatures, t, a, b, p); STImage *morph2 = FieldMorph(targetImage, gTargetFeatures, gSourceFeatures, (1-t), a, b, p); STImage *result = BlendImages(morph1, morph2, t); return result; }
/*********************************************************************\ * * * BOOL DoAlphaBlend() * * * * Purpose: * * Captures a copy of the source and destination areas and * * alpha blends them into a memory surface that it displays * * into the destination area. * * * * Notes: * * Takes the same parameters as the AlphaBlend function except * * that the last parameter is a source weighting value rather * * than a BLENDFUNCTION structure. * * * \*********************************************************************/ BOOL DoAlphaBlend_internal( HDC hdcDest, // Handle to destination DC. int nXOriginDest, // X-coord of upper-left corner. int nYOriginDest, // Y-coord of upper-left corner. int nWidthDest, // Destination width. int nHeightDest, // Destination height. HDC hdcSrc, // Handle to source DC. int nXOriginSrc, // X-coord of upper-left corner. int nYOriginSrc, // Y-coord of upper-left corner. int nWidthSrc, // Source width. int nHeightSrc, // Source height. DWORD dwSourceWeight) // Source weighting (between 0 and 255). { if(pfnSetStretchBltMode) { #ifdef PNA pfnSetStretchBltMode = (pfnSetStretchBltMode_t) GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), TEXT("SetStretchBltMode")); #else pfnSetStretchBltMode = SetStretchBltMode; #endif } HDC hdcSrc1 = NULL; HDC hdcSrc2 = NULL; HDC hdcDst = NULL; HBITMAP hbmSrc1 = NULL; HBITMAP hbmSrc2 = NULL; HBITMAP hbmDst = NULL; BOOL bReturn; // Create surfaces for sources and destination images. hbmSrc1 = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest); if (!hbmSrc1) goto HANDLEERROR; hbmSrc2 = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest); if (!hbmSrc2) goto HANDLEERROR; hbmDst = Create24BPPDIBSection(hdcDest, nWidthDest,nHeightDest); if (!hbmDst) goto HANDLEERROR; // Create HDCs to hold our surfaces. hdcSrc1 = CreateCompatibleDC(hdcDest); if (!hdcSrc1) goto HANDLEERROR; hdcSrc2 = CreateCompatibleDC(hdcDest); if (!hdcSrc2) goto HANDLEERROR; hdcDst = CreateCompatibleDC(hdcDest); if (!hdcDst) goto HANDLEERROR; // Prepare the surfaces for drawing. SelectObject(hdcSrc1, hbmSrc1); SelectObject(hdcSrc2, hbmSrc2); SelectObject(hdcDst, hbmDst); if(pfnSetStretchBltMode) { pfnSetStretchBltMode(hdcSrc1, COLORONCOLOR); pfnSetStretchBltMode(hdcSrc2, COLORONCOLOR); } // Capture a copy of the source area. if (!StretchBlt(hdcSrc1, 0,0,nWidthDest,nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY)) goto HANDLEERROR; // Capture a copy of the destination area. if (!StretchBlt(hdcSrc2, 0,0,nWidthDest,nHeightDest, hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, SRCCOPY)) goto HANDLEERROR; // Blend the two source areas to create the destination image. bReturn = BlendImages(hbmSrc1, hbmSrc2, hbmDst, dwSourceWeight); // Clean up objects you do not need any longer. // You cannot delete an object that's selected into an // HDC so delete the HDC first. DeleteDC(hdcSrc1); DeleteDC(hdcSrc2); DeleteObject(hbmSrc1); DeleteObject(hbmSrc2); // Display the blended (destination) image to the target HDC. if (bReturn) { BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcDst, 0,0, SRCCOPY); } // Clean up the rest of the objects you created. DeleteDC(hdcDst); DeleteObject(hbmDst); return bReturn; HANDLEERROR: if (hdcSrc1) DeleteDC(hdcSrc1); if (hdcSrc2) DeleteDC(hdcSrc2); if (hdcDst) DeleteDC(hdcDst); if (hbmSrc1) DeleteObject(hbmSrc1); if (hbmSrc2) DeleteObject(hbmSrc2); if (hbmDst) DeleteObject(hbmDst); return FALSE; }
INT_PTR CALLBACK ControlDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { // These will be garbage in WM_INITDIALOG, but we're not using them there anyway, so who cares LPBLENDSETTINGS settings = (LPBLENDSETTINGS)GetWindowLongPtr(hDlg, GWLP_USERDATA); LPBLENDRESULT results = (LPBLENDRESULT)(settings + 1); HWND *imgWindows = (HWND*)(results + 1); switch (uMsg) { case WM_INITDIALOG: { // Check the serial radio button by default HWND hwndSerialRadioBtn = GetDlgItem(hDlg, IDC_RADIO_SERIAL); SendMessage(hwndSerialRadioBtn, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); // Allocate space for BLENDSETTINGS, BLENDRESULT and the HWNDs to display the images (one for the image, one for the kernel, and one for the blend result) LPVOID userData = (LPVOID)malloc(sizeof(BLENDSETTINGS) + sizeof(BLENDRESULT) + sizeof(HWND) * 3); // Allocate space for the file names LPBLENDSETTINGS blendSettings = (LPBLENDSETTINGS)userData; blendSettings->lpszImageFile = (TCHAR*)malloc(sizeof(TCHAR) * FILENAME_SIZE); blendSettings->lpszKernelFile = (TCHAR*)malloc(sizeof(TCHAR) * FILENAME_SIZE); LPBLENDRESULT blendResult = (LPBLENDRESULT)(blendSettings + 1); blendResult->hwndNotifyWindow = hDlg; blendResult->bufs[BLENDRESULT_IMAGE].pixels = NULL; blendResult->bufs[BLENDRESULT_KERNEL].pixels = NULL; blendResult->bufs[BLENDRESULT_BLENDED].pixels = NULL; // Initialise the display windows HWND *displayWindows = (HWND*)(blendResult + 1); displayWindows[0] = (HWND)INVALID_HANDLE_VALUE; displayWindows[1] = (HWND)INVALID_HANDLE_VALUE; displayWindows[2] = (HWND)INVALID_HANDLE_VALUE; SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)userData); return TRUE; } case WM_BLENDFINISHED: { DWORD dwError = wParam; switch (dwError) { case BLEND_GENERAL_FAILURE: MessageBox(NULL, TEXT("The images could not be blended for some reason. Please try again later."), TEXT("General Failure"), MB_ICONERROR); return TRUE; case BLEND_KERNEL_2LARGE: MessageBox(NULL, TEXT("The kernel image was too large. Its maximum dimensions must be those of the image to blend. Please select another kernel."), TEXT("Kernel Too Large"), MB_ICONERROR); return TRUE; } // Set the amount of time taken HWND hwndTimeMessage = GetDlgItem(hDlg, IDC_PROC_TIME_TXT); TCHAR buf[128] = { 0 }; _sntprintf_s(buf, _countof(buf), TEXT("Processing Time (ms): %.3f"), results->processTime); SetWindowText(hwndTimeMessage, buf); // Re-enable the start button EnableWindow(GetDlgItem(hDlg, IDSTART), TRUE); // Create the windows if we haven't already if (imgWindows[0] == (HWND)INVALID_HANDLE_VALUE) { HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE); InitImageWindow(&imgWindows[BLENDRESULT_IMAGE], hDlg, hInst, TEXT("Original Image")); InitImageWindow(&imgWindows[BLENDRESULT_KERNEL], hDlg, hInst, TEXT("Kernel Image")); InitImageWindow(&imgWindows[BLENDRESULT_BLENDED], hDlg, hInst, TEXT("Blended Image")); for (int i = 0; i < 3; i++) { ShowWindow(imgWindows[i], SW_SHOW); } } for (int i = 0; i < 3; i++) { LPOFFSCREENBUFFER oldBuf = (LPOFFSCREENBUFFER)GetWindowLongPtr(imgWindows[i], IMG_GWLP_OFFSCREENBUFFER); LPOFFSCREENBUFFER newBuf = &results->bufs[i]; // Set the new pixels DWORD newSize = (DWORD)(DIB_WIDTHBYTES(newBuf->width * newBuf->bytesPerPixel * 8) * newBuf->height); oldBuf->pixels = realloc(oldBuf->pixels, newSize); memcpy(oldBuf->pixels, newBuf->pixels, newSize); // Copy over the new bitmap info memcpy(&oldBuf->info, &newBuf->info, sizeof(BITMAPINFO)); oldBuf->height = newBuf->height; oldBuf->width = newBuf->width; SetWindowPos(imgWindows[i], 0, 0, 0, newBuf->width, newBuf->height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); UpdateWindow(imgWindows[i]); } return TRUE; } case WM_CLOSE: /* there are more things to go here, */ DestroyWindow(hDlg); return TRUE; case WM_DESTROY: // TODO: Destroy the child windows and tell them to free any memory they have // Free the settings object free(settings->lpszImageFile); free(settings->lpszKernelFile); // settings is actually the pointer to the whole buffer, so we need to free it last free(settings); PostQuitMessage(0); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_IMG_BROWSE: ChooseFile(hDlg, GetDlgItem(hDlg, IDC_IMAGE_EDIT)); return TRUE; case IDC_KERNEL_BROWSE: ChooseFile(hDlg, GetDlgItem(hDlg, IDC_KERNEL_EDIT)); return TRUE; case IDSTART: { TCHAR szBlendFactor[64] = { 0 }; BYTE blendType; BOOL bIsSerial = SendMessage(GetDlgItem(hDlg, IDC_RADIO_SERIAL), BM_GETCHECK, 0, 0) == BST_CHECKED; BOOL bIsMMX = SendMessage(GetDlgItem(hDlg, IDC_RADIO_MMX), BM_GETCHECK, 0, 0) == BST_CHECKED; // Try to get the blend factor GetWindowText(GetDlgItem(hDlg, IDC_BLEND), szBlendFactor, 64); if (_stscanf_s(szBlendFactor, TEXT("%lf"), &settings->blendFactor) != 1 || settings->blendFactor < 0 || settings->blendFactor > 1) { MessageBox(hDlg, TEXT("Blend factor must be between 0 and 1."), TEXT("Invalid Blend Factor"), MB_ICONERROR); return TRUE; } // Set the blend procedure if (bIsSerial) settings->blendType = BLEND_SERIAL; else if (bIsMMX) settings->blendType = BLEND_MMX; else settings->blendType = BLEND_SSE; // Get the file names and check to make sure they're valid GetWindowText(GetDlgItem(hDlg, IDC_IMAGE_EDIT), settings->lpszImageFile, FILENAME_SIZE); GetWindowText(GetDlgItem(hDlg, IDC_KERNEL_EDIT), settings->lpszKernelFile, FILENAME_SIZE); if (!IsValidImageFile(settings->lpszImageFile)) { MessageBox(hDlg, TEXT("Invalid image file. Please select an existing file file with one of the specified extensions."), TEXT("Invalid Image File"), MB_ICONERROR); return TRUE; } else if (!IsValidImageFile(settings->lpszKernelFile)) { MessageBox(hDlg, TEXT("Invalid kernel image file. Please select an existing file with one of the specified extensions."), TEXT("Invalid Kernel Image File"), MB_ICONERROR); return TRUE; } HWND startBtnHwnd = (HWND)lParam; EnableWindow(GetDlgItem(hDlg, IDSTART), FALSE); BlendImages(settings, results); return TRUE; } } default: return FALSE; } }
int BlendPairs(int argc, const char *argv[]) { // Blend a sequence of images given the pairwise transformations if (argc < 5) { printf("usage: %s pairlist.txt outimg.tga blendWidth\n", argv[1]); return -1; } const char *pairlist= argv[2]; const char *outfile = argv[3]; float blendWidth = (float) atof(argv[4]); // Open the list of image pairs FILE *stream = fopen(pairlist, "r"); if (stream == 0) throw CError("%s: could not open the file %s", argv[1], pairlist); // Construct the list of images and translations CImagePositionV ipList; char line[1024], infile1[1024], infile2[1024]; // float rel_t[2]; CTransform3x3 M; int n; for (n = 0; fgets(line, 1024, stream); n++) { // Compute the position from the PREVIOUS displacement CImagePosition ip; if (n == 0) { ip.position = CTransform3x3::Translation(0.0, 0.0); /* Ident matrix */ // ip.position = CTransform3x3::Rotation(45.0); /* Ident matrix */ } else { ip.position = ipList[n-1].position * M; } // for (int k = 0; k < 2; k++) // ip.position[k] = (n > 0) ? ipList[n-1].position[k] - rel_t[k] : 0.0f; // Read the line and push the image onto the list // if (sscanf(line, "%s %s %f %f", infile1, infile2, // &rel_t[0], &rel_t[1]) != 4) // throw CError("%s: error reading %s", argv[1], pairlist); if (sscanf(line, "%s %s %lf %lf", infile1, infile2, &(M[0][2]), &(M[1][2])) != 4) throw CError("%s: error reading %s\n", argv[1], pairlist); M[1][2] = -M[1][2]; ReadFile(ip.img, infile1); ipList.push_back(ip); } // Read in the last image CImagePosition ip; // for (int k = 0; k < 2; k++) // ip.position[k] = ipList[n-1].position[k] - rel_t[k]; ip.position = ipList[n-1].position * M; ReadFile(ip.img, infile2); ipList.push_back(ip); fclose(stream); CByteImage result = BlendImages(ipList, blendWidth); WriteFile(result, outfile); return 0; }