【问题标题】:Transparent spectrogram selection overlays透明的频谱图选择覆盖
【发布时间】:2018-01-08 02:06:38
【问题描述】:

我正在尝试在频谱图上创建透明的选择叠加层,但效果不佳。我的意思是结果并不令人满意。相比之下,在波形顶部绘制的叠加层效果很好,但我需要同时支持波形和频谱图视图(未来可能还有其他视图)

选择覆盖在波形视图中工作正常

这是频谱图视图中的选择叠加层(选择看起来非常糟糕并且遮挡了频谱图的某些部分)

两个视图的代码 (VCL) 相同

void TWaveDisplayContainer::DrawSelectedRegion(){


        if(selRange.selStart.x == selRange.selEnd.x){
            DrawCursorPosition( selRange.selStart.x);
            return;
        }
        Graphics::TBitmap *pWaveBmp = eContainerView == WAVEFORM ? pWaveBmpLeft : pSfftBmpLeft;
        TRect selRect(selRange.selStart.x, 0, selRange.selEnd.x, pWaveLeft->Height);
        TCanvas *pCanvas = pWaveLeft->Canvas;
        int copyMode = pCanvas->CopyMode;

        pCanvas->Draw(0,0, pWaveBmp);
        pCanvas->Brush->Color = clActiveBorder;
        pCanvas->CopyMode = cmSrcAnd;
        pCanvas->Rectangle(selRect);
        pCanvas->CopyRect(selRect, pWaveBmp->Canvas, selRect);
        pCanvas->CopyMode = copyMode;

        if(numChannels == 2){

            TCanvas* pOtherCanvas = pWaveRight->Canvas;
            pWaveBmp = eContainerView == WAVEFORM ? pWaveBmpRight : 
 pSfftBmpRight;
            pOtherCanvas->Draw(0,0, pWaveBmp);
            pOtherCanvas->Brush->Color = clActiveBorder;
            pOtherCanvas->CopyMode = cmSrcAnd;
            pOtherCanvas->Rectangle(selRect);
            pOtherCanvas->CopyRect(selRect, pWaveBmp->Canvas, selRect);
            pOtherCanvas->CopyMode = copyMode;

        }
}

所以,我使用cmSrcAnd 复制模式和CopyRect 方法来进行实际的绘画/绘图(TCanvas 对应于设备上下文(HDC on Windows)。我认为,因为频谱图,不像一个波形,实际上没有单一的背景颜色,使用简单的混合复制模式在大多数情况下都不能很好地工作。

请注意,我仍然可以完成我想要的,但这需要弄乱单个像素,这是我希望尽可能避免的事情)

我基本上是在寻找能够做到这一点的APIVCL 包装GDI 所以即使是 WINAPI 也可以)。

非常感谢任何帮助

【问题讨论】:

标签: c++ transparency vcl


【解决方案1】:

我将回答我自己的问题,希望这对某些人有用。由于显然没有办法做到这一点 在普通的VCL 或使用WINAPI(某些情况下除外)中,我编写了一个简单的函数,将位图(32bpp / 24bpp)与覆盖颜色(任何颜色)混合。 实际结果还取决于赋予单个像素的red, green and blue 分量的权重 (w0,w1)。改变这些会产生 分别更倾向于光谱图颜色或叠加颜色的叠加。

代码

Graphics::TBitmap *TSelectionOverlay::GetSelectionOverlay(Graphics::TBitmap *pBmp, TColor selColour,
TRect &rect, EChannel eChannel){

 Graphics::TBitmap *pSelOverlay = eChannel==LEFT ? pSelOverlayLeft : pSelOverlayRight;

 const unsigned cGreenShift = 8;
 const unsigned cBlueShift = 16;

 const unsigned overlayWidth = abs(rect.right-rect.left);
 const unsigned overlayHeight = abs(rect.bottom-rect.top);

 pSelOverlay->Width = pBmp->Width;
 pSelOverlay->Height = pBmp->Height;

 const unsigned startOffset = rect.right>rect.left ? rect.left : rect.right;

 pSelOverlay->Assign(pBmp);

 unsigned char cRed0, cGreen0, cBlue0,cRed1, cGreen1, cBlue1, bRedColor0, bGreenColor0, bBlueColor0;

 cBlue0 =   selColour >> cBlueShift;
 cGreen0 =  selColour >> cGreenShift & 0xFF;
 cRed0 =    selColour & 0xFF;

 unsigned *pPixel;

 for(int i=0;i<overlayHeight;i++){

    pPixel = (unsigned*)pSelOverlay->ScanLine[i];//provides access to the pixel array
    for(int j=0;j<overlayWidth;j++){

    unsigned pixel =  pPixel[startOffset+j];
    cBlue1 =    pixel >> cBlueShift;
    cGreen1 =   pixel >> cGreenShift & 0xFF;
    cRed1 =     pixel & 0xFF;

    //blend the current bitmap pixel with the overlay colour

    const float w0 = 0.5f; //these weights influence the appearance of the overlay (here we use 50%)
    const float w1 = 0.5f;

    bRedColor0 = cRed0*w0+cRed1*w1;
    bGreenColor0 = cGreen0*w0+cGreen1*w1);
    bBlueColor0 = cBlue0*w0+cBlue1*w1;

    pPixel[startOffset+j] =  ((bBlueColor0 << cBlueShift) | (bGreenColor0 << cGreenShift)) | bRedColor0;
    }
 }

  return pSelOverlay;
}

请注意,由于某种原因,CopyRectCopyMode 的值 cmSrcCopy 一起使用效果不佳,因此我改用了 Draw

pCanvas->CopyMode = cmSrcCopy;
pCanvas->CopyRect(dstRect, pSelOverlay->Canvas, srcRec);//this still didn't work well--possibly a bug

所以我用了

pCanvas->Draw(0,0, pSelOverlay);

结果

【讨论】:

    猜你喜欢
    • 2016-12-10
    • 2016-01-21
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多