Avoid re-loading images during scrolling

56 Views Asked by At

I am building a MFC 2008 mdi application which displays images. When i scroll all the images must be re-loaded. I am tring to avoid this by saving the CPngImage and CBitmap files the first time through, then re-use them subsequently.

The statement pngBmp[iPic].GetBitmap(&bi); causing a break the second time through once the files have been loaded;

Can someone help me with this. The code is listed below;

// Global

#define MAX_IMAGE 100

CPngImage pngImage[MAX_IMAGE];
CBitmap pngBmp[MAX_IMAGE];

    void CFileViewerView::DrawImages(CDC* pDC)
{
    CString pngPath,imageLegend;
    CDC bmDC;
    CBitmap *pOldbmp;
    BITMAP  bi;
    int xPos = marginRect.left, yPos,nPic,nPage;
    int xOffset,yOffset,imageHeight,imageWidth,numPics;
    float aspect;
    BOOL status;

    PayAppReport report = 
            projectList[m_pModeless->GetCurrentProject()].reports[m_pModeless->GetCurrentReport()];

    numPics = report.GetNumberOfPictures();
    bmDC.CreateCompatibleDC(pDC);
    imageHeight = 6500;
    //yPos = pageRect.bottom + marginRect.top;

    nPage = numPics/6;
    for(int iPic=0; iPic<numPics; iPic++)
        {
        if(!imagesLoaded)
            {
            pngPath = report.GetPictures(iPic);
            pngPath.TrimRight();

            pngImage[iPic].LoadFromFile(pngPath);
            status = pngBmp[iPic].Attach(pngImage[iPic].Detach());
            if(!status) 
                {
                CString err;
                err.Format(_T("Cannot open image file \n\r %s"),pngPath);
                MessageBox(err,_T("Image Loading Error"),MB_ICONERROR);
                return;
                }
            }
        else
            pngBmp[iPic].Attach(pngImage[iPic].Detach());

        pngBmp[iPic].GetBitmap(&bi); //   ****** ABORTS Here

        pOldbmp= bmDC.SelectObject(&pngBmp[iPic]);

        aspect = (float)bi.bmWidth / (float)bi.bmHeight;
        imageWidth = (int)(aspect*imageHeight),numPics;

        xOffset = imageWidth;
        yOffset = (int)(-imageHeight*1.20f);

        nPic = iPic;
        if(iPic > 5)
            nPic = iPic - (iPic/6)*6;

        if(nPic == 0)
            {
            xPos = marginRect.left;
            yPos = (pageRect.bottom + marginRect.top)*((iPic/6)+1);
            }
        else if(nPic < 3)
            {
            xPos = marginRect.left;
            yPos += yOffset;
            }
        else if(nPic == 3)
            {
            xPos = marginRect.right-imageWidth;
            yPos = (pageRect.bottom + marginRect.top)*((iPic/6)+1);
            }
        else if(nPic > 3 && nPic < 6)
            {
            xPos = marginRect.right-imageWidth;
            yPos += yOffset;
            }

        _ftprintf(dbgFile,_T("iPic %d nPic %d xPos %d yPos %d\n"),iPic,nPic,xPos,yPos);

        pDC->SetStretchBltMode(HALFTONE);
        SetBrushOrgEx(bmDC,0,0,NULL);
        pDC->StretchBlt(xPos,yPos,imageWidth,-imageHeight,&bmDC,0,0,bi.bmWidth, bi.bmHeight,SRCCOPY);
        bmDC.SelectObject(pOldbmp);
        pngBmp[iPic].Detach();

        imageLegend.Format(_T("Photo %2d"),iPic+1);
        CSize rSize = pDC->GetTextExtent(imageLegend, imageLegend.GetLength());
        pDC->TextOut(xPos+(imageWidth/2)-rSize.cx/2,yPos-imageHeight,imageLegend, imageLegend.GetLength());
        }
    imagesLoaded = true;
}
1

There are 1 best solutions below

1
On
pngBmp[iPic].Attach(pngImage[iPic].Detach());

You have called Detach() on pngImage, so pngImage is no longer valid. In the next call pngBmp will be invalid.

pngBmp[iPic].GetBitmap(&bi); //   ****** ABORTS Here

pngBmp[iPic].GetBitmap(&bi); will fail if there is no valid HBITMAP

Easier solution:

CPngImage is derived from CBitmap, it can do everything CBitmap does. You can simplify your code by removing pngBmp altogether and use pngImage for painting.

You can test the validity of png image with:

if(!pngImage[index].m_hObject)
    return;