再问GDI+的问题,如何获得Region的边界线

时间:2022-10-29 23:54:25
如何获得Region的边界线?

不要 Region.Translate 的方法。因为我显示的图片比例不定,采用此方法取出的边界线很难看。缩到很小时,几乎就看不到边界了

49 个解决方案

#1


呵,今天终于能发200分的贴了。

#2


应该是可以通用 Region.GetRegionData() 获得,但不知道如何做

#3


谁进来帮我顶一下吧 有分

#4


up

#5


你想要做成什么效果?是描出图片的边界么?

#6


一个已知的不规则的 Region,如何能得到它的边界,即一串 Point[]

#7


具体说出来,应该能有很多方法实现

#8


你的区域是什么?是位图么?

#9


就是要得到一串Point[]嘛,由它构成的边界。

#10


to wawaku,2位的黑白图

#11


或者能实现 API 的 FrameRgn 的功能也行

#12


就是说你的图是一张黑白的位图.而你想对位图中的某一区域进行描边.没理解错吧?

#13


to wawaku,是这个意思。

在网上找到一段代码:

Region r1, r2, rOut;
r1 = region.Clone();
r2 = region.Clone();
rOut = region.Clone();
r1.Translate(1, 0);
r2.Xor(r1);
r1.Translate(-1, 1);
rOut.Xor(r1);
rOut.Union(r2);

return rOut;

能实现功能,但当图片放大或缩小后,边界线非常难看

#14


GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

#15


to asus111: 这样只能得到 Region 的信息。但 Region 的边界呢?我要的是边界线

#16


帮你顶.

#17


多谢楼上。我如果采用上面的方法取得的边界,就会像这个样子,实在太难看了

http://www.cnblogs.com/images/cnblogs_com/loyee/77051/o_map.jpg

#18



Region r1, r2, rOut;
r1 = region.Clone();//??你原来的这个region是从哪来的?你的图是给定了这个region的?
r2 = region.Clone();
rOut = region.Clone();
r1.Translate(1, 0);
r2.Xor(r1);
r1.Translate(-1, 1);
rOut.Xor(r1);
rOut.Union(r2);

return rOut;

#19


原来的 region 就是采用 这个方法得来的
 asus1111(寒羽) ( ) 信誉:100    Blog  2006-11-23 13:37:40  得分: 0  
 
 
   GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

#20


看了你的图,你做GIS?那怎么会没有你想要的point[]?
而且GIS上的地图是解析地图文件来的,怎么会是位图?
你这个图要是位图的话,缩放也就没有意义了

#21


帮你up

#22


帮你up

#23


呵呵,不是用GIS做的,这只是随便举的一个例子。

#24


哪位在 .Net 下用过像 API  中的 FrameRgn 吗?我就是要实现这个功能

#25


原来的 region 就是采用 这个方法得来的
 asus1111(寒羽) ( ) 信誉:100    Blog  2006-11-23 13:37:40  得分: 0  
 
 
   GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

////////////////////////////////////////////////////////////

你说region是从这里来的,我觉得没有什么道理.
1,那你的new Rectangle(...);数据从哪里来?
2,如果你的region是从path来的,那何必费这个劲来画呢,你想要的数组就在
 ph.PathData.Points[]里啊.
3,如果你不是做GIS的,我看到的那个只是一个位图,那你放大缩小便没有意义了

#26


想用就直接用呗 

[DllImport("gdi32.dll", EntryPoint = "FrameRgn")]
        public static extern int FrameRgn (....);

#27


1、new Rectangle(...)采用位图中的每个点上的颜色判断得来;
2、ph.PathData.Points[] 里面存的点并不是边界,而是每次 AddRectangle() 的点信息,导至 DrawLines(Pen, Point[])是一片,而不是一条线;
3、至于位图放大缩小是否有意义,因为系统需要

#28


wawaku
 
   想用就直接用呗 
=======================================
似乎并不能那么直接地使用

#29


1、new Rectangle(...)采用位图中的每个点上的颜色判断得来;
2、ph.PathData.Points[] 里面存的点并不是边界,而是每次 AddRectangle() 的点信息,导至 DrawLines(Pen, Point[])是一片,而不是一条线;
3、至于位图放大缩小是否有意义,因为系统需要
///////////////////////////////////////////////

既然你的通过判断每个点得来的new Rectangle(...),你必然可以取到颜色有变化的地方的点.
比如上一点是黑色,而一下点是白色,那你则可在另一点数组记此点.由此得到边界点数组.

