convert UIImage to NSData and back to UIImage - ios

I have to populate table cell from database and images are on device.
I've to store that image in imageDataObject, how to convert that UIImage to NSData.
Please suggest, I tried many solution but it's not converting back that NSData to UIImage.
cell.textLabel.text = [[offlineImageListArray objectAtIndex:indexPath.row] imageName];
UIImage *thumbnail = [self retrieveImageFromDevice:[[offlineImageListArray objectAtIndex:indexPath.row] imageName]];
NSData* data = ??????????;
ImageData *imageDataObject = [[ImageData alloc] initWithImageId:[[offlineImageListArray objectAtIndex:indexPath.row]imageId]
imageName:[[offlineImageListArray objectAtIndex:indexPath.row] imageName] imageData:data];
[imagesArray addObject:imageDataObject];

To convert UIImage to NSData, use either UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality) or UIImagePNGRepresentation(UIImage *image)
To convert NSData to UIImage, use [UIImage imageWithData:imageData]
So your example could look like this:
cell.textLabel.text = [[offlineImageListArray objectAtIndex:indexPath.row] imageName];
UIImage *thumbnail = [self retrieveImageFromDevice:[[offlineImageListArray objectAtIndex:indexPath.row] imageName]];
NSData* data = UIImagePNGRepresentation(thumbnail);
ImageData *imageDataObject = [[ImageData alloc] initWithImageId:[[offlineImageListArray objectAtIndex:indexPath.row]imageId] imageName:[[offlineImageListArray objectAtIndex:indexPath.row] imageName] imageData:data];
[imagesArray addObject:imageDataObject];
References: https://developer.apple.com/LIBRARY/IOS/documentation/UIKit/Reference/UIKitFunctionReference/Reference/reference.html
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIImage_Class/Reference/Reference.html

Try With this:
Use this for convert UIImage to NSData.
NSData *imagedata = UIImagePNGRepresentation(thumbnail);
Try this for image data convert back to UIImage
UIImage *image= [UIImage imageWithData:imagedata];

in Swift version:
let imageData = image!.pngData()
let imageFromData = UIImage(data: imageData)
See: https://developer.apple.com/documentation/uikit/uiimage/1624096-pngdata

