代码之家  ›  专栏  ›  技术社区  ›  AlwaysLearningNewStuff

在按钮背景上拉伸/收缩时,位图会失去质量

  •  4
  • AlwaysLearningNewStuff  · 技术社区  · 11 年前

    简介及相关信息:

    我有一个所有者绘制的静态控件。

    它应该在渐变背景的顶部有位图。

    静态控件尺寸 不是固定的 ,它们是在创建父窗口的过程中计算的。

    我从资源文件中加载了一个背景色为RGB(25516394)的位图。

    使用 TransparentBlt( ... , RGB( 255, 163, 94 ) ) API I拉伸/收缩位图以适应静态控件客户端区域(如果重要的话,位图是设备相关位图,而不是DIB)。

    位图图片具有150 DPI的水平和垂直分辨率、24色位深度、4395像素的宽度和5613像素的高度。

    位图通过加载 LoadBitmap( ... ) API打开 WM_CREATE .

    原始图片如下,但我已经缩小了尺寸,所以我可以上传:

    enter image description here

    问题是:

    问题出在图片的质量上。

    波纹管是业主绘制静态控制后我得到的结果:

    enter image description here

    这个 像素化 显而易见。

    纵横比也会丢失,因为我使用 TransparentBlt() .

    我为解决这个问题所做的努力:

    浏览SO档案,我发现了类似的问题,但它们与Android有关。他们都没有帮助我。也许我的经验不足使我无法看到有用的信息。

    根据这些问题中的一个链接,我了解到了图像缩放算法的存在。这是我脑海中的页面: http://en.wikipedia.org/wiki/Resampling_%28bitmap%29

    我试着使用较小的位图,但图片很模糊,尽管我解决了 像素化 在某种程度上。

    似乎我的问题在于位图中的数据不足或过多,所以当我试图将大位图“推”到小按钮中时,它无法容纳,所以我得到 像素化 参差不齐的 效果,但如果我试图将小位图放入大按钮中,则数据丢失,导致图片模糊。

    在浏览互联网后,我看到了一些建议和建议,可以用矢量图形和元文件来解决这个问题。

    既然我被这件事惊呆了,我会问几个问题。

    如果主题很宽泛,我会要求社区通过评论告知我,我会删除它,并尝试重新措辞,以更好地符合SO发布问题的规则。

    问题:

    这个问题的发生出乎我的意料,所以我不知道如何开始解决它,因为我对WIN32还很陌生。

    我必须承认我很震惊,因为我早就预料到了 透明Blt() 会为我做所有的工作。

    我该如何解决这个问题,以便保持图片的纵横比和质量?

    我将考虑以下解决方案:

    1. 将某些GDI API调用组合到我现有的处理程序中进行拉伸/收缩,这样我就可以实现高质量并保持图片的纵横比,而无需过多修改代码?

    2. 使用GDI+来解决我的问题。到目前为止,我还没有使用GDI+,但有一天必须开始,为什么不现在开始,如果这能解决我的问题的话?

    3. 如果矢量图形可以解决我的问题,我必须敦促社区帮我以下忙:任何关于PURE WIN32中矢量图形的书籍/教程/文档/文章/代码示例的推荐都将不胜感激,因为我自己还没有找到。

    4. 如果我必须实现其中一种缩放算法,请推荐一些书籍/教程/链接/代码示例,因为我自己还没有找到。

    我不能使用图书馆,这是对我的限制 但是,如果解决方案是可接受的 并且可以快速实现 ,我可以试着说服我的雇主放宽他们的标准,这样图书馆就可以使用了。

    如果我的标准要保留 二者都 图片的纵横比和质量太高了,我会选择 图片的质量 然后我总是可以发布一个关于纵横比的新问题,也许我会在这期间自己找到解决方案。

    仅此而已。谢谢你的耐心和时间。

    当做

    2 回复  |  直到 11 年前
        1
  •  3
  •   digory doo    11 年前

    由于目标大小小于图像的原始大小,GDI只会漏掉某些像素。这是有效的,但结果往往质量很差。要做得更好,您需要启用抗锯齿。启用抗锯齿后,过多的像素不仅会被丢弃,还会与相邻像素合并(平均)在一起。

    在GDI中,你基本上必须调用

    SetStretchBltMode (HALFTONE);
    

    然后调用StretchBlt/TransparentBlt以实现抗锯齿效果。

    编辑:我想我记得TransparentBlt忽略了StretchBltMode。如果这是真的,你将不得不在没有透明度的情况下行事。可能的解决方案:创建一个与原始图像一样大的内存DC,绘制背景,使用TransparentBlt在顶部渲染图像。稍后,使用StretchBlt将图像从mem DC绘制到屏幕。

        2
  •  1
  •   AlwaysLearningNewStuff    10 年前

    我已经和这个问题“斗争”了将近三个月,经过这么多研究,我必须承认 Passant先生 是正确的,像上面这样的清晰图像在缩放时只会失去质量。

    因此,我决定使用矢量图形。

    也许我会用 Enhanced Windows Metafile s或将尝试使用的某些库 SVG .

    我在此感谢所有尽力提供帮助的人。

    顺致敬意,