问题标签 [stretchblt]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
700 浏览

stretchblt - 使用 StretchBlt() 缩小问题

我有一些代码可以根据源位图绘制我自己的矩形按钮。

大多数时候目标按钮比我的源位图图像大,并且 StretchBlt 工作正常。但是,当目标小于源图像时,StretchBlt 拒绝填充整个目标区域。

我知道 StretchBlt 在缩小图像时的质量不是很好,但我并不太担心。我只是不想丢失像素。

这是顶部的源图像和底部的目标图像的链接:

链接文本 注意,我实际上是将源图像的一部分缩小到目标中。我没有缩小整个图像。因此,例如,我使用 BitBlt() 复制角大小的大小,然后将角之间的水平像素数据从源图像拉伸(挤压)到目标 DC。

我的源坐标和目标坐标没有错。如果我从 SRCCOPY 更改为 WHITENESS,整个区域将如您所料填充为白色。正如您在上面的 Broken.bmp 图像中看到的那样,没有灰色条没有复制像素。

以前有没有人遇到过这个问题,如果有,有人可以提出解决方案吗?

干杯

0 投票
4 回答
1623 浏览

delphi - System.Move 中的内存损坏由于更改了 8087CW 模式 (png + stretchblt)

我有一个奇怪的内存损坏问题。经过几个小时的调试和尝试,我想我找到了一些东西。

例如:我做了一个简单的字符串赋值:

但是,结果有时会变成:

因此,_ 被一个 0 字节替换。

我在 System.Move 函数中看到过这种情况发生过一次(复制很棘手,取决于时间),当时它使用 FPU 堆栈(fild,fistp)进行快速内存复制(如果要移动 9 到 32 个字节):

使用 FPU 视图和 2 个内存调试视图(Delphi -> View -> Debug -> CPU -> Memory)我看到它出错了......曾经......但是无法重现......

今天早上我读到了一些关于 8087CW 模式的内容,是的,如果将其更改为 $27FI,则会导致内存损坏!通常是 $133F:

$133F 和 $027F 之间的区别在于 $027F 将 FPU 设置为执行不太精确的计算(限制为 Double 而不是 Extended)和不同的 infiniti 处理(用于较旧的 FPU,但不再使用)。

好的,现在我找到了原因,但没有找到时间

我通过一个简单的检查改变了我的AsmProfiler的工作(所以在进入和离开时检查所有功能):

我“分析”了一些单元和 dll 和宾果游戏(见堆栈):

所以它发生在 StretchBlt...

现在做什么?是 Windows 的错误,还是 PNG 中的错误(包含在 D2007 中)?或者 System.Move 函数不是故障安全的?

注意:简单地尝试重现是行不通的:

它似乎更具异国情调......但是通过'Get8087CW = $27F'上的debugbreak,我可以在另一个字符串上重现它:FPU part 1: FPU 第 1 部分 FPU part 2: FPU 第 2 部分 FPU part 3: FPU 第 3 部分 FPU Final:损坏!: FPU决赛:腐败!

注意 2:也许 FPU 堆栈必须在 System.Move 中清除?

0 投票
1 回答
2822 浏览

c++ - StretchBlt 和过滤 Alpha 通道

我正在使用 缩小图像StretchBlt()

http://img684.imageshack.us/img684/2152/stretchblt.png

如您所见,目前看来我必须在质量过滤和透明度之间进行选择。有没有办法两者兼得?这是我需要执行的唯一图像操作,所以我宁愿避免使用额外的库。

我的代码:

0 投票
1 回答
1186 浏览

bitmap - 精确映射由 Graphics.DrawImage 缩放的像素

我有一个用于拉伸和绘制位图的 Winforms 应用程序,Graphics.DrawImage我需要帮助来准确理解源像素如何映射到目标。

理想情况下,我想编写一个函数,例如:

它采用源图像上的像素坐标并返回在缩放目标上与其对应的“左上”像素的坐标。

为清楚起见,这是一个简单的示例,其中 2x2 位图缩放为 4x4:

缩放示例

箭头说明了如何将点 (1,0) 输入 MapPixel:

应该给出 (2,0) 的结果。

使用以下逻辑使 MapPixel 适用于上述示例很简单:

但是我注意到这种幼稚的实现会由于舍入dst.Width而不是src.Width. 在这种情况下,DrawImage 需要选择一些像素来绘制比其他像素更大的像素,以使图像适合,我在复制其逻辑时遇到了麻烦。

下面的代码通过将 2x1 位图缩放到几个不同的宽度来演示这个问题:

这是原始src图像和输出dst图像的样子,以及一些显示 MapPixel 需要如何映射蓝色像素的数字:

缩放示例

我一生都无法弄清楚 DrawImage 是如何决定放大哪个像素的。它似乎有时向上取整,有时向下取整。我不在乎它选择哪个,但我需要它是可预测的,我的功能才能正常工作。

我尝试修改上面的 MapPixel 示例以使用MidpointRounding.AwayFromZero,甚至替换Math.Round为四舍五入到最接近的奇数的函数(稍微改善了结果,但仍然不完美)。我还尝试让 Graphics 类处理缩放 - 即我设置ScaleTransform、调用DrawImageUnscaled然后尝试使用它TransformPoints来转换坐标。有趣的是,TransformPoints 方法的结果并不总是与 DrawImage 和 DrawImageUnscaled 所做的一致。