#30


API 在.NET中是可以使用的.只是这个函数我没用过,很多GDI里的API函数我都用过.用我那样写是可以的.

#31


to wawaku:

你必然可以取到颜色有变化的地方的点.
======================================================
没错,就是根据颜色变化情况得到。但比如下面:
------------------------------
____1****7______******________
---2******6____********_______
----3****5------*****---------
------4*----------**----------
------------------------------
横线表示白色,星表示黑色。边框,就应该是1->2->3->4->5->6-7这样的点顺序才能画出来。
而这个点的顺序在 path.PathPoints 中保存是顺序并不是这样,导至画的线而不是边框

#32


在 path.PathPoints 中的顺序是 1->7->2->6->3->5->4

#33


wawaku

API 在.NET中是可以使用的.只是这个函数我没用过,很多GDI里的API函数我都用过.用我那样写是可以的.
============================================================
我的意思不是说GDI的API不能在.Net中使用。这是因为gdi32和gdi+(gdiplus)的区别,能直接使用吗?

Region是在.Net中创建的System.Drawng.Region,而不是采用gdi32中的Create...Rgn

#34


倒是可以这样 IntPtr hrgn =region.GetHrgn(g);
来得到HRGN,但HBrush我没找到.需要实验

#35


费了九牛二虎之力,终于调成了
         [DllImport("gdi32.dll", EntryPoint = "FrameRgn")]
         public static extern int FrameRgn(
           IntPtr hdc,     // handle to device context
           IntPtr hrgn,   // handle to region to be framed
           IntPtr hbr,  // handle to brush used to draw border
           int nWidth,  // width of region frame
           int nHeight);
描边成功.
但,不能解决你的问题.他也是,如果按我们得到的region,点的顺序是乱的.那他画的也是乱的.
看来得另想办法了

#36


请问 wawaku,

hdc 应该传 Graphics.GetHdc()?
hrgn 应该传 Gegion.GetHrgn(graphics)?
hbr 呢,难道用 gdi32 中 CreateSolidBrush?

#37


对了,真就是用的gdi32中的CreateSolidBrush.
可是白忙火了半天,还是不能解决问题

#38


可是我这样调用会报错:
....
IntPtr hdc = graphics.GetHdc();
IntPtr hRgn = region.GetHrgn(graphics); //报“当前对象正在其它地方使用”
...

#39



IntPtr hRgn = region.GetHrgn(graphics);
IntPtr hdc = graphics.GetHdc();

g在绑定dc之后,就不能给别的东西用了

#40


成功!!!!

#41


多谢 wawaku。

效果图
http://www.cnblogs.com/images/cnblogs_com/loyee/77051/o_map2.jpg

#42


??晕倒,我用这个函数,打乱了顺序咋就不行呢?
你是自己做的DEMO么?
要是没什么保密的能发给我一份不?
guofengxiang-9@163.com

#43


核心代码,将以下拷贝到 Form 中运行。

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int FrameRgn(IntPtr hdc, IntPtr hRgn, IntPtr hBrush, int nWidth, int nHeight);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern IntPtr CreateSolidBrush(int crColor);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int DeleteObject(IntPtr hObject);

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    Region region = new Region(new Rectangle(10, 10, 50, 50));
    region.Union(new Rectangle(40, 40, 100, 100));
    e.Graphics.FillRegion(Brushes.Black, region);
    IntPtr hBrush = CreateSolidBrush(255);
    IntPtr hRgn = region.GetHrgn(e.Graphics);
    IntPtr hdc = e.Graphics.GetHdc();
    FrameRgn(hdc, hRgn, hBrush, 1, 1);
    e.Graphics.ReleaseHdc();
    region.ReleaseHrgn(hRgn);
    DeleteObject(hBrush);
}

#44


我倒!
这么写你认为我不会么?
我自己造了一个region.从path里来的.加了一个10个点的多边形.
当顺序正确时描边成功 .当顺序不对时,描边描的乱七八糟.

如果按我这样的结果.跟本就没必要搞什么FrameRgn了,因为它和g.DrawPolygon完成功能一样.那我们还讨论一下午干嘛

#45


今天下班了,如果你有时间,明天再开一贴与你讨论

#46


DrawPolygon或DrawLines都是不能的

#47


明见

#48


