CIConstantColorGenerator CIFilter failed with error in Playground with Swift 2.0 - swift-playground

I tried to create a color filter with the following line of code
let parameters = [kCIInputColorKey: CIColor(string: "0.5 0.7 0.3 1.0")]
let colorFilter = CIFilter(name: "CIConstantColorGenerator", withInputParameters: parameters)
colorFilter?.outputImage
but the debug console output the rolling info
<Error>: CGImageProviderCreate: invalid image provider size: 1.79769e+308 x 1.79769e+308.
<Error>: CGImageCreate: invalid image width.
<Error>: ImageIO: CGImageDestinationFinalize image destination must have at least one image
CGImageDestinationFinalize failed for output type 'public.tiff'
Thanks,
plus: I tried to write this code in Swift Project, it works fine, but when worked in playground, just showed this error

Just try to clarify what size of output image you want to get:
colorFilter?.outputImage?.imageByCroppingToRect(CGRectMake(0, 0, 200, 200))

Related

Can't get CoreSpotlight to work properly on the Mac... sample code anyone?

Can someone point me to some sample code for using CoreSpotlight on the Mac? I can’t find a single sample code example (for mac, plenty of iOS ones out there). I have already successfully implemented CS on our iOS app.
Using code similar to what I used for iOS, I’m getting it to index the content, but it’s very minimal: it gives me the generic app icon for the content (rather than the custom thumbnail image I specify) and has no description, etc (on the Spotlight pane, the entire right side is blank).
Also, it's unclear to me what code I need to add to AppDelegate to handle the click on the spotlight data. I used `func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler:) on iOS but this doesn't seem to get called on the Mac.
Here's the code I'm using to index the content:
attributeSet.title = content.name
attributeSet.contentDescription = content.description
if let image = image {
let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)!
let bitmapRep = NSBitmapImageRep(cgImage: cgImage)
attributeSet.thumbnailData = bitmapRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
}
let item = CSSearchableItem(uniqueIdentifier:content.uuid, domainIdentifier: "com.my.app.bundle.id", attributeSet: attributeSet)
searchableIndex?.indexSearchableItems([item]) { error in
if let error = error {
NSLog("CoreSpotlight Indexing error: \(error.localizedDescription)")
}
}
And this is an example of what I get in Spotlight:
A bit of sample code would clear this right up, Methinks.
Thanks in advance.

vImage on the Mac: unable to convert from Core Video

Edit: Fixed. A working sample is at https://github.com/halmueller/vImage-mac-sample.
I'm trying to read the feed of a MacBook Pro's Facetime camera to process it with the vImage framework. I'm following the example in Apple's VideoCaptureSample, which is written for iOS.
I'm getting hung up on creating the vImageConverter, which creates an image buffer that vImage can use. My call to vImageConverter_CreateForCVToCGImageFormat() fails, with the console error "insufficient information in srcCVFormat to decode image. vImageCVImageFormatError = -21601".
The same call works on iOS. But the image formats are different on iOS and macOS. On iOS, the vImageConverter constructor is able to infer the format information, but on macOS, it can't.
Here's my setup code:
func displayEqualizedPixelBuffer(pixelBuffer: CVPixelBuffer) {
var error = kvImageNoError
if converter == nil {
let cvImageFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer).takeRetainedValue()
let deviceRGBSpace = CGColorSpaceCreateDeviceRGB()
let dcip3SolorSpace = CGColorSpace(name: CGColorSpace.dcip3)
vImageCVImageFormat_SetColorSpace(cvImageFormat,
deviceRGBSpace)
print(cvImageFormat)
if let unmanagedConverter = vImageConverter_CreateForCVToCGImageFormat(
cvImageFormat,
&cgImageFormat,
nil,
vImage_Flags(kvImagePrintDiagnosticsToConsole),
&error) {
guard error == kvImageNoError else {
return
}
converter = unmanagedConverter.takeRetainedValue()
} else {
return
}
}
When I run on iOS, I see in the console:
vImageCVFormatRef 0x101e12210:
type: '420f'
matrix:
0.29899999499321 0.58700001239777 0.11400000005960
-0.16873589158058 -0.33126410841942 0.50000000000000
0.50000000000000 -0.41868758201599 -0.08131241053343
chroma location: <RGB Base colorspace missing>
RGB base colorspace: =Bo
On macOS, though, the call to vImageConverter_CreateForCVToCGImageFormat returns nil, and I see:
vImageCVFormatRef 0x10133a270:
type: '2vuy'
matrix:
0.29899999499321 0.58700001239777 0.11400000005960
-0.16873589158058 -0.33126410841942 0.50000000000000
0.50000000000000 -0.41868758201599 -0.08131241053343
chroma location: <RGB Base colorspace missing>
RGB base colorspace: Рü
2018-03-13... kvImagePrintDiagnosticsToConsole: vImageConverter_CreateForCVToCGImageFormat error:
insufficient information in srcCVFormat to decode image. vImageCVImageFormatError = -21601
Note that the image type (4 letter code) is different, as is the RGB base colorspace. I've tried on the Mac using dcip3ColorSpace instead of deviceRGB, and the results are the same.
What am I missing to get this vImageConverter created?
The -21601 error code means that the source CV format is missing chroma siting information (see http://dougkerr.net/Pumpkin/articles/Subsampling.pdf for a nice background of chroma siting). You can fix this by explicitly setting it with vImageCVImageFormat_SetChromaSiting. So, immediately after setting the format's color space, and before creating the converter (i.e. where you have print(cvImageFormat)), add the following:
vImageCVImageFormat_SetChromaSiting(cvImageFormat,
kCVImageBufferChromaLocation_Center)
Cheers!
simon
So, while the answer about calling setting the chorma property on the vImage format does work, there is a better way to do that. Just set the property on the core video pixel buffer and then when you call vImageCVImageFormat_CreateWithCVPixelBuffer() it will just work, like so:
NSDictionary *pbAttachments = #{
(__bridge NSString*)kCVImageBufferChromaLocationTopFieldKey:(__bridge NSString*)kCVImageBufferChromaLocation_Center,
(__bridge NSString*)kCVImageBufferAlphaChannelIsOpaque: (id)kCFBooleanTrue,
};
CVBufferRef pixelBuffer = cvPixelBuffer;
CVBufferSetAttachments(pixelBuffer, (__bridge CFDictionaryRef)pbAttachments, kCVAttachmentMode_ShouldPropagate);
For extra points, you can also set the colorspace ref with the kCVImageBufferICCProfileKey and the CGColorSpaceCopyICCData() API.

