请问这段实现视频渐隐渐显的代码有什么问题?
这是我的filter中的一个渐隐的函数,其中p是一帧帧的视频数据流,cx、cy是宽高。(因为是24位,所以不用alpha通道实现)
现在的问题是:显示原图像,然后等待100MS后直接变黑色,没有渐变。
我的分析是:视频数据流的颜色没有随prgbSrc实时改变,而是取了prgbSrc的最终值。
bool FadeOut(BYTE* p, int cx, int cy)
{
BOOL bDraw = FALSE;
int r,g,b;
RGBTRIPLE *prgbSrc =(RGBTRIPLE*)p;
while(!bDraw)
{
bDraw=TRUE;
for(int j=0; j<cy; j++)
{
for(int i=0; i<cx; i++)
{
r=prgbSrc[i+j*cx].rgbtRed;
g=prgbSrc[i+j*cx].rgbtGreen;
b=prgbSrc[i+j*cx].rgbtBlue;
r=r-10>0?r-10:0;
g=g-10>0?g-10:0;
b=b-10>0?b-10:0;
prgbSrc[i+j*cx].rgbtRed = (BYTE)r;
prgbSrc[i+j*cx].rgbtGreen = (BYTE)g;
prgbSrc[i+j*cx].rgbtBlue = (BYTE)b;
if((r>0)||(g>0)||(b>0))
bDraw=FALSE;
}
}
///觉得这里应该加什么代码来实时保存prgbSrc,不知对不对?
Sleep(100);
}
return true;
}
[解决办法]
if((r> 0) ¦ ¦(g> 0) ¦ ¦(b> 0))
bDraw=FALSE;
你的这句不知道是干什么的,不行就把这句去掉,应该就可以了。
[解决办法]
是一帧,但一帧比一帧暗。
[解决办法]
bool FadeOut(BYTE* p, int cx, int cy)
{
BOOL bDraw = FALSE;
int r,g,b;
RGBTRIPLE *prgbSrc =(RGBTRIPLE*)p;
while(!bDraw)
{
bDraw=TRUE;
for(int j=0; j <cy; j++)
{
for(int i=0; i <cx; i++)
{ //从图象(0,0)点开始处理[/color]
r=prgbSrc[i+j*cx].rgbtRed;
g=prgbSrc[i+j*cx].rgbtGreen;
b=prgbSrc[i+j*cx].rgbtBlue;
r=r-10> 0?r-10:0; //对一帧图象的一点R G B 三个通道 值减10和0判断
g=g-10> 0?g-10:0;
b=b-10> 0?b-10:0;
prgbSrc[i+j*cx].rgbtRed = (BYTE)r;
prgbSrc[i+j*cx].rgbtGreen = (BYTE)g;
prgbSrc[i+j*cx].rgbtBlue = (BYTE)b;
if((r> 0) ¦ ¦(g> 0) ¦ ¦(b> 0))
bDraw=FALSE;
}
}
也就是说你这一帧图象处理完了之后 很有可能是每1个象素点RGB都减了10 (假设没有点的RGB三个值均小于10的情况)
下一帧重新读如然后相同处理.......
个人感觉:如果你要实现渐变 那个10不应该是固定的 应该是动态增加的,而且要保存.....
处理完了后 第二次看这个视频的时候视频会出现渐变.
wuchuncai那个 用动态Val的是对的 每帧val += 10;(每帧多减一个10)
你那个代码对同一副图象的反复读入应该就可以实现简便效果的
前提是你每一个点RGB都大于10 如果有一个点是(5,4,4)那么处理后都变成0
那么if((r> 0) ¦ ¦(g> 0) ¦ ¦(b> 0))
bDraw=FALSE; //不起作用了
之后就不进入WHILE
[解决办法]
昨天捡了张光盘,里面有个浅显的部分
/*渐显特效显示*/void CDynSplitView2::OnJianxian() { //刷新屏幕 CDC *pDC=GetDC(); CRect rect(0,0,1000,1000); CBrush brush(RGB(255,255,255)); pDC->FillRect(&rect,&brush); //复制图像数据 clearmem(); CDSplitDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if(!pDoc ->statedoc&&state2==1 ) { BYTE* pBitmapData = CDibNew1->GetData(); LPBITMAPINFO pBitmapInfo = CDibNew1->GetInfo(); int bitmapHeight= CDibNew1->GetHeight(); int bitmapWidth = CDibNew1->GetWidth(); if (CDibNew1->GetRGB()) // Has a color table { CPalette * hPalette=CreateBitmapPalette(CDibNew1); CPalette * hOldPalette = pDC->SelectPalette(hPalette, true); pDC->RealizePalette(); LPBYTE temp,temp1,temp2; temp=new BYTE[CDibNew1->GetHeight()*CDibNew1->GetWidth()]; memset (temp,0,CDibNew1->GetHeight()*CDibNew1->GetWidth()); for(int n=0;n<=256;n++) { temp1=temp; temp2=pBitmapData; for(int j = 0; j < bitmapHeight; j++) { for(int i = 0; i < bitmapWidth; i ++) { *temp1=(*temp2)*(n)/256; temp1++; temp2++; } } ::StretchDIBits(pDC->GetSafeHdc(),0, 0, bitmapWidth, bitmapHeight, 0, 0, bitmapWidth, bitmapHeight, temp,pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); Sleep(10); } pDC->SelectPalette(hOldPalette, true); ::DeleteObject(hPalette); delete temp; } else { LPBYTE temp; temp=new BYTE[CDibNew1->GetHeight()*CDibNew1->GetWidth()*3]; memset (temp,0,CDibNew1->GetHeight()*CDibNew1->GetWidth()*3); for(int m=0;m<256;m++) { for(int j = 0; j < bitmapHeight; j++) { for(int i = 0; i < bitmapWidth; i ++) { temp[j*bitmapWidth*3+i*3]=pBitmapData[j*bitmapWidth*3+i*3]*(m)/256; temp[j*bitmapWidth*3+i*3+1]=pBitmapData[j*bitmapWidth*3+i*3+1]*(m)/256; temp[j*bitmapWidth*3+i*3+2]=pBitmapData[j*bitmapWidth*3+i*3+2]*(m)/256; } } ::StretchDIBits(pDC->GetSafeHdc(), 0, 0, bitmapWidth, bitmapHeight, 0, 0, bitmapWidth, bitmapHeight, temp, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); Sleep(20); } delete temp; } }}
[解决办法]
虽然没有做过directshow的filter开发,但可以想象:
1、如果filter与Video Render 是共享一帧视频数据内存的(在这里就是传入的参数BYTE* p),那么在你的FILTER处理完一次后也应该有个通信机制,让Video Render 显示处理完的一帧,而不是要等到FILTER返回之后才显示。FILTER返回之后才显示,那么你永远只能够显示最后一次处理的结果;
2、如果FILTER接管了Video Render 的缓存(即Video Render 是直接从FILTER的输出中取数据显示的),那么在你的FILTER接收了一帧数据之后,应该连续输出N帧,也就是你Sleep(100)处的语句应该变成向Video Render 缓存中输出一帧的语句。这时也就是:USB视频设备(一帧数据)-> Filter->(渐变的N帧数据) Video Render
[解决办法]
要进行实施显示才可
Sleep(100);
///add
Display(prgbSrc);