至少现在,我还没有发现FrameRgn和g.DrawPolygon有啥区别

#49


标记

#1


呵,今天终于能发200分的贴了。

#2


应该是可以通用 Region.GetRegionData() 获得,但不知道如何做

#3


谁进来帮我顶一下吧 有分

#4


up

#5


你想要做成什么效果?是描出图片的边界么?

#6


一个已知的不规则的 Region,如何能得到它的边界,即一串 Point[]

#7


具体说出来,应该能有很多方法实现

#8


你的区域是什么?是位图么?

#9


就是要得到一串Point[]嘛,由它构成的边界。

#10


to wawaku,2位的黑白图

#11


或者能实现 API 的 FrameRgn 的功能也行

#12


就是说你的图是一张黑白的位图.而你想对位图中的某一区域进行描边.没理解错吧?

#13


to wawaku,是这个意思。

在网上找到一段代码:

Region r1, r2, rOut;
r1 = region.Clone();
r2 = region.Clone();
rOut = region.Clone();
r1.Translate(1, 0);
r2.Xor(r1);
r1.Translate(-1, 1);
rOut.Xor(r1);
rOut.Union(r2);

return rOut;

能实现功能,但当图片放大或缩小后,边界线非常难看

#14


GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

#15


to asus111: 这样只能得到 Region 的信息。但 Region 的边界呢?我要的是边界线

#16


帮你顶.

#17


多谢楼上。我如果采用上面的方法取得的边界,就会像这个样子,实在太难看了

http://www.cnblogs.com/images/cnblogs_com/loyee/77051/o_map.jpg

#18



Region r1, r2, rOut;
r1 = region.Clone();//??你原来的这个region是从哪来的?你的图是给定了这个region的?
r2 = region.Clone();
rOut = region.Clone();
r1.Translate(1, 0);
r2.Xor(r1);
r1.Translate(-1, 1);
rOut.Xor(r1);
rOut.Union(r2);

return rOut;

#19


原来的 region 就是采用 这个方法得来的
 asus1111(寒羽) ( ) 信誉:100    Blog  2006-11-23 13:37:40  得分: 0  
 
 
   GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

#20


看了你的图,你做GIS?那怎么会没有你想要的point[]?
而且GIS上的地图是解析地图文件来的,怎么会是位图?
你这个图要是位图的话,缩放也就没有意义了

#21


帮你up

#22


帮你up

#23


呵呵,不是用GIS做的,这只是随便举的一个例子。

#24


哪位在 .Net 下用过像 API  中的 FrameRgn 吗?我就是要实现这个功能

#25


原来的 region 就是采用 这个方法得来的
 asus1111(寒羽) ( ) 信誉:100    Blog  2006-11-23 13:37:40  得分: 0  
 
 
   GraphicsPath path = new GraphicsPath();
//......
path.AddRectangle(new Rectangle(...));
//......
Region region = new Region(path);

////////////////////////////////////////////////////////////

你说region是从这里来的,我觉得没有什么道理.
1,那你的new Rectangle(...);数据从哪里来?
2,如果你的region是从path来的,那何必费这个劲来画呢,你想要的数组就在
 ph.PathData.Points[]里啊.
3,如果你不是做GIS的,我看到的那个只是一个位图,那你放大缩小便没有意义了

#26


想用就直接用呗 

[DllImport("gdi32.dll", EntryPoint = "FrameRgn")]
        public static extern int FrameRgn (....);

#27


1、new Rectangle(...)采用位图中的每个点上的颜色判断得来;
2、ph.PathData.Points[] 里面存的点并不是边界,而是每次 AddRectangle() 的点信息,导至 DrawLines(Pen, Point[])是一片,而不是一条线;
3、至于位图放大缩小是否有意义,因为系统需要

#28


wawaku
 
   想用就直接用呗 
=======================================
似乎并不能那么直接地使用

#29


1、new Rectangle(...)采用位图中的每个点上的颜色判断得来;
2、ph.PathData.Points[] 里面存的点并不是边界,而是每次 AddRectangle() 的点信息,导至 DrawLines(Pen, Point[])是一片,而不是一条线;
3、至于位图放大缩小是否有意义,因为系统需要
///////////////////////////////////////////////

既然你的通过判断每个点得来的new Rectangle(...),你必然可以取到颜色有变化的地方的点.
比如上一点是黑色,而一下点是白色,那你则可在另一点数组记此点.由此得到边界点数组.

