Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > BMP объясните пожалуйста


Автор: kurlyak 19.10.2009, 19:49
У меня есть кусок программы- он работатет. Суть заключаеться в том, что  этот кусок пр. выводит изображение БМП в виде региона назначенного диалогу. То есть по очертаниям БМП рисуеться диалог (нестандартный). Вот код:

Код

// TODO: Add extra initialization here
    
    maskBitmap = (HBITMAP)LoadImage(NULL, "avatar.bmp", 
                               IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    if (!maskBitmap) return NULL;

    BITMAP bi;
    BYTE bpp;
    DWORD TransPixel;
    DWORD pixel;
    int startx;
    INT i, j;
    HRGN Rgn, ResRgn = CreateRectRgn(0, 0, 0, 0);

    GetObject(maskBitmap, sizeof( BITMAP ), &bi);

    bpp = bi.bmBitsPixel >> 3;

    BYTE *pBits = new BYTE[ bi.bmWidth * bi.bmHeight * bpp ];

    int  p = GetBitmapBits( maskBitmap, bi.bmWidth * bi.bmHeight * bpp,
                                                                pBits );

    TransPixel = *(DWORD*)pBits;

    TransPixel <<= 32 - bi.bmBitsPixel;

    for (i = 0; i < bi.bmHeight; i++)
    {
        startx=-1;
        for (j = 0; j < bi.bmWidth; j++)
        {
            pixel = *(DWORD*)(pBits + (i * bi.bmWidth +    j) * bpp) << (32 - bi.bmBitsPixel);
            if (pixel != TransPixel)
            {
                if (startx<0)
                {
                    startx = j;
                } else if (j == (bi.bmWidth - 1))
                {
                    Rgn = CreateRectRgn( startx, i, j, i + 1 );
                    CombineRgn( ResRgn, ResRgn, Rgn, RGN_OR);
                    startx=-1;
                }
            } else if (startx>=0)
            {
                Rgn = CreateRectRgn(startx, i, j, i + 1);
                CombineRgn(ResRgn, ResRgn, Rgn, RGN_OR);
                startx=-1;
            }
        }
    }
    delete pBits;
    SetWindowRgn(ResRgn, TRUE);


В частности мне не ясно почему мы сдвигаем здесь на 3 бита вправо:
bpp = bi.bmBitsPixel >> 3;

Почему мы отнимаем здесь от 32- х:
TransPixel <<= 32 - bi.bmBitsPixel;

И почему здесь отнимаем от 32- х:
pixel = *(DWORD*)(pBits + (i * bi.bmWidth +    j) * bpp) << (32 - bi.bmBitsPixel);

Что это все дает?

Автор: mes 19.10.2009, 21:21
сдвиг вправо на 3 аналогичен целочисленному делению на 8 (2 в 3й степени) - этой операции, имея кол-во бит_про_пиксел,  узнаем кол-во байт_про_пиксел.

32 это кол-во бит в DWORD.

вся эта арифметика нужна, чтоб перемещаться по памяти "по-пиксельно" .

Автор: Alexeis 19.10.2009, 21:32
bpp = bi.bmBitsPixel >> 3; тоже что bi.bmBitsPixel / 8; // галимая оптимизация в ненужно месте. делим биты на 8 и получаем байты. 3 байта занимает цветовая часть пикселя. 
TransPixel <<= 32 - bi.bmBitsPixel; - скорее всего получают значение альфа-канала пиксела из общего цвета. Сдвигают все байты чтобы остался только канал прозрачности.

32 - bi.bmBitsPixel = 32 - 24 = 8 бит прозрачности.
Это уже галимая универсальность, учитывая что битмап поддерживает только один формат прозрачности, да и тот не настоящий стандарт, а де факто.
Формат цвета 32 бита 24 бита цвет + 8 бит альфа-канал. Других просто нет. RGBA
8 бит красный 8 зеленый 8 синий 8 альфа.

Правильно будет просто проверить является ли формат 32х битным, если нет, то просто прекратить загружать из него, если да, то считать его как 8:8:8:8 и ничего не вычислять smile .

Автор: kurlyak 20.10.2009, 12:26
Большое спасибо!
У меня bi.bmBitsPixel = 32 я проверял в программе а не 24 как вы указали выше. Если например это значение как для монохромного изображения равно 4 (если я не ошибаюсь) что занчит следующее:

Код

TransPixel <<= 32 - bi.bmBitsPixel;
.......
pixel = *(DWORD*)(pBits + (i * bi.bmWidth +    j) * bpp) << (32 - bi.bmBitsPixel);


Причем TransPixel это как описано в книге цвет исходного левого крайнего пикселя. Мы сравниваем с ним все пиксели, что бы найти гранцы изображения. Почему мы именно следующий пиксель находим когда делаем <<(32 - bi.bmBitsPixel) если и так понятно что i, j строка и точка в строке умножаються (см. ниже) добавляються и еще раз умножаютсья на bpp - мы и должны получить следующий пиксель, зачем здесь << (32 - bi.bmBitsPixel):

Код

pixel = *(DWORD*)(pBits + (i * bi.bmWidth +    j) * bpp) << (32 - bi.bmBitsPixel);


И что у меня в программе значит bi.bmBitsPixel = 32 значти что rgb занимают 32 разряда? А альфа тогда как? 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)