簡體   English   中英

從UIImages創建mov時的iOS綠色邊框

[英]iOS green border when creating mov from UIImages

我正在使用下面的代碼來獲取一系列UIImage並將其轉換為mov。 由於某種原因,我總是在底部或右側獲得綠色邊框,具體取決於它是風景照片還是肖像照片。 圖片為215x320。

如何刪除綠色邊框? 有沒有更好的方法來從UIImages創建.mov?

- (void)createMov
{
  UIImage *first = [self.videoFrames objectAtIndex:0];

  CGSize frameSize = first.size;

  NSError *error = nil;
  AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:
                                [NSURL fileURLWithPath:fileName] fileType:AVFileTypeQuickTimeMovie
                                                        error:&error];

  if (error) {
    NSLog(@"error creating AssetWriter: %@",[error description]);
  }

  int numPixels = first.size.width * first.size.height;
  int bitsPerSecond = numPixels * 11.04;


  NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                 AVVideoCodecH264, AVVideoCodecKey,
                                 [NSNumber numberWithInt:frameSize.width], AVVideoWidthKey,
                                 [NSNumber numberWithInt:frameSize.height], AVVideoHeightKey,
                                 [NSDictionary dictionaryWithObjectsAndKeys:
                                  [NSNumber numberWithInteger:bitsPerSecond], AVVideoAverageBitRateKey,
                                  [NSNumber numberWithInteger:30], AVVideoMaxKeyFrameIntervalKey,
                                  nil], AVVideoCompressionPropertiesKey,
                                 nil];

  AVAssetWriterInput* writerInput = [[AVAssetWriterInput
                                      assetWriterInputWithMediaType:AVMediaTypeVideo
                                      outputSettings:videoSettings] retain];

  NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
  [attributes setObject:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB] forKey:   (NSString*)kCVPixelBufferPixelFormatTypeKey];
  [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.width] forKey:(NSString*)kCVPixelBufferWidthKey];
  [attributes setObject:[NSNumber numberWithUnsignedInt:frameSize.height] forKey:(NSString*)kCVPixelBufferHeightKey];

  AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
                                              assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
                                               sourcePixelBufferAttributes:attributes];

  [videoWriter addInput:writerInput];

  // fixes all errors
  writerInput.expectsMediaDataInRealTime = YES;

  //Start a session:
  BOOL start = [videoWriter startWriting];
  NSLog(@"Session started? %d", start);
  [videoWriter startSessionAtSourceTime:kCMTimeZero];


  // Writing.
  CVPixelBufferRef buffer = NULL;
  buffer = [self pixelBufferFromCGImage:[first CGImage]];
  BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:kCMTimeZero];

  if (result == NO) //failes on 3GS, but works on iphone 4
    NSLog(@"failed to append buffer");

  if(buffer)
    CVBufferRelease(buffer);

  [NSThread sleepForTimeInterval:0.05];

  int fps = [Utils frameRate];

  int i = 0;
  for (UIImage *imgFrame in self.videoFrames) {
    i = [self addFrame:adaptor videoWriter:videoWriter buffer:buffer imgFrame:imgFrame i:i fps:fps];
  }

  //Finish the session:
  [writerInput markAsFinished];
  [videoWriter finishWriting];
  CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
  [videoWriter release];
  [writerInput release];
}


- (int)addFrame:(AVAssetWriterInputPixelBufferAdaptor *)adaptor videoWriter:(AVAssetWriter *)videoWriter buffer:(CVPixelBufferRef)buffer imgFrame:(UIImage *)imgFrame i:(int)i fps:    (float)fps
{
  if (adaptor.assetWriterInput.readyForMoreMediaData) {

    i++;
    NSLog(@"inside for loop %d",i);
    CMTime frameTime = CMTimeMake(1, fps);
    CMTime lastTime=CMTimeMake(i, fps);
    CMTime presentTime=CMTimeAdd(lastTime, frameTime);

    buffer = [self pixelBufferFromCGImage:[imgFrame CGImage]];
    BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime];

    if (result == NO) { //fails on 3GS, but works on iphone 4
      NSLog(@"failed to append buffer");
      NSLog(@"The error is %@", [videoWriter error]);
    }

    if (buffer) {
      CVBufferRelease(buffer);
    }

    [NSThread sleepForTimeInterval:0.05];
  } else {
    NSLog(@"error");
    i--;
  }
  [NSThread sleepForTimeInterval:0.02];

  return i;
}


- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                           [NSNumber numberWithBool:YES],     kCVPixelBufferCGImageCompatibilityKey,
                           [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                           nil];
  CVPixelBufferRef pxbuffer = NULL;

  CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image),
                      CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,
                  &pxbuffer);

  CVPixelBufferLockBaseAddress(pxbuffer, 0);
  void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
  size_t rowBytes = CVPixelBufferGetBytesPerRow(pxbuffer);


  CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
  CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image),
                                           CGImageGetHeight(image), 8, rowBytes, rgbColorSpace,
                                           kCGImageAlphaNoneSkipFirst);

  CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));


  CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                     CGImageGetHeight(image)), image);
  CGColorSpaceRelease(rgbColorSpace);
  CGContextRelease(context);

  CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

  return pxbuffer;
}

看來我遇到了類似的問題,在閱讀了以下兩篇文章后,我的腦海有了一個想法。

http://forum.videohelp.com/threads/314973-green-line-at-bottom-of-video-window

http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#功能

NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                       AVVideoCodecH264, AVVideoCodecKey,
                                       [NSNumber numberWithUnsignedLong:sourceWidth], AVVideoWidthKey,
                                       [NSNumber numberWithUnsignedLong:sourceHeight], AVVideoHeightKey,
                                       nil];
AVAssetWriterInput *writerInput =
        [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];

在開始通過AVAssertWriter寫入數據之前,請使用以下方法重置sourceWidthsourceHeight

size_t fixedLineValue(size_t sourceValue){
    size_t divide = sourceValue%4;
    size_t finalValue = sourceValue;
    if (divide) {
        finalValue=(sourceValue/4+1)*4;
    }
    return finalValue;
}   

我不能清楚地指出為什么這樣做,但是在那之后,丑陋的綠色邊框被刪除了。 如果有更好的答案,請發表評論,讓我們知道。 謝謝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM