stretchblt为啥会造成图片失真

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stretchblt为啥会造成图片失真相关的知识,希望对你有一定的参考价值。

我用stretchblt缩小图片,结果发现图片上有麻点、网格等,色彩也变了。这是怎么回事

VC 下 StretchBlt 的模式及失真问题
用一个CCD的相机,采集图像,然后在对话框的图片控件中显示。
现象:原本应该是黑白相机的灰度图像,显示出来的却是花花绿绿的彩色图像。

开始的时候
怀疑是采集的数据有问题,可是查看保存下来的bmp文件,却正常的很。可以确定是显示程序的
问题。问题是,基本上是按照sdk的sample逐行抄的,唯一的一点区别就是,sdk是在一个单
文档的view中显示,我的程序是在对话框的图片控件中显示,最有可能出错的就是
StretchDIBits(pDC->GetSafeHdc(),
rect.left,
rect.top,
rect.Width(), //显示窗口宽度
rect.Height(), //显示窗口高度
0,
0,
Width, //图像宽度
Height, //图像高度
m_pImageBuffer, //图像缓冲区
m_pBmpInfo, //BMP图像描述信息
DIB_RGB_COLORS,
SRCCOPY
);

认真地检查了所有的参数,没有发现异常。
跑到baidu和google上疯狂地搜,又重新建立了一个对话框工程,load一个图片来显示,问题
重现,偶然看到 http://hi.baidu.com/68400165/blog/item/fa2409c66ab7e2dbd000601a.html里面
提到StretchDIBits引起的失真问题,
遂增加pDC-> SetStretchBltMode(HALFTONE);
问题解决!

附上网文:
 在 VC 中使用 StretchBlt 会碰到一些与点阵图大小缩放相关的一些问题。在扩展一个点阵图时,StretchBlt必须复制图素行或列。如果放大倍数不是原图的整数倍,那么此操作会造成产生的图像有些失真。
  如果目的矩形比来源矩形小,那么StretchBlt在缩小图像时就必须把两行(或列)或者多 行(或列)的图素合并到一行(或列)。完成此操作有四种方法,它根据装置内容伸展模式属性来选择其中一种方法。您可使用 SetStretchBltMode 函数来修改这个属性。