Use if-let block with Data to prevent app crash & safe execution of code, as function UIImagePNGRepresentation returns an optional value.
if let img = UIImage(named: "TestImage.png") {
if let data:Data = UIImagePNGRepresentation(img) {
// Handle operations with data here...
}
}
Note: Data is Swift 3 class. Use Data instead of NSData with
Swift 3
Generic image operations (like png & jpg both):
if let img = UIImage(named: "TestImage.png") { //UIImage(named: "TestImage.jpg")
if let data:Data = UIImagePNGRepresentation(img) {
handleOperationWithData(data: data)
} else if let data:Data = UIImageJPEGRepresentation(img, 1.0) {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}
By using extension:
extension UIImage {
var pngRepresentationData: Data? {
return UIImagePNGRepresentation(img)
}
var jpegRepresentationData: Data? {
return UIImageJPEGRepresentation(self, 1.0)
}
}
*******
if let img = UIImage(named: "TestImage.png") { //UIImage(named: "TestImage.jpg")
if let data = img.pngRepresentationData {
handleOperationWithData(data: data)
} else if let data = img.jpegRepresentationData {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}

Convert Data from Image:
Try JPEG or PNG representation depending on your image format:
UIImageJPEGRepresentation
Returns the data for the specified image in JPEG format.
NSData * UIImageJPEGRepresentation (
UIImage *image,
CGFloat compressionQuality
);
UIImagePNGRepresentation
Returns the data for the specified image in PNG format
NSData * UIImagePNGRepresentation (
UIImage *image
);
Example:
extension UIImage {
var pngRepresentationData: Data? {
return UIImagePNGRepresentation(img)
}
var jpegRepresentationData: Data? {
return UIImageJPEGRepresentation(self, 1.0)
}
}
Use:
let data = myImage.jpegRepresentationData
let data1 = myImage.pngRepresentationData
Convert Image from Data:
let image = UIImage(data: data)

Related

How to load raw image using PHPicker in iOS programmatically?

I can load normal images: public.image types.
The Apple proRaw(adobe raw image type: DNG format) can be used in iPhone 12 series.
So, I captured with RAW image and I want to load the DNG file from app.
But I can't load the image using PHPicker.
Normally, the codes below.
PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init];
configuration.filter = [PHPickerFilter anyFilterMatchingSubfilters:#[[PHPickerFilter imagesFilter], [PHPickerFilter livePhotosFilter]]];
PHPickerViewController *pickerController = [[PHPickerViewController alloc] initWithConfiguration:configuration];
pickerController.delegate = self;
[pickerController setModalPresentationStyle:UIModalPresentationCustom];
[pickerController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[viewController presentViewController:pickerController animated:YES completion:nil];
-(void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) {
[picker dismissViewControllerAnimated:YES completion:nil];
PHPickerResult *result = [results firstObject];
if ([result.itemProvider canLoadObjectOfClass:[UIImage class]]) { // 1
[result.itemProvider loadObjectOfClass:[NSObject class] completionHandler:^(__kindof id<NSItemProviderReading> _Nullable object, NSError * _Nullable error) {
if ([object isKindOfClass:[UIImage class]]) {
UIImage *image = object;
...
}
}];
}
In comment 1 line, returned NO.
How to load raw image using PHPicker?
Using loadFileRepresentation to get the photo's data into a CGImage object worked for me. Something like:
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { url, _ in
guard let url = url,
let data = NSData(contentsOf: url),
let source = CGImageSourceCreateWithData(data, nil),
let cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil) else {
// handle
}
let image = UIImage(cgImage)
...
}
or
[result.itemProvider loadFileRepresentationForTypeIdentifier:#"public.image" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
if (url) {
NSData *data = [NSData dataWithContentsOfURL:url];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
UIImage *image = [UIImage imageWithCGImage:cgImage];
...
}
}];
You may need to get the correct orientation using CGImageSourceCopyPropertiesAtIndex to get the metadata dictionary, find the correct value with the kCGImagePropertyOrientation key, transform it from CGImagePropertyOrientation to UIImage.Orientation, and pass it to the UIImage initializer.
It's a bit more involved than just using loadObjectOfClass but it won't require photo access authorization.
You can use this code also. for opening new PHPicker.
For More Knowledge about PHPicker in WWDC21 PHPicker WWDC20 Video and PHPicker WWDC21 Video
WWDC PHPicker Notes PHPicker Notes
import Photos
import PhotosUI
// MARK: - PHPicker Configurations (PHPickerViewControllerDelegate)
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: .none)
results.forEach { result in
result.itemProvider.loadObject(ofClass: UIImage.self) { reading, error in
guard let image = reading as? UIImage, error == nil else { return }
DispatchQueue.main.async {
self.profilePictureOutlet.image = image
// TODO: - Here you get UIImage
}
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { [weak self] url, _ in
// TODO: - Here You Get The URL
}
}
}
}
/// call this method for `PHPicker`
func openPHPicker() {
var phPickerConfig = PHPickerConfiguration(photoLibrary: .shared())
phPickerConfig.selectionLimit = 1
phPickerConfig.filter = PHPickerFilter.any(of: [.images, .livePhotos])
let phPickerVC = PHPickerViewController(configuration: phPickerConfig)
phPickerVC.delegate = self
present(phPickerVC, animated: true)
}
}

pngData back to UIImage

I have a UIImage variable, a. I would like to use it within my app as a .png data file. How do I go about recasting a back into a UIImage for use?
How can I cast this data object back into a UIImage?
let pngImage = a!.pngData()
Converting UIImage to PNG Data:
extension UIImage {
// UIImage to Data (PNG Representation)
var PNGData: Data? {
return UIImagePNGRepresentation(self)
}
}
Using your example:
let a = UIImage("foo") // Sample image named foo
UIImage to Data:
let pngData = a.data
Data to UIImage:
let pngImage = UIImage(data: pngData)

How to get Exif data from local image using Swift?

If we have image imageName.jpg in Assets.xcassets and let's put that image in UIImage like this:
let imageForExif: UIImage = UIImage(named: "imageName.jpg")!
How we can get (extract) Exif data from imageForExif using Swift?
Try this...
if let imageData = UIImageJPEGRepresentation(imageForExif, 1.0) {
let imageCFData = imageData as CFData
if let cgImage = CGImageSourceCreateWithData(imageCFData, nil), let metaDict: NSDictionary = CGImageSourceCopyPropertiesAtIndex(cgImage, 0, nil) {
let exifDict: NSDictionary = metaDict.object(forKey: kCGImagePropertyExifDictionary) as! NSDictionary
print(exifDict)
}
}
But you may have very limited data available. Hope it helps.

Convert UIImage to NSData and convert back to UIImage in Swift?

