GDI+位图经过矩阵变换后裁切出错

Simality 2011-06-24 06:54:01
我用GDI+载入了一幅分辨率为813×6200的图片(先不管为什么,现在必须用这么大的)

程序是MFC的对话框界面,载入图片的相关代码如下(一些具体的值太长用…代替了):

//这一段在**Dlg.cpp文件开头
Graphics *m_pGraphics; // Create a global graphics pointer
Image *m_pImageAttitude; // Create a globalimage pointer


//这一段位于OnInitDialog()函数中
CDC *pDC=GetDC(); // Obtain device context
m_pGraphics = new Graphics(pDC->m_hDC); // Initialize graphics pointer
m_pGraphics->SetPageUnit(Unit::UnitPixel); // Use pixel unit

m_pImageAttitude = Bitmap::FromResource( // Obtain bitmap from resource
AfxGetApp()->m_hInstance,
(WCHAR*)(LPCTSTR)MAKEINTRESOURCE(IDB_BITMAP2));


//这一段位于专门用来刷新画面的函数中
Matrix m_matrix; // Create a unit matrix
m_matrix.Translate(………………); // Matrix translate transform
m_matrix.RotateAt(………………); // Matrix rotate transform
m_pGraphics->SetTransform(&m_matrix); // Apply transformation to image
m_pGraphics->DrawImage(m_pImageAttitude,0,0); // Display image starting at top left corner of current window



这部分工作正常。载入的画面正常显示在窗口上,我通过改变平移和旋转的变量可以控制位图做对应的运动。但由于图片很大,旋转后扫过了整个对话框的画面,现需要在当前对话框的固定位置创建一个固定的矩形区域作为窗口,仅在该窗口内显示变换后的图片。我决定使用区域集合的方式实现。增加以下代码

//修改过的用于刷新画面的代码:
Matrix m_matrix; // Create a unit matrix
m_matrix.Translate(………………); // Matrix translate transform
m_matrix.RotateAt(………………); // Matrix rotate transform
m_pGraphics->SetTransform(&m_matrix); // Apply transformation to image

// Inserted section start
CDC *pDC=GetDC(); // Obtain device context
Graphics rgnGraph(pDC->m_hDC); // Create a local graphics object
rgnGraph.SetPageUnit(Unit::UnitPixel); // Use pixel unit
GraphicsPath rgnPath; // Create an empty path
Rect fillRect(…,…,…,…); // Create a rectangle
rgnPath.AddRectangle(fillRect); // Add rectangle into path
Region m_rgnADI(&rgnPath); // Create a region from path
m_pGraphics->IntersectClip(&m_rgnADI); // Clip the image with region
// Inserted section end

m_pGraphics->DrawImage(m_pImageAttitude,0,0); // Display image starting at top left corner of current window



运行程序发现画面上神马都没有。当我把矩阵平移语句
	m_matrix.Translate(………………);		// Matrix translate transform

注释掉后发现可以显示了,但只能在很小角度范围内旋转(SliderCtrl控制0~359度旋转),如果转多了图像就呈现拖影,固定住了。再转回来也不会刷新了。

请问这个现象怎么解决?谢谢。
...全文
196 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Simality 2011-06-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fredh 的回复:]

Sorry啊,这个问题几年前的一个项目遇到过,也解决了。但时间太久,忘了具体怎么解决的,但隐约记得是和哪个参数值有关,你试着找找看吧
[/Quote]

哈,问题已解决。多谢提醒。尽管只是一句话,立即让我顺藤摸瓜找到了要找的东西。详情如下:

前面说到了有两种裁切的方法,Graphics::IntersectClip和Graphics::SetClip。前者需要另行准备一个Region对象,然后用当前的Graphics对象与之取交集。而后者只需要一个矩形——至少一开始我是这么认为。

初步实验二者的结果是等效的,出问题都出得一模一样。但经您提醒之后我分别查看了这两个函数的原型,它们都在GdiPlusGraphics.h文件中。IntersectClip一共有3个重载函数,SetClip有6个。

在我查看代码的时候发现了SetClip第6个重载函数开头前的一段注释:


这也证实了其它裁切函数都不可避免随Graphics对象一起被转换,IntersectClip没有一个重载是能用的。现在我通过创建HRGN实现了快捷有效的裁切。结贴给分。
Simality 2011-06-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fredh 的回复:]

Sorry啊,这个问题几年前的一个项目遇到过,也解决了。但时间太久,忘了具体怎么解决的,但隐约记得是和哪个参数值有关,你试着找找看吧
[/Quote]

