[关闭]
@Xiaojun-Jin 2015-03-30T02:10:33.000000Z 字数 13560 阅读 2659

ArcSoft常用图片格式和UIImage的转换

iOS UIImage


  1. typedef struct __tag_MBITMAP
  2. {
  3. MDWord dwPixelArrayFormat;
  4. MLong lWidth;
  5. MLong lHeight;
  6. MLong lPitch[MPAF_MAX_PLANES];
  7. MByte *pPlane[MPAF_MAX_PLANES];
  8. }MBITMAP, *LPMBITMAP;

初始化32位的空MBITMAP:

  1. + (MBITMAP *)mallocEmptyMBitmap32WithWidth:(MLong)lWidth height:(MLong)lHeight
  2. {
  3. MBITMAP *pBitmapData = (MBITMAP *)malloc(sizeof(MBITMAP));
  4. if (!pBitmapData) return nil;
  5. memset(pBitmapData, 0, sizeof(MBITMAP));
  6. pBitmapData->dwPixelArrayFormat = DISPLAY32PIXEL;
  7. pBitmapData->lWidth = lWidth;
  8. pBitmapData->lHeight = lHeight;
  9. pBitmapData->lPitch[0] = LINE_BYTES(pBitmapData->lWidth, 32);
  10. pBitmapData->pPlane[0] = (MByte *)malloc(pBitmapData->lPitch[0] * pBitmapData->lHeight);
  11. if (pBitmapData->pPlane[0] == nil)
  12. {
  13. free(pBitmapData); pBitmapData = nil;
  14. }
  15. return pBitmapData;
  16. }

UIImage 转32位 MBITMAP:

  1. + (MRESULT)convertUIImage:(UIImage *)image toMBitmap:(MBITMAP *)pBitmap
  2. {
  3. MRESULT res = MOK; if(!image || !pBitmap) return MERR_INVALID_PARAM;
  4. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  5. CGImageRef imgRef = [image CGImage];
  6. if (CGImageGetWidth(imgRef) != pBitmap->lWidth ||
  7. CGImageGetHeight(imgRef) != pBitmap->lHeight)
  8. {
  9. CGColorSpaceRelease(colorSpace);
  10. return MERR_INVALID_PARAM;
  11. }
  12. CGContextRef context = CGBitmapContextCreate(pBitmap->pPlane[0],
  13. pBitmap->lWidth,
  14. pBitmap->lHeight,
  15. 8,
  16. pBitmap->lPitch[0],
  17. colorSpace,
  18. kCGImageAlphaPremultipliedLast |
  19. kCGBitmapByteOrder32Big);
  20. CGColorSpaceRelease(colorSpace);
  21. colorSpace = nil; if (!context) return MERR_UNKNOWN;
  22. CGRect rect = {{0,0}, {pBitmap->lWidth, pBitmap->lHeight}};
  23. CGContextDrawImage(context, rect, imgRef);
  24. CGContextRelease(context); context = nil;
  25. return res;
  26. }

32位MBITMAP 转 UIImage:

  1. + (UIImage *)convertMBitmap32:(MBITMAP *)bitmap
  2. withOrientation:(UIImageOrientation)orientation
  3. {
  4. CGFloat width = bitmap->lWidth; CGFloat height = bitmap->lHeight;
  5. unsigned char *buffer = bitmap->pPlane[0];
  6. size_t bufferLength = width * height * 4;
  7. CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLength, NULL);
  8. size_t bitsPerComponent = 8;
  9. size_t bitsPerPixel = 32;
  10. size_t bytesPerRow = 4 * width;
  11. CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
  12. if(colorSpaceRef == NULL)
  13. {
  14. CGDataProviderRelease(provider); return nil;
  15. }
  16. CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
  17. CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
  18. CGImageRef iref = CGImageCreate(width,
  19. height,
  20. bitsPerComponent,
  21. bitsPerPixel,
  22. bytesPerRow,
  23. colorSpaceRef,
  24. bitmapInfo,
  25. provider,
  26. NULL,
  27. YES,
  28. renderingIntent);
  29. uint32_t* pixels = (uint32_t*)malloc(bufferLength);
  30. if(pixels == NULL)
  31. {
  32. CGDataProviderRelease(provider);
  33. CGColorSpaceRelease(colorSpaceRef);
  34. CGImageRelease(iref); return nil;
  35. }
  36. CGContextRef context = CGBitmapContextCreate(pixels,
  37. width,
  38. height,
  39. bitsPerComponent,
  40. bytesPerRow,
  41. colorSpaceRef,
  42. kCGImageAlphaPremultipliedLast |
  43. kCGBitmapByteOrder32Big);
  44. if(context == NULL)
  45. {
  46. NSLog(@"Error context not created"); // free(pixels);
  47. }
  48. UIImage *image = nil;
  49. if(context)
  50. {
  51. CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), iref);
  52. CGImageRef imageRef = CGBitmapContextCreateImage(context);
  53. // Support both iPad 3.2 and iPhone 4 Retina displays with the correct scale
  54. if([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)])
  55. {
  56. image = [UIImage imageWithCGImage:imageRef
  57. scale:1.f
  58. orientation:UIImageOrientationUp];
  59. }
  60. else
  61. {
  62. image = [UIImage imageWithCGImage:imageRef];
  63. }
  64. CGImageRelease(imageRef); CGContextRelease(context);
  65. }
  66. CGColorSpaceRelease(colorSpaceRef);
  67. CGImageRelease(iref);
  68. CGDataProviderRelease(provider);
  69. if(pixels) free(pixels); return image;
  70. }