我也尝试挖掘 GDI+ 以获取提示,但还没有发现任何有用的东西。

我不想为了保持对它降落位置的可预测性而不得不单独绘制每个像素。

如果您想知道,我使用的原因InterpolationMode.NearestNeighbor是避免抗锯齿(我需要保持单个像素的保真度),并且PixelOffsetMode.Half包含在内是因为如果它不存在,那么 DrawImage 会将我的位图平移半个像素。

问题点的更多示例包括将 4px 缩放到 13px 时 x=7,以及将 4px 缩放到 17px 时 x=8。

如果需要,我可以发布完整的单元测试代码,允许您插入并验证 MapPixel 函数。到目前为止,我能够达到 100% 准确度的唯一方法是通过一个丑陋的 hack,它生成一个“提示”源图像,其中每个像素都设置为唯一的颜色。它通过检查提示图像中的颜色来映射坐标,然后在提示图像的缩放版本中查找该颜色。优化是可能的(例如,提示图像的宽度或高度为单像素,上面的幼稚逻辑用于猜测近似答案并从那里向外工作),但它仍然很丑陋。

如果有人能阐明 DrawImage 背后的管道并帮助我为 MapPixel 提出一个更简单(但仍然准确)的实现,我将不胜感激。

0 投票
1 回答
335 浏览

.net - StretchBlt 失败

我有一个 COM 组件。此 COM 组件在屏幕上显示图像。图像位通过这样的缓冲区复制:

imagecv::Mat在哪里。在某些条件下,这是一个裁剪的 cv::Mat,即。raw_image(x0, y0, w, h)where的返回raw_image是另一个 cv::Mat。

稍后应用程序调用StretchBlt以显示图像。

如果我在 .NET 应用程序中运行此 COM 组件(并且当在 .NET 应用程序中,这不会在纯非托管环境中发生)调用StretchBlt失败时(再次,仅当)image被裁剪。它不会在未裁剪图像的代码路径上失败。两个代码路径的绘图代码相同。GetLastError()将返回错误 8。

有人可以阐明这个问题吗?

0 投票
2 回答
2244 浏览

c++ - StretchBlt 收缩损坏

我正在使用 Windows(7 和 XP - 均为 32 位)并使用 C++ 进行编码

我从外部源接收位图。这些位图具有固定的分辨率 (384x288)

收到位图后,我需要根据可变大小的布局调整它的大小,因此我目前正在使用 StretchBlt 来执行这些任务。

如果我将位图的大小调整为更大的屏幕图像,则效果很好。

但是,如果我将传入的位图缩小到较小的版本以放置在屏幕上,我会在图像上出现一些奇怪的“装箱”类型效果。

在以下示例中,三个面板中的每一个的源图像都是相同的。但是左边的两个(缩小尺寸)都对它们有装箱/线条效果。

在此处输入图像描述

对于实际的 StretchBlt 调用,我这样做:

但我想知道问题是否出在其他地方。

有没有其他人有过这种调整大小的图像损坏的经验,知道如何修复它?

0 投票
1 回答
2686 浏览

c++ - StretchBlt() 不创建镜像

根据 MSDN:

如果 nWidthSrc 和 nWidthDest 参数的符号或者如果 nHeightSrc 和 nHeightDest 参数不同,则 StretchBlt 会创建位图的镜像。

所以我尝试创建颠倒的图像。我有一个看起来像这样的课程:

我有这个方法:

但它不起作用,什么也没有发生。我想知道这是否与 DC 兼容性有关,我一直无法理解其背后的逻辑。

那么,我应该怎么做才能让我的位图翻转呢?

0 投票
1 回答
380 浏览

visual-c++ - StretchBlt 提供单色位图作为输出

我正在编写用于在 VC++ 中缩小图像的代码。当我保存目标位图时,它会给出单色图像。代码:

如果有人在这里帮助我,我将非常感激。提前致谢

0 投票
1 回答
700 浏览

performance - StretchBlt 太慢了,还是更快?

我正在使用 StretchBlt 绘制调整大小的实时视频。

但是,StretchBlt api 太慢了。每次执行 StretchBlt 在我的计算机上大约需要 100 毫秒。是否有任何其他 API 或任何方法可以提高速度?

0 投票
0 回答
454 浏览

c++ - StretchBlt 仅在 nHeightDest 为负数时有效

我正在尝试使用StretchBlt将像素从内存 hdc 复制到窗口 hdc。
内存 hdc 从一个不可见的窗口获取图像,该窗口使用 openGL 呈现流。

这是我的代码:

windowHdc我想要将像素复制到的窗口的 hdc 在哪里StretchBlt,并且offscreenBuffervoid*从 openGL 正在渲染的屏幕外窗口复制的像素。

这段代码很好用,除了图像是颠倒的,我希望它垂直翻转。
我知道发生这种情况是因为:

如果 nHeightSrc 和 nHeightDest 有不同的符号,该函数创建位图沿 y 轴的镜像

但是当我删除减号并且目标和源高度相同时,我在窗口中看不到任何图像。
只是为了检查,我尝试在 上加上减号,sourceDimensions.height但这也导致没有图像,如果我尝试否定宽度(目标和源),也是如此。

知道为什么吗?
谢谢。