#30


API 在.NET中是可以使用的.只是这个函数我没用过,很多GDI里的API函数我都用过.用我那样写是可以的.

#31


to wawaku:

你必然可以取到颜色有变化的地方的点.
======================================================
没错,就是根据颜色变化情况得到。但比如下面:
------------------------------
____1****7______******________
---2******6____********_______
----3****5------*****---------
------4*----------**----------
------------------------------
横线表示白色,星表示黑色。边框,就应该是1->2->3->4->5->6-7这样的点顺序才能画出来。
而这个点的顺序在 path.PathPoints 中保存是顺序并不是这样,导至画的线而不是边框

#32


在 path.PathPoints 中的顺序是 1->7->2->6->3->5->4

#33


wawaku

API 在.NET中是可以使用的.只是这个函数我没用过,很多GDI里的API函数我都用过.用我那样写是可以的.
============================================================
我的意思不是说GDI的API不能在.Net中使用。这是因为gdi32和gdi+(gdiplus)的区别,能直接使用吗?

Region是在.Net中创建的System.Drawng.Region,而不是采用gdi32中的Create...Rgn

#34


倒是可以这样 IntPtr hrgn =region.GetHrgn(g);
来得到HRGN,但HBrush我没找到.需要实验

#35


费了九牛二虎之力,终于调成了
         [DllImport("gdi32.dll", EntryPoint = "FrameRgn")]
         public static extern int FrameRgn(
           IntPtr hdc,     // handle to device context
           IntPtr hrgn,   // handle to region to be framed
           IntPtr hbr,  // handle to brush used to draw border
           int nWidth,  // width of region frame
           int nHeight);
描边成功.
但,不能解决你的问题.他也是,如果按我们得到的region,点的顺序是乱的.那他画的也是乱的.
看来得另想办法了

#36


请问 wawaku,

hdc 应该传 Graphics.GetHdc()?
hrgn 应该传 Gegion.GetHrgn(graphics)?
hbr 呢,难道用 gdi32 中 CreateSolidBrush?

#37


对了,真就是用的gdi32中的CreateSolidBrush.
可是白忙火了半天,还是不能解决问题

#38


可是我这样调用会报错:
....
IntPtr hdc = graphics.GetHdc();
IntPtr hRgn = region.GetHrgn(graphics); //报“当前对象正在其它地方使用”
...

#39



IntPtr hRgn = region.GetHrgn(graphics);
IntPtr hdc = graphics.GetHdc();

g在绑定dc之后,就不能给别的东西用了

#40


成功!!!!

#41


多谢 wawaku。

效果图
http://www.cnblogs.com/images/cnblogs_com/loyee/77051/o_map2.jpg

#42


??晕倒,我用这个函数,打乱了顺序咋就不行呢?
你是自己做的DEMO么?
要是没什么保密的能发给我一份不?
guofengxiang-9@163.com

#43


核心代码,将以下拷贝到 Form 中运行。

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int FrameRgn(IntPtr hdc, IntPtr hRgn, IntPtr hBrush, int nWidth, int nHeight);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern IntPtr CreateSolidBrush(int crColor);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern int DeleteObject(IntPtr hObject);

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    Region region = new Region(new Rectangle(10, 10, 50, 50));
    region.Union(new Rectangle(40, 40, 100, 100));
    e.Graphics.FillRegion(Brushes.Black, region);
    IntPtr hBrush = CreateSolidBrush(255);
    IntPtr hRgn = region.GetHrgn(e.Graphics);
    IntPtr hdc = e.Graphics.GetHdc();
    FrameRgn(hdc, hRgn, hBrush, 1, 1);
    e.Graphics.ReleaseHdc();
    region.ReleaseHrgn(hRgn);
    DeleteObject(hBrush);
}

#44


我倒!
这么写你认为我不会么?
我自己造了一个region.从path里来的.加了一个10个点的多边形.
当顺序正确时描边成功 .当顺序不对时,描边描的乱七八糟.

如果按我这样的结果.跟本就没必要搞什么FrameRgn了,因为它和g.DrawPolygon完成功能一样.那我们还讨论一下午干嘛

#45


今天下班了,如果你有时间,明天再开一贴与你讨论

#46


DrawPolygon或DrawLines都是不能的

#47


明见

#48


至少现在,我还没有发现FrameRgn和g.DrawPolygon有啥区别

#49


标记