I'm trying to save a UIImage to NSData and then read the NSData back to a new UIImage in Swift. To convert the UIImage to NSData I'm using the following code:
let imageData: NSData = UIImagePNGRepresentation(myImage)
How do I convert imageData (i.e., NSData) back to a new UIImage?
UIImage(data:imageData,scale:1.0) presuming the image's scale is 1.
In swift 4.2, use below code for get Data().
image.pngData()
Thanks. Helped me a lot. Converted to Swift 3 and worked
To save: let data = UIImagePNGRepresentation(image)
To load: let image = UIImage(data: data)
Use imageWithData: method, which gets translated to Swift as UIImage(data:)
let image : UIImage = UIImage(data: imageData)
Now in Swift 4.2 you can use pngData() new instance method of UIImage to get the data from the image
let profileImage = UIImage(named:"profile")!
let imageData = profileImage.pngData()
Details
Xcode 10.2.1 (10E1001), Swift 5
Solution 1
guard let image = UIImage(named: "img") else { return }
let jpegData = image.jpegData(compressionQuality: 1.0)
let pngData = image.pngData()
Solution 2.1
extension UIImage {
func toData (options: NSDictionary, type: CFString) -> Data? {
guard let cgImage = cgImage else { return nil }
return autoreleasepool { () -> Data? in
let data = NSMutableData()
guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
CGImageDestinationAddImage(imageDestination, cgImage, options)
CGImageDestinationFinalize(imageDestination)
return data as Data
}
}
}
Usage of solution 2.1
// about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
let options: NSDictionary = [
kCGImagePropertyOrientation: 6,
kCGImagePropertyHasAlpha: true,
kCGImageDestinationLossyCompressionQuality: 0.5
]
// https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
guard let data = image.toData(options: options, type: kUTTypeJPEG) else { return }
let size = CGFloat(data.count)/1000.0/1024.0
print("\(size) mb")
Solution 2.2
extension UIImage {
func toJpegData (compressionQuality: CGFloat, hasAlpha: Bool = true, orientation: Int = 6) -> Data? {
guard cgImage != nil else { return nil }
let options: NSDictionary = [
kCGImagePropertyOrientation: orientation,
kCGImagePropertyHasAlpha: hasAlpha,
kCGImageDestinationLossyCompressionQuality: compressionQuality
]
return toData(options: options, type: .jpeg)
}
func toData (options: NSDictionary, type: ImageType) -> Data? {
guard cgImage != nil else { return nil }
return toData(options: options, type: type.value)
}
// about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
func toData (options: NSDictionary, type: CFString) -> Data? {
guard let cgImage = cgImage else { return nil }
return autoreleasepool { () -> Data? in
let data = NSMutableData()
guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
CGImageDestinationAddImage(imageDestination, cgImage, options)
CGImageDestinationFinalize(imageDestination)
return data as Data
}
}
// https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
enum ImageType {
case image // abstract image data
case jpeg // JPEG image
case jpeg2000 // JPEG-2000 image
case tiff // TIFF image
case pict // Quickdraw PICT format
case gif // GIF image
case png // PNG image
case quickTimeImage // QuickTime image format (OSType 'qtif')
case appleICNS // Apple icon data
case bmp // Windows bitmap
case ico // Windows icon data
case rawImage // base type for raw image data (.raw)
case scalableVectorGraphics // SVG image
case livePhoto // Live Photo
var value: CFString {
switch self {
case .image: return kUTTypeImage
case .jpeg: return kUTTypeJPEG
case .jpeg2000: return kUTTypeJPEG2000
case .tiff: return kUTTypeTIFF
case .pict: return kUTTypePICT
case .gif: return kUTTypeGIF
case .png: return kUTTypePNG
case .quickTimeImage: return kUTTypeQuickTimeImage
case .appleICNS: return kUTTypeAppleICNS
case .bmp: return kUTTypeBMP
case .ico: return kUTTypeICO
case .rawImage: return kUTTypeRawImage
case .scalableVectorGraphics: return kUTTypeScalableVectorGraphics
case .livePhoto: return kUTTypeLivePhoto
}
}
}
}
Usage of solution 2.2
let compressionQuality: CGFloat = 0.4
guard let data = image.toJpegData(compressionQuality: compressionQuality) else { return }
printSize(of: data)
let options: NSDictionary = [
kCGImagePropertyHasAlpha: true,
kCGImageDestinationLossyCompressionQuality: compressionQuality
]
guard let data2 = image.toData(options: options, type: .png) else { return }
printSize(of: data2)
Problems
Image representing will take a lot of cpu and memory resources. So, in this case it is better to follow several rules:
- do not run jpegData(compressionQuality:) on main queue
- run only one jpegData(compressionQuality:) simultaneously
Wrong:
for i in 0...50 {
DispatchQueue.global(qos: .utility).async {
let quality = 0.02 * CGFloat(i)
//let data = image.toJpegData(compressionQuality: quality)
let data = image.jpegData(compressionQuality: quality)
let size = CGFloat(data!.count)/1000.0/1024.0
print("\(i), quality: \(quality), \(size.rounded()) mb")
}
}
Right:
let serialQueue = DispatchQueue(label: "queue", qos: .utility, attributes: [], autoreleaseFrequency: .workItem, target: nil)
for i in 0...50 {
serialQueue.async {
let quality = 0.02 * CGFloat(i)
//let data = image.toJpegData(compressionQuality: quality)
let data = image.jpegData(compressionQuality: quality)
let size = CGFloat(data!.count)/1000.0/1024.0
print("\(i), quality: \(quality), \(size.rounded()) mb")
}
}
Links
UTI Image Content Types
CGImageDestinationAddImage(::_:)
Thinking about Memory: Converting UIImage to Data in Swift
Different resize technics
To save as data:
From StoryBoard, if you want to save "image" data on the imageView of MainStoryBoard, following codes will work.
let image = UIImagePNGRepresentation(imageView.image!) as NSData?
To load "image" to imageView:
Look at exclamation point "!", "?" closely whether that is quite same as this one.
imageView.image = UIImage(data: image as! Data)
"NSData" type is converted into "Data" type automatically during this process.
Image to Data:-
if let img = UIImage(named: "xxx.png") {
let pngdata = img.pngData()
}
if let img = UIImage(named: "xxx.jpeg") {
let jpegdata = img.jpegData(compressionQuality: 1)
}
Data to Image:-
guard let image = UIImage(data: pngData) else { return }
For safe execution of code, use if-let block with Data to prevent app crash & , as function UIImagePNGRepresentation returns an optional value.
if let img = UIImage(named: "TestImage.png") {
if let data:Data = UIImagePNGRepresentation(img) {
// Handle operations with data here...
}
}
Note: Data is Swift 3+ class. Use Data instead of NSData with
Swift 3+
Generic image operations (like png & jpg both):
if let img = UIImage(named: "TestImage.png") { //UIImage(named: "TestImage.jpg")
if let data:Data = UIImagePNGRepresentation(img) {
handleOperationWithData(data: data)
} else if let data:Data = UIImageJPEGRepresentation(img, 1.0) {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}
By using extension:
extension UIImage {
var pngRepresentationData: Data? {
return UIImagePNGRepresentation(self)
}
var jpegRepresentationData: Data? {
return UIImageJPEGRepresentation(self, 1.0)
}
}
*******
if let img = UIImage(named: "TestImage.png") { //UIImage(named: "TestImage.jpg")
if let data = img.pngRepresentationData {
handleOperationWithData(data: data)
} else if let data = img.jpegRepresentationData {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}
Swift 5
let the image you create as UIImage be image
image.pngData() as NSData?
Use this for a simple solution
static var UserProfilePhoto = UIImage()
guard let image = UIImage(named: "Photo") else { return }
guard let pngdata = image.pngData() else { return }
UserProfilePhoto = UIImage(data: pngdata)!

NSData and UIImage

I am trying to load UIImage object from NSData, and the sample code was to NSImage, I guess they should be the same. But just now loading the image, I am wondering what's the best to troubleshoot the UIImage loading NSData issue.
I didn't try UIImageJPEGRepresentation() before, but UIImagePNGRepresentation works fine for me, and conversion between NSData and UIImage is dead simple:
NSData *imageData = UIImagePNGRepresentation(image);
UIImage *image=[UIImage imageWithData:imageData];
UIImage has an -initWithData: method. From the docs: "The data in the data parameter must be formatted to match the file format of one of the system’s supported image types."
Try this to convert an image to NSdata:
UIImage *img = [UIImage imageNamed:#"image.png"];
NSData *data1 = UIImagePNGRepresentation(img);
theData should be a NSData object which already contains the data. You need to do the file loading/downloading to the NSData object before it is used. You can inspect it by using NSLog on theData and see if it contains the valid data.
For safe execution of code, use if-let block with Data, as function UIImagePNGRepresentation returns, optional value.
if let img = UIImage(named: "Hello.png") {
if let data:Data = UIImagePNGRepresentation(img) {
// Handle operations with data here...
}
}
Note: Data is Swift 3 class. Use Data instead of NSData with
Swift 3
Generic image operations (like png & jpg both):
if let img = UIImage(named: "Hello.png") {
if let data:Data = UIImagePNGRepresentation(img) {
handleOperationWithData(data: data)
} else if let data:Data = UIImageJPEGRepresentation(img, 1.0) {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}
By using extension:
extension UIImage {
var pngRepresentationData: Data? {
return UIImagePNGRepresentation(img)
}
var jpegRepresentationData: Data? {
return UIImageJPEGRepresentation(self, 1.0)
}
}
*******
if let img = UIImage(named: "Hello.png") {
if let data = img.pngRepresentationData {
handleOperationWithData(data: data)
} else if let data = jpegRepresentationData {
handleOperationWithData(data: data)
}
}
*******
func handleOperationWithData(data: Data) {
// Handle operations with data here...
if let image = UIImage(data: data) {
// Use image...
}
}

Resources