您的意思是仍然使用我上面的某一个流程,只是修改一下参数?那我仔细查查用过的函数都有哪些重载。

还有,我上面一楼说的漏掉了一步:ResetTransform

像这样:
	m_pGraphics->DrawImage(m_pImageAttitude,0,0);
m_pGraphics->ResetTransform();
m_pGraphics->SetClip(&m_rgnADI,CombineModeIntersect);


只有消除施加于Graphics对象上的变换再应用clip才能工作。不过这样clip已经没有什么意义了,外围已经被污染了,与其clip过后再去用背景色填充外围,不如每次都直接填充外围,不用clip了。
自由心证 2011-06-25
  • 打赏
  • 举报
回复
Sorry啊,这个问题几年前的一个项目遇到过,也解决了。但时间太久,忘了具体怎么解决的,但隐约记得是和哪个参数值有关,你试着找找看吧
Simality 2011-06-24
  • 打赏
  • 举报
回复
刚才又试了Graphics.SetClip方法,一样的毛病。

现在已确认矩阵变换会影响取交集的操作。因为执行的IntersectClip函数属于被变换过的那个Graphics对象。折中的办法是先用DrawImage方法把图画出来,之后再去裁切。先画出来的多余部分会污染周围的空间,正在想办法解决。
下载代码方式:https://pan.quark.cn/s/957405011bdf 在计算机视觉技术中,轮廓提取与中心识别被视为两项核心的技术,它们对于图像处理及模式识别领域扮演着不可或缺的角色。本文将深入剖析这两种算法,并围绕"轮廓提取(中心识别)算法"这一核心主题,同时结合所提供的压缩包文件"Contour",对相关知识点进行详尽的阐述。 轮廓提取算法,主要功能在于识别并分离图像中的不同对象。该算法通过探测物体边缘,构建出明确的边界线,从而实现图像内部各组成部分的区分。在多色位图环境下,不同的色彩可能象征着不同的对象或区域,因此,一个性能优越的轮廓提取算法应当具备处理此类复杂场景的能力。常见的轮廓提取算法包括Canny边缘检测、Sobel算子、Laplacian算子和Hough变换等。这些算法各自具备独特的优缺点,究竟选择何种方法,需要依据具体的应用情境以及性能要求来决定。 1. Canny边缘检测:由John F. Canny所研发,这是一种自适应的多级边缘检测方法。Canny算法借助高斯滤波器来降低噪声干扰,随后运用强度梯度和非极大值抑制技术来定位最显著的边缘,最终通过双阈值检测来区分边缘与噪声。 2. Sobel算子:Sobel算子是一种基于梯度的边缘检测工具,它通过计算图像在水平和垂直方向上的梯度来探测边缘。此方法操作简便且效率较高,但可能对图像中的噪声较为敏感。 3. Laplacian算子:Laplacian算子是一种二阶导数算子,能够迅速识别图像中的尖峰(即边缘)。然而,它容易受到噪声的影响,因此通常需要与其他技术结合使用,例如Gaussian滤波。 4. Hough变换:Hough变换是一种在参数空间中进行边缘检测的方法,它能够检测出任意...
【重要提示】本资源设置为0积分下载,若非0积分请勿轻易下载 亲爱的CSDN用户: 首先感谢你点进这个资源页面。我需要提前说明一个重要情况: **本资源原本已设置为“0积分下载”**,即作者希望完全免费共享。但CSDN平台有时会根据文件的下载热度、文件大小、用户权限等因素,**自动将部分资源的积分调整为非0数值**(如1积分、2积分、5积分等)。这是平台系统的自动行为,而非作者本人的设定。 **因此,如果你当前看到该资源的下载所需积分不是0(例如显示为1、2、3……),请谨慎决定是否下载。** 如果你按照非0积分支付并下载后发现资源内容不符合预期、链接失效,或者实际上该资源本应是免费的,作者无法为此承担积分损失或退还操作。**强烈建议:仅在页面显示为0积分时进行下载。** 另外,本资源描述中**并未直接提供具体的下载地址或外部链接**,因为它本身是一个通过CSDN官方上传通道提交的文件/内容包。如果你看到描述中没有外部网盘地址,这是正常的——资源文件应通过CSDN内置的“下载”按钮获取。若因平台积分显示异常导致你支付了积分,请优先联系CSDN客服咨询积分退还政策,作者没有权限修改平台自动设定的积分值。 感谢你的理解与支持。技术分享本应开放,但受限于平台规则,特此提醒如上。祝学习进步!

15,976

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