释放MBITMAP:

  1. + (void)releaseBitmap:(MBITMAP *)bitmap
  2. {
  3. if (bitmap)
  4. {
  5. if (bitmap->pPlane[0])
  6. {
  7. free(bitmap->pPlane[0]);
  8. bitmap->pPlane[0] = nil;
  9. free(bitmap);
  10. bitmap = nil;
  11. }
  12. }
  13. }

UIImage 转24位 MBITMAP:

  1. - (unsigned char *)bitmap24FromUIImage:(UIImage *)image
  2. {
  3. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  4. if (colorSpace == NULL) return NULL;
  5. void *bitmapData = malloc(image.size.width * image.size.height * 4);
  6. if (bitmapData == NULL)
  7. {
  8. CGColorSpaceRelease(colorSpace); return NULL;
  9. }
  10. CGContextRef context = CGBitmapContextCreate (bitmapData,
  11. image.size.width,
  12. image.size.height,
  13. 8,
  14. image.size.width * 4,
  15. colorSpace,
  16. kCGImageAlphaPremultipliedFirst);
  17. CGColorSpaceRelease(colorSpace );
  18. if (context == NULL)
  19. {
  20. free (bitmapData); return NULL;
  21. }
  22. CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
  23. CGContextDrawImage(context, rect, image.CGImage);
  24. unsigned char *data = CGBitmapContextGetData (context);
  25. CGContextRelease(context);
  26. long lWidth = image.size.width; long lHeight = image.size.height;
  27. unsigned char *pRstData = MNull; pRstData = malloc(lWidth * lHeight * 3);
  28. for (int j=0; j<lHeight; j++)
  29. {
  30. for (int i=0; i<lWidth; i++)
  31. {
  32. *(pRstData + j*3*lWidth+i*3) = *(data + j*4*lWidth+i*4+3);
  33. *(pRstData + j*3*lWidth+i*3+1) = *(data + j*4*lWidth+i*4+2);
  34. *(pRstData + j*3*lWidth+i*3+2) = *(data + j*4*lWidth+i*4+1);
  35. }
  36. }
  37. if (data) { free(data); data = NULL; }
  38. return pRstData;
  39. }

转换示例代码:

  1. // create
  2. MBITMAP offImageOri = {0};
  3. unsigned char *pImgData = [self bitmap24FromUIImage:newImage];
  4. long lWidth = newImage.size.width; long lHeight = newImage.size.height;
  5. offImageOri.dwPixelArrayFormat = MPAF_RGB24_B8G8R8;
  6. offImageOri.lWidth = lWidth;
  7. offImageOri.lHeight = lHeight;
  8. offImageOri.lPitch[0] = lWidth*3;
  9. offImageOri.pPlane[0] = pImgData;
  10. // release
  11. if (offImageOri.pPlane[0]) free(offImageOri.pPlane[0]);

