Thread: Loading from resources and showing a JPEG file

  1. #1
    Registered User
    Join Date
    Jul 2004
    Posts
    35

    Loading from resources and showing a JPEG file

    I'm trying to load and show a JPEG file this way:
    Code:
    LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam,  LPARAM lParam)
    {
        static HDC     hdcMem;
    
        HRSRC       hRsrc;
        HGLOBAL     hGlobal;
        byte*       lpBits;
        
        BITMAPINFO  bmi;
        HDC         hdc;
        int         iRet;
        PAINTSTRUCT ps;
    
        switch (message)
        {
            case WM_CREATE:
            {
                hRsrc = FindResource(NULL, "RCDATA_0", RT_RCDATA);
                if (hRsrc==NULL) {
                    MessageBox(NULL, "hRsrc==NULL", "Error", MB_OK | MB_ICONERROR);
                    return 0;
                }
                
                hGlobal = LoadResource(NULL, hRsrc);
                if (hGlobal==NULL) {
                    MessageBox(NULL, "hGlobal==NULL", "Error", MB_OK | MB_ICONERROR);
                    return 0;
                }
                
                lpBits = LockResource(hGlobal);
                if (lpBits==NULL) {
                    MessageBox(NULL, "lpBits==NULL", "Error", MB_OK | MB_ICONERROR);
                    return 0;
                } 
                
                memset(&bmi, 0, sizeof(bmi));
                bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
                bmi.bmiHeader.biWidth       = 400;
                bmi.bmiHeader.biHeight      = -300;
                bmi.bmiHeader.biPlanes      = 1;
                bmi.bmiHeader.biBitCount    = 0;
                bmi.bmiHeader.biCompression = BI_JPEG;
                bmi.bmiHeader.biSizeImage   = SizeofResource(NULL, hRsrc);
                
                hdcMem  = CreateCompatibleDC(NULL);
                
                iRet = StretchDIBits
                (
                    hdcMem,
                    0, 0, 400, 300,
                    0, 0, 400, 300,
                    lpBits,
                    &bmi,
                    DIB_RGB_COLORS,
                    SRCCOPY
                );
    
                FreeResource(hGlobal);
                
                if (iRet==GDI_ERROR) {
                    MessageBox(NULL, "iRet==GDI_ERROR", "Error", MB_OK | MB_ICONERROR);
                }
                break;    
    
            }
            case WM_PAINT:
            {
                hdc = BeginPaint(hwnd, &ps);
                iRet = StretchBlt
                (
                    hdc,
                    0, 0, 400, 300,
                    hdcMem,
                    0, 0, 400, 300,
                    SRCCOPY
                );
                EndPaint(hwnd, &ps);
                break;
            } 
            case WM_DESTROY:
            {
                DeleteDC(hdcMem);
                PostQuitMessage (0);
                break;
            }    
            default:
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
        return 0;
    }
    If StretchDIBits fails, the return value is GDI_ERROR, but I never get it. If StretchDIBits succeeds, the return value is the number of scan lines copied, and I always get 0.

    Can anybody help me?

  2. #2
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Some printer and display drivers may support JPEG images passed to StretchDIBits, but typically they don't. The typical method is to use the IPicture interface. Despite the documentation claiming otherwise, IPicture supports JPEG and GIF images. Here is a C++ sample that loads an image file and renders it to an HDC (error checking is omitted).
    Code:
    IPicture*  pPicture       = NULL;
    IStream*   pStream        = NULL;
    OLE_XSIZE_HIMETRIC hm_cx  = 0;
    OLE_YSIZE_HIMETRIC hm_cy  = 0;
    
    SHCreateStreamOnFile(szImageFile, STGM_READ | STGM_SHARE_DENY_WRITE, &pStream);
    OleLoadPicture(pStream, 0, TRUE, IID_IPicture, (void**) &pPicture);
    
    pPicture->get_Width(&hm_cx);
    pPicture->get_Height(&hm_cy);
    pPicture->Render(hdcMem, 0, 0, 400, 300, 0, hm_cy, hm_cx, -hm_cy, NULL);
    
    pPicture->Release();
    pStream->Release();
    Getting a stream based on a resource is a little more complex, but several samples can be found here.

    Another alternative is GDI+, although this may be overkill if you just want to show a JPEG image.

    Also, your code to create a back buffer is not complete. You need to create an appropriately sized bitmap and select it into the new hdc.
    Code:
                hdcWindow = GetDC(hwnd);
                hdcMem  = CreateCompatibleDC(hdcWindow);
                hBitmap = CreateCompatibleBitmap(hdcWindow, 400, 300);
                hOldBitmap = (HBITMAP) SelectObject(hdcMem, hBitmap);
                ReleaseDC(hdcWindow);
    and we need to restore the hdc and delete the bitmap in WM_DESTROY:
    Code:
            case WM_DESTROY:
            {
                SelectObject(hdcMem, hOldBitmap);
                DeleteObject(hBitmap);
                DeleteDC(hdcMem);
                PostQuitMessage (0);
                break;
            }
    Last edited by anonytmouse; 02-26-2005 at 04:29 AM.

  3. #3
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Another way is to use a paint program to convert the image to a bmp and use that as a resource (depends on size) or load from disk.

    I use LoadImage() then CreatePatternBrush() with the image and 'tile' the area with FillRect() or similar.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  4. #4
    Registered User
    Join Date
    Sep 2003
    Posts
    23

Popular pages Recent additions subscribe to a feed