【问题标题】:EZAudio iOS - Save Waveform to ImageEZAudio iOS - 将波形保存到图像
【发布时间】:2014-06-13 08:53:41
【问题描述】:

我正在使用适用于 iOS 的 EZAudio 库来处理音频文件的播放并绘制其波形。我想创建一个包含整个波形的视图(EZAudioPlotGL 视图,它是 UIView 的子类),然后将其保存为 png。

我有几个问题:

  1. 我为保存快照图像而创建的临时音频图正在绘制到视图中,我不明白,因为我从未将它添加为子视图。
  2. tempPlot 仅绘制波形的上半部分(不是我在代码中设置的“镜像”)
  3. 从 tempPlot 保存的 UIImage 仅保存波形开头的一小部分。

从这些图片中可以看出问题:

屏幕应该如何处理(原始音频图):

屏幕的外观(显示我不想在屏幕上绘制的 tempPlot):

我得到的保存图像应该是 tempPlot 的副本:

EZAudio 库可以在这里找到:https://github.com/syedhali/EZAudio

我的项目可以在这里找到,如果你想自己看看问题:https://www.dropbox.com/sh/8ilfaofvaa8aq3p/AADU5rOwqzCtEmJz-ePRXIDZa

我对 OpenGL 图形不是很有经验,所以在 EZAudioPlotGL 类中进行的很多工作让我有点头疼。

以下是相关代码:

ViewController.m:

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Customizing the audio plot's look
    self.audioPlot.backgroundColor = [UIColor blueColor];
    self.audioPlot.color           = [UIColor whiteColor];
    self.audioPlot.plotType        = EZPlotTypeBuffer;
    self.audioPlot.shouldFill      = YES;
    self.audioPlot.shouldMirror    = YES;

    // Try opening the sample file
    [self openFileWithFilePathURL:[NSURL fileURLWithPath:kAudioFileDefault]];
}
-(void)openFileWithFilePathURL:(NSURL*)filePathURL {
    self.audioFile = [EZAudioFile audioFileWithURL:filePathURL];

    // Plot the whole waveform
    [self.audioFile getWaveformDataWithCompletionBlock:^(float *waveformData, UInt32 length) {
        [self.audioPlot updateBuffer:waveformData withBufferSize:length];
    }];

    //save whole waveform as image
    [self.audioPlot fullWaveformImageForSender:self];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"waveformImage.png"];
    [UIImagePNGRepresentation(self.snapshotImage) writeToFile:filePath atomically:YES];
}
@end

我的 EZAudioPlotGL 类别:

- (void)fullWaveformImageForSender:(ViewController *)sender{
    EZAudioPlotGL *tempPlot = [[EZAudioPlotGL alloc]initWithFrame:self.frame];

    [tempPlot setPlotType:        EZPlotTypeBuffer];
    [tempPlot setShouldFill:      YES];
    [tempPlot setShouldMirror:    YES];
    [tempPlot setBackgroundColor: [UIColor redColor]];
    [tempPlot setColor:           [UIColor greenColor]];

    //plot full waveform on tempPlot
    [sender.audioFile getWaveformDataWithCompletionBlock:^(float *waveformData, UInt32 length) {
        [tempPlot updateBuffer:waveformData withBufferSize:length];

        //tempPlot.glkVC is a getter for the private EZAudioPlotGLKViewController property in tempPlot (added by me in the EZAudioPlotGL class)
        sender.snapshotImage = [((GLKView *)tempPlot.glkVC.view) snapshot];
    }];
}

【问题讨论】:

  • 在“openFileWithFilePathURL”中你应该把你的调用放到completionBlockinside中,因为这个块是在波形数据被读取之后调用的。事实上,您的快照图像会在 audioFile 被完全读取之前写入文件。
  • 这里是它的答案。 stackoverflow.com/questions/29910476/…

标签: ios objective-c cocoa-touch opengl-es glkit


【解决方案1】:

drawViewHierarchyInRect 仅适用于捕获基于 CoreGraphics 的视图绘图。 (CG 绘制发生在 CPU 上并渲染到主内存中的缓冲区中,因此 CG,又名UIGraphics,可以从那里抓取图像。)如果您的视图使用 OpenGL 绘制其内容,它对您没有帮助。 (OpenGL 绘图发生在 GPU 上,因此您需要使用 GL 将像素从 GPU 读回主内存,然后才能使用它们构建图像。)

看起来您的库使用GLKView 的实例进行绘图。 (在源代码中四处寻找,EZAudioPlotGL 使用 EZAudioPlotGLKViewController,它创建了自己的 GLKView。)该类又具有一个 snapshot 方法,该方法完成所有繁重的工作以从 GPU 和将它们放入UIImage

【讨论】:

  • 我根据您的建议编辑了原始帖子中的代码,但现在我遇到了一些新问题,我已经在上面概述了这些问题。感谢您的帮助
  • 我正面临“tempPlot 仅绘制波形的上半部分(不是我在代码中设置的“镜像”)这个问题。你有解决方案吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 2018-06-06
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 2013-12-11
相关资源
最近更新 更多