Visual C++程序开发范例宝典(软件工程师典藏版)
上QQ阅读APP看书,第一时间看更新

3.5 图形转换与缩放

实例108 将位图转换为JPG

本实例是一个提高效率的程序

实例位置:光盘\mingrisoft\03\108

实例说明

在进行图像处理时,经常涉及图形转换。本实例实现了将位图转换为JPG格式图像,效果如图3.30所示。

技术要点

JPG文件采用了复杂的数据压缩技术。本实例通过OCX控件CJPG实现从位图到JPG的转换。有关CJPG的源代码可以在本实例源代码目录下的“JPG”文件夹下找到。

图3.30 将位图转换为JPG

实现过程

(1)新建一个基于对话框的应用程序。

(2)在对话框中添加图片控件和按钮控件。

(3)注册JPGXControl1.ocx控件,导入OCX控件CJPG。

(4)主要程序代码如下:

            void CRevertPictureDlg::OnOK()
            {
              m_JPG.SetBmpFile(m_filename);                                          //设置位图文件路径
              m_JPG.SetQuality((long)90);
              CFileDialog m_dlg(FALSE,"JPG",NULL,NULL,"JPG图像(JPG)|*.JPG",this);     //构造另存为对话框
            if (m_dlg.DoModal()==IDOK)
            {
            m_JPG.BmpToJPG(m_dlg.GetPathName());                          //转换图片
            }
        }

举一反三

根据本实例,读者可以:

将JPG转换为位图。

实例109 将位图转为GIF图标

本实例是一个提高效率的程序

实例位置:光盘\mingrisoft\03\109

实例说明

由于位图文件通常很大,因此网上的许多动画和图片都是采用GIF或JPG格式显示。本实例将实现位图转换为GIF格式,效果如图3.31所示。

技术要点

在Visual C++中没有提供相应的类或函数将位图转换为GIF,本实例使用了OCX控件CGIF。通过调用CGIF控件的SaveToFile方法实现位图的转换。CGIF控件的源代码位于本实例源代码下的GIF文件夹下。

图3.31 将位图转为GIF图标

实现过程

(1)新建一个基于对话框的应用程序。

(2)在对话框中添加图片控件、按钮和编辑框控件。

(3)注册GIFXControl1.ocx控件,导入OCX控件CGIF。

(4)主要程序代码如下:

        void CConvertGIfDlg::OnConvert()
        {
            if (!m_FileName.IsEmpty())
            {
              m_Gif.SetBmpFile(m_FileName);                                         //设置待转换的文件路径
              CFileDialog dlg(FALSE,"gif",NULL,NULL,"GIF文件(GIF)|*.gif",this);      //构造另存为对话框
              if (dlg.DoModal()==IDOK)
              {
                    m_Gif.SaveToFile(dlg.GetPathName()); //转换为GIF图标
              }
            }
        }

举一反三

根据本实例,读者可以:

将GIF转换为位图。

实例110 图片的平滑缩放

本实例是一个提高效率、人性化的程序

实例位置:光盘\mingrisoft\03\110

实例说明

在浏览图片的时候,如果被浏览的图片失真或大于浏览区的界面,可以将图片缩小或放大后再进行浏览。本实例实现了等比例平滑缩放图片的功能。运行程序,单击“打开”按钮,打开要进行平滑缩放的图片文件,将打开的文件显示在窗体中。通过拖动窗体中间部分的滑块控件设置图片缩放的比例,单击“缩放”按钮,完成图片的平滑缩放,如图3.32所示。

图3.32 图片的平滑缩放

本实例通过滑块控件设置图片的缩放比率,然后使用StretchBlt函数将图片按比例进行缩放,最后通过带有滚动条的无模式对话框配合图片控件显示缩放后的图片。利用SetRange方法设置滑块控件两侧的刻度,语法如下:

技术要点

void SetRange( int nMin, int nMax, BOOL bRedraw = FALSE );

参数说明:

● nMin:滑块控件的最小值。

● nMax:滑块控件的最大值。

● bRedraw:指定滑块控件是否重画以反映滑标的变化。如果这个参数为TRUE,滑标将被重画,否则不被重画。

注意:StretchBlt函数的使用方法可以参照实例097放大和缩小图片。

实现过程

(1)新建一个基于对话框的应用程序。

(2)创建一个对话框,并选择Horizontal Scroll和Vertical Scroll风格。为对话框添加类CFrameDlg,在该类中设置滚动条的滑块位置等参数。

(3)向窗体中添加一个滑块控件、两个图片控件和两个按钮控件。

