Transparent spectral selection overlays

I am trying to create transparent selections on the top of the spectrogram, but this does not quite work. I mean, the result is not really satisfactory. On the contrary, overlays drawn on top of the waveform work well, but I need to maintain both the waveform and the spectrogram representation (and possibly other representations in the future)

Overlay of choice works great in representing waveforms

enter image description here

Here is the outline of the choice in the form of a spectrogram (the choice looks very bad and hides parts of the spectrogram)

enter image description here

Code (VCL) is the same for both views

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). , , , , , .

, , , , , )

API (VCL wraps GDI, WINAPI ), .

+4
1

, , . , -, VCL WINAPI ( ), , (32bpp / 24bpp) ( ). (w0,w1), red, green and blue . , .

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;
}

, - CopyRect, CopyMode 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);

enter image description here

0

Source: https://habr.com/ru/post/1691580/


All Articles