SetStretchBltMode (hdc, iMode) ;
iMode 可取下列值:
BLACKONWHITE 或者 STRETCH_ANDSCANS(内定):如果两个或多个图素得合并成一个图素,那么StretchBlt会对图素执行一个逻辑AND运算。这样的结果是只有全部的原始图素是白色时该图素才为白 色,其实际意义是黑色图素控制了白色图素。这适用于白背景中主要是黑色的单色点阵图。
WHITEONBLACK 或 STRETCH_ORSCANS:如果两个或多个图素得合并成一个图素,那么StretchBlt 执行逻辑OR运算。这样的结果是只有全部的原始图素都是黑色时才是黑色,也就是说由白色图 素决定颜色。这适用於黑色背景中主要是白色的单色点阵图。
COLORONCOLOR 或 STRETCH_DELETESCANS:StretchBlt 简单地消除图素行或列,而没有任何逻辑组合。这是通常是处理彩色点阵图的最佳方法。
HALFTONE 或 STRETCH_HALFTONE:Windows根据组合起来的来源颜色来计算目的的平均颜色。这将与半调调色盘联合使用,第十六章将展示这一程序。
利用StretchBlt缩小图片时有时会出现颜色失真。解决步骤如下:
1、先把目标DC (也就是 HDC hDestDC) ::SetStretchBltMode (hDestDC, HALFTONE);
2、调用一下 ::SetBrushOrgEx(hDestDC, 0, 0, NULL);
3、最后调用 CImage 的 StretchBlt
或者这样解决:
1。hbit = (HBITMAP)LoadImage( NULL,cBmpPath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(hbit != NULL)
Bitmap.Attach(hbit);
DCCompatible.CreateCompatibleDC(GetDC());
DCCompatible.SelectObject(&Bitmap);
Bitmap.GetObject(sizeof(bm),&bm);
2。OnPaint():
pDC->SetStretchBltMode(HALFTONE);
pDC->StretchBlt(MAP_LEFT,MAP_TOP,MAP_WIDTH,MAP_HEIGHT,
&DCCompatible,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
参考技术A   对于点阵图,放大缩小失真是理所当然的,要想不失真是不可能的,只能用算法减少失真而已.
  StretchBlt函数缩放图片后图片失真严重,所以要用SetStretchBltMode函数来设置 StretchBlt(或StretchDIBits)函数的伸缩模式。具体用法是
  调用StretchBlt前调用:
  SetStretchBltMode(pDC->m_hDC,STRETCH_HALFTONE);

如何修复 iPhone 应用程序中的多个音频流造成失真?

【中文标题】如何修复 iPhone 应用程序中的多个音频流造成失真?【英文标题】:How can I fix multiple audio streams in an iPhone app from creating distortion? 【发布时间】:2013-05-23 18:36:21 【问题描述】:

我正在使用多个 AVAudioPlayer 实例来播放重叠的声音,因此会产生严重的失真。这是我的情况......我有一个带有几个钢琴键的应用程序。在触摸一个键时,它会播放一个音符。如果我快速连续触摸 6-7 个键,我的应用程序会为每个键播放一个 2 秒的 .mp3 剪辑。由于我使用单独的音频流,它们听起来会重叠(它们应该重叠),但结果是很多失真、爆裂声或嗡嗡声!

如何使重叠的音频清晰干净?我自己录制了钢琴的声音,它们非常好听、干净、无噪音,我不明白为什么重叠的流听起来如此糟糕。即使在低音量或通过耳机时,质量也会非常下降。

欢迎提出任何建议!

【问题讨论】:

【参考方案1】:

几件事:

剪辑

您所描述的“嗡嗡声”几乎可以肯定是削波——将两个或多个波形相加的结果,其峰值被截断的组合波形在同一处被削波。

当您设计带有复音的虚拟合成器时,您必须考虑可能同时播放多少个声音并提供动态余量,通常是通过衰减每个声音。

实际上,您可以使用AVAudioPlayer 实现此目的,方法是将每个实例的volume 属性设置为0.316 以获得10 dB 的动态余量。 (足以同时发出 8 个声音)

这里的一个明显问题是,当用户演奏单个声音时,它可能看起来太安静了——您需要尝试各种动态余量值和典型的用户行为并根据口味进行调整(这也取决于信号。您的钢琴样本根据记录的幅度,可能会比其他波形更容易/更不容易被削波。)

根据您应用的目标用户,您可能会考虑向他们提供此余量参数。

不连续性/性能

您听到的爆裂声和咔哒声可能不是剪辑的结果,而是您使用 mp3 作为音频文件格式这一事实的副作用。这是一个坏主意™。 iOS 设备只有一个硬件立体声 mp3 解码器,因此一旦您启动第二个、第三个等语音,iOS 必须在 cpu 上解码 mp3 音频数据。根据设备的不同,在遇到下溢不连续性之前,您只能以这种方式解码几个音频流(显然,将立体声文件减半)...... CPU 根本无法及时为输出音频流解码足够的样本,所以你会听到讨厌的爆裂声和咔哒声。

对于示例播放,您希望使用 LPCM 音频编码(如 wav 或 aiff)或解码效率极高的东西,如 ima4。在我发布的每个包含这些类型的音频样本的应用程序中,我使用的一个策略是以 mp3 或 aac 格式发布样本,但在应用程序第一次启动时将它们解码为应用程序沙箱中的 LPCM 文件.通过这种方式,您可以在解码样本时受益于较小的应用程序包低 CPU 利用率/运行时更高的复音。 (在用户等待样本解码时,对首次用户体验的影响很小。)

【讨论】:

非常有帮助...感谢您的彻底回复!它确实解决了我的问题。【参考方案2】:

我的理解是 AVAudioPlayer 不适合那样使用。通常,当像这样将大量声音组合成单个输出时,您希望打开单个流并自己混合声音。

【讨论】:

【参考方案3】:

您遇到的是clipping — 这是因为您正在播放的声音的总音量超过了可能的最大音量。当一次播放多个声音时,您需要降低这些声音的音量。

【讨论】:

以上是关于stretchblt为啥会造成图片失真的主要内容,如果未能解决你的问题,请参考以下文章

c++利用StretchBlt函数改变CImage输出图片的位置

c++利用StretchBlt函数改变CImage输出图片的位置

为啥 Android Studio Emulator 会扭曲背景图片

简单的 AudioQueue 正弦波——为啥会失真?

如何修复 iPhone 应用程序中的多个音频流造成失真?

php 合并图片及图片失真的解决办法