(4)主要程序代码如下:

            void CSmoothnessDlg::OnButopen()
            {
              CFileDialog m_dialog (true,"bmp",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                  "位图文件(*.bmp)|*.bmp",this);                           //构造打开对话框
              if (m_dialog.DoModal()==IDOK)
              {
              CString str;
              str = m_dialog.GetPathName();
              m_hBitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(),str,IMAGE_BITMAP,0,0,LR_LOADFR
                          OMFILE|LR_DEFAULTCOLOR|LR_DEFAULTSIZE);          //加载位图资源
              if (m_hBitmap != NULL)
              {
                      m_picture.SetBitmap(m_hBitmap);                      //显示图片
              }
              BITMAP bmp;
              GetObject(m_hBitmap,sizeof(bmp),&bmp);                       //获得图片信息
              CRect rect;
              dlg.GetClientRect(rect);
              int xpos = dlg.GetScrollPos(SB_HORZ);
              if (xpos != 0)
                      dlg.ScrollWindow(xpos,0);                            //恢复窗口的水平滚动区域
              int ypos = dlg.GetScrollPos(SB_VERT);
              if (ypos != 0)
                      dlg.ScrollWindow(0,ypos);                            //恢复窗口的垂直滚动区域
              SCROLLINFO vinfo;
              vinfo.cbSize = sizeof(vinfo);
              vinfo.fMask = SIF_ALL;
              vinfo.nPage = bmp.bmHeight/10;
              vinfo.nMax= bmp.bmHeight-rect.Height()+bmp.bmHeight/10;
              vinfo.nMin = 0;
              vinfo.nTrackPos = 0;
              vinfo.nPos = 0;
              //设置垂直滚动条信息
              dlg.SetScrollInfo(SB_VERT,&vinfo);
              vinfo.fMask = SIF_ALL;
              vinfo.nPage = bmp.bmWidth/10;
              vinfo.nMax= bmp.bmWidth-rect.Width()+bmp.bmWidth/10;
              vinfo.nMin = 0;
              vinfo.nPos  =0;
              vinfo.nTrackPos = 0;
              vinfo.cbSize = sizeof(vinfo);
              //设置水平滚动条信息
              dlg.SetScrollInfo(SB_HORZ,&vinfo);
            }
        }
        void CSmoothnessDlg::OnReleasedcaptureSlider1(NMHDR* pNMHDR, LRESULT* pResult)
        {
            CString str;
            str.Format("%d%%",m_slider.GetPos());                      //将滑块当前位置格式化为字符串
            m_edit.SetWindowText(str);                                 //显示当前位置
            *pResult = 0;
        }
        void CSmoothnessDlg::OnButdraw()
        {
            CRect rect;
            dlg.GetClientRect(rect);
            int xpos = dlg.GetScrollPos(SB_HORZ);
            if (xpos != 0)
              dlg.ScrollWindow(xpos,0);                                //恢复窗口的水平滚动区域
            int ypos = dlg.GetScrollPos(SB_VERT);
            if (ypos != 0)
              dlg.ScrollWindow(0,ypos);                                //恢复窗口的垂直滚动区域
            CDC* pDC = m_picture.GetDC();
            //将位图选进设备场景中
            CDC memdc;
            memdc.CreateCompatibleDC( pDC );
            memdc.SelectObject(m_hBitmap);
            BITMAP bmp;
            GetObject(m_hBitmap,sizeof(bmp),&bmp);                                                 //获得图片信息
            int x,y;
            x = bmp.bmWidth*m_slider.GetPos()/100;
            y = bmp.bmHeight*m_slider.GetPos()/100;
            m_picture.MoveWindow(rect.left,rect.top,x,y,true);
            pDC->StretchBlt(rect.left,rect.top,x,y,&memdc,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);   //绘制图片
            memdc.DeleteDC();
            SCROLLINFO vinfo;
            vinfo.cbSize = sizeof(vinfo);
            vinfo.fMask = SIF_ALL;
            vinfo.nPage = y/10;
            vinfo.nMax= y-rect.Height()+y/10;
            vinfo.nMin = 0;
            vinfo.nTrackPos = 0;
            vinfo.nPos = 0;
            //设置垂直滚动条信息
            dlg.SetScrollInfo(SB_VERT,&vinfo);
            vinfo.fMask = SIF_ALL;
            vinfo.nPage = x/10;
            vinfo.nMax= x-rect.Width()+x/10;
            vinfo.nMin = 0;
            vinfo.nPos  =0;
            vinfo.nTrackPos = 0;
            vinfo.cbSize = sizeof(vinfo);
            //设置水平滚动条信息
            dlg.SetScrollInfo(SB_HORZ,&vinfo);
        }

举一反三

根据本实例,读者可以:

开发图像编辑软件。