본문 바로가기

프로그래밍/iOS

[iOS] BGRA를 RGBA로 변경

AVCaptureSession을 사용하여 videoData를 얻을 시 kCVPixelFormatType_32RGBA를 쓰고 싶으나, 이 값으로 셋팅하면 동작하지 않는다.

비디오에서 지원하는 포멧은 아래 링크와 같다.

https://developer.apple.com/library/content/qa/qa1501/_index.html

따라서 가장 비슷하게 사용가능한것이 kCVPixelFormatType_32BGRA이다.


이렇게 되면  captureOutput: didOutSampleBuffer: fromConnection: 함수에서 BGRA데이터를 받게 되는데 그 데이터를 RGBA로 변환하는 과정에 대해 기술한다.

#if !defined(byte)

typedef unsigned char byte; // 바이트 선언


- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection

{

        

     CVImageBufferRef imageBuffer CMSampleBufferGetImageBuffer(sampleBuffer);

     /*Lock the image buffer*/

     CVPixelBufferLockBaseAddress(imageBuffer,0);

        

     /*Get information about the image*/

     uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);

     size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);

     size_t dataSize = CVPixelBufferGetDataSize(imageBuffer);

     

     size_t width = bytesPerRow/4; // 32bit RGB이기 때문에 4 사용, 만약 다른 bit RGB 사용할 경우 바꿔야함

     size_t height = dataSize/bytesPerRow;

        

     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

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

     CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);

        

     CVPixelBufferUnlockBaseAddress(imageBuffer,0);

     CGContextRelease(bitmapContext);

     CGColorSpaceRelease(colorSpace);

        

     NSMutableData *rgbData = [(__bridge_transfer NSData *)CGDataProviderCopyData(CGImageGetDataProvider(cgImage)) mutableCopy];

        CGImageRelease(cgImage);

        

        // 비디오데이터 영상이 bgra 오기때문에 인식기에서 인식할 있는 rgba 변환(32bit rgba 셋팅 카메라 동작안하고 crash)

    int bpp = 4; // 32bitBGRA이기 때문에 byte per pixel 값이 4

    byte* src = [rgbData mutableBytes]; // rgbData의 시작 주소

    for(int i=0; i<height; i++)

    {

        for(int j = 0; j < width; j++)

        {

            byte* pDst = (byte*)(src + i*(int)imageSize.width*bpp +j*bpp); // bgra의 시작주소(각 픽셀의 시작 주소)

            // bgra->rgba로 바꾸기 때문에 r과 b값을 치환해준다.

            byte value = *(pDst+0);

            *(pDst+0) = *(pDst+2);

            *(pDst+2) = value;

        }

    }

    // 주소에 직접 접근하여 바꿨기 때문에 rgbData는 32bit rgba로 바뀌어 있음 사용하면 된다.

    // use rgbData

}