Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > LibPNG to HBITMAP


Автор: V0LT 6.6.2010, 11:50
Скачал от сюда http://sourceforge.net/projects/libpng/files/ LibPNG но совершенно не понимаю как добиться адекватного отображения альфа прозрачности 
Код

void PNGAPI user_error_fn(png_structp png, png_const_charp sz) { }
void PNGAPI user_warning_fn(png_structp png, png_const_charp sz) { }
 
HBITMAP LoadBitmapPNG(char *szFile)
{
    HBITMAP hbm = NULL;

    bool retVal = false;
    int size = 0;
    // check the header first
    FILE *fp = fopen(szFile, "rb");
    if (!fp)
        return false;
    BYTE header[8];
    fread(header, 1, 8, fp);
    fseek(fp, 0, SEEK_END);
    size = ftell(fp);
    fclose(fp);
    if (png_sig_cmp(header, 0, 8))
        return false;
    // now allocate stuff
    png_structp png_ptr =
        png_create_read_struct(PNG_LIBPNG_VER_STRING,
        NULL, user_error_fn, user_warning_fn);
    if (!png_ptr)
        return false;
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr,
            (png_infopp)NULL, (png_infopp)NULL);
        return false;
    }

    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr,
            (png_infopp)NULL);
        return false;
    }

    fp = fopen(szFile, "rb");
    if (fp)
    {
        png_init_io(png_ptr, fp);

        // should really use png_set_rows() to allocate space first, rather than doubling up

        png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_BGR | PNG_TRANSFORM_PACKING, NULL);

        fclose(fp);

        png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);//new png_bytep[info_ptr->height];

        // now for a tonne of ugly DIB setup crap

        int width = info_ptr->width;
        int height = info_ptr->height;
        int bpp = info_ptr->channels * 8;
        int memWidth = (width * (bpp >> 3) + 3) & ~3;

        LPBITMAPINFO lpbi = (LPBITMAPINFO) new char[sizeof(BITMAPINFOHEADER) + (256 * sizeof(RGBQUAD))];

        // create a greyscale palette
        for (int a_i = 0; a_i < 256; a_i++)
        {
            lpbi->bmiColors[a_i].rgbRed = (BYTE)a_i;
            lpbi->bmiColors[a_i].rgbGreen = (BYTE)a_i;
            lpbi->bmiColors[a_i].rgbBlue = (BYTE)a_i;
            lpbi->bmiColors[a_i].rgbReserved = 0;
        }

        lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        lpbi->bmiHeader.biWidth = width;
        lpbi->bmiHeader.biHeight = -height; // must be negative for top down
        lpbi->bmiHeader.biPlanes = 1;
        lpbi->bmiHeader.biBitCount = bpp;
        lpbi->bmiHeader.biCompression = BI_RGB;
        lpbi->bmiHeader.biSizeImage = memWidth * height;
        lpbi->bmiHeader.biXPelsPerMeter = 0;
        lpbi->bmiHeader.biYPelsPerMeter = 0;
        lpbi->bmiHeader.biClrUsed = 0;
        lpbi->bmiHeader.biClrImportant = 0;

        BYTE * pixelData;
        hbm = CreateDIBSection(NULL, lpbi, DIB_RGB_COLORS, (void **)&pixelData, NULL, 0 );
        if (hbm && pixelData)
        {
            // now copy the rows
            for (int i = 0; i < height; i++)
                memcpy(pixelData + memWidth * i, row_pointers[i], width * info_ptr->channels);
        }

        delete (char*) lpbi;
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

    return hbm;
}


void SetSplashImage(HWND hwndSplash, HBITMAP hbmpSplash)
{
    // get the size of the bitmap
    BITMAP bm;
    GetObject(hbmpSplash, sizeof(bm), &bm);
    SIZE sizeSplash = { bm.bmWidth, bm.bmHeight };
 
    // get the primary monitor's info
    POINT ptZero = { 0 };
    HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
    MONITORINFO monitorinfo = { 0 };
    monitorinfo.cbSize = sizeof(monitorinfo);
    GetMonitorInfo(hmonPrimary, &monitorinfo);
 
    // center the splash screen in the middle of the primary work area
    const RECT & rcWork = monitorinfo.rcWork;
    POINT ptOrigin;
    ptOrigin.x = rcWork.left + (rcWork.right - rcWork.left - sizeSplash.cx) / 2;
    ptOrigin.y = rcWork.top + (rcWork.bottom - rcWork.top - sizeSplash.cy) / 2;
 
    // create a memory DC holding the splash bitmap
    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpSplash);
 
    // use the source image's alpha channel for blending
    BLENDFUNCTION blend = { 0 };
    blend.BlendOp = AC_SRC_OVER;
    blend.SourceConstantAlpha = 255;
    blend.AlphaFormat = AC_SRC_ALPHA;
 
    // paint the window (in the right location) with the alpha-blended bitmap
    UpdateLayeredWindow(hwndSplash, hdcScreen, &ptOrigin, &sizeSplash,
        hdcMem, &ptZero, RGB(0, 0, 0), &blend, ULW_ALPHA);
 
    // delete temporary objects
    SelectObject(hdcMem, hbmpOld);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);
}

Автор: Dem_max 6.6.2010, 14:42
Вот:

http://forum.sources.ru/index.php?showtopic=284876&st=0&#entry2405961
http://forum.sources.ru/index.php?showtopic=284876&hl=png
http://forum.sources.ru/index.php?showtopic=208869

http://forum.sources.ru/index.php?showtopic=294926&hl=png

Автор: V0LT 8.6.2010, 02:27
Dem_max, за ссылки большой спасиб .. почитал - было интересно
Но всё же проблему решил по своему ... GDI+ никак низя из за Windows 2k в которой нет GDI+ ... сделал как и хотел на libpng  smile 
... и да спасиб участнику deniska 
user posted image

Автор: Dem_max 8.6.2010, 03:32
Цитата

GDI+ никак низя из за Windows 2k в которой нет GDI+ ... 


Носи с собой GDIPlus.DLL говорят она без проблем в 2k работает

V0LT выложи участок кода в виде текста или подкрепи кусок проекта, как ты это сделал.  Собственно выложи те моменты как загружаешь картинку, и как создаешь окно с этой картинкой.  Следующим поколениям пригодиться.

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