Tag: gdi +

在透明表单上单击以访问桌面

我有一个屏幕捕获实用程序,我可以在桌面上橡皮筋区域。 我这样做是一种相当简单的方式,我有一个与屏幕大小相同的表单,我将绘制的桌面屏幕截图转换为灰度。 当用户按住鼠标左键时,他/她可以选择表单上的区域。 用户绘制的矩形用TransparentColor填充。 一旦用户抬起他/她的鼠标,透明矩形就会保留在原位并且实际桌面可见。 这就是我的问题:在我的开发PC上,我实际上可以点击这个透明的矩形并导航等,而在我的另一台PC上,表单响应鼠标点击实际的透明矩形。 我在C#中使用.NET 4.0,关于如何让它在所有情况下实际点击进入桌面的任何想法? 谢谢你,非常感谢:)

为什么位图比较不等于自身?

这有点令人费解。 以下代码是一个小测试应用程序的一部分,用于validation代码更改未引入回归。 为了加快速度,我们使用了memcmp ,它似乎是比较两个相同大小图像的最快方法 (不出所料)。 但是,我们有一些测试图像显示出一个相当令人惊讶的问题:位图数据上的memcmp告诉我们它们不相等,但是,逐像素比较根本没有发现任何差异。 我的印象是,在Bitmap上使用LockBits ,您会得到图像的实际原始字节。 对于24 bpp位图,有点难以想象像素相同但基础像素数据不相同的情况。 一些令人惊讶的事情: 差异始终是单个字节,在一个映像中为00在另一个映像中为FF 。 如果将Format32bppRgb的PixelFormat更改为Format32bppRgb或Format32bppArgb ,则比较成功。 如果将第一个LockBits调用返回的BitmapData作为第四个参数传递给第二个参数,则比较成功。 如上所述,逐像素比较也成功。 我有点难过,因为坦率地说我无法想象为什么会这样。 (简化)代码如下。 只需使用csc /unsafe编译,并将24bpp的PNG图像作为第一个参数传递。 using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; class Program { public static void Main(string[] args) { Bitmap title = new Bitmap(args[0]); Console.WriteLine(CompareImageResult(title, new Bitmap(title))); } private static string CompareImageResult(Bitmap bmp, Bitmap expected) { […]

双线性插值 – DirectX与GDI +

我有一个C#应用程序,我已经编写了GDI +代码,它使用Bitmap / TextureBrush渲染来呈现2D图像,这些图像可以应用各种图像处理function。 此代码是模拟现有DX9代码的应用程序中的新路径,它们共享一个公共库以执行所有向量和矩阵(例如ViewToWorld / WorldToView)操作。 我的测试床由DX9输出图像组成,我将其与新GDI +代码的输出进行比较。 渲染到与Bitmap尺寸匹配的视口(即没有缩放或平移)的简单测试用例确实匹配像素完美(没有二进制差异) – 但是一旦图像被放大(放大),我就会得到非常小的差异在5-10%的像素中。 差异的大小是1(偶尔2)/ 256。 我怀疑这是由于插值差异造成的。 问题 :对于DX9正射投影(和身份世界空间),相机垂直并以纹理四边形为中心,期望DirectX.Direct3D.TextureFilter.Linear生成相同的输出到GDI + TextureBrush填充的矩形/多边形是合理的使用System.Drawing.Drawing2D.InterpolationMode.Bilinear设置? 对于这个(放大)情况,DX9代码正在使用它(MinFilter,MipFilter设置类似): Device.SetSamplerState(0, SamplerStageStates.MagFilter, (int)TextureFilter.Linear); 并且GDI +路径正在使用: g.InterpolationMode = InterpolationMode.Bilinear; 我认为“双线性插值”是一个相当具体的滤波器定义,但后来我注意到GDI +中还有另一种选择“HighQualityBilinear”(我尝试过,没有区别 – 考虑到“添加预滤波”的描述,这是有道理的缩小“) 后续问题:期望DirectX和GDI +之间的像素完美输出匹配是否合理(假设传入的所有外部坐标相等)? 如果没有,为什么不呢? 澄清:我正在使用的图像是使用Format32bppPArgb的不透明灰度(R = G = B,A = 1)。 最后,我可以使用许多其他API(Direct2D,WPF,GDI等) – 这个问题通常适用于比较“等效”双线性插值输出图像的输出。 谢谢!

澄清ColorMatrix转换的工作原理

我正在做一些关于图像处理应用程序的工作(为了好玩),我正在努力完全理解ColorMatrix转换的工作原理。 我得到线性/仿射变换的基础知识,并且可以通过在线复制示例得到很好的结果,但我想完全理解为什么有些东西可以工作而不仅仅是满足它的工作原理。 例如,对图像进行简单转换以产生其负值(每种颜色转换为其各自的互补)使用以下矩阵: [-1, 0, 0, 0, 0] [0, -1, 0, 0, 0] [0, 0, -1, 0, 0] [0, 0, 0, 1, 0] [1, 1, 1, 0, 1] 我知道-1是180度的余弦,这是将一种颜色“翻转”到它的互补所需的旋转,但我不明白的是颜色向量如何与上面的矩阵相乘并产生正确的互补向量。 例如,如果像素的颜色矢量为[247,255,0,255,1](使用RGBAW空间),则对上述矩阵进行乘法会产生[-247,-255,0,255,1] ,但这是不正确的,因为上面的实际互补色是[8,0,255,255,1]。 我在这里遗漏了一些明显的东西,我很高兴地承认我不完全确定我在做什么:)变换的颜色矢量是否在其他坐标系中表示? (例如不是0-255) 如果有人能帮助提供我理解的“缺失环节”,我会非常感激。 编辑 我刚刚发现以下矩阵也有效,并且实际上是直观的(它产生了正确的向量)。 -1 0 0 0 0 0 -1 0 0 0 0 0 -1 0 0 1 1 1 1 […]

渲染半透明/透明叠加

我需要一种快速的方法来在支持透明度的屏幕上绘制叠加层。 我做了很多搜索,找到了一个可能的解决方案(有自己的问题)和另一个不符合我要求的解决方案; 特别是透明支持。 我将从后者开始,然后触摸前者。 解决方案1 使用带有TransparencyKey的无边框表单,这是我发现的最有用的解决方案之一。 这个解决方案的工作原理是使用一个新的Form,让它无边框,将背景设置为类似Colour.White ,并将TransparencyKey设置为相同的颜色,将其设置为全屏和最顶层,并可能设置一些其他选项以使其不可见鼠标和键盘。 该解决方案的问题在于它不支持透明度; 它只会“剔除”与TransparencyKey 完全相同的颜色,因此,即使是最微小的差异,也会显示出在屏幕外面有半透明物体的想法。 解决方案2 使用P / Invoke和GDI +获取( GetDC & Graphics.FromHdc ),实际绘制,然后释放( ReleaseDC )桌面。 它的function很好,不幸的是,但是存在一些问题。 首先; 调用它一次显然只会画一次,因此如果画面完全刷新后它会消失,我不明白如何解决这个问题,如果这是最好的解决方案,我肯定需要帮助这个问题。 第二; 使用半透明的Brush和FillRectangle这种方法GDI +非常慢,我老实说不能怪它,但我要求它做得很快; GDI +显然无法满足的要求。 结论; 我需要一种在具有透明度支持的屏幕上绘制叠加层的方法,如果第二种方法是我应该使用的方法,我怎么能用半透明刷子绘制得足够快以至于它不是问题我怎么能让它更新呢屏幕刷新后它不会消失,如果不是我应该使用的方法,请指定我应该使用的方法。

LinearGradientBrush工件解决方法?

.net中的LinearGradientBrush(甚至是GDI +中的整体?)似乎有一个严重的错误:有时,它会引入工件。 (参见此处或此处 – 基本上,线性渐变的第一行在endcolor中绘制,即从白色到黑色的渐变将以黑色线条开始,然后使用正确的白色到黑色渐变) 我想知道是否有人为此找到了解决方法? 这是一个非常讨厌的bug 🙁 这是Artifacts的图片,请注意有2个LinearGradientBrushes: alt text http://img142.imageshack.us/img142/7711/gradientartifactmm6.jpg

我应该为每个Paint请求创建新的Pens / Brushes还是在整个应用程序生命周期中保留它们?

我有一个应用程序做了很多绘图,让我们假装它是一个类似Viso的应用程序。 它有一些对象,它们有多个绘制的子对象,可以连接的东西,resize等等。目前,当我在特定的子对象或对象上调用paint时,我会执行以下操作: using(var pen = new Pen(this.ForeColor)) { // Paint for this object. } 我已经阅读了相互矛盾的答案,这应该为一个不断绘制相同内容的应用程序(可能只是resize,移动等)来完成。 我应该将Pen/Brush与对象一起存储,然后在处理应用程序时将它们全部丢弃,或者它们是否足够高效以便为每次绘制调用创建/处理(记住这是一个非常图形密集的应用程序)。 编辑 :已经有两个答案有相互矛盾的答案,这是我不确定要切换的地方。 有没有人对这些差异有任何统计数据?

如何绘制不断变化的图形

之前没有这样做过( 除了在java中 ,看看Steve McLeod是如何修复它的),所以显然我很沮丧。 这里,当前鼠标位置周围的64个像素在表格上绘制得更大。 问题是,它有点’缓慢’,我不知道从哪里开始修复。 除此之外,我制作了一个计时器线程,它在完成后不断调用更新图形,并且像文本一样点fps,以显示绘制事物的速度。 图像示例:(图像来自Microsoft VS2010中“IntelliTrace”中的字母’a’) 来源示例: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace Zoom { public partial class Form1 : Form { static class dllRef { [DllImport(“user32.dll”)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out Point lpPoint); [DllImport(“user32.dll”)] static extern IntPtr […]

如何禁用.NET / GDI +的子采样?

我想使用Bitmap类保存JPEG图像。 我注意到,无论我指定的质量水平如何,锋利的边缘总是blury。 我发现这是由于一个或多个通道的子采样。 保存图像时如何禁用子采样? 我目前正在使用此代码: EncoderParameters parameters = new EncoderParameters(1); parameters.Param[0] = new EncoderParameter(Encoder.Quality, 85L); ImageCodecInfo codec = GetEncoderInfo(“image/jpeg”); image.Save(path, codec, parameters); 注意 我知道JPEG是有损的,但这不是问题。 如果我使用ImageMagick并使用默认选项保存图像,我会得到类似的结果。 但是,如果我指定1:1:1子采样,则模糊消失。 我不想使用PNG,因为我需要更好的压缩。 如果我将图像保存为BMP,然后手动将其转换为JPEG,我会得到很好的结果,而不会模糊。 因此,格式不是这里的问题。

缩短一行像素数

我正在使用.NET GDI +绘制业务对象的自定义图表。 除此之外,该图由连接对象的几行组成。 在特定场景中,我需要将一条线缩短特定数量的像素,比方说10个像素,即找到线的终点之前10个像素的线上的点。 想象一个半径为r = 10像素的圆,以及一条带有起点(x1,y1)和终点(x2,y2)的直线。 圆圈以线的终点为中心,如下图所示。 插图http://sofzh.miximages.com/c%23/140b5w5.gif 如何计算用红色圆圈标记的点,即圆与线之间的交点? 这会给我一个新的终点,缩短10个像素。 解 感谢您的答案,我可以将以下程序放在一起。 我将它命名为LengthenLine,因为如果我想缩短线条,我发现传递负像素数更自然。 具体来说,我试图组合一个可以绘制圆角线的function,可以在这里找到。 public void LengthenLine(PointF startPoint, ref PointF endPoint, float pixelCount) { if (startPoint.Equals(endPoint)) return; // not a line double dx = endPoint.X – startPoint.X; double dy = endPoint.Y – startPoint.Y; if (dx == 0) { // vertical line: if (endPoint.Y […]