CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Feb 2005
    Location
    Madrid (Spain)
    Posts
    511

    Fast way to display large images

    Hi gurus!!

    I am working with a large images (280 Mb aprox) in BMP format.

    I can print a image on DC using StretchDIBits and it works fine.

    I want to save in a buffer the content of the DC (after the image was printed) because if part of the dialog is invalidate (down or move the dialog) I can print again in small time.

    What is the best way?

    Thanks in advance!!!

  2. #2
    Join Date
    Feb 2005
    Location
    Madrid (Spain)
    Posts
    511

    Re: Fast way to display large images

    Hi!

    Perhaps the ask is not very clear...


    Step 1.- Read BMP file:
    IN .H FILE:
    Code:
    class CTrasformaDlg : public CDialog
    {
    // Construcción
    public:
        CTrasformaDlg(CWnd* pParent = NULL);    // Constructor estándar
    
    // Datos del cuadro de diálogo
        enum { IDD = IDD_TRASFORMA_DIALOG };
    
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // Compatibilidad con DDX/DDV
    
    
    // Implementación
    protected:
        HICON m_hIcon;
    
        // Funciones de asignación de mensajes generadas
        virtual BOOL OnInitDialog();
        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
        afx_msg void OnPaint();
        afx_msg HCURSOR OnQueryDragIcon();
        DECLARE_MESSAGE_MAP()
    public:
        afx_msg void OnDestroy();
        afx_msg void OnBnClickedButtonLoadbmp();
        
        CString szBmpFile;
        CString szEcwFile;
    
        HWND hndWnd;
        // BMP Completo
    
        BYTE *pBits;
        BITMAPINFOHEADER infoHeader;
        int nBitsPixel, nHeight, nPlanos, nWidth, nImgSize;
        CRect rBmp;
        HDC hDC;
    };
    IN .CPP FILE:
    Code:
    void CTrasformaDlg::OnBnClickedButtonLoadbmp()
    {
        // TODO: Agregue aqu* su código de controlador de notificación de control
        CFileDialog fDlg(TRUE, _T("*.bmp"), 0, 4|2, _T("Ficheros BMP (*.bmp)|*.bmp||"), this);
        fDlg.DoModal();
        szBmpFile = fDlg.GetPathName();
    
        if(szBmpFile == "") return;  
    
        char sNombre[500];
        WideCharToMultiByte(CP_ACP, NULL, szBmpFile, -1, sNombre, 500, NULL, NULL);
    
        FILE *pf = fopen(sNombre, "rb");
    
        nWidth = 0;
        nHeight = 0;
        nBitsPixel = 0;
        nPlanos = 0;
        int nOffsetImg = 0;
        nImgSize = 0;
    
        fseek(pf, 10L, SEEK_SET);
        fread(&nOffsetImg, 4, 1, pf);
        fseek(pf, 34L, SEEK_SET);
        fread(&nImgSize, 4, 1, pf);
    
        fseek(pf, 18L, SEEK_SET);
        fread(&nWidth, 4, 1, pf);
        fseek(pf, 22L, SEEK_SET);
        fread(&nHeight, 4, 1, pf);        
    
        fseek(pf, 26L, SEEK_SET);
        fread(&nPlanos, 2, 1, pf);
        fseek(pf, 28L, SEEK_SET);
        fread(&nBitsPixel, 2, 1, pf);    
    
        pBits = (BYTE *) malloc(nImgSize);
        memset(pBits, 0, nImgSize);
    
        fseek(pf, nOffsetImg, SEEK_SET);
        fread(pBits, nImgSize, 1, pf);
    
        fclose(pf);
      
        hndWnd = ::GetDlgItem(this->GetSafeHwnd(), IDC_STATIC_IMG);             
        ::GetClientRect(hndWnd, &rBmp);
    
        memset(&infoHeader, 0, sizeof(BITMAPINFOHEADER));
        infoHeader.biBitCount = nBitsPixel;
        infoHeader.biCompression = BI_RGB;
        infoHeader.biHeight = nHeight;
        infoHeader.biPlanes = nPlanos;
        infoHeader.biWidth = nWidth;
        infoHeader.biSize = sizeof(BITMAPINFOHEADER);    
        infoHeader.biSizeImage = nImgSize;      
    
        OnPaint();
    }
    
    void CTrasformaDlg::OnPaint()
    {
        if (IsIconic())
        {
            CPaintDC dc(this); // Contexto de dispositivo para dibujo
    
            SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
            // Centrar icono en el rectángulo de cliente
            int cxIcon = GetSystemMetrics(SM_CXICON);
            int cyIcon = GetSystemMetrics(SM_CYICON);
            CRect rect;
            GetClientRect(&rect);
            int x = (rect.Width() - cxIcon + 1) / 2;
            int y = (rect.Height() - cyIcon + 1) / 2;
    
            // Dibujar el icono
            dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {        
            CDialog::OnPaint();        
        }
        Dibuja();
    }
    Step 2.- Print the image into DC:

    Code:
    void CTrasformaDlg::Dibuja(void) {
        hDC = ::GetDC(hndWnd);    
        BITMAPINFO bInfo;
        memset(&bInfo, 0, sizeof(BITMAPINFO));
        bInfo.bmiHeader = infoHeader;
    
        ::SetStretchBltMode(hDC, HALFTONE);
        int nLines = ::StretchDIBits(
            hDC, 
            0, 
            0, 
            rBmp.Width(), 
            rBmp.Height(), 
            0, 
            0, 
            rBmp.Width(), 
            rBmp.Height(), 
            (void **)pBits, 
            &bInfo, 
            DIB_RGB_COLORS,SRCCOPY);
        ::DeleteDC(hDC);
    }
    ....

    Now I have the image loaded in memory and printed in the window. I want to save the printed image in a buffer like a primary image was saved.

    It is quite clear?


    Thanks!!

  3. #3
    Join Date
    Mar 2008
    Location
    Turin / Italy
    Posts
    178

    Re: Fast way to display large images

    You have already done half of the work I think. Something like this will do the trick.

    Code:
    CDC pDC = GetDC();
    CRect Rect;
    GetWindowRect(&Rect);
    
    CDC MemDC;
    MemDC.CreateCompatibleDC(pDC);
    CBitmap m_Bitmap;
    m_Bitmap.CreateCompatibleBitmap(pDC,Rect.Width(),Rect.Height());
    CBitmap *pOldBmp = MemDC.SelectObject(&m_Bitmap);
    MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),pDC,Rect.left,Rect.top,SRCCOPY);
    MemDC.SelectObject(pOldBmp);
    
    now m_Bitmap holds the image of the pDC.
    
    BITMAP myBitmap;
    
    m_Bitmap.GetBitmap(&myBitmap);
    
    myBitmap holds the image structure. and you're done.

  4. #4
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Fast way to display large images

    That's a really huge image. Odds are, you don't need to see the whole thing at once, or if you do, you'll be zoomed out.

    This suggests that mipmapping the image and/or breaking it up into tiles may allow you to redraw it more quickly.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured