How to check if a NSData is valid for usage in UIImage
Asked Answered
V

8

17
NSError *error = nil;
NSURL *url = [NSURL URLWithString:[imageLinks objectAtIndex:0]];
NSData *tdata = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
if (error) {
    NSLog(@"%@", [error localizedDescription]);
}else {
    // no error, this one is being called within my app
    NSLog(@"Data loaded successfully");
}
self.pictureView1.image = [UIImage imageWithData:tdata];

I have a jpeg file, I can confirm that the URL content is gathered successfully, but when I try to put my image data into the UIImage my app fails. I wonder if there is any check for NSData to confirm it is usable for UIImage.

I also don't know what causes this failure, and how to prevent it. Any help would be appreciated.

Visser answered 17/6, 2012 at 15:42 Comment(3)
You can check whether the return value from the static constructor UIImage is nil or not to see if the data really can be used as image. As to why it fails, there is too little information to even guess the reason. Can you post the log for printing out NSData received?Behnken
the image data is corrupted, how can it be checked if it can be used as an image, and why it cannot be used if so?Visser
I think I answered this 2 questions of yours in my comment.Behnken
P
27

As stated in the documentation imageWithData: returns nil if UIImage could not create an image from the data. The correct way to handle this at runtime is to provide a placeholder image when that method returns nil.

As for the diagnostic, first look at the console messages, they sometimes provide useful info. If not, your best luck is to dump the NSData to disk and compare the result to the file stored on the server. You sometimes get corrupted data, you sometimes just get an html error message where you were expecting jpeg binary data.

Pyrone answered 17/6, 2012 at 15:52 Comment(0)
U
6

If you're dealing with a single small image, you could convert Data to an UIImage :

if let _ = UIImage(data: data) {
   print("data contains image data")
} else {
   print("data does not contain image data")
}

But if you're dealing with numerous images or high definition images, you could use what's called The magic bytes in all files, that is, the first few bytes representing a file signature.

Basically you'll just have to extract a few bytes instead of allocation a whole image.

Here is a Data extension using this technique :

import Foundation

extension Data {
    var isImageData: Bool {
        let array = self.withUnsafeBytes {
            [UInt8](UnsafeBufferPointer(start: $0, count: 10))
        }
        let intervals: [[UInt8]] = [
            [0x42, 0x4D], // bmp
            [0xFF, 0xD8, 0xFF], // jpg
            [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A], // png
            [0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20], // jpeg2000
            [0x49, 0x49, 0x2A, 0x00], // tiff1
            [0x4D, 0x4D, 0x00, 0x2A] // tiff2
        ]

        for interval in intervals {
            var image = true
            for i in 0..<interval.count {
                if array[i] != interval[i] {
                    image = false
                    break
                }
            }
            if image { return true }
        }
        return false
    }
}

You can add more images or imagine any file type recognition based on that code and file types (see Wikipedia list of file signatures for example).

Ulyanovsk answered 18/8, 2017 at 13:44 Comment(2)
The Data extension helped me! Thanks!Paresh
Swift 5, create the array with let array = self.subdata(in: 0 ..< 8).withUnsafeBytes{ Array($0.bindMemory(to: UInt8.self))} to avoid an unsafe bytes warningTopographer
S
4

You can use

 if ([UIImage imageWithData:yourNSData]) {
     // there was an image
 }
Scientist answered 16/4, 2015 at 19:55 Comment(0)
A
4

For Swift try this,

if let image = UIImage(data: yourNSData){
   YourImageView.image = image
}
Aphrodisia answered 11/2, 2016 at 21:59 Comment(0)
T
1

In Swift 4.2

self.userImageView.image = UIImage(data: data) != nil ? UIImage(data: data) : UIImage.init(named: "YourDesiredImage")
Traumatism answered 25/10, 2018 at 11:49 Comment(1)
This will create the image from the data twice, it would be better to use the nil coalescing operator to handle this instead like image = UIImage(data: data) ?? UIImage(named: "YourDesiredImage") This way it only creates the image from data once and still falls back to the other image if it is nil.Towhaired
S
0

Give this a try...

if ((dataImage != NULL) && ![v isKindOfClass:[NSNull class]])
{

}

Nothing worked in my case besides this.

Samons answered 28/8, 2015 at 8:54 Comment(0)
W
-2
if (tdata !=(NSData *)nil){ 
    NSlog(@"Valid");
}
Wexler answered 18/6, 2012 at 7:56 Comment(0)
P
-3
if (tdata !=nil){ 
    NSlog(@"Valid");
}

try this, this would check whether nsdata is empty or not.

Pharmacology answered 18/6, 2012 at 6:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.