Edited at

iOSで使える色々な画像形式の相互変換

More than 1 year has passed since last update.

2017/02/14「CMSampleBuffer - UIImage」を追記

毎回忘れるのでまとめました。

メモ程度なので何かもっと良い方法あるとかリークするとかあったら教えて下さい。


CMSampleBuffer - UIImage

//CMSampleBufferRefからUIImage

-(UIImage *)imageFromSampleBuffer:(CMSampleBufferRef)sampleBuffer{

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

// ピクセルバッファのベースアドレスをロックする
CVPixelBufferLockBaseAddress(imageBuffer, 0);

// Get information of the image
uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);

// RGBの色空間
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef newContext = CGBitmapContextCreate(baseAddress,
width,
height,
8,
bytesPerRow,
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

CGImageRef cgImage = CGBitmapContextCreateImage(newContext);

CGContextRelease(newContext);
CGColorSpaceRelease(colorSpace);

UIImage *rtnImage = [UIImage imageWithCGImage:cgImage scale:1.0 orientation:UIImageOrientationUp];

CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
CGImageRelease(cgImage);

return rtnImage;
}


UIImage - CGImage


uiimage-cgimage.m

//UIImageからCGImage

CGImageRef cgimage = uiimage.CGImage;

//CGImageからUIImage
UIImage *uiimage = [UIImage imageWithCGImage:cgimage];
CGImageRelease(cgimage);



CIImage - CGImage


uiimage-ciimage.m

//CIImageからCGImage

//[CIContext new]はダメ 2016/06/08更新
CGImageRef cgimage = [[CIContext contextWithOptions:nil] createCGImage:ciimage fromRect:ciimage.extent];

//CGImageからCIImage
CIImage *ciimage = [CIImage imageWithCGImage:cgimage];



vImage - CGImage


vimage-cgimage.m

    /*

* format
*
* typedef struct vImage_CGImageFormat
* {
* uint32_t bitsPerComponent;
* uint32_t bitsPerPixel;
* CGColorSpaceRef colorSpace;
* CGBitmapInfo bitmapInfo;
* uint32_t version;
* const CGFloat * decode;
* CGColorRenderingIntent renderingIntent;
* }vImage_CGImageFormat;

* 例
* ARGB8888 -> {8, 32, NULL, alpha first, 0, NULL, kCGRenderingIntentDefault} alpha first = { kCGImageAlphaFirst, kCGImageAlphaPremultipliedFirst, kCGImageAlphaNoneSkipFirst }
* RGBA8888 -> {8, 32, NULL, alpha last, 0, NULL, kCGRenderingIntentDefault} alpha last = { kCGImageAlphaLast, kCGImageAlphaPremultipliedLast, kCGImageAlphaNoneSkipLast }
* BGRA8888 -> {8, 32, NULL, alpha first | kCGBitmapByteOrder32Little, 0, NULL, kCGRenderingIntentDefault}
* RGB888 -> {8, 24, NULL, kCGImageAlphaNone | kCGBitmapByteOrderDefault, 0, NULL, kCGRenderingIntentDefault}
* RGB565 -> {5, 16, NULL, kCGImageAlphaNone | kCGBitmapByteOrder16Little, 0, NULL, kCGRenderingIntentDefault}
* ARGB1555 -> {5, 16, NULL, alpha first | kCGBitmapByteOrder16Little, 0, NULL, kCGRenderingIntentDefault}
* RGBA16F -> {16, 64, NULL, alpha last | kCGBitmapFloatComponents | kCGBitmapByteOrder16Little, 0, NULL, kCGRenderingIntentDefault }
* CMYK8888 -> {8, 32, CGColorSpaceCreateDeviceCMYK(), kCGImageAlphaNone, 0, NULL, kCGRenderingIntentDefault }
* ARGBFFFF premultiplied -> {32, 128, NULL, kCGImageAlphaPremultipliedFirst | kCGBitmapFloatComponents | kCGBitmapByteOrder32Little, 0, NULL, kCGRenderingIntentDefault }
* ARGBFFFF not-premultiplied -> {32, 128, NULL, kCGImageAlphaFirst | kCGBitmapFloatComponents | kCGBitmapByteOrder32Little, 0, NULL, kCGRenderingIntentDefault }
* ARGBFFFF, alpha = 1 -> {32, 128, NULL, kCGImageAlphaNoneSkipFirst | kCGBitmapFloatComponents | kCGBitmapByteOrder32Little, 0, NULL, kCGRenderingIntentDefault }

* uiimageviewに表示する時用のformat
* vImage_CGImageFormat format = {
* .bitsPerComponent = 8,
* .bitsPerPixel = 32,
* .bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast, //RGBA8888
* }; // .colorspace, .version, .renderingIntent and .decode all initialized to 0 per C rules
*/