24位 MBITMAP 转 UIImage:

  1. - (UIImage *)createUIImageFrom24MBitmap:(MBITMAP)offImageRst
  2. {
  3. unsigned char *pRstData = NULL; pRstData = malloc(lWidth * lHeight * 4);
  4. for (int j=0; j<lHeight; j++)
  5. {
  6. for (int i=0; i<lWidth; i++)
  7. {
  8. *(pRstData + j*4*lWidth+i*4) = 255;
  9. *(pRstData + j*4*lWidth+i*4+1) = *(offImageRst.pPlane[0] + j*3*lWidth+i*3+2);
  10. *(pRstData + j*4*lWidth+i*4+2) = *(offImageRst.pPlane[0] + j*3*lWidth+i*3+1);
  11. *(pRstData + j*4*lWidth+i*4+3) = *(offImageRst.pPlane[0] + j*3*lWidth+i*3+0);
  12. }
  13. }
  14. UIImage *resultImage = [self imageWithBits:pRstData
  15. withSize:CGSizeMake(offImageRst.lWidth,
  16. offImageRst.lHeight)];
  17. return resultImage;
  18. }
  19. - (UIImage *)imageWithBits:(unsigned char *)bits withSize:(CGSize)size
  20. {
  21. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  22. if (colorSpace == NULL) free(bits); return nil;
  23. CGContextRef context = CGBitmapContextCreate (bits,
  24. size.width,
  25. size.height,
  26. 8,
  27. size.width * 4,
  28. colorSpace,
  29. kCGImageAlphaPremultipliedFirst);
  30. if (context == NULL)
  31. {
  32. free (bits); CGColorSpaceRelease(colorSpace ); return nil;
  33. }
  34. CGColorSpaceRelease(colorSpace );
  35. CGImageRef ref = CGBitmapContextCreateImage(context);
  36. free(CGBitmapContextGetData(context));
  37. CGContextRelease(context);
  38. UIImage *img = [UIImage imageWithCGImage:ref];
  39. CFRelease(ref); return img;
  40. }

  1. typedef struct __tag_ASVL_OFFSCREEN
  2. {
  3. MUInt32 u32PixelArrayFormat;
  4. MInt32 i32Width;
  5. MInt32 i32Height;
  6. MUInt8* ppu8Plane[4];
  7. MInt32 pi32Pitch[4];
  8. }ASVLOFFSCREEN, *LPASVLOFFSCREEN;

UIImage 转 ASVL_OFFSCREEN (RGB):

  1. - (unsigned char *)createASVLImageFromUIImage:(UIImage *)image
  2. {
  3. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  4. if (colorSpace == NULL) return NULL;
  5. void *bitmapData = malloc(image.size.width * image.size.height * 4);
  6. if (bitmapData == NULL)
  7. {
  8. CGColorSpaceRelease(colorSpace); return NULL;
  9. }
  10. CGContextRef context = CGBitmapContextCreate (bitmapData,
  11. image.size.width,
  12. image.size.height,
  13. 8,
  14. image.size.width * 4,
  15. colorSpace,
  16. kCGImageAlphaPremultipliedFirst);
  17. CGColorSpaceRelease(colorSpace );
  18. if (context == NULL)
  19. {
  20. free (bitmapData); return NULL;
  21. }
  22. CGRect rect = CGRectMake(0.0f, 0.0f, image.size.width, image.size.height);
  23. CGContextDrawImage(context, rect, image.CGImage);
  24. unsigned char *data = CGBitmapContextGetData (context);
  25. CGContextRelease(context); return data;
  26. }

转换示例代码:

  1. unsigned char *pImgData = [self createASVLImageFromUIImage:newImage];
  2. long lWidth = newImage.size.width; long lHeight = newImage.size.height;
  3. ASVLOFFSCREEN m_offscreenOri;
  4. m_offscreenOri.u32PixelArrayFormat = ASVL_PAF_RGB32_A8R8G8B8;
  5. m_offscreenOri.i32Width = lWidth;
  6. m_offscreenOri.i32Height = lHeight;
  7. m_offscreenOri.pi32Pitch[0] = lWidth*4;
  8. m_offscreenOri.ppu8Plane[0] = pImgData;

