djk
djk

Reputation: 33

How to get errors/warnings in [UIImage initWithData:]

i have an MJPEG stream over RTSP/UDP from which i want to generate JPEGs for a UIImageView with [UIImage initWithData:]. Most of the time this works good, but sometimes i get corrupt images and log messages like:

ImageIO: <ERROR> JPEGCorrupt JPEG data: premature end of data segment

My Question is: how can i see (during runtime), that such message occurs? Unfortunatly 'initWithData' has no error output, is there any other way?

Thank you.

Edit: in this case, the initWithData does return a valid UIImage object, not nil!

Upvotes: 3

Views: 5049

Answers (3)

Zmey
Zmey

Reputation: 2558

I've encountered the same problem in this exact situation.

It turned out that I was passing an instance of NSMutableData to global queue for decoding. During decoding the data in NSMutableData was overwritten by next frame received from network.

I've fixed the errors by passing a copy of the data. It might be better to use a buffer pool to improve performance:

    NSData *dataCopy = [_receivedData copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    ZAssert([self isJPEGValid:dataCopy], @"JPEG data is invalid"); // should never happen
    UIImage *image = [UIImage imageWithData:dataCopy];
    dispatch_async(dispatch_get_main_queue(), ^{
        // show image
    });
});

Upvotes: -1

Alex Nichol
Alex Nichol

Reputation: 7510

There is a similar thread to this one on stack overflow: Catching error: Corrupt JPEG data: premature end of data segment.

There solution is to check for the header bytes FF D8 and ending bytes FF D9. So, if you have image data in an NSData, you can check it like so:

- (BOOL)isJPEGValid:(NSData *)jpeg {
    if ([jpeg length] < 4) return NO;
    const char * bytes = (const char *)[jpeg bytes];
    if (bytes[0] != 0xFF || bytes[1] != 0xD8) return NO;
    if (bytes[[jpeg length] - 2] != 0xFF || bytes[[jpeg length] - 1] != 0xD9) return NO;
    return YES;
}

Then, to check if JPEG data is invalid, just write:

if (![self isJPEGValid:myData]) {
    NSLog(@"Do something here");
}

Hope this helps!

Upvotes: 2

user756245
user756245

Reputation:

The initWithData: method should return nil in such cases.

Try :

UIImage *myImage = [[UIImage alloc] initWithData:imgData];
if(!myImage) {
    // problem
}

Upvotes: 1

Related Questions