Search code examples
ioswindowsuiimagergbbgr

RBG24 can be played well on Windows, but on iOS it can't


By decoder transform H264 video to rgb24 file, it can be displayer well on Windows, but when I use UIImage to display it on UIImageView its color is not right. The code I use as this:

- (UIImage *)imageFromAVPicture:(const UInt8 *)pict width:(int)width height:(int)height
{
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, pict, width*height*3,kCFAllocatorNull);

    CGDataProviderRef provider = CGDataProviderCreateWithCFData(data);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGImageRef cgImage = CGImageCreate(width, 
                                       height, 
                                       8,
                                       24, 
                                       width*3, 
                                       colorSpace, 
                                       bitmapInfo, 
                                       provider, 
                                       NULL, 
                                       YES, 
                                       kCGRenderingIntentDefault);

    CGColorSpaceRelease(colorSpace);

    UIImage *image = [self scaleImage:cgImage];
    //UIImage *image = [[UIImage alloc] initWithCGImage:cgImage];
    CGImageRelease(cgImage);
    CGDataProviderRelease(provider);
    CFRelease(data);

    return image;
}

But before create CGImage, add code as following, its show will be right, what following code do is transform betweent rgb and bgr.

UInt8 tmpBuff1,*tmpBuff2;
tmpBuff2 = (UInt8 *)pict;

for(int i =0;i<height;i++)
{
    for(int j=0;j<width;j++)
    {
        tmpBuff1 = *tmpBuff2;
        *tmpBuff2 = *(tmpBuff2+2);
        *(tmpBuff2+2) = tmpBuff1;
        tmpBuff2 += 3;
    }
}

After transform from rgb to bgr, its show will be right.

So I want to know why, why the same RGB24 file can play well on PC, but wrong on iOS before transform from RGB24 to BGR24.


Solution

  • This is a standard endianness issue. Which byte represents which color is not standardized for RGB. Windows uses R in the MSB and Mac/iOS uses R in the LSB. So you always need to do the byte order transform you showed when moving RGB between Windows and Mac/iOS. Note that you will likely find it more efficient to use the Accelerate framework's vImagePermuteChannels_ARGB8888 to do this type of transform instead of writing your own code.