New CGIImage or CGImageRef from std::string using

2019-05-30 20:24发布

问题:

everyone:

I've been working on this for days. Here's a little bit of background. I'm sending an image to a server using protobuf. The image is directly from the camera, so it is not a jpeg nor a png. I found code to get the data from the UIImage using the CGImage to create a CGImageRef. See the following code:

- (UIImage *)testProcessedImage:(UIImage *)processedImage
{
    CGImageRef imageRef = processedImage.CGImage;
    NSData *data1 = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

Google protobuf uses C++ code to send and receive the bytes to and from the server. When I tried to get the data bytes back into NSData and alloc init a UIImage with that data the UIImage was always nil. This tells me that my NSData is not in the correct format.

At first, I thought my issue was with the C++ conversion, as shown with my previous question here. But after much frustration, I cut out everything in the middle and just created a UIImage with the CGImageRef and it worked. See the following code:

- (UIImage *)testProcessedImage:(UIImage *)processedImage
{
    CGImageRef imageRef = processedImage.CGImage;
    NSData *data1 = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

    // Added this line and cut out everything in the middle
    UIImage *image = [UIImage imageWithCGImage:imageRef];

Following is a description of what I ultimately need to do. There are two parts. Part 1 takes a UIImage and converts it into a std::string.

  1. take a UIImage
  2. get the NSData from it
  3. convert the data to unsigned char *
  4. stuff the unsigned char * into a std::string

The string is what we would receive from the protobuf call. Part 2 takes the data from the string and converts it back into the NSData format to populate a UIImage. Following are the steps to do that:

  1. convert the std::string to char array
  2. convert the char array to a const char *
  3. put the char * into NSData
  4. return NSData

Now, with that background information and armed with the fact that populating the UIImage with a CGImageRef works, meaning that data in that format is the correct format to populate the UIImage, I'm looking for help in figuring out how to get the base64.data() into either a CFDataRef or a CGImageRef. Below is my test method:

- (UIImage *)testProcessedImage:(UIImage *)processedImage
{
    CGImageRef imageRef = processedImage.CGImage;
    NSData *data1 = (NSData *) CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(imageRef)));

    unsigned char *pixels = (unsigned char *)[data1 bytes];
    unsigned long size = [data1 length];

    // ***************************************************************************
    // This is where we would call transmit and receive the bytes in a std::string
    //
    // The following line simulates that:
    //
    const std::string byteString(pixels, pixels + size);
    //
    // ***************************************************************************

    // converting to base64        
    std::string encoded = base64_encode(reinterpret_cast<const unsigned char*>(byteString.c_str()), byteString.length());

    // retrieving base64        
    std::string decoded = base64_decode(encoded);

    // put byte array back into NSData format
    NSUInteger usize = decoded.length();
    const char *bytes = decoded.data();
    NSData *data2 = [NSData dataWithBytes:(const void *)bytes length:sizeof(unsigned char)*usize];
    NSLog(@"examine data");

    // But when I try to alloc init a UIImage with the data, the image is nil
    UIImage *image2 = [[UIImage alloc] initWithData:data2];
    NSLog(@"examine image2");


    // *********** Below is my convoluted approach at CFDataRef and CGImageRef **************** 

    CFDataRef dataRef = CFDataCreate( NULL, (const UInt8*) decoded.data(), decoded.length() );
    NSData *myData = (__bridge NSData *)dataRef;
    //CGDataProviderRef ref = CGDataProviderCreateWithCFData(dataRef);
    id sublayer = (id)[UIImage imageWithCGImage:imageRef].CGImage;
    UIImage *image3 = [UIImage imageWithCGImage:(__bridge CGImageRef)(sublayer)];

    return image3;
}

As any casual observer can see, I need help. HELP!!! I've tried some of the other questions on SO, such as this one and this one and this one and cannot find the information I need for the solution. I admit part of my problem is that I do not understand much about images (like RGBA values and other stuff).