//vImageからCGImage
-(CGImageRef)vImageToCGImage:(vImage_Buffer)vimage withFormat:(vImage_CGImageFormat) format{
vImage_Error error;
CGImageRef cgimage = vImageCreateCGImageFromBuffer( &vimage, &format, NULL, NULL, kvImageNoFlags, &error);
if (error != kvImageNoError) {
NSLog(@"[VIImage ERROR][No %d]", (int)error);
}

return cgimage;
}

//CGImageからvImage
-(vImage_Buffer)CGImageToVImage:(CGImageRef)cgimage withFormat:(vImage_CGImageFormat) format{
vImage_Buffer vimage;
vImage_Error error = vImageBuffer_InitWithCGImage( &vimage, &format, NULL, cgimage, kvImageNoFlags );
if (error != kvImageNoError) {
NSLog(@"[VIImage ERROR][No %d]", (int)error);
}

return vimage;
}



GPUImagePicture(GPUImage) - UIImage


gpuimagepicture-uiimage.m

//uiimageからgpuimagepicture

GPUImagePicture *gpuImage = [[GPUImagePicture alloc] initWithImage:uiimage];

//gpuimagepictureからuiimage(GPUImageFilterを通す)
GPUImageFilter *filter = /*GPUImgeFilterを継承しているなにかしら*/
[gpuImage addTarget:filter];
[filter useNextFrameForImageCapture];
[gpuImage processImage];
UIImage *dstuiimage = [filter imageFromCurrentFramebuffer];



cv::Mat(OpenCV) - UIImage


cvmat-uiimage.m


#import "opencv2/imgcodecs/ios.h"

//uiimageからcv::Mat
cv::Mat cvmat;
UIImageToMat(uiimage, cvmat);

//cv::Matからuiimage
UIImage *uiimage = MatToUIImage(cvmat);



(オマケ)opencvで画像処理するときのテンプレート


UtilOpenCVHelper.h


#ifndef UtilOpenCVHelper_h
#define UtilOpenCVHelper_h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface UtilOpenCVHelper : NSObject
+(UIImage *)testOpenCVMethodWithUIImage:(UIImage *)image;
@end



UtilOpenCVHelper.mm

#import "UtilOpenCVHelper.h"

#import "opencv2/imgcodecs/ios.h"

@interface UtilOpenCVHelper()
@end

@implementation UtilOpenCVHelper

typedef BOOL (^openCVAlgorithm)(const cv::Mat&, cv::Mat&) ;

//UIImageをopencvで処理してUIImageで返すテンプレート
+(UIImage *)template:(UIImage *)uiimage withAlgorithm:(openCVAlgorithm)algorithm{
cv::Mat cvmat;
UIImageToMat(uiimage, cvmat);

UIImage *dstuiimage = uiimage;

cv::Mat cvdstmat;

if(algorithm(cvmat, cvdstmat)){
dstuiimage = MatToUIImage(cvdstmat);
}
else{
NSLog(@"[OPENCV ERROR]");
}

return dstuiimage;
}

//実際にOpenCVで処理する部分
+(UIImage *)testOpenCVMethodWithUIImage:(UIImage *)image{
return [UtilOpenCVHelper template:image
withAlgorithm:^BOOL (const cv::Mat &cvmat, cv::Mat &cvdstmat){
/*
opencvで画像処理
cvdstmatが出力
*/

return ! cvdstmat.empty()
}];
}