Сообщений 7    Оценка 75        Оценить  
Система Orphus

Функция RasterAlphaBlend

Автор: Serge Kandakov
ТВК
Опубликовано: 17.11.2001
Исправлено: 13.03.2005
Версия текста: 1.0.1


Пример работы функции

Исходный текст функции - 669 b
Демонстрационная программа - 146 Kb

Введение

Итак, речь пойдет о функции, реализующей микширование двух изображений с учетом альфа-канала. Данная проблема встала передо мной поскольку моя текущая работа плотно связана с программированием графики, и, в частности, с цифровой обработкой изображений.

Windows GDI, как известно, предоставляет очень скудный инструментарий в этом плане, что приводит к необходимости самостоятельно реализовывать требуемую функциональность (опускаю обсуждение GDI+ - хорошо, но поздновато :). Надеюсь, что программистам со схожей спецификой работы, эта информация не покажется безынтересной.

Описание работы

Ниже представлена, собственно, сама функция. На входе шесть параметров:
void RasterAlphaBlend(int w1, int h1, int w2, int h2, DWORD* pSrc1, DWORD* pSrc2);
w1 ширина первого буфера, в пикселах
h1 высота первого буфера, в пикселах
w2 ширина второго буфера, в пикселах
h2 высота второго буфера, в пикселах
pSrc1 указатель на первый буфер
pSrc2 указатель на второй буфер

Исходный текст:

void RasterAlphaBlend(int w1, int h1, int w2, int h2, DWORD* pSrc1, DWORD* pSrc2)
{
    // first source buffer (destination) must be LARGER than second!!! 
    if (w1 < w2 || h1 < h2)
        return;
    DWORD dx1 = w1 * 4;
    DWORD dx2 = w2 * 4;
    DWORD diff = (w1 - w2) * 4;

    _asm{
        mov esi, pSrc1
        mov edi, pSrc2
        mov eax, 1
        cpuid
        test edx, 0x00800000
        jz END
MMX:

        mov ecx, h2
LM1:
        push ecx
        mov ecx, w2
LM2:
        mov al, [edi + 3]
        or al, al
        jz NX1
        mov ah, al
        mov dx, ax
        bswap eax
        mov ax, dx

        pxor mm2, mm2
        movd mm3, eax
        punpcklbw mm3, mm2        // a

        mov eax, 0xffffffff
        movd mm4, eax
        punpcklbw mm4, mm2
        psubw mm4, mm3            // 1-a


        movd mm0, [esi]
        punpcklbw mm0, mm2
        movd mm1, [edi]
        punpcklbw mm1, mm2

        pmullw mm1, mm3
        pmullw mm0, mm4
        paddusw mm1, mm0
        psrlw mm1, 8        // !!!!!!!

        packuswb mm1, mm2
        movd ebx, mm1
        and ebx, 0x00ffffff

        mov eax, [esi]			Строка 1
        and eax, 0xff000000
        or eax, ebx			
        mov [esi], eax			Строка 2
NX1:
        add esi, 4
        add edi, 4
        sub ecx, 1
        jnz LM2

        add esi, diff
        pop ecx
        sub ecx, 1
        jnz LM1
        emms
END:
    }
}

Для того, чтобы использовать функцию, необходимо:

  1. Включить ее в свой проект :)
  2. Создать два 32-х битных буфера, и заполнить их.
  3. Вызвать функцию с соответствующими параметрами.

Результат микширования будет находиться в pSrc1. Для приведенной выше реализации альфа-каналом выходного изображения будет являться альфа-канал из pSrc1.

Если в Строка 1 [esi] заменить на [edi], то результирующий альфа-канал будет взят из pSrc2.

Если же код, между Строка 1 и Строка 2, заменить на:

        mov eax, [esi]
        and eax, 0xff000000
        mov edx, [edi]
        and edx, 0xff000000
        cmp eax, edx
        jnc NX2
        mov eax, edx
NX2:
        or eax, ebx
        mov [esi], eax

то результирующий альфа-канал - большее из pSrc1[i] и pSrc2[i].

ПРЕДУПРЕЖДЕНИЕ

Функция чувствительна к параметрам!

  1. Изображение должно иметь глубину пикселя = 32 бита
  2. Размер первого изображения должен быть равен или больше размера второго изображения
  3. Функция использует ММХ инструкции, и на процессорах без поддержки этой технологии работать не будет

Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 7    Оценка 75        Оценить