QLPreviewRequestSetDataRepresentation seems not to work when passing an image [duplicate]

My quick look generator used to work properly but is now broken.
Is it a bug or am I doing something wrong?
Here’s my code:
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview,
CFURLRef url, CFStringRef contentTypeUTI,
CFDictionaryRef options) {
NSDictionary * myDoc = [NSDictionary dictionaryWithContentsOfURL:(NSURL *)url];
if (myDoc) {
NSData * pngData = [myDoc valueForKey:#"pngPreview"];
if (pngData) {
QLPreviewRequestSetDataRepresentation(preview,(__bridge CFDataRef)pngData,
kUTTypeImage,NULL);
}
}
}
My doc is a normal plist with a png preview stored as data in it.
I checked that pngPreview does contain png data, I created the image and its size was 350×350.
However, I’m constantly getting these errors:
qlmanage[702] : CGImageCreate: invalid image size: 0 x 0.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x9e27, name = 'com.apple.tsm.portname'
See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x3f2b, name = 'com.apple.CFPasteboardClient'
See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] Failed to allocate communication port for com.apple.CFPasteboardClient; this is likely due to sandbox restrictions
My app is not sandboxed so I don’t think the last 3 errors are important.
I used to use kUTTypePNG but have tried kUTTypeImage to no avail (the docs for QLPreviewRequestSetDataRepresentation says currently supported UTIs are kUTTypeImage, kUTTypePDF, kUTTypeHTML, kUTTypeXML, kUTTypePlainText, kUTTypeRTF, kUTTypeMovie, and kUTTypeAudio).
Other points to consider:
The docs state:
"The binary of a Quick Look generator must be universal and must be 32-bit only." This page
But this page states:
"For OS X v10.6 and later, you must build Quick Look generators for both 32- and 64-bit." Which is rather unclear...
How do I set my target?
Facing the same problem I've decided to go an alternate route: use QLPreviewRequestCreateContext to get a context in which to draw my image in:
QLPreviewRequestRef preview; // The preview request passed to GeneratePreviewForURL()
CGImageRef image; // Create your CGImage however you like
CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
CGContextRef ctxt = QLPreviewRequestCreateContext(preview, size, YES, nil);
CGContextDrawImage(ctxt, CGRectMake(0, 0, size.width, size.height), image);
QLPreviewRequestFlushContext(preview, ctxt);
CGContextRelease(ctxt);
At least that works...

CIColorClamp not working correctly in OS X El Capitan

