简体   繁体   中英

EZAudio iOS - Save Waveform to Image

I'm using the EZAudio library for iOS to handle the playback of an audio file and draw its waveform. I'd like to create aa view with the entire waveform (an EZAudioPlotGL view, which is a subclass of UIView) and then save it as a png.

I'm having a couple problems with this:

  1. The temporary audio plot I'm creating to save the snapshot image is drawing to the view, which I don't understand because I never add it as a subview.
  2. The tempPlot is only drawing the top half of the waveform (not "mirrored" as I set it in the code)
  3. The UIImage being saved from the tempPlot is only saving a short portion of the beginning of the waveform.

The problems can be seen in these images:

How the screen should look after (the original audio plot): 在此处输入图片说明

How the screen does look (showing the tempPlot I don't want to draw to the screen): 在此处输入图片说明

The saved image I get out that should be a copy of tempPlot: 在此处输入图片说明

The EZAudio library can be found here: https://github.com/syedhali/EZAudio

And my project can be found here, if you want to see the problem for yourself: https://www.dropbox.com/sh/8ilfaofvaa8aq3p/AADU5rOwqzCtEmJz-ePRXIDZa

I'm not very experienced with OpenGL graphics, so a lot of the work going on inside the EZAudioPlotGL class is a bit over my head.

Here's the relevant code:

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

My Category of 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];
    }];
}

drawViewHierarchyInRect only works for capturing CoreGraphics-based view drawing. (CG drawing happens on the CPU and renders into a buffer in main memory, so CG, aka UIGraphics , can just slurp an image out of there.) It won't help you if your view draws its content using OpenGL. (OpenGL drawing happens on the GPU, so you need to use GL to read pixels back from the GPU to main memory before you can build an image out of them.)

It looks like your library does its drawing with an instance of GLKView . (Poking around in the source, EZAudioPlotGL uses EZAudioPlotGLKViewController , which creates its own GLKView .) That class, in turn, has a snapshot method that does all the heavy lifting to get pixels back from the GPU and put them in a UIImage .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM