I used this method to take a picture.
func convertImageFromCMSampleBufferRef(sampleBuffer:CMSampleBuffer) -> CIImage{
let pixelBuffer:CVPixelBufferRef = CMSampleBufferGetImageBuffer(sampleBuffer)!;
let ciImage:CIImage = CIImage(CVPixelBuffer: pixelBuffer)
if done == true {
newImage = UIImage(CIImage:ciImage, scale: CGFloat(1.0), orientation: .DownMirrored)
var imageData = UIImageJPEGRepresentation(newImage, 0.6)
var compressedJPGImage = UIImage(data: imageData)
UIImageWriteToSavedPhotosAlbum(compressedJPGImage!, nil, nil, nil)
}
return ciImage;
}
The code should work, but the variable imageData = nil
I tried converting the image in PNG, but with the same result.
with print
newImage = , {720, 1280} imageData = nil
You must convert CIImage to a CGImage, then CGImage to an UIImage, and then UIImage to NSData.
static let context = CIContext(options:nil);
let tempImage:CGImageRef = context.createCGImage(ciImage, fromRect: ciImage.extent())
let image = UIImage(CGImage: tempImage);
let imageData: NSData? = UIImageJPEGRepresentation(image, 0.6);
Related
I have an NSImage object, I have an CIDetector object that detects QR codes on that image. After it detects, I wants to trim that image so it only has the QR code in it. This is how I've got the bounds of the QR code:
NSArray *features = [myQRDetector featureInImage:myCIImage];
CIQRCodeFeature *qrFeature = features[0];
CGRect qrBounds = qrFeature.bounds;
Now how can I trim the image so it only contains the area described by qrBounds variable.
In Swift 5
func trim(image: NSImage, rect: CGRect) -> NSImage {
let result = NSImage(size: rect.size)
result.lockFocus()
let destRect = CGRect(origin: .zero, size: result.size)
image.draw(in: destRect, from: rect, operation: .copy, fraction: 1.0)
result.unlockFocus()
return result
}
The answer from onmyway133 is great, but it doesn't preserve the datatype of the source image. For instance, if your source is an .hdr image, each color channel will be floats, but the cropped image will be an 8-bit integer RGBA image.
For preserving the format of the source, it seems you have to go down to the associated CGImage. I do this:
extension NSImage {
func cropping(to rect: CGRect) -> NSImage {
var imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
guard let imageRef = self.cgImage(forProposedRect: &imageRect, context: nil, hints: nil) else {
return NSImage(size: rect.size)
}
guard let crop = imageRef.cropping(to: rect) else {
return NSImage(size: rect.size)
}
return NSImage(cgImage: crop, size: NSZeroSize)
}
}
You need to create a new NSImage and draw the part of the original image you want to it.
NSImage* newImage = [[NSImage alloc] initWithSize:NSSizeFromCGSize(qrBounds.size)];
[newImage lockFocus];
NSRect dest = { NSZeroPoint, newImage.size };
[origImage drawInRect:dest fromRect:NSRectFromCGRect(qrBounds) operation:NSCompositeCopy fraction:1];
[newImage unlockFocus];
The filtering on the photo works but I'm stuck with this problem.
When I run this code:
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setDefaults()
filter.setValue(originalImage, forKey: kCIInputImageKey)
var newImage = UIImage(CIImage: filter.outputImage)
imageView.image = newImage
The first error is:
BSXPCMessage received error for message: Connection interrupted
The second error is:
fatal error: unexpectedly found nil while unwrapping an Optional value
Then the app crashes.
How would I fix it and the errors?
Try this:
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(originalImage, forKey: kCIInputImageKey)
let context = CIContext(options:nil)
let ouputImage = context.createdCGImage(filter,fromRect:filter.extend())
var newImage = UIImage(CGImage: ouputImage)
imageView.image = newImage
Your code runs fine. Your image source imageView.image is probably nil when you call it. You can try this at playground:
let myPicture = UIImage(data: NSData(contentsOfURL: NSURL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!)!)!
let filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(CIImage(image: myPicture), forKey: kCIInputImageKey)
let newImage = UIImage(CIImage: filter.outputImage)
I Found A Solution:
Updated
let originalImage = CIImage(image: imageView.image)
var filter = CIFilter(name: "CIPhotoEffectMono")
filter.setValue(originalImage, forKey: kCIInputImageKey)
let context = CIContext(options: [kCIContextUseSoftwareRenderer: true])
let outputImage = context.createCGImage(filter.outputImage, fromRect: filter.outputImage.extent())
var newImage = UIImage(CGImage: outputImage)
imageView.image = newImage
*Based on Lamar's code.
CIContext(options: nil) was causing BSXPCMessage received error for message: Connection interrupted error.
SO replace:
CIContext(options: nil) with CIContext(options: [kCIContextUseSoftwareRenderer: true])
Thanks For The Help:
Lamar
The app doesn't crash anymore.
**I have added Black n White Effect To an Image**
UIGraphicsBeginImageContext(clickedImage.bounds.size)
clickedImage.layer.renderInContext(UIGraphicsGetCurrentContext())
var image2: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
origionalimage=image2;
var CIfilterName = "CIPhotoEffectTonal"
let ciContext = CIContext(options: nil)
let startImage = CIImage(image: image2)
let filter = CIFilter(name: CIfilterName)
filter.setDefaults()
filter.setValue(startImage, forKey: kCIInputImageKey)
let filteredImageData = filter.valueForKey(kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
var newImage = UIImage(CGImage: filteredImageRef)!
self.mediaData = UIImagePNGRepresentation(newImage )
self.videoThumbData = UIImageJPEGRepresentation(image2, 0.1)
self.clickedImage.image = newImage;
I have archived an NSColor to store it in NSUserDefaults:
var data = NSArchiver.archivedDataWithRootObject(NSColor.redColor())
storage.setObject(data, forKey: "color")
storage.synchronize()
But now I need to get the color back from NSData, I have no idea how to do that
You just need to use if let to unwrap your NSData and also you will need a conditional cast as follow:
edit/update:
Swift 3 or later
// archiving
let color: NSColor = .red
let data = NSKeyedArchiver.archivedData(withRootObject: color)
UserDefaults.standard.set(data, forKey: "color")
// unarchiving
if let loadedData = UserDefaults.standard.data(forKey: "color"),
let loadedColor = NSKeyedUnarchiver.unarchiveObject(with: loadedData) as? NSColor {
// you can access loadedColor here
print(loadedColor) // "sRGB IEC61966-2.1 colorspace 1 0 0 1\n"
}
Ran into some errors trying to get Leo's answer working in Swift 5. Came up with this extension which lets UserDefaults store and retrieve colors. Try pasting this into a Playground.
import Cocoa
extension UserDefaults {
func set(_ color: NSColor, forKey: String) {
if let data = try? NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) {
self.set(data, forKey: forKey)
}
}
func color(forKey: String) -> NSColor? {
guard
let storedData = self.data(forKey: forKey),
let unarchivedData = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSColor.self, from: storedData),
let color = unarchivedData as NSColor?
else {
return nil
}
return color
}
}
// get defaults instance
let defaults = UserDefaults.standard
// create a color
let mycolor = NSColor(red: 0.0, green: 0.5, blue: 0.8, alpha: 0.5)
// save the color
defaults.set(mycolor, forKey: "mycolor")
// read the color back. this returns an optional, may be nil
defaults.color(forKey: "mycolor")
I'm trying to save images retrieved from Parse.com like this:
let userImageFile = object["Image"] as PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
image = UIImage(data:imageData)
let imageToSave:NSData = UIImagePNGRepresentation(image)
self.saveImage(intRandomNumb, retImage: imageToSave)
}
}
where the saveImage-function looks like this:
func saveImage(imagepath:Int, retImage:NSData){
println("image is being saved")
let defaults = NSUserDefaults.standardUserDefaults()
let imagePathName = "\(imagepath)"
defaults.setObject(retImage, forKey: imagePathName)
}
and later, I'm trying to display this image like this:
var point = gestureRecognizer.locationInView(self.tv)
if let indexPath = self.tv.indexPathForRowAtPoint(point)
{
let data = mainList[indexPath.row] as SecondModel
let fileRef = data.fileReference
let intFileRef = Int(fileRef)
println(intFileRef)
let defaults = NSUserDefaults.standardUserDefaults()
let usedKeyName = "\(intFileRef)"
if let photo = defaults.objectForKey(usedKeyName) as? UIImage {
println("Image created")
let photo = defaults.objectForKey(usedKeyName) as UIImage
var imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = photo
self.view.addSubview(imageView)
}
and the "Image created" never gets printed which means the retrieving somehow doesn't work.
I'm not quite sure if you're able to save images to the userdefaults like I've done here, but that was the best I could come up with, and I couldn't find any previous questions like this for Swift.
Any suggestions on how to proceed would be appreciated.
SOLUTION: The problem was that I tried to load the image directly as a UIImage. I also had to convert the NSData to a UIImage, this all happens in the last section of the code displayed above. Finally my code looks like this:
if let photo = defaults.objectForKey("\(intFileRef)") as? NSData {
println("Image created")
let photo = defaults.objectForKey("\(intFileRef)") as NSData
let imageToView:UIImage = UIImage(data: photo)
var imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
imageView.image = imageToView
self.view.addSubview(imageView)
}
I hope this can help others struggling with something similar to this.
Swift 3
Hey, try this beautiful code here:
Convert your UIImage to Data.
PNG:
yourDataImagePNG = UIImagePNGRepresentation(yourUIImageHere)
JPEG :
yourDataImageJPG = UIImage(data: yourUIImageHere,scale:1.0)
Save in UserDefaults.
UserDefaults().set(yourDataImagePNG, forKey: "image")
Recover from:
UserDefaults.standard.object(forKey: "image") as! Data
I hope to help!
It seems like you do not call defaults.synchronize() so it's not written to the defaults file.
How can I convert a NSImage to CGImage in Swift? In Objective-C I did it like this:
- (CGImageRef)CGImage {
NSData *imageData = self.TIFFRepresentation;
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CGImageRef maskRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
return maskRef;
}
Now I tried with:
extension NSImage {
var CGImage: CGImageRef {
get {
let imageData = self.TIFFRepresentation
let source = CGImageSourceCreateWithData(imageData as CFDataRef, nil)
let maskRef = CGImageSourceCreateImageAtIndex(source, UInt(0), nil)
return maskRef;
}
}
}
I can't compile, I'm getting the error: Could not find an overload for 'init' that accepts the supplied arguments' at the line let maskRef ...
Here's what I'm using to convert NSImage to CGImage:
let image = NSImage(named:"image")
if let image = image {
var imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
let imageRef = image.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)
}
Swift 5 code :-
if let image = NSImage(named: "Icon"){
let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
}
Ah, I found the solution. It's because in Swift you only the an unmanaged object (I just did not really understand, what this means). But this code now works:
extension NSImage {
var CGImage: CGImageRef {
get {
let imageData = self.TIFFRepresentation
let source = CGImageSourceCreateWithData(imageData as CFDataRef, nil).takeUnretainedValue()
let maskRef = CGImageSourceCreateImageAtIndex(source, UInt(0), nil)
return maskRef.takeUnretainedValue();
}
}
}
For Swift 4.0, XCode 9.2:
extension NSImage {
#objc var CGImage: CGImage? {
get {
guard let imageData = self.tiffRepresentation else { return nil }
guard let sourceData = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil }
return CGImageSourceCreateImageAtIndex(sourceData, 0, nil)
}
}
}
A Swift 5 implementation:
extension NSImage {
var CGImage: CGImage {
get {
let imageData = self.tiffRepresentation!
let source = CGImageSourceCreateWithData(imageData as CFData, nil).unsafelyUnwrapped
let maskRef = CGImageSourceCreateImageAtIndex(source, Int(0), nil)
return maskRef.unsafelyUnwrapped
}
}
}