ASVL_OFFSCREEN (YUV) 转 UIImage:

  1. - (UIImage *)convertASVLImageToUIImage:(ASVLOFFSCREEN *)pImg
  2. {
  3. CVPixelBufferRef pBuffer;
  4. int bufferWidth = pImg->i32Width;
  5. int bufferHeight = pImg->i32Height;
  6. OSType pixelFormatType = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
  7. NSDictionary *mAttrs = [NSDictionary dictionaryWithObject:[NSDictionary dictionary]
  8. forKey:(id)kCVPixelBufferIOSurfacePropertiesKey];
  9. CVPixelBufferCreate(kCFAllocatorDefault,
  10. bufferWidth,
  11. bufferHeight,
  12. pixelFormatType,
  13. (CFDictionaryRef)mAttrs,
  14. &pBuffer);
  15. CVPixelBufferLockBaseAddress(pBuffer,0);
  16. UInt8 *pPlanY = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(pBuffer, 0);
  17. UInt8 *pPlanUV = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(pBuffer, 1);
  18. // Taking 4 bytes alignment into consideration, do not use bufferWdith drectly
  19. size_t rowBytesY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
  20. size_t rowBytesUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
  21. for (int i = 0; i < pImg->i32Height; ++i)
  22. {
  23. memcpy(pPlanY + i*rowBytesY, pImg->ppu8Plane[0]+ i*pImg->pi32Pitch[0], pImg->i32Width);
  24. }
  25. for (int i = 0; i < pImg->i32Height/2; ++i)
  26. {
  27. memcpy(pPlanUV + i*rowBytesUV, pImg->ppu8Plane[1]+i*pImg->pi32Pitch[1], pImg->i32Width);
  28. }
  29. CVPixelBufferUnlockBaseAddress(pBuffer,0);
  30. CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pBuffer];
  31. CIContext *context = [CIContext contextWithOptions:nil];
  32. CGImageRef myImage = [context createCGImage:ciImage
  33. fromRect:CGRectMake(0, 0,
  34. CVPixelBufferGetWidth(pBuffer),
  35. CVPixelBufferGetHeight(pBuffer))];
  36. UIImage *nImage = [UIImage imageWithCGImage:myImage];
  37. CGImageRelease(myImage); CVPixelBufferRelease(pBuffer);
  38. return nImage;
  39. }

CIContext 对渲染图片的大小有限制, 可以用inputImageMaximumSize和outputImageMaximumSize查看最大值(4096*4096)

CVPixelBuffer 转 ASVL_OFFSCREEN (YUV):

  1. - (void)createASVLImageFromCVPixelBufferRef:(CVPixelBufferRef)pixelBuffer
  2. {
  3. int width = CVPixelBufferGetWidth(pixelBuffer);
  4. int height = CVPixelBufferGetHeight(pixelBuffer);
  5. UInt8 *pPlanY = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
  6. size_t nPlanYRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
  7. UInt8 *pPlanUV = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
  8. size_t nPlanUVRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
  9. MRESULT eResult = MOK; ASVLOFFSCREEN fullSrcImage;
  10. memset(&fullSrcImage, 0, sizeof(ASVLOFFSCREEN));
  11. fullSrcImage.i32Width =width;
  12. fullSrcImage.i32Height =height;
  13. fullSrcImage.u32PixelArrayFormat =ASVL_PAF_NV12;
  14. fullSrcImage.pi32Pitch[0] =nPlanYRow;
  15. fullSrcImage.ppu8Plane[0] =pPlanY;
  16. fullSrcImage.pi32Pitch[1] =nPlanUVRow;
  17. fullSrcImage.ppu8Plane[1] =pPlanUV;
  18. }

ASVL_OFFSCREEN (YUV) 转 UIImage (RGB):

  1. - (UIImage *)imageFromASVLImage:(ASVLOFFSCREEN *)pImg
  2. {
  3. uint8_t *rgbBuffer = malloc(pImg->i32Height * pImg->i32Width * 4);
  4. uint8_t *yBuffer = pImg->ppu8Plane[0];
  5. uint8_t *cbCrBuffer = pImg->ppu8Plane[1];
  6. for(int y = 0; y < pImg->i32Height; y++)
  7. {
  8. uint8_t *rgbBufferLine = &rgbBuffer[y * pImg->i32Width * 4];
  9. uint8_t *yBufferLine = &yBuffer[y * pImg->pi32Pitch[0]];
  10. uint8_t *cbCrBufferLine = &cbCrBuffer[(y >> 1) * pImg->pi32Pitch[1]];
  11. for(int x = 0; x < pImg->i32Width; x++)
  12. {
  13. uint8_t y = yBufferLine[x];
  14. uint8_t cb = cbCrBufferLine[x & ~1];
  15. uint8_t cr = cbCrBufferLine[x | 1];
  16. uint8_t *rgbOutput = &rgbBufferLine[x*4];
  17. int r, g, b;
  18. r = y + 1.4075 *(cr-128);
  19. g = y - 0.3455 *(cb -128)-0.7169 *(cr-128);
  20. b = y + 1.779 *(cb - 128);
  21. r = r<0?0:r; r = r>255?255:r;
  22. g = g<0?0:g; g = g>255?255:g;
  23. b = b<0?0:b; b = b>255?255:b;
  24. rgbOutput[0] = r;
  25. rgbOutput[1] = g;
  26. rgbOutput[2] = b;
  27. rgbOutput[3] = 255;
  28. }
  29. }
  30. // Create a device-dependent RGB color space
  31. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  32. if (!colorSpace) NSLog(@"CGColorSpaceCreateDeviceRGB failure");
  33. CGContextRef context = CGBitmapContextCreate(rgbBuffer,
  34. pImg->i32Width,
  35. pImg->i32Height,
  36. 8,
  37. pImg->i32Width*4,
  38. colorSpace,
  39. kCGBitmapByteOrder32Big |
  40. kCGImageAlphaPremultipliedLast);
  41. CGImageRef cgiMage = CGBitmapContextCreateImage(context);
  42. CGColorSpaceRelease(colorSpace); free(rgbBuffer); CGContextRelease(context);
  43. UIImage *img = [UIImage imageWithCGImage:cgiMage];
  44. CFRelease(cgiMage); return img;
  45. }

CVPixelBuffer 转 UIImage:

  1. - (UIImage *)imageFromCMSampleBuffer:(CMSampleBufferRef)sampleBufferRef
  2. {
  3. CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBufferRef);
  4. CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
  5. CIContext *context = [CIContext contextWithOptions:nil];
  6. CGImageRef myImage = [context createCGImage:ciImage
  7. fromRect:CGRectMake(0, 0,
  8. CVPixelBufferGetWidth(pixelBuffer),
  9. CVPixelBufferGetHeight(pixelBuffer))];
  10. UIImage *uiImage = [UIImage imageWithCGImage:myImage];
  11. return uiImage;
  12. }

Resize SampleBuffer:

  1. void resizeSampleBuffer(CVPixelBufferRef cameraFrame,
  2. CGSize finalSize,
  3. CMSampleBufferRef *sampleBuffer)
  4. {
  5. // CVPixelBufferCreateWithPlanarBytes for YUV input
  6. CGSize originalSize = CGSizeMake(CVPixelBufferGetWidth(cameraFrame),
  7. CVPixelBufferGetHeight(cameraFrame));
  8. CVPixelBufferLockBaseAddress(cameraFrame, 0);
  9. GLubyte *sourceImageBytes = CVPixelBufferGetBaseAddress(cameraFrame);
  10. CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, sourceImageBytes,
  11. CVPixelBufferGetBytesPerRow(cameraFrame) * originalSize.height, NULL);
  12. CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
  13. CGImageRef cgImageFromBytes = CGImageCreate((int)originalSize.width,
  14. (int)originalSize.height,
  15. 8,
  16. 32,
  17. CVPixelBufferGetBytesPerRow(cameraFrame),
  18. genericRGBColorspace,
  19. kCGBitmapByteOrder32Little |
  20. kCGImageAlphaPremultipliedFirst,
  21. dataProvider,
  22. NULL,
  23. NO,
  24. kCGRenderingIntentDefault);
  25. GLubyte *imageData = (GLubyte *) calloc(1, (int)finalSize.width * (int)finalSize.height * 4);
  26. CGContextRef imageContext = CGBitmapContextCreate(imageData,
  27. (int)finalSize.width,
  28. (int)finalSize.height,
  29. 8,
  30. (int)finalSize.width * 4,
  31. genericRGBColorspace,
  32. kCGBitmapByteOrder32Little |
  33. kCGImageAlphaPremultipliedFirst);
  34. CGContextDrawImage(imageContext,
  35. CGRectMake(0.0, 0.0, finalSize.width, finalSize.height),
  36. cgImageFromBytes);
  37. CGImageRelease(cgImageFromBytes);
  38. CGContextRelease(imageContext);
  39. CGColorSpaceRelease(genericRGBColorspace);
  40. CGDataProviderRelease(dataProvider);
  41. CVPixelBufferRef pixel_buffer = NULL;
  42. CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
  43. finalSize.width,
  44. finalSize.height,
  45. kCVPixelFormatType_32BGRA,
  46. imageData,
  47. finalSize.width * 4,
  48. stillImageDataReleaseCallback, NULL, NULL, &pixel_buffer);
  49. CMVideoFormatDescriptionRef videoInfo = NULL;
  50. CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixel_buffer, &videoInfo);
  51. CMTime frameTime = CMTimeMake(1, 30);
  52. CMSampleTimingInfo timing = {frameTime, frameTime, kCMTimeInvalid};
  53. CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault,
  54. pixel_buffer,
  55. YES,
  56. NULL,
  57. NULL,
  58. videoInfo,
  59. &timing,
  60. sampleBuffer);
  61. CVPixelBufferUnlockBaseAddress(cameraFrame, 0);
  62. CFRelease(videoInfo);
  63. CVPixelBufferRelease(pixel_buffer);
  64. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注