www.gusucode.com > 基于dwt的视频数字水印源代码 > 基于dwt的视频数字水印源代码\code\HaYDWT\EmbedRecoverProcess.cpp
//Download by http://www.NewXing.com //--------------------------------------------------------------------------- #pragma hdrstop #include "EmbedRecoverProcess.h" #include "EmbedVideo.h" #include "WatRecover.h" #include "Main.h" #include "Common.h" #include "FileServices.h" #include "dwt.h" #include "MemUtil.h" #include <math.h> //--------------------------------------------------------------------------- #pragma package(smart_init) /* Embed AVI Video Constraints: 1. Doesn't support AVI files with audio */ int EmbedWatermarkAVI_Chasan( HWND thisHwnd, AnsiString inVideoFileName, AnsiString outVideoFileName, // watermark inputs Graphics::TBitmap *pEWbmpImage, stcImageType EWImageType, UCHAR **Gray_Image, long Gray_Image_Width, long Gray_Image_Height, // Key Image inputs Graphics::TBitmap *pEWKeybmpImage, stcImageType EWKImageType, UCHAR **Gray_Image_Key, long Gray_Image_Key_Width, long Gray_Image_Key_Height, // embed inputs double GainFactor, // gain factor needed at embedding time int DWTLevels, // wavelet tansform level int LevelEmbed ) // Which level watermark will be embedded { long AviWidth, AviHeight, i, j, iImg, jImg, iImgKey, jImgKey, NumFrames, iFrm, is, js; long tmpW, tmpH, EWWidth, EWHeight, EWKeyWidth, EWKeyHeight; long EmbedHorW, EmbedHorH, EmbedVerW, EmbedVerH; long StartEmbedHorW, StartEmbedHorH, StartEmbedVerW, StartEmbedVerH; TAviUtil *inAvi, *outAvi; HAVI AviIn, AviOut; UCHAR **TempImage; char **TempImageKey; UCHAR **Red, **Green, **Blue; double **waveRed, **waveGreen, **waveBlue; BlockInfoStrc DWTSegmentAdrs[10]; int szSeg; // ------------------------ // CHECK 1 // there must be two images if ((EWImageType == Img_NONE) || (EWKImageType == Img_NONE) || (EWImageType == EWKImageType)) { MessageDlg("You must select a Watermark and Key image.", mtError, TMsgDlgButtons() << mbOK, 0); return false; } // ----------------------------------------------------------- // CHECK 2 // Key image sizes MUST be equal to video DWT level size. // Open the AVI file and set handle AviIn = RDOpenAviFile(inVideoFileName.c_str(), true); if (AviIn == NULL) { DispError("ERROR! Cannot open AVI file."); return S_FALSE; } inAvi = (TAviUtil*)AviIn; AviWidth = inAvi->iWidth; AviHeight = inAvi->iHeight; NumFrames = inAvi->numframes; if ( DWTLevels < LevelEmbed ) { MessageDlg("DWT Levels cannot be smaller than Embed Levels.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // Check the dimensions for compatability. if (AviWidth%(1 << DWTLevels) || AviHeight%(1 << DWTLevels)) { AnsiString sss = "width and height of input video must be divisible by 2^" + IntToStr(DWTLevels) + " = " + IntToStr((int)pow(2, DWTLevels)); MessageDlg(sss, mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } if ((DWTLevels == 2) || (DWTLevels == 3)) { if (LevelEmbed == 1) { tmpW = AviWidth >> 1; // division by 2 tmpH = AviHeight >> 1; } else if (LevelEmbed == 2) { tmpW = AviWidth >> 2; // division by 4 tmpH = AviHeight >> 2; } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // check the sizes /* if (EWKImageType == Img_PGMGray) { if ( (Gray_Image_Key_Width != tmpW) || (Gray_Image_Key_Height != tmpH)) { MessageDlg("Size of Key must fit the DWT sub-frequency size of the video frame.\nCannot use this Key.", mtError, TMsgDlgButtons() << mbOK, 0); RdCloseAvi(AviIn); inAvi = NULL; return false; } } else // BMP { if ( (pEWKeybmpImage->Width != tmpW) || (pEWKeybmpImage->Height != tmpH)) { MessageDlg("Size of Key must fit the DWT sub-frequency size of the video frame.\nCannot use this Key.", mtError, TMsgDlgButtons() << mbOK, 0); RdCloseAvi(AviIn); inAvi = NULL; return false; } } // ----------------------------------------------------------- */ // if we came this far, inAvi structure is still open. // We will continue to use this structure. /* // we only support 8-bmp and PGM images if ( (EWImageType != Img_PGMGray) || (EWImageType != Img_BMPGray)) { MessageDlg("Watermark must be 8-bit BMP or PGM.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } */ // Erase file if exists if (FileExists(outVideoFileName.c_str())) DeleteFileA(outVideoFileName.c_str()); // Create Avi AviOut = CreateAvi(outVideoFileName.c_str(), inAvi->AviInfo.dwScale, inAvi->AviInfo.dwRate, NULL); if (MessageBox(thisHwnd, "Do you want to compress output AVI?","Question", MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES) { HBITMAP hbm; HDC hdcscreen=GetDC(0), hdc=CreateCompatibleDC(hdcscreen); ReleaseDC(0,hdcscreen); BITMAPINFO bmi; ZeroMemory(&bmi,sizeof(bmi)); BITMAPINFOHEADER &bih = bmi.bmiHeader; bih.biSize = sizeof(bih); bih.biWidth = AviWidth; bih.biHeight = AviHeight; bih.biPlanes = 1; bih.biBitCount = 24; bih.biCompression = BI_RGB; bih.biSizeImage = ((bih.biWidth*bih.biBitCount/8+3)&0xFFFFFFFC)*bih.biHeight; bih.biXPelsPerMeter = 1; bih.biYPelsPerMeter = 1; bih.biClrUsed = 0; bih.biClrImportant = 0; void *bits; hbm = CreateDIBSection(hdc,(BITMAPINFO*)&bih,DIB_RGB_COLORS,&bits,NULL,NULL); AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts)); opts.fccHandler = mmioFOURCC('d','i','v','x'); SetAviVideoCompression(AviOut, hbm, &opts, true, thisHwnd); DeleteDC(hdc); DeleteObject(hbm); } /* Allocate required buffers */ // watermark if (EWImageType == Img_PGMGray) { TempImage = Alloc_2D_UCHAR(Gray_Image_Width, Gray_Image_Height); EWWidth = Gray_Image_Width; EWHeight = Gray_Image_Height; } else { TempImage = Alloc_2D_UCHAR(pEWbmpImage->Width, pEWbmpImage->Height); EWWidth = pEWbmpImage->Width; EWHeight = pEWbmpImage->Height; } // key if (EWKImageType == Img_PGMGray) { TempImageKey = Alloc_2D_char(Gray_Image_Key_Width, Gray_Image_Key_Height); EWKeyWidth = Gray_Image_Key_Width; EWKeyHeight = Gray_Image_Key_Height; } else { TempImageKey = Alloc_2D_char(pEWKeybmpImage->Width, pEWKeybmpImage->Height); EWKeyWidth = pEWKeybmpImage->Width; EWKeyHeight = pEWKeybmpImage->Height; } Red = Alloc_2D_UCHAR(AviWidth, AviHeight); Green = Alloc_2D_UCHAR(AviWidth, AviHeight); Blue = Alloc_2D_UCHAR(AviWidth, AviHeight); waveRed = Alloc_2D_Double(AviWidth, AviHeight); waveGreen = Alloc_2D_Double(AviWidth, AviHeight); waveBlue = Alloc_2D_Double(AviWidth, AviHeight); int wLL = AviWidth >> DWTLevels; int hLL = AviHeight >> DWTLevels; /*********************************/ /* Determine Incriment positions */ DWTSegmentAdrs[0].x = 0; DWTSegmentAdrs[0].y = 0; /****************/ /* Level=3 */ DWTSegmentAdrs[1].x = 0; DWTSegmentAdrs[1].y = hLL; DWTSegmentAdrs[2].x = wLL; DWTSegmentAdrs[2].y = 0; DWTSegmentAdrs[3].x = wLL; DWTSegmentAdrs[3].y = hLL; szSeg = 4; if (DWTLevels > 1) { /****************/ /* Level=2 */ DWTSegmentAdrs[4].x = 0; // South - West DWTSegmentAdrs[4].y = hLL<<1; // hLL*2 DWTSegmentAdrs[5].x = wLL<<1; // North - East DWTSegmentAdrs[5].y = 0; DWTSegmentAdrs[6].x = wLL<<1; // Diagonal DWTSegmentAdrs[6].y = hLL<<1; // hLL * 2 szSeg = 7; if (DWTLevels == 3) { /****************/ /* Level=1 */ DWTSegmentAdrs[7].x = 0; DWTSegmentAdrs[7].y = hLL<<2; DWTSegmentAdrs[8].x = wLL<<2; DWTSegmentAdrs[8].y = 0; DWTSegmentAdrs[9].x = wLL<<2; DWTSegmentAdrs[9].y = hLL<<2; /*********************************/ szSeg = 10; } } // Determine embed starting and ending positions. // Only supports embedding in Level 1 or 2 after DWT_Level_2 or DWT_Level_3 transform if ((DWTLevels == 2) && (LevelEmbed == 1)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } else if ((DWTLevels == 2) && (LevelEmbed == 2)) { StartEmbedHorW = DWTSegmentAdrs[1].x; StartEmbedHorH = DWTSegmentAdrs[1].y; StartEmbedVerW = DWTSegmentAdrs[2].x; StartEmbedVerH = DWTSegmentAdrs[2].y; EmbedHorW = StartEmbedHorW + wLL; EmbedHorH = StartEmbedHorH + hLL; EmbedVerW = StartEmbedVerW + wLL; EmbedVerH = StartEmbedVerH + hLL; } else if ((DWTLevels == 3) && (LevelEmbed == 1)) { StartEmbedHorW = DWTSegmentAdrs[7].x; StartEmbedHorH = DWTSegmentAdrs[7].y; StartEmbedVerW = DWTSegmentAdrs[8].x; StartEmbedVerH = DWTSegmentAdrs[8].y; EmbedHorW = StartEmbedHorW + wLL * 4; EmbedHorH = StartEmbedHorH + hLL * 4; EmbedVerW = StartEmbedVerW + wLL * 4; EmbedVerH = StartEmbedVerH + hLL * 4; } else if ((DWTLevels == 3) && (LevelEmbed == 2)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } // long AviWidth, AviHeight, i, j, iImg, jImg, iImgKey, jImgKey; // long tmpW, tmpH, EWWidth, EWHeight, EWKeyWidth, EWKeyHeight; // long EmbedHorW, EmbedHorH, EmbedVerW, EmbedVerH; // long StartEmbedHorW, StartEmbedHorH, StartEmbedVerW, StartEmbedVerH; // don't scale watermark image. we don't need. if (EWImageType == Img_PGMGray) { // scale watermark image to for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { TempImage[i][j] = Gray_Image[i][j]; } } } else { // scale watermark image to for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { TempImage[i][j] = (UCHAR)(pEWbmpImage->Canvas->Pixels[j][i] & 0xFF); } } } // Scale Key Image to 0-1 if (EWKImageType == Img_PGMGray) { // scale watermark image to for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { //TempImageKey[i][j] = (double)Gray_Image_Key[i][j] / 255.0; TempImageKey[i][j] = Gray_Image_Key[i][j]; } } } else { // scale watermark image to for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { //TempImageKey[i][j] = (double)( pEWKeybmpImage->Canvas->Pixels[j][i] & 0xFF ) / 255.0; TempImageKey[i][j] = (ULONG)pEWKeybmpImage->Canvas->Pixels[j][i] & 0xFF; } } } for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { if (TempImageKey[i][j] == 0) TempImageKey[i][j] = -1; else TempImageKey[i][j] = 1; } } int tmpImGGG; int aaH, abH, baH, bbH, aaW, abW, baW, bbW; FormEmbedVideo->ButtonCancel->Enabled = true; FormEmbedVideo->ButtonEmbed->Enabled = false; FormEmbedVideo->LabelBlink->Visible = true; Application->ProcessMessages(); for(iFrm=0; iFrm<NumFrames; iFrm++) // for each frame { // Read Video RDGetFrame(AviIn, iFrm, Red, Green, Blue); // DWT Transform waveletTransform2D(Red, waveRed, AviWidth, AviHeight, DWTLevels, true); waveletTransform2D(Green, waveGreen, AviWidth, AviHeight, DWTLevels, true); waveletTransform2D(Blue, waveBlue, AviWidth, AviHeight, DWTLevels, true); // EMBED the image for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { tmpImGGG = TempImage[i][j]; if (tmpImGGG > 0 ) tmpImGGG = -1; else tmpImGGG = 1; is = i*2; js = j*2; // Horizontal scan positions aaH = StartEmbedHorH + is; // + 0 abH = StartEmbedHorH + is + 1; aaW = StartEmbedHorW + js; // + 0 abW = StartEmbedHorW + js + 1; // Vertical scan positions baH = StartEmbedVerH + is; // + 0 bbH = StartEmbedVerH + is + 1; baW = StartEmbedVerW + js; // + 0 bbW = StartEmbedVerW + js + 1; // RED // Horizontal Scan waveRed[aaH][aaW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveRed[aaH][abW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveRed[abH][aaW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveRed[abH][abW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // Vertical Scan waveRed[baH][baW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveRed[baH][bbW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveRed[bbH][baW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveRed[bbH][bbW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // GREEN // Horizontal Scan waveGreen[aaH][aaW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveGreen[aaH][abW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveGreen[abH][aaW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveGreen[abH][abW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // Vertical Scan waveGreen[baH][baW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveGreen[baH][bbW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveGreen[bbH][baW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveGreen[bbH][bbW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // BLUE // Horizontal Scan waveBlue[aaH][aaW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveBlue[aaH][abW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveBlue[abH][aaW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveBlue[abH][abW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // Vertical Scan waveBlue[baH][baW] += GainFactor * TempImageKey[is][js] * tmpImGGG; waveBlue[baH][bbW] += GainFactor * TempImageKey[is][js+1] * tmpImGGG; waveBlue[bbH][baW] += GainFactor * TempImageKey[is+1][js] * tmpImGGG; waveBlue[bbH][bbW] += GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; } // j } // i /* Inverse wavelet transform.Back to Image matrix */ waveletTransform2D(Red, waveRed, AviWidth, AviHeight, DWTLevels, false); waveletTransform2D(Green, waveGreen, AviWidth, AviHeight, DWTLevels, false); waveletTransform2D(Blue, waveBlue, AviWidth, AviHeight, DWTLevels, false); /* WRITE Image to NEW AVI File */ AddAviFrameMatrix(AviOut, AviWidth, AviHeight, Red, Green, Blue); FormEmbedVideo->LabelEmbed->Caption = IntToStr(iFrm+1) + "/" + IntToStr(NumFrames) + " frames"; FormEmbedVideo->BarEmbed->Percent = ((iFrm+1)*100)/NumFrames; Application->ProcessMessages(); if (FormEmbedVideo->CancelEmbed) { FormEmbedVideo->ButtonCancel->Enabled = false; FormEmbedVideo->ButtonEmbed->Enabled = true; FormEmbedVideo->LabelBlink->Visible = false; StreamCopyAudio(AviIn, AviOut); // Close and Free all handles Free_2D_UCHAR(TempImage, EWHeight); Free_2D_char(TempImageKey, EWKeyHeight); Free_2D_UCHAR(Red, AviHeight); Free_2D_UCHAR(Green, AviHeight); Free_2D_UCHAR(Blue, AviHeight); Free_2D_Double(waveRed, AviHeight); Free_2D_Double(waveGreen, AviHeight); Free_2D_Double(waveBlue, AviHeight); RDCloseAvi(AviIn); CloseAvi(AviOut); inAvi = NULL; outAvi = NULL; return true; } Application->ProcessMessages(); } FormEmbedVideo->ButtonEmbed->Enabled = true; FormEmbedVideo->ButtonCancel->Enabled = false; FormEmbedVideo->LabelBlink->Visible = false; StreamCopyAudio(AviIn, AviOut); // Close and Free all handles Free_2D_UCHAR(TempImage, EWHeight); Free_2D_char(TempImageKey, EWKeyHeight); Free_2D_UCHAR(Red, AviHeight); Free_2D_UCHAR(Green, AviHeight); Free_2D_UCHAR(Blue, AviHeight); Free_2D_Double(waveRed, AviHeight); Free_2D_Double(waveGreen, AviHeight); Free_2D_Double(waveBlue, AviHeight); RDCloseAvi(AviIn); CloseAvi(AviOut); inAvi = NULL; outAvi = NULL; return true; } /* Detect AVI Video */ int RecoverWatermarkAVI_Chasan( HWND thisHwnd, AnsiString inVideoFileName, // watermark inputs Graphics::TBitmap *pRWbmpImage, stcImageType RWImageType, UCHAR **Gray_Image_RW, long Gray_Image_RW_Width, long Gray_Image_RW_Height, // Key Image inputs Graphics::TBitmap *pRWKeybmpImage, stcImageType RWKImageType, UCHAR **Gray_Image_RW_Key, long Gray_Image_RW_Key_Width, long Gray_Image_RW_Key_Height, // embed inputs double BetaFactorRW, int DWTLevelsRW, // wavelet tansform level int LevelEmbedRW, // in which level watermark has been embedded bool AllFrames, long FrameNo) { long AviWidth, AviHeight, i, j, iImg, jImg, iImgKey, jImgKey, NumFrames, iFrm, is, js; long tmpW, tmpH, RWWidth, RWHeight, RWKeyWidth, RWKeyHeight; long EmbedHorW, EmbedHorH, EmbedVerW, EmbedVerH; long StartEmbedHorW, StartEmbedHorH, StartEmbedVerW, StartEmbedVerH; TAviUtil *inAvi; HAVI AviIn; UCHAR **TempImage; char **TempImageKey; UCHAR **Red, **Green, **Blue; double **waveRed, **waveGreen, **waveBlue; BlockInfoStrc DWTSegmentAdrs[10]; int szSeg; Graphics::TBitmap *pBitmapTMP; int tmpImGGG; int aaH, abH, baH, bbH, aaW, abW, baW, bbW; double mA1, mA2, mcorr, corr, corr1, corr2, A11, A12, A13, A14, A21, A22, A23, A24, mB, B, B1, B2, B3, B4; double tmp, tmp1, tmp2, tmp3, fThreshold, mCorrRed, mCorrGreen, mCorrBlue, WatCorr, WatBER; double *tmpCorrM; TListItem *ListItem; AnsiString strTmp; // ------------------------ // CHECK 1 // there must be two images if ((RWKImageType == Img_NONE)) { MessageDlg("You must select a Watermark and Key image.", mtError, TMsgDlgButtons() << mbOK, 0); return false; } // ----------------------------------------------------------- // CHECK 2 // Key image sizes MUST be equal to video DWT level size. // Open the AVI file and set handle AviIn = RDOpenAviFile(inVideoFileName.c_str(), true); if (AviIn == NULL) { DispError("ERROR! Cannot open AVI file."); return S_FALSE; } inAvi = (TAviUtil*)AviIn; AviWidth = inAvi->iWidth; AviHeight = inAvi->iHeight; NumFrames = inAvi->numframes; if ( DWTLevelsRW < LevelEmbedRW ) { MessageDlg("DWT Levels cannot be smaller than Embed Levels.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // Check the dimensions for compatability. if (AviWidth%(1 << DWTLevelsRW) || AviHeight%(1 << DWTLevelsRW)) { AnsiString sss = "width and height of input video must be divisible by 2^" + IntToStr(DWTLevelsRW) + " = " + IntToStr((int)pow(2, DWTLevelsRW)); MessageDlg(sss, mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } if ((DWTLevelsRW == 2) || (DWTLevelsRW == 3)) { if (LevelEmbedRW == 1) { tmpW = AviWidth >> 1; // division by 2 tmpH = AviHeight >> 1; } else if (LevelEmbedRW == 2) { tmpW = AviWidth >> 2; // division by 4 tmpH = AviHeight >> 2; } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // if we came this far, inAvi structure is still open. // We will continue to use this structure. /* Allocate required buffers */ // original watermark if (RWImageType == Img_PGMGray) { TempImage = Alloc_2D_UCHAR(Gray_Image_RW_Width, Gray_Image_RW_Height); RWWidth = Gray_Image_RW_Width; RWHeight = Gray_Image_RW_Height; } else if (RWImageType != Img_NONE) { TempImage = Alloc_2D_UCHAR(pRWbmpImage->Width, pRWbmpImage->Height); RWWidth = pRWbmpImage->Width; RWHeight = pRWbmpImage->Height; } // key if (RWKImageType == Img_PGMGray) { TempImageKey = Alloc_2D_char(Gray_Image_RW_Key_Width, Gray_Image_RW_Key_Height); RWKeyWidth = Gray_Image_RW_Key_Width; RWKeyHeight = Gray_Image_RW_Key_Height; } else { TempImageKey = Alloc_2D_char(pRWKeybmpImage->Width, pRWKeybmpImage->Height); RWKeyWidth = pRWKeybmpImage->Width; RWKeyHeight = pRWKeybmpImage->Height; } Red = Alloc_2D_UCHAR(AviWidth, AviHeight); Green = Alloc_2D_UCHAR(AviWidth, AviHeight); Blue = Alloc_2D_UCHAR(AviWidth, AviHeight); waveRed = Alloc_2D_Double(AviWidth, AviHeight); waveGreen = Alloc_2D_Double(AviWidth, AviHeight); waveBlue = Alloc_2D_Double(AviWidth, AviHeight); int wLL = AviWidth >> DWTLevelsRW; int hLL = AviHeight >> DWTLevelsRW; /*********************************/ /* Determine Incriment positions */ DWTSegmentAdrs[0].x = 0; DWTSegmentAdrs[0].y = 0; /****************/ /* Level=3 */ DWTSegmentAdrs[1].x = 0; DWTSegmentAdrs[1].y = hLL; DWTSegmentAdrs[2].x = wLL; DWTSegmentAdrs[2].y = 0; DWTSegmentAdrs[3].x = wLL; DWTSegmentAdrs[3].y = hLL; szSeg = 4; if (DWTLevelsRW > 1) { /****************/ /* Level=2 */ DWTSegmentAdrs[4].x = 0; // South - West DWTSegmentAdrs[4].y = hLL<<1; // hLL*2 DWTSegmentAdrs[5].x = wLL<<1; // North - East DWTSegmentAdrs[5].y = 0; DWTSegmentAdrs[6].x = wLL<<1; // Diagonal DWTSegmentAdrs[6].y = hLL<<1; // hLL * 2 szSeg = 7; if (DWTLevelsRW == 3) { /****************/ /* Level=1 */ DWTSegmentAdrs[7].x = 0; DWTSegmentAdrs[7].y = hLL<<2; DWTSegmentAdrs[8].x = wLL<<2; DWTSegmentAdrs[8].y = 0; DWTSegmentAdrs[9].x = wLL<<2; DWTSegmentAdrs[9].y = hLL<<2; /*********************************/ szSeg = 10; } } // Determine embed starting and ending positions. // Only supports embedding in Level 1 or 2 after DWT_Level_2 or DWT_Level_3 transform if ((DWTLevelsRW == 2) && (LevelEmbedRW == 1)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } else if ((DWTLevelsRW == 2) && (LevelEmbedRW == 2)) { StartEmbedHorW = DWTSegmentAdrs[1].x; StartEmbedHorH = DWTSegmentAdrs[1].y; StartEmbedVerW = DWTSegmentAdrs[2].x; StartEmbedVerH = DWTSegmentAdrs[2].y; EmbedHorW = StartEmbedHorW + wLL; EmbedHorH = StartEmbedHorH + hLL; EmbedVerW = StartEmbedVerW + wLL; EmbedVerH = StartEmbedVerH + hLL; } else if ((DWTLevelsRW == 3) && (LevelEmbedRW == 1)) { StartEmbedHorW = DWTSegmentAdrs[7].x; StartEmbedHorH = DWTSegmentAdrs[7].y; StartEmbedVerW = DWTSegmentAdrs[8].x; StartEmbedVerH = DWTSegmentAdrs[8].y; EmbedHorW = StartEmbedHorW + wLL * 4; EmbedHorH = StartEmbedHorH + hLL * 4; EmbedVerW = StartEmbedVerW + wLL * 4; EmbedVerH = StartEmbedVerH + hLL * 4; } else if ((DWTLevelsRW == 3) && (LevelEmbedRW == 2)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } // fill temp watermark image matrix if (RWImageType == Img_PGMGray) { for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { TempImage[i][j] = Gray_Image_RW[i][j]; } } } else if (RWImageType != Img_NONE) { for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { TempImage[i][j] = (UCHAR)(pRWbmpImage->Canvas->Pixels[j][i] & 0xFF); } } } // fill temp key image matrix if (RWKImageType == Img_PGMGray) { for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { TempImageKey[i][j] = Gray_Image_RW_Key[i][j]; } } } else { for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { TempImageKey[i][j] = (ULONG)pRWKeybmpImage->Canvas->Pixels[j][i] & 0xFF; } } } for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { if (TempImageKey[i][j] == 0) TempImageKey[i][j] = -1; else TempImageKey[i][j] = 1; } } // temporary recover image pBitmapTMP = new Graphics::TBitmap(); pBitmapTMP->PixelFormat = pf24bit; pBitmapTMP->Width = RWKeyWidth/2; pBitmapTMP->Height = RWKeyHeight/2; TCanvas *tmpCanvas = pBitmapTMP->Canvas; if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = true; FormRecover->ButtonRecover->Enabled = false; } else { FormRecover->ButtonCancel->Enabled = true; FormRecover->ButtonCalcBER->Enabled = false; } FormRecover->GroupBoxOptions->Enabled = false; FormRecover->ListResult->Items->Clear(); Application->ProcessMessages(); tmpCorrM = (double *)malloc((RWKeyWidth/2) * (RWKeyHeight/2) * sizeof(double)); for(iFrm=0; iFrm<NumFrames; iFrm++) // for each frame { // Read Video if (!AllFrames) // only one frame { RDGetFrame(AviIn, FrameNo, Red, Green, Blue); } else // all frames { RDGetFrame(AviIn, iFrm, Red, Green, Blue); } // DWT Transform waveletTransform2D(Red, waveRed, AviWidth, AviHeight, DWTLevelsRW, true); waveletTransform2D(Green, waveGreen, AviWidth, AviHeight, DWTLevelsRW, true); waveletTransform2D(Blue, waveBlue, AviWidth, AviHeight, DWTLevelsRW, true); corr = 0.0; for(i=0; i < RWKeyHeight/2; i++) { for(j=0; j < RWKeyWidth/2; j++) { is = i*2; js = j*2; // Horizontal scan positions aaH = StartEmbedHorH + is; // + 0 abH = StartEmbedHorH + is + 1; aaW = StartEmbedHorW + js; // + 0 abW = StartEmbedHorW + js + 1; // Vertical scan positions baH = StartEmbedVerH + is; // + 0 bbH = StartEmbedVerH + is + 1; baW = StartEmbedVerW + js; // + 0 bbW = StartEmbedVerW + js + 1; // RED // image matrix elements A11 = waveRed[aaH][aaW]; A12 = waveRed[aaH][abW]; A13 = waveRed[abH][aaW]; A14 = waveRed[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = waveRed[baH][baW]; A22 = waveRed[baH][bbW]; A23 = waveRed[bbH][baW]; A24 = waveRed[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrRed = (corr1 + corr2)/2.0; // GREEN // image matrix elements A11 = waveGreen[aaH][aaW]; A12 = waveGreen[aaH][abW]; A13 = waveGreen[abH][aaW]; A14 = waveGreen[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = waveGreen[baH][baW]; A22 = waveGreen[baH][bbW]; A23 = waveGreen[bbH][baW]; A24 = waveGreen[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrGreen = (corr1 + corr2)/2.0; // BLUE // image matrix elements A11 = waveBlue[aaH][aaW]; A12 = waveBlue[aaH][abW]; A13 = waveBlue[abH][aaW]; A14 = waveBlue[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = waveBlue[baH][baW]; A22 = waveBlue[baH][bbW]; A23 = waveBlue[bbH][baW]; A24 = waveBlue[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrBlue = (corr1 + corr2)/2.0; // find the biggest correlation mcorr = mCorrRed; if (mCorrGreen > mcorr) mcorr = mCorrGreen; if (mCorrBlue > mcorr) mcorr = mCorrBlue; // add current correlation to total correlation tmpCorrM[i * RWKeyWidth/2 + j] = mcorr; } // j } // i // find mean correlation corr = 0.0; for(i=0; i < (RWKeyWidth * RWKeyHeight)/4; i++) { corr+= tmpCorrM[i]; } mcorr = corr / (double)((RWKeyWidth * RWKeyHeight)/4.0); // find final theshold fThreshold = BetaFactorRW * mcorr; if (!AllFrames) // only one frame { // display image for(i=0; i < RWKeyHeight/2; i++) { for(j=0; j < RWKeyWidth/2; j++) { if ( tmpCorrM[i * RWKeyWidth/2 + j] >= fThreshold) tmpCanvas->Pixels[j][i] = (TColor)RGB(0, 0, 0); else tmpCanvas->Pixels[j][i] = (TColor)RGB(255, 255, 255); } } FormRecover->ImageRecover->Picture->Assign(pBitmapTMP); FormRecover->ButtonSaveImage->Enabled = true; FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; FormRecover->GroupBoxOptions->Enabled = true; // display BitErrors (BER) if (FormMain->RWImageType != Img_NONE) { // find BER and means WatBER = 0; for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { if ( (tmpCanvas->Pixels[j][i] & 0xFF ) != TempImage[i][j]) WatBER += 1; } } WatBER = (WatBER * 100)/ (RWWidth * RWHeight); ListItem = FormRecover->ListResult->Items->Add(); // FrameNo ListItem->Caption = IntToStr(FrameNo); // BER strTmp.sprintf("%3.2f", WatBER); ListItem->SubItems->Add( strTmp ); } delete pBitmapTMP; if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_UCHAR(Red, AviHeight); Free_2D_UCHAR(Green, AviHeight); Free_2D_UCHAR(Blue, AviHeight); Free_2D_Double(waveRed, AviHeight); Free_2D_Double(waveGreen, AviHeight); Free_2D_Double(waveBlue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; } else // all frames { FormRecover->LabelRecover->Caption = IntToStr(iFrm+1) + "/" + IntToStr(NumFrames) + " frames"; FormRecover->BarRecover->Percent = ((iFrm+1)*100)/NumFrames; // add MER line into List // display BitErrors (BER) if (FormMain->RWImageType != Img_NONE) { // find BER and means WatBER = 0; for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { if ( tmpCorrM[i * RWKeyWidth/2 + j] >= fThreshold) szSeg = 0; else szSeg = 255; if ( szSeg != TempImage[i][j]) WatBER += 1; } } WatBER = (WatBER * 100)/ (RWWidth * RWHeight); ListItem = FormRecover->ListResult->Items->Add(); // FrameNo ListItem->Caption = IntToStr(iFrm); // BER strTmp.sprintf("%3.2f", WatBER); FormRecover->recAllFrames = FormRecover->recAllFrames + strTmp + ", "; ListItem->SubItems->Add( strTmp ); } } Application->ProcessMessages(); if (FormRecover->cancelRecover) { if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; } else { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonCalcBER->Enabled = true; } FormRecover->GroupBoxOptions->Enabled = true; // Close and Free all handles if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_UCHAR(Red, AviHeight); Free_2D_UCHAR(Green, AviHeight); Free_2D_UCHAR(Blue, AviHeight); Free_2D_Double(waveRed, AviHeight); Free_2D_Double(waveGreen, AviHeight); Free_2D_Double(waveBlue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; } Application->ProcessMessages(); } if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; } else { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonCalcBER->Enabled = true; FormRecover->ButtonSaveResults->Enabled = true; } FormRecover->GroupBoxOptions->Enabled = true; // Close and Free all handles if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_UCHAR(Red, AviHeight); Free_2D_UCHAR(Green, AviHeight); Free_2D_UCHAR(Blue, AviHeight); Free_2D_Double(waveRed, AviHeight); Free_2D_Double(waveGreen, AviHeight); Free_2D_Double(waveBlue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; } int EmbedWatermarkAVI_Lifting( HWND thisHwnd, AnsiString inVideoFileName, AnsiString outVideoFileName, // watermark inputs Graphics::TBitmap *pEWbmpImage, stcImageType EWImageType, UCHAR **Gray_Image, long Gray_Image_Width, long Gray_Image_Height, // Key Image inputs Graphics::TBitmap *pEWKeybmpImage, stcImageType EWKImageType, UCHAR **Gray_Image_Key, long Gray_Image_Key_Width, long Gray_Image_Key_Height, // embed inputs double GainFactor, // gain factor needed at embedding time int DWTLevels, // wavelet tansform level int LevelEmbed ) // Which level watermark will be embedded { long AviWidth, AviHeight, i, j, iImg, jImg, iImgKey, jImgKey, NumFrames, iFrm, is, js; long tmpW, tmpH, EWWidth, EWHeight, EWKeyWidth, EWKeyHeight; long EmbedHorW, EmbedHorH, EmbedVerW, EmbedVerH; long StartEmbedHorW, StartEmbedHorH, StartEmbedVerW, StartEmbedVerH; TAviUtil *inAvi, *outAvi; HAVI AviIn, AviOut; UCHAR **TempImage; char **TempImageKey; int **Red, **Green, **Blue; BlockInfoStrc DWTSegmentAdrs[10]; int szSeg; // ------------------------ // CHECK 1 // there must be two images if ((EWImageType == Img_NONE) || (EWKImageType == Img_NONE) || (EWImageType == EWKImageType)) { MessageDlg("You must select a Watermark and Key image.", mtError, TMsgDlgButtons() << mbOK, 0); return false; } // ----------------------------------------------------------- // CHECK 2 // Key image sizes MUST be equal to video DWT level size. // Open the AVI file and set handle AviIn = RDOpenAviFile(inVideoFileName.c_str(), true); if (AviIn == NULL) { DispError("ERROR! Cannot open AVI file."); return S_FALSE; } inAvi = (TAviUtil*)AviIn; AviWidth = inAvi->iWidth; AviHeight = inAvi->iHeight; NumFrames = inAvi->numframes; if ( DWTLevels < LevelEmbed ) { MessageDlg("DWT Levels cannot be smaller than Embed Levels.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // Check the dimensions for compatability. if (AviWidth%(1 << DWTLevels) || AviHeight%(1 << DWTLevels)) { AnsiString sss = "width and height of input video must be divisible by 2^" + IntToStr(DWTLevels) + " = " + IntToStr((int)pow(2, DWTLevels)); MessageDlg(sss, mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } if ((DWTLevels == 2) || (DWTLevels == 3)) { if (LevelEmbed == 1) { tmpW = AviWidth >> 1; // division by 2 tmpH = AviHeight >> 1; } else if (LevelEmbed == 2) { tmpW = AviWidth >> 2; // division by 4 tmpH = AviHeight >> 2; } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // Erase file if exists if (FileExists(outVideoFileName.c_str())) DeleteFileA(outVideoFileName.c_str()); // Create Avi AviOut = CreateAvi(outVideoFileName.c_str(), inAvi->AviInfo.dwScale, inAvi->AviInfo.dwRate, NULL); if (MessageBox(thisHwnd, "Do you want to compress output AVI?","Question", MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES) { HBITMAP hbm; HDC hdcscreen=GetDC(0), hdc=CreateCompatibleDC(hdcscreen); ReleaseDC(0,hdcscreen); BITMAPINFO bmi; ZeroMemory(&bmi,sizeof(bmi)); BITMAPINFOHEADER &bih = bmi.bmiHeader; bih.biSize = sizeof(bih); bih.biWidth = AviWidth; bih.biHeight = AviHeight; bih.biPlanes = 1; bih.biBitCount = 24; bih.biCompression = BI_RGB; bih.biSizeImage = ((bih.biWidth*bih.biBitCount/8+3)&0xFFFFFFFC)*bih.biHeight; bih.biXPelsPerMeter = 1; bih.biYPelsPerMeter = 1; bih.biClrUsed = 0; bih.biClrImportant = 0; void *bits; hbm = CreateDIBSection(hdc,(BITMAPINFO*)&bih,DIB_RGB_COLORS,&bits,NULL,NULL); AVICOMPRESSOPTIONS opts; ZeroMemory(&opts,sizeof(opts)); opts.fccHandler = mmioFOURCC('d','i','v','x'); SetAviVideoCompression(AviOut, hbm, &opts, true, thisHwnd); DeleteDC(hdc); DeleteObject(hbm); } /* Allocate required buffers */ // watermark if (EWImageType == Img_PGMGray) { TempImage = Alloc_2D_UCHAR(Gray_Image_Width, Gray_Image_Height); EWWidth = Gray_Image_Width; EWHeight = Gray_Image_Height; } else { TempImage = Alloc_2D_UCHAR(pEWbmpImage->Width, pEWbmpImage->Height); EWWidth = pEWbmpImage->Width; EWHeight = pEWbmpImage->Height; } // key if (EWKImageType == Img_PGMGray) { TempImageKey = Alloc_2D_char(Gray_Image_Key_Width, Gray_Image_Key_Height); EWKeyWidth = Gray_Image_Key_Width; EWKeyHeight = Gray_Image_Key_Height; } else { TempImageKey = Alloc_2D_char(pEWKeybmpImage->Width, pEWKeybmpImage->Height); EWKeyWidth = pEWKeybmpImage->Width; EWKeyHeight = pEWKeybmpImage->Height; } Red = Alloc_2D_Int(AviWidth, AviHeight); Green = Alloc_2D_Int(AviWidth, AviHeight); Blue = Alloc_2D_Int(AviWidth, AviHeight); int wLL = AviWidth >> DWTLevels; int hLL = AviHeight >> DWTLevels; /*********************************/ /* Determine Incriment positions */ DWTSegmentAdrs[0].x = 0; DWTSegmentAdrs[0].y = 0; /****************/ /* Level=3 */ DWTSegmentAdrs[1].x = 0; DWTSegmentAdrs[1].y = hLL; DWTSegmentAdrs[2].x = wLL; DWTSegmentAdrs[2].y = 0; DWTSegmentAdrs[3].x = wLL; DWTSegmentAdrs[3].y = hLL; szSeg = 4; if (DWTLevels > 1) { /****************/ /* Level=2 */ DWTSegmentAdrs[4].x = 0; // South - West DWTSegmentAdrs[4].y = hLL<<1; // hLL*2 DWTSegmentAdrs[5].x = wLL<<1; // North - East DWTSegmentAdrs[5].y = 0; DWTSegmentAdrs[6].x = wLL<<1; // Diagonal DWTSegmentAdrs[6].y = hLL<<1; // hLL * 2 szSeg = 7; if (DWTLevels == 3) { /****************/ /* Level=1 */ DWTSegmentAdrs[7].x = 0; DWTSegmentAdrs[7].y = hLL<<2; DWTSegmentAdrs[8].x = wLL<<2; DWTSegmentAdrs[8].y = 0; DWTSegmentAdrs[9].x = wLL<<2; DWTSegmentAdrs[9].y = hLL<<2; /*********************************/ szSeg = 10; } } // Determine embed starting and ending positions. // Only supports embedding in Level 1 or 2 after DWT_Level_2 or DWT_Level_3 transform if ((DWTLevels == 2) && (LevelEmbed == 1)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } else if ((DWTLevels == 2) && (LevelEmbed == 2)) { StartEmbedHorW = DWTSegmentAdrs[1].x; StartEmbedHorH = DWTSegmentAdrs[1].y; StartEmbedVerW = DWTSegmentAdrs[2].x; StartEmbedVerH = DWTSegmentAdrs[2].y; EmbedHorW = StartEmbedHorW + wLL; EmbedHorH = StartEmbedHorH + hLL; EmbedVerW = StartEmbedVerW + wLL; EmbedVerH = StartEmbedVerH + hLL; } else if ((DWTLevels == 3) && (LevelEmbed == 1)) { StartEmbedHorW = DWTSegmentAdrs[7].x; StartEmbedHorH = DWTSegmentAdrs[7].y; StartEmbedVerW = DWTSegmentAdrs[8].x; StartEmbedVerH = DWTSegmentAdrs[8].y; EmbedHorW = StartEmbedHorW + wLL * 4; EmbedHorH = StartEmbedHorH + hLL * 4; EmbedVerW = StartEmbedVerW + wLL * 4; EmbedVerH = StartEmbedVerH + hLL * 4; } else if ((DWTLevels == 3) && (LevelEmbed == 2)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } // don't scale watermark image. we don't need. if (EWImageType == Img_PGMGray) { // scale watermark image to for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { TempImage[i][j] = Gray_Image[i][j]; } } } else { // scale watermark image to for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { TempImage[i][j] = (UCHAR)(pEWbmpImage->Canvas->Pixels[j][i] & 0xFF); } } } // Scale Key Image to 0-1 if (EWKImageType == Img_PGMGray) { // scale watermark image to for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { //TempImageKey[i][j] = (double)Gray_Image_Key[i][j] / 255.0; TempImageKey[i][j] = Gray_Image_Key[i][j]; } } } else { // scale watermark image to for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { //TempImageKey[i][j] = (double)( pEWKeybmpImage->Canvas->Pixels[j][i] & 0xFF ) / 255.0; TempImageKey[i][j] = (ULONG)pEWKeybmpImage->Canvas->Pixels[j][i] & 0xFF; } } } for(i=0; i < EWKeyHeight; i++) { for(j=0; j < EWKeyWidth; j++) { if (TempImageKey[i][j] == 0) TempImageKey[i][j] = -1; else TempImageKey[i][j] = 1; } } int tmpImGGG; int aaH, abH, baH, bbH, aaW, abW, baW, bbW; int ADD1, ADD2, ADD3, ADD4; FormEmbedVideo->ButtonCancel->Enabled = true; FormEmbedVideo->ButtonEmbed->Enabled = false; FormEmbedVideo->LabelBlink->Visible = true; Application->ProcessMessages(); for(iFrm=0; iFrm<NumFrames; iFrm++) // for each frame { // Read Video RDGetFrame_Int(AviIn, iFrm, Red, Green, Blue); // DWT Transform l97_2D(Red, AviWidth, AviHeight, DWTLevels, false); l97_2D(Green, AviWidth, AviHeight, DWTLevels, false); l97_2D(Blue, AviWidth, AviHeight, DWTLevels, false); // EMBED the image for(i=0; i < EWHeight; i++) { for(j=0; j < EWWidth; j++) { tmpImGGG = TempImage[i][j]; if (tmpImGGG > 0 ) tmpImGGG = -1; else tmpImGGG = 1; is = i<<1; // i*2; js = j<<1; // j*2; // Horizontal scan positions aaH = StartEmbedHorH + is; // + 0 abH = StartEmbedHorH + is + 1; aaW = StartEmbedHorW + js; // + 0 abW = StartEmbedHorW + js + 1; // Vertical scan positions baH = StartEmbedVerH + is; // + 0 bbH = StartEmbedVerH + is + 1; baW = StartEmbedVerW + js; // + 0 bbW = StartEmbedVerW + js + 1; // calculate affect factors ADD1 = GainFactor * TempImageKey[is][js] * tmpImGGG; ADD2 = GainFactor * TempImageKey[is][js+1] * tmpImGGG; ADD3 = GainFactor * TempImageKey[is+1][js] * tmpImGGG; ADD4 = GainFactor * TempImageKey[is+1][js+1] * tmpImGGG; // RED // Horizontal Scan Red[aaH][aaW] += ADD1; Red[aaH][abW] += ADD2; Red[abH][aaW] += ADD3; Red[abH][abW] += ADD4; // Vertical Scan Red[baH][baW] += ADD1; Red[baH][bbW] += ADD2; Red[bbH][baW] += ADD3; Red[bbH][bbW] += ADD4; // GREEN // Horizontal Scan Green[aaH][aaW] += ADD1; Green[aaH][abW] += ADD2; Green[abH][aaW] += ADD3; Green[abH][abW] += ADD4; // Vertical Scan Green[baH][baW] += ADD1; Green[baH][bbW] += ADD2; Green[bbH][baW] += ADD3; Green[bbH][bbW] += ADD4; // BLUE // Horizontal Scan Blue[aaH][aaW] += ADD1; Blue[aaH][abW] += ADD2; Blue[abH][aaW] += ADD3; Blue[abH][abW] += ADD4; // Vertical Scan Blue[baH][baW] += ADD1; Blue[baH][bbW] += ADD2; Blue[bbH][baW] += ADD3; Blue[bbH][bbW] += ADD4; } // j } // i /* Inverse wavelet transform.Back to Image matrix */ l97_2D(Red, AviWidth, AviHeight, DWTLevels, true); l97_2D(Green, AviWidth, AviHeight, DWTLevels, true); l97_2D(Blue, AviWidth, AviHeight, DWTLevels, true); /* WRITE Image to NEW AVI File */ AddAviFrameMatrix_Int(AviOut, AviWidth, AviHeight, Red, Green, Blue); FormEmbedVideo->LabelEmbed->Caption = IntToStr(iFrm+1) + "/" + IntToStr(NumFrames) + " frames"; FormEmbedVideo->BarEmbed->Percent = ((iFrm+1)*100)/NumFrames; Application->ProcessMessages(); if (FormEmbedVideo->CancelEmbed) { FormEmbedVideo->ButtonCancel->Enabled = false; FormEmbedVideo->ButtonEmbed->Enabled = true; FormEmbedVideo->LabelBlink->Visible = false; StreamCopyAudio(AviIn, AviOut); // Close and Free all handles Free_2D_UCHAR(TempImage, EWHeight); Free_2D_char(TempImageKey, EWKeyHeight); Free_2D_Int(Red, AviHeight); Free_2D_Int(Green, AviHeight); Free_2D_Int(Blue, AviHeight); RDCloseAvi(AviIn); CloseAvi(AviOut); inAvi = NULL; outAvi = NULL; return true; } Application->ProcessMessages(); } FormEmbedVideo->ButtonEmbed->Enabled = true; FormEmbedVideo->ButtonCancel->Enabled = false; FormEmbedVideo->LabelBlink->Visible = false; StreamCopyAudio(AviIn, AviOut); // Close and Free all handles Free_2D_UCHAR(TempImage, EWHeight); Free_2D_char(TempImageKey, EWKeyHeight); Free_2D_Int(Red, AviHeight); Free_2D_Int(Green, AviHeight); Free_2D_Int(Blue, AviHeight); RDCloseAvi(AviIn); CloseAvi(AviOut); inAvi = NULL; outAvi = NULL; return true; } /* Detect AVI Video */ int RecoverWatermarkAVI_Lifting( HWND thisHwnd, AnsiString inVideoFileName, // watermark inputs Graphics::TBitmap *pRWbmpImage, stcImageType RWImageType, UCHAR **Gray_Image_RW, long Gray_Image_RW_Width, long Gray_Image_RW_Height, // Key Image inputs Graphics::TBitmap *pRWKeybmpImage, stcImageType RWKImageType, UCHAR **Gray_Image_RW_Key, long Gray_Image_RW_Key_Width, long Gray_Image_RW_Key_Height, // embed inputs double BetaFactorRW, int DWTLevelsRW, // wavelet tansform level int LevelEmbedRW, // in which level watermark has been embedded bool AllFrames, long FrameNo) { long AviWidth, AviHeight, i, j, iImg, jImg, iImgKey, jImgKey, NumFrames, iFrm, is, js; long tmpW, tmpH, RWWidth, RWHeight, RWKeyWidth, RWKeyHeight; long EmbedHorW, EmbedHorH, EmbedVerW, EmbedVerH; long StartEmbedHorW, StartEmbedHorH, StartEmbedVerW, StartEmbedVerH; TAviUtil *inAvi; HAVI AviIn; UCHAR **TempImage; char **TempImageKey; int **Red, **Green, **Blue; BlockInfoStrc DWTSegmentAdrs[10]; int szSeg; Graphics::TBitmap *pBitmapTMP; int tmpImGGG; int aaH, abH, baH, bbH, aaW, abW, baW, bbW; double mA1, mA2, mcorr, corr, corr1, corr2, A11, A12, A13, A14, A21, A22, A23, A24, mB, B, B1, B2, B3, B4; double tmp, tmp1, tmp2, tmp3, fThreshold, mCorrRed, mCorrGreen, mCorrBlue, WatCorr, WatBER; double *tmpCorrM; TListItem *ListItem; AnsiString strTmp; // ------------------------ // CHECK 1 // there must be two images if ((RWKImageType == Img_NONE)) { MessageDlg("You must select a Watermark and Key image.", mtError, TMsgDlgButtons() << mbOK, 0); return false; } // ----------------------------------------------------------- // CHECK 2 // Key image sizes MUST be equal to video DWT level size. // Open the AVI file and set handle AviIn = RDOpenAviFile(inVideoFileName.c_str(), true); if (AviIn == NULL) { DispError("ERROR! Cannot open AVI file."); return S_FALSE; } inAvi = (TAviUtil*)AviIn; AviWidth = inAvi->iWidth; AviHeight = inAvi->iHeight; NumFrames = inAvi->numframes; if ( DWTLevelsRW < LevelEmbedRW ) { MessageDlg("DWT Levels cannot be smaller than Embed Levels.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // Check the dimensions for compatability. if (AviWidth%(1 << DWTLevelsRW) || AviHeight%(1 << DWTLevelsRW)) { AnsiString sss = "width and height of input video must be divisible by 2^" + IntToStr(DWTLevelsRW) + " = " + IntToStr((int)pow(2, DWTLevelsRW)); MessageDlg(sss, mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } if ((DWTLevelsRW == 2) || (DWTLevelsRW == 3)) { if (LevelEmbedRW == 1) { tmpW = AviWidth >> 1; // division by 2 tmpH = AviHeight >> 1; } else if (LevelEmbedRW == 2) { tmpW = AviWidth >> 2; // division by 4 tmpH = AviHeight >> 2; } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } } else { MessageDlg("This software supports maximum 3-level DWT and level-1 or level-2 embeding.", mtError, TMsgDlgButtons() << mbOK, 0); RDCloseAvi(AviIn); inAvi = NULL; return false; } // if we came this far, inAvi structure is still open. // We will continue to use this structure. /* Allocate required buffers */ // original watermark if (RWImageType == Img_PGMGray) { TempImage = Alloc_2D_UCHAR(Gray_Image_RW_Width, Gray_Image_RW_Height); RWWidth = Gray_Image_RW_Width; RWHeight = Gray_Image_RW_Height; } else if (RWImageType != Img_NONE) { TempImage = Alloc_2D_UCHAR(pRWbmpImage->Width, pRWbmpImage->Height); RWWidth = pRWbmpImage->Width; RWHeight = pRWbmpImage->Height; } // key if (RWKImageType == Img_PGMGray) { TempImageKey = Alloc_2D_char(Gray_Image_RW_Key_Width, Gray_Image_RW_Key_Height); RWKeyWidth = Gray_Image_RW_Key_Width; RWKeyHeight = Gray_Image_RW_Key_Height; } else { TempImageKey = Alloc_2D_char(pRWKeybmpImage->Width, pRWKeybmpImage->Height); RWKeyWidth = pRWKeybmpImage->Width; RWKeyHeight = pRWKeybmpImage->Height; } Red = Alloc_2D_Int(AviWidth, AviHeight); Green = Alloc_2D_Int(AviWidth, AviHeight); Blue = Alloc_2D_Int(AviWidth, AviHeight); int wLL = AviWidth >> DWTLevelsRW; int hLL = AviHeight >> DWTLevelsRW; /*********************************/ /* Determine Incriment positions */ DWTSegmentAdrs[0].x = 0; DWTSegmentAdrs[0].y = 0; /****************/ /* Level=3 */ DWTSegmentAdrs[1].x = 0; DWTSegmentAdrs[1].y = hLL; DWTSegmentAdrs[2].x = wLL; DWTSegmentAdrs[2].y = 0; DWTSegmentAdrs[3].x = wLL; DWTSegmentAdrs[3].y = hLL; szSeg = 4; if (DWTLevelsRW > 1) { /****************/ /* Level=2 */ DWTSegmentAdrs[4].x = 0; // South - West DWTSegmentAdrs[4].y = hLL<<1; // hLL*2 DWTSegmentAdrs[5].x = wLL<<1; // North - East DWTSegmentAdrs[5].y = 0; DWTSegmentAdrs[6].x = wLL<<1; // Diagonal DWTSegmentAdrs[6].y = hLL<<1; // hLL * 2 szSeg = 7; if (DWTLevelsRW == 3) { /****************/ /* Level=1 */ DWTSegmentAdrs[7].x = 0; DWTSegmentAdrs[7].y = hLL<<2; DWTSegmentAdrs[8].x = wLL<<2; DWTSegmentAdrs[8].y = 0; DWTSegmentAdrs[9].x = wLL<<2; DWTSegmentAdrs[9].y = hLL<<2; /*********************************/ szSeg = 10; } } // Determine embed starting and ending positions. // Only supports embedding in Level 1 or 2 after DWT_Level_2 or DWT_Level_3 transform if ((DWTLevelsRW == 2) && (LevelEmbedRW == 1)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } else if ((DWTLevelsRW == 2) && (LevelEmbedRW == 2)) { StartEmbedHorW = DWTSegmentAdrs[1].x; StartEmbedHorH = DWTSegmentAdrs[1].y; StartEmbedVerW = DWTSegmentAdrs[2].x; StartEmbedVerH = DWTSegmentAdrs[2].y; EmbedHorW = StartEmbedHorW + wLL; EmbedHorH = StartEmbedHorH + hLL; EmbedVerW = StartEmbedVerW + wLL; EmbedVerH = StartEmbedVerH + hLL; } else if ((DWTLevelsRW == 3) && (LevelEmbedRW == 1)) { StartEmbedHorW = DWTSegmentAdrs[7].x; StartEmbedHorH = DWTSegmentAdrs[7].y; StartEmbedVerW = DWTSegmentAdrs[8].x; StartEmbedVerH = DWTSegmentAdrs[8].y; EmbedHorW = StartEmbedHorW + wLL * 4; EmbedHorH = StartEmbedHorH + hLL * 4; EmbedVerW = StartEmbedVerW + wLL * 4; EmbedVerH = StartEmbedVerH + hLL * 4; } else if ((DWTLevelsRW == 3) && (LevelEmbedRW == 2)) { StartEmbedHorW = DWTSegmentAdrs[4].x; StartEmbedHorH = DWTSegmentAdrs[4].y; StartEmbedVerW = DWTSegmentAdrs[5].x; StartEmbedVerH = DWTSegmentAdrs[5].y; EmbedHorW = StartEmbedHorW + wLL * 2; EmbedHorH = StartEmbedHorH + hLL * 2; EmbedVerW = StartEmbedVerW + wLL * 2; EmbedVerH = StartEmbedVerH + hLL * 2; } // fill temp watermark image matrix if (RWImageType == Img_PGMGray) { for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { TempImage[i][j] = Gray_Image_RW[i][j]; } } } else if (RWImageType != Img_NONE) { for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { TempImage[i][j] = (UCHAR)(pRWbmpImage->Canvas->Pixels[j][i] & 0xFF); } } } // fill temp key image matrix if (RWKImageType == Img_PGMGray) { for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { TempImageKey[i][j] = Gray_Image_RW_Key[i][j]; } } } else { for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { TempImageKey[i][j] = (ULONG)pRWKeybmpImage->Canvas->Pixels[j][i] & 0xFF; } } } for(i=0; i < RWKeyHeight; i++) { for(j=0; j < RWKeyWidth; j++) { if (TempImageKey[i][j] == 0) TempImageKey[i][j] = -1; else TempImageKey[i][j] = 1; } } // temporary recover image pBitmapTMP = new Graphics::TBitmap(); pBitmapTMP->PixelFormat = pf24bit; pBitmapTMP->Width = RWKeyWidth/2; pBitmapTMP->Height = RWKeyHeight/2; TCanvas *tmpCanvas = pBitmapTMP->Canvas; if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = true; FormRecover->ButtonRecover->Enabled = false; } else { FormRecover->ButtonCancel->Enabled = true; FormRecover->ButtonCalcBER->Enabled = false; } FormRecover->GroupBoxOptions->Enabled = false; FormRecover->ListResult->Items->Clear(); Application->ProcessMessages(); tmpCorrM = (double *)malloc((RWKeyWidth/2) * (RWKeyHeight/2) * sizeof(double)); for(iFrm=0; iFrm<NumFrames; iFrm++) // for each frame { // Read Video if (!AllFrames) // only one frame { RDGetFrame_Int(AviIn, FrameNo, Red, Green, Blue); } else // all frames { RDGetFrame_Int(AviIn, iFrm, Red, Green, Blue); } // DWT Transform l97_2D(Red, AviWidth, AviHeight, DWTLevelsRW, false); l97_2D(Green,AviWidth, AviHeight, DWTLevelsRW, false); l97_2D(Blue, AviWidth, AviHeight, DWTLevelsRW, false); corr = 0.0; for(i=0; i < RWKeyHeight/2; i++) { for(j=0; j < RWKeyWidth/2; j++) { is = i*2; js = j*2; // Horizontal scan positions aaH = StartEmbedHorH + is; // + 0 abH = StartEmbedHorH + is + 1; aaW = StartEmbedHorW + js; // + 0 abW = StartEmbedHorW + js + 1; // Vertical scan positions baH = StartEmbedVerH + is; // + 0 bbH = StartEmbedVerH + is + 1; baW = StartEmbedVerW + js; // + 0 bbW = StartEmbedVerW + js + 1; // RED // image matrix elements A11 = Red[aaH][aaW]; A12 = Red[aaH][abW]; A13 = Red[abH][aaW]; A14 = Red[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = Red[baH][baW]; A22 = Red[baH][bbW]; A23 = Red[bbH][baW]; A24 = Red[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrRed = (corr1 + corr2)/2.0; // GREEN // image matrix elements A11 = Green[aaH][aaW]; A12 = Green[aaH][abW]; A13 = Green[abH][aaW]; A14 = Green[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = Green[baH][baW]; A22 = Green[baH][bbW]; A23 = Green[bbH][baW]; A24 = Green[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrGreen = (corr1 + corr2)/2.0; // BLUE // image matrix elements A11 = Blue[aaH][aaW]; A12 = Blue[aaH][abW]; A13 = Blue[abH][aaW]; A14 = Blue[abH][abW]; mA1 = (A11+A12+A13+A14)/4.0; A21 = Blue[baH][baW]; A22 = Blue[baH][bbW]; A23 = Blue[bbH][baW]; A24 = Blue[bbH][bbW]; mA2 = (A21+A22+A23+A24)/4.0; B1 = TempImageKey[is][js]; B2 = TempImageKey[is][js+1]; B3 = TempImageKey[is+1][js]; B4 = TempImageKey[is+1][js+1]; mB = (B1 + B2 + B3 + B4)/ 4.0; // Horizontal Scan tmp1 = (A11-mA1)*(B1 - mB) + (A12-mA1)*(B2 - mB) + (A13-mA1)*(B3 - mB) + (A14-mA1)*(B4 - mB); tmp2 = (A11-mA1)*(A11-mA1) + (A12-mA1)*(A12-mA1) + (A13-mA1)*(A13-mA1) + (A14-mA1)*(A14-mA1); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr1 = 0; else corr1 = (tmp1)/(sqrt(tmp2*tmp3)); // Vertical Scan tmp1 = (A21-mA2)*(B1 - mB) + (A22-mA2)*(B2 - mB) + (A23-mA2)*(B3 - mB) + (A24-mA2)*(B4 - mB); tmp2 = (A21-mA2)*(A21-mA2) + (A22-mA2)*(A22-mA2) + (A23-mA2)*(A23-mA2) + (A24-mA2)*(A24-mA2); tmp3 = (B1 - mB)*(B1 - mB) + (B2 - mB)*(B2 - mB) + (B3 - mB)*(B3 - mB) + (B4 - mB)*(B4 - mB); if ((tmp2 == 0.0) || (tmp3 == 0.0)) corr2 = 0; else corr2 = (tmp1)/(sqrt(tmp2*tmp3)); mCorrBlue = (corr1 + corr2)/2.0; // find the biggest correlation mcorr = mCorrRed; if (mCorrGreen > mcorr) mcorr = mCorrGreen; if (mCorrBlue > mcorr) mcorr = mCorrBlue; // add current correlation to total correlation tmpCorrM[i * RWKeyWidth/2 + j] = mcorr; } // j } // i // find mean correlation corr = 0.0; for(i=0; i < (RWKeyWidth * RWKeyHeight)/4; i++) { corr+= tmpCorrM[i]; } mcorr = corr / (double)((RWKeyWidth * RWKeyHeight)/4.0); // find final theshold fThreshold = BetaFactorRW * mcorr; if (!AllFrames) // only one frame { // display image for(i=0; i < RWKeyHeight/2; i++) { for(j=0; j < RWKeyWidth/2; j++) { if ( tmpCorrM[i * RWKeyWidth/2 + j] >= fThreshold) tmpCanvas->Pixels[j][i] = (TColor)RGB(0, 0, 0); else tmpCanvas->Pixels[j][i] = (TColor)RGB(255, 255, 255); } } FormRecover->ImageRecover->Picture->Assign(pBitmapTMP); FormRecover->ButtonSaveImage->Enabled = true; FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; FormRecover->GroupBoxOptions->Enabled = true; // display BitErrors (BER) if (FormMain->RWImageType != Img_NONE) { // find BER and means WatBER = 0; for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { if ( (tmpCanvas->Pixels[j][i] & 0xFF ) != TempImage[i][j]) WatBER += 1; } } WatBER = (WatBER * 100)/ (RWWidth * RWHeight); ListItem = FormRecover->ListResult->Items->Add(); // FrameNo ListItem->Caption = IntToStr(FrameNo); // BER strTmp.sprintf("%3.2f", WatBER); ListItem->SubItems->Add( strTmp ); } delete pBitmapTMP; if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_Int(Red, AviHeight); Free_2D_Int(Green, AviHeight); Free_2D_Int(Blue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; } else // all frames { FormRecover->LabelRecover->Caption = IntToStr(iFrm+1) + "/" + IntToStr(NumFrames) + " frames"; FormRecover->BarRecover->Percent = ((iFrm+1)*100)/NumFrames; // add MER line into List // display BitErrors (BER) if (FormMain->RWImageType != Img_NONE) { // find BER and means WatBER = 0; for(i=0; i < RWHeight; i++) { for(j=0; j < RWWidth; j++) { if ( tmpCorrM[i * RWKeyWidth/2 + j] >= fThreshold) szSeg = 0; else szSeg = 255; if ( szSeg != TempImage[i][j]) WatBER += 1; } } WatBER = (WatBER * 100)/ (RWWidth * RWHeight); ListItem = FormRecover->ListResult->Items->Add(); // FrameNo ListItem->Caption = IntToStr(iFrm); // BER strTmp.sprintf("%3.2f", WatBER); FormRecover->recAllFrames = FormRecover->recAllFrames + strTmp + ", "; ListItem->SubItems->Add( strTmp ); } } Application->ProcessMessages(); if (FormRecover->cancelRecover) { if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; } else { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonCalcBER->Enabled = true; } FormRecover->GroupBoxOptions->Enabled = true; // Close and Free all handles if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_Int(Red, AviHeight); Free_2D_Int(Green, AviHeight); Free_2D_Int(Blue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; } Application->ProcessMessages(); } if (!AllFrames) // only one frame { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonRecover->Enabled = true; } else { FormRecover->ButtonCancel->Enabled = false; FormRecover->ButtonCalcBER->Enabled = true; FormRecover->ButtonSaveResults->Enabled = true; } FormRecover->GroupBoxOptions->Enabled = true; // Close and Free all handles if (FormMain->wantRWCalcCorrelation) Free_2D_UCHAR(TempImage, RWHeight); // watermark Free_2D_char(TempImageKey, RWKeyHeight); Free_2D_Int(Red, AviHeight); Free_2D_Int(Green, AviHeight); Free_2D_Int(Blue, AviHeight); free(tmpCorrM); RDCloseAvi(AviIn); inAvi = NULL; return true; }