I am using Swift to do some video processing. After upgrading to El Capitan (and Swift 2) my code broke. I traced an error down to the CIFilter function CIColorClamp. This function is supposed to clamp the pixel values, but in fact messes up the image extent.
let _c:CGFloat = 0.05
let minComp = CIVector(x:_c, y:_c, z:_c, w: 1)
let maxComp = CIVector(x:1, y:1, z:1, w: 1)
let clamp: CIFilter = CIFilter(name: "CIColorClamp")!
print("clamp-in \(image.extent)")
clamp.setDefaults()
clamp.setValue(image, forKey: kCIInputImageKey)
clamp.setValue(minComp, forKey: "inputMinComponents")
clamp.setValue(maxComp, forKey: "inputMaxComponents")
print("clamp-out \(clamp.outputImage!.extent)")
The code above produces the output:
> clamp-in (6.0, 6.0, 1268.0, 708.0)
CoreAnimation: Warning! CAImageQueueSetOwner() is deprecated and does nothing. Please stop calling this method.
> clamp-out (-8.98846567431158e+307, -8.98846567431158e+307, 1.79769313486232e+308, 1.79769313486232e+308)
The fact that this call produces an internal warning does not instill confidence either!
Can anyone confirm this behavior? What am I doing wrong?
I also ran into this Problem. The extent was always set like this
-8.98846567431158e+307, -8.98846567431158e+307, 1.79769313486232e+308, 1.79769313486232e+308
but then I tried calling filter.debugDescription and recognized that in the extent in the sourceImage is given properly.
Here's my workaround. Because I use different filters, I ask if the filters name is 'CIColorClamp' and then I set the extent used in the CGImageRef to the values from the original image.
var extent = filteredImage.extent
if filter.name == "CIColorClamp" {
extent = sourceImage.extent
}
let cgImage:CGImageRef = context.createCGImage(filteredImage, fromRect: extent)
UIImageJPEGRepresentation(UIImage(CGImage: cgImage), 1.0).writeToFile(...)
Before that fix I always had an Crash cause the UIImageJPEGRepresentation could not be created, cause of the wrong extent values.
So it looks like that the extent is not transferred to the filtered image.
I had exactly the problem. I fixed it simply by cropping the returned image to the original image rect (Objective-C code):
if ([filter.name isEqualToString:#"CIColorClamp"]) {
image = [image imageByCroppingToRect:sourceImage.extent];
}

Why does QLPreviewRequestSetDataRepresentation on Mavericks return error " CGImageCreate: invalid image size: 0 x 0" for png

My quick look generator used to work properly but is now broken.
Is it a bug or am I doing something wrong?
Here’s my code:
OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview,
CFURLRef url, CFStringRef contentTypeUTI,
CFDictionaryRef options) {
NSDictionary * myDoc = [NSDictionary dictionaryWithContentsOfURL:(NSURL *)url];
if (myDoc) {
NSData * pngData = [myDoc valueForKey:#"pngPreview"];
if (pngData) {
QLPreviewRequestSetDataRepresentation(preview,(__bridge CFDataRef)pngData,
kUTTypeImage,NULL);
}
}
}
My doc is a normal plist with a png preview stored as data in it.
I checked that pngPreview does contain png data, I created the image and its size was 350×350.
However, I’m constantly getting these errors:
qlmanage[702] : CGImageCreate: invalid image size: 0 x 0.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x9e27, name = 'com.apple.tsm.portname'
See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] *** CFMessagePort: bootstrap_register(): failed 1100 (0x44c) 'Permission denied', port = 0x3f2b, name = 'com.apple.CFPasteboardClient'
See /usr/include/servers/bootstrap_defs.h for the error codes.
qlmanage[702:303] Failed to allocate communication port for com.apple.CFPasteboardClient; this is likely due to sandbox restrictions
My app is not sandboxed so I don’t think the last 3 errors are important.
I used to use kUTTypePNG but have tried kUTTypeImage to no avail (the docs for QLPreviewRequestSetDataRepresentation says currently supported UTIs are kUTTypeImage, kUTTypePDF, kUTTypeHTML, kUTTypeXML, kUTTypePlainText, kUTTypeRTF, kUTTypeMovie, and kUTTypeAudio).
Other points to consider:
The docs state:
"The binary of a Quick Look generator must be universal and must be 32-bit only." This page
But this page states:
"For OS X v10.6 and later, you must build Quick Look generators for both 32- and 64-bit." Which is rather unclear...
How do I set my target?
Facing the same problem I've decided to go an alternate route: use QLPreviewRequestCreateContext to get a context in which to draw my image in:
QLPreviewRequestRef preview; // The preview request passed to GeneratePreviewForURL()
CGImageRef image; // Create your CGImage however you like
CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
CGContextRef ctxt = QLPreviewRequestCreateContext(preview, size, YES, nil);
CGContextDrawImage(ctxt, CGRectMake(0, 0, size.width, size.height), image);
QLPreviewRequestFlushContext(preview, ctxt);
CGContextRelease(ctxt);
At least that works...

Resources