C ++: оптимизация простой операции обрезки изображения ... слишком много операторов if () - PullRequest
2 голосов
/ 14 марта 2011

Код, который я имею здесь, является предварительным. Я сосредоточен на процедурах отсечения. Кажется, есть много операторов if (), и я надеюсь, что у кого-нибудь будет умный способ оптимизировать это хотя бы немного.

Если вам интересно, что такое m_nStride, это количество элементов, которое нужно добавить к любому указателю пикселя, чтобы достичь пикселя непосредственно под ним (y + 1, x + 0). Но в любом случае, это неважно в отношении моего вопроса.

Общая идея состоит в том, чтобы заполнить прямоугольную область изображения (32 bpp), используя координаты left, top, width и height. В тех случаях, когда координаты приводят к тому, что эта область пересекает границы изображения, эта область будет обрезаться, чтобы уместиться внутри изображения, а не интерпретироваться как ошибка.

void Image::Clear(int nLeft, int nTop, int nWidth, int nHeight, DWORD dwColor)
{
    if(nWidth <= 0) return;
    if(nHeight <= 0) return;
    if(nLeft >= m_nWidth) return;
    if(nTop >= m_nHeight) return;

    if(nLeft < 0)
    {
        nWidth += nLeft;
        if(nWidth <= 0)
            return;
        nLeft = 0;
    }

    if(nTop < 0)
    {
        nHeight += nTop;
        if(nHeight <= 0)
            return;
        nTop = 0;
    }

    if(nLeft + nWidth > m_nWidth)
    {
        nWidth -= ((nLeft + nWidth) - m_nWidth);
        if(nWidth <= 0) 
            return;
    }

    if(nTop + nHeight > m_nHeight)
    {
        nHeight -= ((nTop + nHeight) - m_nHeight);
        if(nHeight <= 0)
            return;
    }

    DWORD *p = m_pBuffer + (m_nStride * nTop) + nLeft;
    for(int y = 0; y < nHeight; y++)
    {
        for(int x = 0; x < nWidth; x++)
            p[x] = dwColor;
        p += m_nStride;
    }
}

1 Ответ

5 голосов
/ 14 марта 2011

Для производительности издержки if практически равны нулю по сравнению с циклами for. Тем не менее, в качестве упражнения приведена версия с меньшим количеством проверок. Сначала он обрезает границы, а затем нужно только проверить, чтобы ширина и высота были положительными.

void Image::Clear(int nLeft, int nTop, int nWidth, int nHeight, DWORD dwColor)
{
    if(nLeft < 0)
    {
        nWidth += nLeft;
        nLeft = 0;
    }

    if(nTop < 0)
    {
        nHeight += nTop;
        nTop = 0;
    }

    if(nLeft + nWidth > m_nWidth)
    {
        nWidth = m_nWidth - nLeft;
    }

    if(nTop + nHeight > m_nHeight)
    {
        nHeight = m_nHeight - nTop;
    }

    if(nWidth <= 0) return;
    if(nHeight <= 0) return;

    DWORD *p = m_pBuffer + (m_nStride * nTop) + nLeft;
    for(int y = 0; y < nHeight; y++)
    {
        for(int x = 0; x < nWidth; x++)
            p[x] = dwColor;
        p += m_nStride;
    }
}
...